This crash was caused by unexpectedly seeing a USING_DECL. Normally we want to make dependent using-decls visible to name lookup, so we know to defer things to instantiation time. But here we're (a) explicitly looking inside uninstantiated templates and (b) want to know the ctors the template definitely has. so we should ignore the dependent inherited ctor.

Before my name reworking, the lookup during the deduction guide generation never saw the using decl, as it never made it into the special CONSTRUCTOR_SLOT.

nathan
--
Nathan Sidwell
2018-03-01  Nathan Sidwell  <nat...@acm.org>

	PR c++/84434
	* name-lookup.c (member_vec_dedup): Remove manually peeled
	iteration.  Ignore dependent ctor inheritance.

	PR c++/84434
	* g++.dg/template/pr84434.C: New.

Index: cp/name-lookup.c
===================================================================
--- cp/name-lookup.c	(revision 258100)
+++ cp/name-lookup.c	(working copy)
@@ -1591,68 +1591,58 @@ member_vec_dedup (vec<tree, va_gc> *memb
   if (!len)
     return;
 
-  tree current = (*member_vec)[0], name = OVL_NAME (current);
-  tree next = NULL_TREE, next_name = NULL_TREE;
-  for (unsigned jx, ix = 0; ix < len;
-       ix = jx, current = next, name = next_name)
+  tree name = OVL_NAME ((*member_vec)[0]);
+  for (unsigned jx, ix = 0; ix < len; ix = jx)
     {
+      tree current = NULL_TREE;
       tree to_type = NULL_TREE;
       tree to_using = NULL_TREE;
       tree marker = NULL_TREE;
-      if (IDENTIFIER_CONV_OP_P (name))
-	{
-	  marker = current;
-	  current = OVL_CHAIN (current);
-	  name = DECL_NAME (OVL_FUNCTION (marker));
-	  gcc_checking_assert (name == conv_op_identifier);
-	}
 
-      if (TREE_CODE (current) == USING_DECL)
+      for (jx = ix; jx < len; jx++)
 	{
-	  current = strip_using_decl (current);
-	  if (is_overloaded_fn (current))
-	    current = NULL_TREE;
-	  else if (TREE_CODE (current) == USING_DECL)
+	  tree next = (*member_vec)[jx];
+	  if (jx != ix)
 	    {
-	      to_using = current;
-	      current = NULL_TREE;
+	      tree next_name = OVL_NAME (next);
+	      if (next_name != name)
+		{
+		  name = next_name;
+		  break;
+		}
 	    }
-	}
 
-      if (current && DECL_DECLARES_TYPE_P (current))
-	{
-	  to_type = current;
-	  current = NULL_TREE;
-	}
-
-      for (jx = ix + 1; jx < len; jx++)
-	{
-	  next = (*member_vec)[jx];
-	  next_name = OVL_NAME (next);
-	  if (next_name != name)
-	    break;
-
-	  if (marker)
+	  if (IDENTIFIER_CONV_OP_P (name))
 	    {
-	      gcc_checking_assert (OVL_FUNCTION (marker)
-				   == OVL_FUNCTION (next));
+	      marker = next;
 	      next = OVL_CHAIN (next);
 	    }
 
 	  if (TREE_CODE (next) == USING_DECL)
 	    {
+	      if (IDENTIFIER_CTOR_P (name))
+		/* Dependent inherited ctor. */
+		continue;
+
 	      next = strip_using_decl (next);
-	      if (is_overloaded_fn (next))
-		next = NULL_TREE;
-	      else if (TREE_CODE (next) == USING_DECL)
+	      if (TREE_CODE (next) == USING_DECL)
 		{
 		  to_using = next;
-		  next = NULL_TREE;
+		  continue;
 		}
+
+	      if (is_overloaded_fn (next))
+		continue;
 	    }
 
-	  if (next && DECL_DECLARES_TYPE_P (next))
-	    to_type = next;
+	  if (DECL_DECLARES_TYPE_P (next))
+	    {
+	      to_type = next;
+	      continue;
+	    }
+
+	  if (!current)
+	    current = next;
 	}
 
       if (to_using)
@@ -1671,13 +1661,15 @@ member_vec_dedup (vec<tree, va_gc> *memb
 	    current = stat_hack (current, to_type);
 	}
 
-      gcc_assert (current);
-      if (marker)
+      if (current)
 	{
-	  OVL_CHAIN (marker) = current;
-	  current = marker;
+	  if (marker)
+	    {
+	      OVL_CHAIN (marker) = current;
+	      current = marker;
+	    }
+	  (*member_vec)[store++] = current;
 	}
-      (*member_vec)[store++] = current;
     }
 
   while (store++ < len)
Index: testsuite/g++.dg/template/pr84434.C
===================================================================
--- testsuite/g++.dg/template/pr84434.C	(revision 0)
+++ testsuite/g++.dg/template/pr84434.C	(working copy)
@@ -0,0 +1,23 @@
+// PR c++/84434 ICE with deduction guide and dependent using decl
+// { dg-do compile { target c++17 } }
+
+template <typename T> class B {
+public:
+  template <typename U> B (U)  {}
+};
+
+template <typename T>
+struct scope_guard : B<T> {
+  using base_type = B<T>;
+
+  using base_type::base_type;
+
+   ~scope_guard() = default;
+};
+
+template <typename T>
+scope_guard (T) -> scope_guard<T>;
+
+void Frob () {
+  scope_guard (1);
+}

Reply via email to