In extract_autos_r, we need to recompute TYPE_CANONICAL for the template
type parameter after adjusting its index, otherwise we end up with a
comptypes ICE for the below testcase. Note that such in-place type
adjustment isn't generally safe to do since the type could be the
TYPE_CANONICAL of another (unadjusted) type, but in this case the
canonical auto (of some level and 0 index) is the first auto (of that
level) that's created, and so any auto that we do end up adjusting can't
be the canonical one.
PR c++/101886
gcc/cp/ChangeLog:
* pt.cc (extract_autos_r): Recompute TYPE_CANONICAL after
adjusting the template type parameter's index. Simplify
by using TEMPLATE_TYPE_IDX. Add some sanity checks.
gcc/testsuite/ChangeLog:
* g++.dg/concepts/auto5.C: New test.
{
/* All the autos were built with index 0; fix that up now. */
tree *p = hash.find_slot (t, INSERT);
{
/* All the autos were built with index 0; fix that up now. */
tree *p = hash.find_slot (t, INSERT);
if (*p)
/* If this is a repeated constrained-type-specifier, use the index we
chose before. */
if (*p)
/* If this is a repeated constrained-type-specifier, use the index we
chose before. */
- idx = TEMPLATE_PARM_IDX (TEMPLATE_TYPE_PARM_INDEX (*p));
+ idx = TEMPLATE_TYPE_IDX (*p);
else
{
/* Otherwise this is new, so use the current count. */
*p = t;
idx = hash.elements () - 1;
}
else
{
/* Otherwise this is new, so use the current count. */
*p = t;
idx = hash.elements () - 1;
}
- TEMPLATE_PARM_IDX (TEMPLATE_TYPE_PARM_INDEX (t)) = idx;
+ if (idx != TEMPLATE_TYPE_IDX (t))
+ {
+ gcc_checking_assert (TEMPLATE_TYPE_IDX (t) == 0);
+ gcc_checking_assert (TYPE_CANONICAL (t) != t);
+ TEMPLATE_TYPE_IDX (t) = idx;
+ TYPE_CANONICAL (t) = canonical_type_parameter (t);
+ }
}
/* Always keep walking. */
}
/* Always keep walking. */
--- /dev/null
+// PR c++/101886
+// { dg-do compile { target c++17_only } }
+// { dg-options "-fconcepts-ts" }
+
+template<typename...> struct A { };
+
+A<int, int> a;
+A<auto, auto> b1 = a;
+A<auto, auto> b2 = a;