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);
+}