commit c712790430099b450bbdcdbda237121893b7b3d2
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Jan 6 09:35:14 2012 -0500

    	* error.c (dump_expr): Print type of CONSTRUCTOR.

diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 21d6781..62b47ca 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -2194,6 +2194,8 @@ dump_expr (tree t, int flags)
 	}
       else
 	{
+	  if (!BRACE_ENCLOSED_INITIALIZER_P (t))
+	    dump_type (TREE_TYPE (t), 0);
 	  pp_cxx_left_brace (cxx_pp);
 	  dump_expr_init_vec (CONSTRUCTOR_ELTS (t), flags);
 	  pp_cxx_right_brace (cxx_pp);
diff --git a/gcc/testsuite/g++.dg/cpp0x/error7.C b/gcc/testsuite/g++.dg/cpp0x/error7.C
new file mode 100644
index 0000000..0dfbf9f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/error7.C
@@ -0,0 +1,10 @@
+// Test for printing the type of T{} in error messages.
+// { dg-options -std=c++0x }
+
+template <class T, T t> struct A { };
+template <class T> A<T,T{}> f(T t); // { dg-message "T{}" }
+
+int main()
+{
+  f();				// { dg-error "no match" }
+}

commit 5bebdf16393c8f6ca7b9b2f2cd741919ac25d952
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Jan 6 09:39:03 2012 -0500

    	* mangle.c (mangle_decl): Don't generate mangling aliases
    	for maybe-in-charge [cd]tors.

diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 548998a..e5c2895 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -3194,7 +3194,10 @@ mangle_decl (const tree decl)
   tree id = get_mangled_id (decl);
   SET_DECL_ASSEMBLER_NAME (decl, id);
 
-  if (G.need_abi_warning)
+  if (G.need_abi_warning
+      /* Don't do this for a fake symbol we aren't going to emit anyway.  */
+      && !DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
+      && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
     {
 #ifdef ASM_OUTPUT_DEF
       /* If the mangling will change in the future, emit an alias with the

commit c427dcbe4bedd0f17df7054d17412960e0cba40c
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Jan 6 09:44:05 2012 -0500

    	* cp-demangle.c (cplus_demangle_type): decltype, pack expansion
    	and vector are substitutable.
    	(cplus_demangle_operators): Sort.

diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index 0f1166b..0ed8397 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -1554,7 +1554,8 @@ d_identifier (struct d_info *di, int len)
 /* operator_name ::= many different two character encodings.
                  ::= cv <type>
                  ::= v <digit> <source-name>
-*/
+
+   This list is sorted for binary search.  */
 
 #define NL(s) s, (sizeof s) - 1
 
@@ -1566,6 +1567,8 @@ const struct demangle_operator_info cplus_demangle_operators[] =
   { "aa", NL ("&&"),        2 },
   { "ad", NL ("&"),         1 },
   { "an", NL ("&"),         2 },
+  { "at", NL ("alignof "),   1 },
+  { "az", NL ("alignof "),   1 },
   { "cl", NL ("()"),        2 },
   { "cm", NL (","),         2 },
   { "co", NL ("~"),         1 },
@@ -1611,8 +1614,6 @@ const struct demangle_operator_info cplus_demangle_operators[] =
   { "rs", NL (">>"),        2 },
   { "st", NL ("sizeof "),   1 },
   { "sz", NL ("sizeof "),   1 },
-  { "at", NL ("alignof "),   1 },
-  { "az", NL ("alignof "),   1 },
   { NULL, NULL, 0,          0 }
 };
 
@@ -2242,12 +2243,14 @@ cplus_demangle_type (struct d_info *di)
 			     d_expression (di), NULL);
 	  if (ret && d_next_char (di) != 'E')
 	    ret = NULL;
+	  can_subst = 1;
 	  break;
 	  
 	case 'p':
 	  /* Pack expansion.  */
 	  ret = d_make_comp (di, DEMANGLE_COMPONENT_PACK_EXPANSION,
 			     cplus_demangle_type (di), NULL);
+	  can_subst = 1;
 	  break;
 	  
 	case 'f':
@@ -2298,6 +2301,7 @@ cplus_demangle_type (struct d_info *di)
 
 	case 'v':
 	  ret = d_vector_type (di);
+	  can_subst = 1;
 	  break;
 
         case 'n':
diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected
index 70abf68..642fe14 100644
--- a/libiberty/testsuite/demangle-expected
+++ b/libiberty/testsuite/demangle-expected
@@ -4018,6 +4018,18 @@ K<1, &S::m>::f()
 --format=gnu-v3
 _ZSt10_ConstructI10CellBorderIS0_EEvPT_DpOT0_
 _ZSt10_ConstructI10CellBorderIS0_EEvPT_DpOT0_
+# A pack expansion is substitutable.
+--format=gnu-v3
+_Z1fIJiEiEv1AIJDpT_EET0_S4_
+void f<int, int>(A<int>, int, int)
+# So is decltype.
+--format=gnu-v3
+_Z1fIiiEDTcvT__EET0_S2_
+decltype ((int)()) f<int, int>(int, int)
+# And vector.
+--format=gnu-v3
+_Z1fDv4_iS_
+f(int __vector(4), int __vector(4))
 #
 # Ada (GNAT) tests.
 #

commit f4d29990c578120c19277e4a55e574ad5d384591
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Jan 6 11:13:01 2012 -0500

    	PR c++/6057
    	PR c++/48051
    	PR c++/50855
    	PR c++/51322
    gcc/cp/
    	* mangle.c (write_expression): Support NEW_EXPR, DELETE_EXPR,
    	THROW_EXPR, CONSTRUCTOR, OVERLOAD.  Fix PREINCREMENT_EXPR and
    	PREDECREMENT_EXPR.
    	(write_template_arg): Fix mangling of class-scope functions and
    	argument packs.
    	(mangle_decl): Update suggested -fabi-version argument.
    	* operators.def: Add DOTSTAR_EXPR, REINTERPRET_CAST_EXPR,
    	DYNAMIC_CAST_EXPR; correct CONST_CAST_EXPR, STATIC_CAST_EXPR.
    	* tree.c (dependent_name): No longer static.
    	* cp-tree.h: Declare it.
    	* pt.c (unify): Defer handling of unconverted functions.
    include/
    	* demangle.h (enum demangle_component_type): Add
    	DEMANGLE_COMPONENT_INITIALIZER_LIST, DEMANGLE_COMPONENT_NULLARY.
    libiberty/
    	* cp-demangle.c (d_dump): Handle DEMANGLE_COMPONENT_NULLARY and
    	DEMANGLE_COMPONENT_INITIALIZER_LIST.
    	(d_make_comp): Likewise.  Allow null right arg for
    	DEMANGLE_COMPONENT_TRINARY_ARG2.
    	(cplus_demangle_operators): Adjust new/delete; add .*, :: and throw.
    	(d_template_args, d_template_arg): Handle 'J' for argument packs.
    	(d_exprlist): Add terminator parm.
    	(d_expression, d_print_comp): Handle initializer lists, nullary
    	expressions, prefix/suffix operators, and new.
    	(d_print_subexpr): Avoid parens around DEMANGLE_COMPONENT_QUAL_NAME
    	and DEMANGLE_COMPONENT_INITIALIZER_LIST.
    	* testsuite/demangle-expected: Add tests.

diff --git a/gcc/common.opt b/gcc/common.opt
index 6cfe17a..0544478 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -782,7 +782,10 @@ Driver Undocumented
 ;    function parameters used in other parameters and the return type.
 ;    First selectable in G++ 4.6.
 ;
-; 6: The version of the ABI that doesn't promote scoped enums to int.
+; 6: The version of the ABI that doesn't promote scoped enums to int and
+;    changes the mangling of template argument packs, const/static_cast,
+;    prefix ++ and --, and a class scope function used as a template
+;    argument.
 ;    First selectable in G++ 4.7.
 ;
 ; Additional positive integers will be assigned as new versions of
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 6e62bd1..ccad644 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5674,6 +5674,7 @@ extern tree hash_tree_cons			(tree, tree, tree);
 extern tree hash_tree_chain			(tree, tree);
 extern tree build_qualified_name		(tree, tree, tree, bool);
 extern int is_overloaded_fn			(tree);
+extern tree dependent_name			(tree);
 extern tree get_fns				(tree);
 extern tree get_first_fn			(tree);
 extern tree ovl_cons				(tree, tree);
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index e5c2895..f4efa67 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -2646,6 +2646,102 @@ write_expression (tree expr)
       write_expression (TREE_OPERAND (expr, 0));
       write_expression (TREE_OPERAND (expr, 2));
     }
+  else if (code == NEW_EXPR || code == VEC_NEW_EXPR)
+    {
+      /* ::= [gs] nw <expression>* _ <type> E
+	 ::= [gs] nw <expression>* _ <type> <initializer>
+	 ::= [gs] na <expression>* _ <type> E
+	 ::= [gs] na <expression>* _ <type> <initializer>
+	 <initializer> ::= pi <expression>* E  */
+      tree placement = TREE_OPERAND (expr, 0);
+      tree type = TREE_OPERAND (expr, 1);
+      tree nelts = TREE_OPERAND (expr, 2);
+      tree init = TREE_OPERAND (expr, 3);
+      tree t;
+
+      gcc_assert (code == NEW_EXPR);
+      if (TREE_OPERAND (expr, 2))
+	code = VEC_NEW_EXPR;
+
+      if (NEW_EXPR_USE_GLOBAL (expr))
+	write_string ("gs");
+
+      write_string (operator_name_info[(int) code].mangled_name);
+
+      for (t = placement; t; t = TREE_CHAIN (t))
+	write_expression (TREE_VALUE (t));
+
+      write_char ('_');
+
+      if (nelts)
+	{
+	  tree domain;
+	  ++processing_template_decl;
+	  domain = compute_array_index_type (NULL_TREE, nelts,
+					     tf_warning_or_error);
+	  type = build_cplus_array_type (type, domain);
+	  --processing_template_decl;
+	}
+      write_type (type);
+
+      if (init && TREE_CODE (init) == TREE_LIST
+	  && TREE_CODE (TREE_VALUE (init)) == CONSTRUCTOR
+	  && CONSTRUCTOR_IS_DIRECT_INIT (TREE_VALUE (init)))
+	write_expression (TREE_VALUE (init));
+      else
+	{
+	  if (init)
+	    write_string ("pi");
+	  if (init && init != void_zero_node)
+	    for (t = init; t; t = TREE_CHAIN (t))
+	      write_expression (TREE_VALUE (t));
+	  write_char ('E');
+	}
+    }
+  else if (code == DELETE_EXPR || code == VEC_DELETE_EXPR)
+    {
+      gcc_assert (code == DELETE_EXPR);
+      if (DELETE_EXPR_USE_VEC (expr))
+	code = VEC_DELETE_EXPR;
+
+      if (DELETE_EXPR_USE_GLOBAL (expr))
+	write_string ("gs");
+
+      write_string (operator_name_info[(int) code].mangled_name);
+
+      write_expression (TREE_OPERAND (expr, 0));
+    }
+  else if (code == THROW_EXPR)
+    {
+      tree op = TREE_OPERAND (expr, 0);
+      if (op)
+	{
+	  write_string ("tw");
+	  write_expression (op);
+	}
+      else
+	write_string ("tr");
+    }
+  else if (code == CONSTRUCTOR)
+    {
+      VEC(constructor_elt,gc)* elts = CONSTRUCTOR_ELTS (expr);
+      unsigned i; tree val;
+
+      if (BRACE_ENCLOSED_INITIALIZER_P (expr))
+	write_string ("il");
+      else
+	{
+	  write_string ("tl");
+	  write_type (TREE_TYPE (expr));
+	}
+      FOR_EACH_CONSTRUCTOR_VALUE (elts, i, val)
+	write_expression (val);
+      write_char ('E');
+    }
+  else if (dependent_name (expr))
+    {
+      write_unqualified_id (dependent_name (expr));
+    }
   else
     {
       int i, len;
@@ -2688,6 +2784,16 @@ write_expression (tree expr)
 
       /* If it wasn't any of those, recursively expand the expression.  */
       name = operator_name_info[(int) code].mangled_name;
+
+      /* We used to mangle const_cast and static_cast like a C cast.  */
+      if (!abi_version_at_least (6)
+	  && (code == CONST_CAST_EXPR
+	      || code == STATIC_CAST_EXPR))
+	{
+	  name = operator_name_info[CAST_EXPR].mangled_name;
+	  G.need_abi_warning = 1;
+	}
+
       if (name == NULL)
 	{
 	  sorry ("mangling %C", code);
@@ -2734,16 +2840,21 @@ write_expression (tree expr)
 	    }
 	  break;
 
-	  /* FIXME these should have a distinct mangling.  */
+	case DYNAMIC_CAST_EXPR:
+	case REINTERPRET_CAST_EXPR:
 	case STATIC_CAST_EXPR:
 	case CONST_CAST_EXPR:
 	  write_type (TREE_TYPE (expr));
 	  write_expression (TREE_OPERAND (expr, 0));
 	  break;
 
-	case NEW_EXPR:
-	  sorry ("mangling new-expression");
-	  break;
+	case PREINCREMENT_EXPR:
+	case PREDECREMENT_EXPR:
+	  if (abi_version_at_least (6))
+	    write_char ('_');
+	  else
+	    G.need_abi_warning = 1;
+	  /* Fall through.  */
 
 	default:
 	  /* In the middle-end, some expressions have more operands than
@@ -2855,12 +2966,28 @@ write_template_arg (tree node)
 	G.need_abi_warning = 1;
     }
 
+  if (TREE_CODE (node) == BASELINK
+      && !type_unknown_p (node))
+    {
+      if (abi_version_at_least (6))
+	node = BASELINK_FUNCTIONS (node);
+      else
+	/* We wrongly wrapped a class-scope function in X/E.  */
+	G.need_abi_warning = 1;
+    }
+
   if (ARGUMENT_PACK_P (node))
     {
       /* Expand the template argument pack. */
       tree args = ARGUMENT_PACK_ARGS (node);
       int i, length = TREE_VEC_LENGTH (args);
-      write_char ('I');
+      if (abi_version_at_least (6))
+	write_char ('J');
+      else
+	{
+	  write_char ('I');
+	  G.need_abi_warning = 1;
+	}
       for (i = 0; i < length; ++i)
         write_template_arg (TREE_VEC_ELT (args, i));
       write_char ('E');
@@ -3208,8 +3335,8 @@ mangle_decl (const tree decl)
 
       SET_IDENTIFIER_GLOBAL_VALUE (id, decl);
       if (IDENTIFIER_GLOBAL_VALUE (id) != decl)
-	inform (DECL_SOURCE_LOCATION (decl), "-fabi-version=4 (or =0) "
-		"avoids this error with a change in vector mangling");
+	inform (DECL_SOURCE_LOCATION (decl), "-fabi-version=6 (or =0) "
+		"avoids this error with a change in mangling");
 
 #ifdef ASM_OUTPUT_DEF
       save_ver = flag_abi_version;
diff --git a/gcc/cp/operators.def b/gcc/cp/operators.def
index 20d811b..3dc7404 100644
--- a/gcc/cp/operators.def
+++ b/gcc/cp/operators.def
@@ -101,8 +101,10 @@ DEF_SIMPLE_OPERATOR ("__real__", REALPART_EXPR, "v18__real__", 1)
 /* The cast operator.  */
 DEF_SIMPLE_OPERATOR ("", TYPE_EXPR, "cv", 1)
 DEF_SIMPLE_OPERATOR ("", CAST_EXPR, "cv", 1)
-DEF_SIMPLE_OPERATOR ("", CONST_CAST_EXPR, "cv", 1)
-DEF_SIMPLE_OPERATOR ("", STATIC_CAST_EXPR, "cv", 1)
+DEF_SIMPLE_OPERATOR ("dynamic_cast", DYNAMIC_CAST_EXPR, "dc", 1)
+DEF_SIMPLE_OPERATOR ("reinterpret_cast", REINTERPRET_CAST_EXPR, "rc", 1)
+DEF_SIMPLE_OPERATOR ("const_cast", CONST_CAST_EXPR, "cc", 1)
+DEF_SIMPLE_OPERATOR ("static_cast", STATIC_CAST_EXPR, "sc", 1)
 
 /* Binary operators.  */
 DEF_SIMPLE_OPERATOR ("+", PLUS_EXPR, "pl", 2)
@@ -125,6 +127,7 @@ DEF_SIMPLE_OPERATOR ("&&", TRUTH_ANDIF_EXPR, "aa", 2)
 DEF_SIMPLE_OPERATOR ("||", TRUTH_ORIF_EXPR, "oo", 2)
 DEF_SIMPLE_OPERATOR (",", COMPOUND_EXPR, "cm", 2)
 DEF_SIMPLE_OPERATOR ("->*", MEMBER_REF, "pm", 2)
+DEF_SIMPLE_OPERATOR (".*", DOTSTAR_EXPR, "ds", 2)
 DEF_SIMPLE_OPERATOR ("->", COMPONENT_REF, "pt", 2)
 DEF_SIMPLE_OPERATOR ("[]", ARRAY_REF, "ix", 2)
 DEF_SIMPLE_OPERATOR ("++", POSTINCREMENT_EXPR, "pp", 2)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 77e3388..bc3dd97 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -16885,7 +16885,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
 
     default:
       /* An unresolved overload is a nondeduced context.  */
-      if (type_unknown_p (parm))
+      if (is_overloaded_fn (parm) || type_unknown_p (parm))
 	return unify_success (explain_p);
       gcc_assert (EXPR_P (parm));
 
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index dea7632..8ef3e25 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1457,7 +1457,7 @@ is_overloaded_fn (tree x)
    (14.6.2), return the IDENTIFIER_NODE for that name.  Otherwise, return
    NULL_TREE.  */
 
-static tree
+tree
 dependent_name (tree x)
 {
   if (TREE_CODE (x) == IDENTIFIER_NODE)
diff --git a/gcc/testsuite/g++.dg/abi/mangle51.C b/gcc/testsuite/g++.dg/abi/mangle51.C
new file mode 100644
index 0000000..4992f1a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle51.C
@@ -0,0 +1,27 @@
+// { dg-options "-std=c++0x -fabi-version=0" }
+
+void* operator new (__SIZE_TYPE__, void *p) { return p; }
+int i;
+
+template <unsigned int> struct helper {};
+// { dg-final { scan-assembler "_Z6check1IiEvP6helperIXsznw_T_EEE" } }
+template <class T> void check1( helper<sizeof(new T)> * ) { }
+// { dg-final { scan-assembler "_Z6check2IiEvP6helperIXszgsnw_T_piEEE" } }
+template <class T> void check2( helper<sizeof(::new T())> * ) { }
+// { dg-final { scan-assembler "_Z6check3IiEvP6helperIXsznwadL_Z1iE_T_piLi1EEEE" } }
+template <class T> void check3( helper<sizeof(new (&i) T(1))> * ) { }
+// { dg-final { scan-assembler "_Z7check3aIiEvP6helperIXsznw_T_ilLi1EEEE" } }
+template <class T> void check3a( helper<sizeof(new T{1})> * ) { }
+// { dg-final { scan-assembler "_Z6check4IiEvP6helperIXszna_A1_T_EEE" } }
+template <class T> void check4( helper<sizeof(new T[1])> * ) { }
+// { dg-final { scan-assembler "_Z6check5IiEvP6helperIXszna_A1_T_piEEE" } }
+template <class T> void check5( helper<sizeof(new T[1]())> * ) { }
+int main()
+{
+  check1<int>(0);
+  check2<int>(0);
+  check3<int>(0);
+  check3a<int>(0);
+  check4<int>(0);
+  check5<int>(0);
+}
diff --git a/gcc/testsuite/g++.dg/abi/mangle52.C b/gcc/testsuite/g++.dg/abi/mangle52.C
new file mode 100644
index 0000000..2c46341
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle52.C
@@ -0,0 +1,21 @@
+// { dg-options "-fabi-version=0" }
+
+template <unsigned int> struct helper {};
+// { dg-final { scan-assembler "_Z6check1IiEvP6helperIXszscT_Li1EEE" } }
+template <class T> void check1( helper<sizeof(static_cast<T>(1))> * ) { }
+// { dg-final { scan-assembler "_Z6check2IiXadL_Z1iEEEvP6helperIXszccPT_T0_EE" } }
+template <class T, T* p> void check2( helper<sizeof(const_cast<T*>(p))> * ) { }
+// { dg-final { scan-assembler "_Z6check3IiEvP6helperIXszrcPT_Li0EEE" } }
+template <class T> void check3( helper<sizeof(reinterpret_cast<T*>(0))> * ) { }
+// { dg-final { scan-assembler "_Z6check4I1AXadL_Z1aEEEvP6helperIXszdcPT_T0_EE" } }
+template <class T, T* p> void check4( helper<sizeof(dynamic_cast<T*>(p))> * ) { }
+
+struct A{} a;
+int i;
+int main()
+{
+  check1<int>(0);
+  check2<int,&i>(0);
+  check3<int>(0);
+  check4<A,&a>(0);
+}
diff --git a/gcc/testsuite/g++.dg/abi/mangle53.C b/gcc/testsuite/g++.dg/abi/mangle53.C
new file mode 100644
index 0000000..b279182
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle53.C
@@ -0,0 +1,13 @@
+// { dg-options "-std=c++0x" }
+
+bool b;
+// { dg-final { scan-assembler "_Z1fIiEDTquL_Z1bEfp_twLi42EET_" } }
+template <class T> auto f (T t) -> decltype(b?t:throw 42) { return 0; }
+// { dg-final { scan-assembler "_Z2f2IiEDTquL_Z1bEfp_trET_" } }
+template <class T> auto f2 (T t) -> decltype(b?t:throw) { return 0; }
+
+int main()
+{
+  f(0);
+  f2(0);
+}
diff --git a/gcc/testsuite/g++.dg/abi/mangle54.C b/gcc/testsuite/g++.dg/abi/mangle54.C
new file mode 100644
index 0000000..ea98df1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle54.C
@@ -0,0 +1,19 @@
+// { dg-options "-std=c++0x -fabi-version=0" }
+
+int i;
+// { dg-final { scan-assembler "_Z2f1IiEDTppfp_ET_" } }
+template <class T> auto f1 (T t) -> decltype(t++) { return i; }
+// { dg-final { scan-assembler "_Z2f2IiEDTpp_fp_ET_" } }
+template <class T> auto f2 (T t) -> decltype(++t) { return i; }
+// { dg-final { scan-assembler "_Z2f3IiEDTmmfp_ET_" } }
+template <class T> auto f3 (T t) -> decltype(t--) { return i; }
+// { dg-final { scan-assembler "_Z2f4IiEDTmm_fp_ET_" } }
+template <class T> auto f4 (T t) -> decltype(--t) { return i; }
+
+int main()
+{
+  f1(0);
+  f2(0);
+  f3(0);
+  f4(0);
+}
diff --git a/gcc/testsuite/g++.dg/abi/mangle55.C b/gcc/testsuite/g++.dg/abi/mangle55.C
new file mode 100644
index 0000000..72caadc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle55.C
@@ -0,0 +1,14 @@
+// { dg-options "-std=c++0x" }
+
+struct A { int i; };
+// { dg-final { scan-assembler "_Z2f1Ii1AEDTdsfp_fp0_ET0_MS2_T_" } }
+template <class T, class U> auto f1 (U u, T U::* p) -> decltype(u.*p) { return u.*p; }
+// { dg-final { scan-assembler "_Z2f2Ii1AEDTpmfp_fp0_EPT0_MS2_T_" } }
+template <class T, class U> auto f2 (U* u, T U::* p) -> decltype(u->*p) { return u->*p; }
+
+int main()
+{
+  A a = {};
+  f1(a, &A::i);
+  f2(&a, &A::i);
+}
diff --git a/gcc/testsuite/g++.dg/abi/mangle56.C b/gcc/testsuite/g++.dg/abi/mangle56.C
new file mode 100644
index 0000000..0fd2701
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle56.C
@@ -0,0 +1,13 @@
+// { dg-options "-std=c++0x" }
+
+template <class T> T g(T t1, T t2) { return t2; }
+// { dg-final { scan-assembler "_Z2f1IiEDTcl1gfp_ilEEET_" } }
+template <class T> auto f1 (T t) -> decltype(g(t,{})) { return g(t,{}); }
+// { dg-final { scan-assembler "_Z2f2IiEDTcl1gfp_tlT_EEES0_" } }
+template <class T> auto f2 (T t) -> decltype(g(t,T{})) { return g(t,T{}); }
+
+int main()
+{
+  f1(0);
+  f2(0);
+}
diff --git a/gcc/testsuite/g++.dg/abi/mangle57.C b/gcc/testsuite/g++.dg/abi/mangle57.C
new file mode 100644
index 0000000..3d9d81e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle57.C
@@ -0,0 +1,16 @@
+// { dg-options "-std=c++0x -fabi-version=0" }
+
+template<typename T> int cmp1(T a, T b);
+int cmp2(char a, char b);
+template<typename T, int (*cmp)(T, T)> struct A { };
+// { dg-final { scan-assembler "_Z1fIcEvR1AIT_X4cmp1EE" } }
+template <typename T> void f (A<T,cmp1> &);
+// { dg-final { scan-assembler "_Z1fIcEvR1AIT_L_Z4cmp2ccEE" } }
+template <typename T> void f (A<T,cmp2> &);
+void g()
+{
+  A<char,cmp1> a;
+  f(a);
+  A<char,cmp2> a2;
+  f(a2);
+}
diff --git a/gcc/testsuite/g++.dg/abi/mangle58.C b/gcc/testsuite/g++.dg/abi/mangle58.C
new file mode 100644
index 0000000..14e5543
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle58.C
@@ -0,0 +1,19 @@
+// { dg-options "-std=c++0x -fabi-version=0" }
+
+template<typename T, int (*cmp)(T, T)> struct A { };
+struct B {
+  template<typename T> static int cmp1(T a, T b);
+  static int cmp2(char a, char b);
+  // { dg-final { scan-assembler "_ZN1B1fIcEEvR1AIT_X4cmp1EE" } }
+  template <typename T> static void f (A<T,cmp1> &);
+  // { dg-final { scan-assembler "_ZN1B1fIcEEvR1AIT_L_ZNS_4cmp2EccEE" } }
+  template <typename T> static void f (A<T,cmp2> &);
+};
+
+void g()
+{
+  A<char,B::cmp1> a;
+  B::f(a);
+  A<char,B::cmp2> a2;
+  B::f(a2);
+}
diff --git a/gcc/testsuite/g++.dg/abi/mangle59.C b/gcc/testsuite/g++.dg/abi/mangle59.C
new file mode 100644
index 0000000..3c88ec8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle59.C
@@ -0,0 +1,19 @@
+// { dg-options "-std=c++0x -fabi-version=0" }
+
+// { dg-final { scan-assembler "_Z1fIiEDTcmdlfp_psfp_EPT_" } }
+template <class T> auto f (T* p) -> decltype(delete p, +p) { return p; }
+// { dg-final { scan-assembler "_Z1gIiEDTcmgsdlfp_psfp_EPT_" } }
+template <class T> auto g (T* p) -> decltype(::delete p, +p) { return p; }
+// { dg-final { scan-assembler "_Z1hIiEDTcmdafp_psfp_EPT_" } }
+template <class T> auto h (T* p) -> decltype(delete[] p, +p) { return p; }
+// { dg-final { scan-assembler "_Z1iIiEDTcmgsdafp_psfp_EPT_" } }
+template <class T> auto i (T* p) -> decltype(::delete[] p, +p) { return p; }
+
+int main()
+{
+  int x;
+  f(&x);
+  g(&x);
+  h(&x);
+  i(&x);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing3.C b/gcc/testsuite/g++.dg/cpp0x/trailing3.C
index 82d36f0..1c64f45 100644
--- a/gcc/testsuite/g++.dg/cpp0x/trailing3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/trailing3.C
@@ -1,5 +1,5 @@
 // More auto/decltype mangling tests.
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++0x -fabi-version=0" }
 
 template <class T>
 struct B
@@ -58,6 +58,6 @@ int main()
   A<int>().h(1);
   // { dg-final { scan-assembler  "_ZN1AIiE1jIiEEDTplfp_clL_Z1xvEEET_" } }
   A<int>().j(1);
-  // { dg-final { scan-assembler  "_Z1gIIidEEDTcl1fspplfp_Li1EEEDpT_" } }  
+  // { dg-final { scan-assembler  "_Z1gIJidEEDTcl1fspplfp_Li1EEEDpT_" } }
   g(42, 1.0);
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic111.C b/gcc/testsuite/g++.dg/cpp0x/variadic111.C
index 378162e..cb94ce6 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic111.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic111.C
@@ -1,5 +1,5 @@
 // PR c++/48424
-// { dg-options -std=c++0x }
+// { dg-options "-std=c++0x -fabi-version=0" }
 
 template<typename... Args1>
 struct S
@@ -16,4 +16,4 @@ int main()
   s.f(1,2.0,false,'a');
 }
 
-// { dg-final { scan-assembler "_ZN1SIIidEE1fIIbcEEEvidDpOT_" } }
+// { dg-final { scan-assembler "_ZN1SIJidEE1fIJbcEEEvidDpOT_" } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic4.C b/gcc/testsuite/g++.dg/cpp0x/variadic4.C
index 9257a92..1bdad32 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic4.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++0x -fabi-version=0" }
 // { dg-do compile }
 template<typename... Args>
 class tuple {};
@@ -9,7 +9,7 @@ void f_two(tuple<int, float>) {}
 void f_nested(tuple<int, tuple<double, char>, float>) { }
 
 
-// { dg-final { scan-assembler "_Z6f_none5tupleIIEE" } }
-// { dg-final { scan-assembler "_Z5f_one5tupleIIiEE" } }
-// { dg-final { scan-assembler "_Z5f_two5tupleIIifEE" } }
-// { dg-final { scan-assembler "_Z8f_nested5tupleIIiS_IIdcEEfEE" } }
+// { dg-final { scan-assembler "_Z6f_none5tupleIJEE" } }
+// { dg-final { scan-assembler "_Z5f_one5tupleIJiEE" } }
+// { dg-final { scan-assembler "_Z5f_two5tupleIJifEE" } }
+// { dg-final { scan-assembler "_Z8f_nested5tupleIJiS_IJdcEEfEE" } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic42.C b/gcc/testsuite/g++.dg/cpp0x/variadic42.C
index 47d9b66..3ec68e8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic42.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic42.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++0x -fabi-version=5" }
 // { dg-do compile }
 template<typename... Args>
 void f(Args...) { }
diff --git a/gcc/testsuite/g++.dg/template/nontype22.C b/gcc/testsuite/g++.dg/template/nontype22.C
index f2c8c46..44d8479 100644
--- a/gcc/testsuite/g++.dg/template/nontype22.C
+++ b/gcc/testsuite/g++.dg/template/nontype22.C
@@ -3,7 +3,7 @@
 
 template<typename T> int cmp1(T a, T b);
 template<typename T, int (*cmp)(T, T) = cmp1> struct A { };
-template <typename T> void f (A<T> &); // { dg-bogus "" "" { xfail *-*-* } }
+template <typename T> void f (A<T> &);
 void g()
 {
   A<char> a;
diff --git a/gcc/testsuite/g++.dg/template/pr35240.C b/gcc/testsuite/g++.dg/template/pr35240.C
index 88e2505..5b94551 100644
--- a/gcc/testsuite/g++.dg/template/pr35240.C
+++ b/gcc/testsuite/g++.dg/template/pr35240.C
@@ -1,12 +1,11 @@
 // PR c++/35240
 // { dg-do compile }
 
-
 template<int> struct A {};
 
-template<int N> A<sizeof(new int[N][N])> foo(); // { dg-message "unimplemented" }
+template<int N> A<sizeof(new int[N][N])> foo();
 
 void bar()
 {
-  foo<1>(); // { dg-message "required" }
+  foo<1>();
 }
diff --git a/include/demangle.h b/include/demangle.h
index 98b11d7..34b3ed3 100644
--- a/include/demangle.h
+++ b/include/demangle.h
@@ -344,6 +344,9 @@ enum demangle_component_type
      template argument, and the right subtree is either NULL or
      another TEMPLATE_ARGLIST node.  */
   DEMANGLE_COMPONENT_TEMPLATE_ARGLIST,
+  /* An initializer list.  The left subtree is either an explicit type or
+     NULL, and the right subtree is a DEMANGLE_COMPONENT_ARGLIST.  */
+  DEMANGLE_COMPONENT_INITIALIZER_LIST,
   /* An operator.  This holds information about a standard
      operator.  */
   DEMANGLE_COMPONENT_OPERATOR,
@@ -353,6 +356,8 @@ enum demangle_component_type
   /* A typecast, represented as a unary operator.  The one subtree is
      the type to which the argument should be cast.  */
   DEMANGLE_COMPONENT_CAST,
+  /* A nullary expression.  The left subtree is the operator.  */
+  DEMANGLE_COMPONENT_NULLARY,
   /* A unary expression.  The left subtree is the operator, and the
      right subtree is the single argument.  */
   DEMANGLE_COMPONENT_UNARY,
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index 0ed8397..2dfd67c 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -648,9 +648,15 @@ d_dump (struct demangle_component *dc, int indent)
     case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
       printf ("template argument list\n");
       break;
+    case DEMANGLE_COMPONENT_INITIALIZER_LIST:
+      printf ("initializer list\n");
+      break;
     case DEMANGLE_COMPONENT_CAST:
       printf ("cast\n");
       break;
+    case DEMANGLE_COMPONENT_NULLARY:
+      printf ("nullary operator\n");
+      break;
     case DEMANGLE_COMPONENT_UNARY:
       printf ("unary operator\n");
       break;
@@ -806,7 +812,6 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
     case DEMANGLE_COMPONENT_BINARY_ARGS:
     case DEMANGLE_COMPONENT_TRINARY:
     case DEMANGLE_COMPONENT_TRINARY_ARG1:
-    case DEMANGLE_COMPONENT_TRINARY_ARG2:
     case DEMANGLE_COMPONENT_LITERAL:
     case DEMANGLE_COMPONENT_LITERAL_NEG:
     case DEMANGLE_COMPONENT_COMPOUND_NAME:
@@ -843,6 +848,8 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
     case DEMANGLE_COMPONENT_PACK_EXPANSION:
     case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS:
     case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS:
+    case DEMANGLE_COMPONENT_NULLARY:
+    case DEMANGLE_COMPONENT_TRINARY_ARG2:
       if (left == NULL)
 	return NULL;
       break;
@@ -850,6 +857,7 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
       /* This needs a right parameter, but the left parameter can be
 	 empty.  */
     case DEMANGLE_COMPONENT_ARRAY_TYPE:
+    case DEMANGLE_COMPONENT_INITIALIZER_LIST:
       if (right == NULL)
 	return NULL;
       break;
@@ -1573,15 +1581,17 @@ const struct demangle_operator_info cplus_demangle_operators[] =
   { "cm", NL (","),         2 },
   { "co", NL ("~"),         1 },
   { "dV", NL ("/="),        2 },
-  { "da", NL ("delete[]"),  1 },
+  { "da", NL ("delete[] "), 1 },
   { "de", NL ("*"),         1 },
-  { "dl", NL ("delete"),    1 },
+  { "dl", NL ("delete "),   1 },
+  { "ds", NL (".*"),        2 },
   { "dt", NL ("."),         2 },
   { "dv", NL ("/"),         2 },
   { "eO", NL ("^="),        2 },
   { "eo", NL ("^"),         2 },
   { "eq", NL ("=="),        2 },
   { "ge", NL (">="),        2 },
+  { "gs", NL ("::"),	    1 },
   { "gt", NL (">"),         2 },
   { "ix", NL ("[]"),        2 },
   { "lS", NL ("<<="),       2 },
@@ -1593,11 +1603,11 @@ const struct demangle_operator_info cplus_demangle_operators[] =
   { "mi", NL ("-"),         2 },
   { "ml", NL ("*"),         2 },
   { "mm", NL ("--"),        1 },
-  { "na", NL ("new[]"),     1 },
+  { "na", NL ("new[]"),     3 },
   { "ne", NL ("!="),        2 },
   { "ng", NL ("-"),         1 },
   { "nt", NL ("!"),         1 },
-  { "nw", NL ("new"),       1 },
+  { "nw", NL ("new"),       3 },
   { "oR", NL ("|="),        2 },
   { "oo", NL ("||"),        2 },
   { "or", NL ("|"),         2 },
@@ -1614,6 +1624,8 @@ const struct demangle_operator_info cplus_demangle_operators[] =
   { "rs", NL (">>"),        2 },
   { "st", NL ("sizeof "),   1 },
   { "sz", NL ("sizeof "),   1 },
+  { "tr", NL ("throw"),     0 },
+  { "tw", NL ("throw "),    1 },
   { NULL, NULL, 0,          0 }
 };
 
@@ -2679,8 +2691,10 @@ d_template_args (struct d_info *di)
      constructor or destructor.  */
   hold_last_name = di->last_name;
 
-  if (! d_check_char (di, 'I'))
+  if (d_peek_char (di) != 'I'
+      && d_peek_char (di) != 'J')
     return NULL;
+  d_advance (di, 1);
 
   if (d_peek_char (di) == 'E')
     {
@@ -2739,6 +2753,7 @@ d_template_arg (struct d_info *di)
       return d_expr_primary (di);
 
     case 'I':
+    case 'J':
       /* An argument pack.  */
       return d_template_args (di);
 
@@ -2747,15 +2762,16 @@ d_template_arg (struct d_info *di)
     }
 }
 
-/* Subroutine of <expression> ::= cl <expression>+ E */
+/* Parse a sequence of expressions until we hit the terminator
+   character.  */
 
 static struct demangle_component *
-d_exprlist (struct d_info *di)
+d_exprlist (struct d_info *di, char terminator)
 {
   struct demangle_component *list = NULL;
   struct demangle_component **p = &list;
 
-  if (d_peek_char (di) == 'E')
+  if (d_peek_char (di) == terminator)
     {
       d_advance (di, 1);
       return d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, NULL, NULL);
@@ -2772,7 +2788,7 @@ d_exprlist (struct d_info *di)
 	return NULL;
       p = &d_right (*p);
 
-      if (d_peek_char (di) == 'E')
+      if (d_peek_char (di) == terminator)
 	{
 	  d_advance (di, 1);
 	  break;
@@ -2863,9 +2879,21 @@ d_expression (struct d_info *di)
       else
 	return name;
     }
+  else if ((peek == 'i' || peek == 't')
+	   && d_peek_next_char (di) == 'l')
+    {
+      /* Brace-enclosed initializer list, untyped or typed.  */
+      struct demangle_component *type = NULL;
+      if (peek == 't')
+	type = cplus_demangle_type (di);
+      d_advance (di, 2);
+      return d_make_comp (di, DEMANGLE_COMPONENT_INITIALIZER_LIST,
+			  type, d_exprlist (di, 'E'));
+    }
   else
     {
       struct demangle_component *op;
+      const char *code = NULL;
       int args;
 
       op = d_operator_name (di);
@@ -2873,12 +2901,13 @@ d_expression (struct d_info *di)
 	return NULL;
 
       if (op->type == DEMANGLE_COMPONENT_OPERATOR)
-	di->expansion += op->u.s_operator.op->len - 2;
-
-      if (op->type == DEMANGLE_COMPONENT_OPERATOR
-	  && strcmp (op->u.s_operator.op->code, "st") == 0)
-	return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
-			    cplus_demangle_type (di));
+	{
+	  code = op->u.s_operator.op->code;
+	  di->expansion += op->u.s_operator.op->len - 2;
+	  if (strcmp (code, "st") == 0)
+	    return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
+				cplus_demangle_type (di));
+	}
 
       switch (op->type)
 	{
@@ -2897,26 +2926,43 @@ d_expression (struct d_info *di)
 
       switch (args)
 	{
+	case 0:
+	  return d_make_comp (di, DEMANGLE_COMPONENT_NULLARY, op, NULL);
+
 	case 1:
 	  {
 	    struct demangle_component *operand;
+	    int suffix = 0;
+
+	    if (code && (code[0] == 'p' || code[0] == 'm')
+		&& code[1] == code[0])
+	      /* pp_ and mm_ are the prefix variants.  */
+	      suffix = !d_check_char (di, '_');
+
 	    if (op->type == DEMANGLE_COMPONENT_CAST
 		&& d_check_char (di, '_'))
-	      operand = d_exprlist (di);
+	      operand = d_exprlist (di, 'E');
 	    else
 	      operand = d_expression (di);
-	    return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
-				operand);
+
+	    if (suffix)
+	      /* Indicate the suffix variant for d_print_comp.  */
+	      return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
+				  d_make_comp (di,
+					       DEMANGLE_COMPONENT_BINARY_ARGS,
+					       operand, operand));
+	    else
+	      return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
+				  operand);
 	  }
 	case 2:
 	  {
 	    struct demangle_component *left;
 	    struct demangle_component *right;
-	    const char *code = op->u.s_operator.op->code;
 
 	    left = d_expression (di);
 	    if (!strcmp (code, "cl"))
-	      right = d_exprlist (di);
+	      right = d_exprlist (di, 'E');
 	    else if (!strcmp (code, "dt") || !strcmp (code, "pt"))
 	      {
 		right = d_unqualified_name (di);
@@ -2936,17 +2982,50 @@ d_expression (struct d_info *di)
 	  {
 	    struct demangle_component *first;
 	    struct demangle_component *second;
+	    struct demangle_component *third;
 
-	    first = d_expression (di);
-	    second = d_expression (di);
+	    if (!strcmp (code, "qu"))
+	      {
+		/* ?: expression.  */
+		first = d_expression (di);
+		second = d_expression (di);
+		third = d_expression (di);
+	      }
+	    else if (code[0] == 'n')
+	      {
+		/* new-expression.  */
+		if (code[1] != 'w' && code[1] != 'a')
+		  return NULL;
+		first = d_exprlist (di, '_');
+		second = cplus_demangle_type (di);
+		if (d_peek_char (di) == 'E')
+		  {
+		    d_advance (di, 1);
+		    third = NULL;
+		  }
+		else if (d_peek_char (di) == 'p'
+			 && d_peek_next_char (di) == 'i')
+		  {
+		    /* Parenthesized initializer.  */
+		    d_advance (di, 2);
+		    third = d_exprlist (di, 'E');
+		  }
+		else if (d_peek_char (di) == 'i'
+			 && d_peek_next_char (di) == 'l')
+		  /* initializer-list.  */
+		  third = d_expression (di);
+		else
+		  return NULL;
+	      }
+	    else
+	      return NULL;
 	    return d_make_comp (di, DEMANGLE_COMPONENT_TRINARY, op,
 				d_make_comp (di,
 					     DEMANGLE_COMPONENT_TRINARY_ARG1,
 					     first,
 					     d_make_comp (di,
 							  DEMANGLE_COMPONENT_TRINARY_ARG2,
-							  second,
-							  d_expression (di))));
+							  second, third)));
 	  }
 	default:
 	  return NULL;
@@ -3666,6 +3745,8 @@ d_print_subexpr (struct d_print_info *dpi, int options,
 {
   int simple = 0;
   if (dc->type == DEMANGLE_COMPONENT_NAME
+      || dc->type == DEMANGLE_COMPONENT_QUAL_NAME
+      || dc->type == DEMANGLE_COMPONENT_INITIALIZER_LIST
       || dc->type == DEMANGLE_COMPONENT_FUNCTION_PARAM)
     simple = 1;
   if (!simple)
@@ -4261,6 +4342,19 @@ d_print_comp (struct d_print_info *dpi, int options,
 	}
       return;
 
+    case DEMANGLE_COMPONENT_INITIALIZER_LIST:
+      {
+	struct demangle_component *type = d_left (dc);
+	struct demangle_component *list = d_right (dc);
+
+	if (type)
+	  d_print_comp (dpi, options, type);
+	d_append_char (dpi, '{');
+	d_print_comp (dpi, options, list);
+	d_append_char (dpi, '}');
+      }
+      return;
+
     case DEMANGLE_COMPONENT_OPERATOR:
       {
 	char c;
@@ -4284,55 +4378,59 @@ d_print_comp (struct d_print_info *dpi, int options,
       d_print_cast (dpi, options, dc);
       return;
 
+    case DEMANGLE_COMPONENT_NULLARY:
+      d_print_expr_op (dpi, options, d_left (dc));
+      return;
+
     case DEMANGLE_COMPONENT_UNARY:
-      if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR
-	  && d_left (dc)->u.s_operator.op->len == 1
-	  && d_left (dc)->u.s_operator.op->name[0] == '&'
-	  && d_right (dc)->type == DEMANGLE_COMPONENT_TYPED_NAME
-	  && d_left (d_right (dc))->type == DEMANGLE_COMPONENT_QUAL_NAME
-	  && d_right (d_right (dc))->type == DEMANGLE_COMPONENT_FUNCTION_TYPE)
-	{
-	  /* Address of a function (therefore in an expression context) must
-	     have its argument list suppressed.
-
-	     unary operator ... dc
-	       operator & ... d_left (dc)
-	       typed name ... d_right (dc)
-		 qualified name ... d_left (d_right (dc))
-		   <names>
-		 function type ... d_right (d_right (dc))
-		   argument list
-		     <arguments>  */
-
-	  d_print_expr_op (dpi, options, d_left (dc));
-	  d_print_comp (dpi, options, d_left (d_right (dc)));
-	  return;
-	}
-      else if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR
-	       && d_left (dc)->u.s_operator.op->len == 1
-	       && d_left (dc)->u.s_operator.op->name[0] == '&'
-	       && d_right (dc)->type == DEMANGLE_COMPONENT_QUAL_NAME)
-	{
-	  /* Keep also already processed variant without the argument list.
+      {
+	struct demangle_component *op = d_left (dc);
+	struct demangle_component *operand = d_right (dc);
+	const char *code = NULL;
 
-	     unary operator ... dc
-	       operator & ... d_left (dc)
-	       qualified name ... d_right (dc)
-		 <names>  */
+	if (op->type == DEMANGLE_COMPONENT_OPERATOR)
+	  {
+	    code = op->u.s_operator.op->code;
+	    if (!strcmp (code, "ad"))
+	      {
+		/* Don't print the argument list for the address of a
+		   function.  */
+		if (operand->type == DEMANGLE_COMPONENT_TYPED_NAME
+		    && d_left (operand)->type == DEMANGLE_COMPONENT_QUAL_NAME
+		    && d_right (operand)->type == DEMANGLE_COMPONENT_FUNCTION_TYPE)
+		  operand = d_left (operand);
+	      }
+	    if (operand->type == DEMANGLE_COMPONENT_BINARY_ARGS)
+	      {
+		/* This indicates a suffix operator.  */
+		operand = d_left (operand);
+		d_print_subexpr (dpi, options, operand);
+		d_print_expr_op (dpi, options, op);
+		return;
+	      }
+	  }
 
-	  d_print_expr_op (dpi, options, d_left (dc));
-	  d_print_comp (dpi, options, d_right (dc));
-	  return;
-	}
-      else if (d_left (dc)->type != DEMANGLE_COMPONENT_CAST)
-	d_print_expr_op (dpi, options, d_left (dc));
-      else
-	{
-	  d_append_char (dpi, '(');
-	  d_print_cast (dpi, options, d_left (dc));
-	  d_append_char (dpi, ')');
-	}
-      d_print_subexpr (dpi, options, d_right (dc));
+	if (op->type != DEMANGLE_COMPONENT_CAST)
+	  d_print_expr_op (dpi, options, op);
+	else
+	  {
+	    d_append_char (dpi, '(');
+	    d_print_cast (dpi, options, op);
+	    d_append_char (dpi, ')');
+	  }
+	if (code && !strcmp (code, "gs"))
+	  /* Avoid parens after '::'.  */
+	  d_print_comp (dpi, options, operand);
+	else if (code && !strcmp (code, "st"))
+	  /* Always print parens for sizeof (type).  */
+	  {
+	    d_append_char (dpi, '(');
+	    d_print_comp (dpi, options, operand);
+	    d_append_char (dpi, ')');
+	  }
+	else
+	  d_print_subexpr (dpi, options, operand);
+      }
       return;
 
     case DEMANGLE_COMPONENT_BINARY:
@@ -4397,11 +4495,33 @@ d_print_comp (struct d_print_info *dpi, int options,
 	  d_print_error (dpi);
 	  return;
 	}
-      d_print_subexpr (dpi, options, d_left (d_right (dc)));
-      d_print_expr_op (dpi, options, d_left (dc));
-      d_print_subexpr (dpi, options, d_left (d_right (d_right (dc))));
-      d_append_string (dpi, " : ");
-      d_print_subexpr (dpi, options, d_right (d_right (d_right (dc))));
+      {
+	struct demangle_component *op = d_left (dc);
+	struct demangle_component *first = d_left (d_right (dc));
+	struct demangle_component *second = d_left (d_right (d_right (dc)));
+	struct demangle_component *third = d_right (d_right (d_right (dc)));
+
+	if (!strcmp (op->u.s_operator.op->code, "qu"))
+	  {
+	    d_print_subexpr (dpi, options, first);
+	    d_print_expr_op (dpi, options, op);
+	    d_print_subexpr (dpi, options, second);
+	    d_append_string (dpi, " : ");
+	    d_print_subexpr (dpi, options, third);
+	  }
+	else
+	  {
+	    d_append_string (dpi, "new ");
+	    if (d_left (first) != NULL)
+	      {
+		d_print_subexpr (dpi, options, first);
+		d_append_char (dpi, ' ');
+	      }
+	    d_print_comp (dpi, options, second);
+	    if (third)
+	      d_print_subexpr (dpi, options, third);
+	  }
+      }
       return;
 
     case DEMANGLE_COMPONENT_TRINARY_ARG1:
diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected
index 642fe14..3f3960a 100644
--- a/libiberty/testsuite/demangle-expected
+++ b/libiberty/testsuite/demangle-expected
@@ -3935,7 +3935,7 @@ _Z1tIlEDTplcvT_Li5EclL_Z1qsELi6EEEv
 decltype (((long)(5))+(q(6))) t<long>()
 # test for expansion of function parameter pack
 --format=gnu-v3
-_Z1gIIidEEDTclL_Z1fEspplfp_Li1EEEDpT_
+_Z1gIJidEEDTclL_Z1fEspplfp_Li1EEEDpT_
 decltype (f(({parm#1}+(1))...)) g<int, double>(int, double)
 # lambda tests
 --format=gnu-v3
@@ -4030,6 +4030,45 @@ decltype ((int)()) f<int, int>(int, int)
 --format=gnu-v3
 _Z1fDv4_iS_
 f(int __vector(4), int __vector(4))
+--format=gnu-v3
+_Z2f1Ii1AEDTdsfp_fp0_ET0_MS2_T_
+decltype ({parm#1}.*{parm#2}) f1<int, A>(A, int A::*)
+--format=gnu-v3
+_Z2f2IiEDTquL_Z1bEfp_trET_
+decltype (b?{parm#1} : (throw)) f2<int>(int)
+--format=gnu-v3
+_Z6check1IiEvP6helperIXsznw_T_EEE
+void check1<int>(helper<sizeof (new int)>*)
+--format=gnu-v3
+_Z6check2IiEvP6helperIXszgsnw_T_piEEE
+void check2<int>(helper<sizeof (::new int())>*)
+--format=gnu-v3
+_Z6check3IiEvP6helperIXsznwadL_Z1iE_T_piLi1EEEE
+void check3<int>(helper<sizeof (new (&i) int(1))>*)
+--format=gnu-v3
+_Z6check4IiEvP6helperIXszna_A1_T_EEE
+void check4<int>(helper<sizeof (new int [1])>*)
+--format=gnu-v3
+_Z6check5IiEvP6helperIXszna_A1_T_piEEE
+void check5<int>(helper<sizeof (new int [1]())>*)
+--format=gnu-v3
+_Z1fIiEDTcmgsdlfp_psfp_EPT_
+decltype ((::delete {parm#1}),(+{parm#1})) f<int>(int*)
+--format=gnu-v3
+_Z1fIiEDTcmdafp_psfp_EPT_
+decltype ((delete[] {parm#1}),(+{parm#1})) f<int>(int*)
+--format=gnu-v3
+_Z2f1IiEDTppfp_ET_
+decltype ({parm#1}++) f1<int>(int)
+--format=gnu-v3
+_Z2f1IiEDTpp_fp_ET_
+decltype (++{parm#1}) f1<int>(int)
+--format=gnu-v3
+_Z2f1IiEDTcl1gfp_ilEEET_
+decltype (g({parm#1}, {})) f1<int>(int)
+--format=gnu-v3
+_Z2f1IiEDTnw_T_ilEES0_
+decltype (new int{}) f1<int>(int)
 #
 # Ada (GNAT) tests.
 #
diff --git a/libstdc++-v3/testsuite/abi/demangle/regression/cw-16.cc b/libstdc++-v3/testsuite/abi/demangle/regression/cw-16.cc
index 49d44bc..12fa6fe 100644
--- a/libstdc++-v3/testsuite/abi/demangle/regression/cw-16.cc
+++ b/libstdc++-v3/testsuite/abi/demangle/regression/cw-16.cc
@@ -39,7 +39,7 @@ verify_demangle("_Z1fPFYPFiiEiE",
 verify_demangle("_Z1fI1XENT_1tES2_",
                 "X::t f<X>(X::t)");
 verify_demangle("_Z1fILi5E1AEvN1CIXstN1T1tEEXszsrS2_1tEE1qE",
-                "void f<5, A>(C<sizeof (T::t), sizeof (T::t)>::q)");
+                "void f<5, A>(C<sizeof (T::t), sizeof T::t>::q)");
 // 2003/12/03, libstdc++/13045
 verify_demangle("_Z1fILi1ELc120EEv1AIXplT_cviLd4028ae147ae147aeEEE",
                 "void f<1, (char)120>(A<(1)+((int)((double)[4028ae147ae147ae]))>)");
