This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] c++/78771 ICE with inheriting ctor


Jason,
this patch fixes 78771, were an assert fires due to recursive instantiation of an inheriting ctor. Normally when a recursive instantiation is needed, we've already constructed and registered the declaration, so simply return it. For ctors though we need to construct the clones after we've instantiated the the master pattern (later in instantiate_template_1). Hence any recursive instantiation of a cloned fn will barf, as we do.

Now, with an inherited ctor we have to deduce its exception spec and deletedness (deduce_inheriting_ctor). That's fine, until one gets the perverse testcase here. In figuring out what Middle ctor is needed by Middle(0), we end up trying to instantiate Derived::Derived (int) to see if Middle::Middle (Derived) is a viable candidate. And that's the recursion, as Derived::Derived inherits from Middle::Middle.

Fixed by checking if the cloned instantiations actually exist before looking for them. I think the only case this can occur is when SPEC is an inherited ctor, hence the assert. Also, I don't think this can get us the wrong exept spec and deletedness -- it will be other (member) ctors that could change it, and we reconstruct the clones later anyway in the usual path.

(I tried creating the clones earlier, immediately after construction and registering the main function, but that didn't work)

ok?

nathan
--
Nathan Sidwell
2016-12-19  Nathan Sidwell  <nathan@acm.org>

	PR c++/78771
	* pt.c (instantiate_template_1): Check for recursive instantiation
	of inheriting constructor.

	PR c++/78771
	* g++.dg/cpp0x/pr78771.C: New.

Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 243746)
+++ cp/pt.c	(working copy)
@@ -17717,10 +17717,22 @@ instantiate_template_1 (tree tmpl, tree
       if (spec == error_mark_node)
 	return error_mark_node;
 
+      /* If this is an inherited ctor, we can recursively clone it
+	 when deducing the validity of the ctor.  But we won't have
+	 cloned the function yet, so do it now.  We'll redo this
+	 later, but any recursive information learnt here can't
+	 change the validity.  */
+      if (!TREE_CHAIN (spec))
+	{
+	  gcc_assert (DECL_INHERITED_CTOR (spec));
+	  clone_function_decl (spec, /*update_method_vec_p=*/0);
+	}
+
       /* Look for the clone.  */
       FOR_EACH_CLONE (clone, spec)
 	if (DECL_NAME (clone) == DECL_NAME (tmpl))
 	  return clone;
+
       /* We should always have found the clone by now.  */
       gcc_unreachable ();
       return NULL_TREE;
Index: testsuite/g++.dg/cpp0x/pr78771.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr78771.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/pr78771.C	(working copy)
@@ -0,0 +1,27 @@
+// PR c++/78771
+// { dg-do compile { target c++11 } }
+
+// ICE instantiating a deleted inherited ctor
+
+struct Base
+{
+  template <typename U> Base (U);
+
+  Base (int);
+};
+
+struct Derived;
+
+struct Middle : Base
+{
+  using Base::Base;
+
+  Middle (Derived);
+};
+
+struct Derived : Middle
+{
+  using Middle::Middle;
+};
+
+Middle::Middle (Derived) : Middle (0) {}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]