This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] c++/78771 ICE with inheriting ctor
- From: Nathan Sidwell <nathan at acm dot org>
- To: Jason Merrill <jason at redhat dot com>
- Cc: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 19 Dec 2016 08:09:22 -0500
- Subject: [PATCH] c++/78771 ICE with inheriting ctor
- Authentication-results: sourceware.org; auth=none
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) {}