[C++] Fix interaction between aka changes and DR1558 (PR92206)

Richard Sandiford Richard.Sandiford@arm.com
Tue Nov 5 16:45:00 GMT 2019


Ping

Richard Sandiford <richard.sandiford@arm.com> writes:
> 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?
>
> Richard
>
>
> 2019-10-25  Richard Sandiford  <richard.sandiford@arm.com>
>
> gcc/cp/
> 	PR c++/92206
> 	* cp-tree.h (STF_ASSUME_VALID): New constant.
> 	* 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.
>
> Index: gcc/cp/cp-tree.h
> ===================================================================
> --- gcc/cp/cp-tree.h	2019-10-25 09:21:28.098331304 +0100
> +++ gcc/cp/cp-tree.h	2019-10-25 14:51:22.618009886 +0100
> @@ -5728,8 +5728,12 @@ #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_ASSUME_VALID: assume where possible that the given type is valid,
> +       relying on code elsewhere to report any appropriate diagnostics.  */
>  const unsigned int STF_USER_VISIBLE = 1U;
> +const unsigned int STF_ASSUME_VALID = 1U << 1;
>  
>  /* Returns the TEMPLATE_DECL associated to a TEMPLATE_TEMPLATE_PARM
>     node.  */
> Index: gcc/cp/tree.c
> ===================================================================
> --- gcc/cp/tree.c	2019-10-22 08:47:01.255327861 +0100
> +++ gcc/cp/tree.c	2019-10-25 14:51:22.618009886 +0100
> @@ -1489,7 +1489,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_ASSUME_VALID)
> +      && 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;
> @@ -1674,7 +1675,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_ASSUME_VALID);
>  	}
>        else
>  	result = TYPE_MAIN_VARIANT (t);
> Index: gcc/testsuite/g++.dg/pr92206-1.C
> ===================================================================
> --- /dev/null	2019-09-17 11:41:18.176664108 +0100
> +++ gcc/testsuite/g++.dg/pr92206-1.C	2019-10-25 14:51:22.618009886 +0100
> @@ -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/pr92206-2.C
> ===================================================================
> --- /dev/null	2019-09-17 11:41:18.176664108 +0100
> +++ gcc/testsuite/g++.dg/pr92206-2.C	2019-10-25 14:51:22.618009886 +0100
> @@ -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/pr92206-3.C
> ===================================================================
> --- /dev/null	2019-09-17 11:41:18.176664108 +0100
> +++ gcc/testsuite/g++.dg/pr92206-3.C	2019-10-25 14:51:22.618009886 +0100
> @@ -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;



More information about the Gcc-patches mailing list