commit 3f2eec8c217136c06a1c24af4ded96a6cde5a4df
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Sep 16 11:11:02 2011 -0400

    	Implement C++11 non-static data member initializers.
    	* cp-tree.h (enum cpp_warn_str): Add CPP0X_NSDMI.
    	* error.c (maybe_warn_cpp0x): Handle it.
    	* call.c (convert_like_real) [ck_user]: Don't complain about
    	using an explicit constructor for direct-initialization.
    	* class.c (check_field_decl): Fix ancient typo.
    	(check_field_decls): NSDMIs make the default ctor non-trivial.
    	* decl.c (cp_finish_decl): Record NSDMI.
    	(grokdeclarator): Allow NSDMI.
    	* decl2.c (grokfield): Allow NSDMI.  Correct LOOKUP flags.
    	* init.c (perform_member_init): Use NSDMI.
    	* method.c (walk_field_subobs): Check for NSDMI.
    	* parser.c (cp_parser_member_declaration): Parse { } init.
    	* semantics.c (register_constexpr_fundef): Don't talk about
    	a return statement in a constexpr constructor.
    	(cxx_eval_call_expression): Check DECL_INITIAL instead of
    	DECL_SAVED_TREE.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 8c99f7a..6a7dfd3 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5648,6 +5648,9 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 	/* When converting from an init list we consider explicit
 	   constructors, but actually trying to call one is an error.  */
 	if (DECL_NONCONVERTING_P (convfn) && DECL_CONSTRUCTOR_P (convfn)
+	    /* Unless this is for direct-list-initialization.  */
+	    && !(BRACE_ENCLOSED_INITIALIZER_P (expr)
+		 && CONSTRUCTOR_IS_DIRECT_INIT (expr))
 	    /* Unless we're calling it for value-initialization from an
 	       empty list, since that is handled separately in 8.5.4.  */
 	    && cand->num_convs > 0)
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index acfe3f2..a7d8218 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -2958,7 +2958,7 @@ check_field_decl (tree field,
     {
       /* `build_class_init_list' does not recognize
 	 non-FIELD_DECLs.  */
-      if (TREE_CODE (t) == UNION_TYPE && any_default_members != 0)
+      if (TREE_CODE (t) == UNION_TYPE && *any_default_members != 0)
 	error ("multiple fields in union %qT initialized", t);
       *any_default_members = 1;
     }
@@ -3256,6 +3256,14 @@ check_field_decls (tree t, tree *access_decls,
 		 "  but does not override %<operator=(const %T&)%>", t);
     }
 
+  /* Non-static data member initializers make the default constructor
+     non-trivial.  */
+  if (any_default_members)
+    {
+      TYPE_NEEDS_CONSTRUCTING (t) = true;
+      TYPE_HAS_COMPLEX_DFLT (t) = true;
+    }
+
   /* If any of the fields couldn't be packed, unset TYPE_PACKED.  */
   if (cant_pack)
     TYPE_PACKED (t) = 0;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f2c9211..2f93bba 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -394,7 +394,9 @@ typedef enum cpp0x_warn_str
   /* inline namespaces */
   CPP0X_INLINE_NAMESPACES,
   /* override controls, override/final */
-  CPP0X_OVERRIDE_CONTROLS
+  CPP0X_OVERRIDE_CONTROLS,
+  /* non-static data member initializers */
+  CPP0X_NSDMI
 } cpp0x_warn_str;
   
 /* The various kinds of operation used by composite_pointer_type. */
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 495d8a0..661cc5e 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6075,6 +6075,10 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
       return;
     }
 
+  /* Just store non-static data member initializers for later.  */
+  if (init && TREE_CODE (decl) == FIELD_DECL)
+    DECL_INITIAL (decl) = digest_init_flags (TREE_TYPE (decl), init, flags);
+
   /* Take care of TYPE_DECLs up front.  */
   if (TREE_CODE (decl) == TYPE_DECL)
     {
@@ -10087,36 +10091,6 @@ grokdeclarator (const cp_declarator *declarator,
 
 	if (decl == NULL_TREE)
 	  {
-	    if (initialized)
-	      {
-		if (!staticp)
-		  {
-		    /* An attempt is being made to initialize a non-static
-		       member.  But, from [class.mem]:
-
-		       4 A member-declarator can contain a
-		       constant-initializer only if it declares a static
-		       member (_class.static_) of integral or enumeration
-		       type, see _class.static.data_.
-
-		       This used to be relatively common practice, but
-		       the rest of the compiler does not correctly
-		       handle the initialization unless the member is
-		       static so we make it static below.  */
-		    if (cxx_dialect >= cxx0x)
-		      {
-			sorry ("non-static data member initializers");
-		      }
-		    else
-		      {
-			permerror (input_location, "ISO C++ forbids initialization of member %qD",
-				   unqualified_id);
-			permerror (input_location, "making %qD static", unqualified_id);
-			staticp = 1;
-		      }
-		  }
-	      }
-
 	    if (staticp)
 	      {
 		/* C++ allows static class members.  All other work
@@ -10157,6 +10131,11 @@ grokdeclarator (const cp_declarator *declarator,
 		    DECL_MUTABLE_P (decl) = 1;
 		    storage_class = sc_none;
 		  }
+
+		if (initialized)
+		  /* An attempt is being made to initialize a non-static
+		     member.  This is new in C++11.  */
+		  maybe_warn_cpp0x (CPP0X_NSDMI);
 	      }
 
 	    bad_specifiers (decl, BSP_FIELD, virtualp,
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 68e9b9b..1e06280 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -795,7 +795,7 @@ grokfield (const cp_declarator *declarator,
 {
   tree value;
   const char *asmspec = 0;
-  int flags = LOOKUP_ONLYCONVERTING;
+  int flags;
   tree name;
 
   if (init
@@ -919,9 +919,10 @@ grokfield (const cp_declarator *declarator,
 		     value);
 	    }
 	}
-      else if (pedantic && TREE_CODE (value) != VAR_DECL)
-	/* Already complained in grokdeclarator.  */
-	init = NULL_TREE;
+      else if (TREE_CODE (value) == FIELD_DECL)
+	/* C++11 NSDMI, keep going.  */;
+      else if (TREE_CODE (value) != VAR_DECL)
+	gcc_unreachable ();
       else if (!processing_template_decl)
 	{
 	  if (TREE_CODE (init) == CONSTRUCTOR)
@@ -955,6 +956,12 @@ grokfield (const cp_declarator *declarator,
   if (attrlist)
     cplus_decl_attributes (&value, attrlist, 0);
 
+  if (init && BRACE_ENCLOSED_INITIALIZER_P (init)
+      && CONSTRUCTOR_IS_DIRECT_INIT (init))
+    flags = LOOKUP_NORMAL;
+  else
+    flags = LOOKUP_IMPLICIT;
+
   switch (TREE_CODE (value))
     {
     case VAR_DECL:
@@ -969,7 +976,6 @@ grokfield (const cp_declarator *declarator,
 	init = error_mark_node;
       cp_finish_decl (value, init, /*init_const_expr_p=*/false,
 		      NULL_TREE, flags);
-      DECL_INITIAL (value) = init;
       DECL_IN_AGGR_P (value) = 1;
       return value;
 
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 598ddf1..392f304 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -3236,6 +3236,11 @@ maybe_warn_cpp0x (cpp0x_warn_str str)
 		 "override controls (override/final) "
 		 "only available with -std=c++0x or -std=gnu++0x");
         break;
+      case CPP0X_NSDMI:
+	pedwarn (input_location, 0,
+		 "non-static data member initializers "
+		 "only available with -std=c++0x or -std=gnu++0x");
+        break;
       default:
 	gcc_unreachable();
       }
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index ac3221e..f5904d5 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -493,6 +493,11 @@ perform_member_init (tree member, tree init)
   tree decl;
   tree type = TREE_TYPE (member);
 
+  /* Use the non-static data member initializer if there was no
+     mem-initializer for this field.  */
+  if (init == NULL_TREE)
+    init = break_out_target_exprs (DECL_INITIAL (member));
+
   /* Effective C++ rule 12 requires that all data members be
      initialized.  */
   if (warn_ecpp && init == NULL_TREE && TREE_CODE (type) != ARRAY_TYPE)
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 88bb2a9..734c23b 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1036,10 +1036,20 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
 	  if (bad && deleted_p)
 	    *deleted_p = true;
 
+	  if (DECL_INITIAL (field))
+	    {
+	      if (msg && DECL_INITIAL (field) == error_mark_node)
+		inform (0, "initializer for %q+#D is invalid", field);
+	      if (trivial_p)
+		*trivial_p = false;
+
+	      /* Don't do the normal processing.  */
+	      continue;
+	    }
+
 	  /* For an implicitly-defined default constructor to be constexpr,
-	     every member must have a user-provided default constructor.  */
-	  /* FIXME will need adjustment for non-static data member
-	     initializers.  */
+	     every member must have a user-provided default constructor or
+	     an explicit initializer.  */
 	  if (constexpr_p && !CLASS_TYPE_P (mem_type))
 	    {
 	      *constexpr_p = false;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 2283312..bd46af3 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -18202,6 +18202,12 @@ cp_parser_member_declaration (cp_parser* parser)
 		    /* Parse the initializer.  */
 		    initializer = cp_parser_constant_initializer (parser);
 		}
+	      else if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)
+		       && !function_declarator_p (declarator))
+		{
+		  bool x;
+		  initializer = cp_parser_initializer (parser, &x, &x);
+		}
 	      /* Otherwise, there is no initializer.  */
 	      else
 		initializer = NULL_TREE;
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0662b29..19ecbee 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -5826,8 +5826,8 @@ register_constexpr_fundef (tree fun, tree body)
   body = massage_constexpr_body (fun, body);
   if (body == NULL_TREE || body == error_mark_node)
     {
-      error ("body of constexpr function %qD not a return-statement", fun);
-      DECL_DECLARED_CONSTEXPR_P (fun) = false;
+      if (!DECL_CONSTRUCTOR_P (fun))
+	error ("body of constexpr function %qD not a return-statement", fun);
       return NULL;
     }
 
@@ -6245,7 +6245,7 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
         {
 	  if (!allow_non_constant)
 	    {
-	      if (DECL_SAVED_TREE (fun))
+	      if (DECL_INITIAL (fun))
 		{
 		  /* The definition of fun was somehow unsuitable.  */
 		  error_at (loc, "%qD called in a constant expression", fun);
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi1.C
new file mode 100644
index 0000000..f6381d0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi1.C
@@ -0,0 +1,53 @@
+// { dg-do run }
+// { dg-options -std=c++0x }
+
+struct A
+{
+  int i = 42;
+};
+
+struct B
+{
+  int i = 42;
+  B() { }
+  B(int i): i(i) { }
+};
+
+template <class T, T t>
+struct C
+{
+  T m = t;
+};
+
+template <class T, T t>
+struct D
+{
+  T m = t;
+  D() { }
+  D(T m):m(m) { }
+};
+
+int main()
+{
+  A a1;
+  if (a1.i != 42) return 1;
+  A a2 = { 24 };
+  if (a2.i != 24) return 2;
+  A a3[1];
+  if (a3[0].i != 42) return 3;
+
+  B b1;
+  if (b1.i != 42) return 3;
+  B b2 (24);
+  if (b2.i != 24) return 4;
+
+  C<int,3> c1;
+  if (c1.m != 3) return 5;
+  C<int,3> c2 { 5 };
+  if (c2.m != 5) return 6;
+
+  D<int,3> d1;
+  if (d1.m != 3) return 7;
+  D<int,3> d2 (5) ;
+  if (d2.m != 5) return 8;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi2.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi2.C
new file mode 100644
index 0000000..9636bed
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi2.C
@@ -0,0 +1,21 @@
+// { dg-options -std=c++0x }
+
+struct A
+{
+  int i;
+  constexpr A(int i): i(i) {}
+};
+
+struct B
+{
+  A a1 = 1;
+  A a2 { 2 };
+  A a3 = { 3 };
+};
+
+#define SA(X) static_assert(X,#X)
+
+constexpr B b;
+SA(b.a1.i == 1);
+SA(b.a2.i == 2);
+SA(b.a3.i == 3);
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi3.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi3.C
new file mode 100644
index 0000000..73b2bc2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi3.C
@@ -0,0 +1,18 @@
+// { dg-options -std=c++0x }
+
+struct A
+{
+  int i;
+  explicit constexpr A(int i): i(i) {}
+};
+
+struct B
+{
+  A a1 = 1;			// { dg-error "" }
+  A a2 { 2 };
+  A a3 = { 3 };			// { dg-error "" }
+};
+
+constexpr B b;			// { dg-error "B::B" }
+
+// { dg-message "a1. is invalid" "" { target *-*-* } 11 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi4.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi4.C
new file mode 100644
index 0000000..db365cb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi4.C
@@ -0,0 +1,24 @@
+// { dg-do run }
+// { dg-options -std=c++0x }
+
+int c;
+
+struct A
+{
+  A() { }
+  A(const A&) { }
+};
+
+A f() { ++c; return A(); }
+
+struct B
+{
+  A a = f();
+};
+
+int main()
+{
+  B b1, b2;
+  if (c != 2)
+    __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/init4.C b/gcc/testsuite/g++.old-deja/g++.other/init4.C
index 92562ef..f8246d6 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/init4.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/init4.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++98 }
+// { dg-options "-std=c++98 -pedantic-errors" }
 // { dg-do assemble  }
 
 class error {

commit 09c44f25bcee3c4f77ba9070522c676d15314576
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Sep 23 14:21:31 2011 -0400

    	Handle deferred parsing of NSDMIs.
    	* parser.h (cp_unparsed_functions_entry): Add nsdmis field.
    	* parser.c (unparsed_nsdmis, cp_parser_save_nsdmi): New.
    	(cp_parser_late_parse_one_default_arg): Split out from
    	cp_parser_late_parsing_default_args.
    	(cp_parser_late_parsing_nsdmi): New.
    	(push_unparsed_function_queues): Set it.
    	(cp_parser_parameter_declaration): Save the '=' token.
    	(cp_parser_template_parameter): Likewise.
    	(cp_parser_default_argument): Call cp_parser_initializer
    	rather than cp_parser_initializer_clause.
    	(cp_parser_class_specifier_1): Parse unparsed_nsdmis.
    	(cp_parser_member_declaration): Handle nsdmis.
    	* decl2.c (grokfield): Handle DEFAULT_ARG for a function.

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 661cc5e..45bf6a1 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6077,7 +6077,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
 
   /* Just store non-static data member initializers for later.  */
   if (init && TREE_CODE (decl) == FIELD_DECL)
-    DECL_INITIAL (decl) = digest_init_flags (TREE_TYPE (decl), init, flags);
+    DECL_INITIAL (decl) = init;
 
   /* Take care of TYPE_DECLs up front.  */
   if (TREE_CODE (decl) == TYPE_DECL)
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 1e06280..6e5f7cc 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -902,6 +902,8 @@ grokfield (const cp_declarator *declarator,
 		  DECL_DECLARED_INLINE_P (value) = 1;
 		}
 	    }
+	  else if (TREE_CODE (init) == DEFAULT_ARG)
+	    error ("invalid initializer for member function %qD", value);
 	  else if (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE)
 	    {
 	      if (integer_zerop (init))
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index bd46af3..2dbe866 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1486,6 +1486,8 @@ cp_parser_context_new (cp_parser_context* next)
   VEC_last (cp_unparsed_functions_entry, parser->unparsed_queues)->funs_with_default_args
 #define unparsed_funs_with_definitions \
   VEC_last (cp_unparsed_functions_entry, parser->unparsed_queues)->funs_with_definitions
+#define unparsed_nsdmis \
+  VEC_last (cp_unparsed_functions_entry, parser->unparsed_queues)->nsdmis
 
 static void
 push_unparsed_function_queues (cp_parser *parser)
@@ -1494,6 +1496,7 @@ push_unparsed_function_queues (cp_parser *parser)
 		 parser->unparsed_queues, NULL);
   unparsed_funs_with_default_args = NULL;
   unparsed_funs_with_definitions = make_tree_vector ();
+  unparsed_nsdmis = NULL;
 }
 
 static void
@@ -1936,12 +1939,18 @@ static tree cp_parser_functional_cast
   (cp_parser *, tree);
 static tree cp_parser_save_member_function_body
   (cp_parser *, cp_decl_specifier_seq *, cp_declarator *, tree);
+static tree cp_parser_save_nsdmi
+  (cp_parser *);
 static tree cp_parser_enclosed_template_argument_list
   (cp_parser *);
 static void cp_parser_save_default_args
   (cp_parser *, tree);
 static void cp_parser_late_parsing_for_member
   (cp_parser *, tree);
+static tree cp_parser_late_parse_one_default_arg
+  (cp_parser *, tree, tree, tree);
+static void cp_parser_late_parsing_nsdmi
+  (cp_parser *, tree);
 static void cp_parser_late_parsing_default_args
   (cp_parser *, tree);
 static tree cp_parser_sizeof_operand
@@ -11343,9 +11352,7 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
 	 user may try to do so, so we'll parse them and give an
 	 appropriate diagnostic here.  */
 
-      /* Consume the `='.  */
       cp_token *start_token = cp_lexer_peek_token (parser->lexer);
-      cp_lexer_consume_token (parser->lexer);
       
       /* Find the name of the parameter pack.  */     
       id_declarator = parameter_declarator->declarator;
@@ -16323,9 +16330,6 @@ cp_parser_parameter_declaration (cp_parser *parser,
   /* If the next token is `=', then process a default argument.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
     {
-      /* Consume the `='.  */
-      cp_lexer_consume_token (parser->lexer);
-
       /* If we are defining a class, then the tokens that make up the
 	 default argument must be saved and processed later.  */
       if (!template_parm_p && at_class_scope_p ()
@@ -16535,7 +16539,7 @@ cp_parser_default_argument (cp_parser *parser, bool template_parm_p)
   tree default_argument = NULL_TREE;
   bool saved_greater_than_is_operator_p;
   bool saved_local_variables_forbidden_p;
-  bool non_constant_p;
+  bool non_constant_p, is_direct_init;
 
   /* Make sure that PARSER->GREATER_THAN_IS_OPERATOR_P is
      set correctly.  */
@@ -16549,7 +16553,7 @@ cp_parser_default_argument (cp_parser *parser, bool template_parm_p)
   if (template_parm_p)
     push_deferring_access_checks (dk_no_deferred);
   default_argument
-    = cp_parser_initializer_clause (parser, &non_constant_p);
+    = cp_parser_initializer (parser, &is_direct_init, &non_constant_p);
   if (BRACE_ENCLOSED_INITIALIZER_P (default_argument))
     maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
   if (template_parm_p)
@@ -17265,7 +17269,7 @@ cp_parser_class_specifier_1 (cp_parser* parser)
      there is no need to delay the parsing of `A::B::f'.  */
   if (--parser->num_classes_being_defined == 0)
     {
-      tree fn;
+      tree decl;
       tree class_type = NULL_TREE;
       tree pushed_scope = NULL_TREE;
       unsigned ix;
@@ -17284,7 +17288,7 @@ cp_parser_class_specifier_1 (cp_parser* parser)
       FOR_EACH_VEC_ELT (cp_default_arg_entry, unparsed_funs_with_default_args,
 			ix, e)
 	{
-	  fn = e->decl;
+	  decl = e->decl;
 	  /* If there are default arguments that have not yet been processed,
 	     take care of them now.  */
 	  if (class_type != e->class_type)
@@ -17295,18 +17299,31 @@ cp_parser_class_specifier_1 (cp_parser* parser)
 	      pushed_scope = push_scope (class_type);
 	    }
 	  /* Make sure that any template parameters are in scope.  */
-	  maybe_begin_member_template_processing (fn);
+	  maybe_begin_member_template_processing (decl);
 	  /* Parse the default argument expressions.  */
-	  cp_parser_late_parsing_default_args (parser, fn);
+	  cp_parser_late_parsing_default_args (parser, decl);
 	  /* Remove any template parameters from the symbol table.  */
 	  maybe_end_member_template_processing ();
 	}
+      VEC_truncate (cp_default_arg_entry, unparsed_funs_with_default_args, 0);
+      /* Now parse any NSDMIs.  */
+      FOR_EACH_VEC_ELT (tree, unparsed_nsdmis, ix, decl)
+	{
+	  if (class_type != DECL_CONTEXT (decl))
+	    {
+	      if (pushed_scope)
+		pop_scope (pushed_scope);
+	      class_type = DECL_CONTEXT (decl);
+	      pushed_scope = push_scope (class_type);
+	    }
+	  cp_parser_late_parsing_nsdmi (parser, decl);
+	}
+      VEC_truncate (tree, unparsed_nsdmis, 0);
       if (pushed_scope)
 	pop_scope (pushed_scope);
-      VEC_truncate (cp_default_arg_entry, unparsed_funs_with_default_args, 0);
       /* Now parse the body of the functions.  */
-      FOR_EACH_VEC_ELT (tree, unparsed_funs_with_definitions, ix, fn)
-	cp_parser_late_parsing_for_member (parser, fn);
+      FOR_EACH_VEC_ELT (tree, unparsed_funs_with_definitions, ix, decl)
+	cp_parser_late_parsing_for_member (parser, decl);
       VEC_truncate (tree, unparsed_funs_with_definitions, 0);
     }
 
@@ -18185,8 +18202,14 @@ cp_parser_member_declaration (cp_parser* parser)
 		     constant-initializer.  When we call `grokfield', it will
 		     perform more stringent semantics checks.  */
 		  initializer_token_start = cp_lexer_peek_token (parser->lexer);
-		  if (function_declarator_p (declarator))
+		  if (function_declarator_p (declarator)
+		      || (decl_specifiers.type
+			  && TREE_CODE (decl_specifiers.type) == TYPE_DECL
+			  && (TREE_CODE (TREE_TYPE (decl_specifiers.type))
+			      == FUNCTION_TYPE)))
 		    initializer = cp_parser_pure_specifier (parser);
+		  else if (decl_specifiers.storage_class != sc_static)
+		    initializer = cp_parser_save_nsdmi (parser);
 		  else if (cxx_dialect >= cxx0x)
 		    {
 		      bool nonconst;
@@ -18206,7 +18229,10 @@ cp_parser_member_declaration (cp_parser* parser)
 		       && !function_declarator_p (declarator))
 		{
 		  bool x;
-		  initializer = cp_parser_initializer (parser, &x, &x);
+		  if (decl_specifiers.storage_class != sc_static)
+		    initializer = cp_parser_save_nsdmi (parser);
+		  else
+		    initializer = cp_parser_initializer (parser, &x, &x);
 		}
 	      /* Otherwise, there is no initializer.  */
 	      else
@@ -18292,6 +18318,11 @@ cp_parser_member_declaration (cp_parser* parser)
 
 	      if (TREE_CODE (decl) == FUNCTION_DECL)
 		cp_parser_save_default_args (parser, decl);
+	      else if (TREE_CODE (decl) == FIELD_DECL
+		       && !DECL_C_BIT_FIELD (decl)
+		       && DECL_INITIAL (decl))
+		/* Add DECL to the queue of NSDMI to be parsed later.  */
+		VEC_safe_push (tree, gc, unparsed_nsdmis, decl);
 	    }
 
 	  if (assume_semicolon)
@@ -20539,6 +20570,30 @@ cp_parser_save_member_function_body (cp_parser* parser,
   return fn;
 }
 
+/* Save the tokens that make up the in-class initializer for a non-static
+   data member.  Returns a DEFAULT_ARG.  */
+
+static tree
+cp_parser_save_nsdmi (cp_parser* parser)
+{
+  /* Save away the tokens that make up the body of the
+     function.  */
+  cp_token *first = parser->lexer->next_token;
+  cp_token *last;
+  tree node;
+
+  cp_parser_cache_group (parser, CPP_CLOSE_PAREN, /*depth=*/0);
+
+  last = parser->lexer->next_token;
+
+  node = make_node (DEFAULT_ARG);
+  DEFARG_TOKENS (node) = cp_token_cache_new (first, last);
+  DEFARG_INSTANTIATIONS (node) = NULL;
+
+  return node;
+}
+
+
 /* Parse a template-argument-list, as well as the trailing ">" (but
    not the opening ">").  See cp_parser_template_argument_list for the
    return value.  */
@@ -20744,6 +20799,83 @@ cp_parser_save_default_args (cp_parser* parser, tree decl)
       }
 }
 
+/* DEFAULT_ARG contains the saved tokens for the initializer of DECL,
+   which is either a FIELD_DECL or PARM_DECL.  Parse it and return
+   the result.  For a PARM_DECL, PARMTYPE is the corresponding type
+   from the parameter-type-list.  */
+
+static tree
+cp_parser_late_parse_one_default_arg (cp_parser *parser, tree decl,
+				      tree default_arg, tree parmtype)
+{
+  cp_token_cache *tokens;
+  tree parsed_arg;
+  bool dummy;
+
+  /* Push the saved tokens for the default argument onto the parser's
+     lexer stack.  */
+  tokens = DEFARG_TOKENS (default_arg);
+  cp_parser_push_lexer_for_tokens (parser, tokens);
+
+  start_lambda_scope (decl);
+
+  /* Parse the default argument.  */
+  parsed_arg = cp_parser_initializer (parser, &dummy, &dummy);
+  if (BRACE_ENCLOSED_INITIALIZER_P (parsed_arg))
+    maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
+
+  finish_lambda_scope ();
+
+  if (!processing_template_decl)
+    {
+      /* In a non-template class, check conversions now.  In a template,
+	 we'll wait and instantiate these as needed.  */
+      if (TREE_CODE (decl) == PARM_DECL)
+	parsed_arg = check_default_argument (parmtype, parsed_arg);
+      else
+	{
+	  int flags = LOOKUP_IMPLICIT;
+	  if (BRACE_ENCLOSED_INITIALIZER_P (parsed_arg)
+	      && CONSTRUCTOR_IS_DIRECT_INIT (parsed_arg))
+	    flags = LOOKUP_NORMAL;
+	  parsed_arg = digest_init_flags (TREE_TYPE (decl), parsed_arg, flags);
+	}
+    }
+
+  /* If the token stream has not been completely used up, then
+     there was extra junk after the end of the default
+     argument.  */
+  if (!cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+    {
+      if (TREE_CODE (decl) == PARM_DECL)
+	cp_parser_error (parser, "expected %<,%>");
+      else
+	cp_parser_error (parser, "expected %<;%>");
+    }
+
+  /* Revert to the main lexer.  */
+  cp_parser_pop_lexer (parser);
+
+  return parsed_arg;
+}
+
+/* FIELD is a non-static data member with an initializer which we saved for
+   later; parse it now.  */
+
+static void
+cp_parser_late_parsing_nsdmi (cp_parser *parser, tree field)
+{
+  tree def;
+
+  push_unparsed_function_queues (parser);
+  def = cp_parser_late_parse_one_default_arg (parser, field,
+					      DECL_INITIAL (field),
+					      NULL_TREE);
+  pop_unparsed_function_queues (parser);
+
+  DECL_INITIAL (field) = def;
+}
+
 /* FN is a FUNCTION_DECL which may contains a parameter with an
    unparsed DEFAULT_ARG.  Parse the default args now.  This function
    assumes that the current scope is the scope in which the default
@@ -20753,7 +20885,6 @@ static void
 cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
 {
   bool saved_local_variables_forbidden_p;
-  bool non_constant_p;
   tree parm, parmdecl;
 
   /* While we're parsing the default args, we might (due to the
@@ -20775,7 +20906,6 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
        parm = TREE_CHAIN (parm),
 	 parmdecl = DECL_CHAIN (parmdecl))
     {
-      cp_token_cache *tokens;
       tree default_arg = TREE_PURPOSE (parm);
       tree parsed_arg;
       VEC(tree,gc) *insts;
@@ -20790,25 +20920,14 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
 	   already declared with default arguments.  */
 	continue;
 
-       /* Push the saved tokens for the default argument onto the parser's
-	  lexer stack.  */
-      tokens = DEFARG_TOKENS (default_arg);
-      cp_parser_push_lexer_for_tokens (parser, tokens);
-
-      start_lambda_scope (parmdecl);
-
-      /* Parse the assignment-expression.  */
-      parsed_arg = cp_parser_initializer_clause (parser, &non_constant_p);
+      parsed_arg
+	= cp_parser_late_parse_one_default_arg (parser, parmdecl,
+						default_arg,
+						TREE_VALUE (parm));
       if (parsed_arg == error_mark_node)
 	{
-	  cp_parser_pop_lexer (parser);
 	  continue;
 	}
-      if (BRACE_ENCLOSED_INITIALIZER_P (parsed_arg))
-	maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
-
-      if (!processing_template_decl)
-	parsed_arg = check_default_argument (TREE_VALUE (parm), parsed_arg);
 
       TREE_PURPOSE (parm) = parsed_arg;
 
@@ -20816,17 +20935,6 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
       for (insts = DEFARG_INSTANTIATIONS (default_arg), ix = 0;
 	   VEC_iterate (tree, insts, ix, copy); ix++)
 	TREE_PURPOSE (copy) = parsed_arg;
-
-      finish_lambda_scope ();
-
-      /* If the token stream has not been completely used up, then
-	 there was extra junk after the end of the default
-	 argument.  */
-      if (!cp_lexer_next_token_is (parser->lexer, CPP_EOF))
-	cp_parser_error (parser, "expected %<,%>");
-
-      /* Revert to the main lexer.  */
-      cp_parser_pop_lexer (parser);
     }
 
   pop_defarg_context ();
diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h
index 33582fb..e08c0b4 100644
--- a/gcc/cp/parser.h
+++ b/gcc/cp/parser.h
@@ -169,6 +169,10 @@ typedef struct GTY(()) cp_unparsed_functions_entry_d {
   /* Functions with defintions that require post-processing.  Functions
      appear in this list in declaration order.  */
   VEC(tree,gc) *funs_with_definitions;
+
+  /* Non-static data members with initializers that require post-processing.
+     FIELD_DECLs appear in this list in declaration order.  */
+  VEC(tree,gc) *nsdmis;
 } cp_unparsed_functions_entry;
 
 DEF_VEC_O(cp_unparsed_functions_entry);
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer1.C
new file mode 100644
index 0000000..b3d9b93
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer1.C
@@ -0,0 +1,14 @@
+// { dg-options -std=c++0x }
+
+#define SA(X) static_assert(X,#X)
+
+struct A
+{
+  int i = f();
+  int j { f() };
+  static constexpr int f() { return 42; }
+};
+
+constexpr A a;
+SA(a.i == 42);
+SA(a.j == 42);
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer2.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer2.C
new file mode 100644
index 0000000..1951262
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer2.C
@@ -0,0 +1,9 @@
+// { dg-options -std=c++0x }
+
+struct A
+{
+  int i = f();
+  static int f(int i = 42) { return i; }
+};
+
+A a;
diff --git a/gcc/testsuite/g++.dg/other/pr39060.C b/gcc/testsuite/g++.dg/other/pr39060.C
index a625aea..e149410 100644
--- a/gcc/testsuite/g++.dg/other/pr39060.C
+++ b/gcc/testsuite/g++.dg/other/pr39060.C
@@ -3,17 +3,17 @@
 
 struct A
 {
-  A(void* i=);	// { dg-error "with|specification" }
-  A(void* i=);	// { dg-error "overloaded" }
-  A(void* i=);	// { dg-error "overloaded" }
+  A(void* i=);	// { dg-error "with|specification|primary-expression" }
+  A(void* i=);	// { dg-error "overloaded|primary-expression" }
+  A(void* i=);	// { dg-error "overloaded|primary-expression" }
 
   void operator+ (void* i=);	// { dg-error "arguments" }
 
-  virtual void foo1(=);	// { dg-error "identifier" }
-  void foo2(=);		// { dg-error "identifier" }
-  void foo3(=);		// { dg-error "identifier" }
-  void foo4(=);		// { dg-error "identifier" }
-  void foo5(=);		// { dg-error "identifier" }
-};	// { dg-error "primary-expression" }
+  virtual void foo1(=);	// { dg-error "identifier|primary-expression" }
+  void foo2(=);		// { dg-error "identifier|primary-expression" }
+  void foo3(=);		// { dg-error "identifier|primary-expression" }
+  void foo4(=);		// { dg-error "identifier|primary-expression" }
+  void foo5(=);		// { dg-error "identifier|primary-expression" }
+};
 
 A::A (void* i=) {}	// { dg-error "primary-expression|argument" }
diff --git a/gcc/testsuite/g++.dg/parse/crash56.C b/gcc/testsuite/g++.dg/parse/crash56.C
index 9a370cb..2b823ae 100644
--- a/gcc/testsuite/g++.dg/parse/crash56.C
+++ b/gcc/testsuite/g++.dg/parse/crash56.C
@@ -5,13 +5,13 @@
 struct A
 {
   typedef void (F)();
-  F f = []{}; /* { dg-error "invalid initializer" } */
+  F f = []{}; /* { dg-error "invalid pure" } */
 };
 
 struct B
 {
   typedef void (F)();
-  F f = 1; /* { dg-error "invalid initializer" } */
-  virtual F f2 = 2; /* { dg-error "invalid initializer" } */
-  F f3 = 3; /* { dg-error "invalid initializer" } */
+  F f = 1; /* { dg-error "invalid pure" } */
+  virtual F f2 = 2; /* { dg-error "invalid pure" } */
+  F f3 = 3; /* { dg-error "invalid pure" } */
 };

commit 10bd74fa7bd2671d9a48aa728691b27b4e2565fa
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Sep 23 12:59:45 2011 -0400

    	* init.c (perform_member_init): Instantiate NSDMI here.
    	* pt.c (tsubst_decl) [FIELD_DECL]: Not here.

diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index f5904d5..f246286 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -496,7 +496,17 @@ perform_member_init (tree member, tree init)
   /* Use the non-static data member initializer if there was no
      mem-initializer for this field.  */
   if (init == NULL_TREE)
-    init = break_out_target_exprs (DECL_INITIAL (member));
+    {
+      if (CLASSTYPE_TEMPLATE_INSTANTIATION (DECL_CONTEXT (member)))
+	/* Do deferred instantiation of the NSDMI.  */
+	init = (tsubst_copy_and_build
+		(DECL_INITIAL (member),
+		 CLASSTYPE_TI_ARGS (DECL_CONTEXT (member)),
+		 tf_warning_or_error, member, /*function_p=*/false,
+		 /*integral_constant_expression_p=*/false));
+      else
+	init = break_out_target_exprs (DECL_INITIAL (member));
+    }
 
   /* Effective C++ rule 12 requires that all data members be
      initialized.  */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index af5ca5c..ebadebf 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -10264,11 +10264,14 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
 	TREE_TYPE (r) = type;
 	cp_apply_type_quals_to_decl (cp_type_quals (type), r);
 
-	/* DECL_INITIAL gives the number of bits in a bit-field.  */
-	DECL_INITIAL (r)
-	  = tsubst_expr (DECL_INITIAL (t), args,
-			 complain, in_decl,
-			 /*integral_constant_expression_p=*/true);
+	if (DECL_C_BIT_FIELD (r))
+	  /* For bit-fields, DECL_INITIAL gives the number of bits.  For
+	     non-bit-fields DECL_INITIAL is a non-static data member
+	     initializer, which gets deferred instantiation.  */
+	  DECL_INITIAL (r)
+	    = tsubst_expr (DECL_INITIAL (t), args,
+			   complain, in_decl,
+			   /*integral_constant_expression_p=*/true);
 	/* We don't have to set DECL_CONTEXT here; it is set by
 	   finish_member_declaration.  */
 	DECL_CHAIN (r) = NULL_TREE;
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer3.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer3.C
new file mode 100644
index 0000000..2777fb5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer3.C
@@ -0,0 +1,19 @@
+// Do NSDMI get deferred instantiation?
+// { dg-options -std=c++0x }
+
+template <class T>
+struct A
+{
+  T t = T(42);
+  constexpr A() { }
+  A(T t): t(t) { }
+};
+
+struct B { };
+
+#define SA(X) static_assert(X,#X)
+
+constexpr A<int> a1;
+SA(a1.t == 42);
+
+A<B> a2 {B()};

commit 6c3a4b9feac862caadd988fab4b54907dfae9ccc
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Sep 15 17:21:34 2011 -0400

    	* except.c (expr_noexcept_p): Split out from finish_noexcept_expr.
    	* cp-tree.h: Declare it.
    	* method.c (walk_field_subobs): Use it.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 2f93bba..0f7deb6 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5047,6 +5047,7 @@ extern tree build_throw				(tree);
 extern int nothrow_libfn_p			(const_tree);
 extern void check_handlers			(tree);
 extern tree finish_noexcept_expr		(tree, tsubst_flags_t);
+extern bool expr_noexcept_p			(tree, tsubst_flags_t);
 extern void perform_deferred_noexcept_checks	(void);
 extern bool nothrow_spec_p			(const_tree);
 extern bool type_noexcept_p			(const_tree);
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index bfc520d..ceec858 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -1125,14 +1125,27 @@ perform_deferred_noexcept_checks (void)
 tree
 finish_noexcept_expr (tree expr, tsubst_flags_t complain)
 {
-  tree fn;
-
   if (expr == error_mark_node)
     return error_mark_node;
 
   if (processing_template_decl)
     return build_min (NOEXCEPT_EXPR, boolean_type_node, expr);
 
+  return (expr_noexcept_p (expr, complain)
+	  ? boolean_true_node : boolean_false_node);
+}
+
+/* Returns whether EXPR is noexcept, possibly warning if allowed by
+   COMPLAIN.  */
+
+bool
+expr_noexcept_p (tree expr, tsubst_flags_t complain)
+{
+  tree fn;
+
+  if (expr == error_mark_node)
+    return false;
+
   fn = cp_walk_tree_without_duplicates (&expr, check_noexcept_r, 0);
   if (fn)
     {
@@ -1151,10 +1164,10 @@ finish_noexcept_expr (tree expr, tsubst_flags_t complain)
 	  else
 	    maybe_noexcept_warning (fn);
 	}
-      return boolean_false_node;
+      return false;
     }
   else
-    return boolean_true_node;
+    return true;
 }
 
 /* Return true iff SPEC is throw() or noexcept(true).  */
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 734c23b..1316dfb 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1042,6 +1042,12 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
 		inform (0, "initializer for %q+#D is invalid", field);
 	      if (trivial_p)
 		*trivial_p = false;
+	      /* Core 1351: If the field has an NSDMI that could throw, the
+		 default constructor is noexcept(false).  FIXME this is
+	         broken by deferred parsing and 1360 saying we can't
+		 lazily declare a non-trivial default constructor.  */
+	      if (spec_p && !expr_noexcept_p (DECL_INITIAL (field), complain))
+		*spec_p = noexcept_false_spec;
 
 	      /* Don't do the normal processing.  */
 	      continue;
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-eh1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-eh1.C
new file mode 100644
index 0000000..09c92d2f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-eh1.C
@@ -0,0 +1,18 @@
+// Core issue 1351
+// { dg-do run { xfail *-*-* } }
+// { dg-options -std=c++0x }
+
+bool fail;
+struct A
+{
+  int i = fail ? throw "noooooooo" : 42;
+};
+
+int main()
+{
+  A a1;
+  if (a1.i != 42) return 1;
+  fail = true;
+  try { A a2; }
+  catch (...) { }
+}
