diff mbox

[C++/58583] ICE instantiating NSDMIs

Message ID 557384CB.1020301@acm.org
State New
Headers show

Commit Message

Nathan Sidwell June 6, 2015, 11:39 p.m. UTC
This patch fixes 58582, a set of ICEs that happen instantiating NSDMIs.  There 
are a couple of causes, both fixed.

1) instantiating the  template while parsing an NSDMI of the template itself. 
We see a DEFAULT_ARG in get_nsdmi.  Fixed  by jumping to the existing error 
handling for the  non-template case.

2) recursive instantiation of the NSDMI itself.  As we instantiate lazily, we 
end up running out of stack.  Fixed by creating a temporary DEFAULT_ARG and then 
detecting it on a subsequent recursion.  I did contemplate having this direct to 
the same error as above, but decided against it, because this really is an 
instantiation problem not a parsing problem.

built & tested on x86_64-linux, ok?

nathan

Comments

Jason Merrill June 8, 2015, 5:47 p.m. UTC | #1
How about using a DECL_LANG_FLAG instead of creating a garbage DEFAULT_ARG?

Jason
Nathan Sidwell June 8, 2015, 7:49 p.m. UTC | #2
On 06/08/15 13:47, Jason Merrill wrote:
> How about using a DECL_LANG_FLAG instead of creating a garbage DEFAULT_ARG?

good idea, I'll go look for an available one.

nathan
diff mbox

Patch

2015-06-05  Nathan Sidwell  <nathan@acm.org>

	cp/
	PR c++/58583
	* init.c (get_nsdmi): Check for DEFAULT_ARG in template case and
	protect it from recursive instantiation.

	testsuite/
	PR c++/58583
	* g++.dg/cpp0x/nsdmi-template14.C: New test.

Index: cp/init.c
===================================================================
--- cp/init.c	(revision 224152)
+++ cp/init.c	(working copy)
@@ -544,6 +544,7 @@  get_nsdmi (tree member, bool in_ctor)
   tree init;
   tree save_ccp = current_class_ptr;
   tree save_ccr = current_class_ref;
+  
   if (!in_ctor)
     {
       /* Use a PLACEHOLDER_EXPR when we don't have a 'this' parameter to
@@ -551,22 +552,41 @@  get_nsdmi (tree member, bool in_ctor)
       current_class_ref = build0 (PLACEHOLDER_EXPR, DECL_CONTEXT (member));
       current_class_ptr = build_address (current_class_ref);
     }
+
   if (DECL_LANG_SPECIFIC (member) && DECL_TEMPLATE_INFO (member))
     {
-      /* Do deferred instantiation of the NSDMI.  */
-      init = (tsubst_copy_and_build
-	      (DECL_INITIAL (DECL_TI_TEMPLATE (member)),
-	       DECL_TI_ARGS (member),
-	       tf_warning_or_error, member, /*function_p=*/false,
-	       /*integral_constant_expression_p=*/false));
+      init = DECL_INITIAL (DECL_TI_TEMPLATE (member));
+      if (TREE_CODE (init) == DEFAULT_ARG)
+	goto unparsed;
 
-      init = digest_nsdmi_init (member, init);
+      /* Check recursive instantiation.  */
+      if (TREE_CODE (DECL_INITIAL (member)) == DEFAULT_ARG)
+	{
+	  error ("recursive instantiation of non-static data member "
+		 "initializer for %qD", member);
+	  init = error_mark_node;
+	}
+      else
+	{
+	  DECL_INITIAL (member) = make_node (DEFAULT_ARG);
+	  
+	  /* Do deferred instantiation of the NSDMI.  */
+	  init = (tsubst_copy_and_build
+		  (init, DECL_TI_ARGS (member),
+		   tf_warning_or_error, member, /*function_p=*/false,
+		   /*integral_constant_expression_p=*/false));
+	  init = digest_nsdmi_init (member, init);
+	  
+	  if (TREE_CODE (DECL_INITIAL (member)) == DEFAULT_ARG)
+	    DECL_INITIAL (member) = void_node;
+	}
     }
   else
     {
       init = DECL_INITIAL (member);
       if (init && TREE_CODE (init) == DEFAULT_ARG)
 	{
+	unparsed:
 	  error ("constructor required before non-static data member "
 		 "for %qD has been parsed", member);
 	  DECL_INITIAL (member) = error_mark_node;
Index: testsuite/g++.dg/cpp0x/nsdmi-template14.C
===================================================================
--- testsuite/g++.dg/cpp0x/nsdmi-template14.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/nsdmi-template14.C	(working copy)
@@ -0,0 +1,23 @@ 
+// PR c++/58583
+// { dg-do compile { target c++11 } }
+
+template<int> struct A // {dg-error "non-static data member initializer" }
+{
+  int i = (A<0>(), 0); // { dg-error "non-static data member initializer required before parsing" }  { dg-error "synthesized method" }
+};
+
+template<int N> struct B
+{
+  B* p = new B<N>;
+};
+
+B<1> x; // { dg-error "constructor required before non-static data member" }
+
+struct C
+{
+  template<int N> struct D
+  {
+    D* p = new D<0>;
+  };
+};
+