2017-01-11  Nathan Sidwell  <nathan@acm.org>

	PR c++/78771
	* pt.c (instantiate_template_1): Check for recursive instantiation
	of inheriting constructor when not new-inheriting-ctor.
	* method.c (deduce_inheriting_ctor): Use originating ctor when
	new-inheriting-ctor.

	PR c++/78771
	* g++.dg/cpp0x/pr78771-old.C: New.
	* g++.dg/cpp0x/pr78771-new.C: New.
	* g++.dg/cpp1z/pr78771.C: New.

Index: cp/method.c
===================================================================
--- cp/method.c	(revision 244314)
+++ cp/method.c	(working copy)
@@ -1858,11 +1858,15 @@ deduce_inheriting_ctor (tree decl)
   gcc_assert (DECL_INHERITED_CTOR (decl));
   tree spec;
   bool trivial, constexpr_, deleted;
+
+  tree inherited = DECL_INHERITED_CTOR (decl);
+  if (flag_new_inheriting_ctors)
+    inherited = strip_inheriting_ctors (inherited);
+
   synthesized_method_walk (DECL_CONTEXT (decl), sfk_inheriting_constructor,
 			   false, &spec, &trivial, &deleted, &constexpr_,
-			   /*diag*/false,
-			   DECL_INHERITED_CTOR (decl),
-			   FUNCTION_FIRST_USER_PARMTYPE (decl));
+			   /*diag=*/false,
+			   inherited, FUNCTION_FIRST_USER_PARMTYPE (decl));
   if (TREE_CODE (inherited_ctor_binfo (decl)) != TREE_BINFO)
     /* Inherited the same constructor from different base subobjects.  */
     deleted = true;
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 244314)
+++ cp/pt.c	(working copy)
@@ -17963,10 +17963,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 (!flag_new_inheriting_ctors
+		      && 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-new.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr78771-new.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/pr78771-new.C	(working copy)
@@ -0,0 +1,28 @@
+// PR c++/78771
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-fnew-inheriting-ctors" }
+
+// 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: testsuite/g++.dg/cpp0x/pr78771-old.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr78771-old.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/pr78771-old.C	(working copy)
@@ -0,0 +1,28 @@
+// PR c++/78771
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-fno-new-inheriting-ctors" }
+
+// 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: testsuite/g++.dg/cpp1z/pr78771.C
===================================================================
--- testsuite/g++.dg/cpp1z/pr78771.C	(revision 0)
+++ testsuite/g++.dg/cpp1z/pr78771.C	(working copy)
@@ -0,0 +1,27 @@
+// PR c++/78771
+// { dg-options -std=c++1z }
+
+// 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) {}
