Jason Merrill <ja...@redhat.com> writes: > On 10/25/19 2:53 PM, Richard Sandiford wrote: >> One of the changes in r277281 was to make the typedef variant >> handling in strip_typedefs pass the raw DECL_ORIGINAL_TYPE to the >> recursive call, instead of applying TYPE_MAIN_VARIANT first. >> This PR shows that that interacts badly with the implementation >> of DR1558, because we then refuse to strip aliases with dependent >> template parameters and trip: >> >> gcc_assert (!typedef_variant_p (result) >> || ((flags & STF_USER_VISIBLE) >> && !user_facing_original_type_p (result))); >> >> Keeping the current behaviour but suppressing the ICE leads to a >> duplicate error (the dg-bogus in the first test), so that didn't >> seem like a good fix. >> >> I assume keeping the alias should never actually be necessary for >> DECL_ORIGINAL_TYPEs, because it will already have been checked >> somewhere, even for implicit TYPE_DECLs. This patch therefore >> passes a flag to say that we can assume the type is validated >> elsewhere. >> >> It seems a rather clunky fix, sorry, but restoring the >> TYPE_MAIN_VARIANT (...) isn't compatible with the aka stuff. >> >> Bootstrapped & regression-tested on aarch64-linux-gnu. OK to install? > >> 2019-10-25 Richard Sandiford <richard.sandif...@arm.com> >> >> gcc/cp/ >> PR c++/92206 >> * cp-tree.h (STF_ASSUME_VALID): New constant. > > Let's call this STF_STRIP_DEPENDENT. > >> * tree.c (strip_typedefs): Add STF_ASSUME_VALID to the flags >> when calling strip_typedefs recursively on a DECL_ORIGINAL_TYPE. >> Don't apply the fix for DR1558 in that case; allow aliases with >> dependent template parameters to be stripped instead. >> >> gcc/testsuite/ >> PR c++/92206 >> * g++.dg/pr92206-1.C: New test. >> * g++.dg/pr92206-2.C: Likewise. >> * g++.dg/pr92206-3.C: Likewise. > > Let's call these g++.dg/cpp0x/alias-decl-pr92206*. > > OK with those changes.
Thanks. For the record, here's what I committed after retesting as above. Richard 2019-11-13 Richard Sandiford <richard.sandif...@arm.com> gcc/cp/ PR c++/92206 * cp-tree.h (STF_STRIP_DEPENDENT): New constant. * tree.c (strip_typedefs): Add STF_STRIP_DEPENDENT to the flags when calling strip_typedefs recursively on a DECL_ORIGINAL_TYPE. Don't apply the fix for DR1558 in that case; allow aliases with dependent template parameters to be stripped instead. gcc/testsuite/ PR c++/92206 * g++.dg/cpp0x/alias-decl-pr92206-1.C: New test. * g++.dg/cpp0x/alias-decl-pr92206-2.C: Likewise. * g++.dg/cpp0x/alias-decl-pr92206-3.C: Likewise. Index: gcc/cp/cp-tree.h =================================================================== --- gcc/cp/cp-tree.h 2019-11-13 08:40:56.000000000 +0000 +++ gcc/cp/cp-tree.h 2019-11-13 08:41:13.222023539 +0000 @@ -5759,8 +5759,13 @@ #define TFF_POINTER (1 STF_USER_VISIBLE: use heuristics to try to avoid stripping user-facing aliases of internal details. This is intended for diagnostics, - where it should (for example) give more useful "aka" types. */ + where it should (for example) give more useful "aka" types. + + STF_STRIP_DEPENDENT: allow the stripping of aliases with dependent + template parameters, relying on code elsewhere to report any + appropriate diagnostics. */ const unsigned int STF_USER_VISIBLE = 1U; +const unsigned int STF_STRIP_DEPENDENT = 1U << 1; /* Returns the TEMPLATE_DECL associated to a TEMPLATE_TEMPLATE_PARM node. */ Index: gcc/cp/tree.c =================================================================== --- gcc/cp/tree.c 2019-11-13 08:40:56.000000000 +0000 +++ gcc/cp/tree.c 2019-11-13 08:41:13.222023539 +0000 @@ -1488,7 +1488,8 @@ strip_typedefs (tree t, bool *remove_att if (t == TYPE_CANONICAL (t)) return t; - if (dependent_alias_template_spec_p (t)) + if (!(flags & STF_STRIP_DEPENDENT) + && dependent_alias_template_spec_p (t)) /* DR 1558: However, if the template-id is dependent, subsequent template argument substitution still applies to the template-id. */ return t; @@ -1673,7 +1674,8 @@ strip_typedefs (tree t, bool *remove_att && !user_facing_original_type_p (t)) return t; result = strip_typedefs (DECL_ORIGINAL_TYPE (TYPE_NAME (t)), - remove_attributes, flags); + remove_attributes, + flags | STF_STRIP_DEPENDENT); } else result = TYPE_MAIN_VARIANT (t); Index: gcc/testsuite/g++.dg/cpp0x/alias-decl-pr92206-1.C =================================================================== --- /dev/null 2019-09-17 11:41:18.176664108 +0100 +++ gcc/testsuite/g++.dg/cpp0x/alias-decl-pr92206-1.C 2019-11-13 08:41:13.226023511 +0000 @@ -0,0 +1,9 @@ +// { dg-require-effective-target c++11 } + +template<typename> struct A {}; +template<typename T1, typename T2 = typename T1::value> using alias1 = A<T1>; +template<typename T> class B { + using alias2 = alias1<A<T>>; // { dg-error {no type named 'value'} } + A<alias2> a; // { dg-bogus {no type named 'value'} } +}; +B<int> b; Index: gcc/testsuite/g++.dg/cpp0x/alias-decl-pr92206-2.C =================================================================== --- /dev/null 2019-09-17 11:41:18.176664108 +0100 +++ gcc/testsuite/g++.dg/cpp0x/alias-decl-pr92206-2.C 2019-11-13 08:41:13.226023511 +0000 @@ -0,0 +1,14 @@ +// { dg-require-effective-target c++11 } + +template <bool> struct A; +class Vector { + template <typename> struct TypeIsGCThing { + template <typename T, typename A<T ::value>::Type> using Vector = Vector; + struct B; + template <typename> class ContainerIter { + using Action = B; + using ActionVector = Vector<Action, 0>; + ContainerIter<ActionVector> a; + }; + }; +}; Index: gcc/testsuite/g++.dg/cpp0x/alias-decl-pr92206-3.C =================================================================== --- /dev/null 2019-09-17 11:41:18.176664108 +0100 +++ gcc/testsuite/g++.dg/cpp0x/alias-decl-pr92206-3.C 2019-11-13 08:41:13.226023511 +0000 @@ -0,0 +1,8 @@ +// { dg-require-effective-target c++11 } + +template <typename> void a(); +template <typename> struct b; +template <bool> using c = int; +template <typename d, typename e = decltype(a<d>)> using f = e; +template <typename e> using g = f<e>; +template <typename h> c<b<g<h>>::i> j;