[PATCH] c++: constraint rewriting during ttp coercion [PR111485]

Jason Merrill jason@redhat.com
Wed Sep 20 20:49:10 GMT 2023


On 9/20/23 13:10, Patrick Palka wrote:
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk and perhaps backports?

OK for trunk and 13.

> -- >8 --
> 
> In order to compare the constraints of a ttp with that of its argument,
> we rewrite the ttp's constraints in terms of the argument template's
> template parameters.  The substitution to achieve this currently uses a
> single level of template arguments, but that never does the right thing
> because a ttp's template parameters always have level >= 2.  This patch
> fixes this by including the outer template arguments in this substitution,
> which ought to match the depth of the ttp.
> 
> The second testcase demonstrates that it's sometimes necessary to
> substitute the concrete outer template arguments instead of generic
> ones, because a ttp's constraints could depend on outer arguments.
> 
> 	PR c++/111485
> 
> gcc/cp/ChangeLog:
> 
> 	* pt.cc (is_compatible_template_arg): New parameter 'args'.
> 	Add the outer template arguments 'args' to 'new_args'.
> 	(convert_template_argument): Pass 'args' to
> 	is_compatible_template_arg.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/cpp2a/concepts-ttp5.C: New test.
> 	* g++.dg/cpp2a/concepts-ttp6.C: New test.
> ---
>   gcc/cp/pt.cc                               |  5 +++--
>   gcc/testsuite/g++.dg/cpp2a/concepts-ttp5.C | 24 ++++++++++++++++++++++
>   gcc/testsuite/g++.dg/cpp2a/concepts-ttp6.C | 17 +++++++++++++++
>   3 files changed, 44 insertions(+), 2 deletions(-)
>   create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-ttp5.C
>   create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-ttp6.C
> 
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index 8758e218ce4..f47887291a6 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -8360,7 +8360,7 @@ canonicalize_expr_argument (tree arg, tsubst_flags_t complain)
>      constrained than the parameter.  */
>   
>   static bool
> -is_compatible_template_arg (tree parm, tree arg)
> +is_compatible_template_arg (tree parm, tree arg, tree args)
>   {
>     tree parm_cons = get_constraints (parm);
>   
> @@ -8381,6 +8381,7 @@ is_compatible_template_arg (tree parm, tree arg)
>       {
>         tree aparms = DECL_INNERMOST_TEMPLATE_PARMS (arg);
>         new_args = template_parms_level_to_args (aparms);
> +      new_args = add_to_template_args (args, new_args);
>         ++processing_template_decl;
>         parm_cons = tsubst_constraint_info (parm_cons, new_args,
>   					  tf_none, NULL_TREE);
> @@ -8635,7 +8636,7 @@ convert_template_argument (tree parm,
>                 // Check that the constraints are compatible before allowing the
>                 // substitution.
>                 if (val != error_mark_node)
> -                if (!is_compatible_template_arg (parm, arg))
> +		if (!is_compatible_template_arg (parm, arg, args))
>                     {
>   		    if (in_decl && (complain & tf_error))
>                         {
> diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-ttp5.C b/gcc/testsuite/g++.dg/cpp2a/concepts-ttp5.C
> new file mode 100644
> index 00000000000..4129e9e1303
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-ttp5.C
> @@ -0,0 +1,24 @@
> +// PR c++/111485
> +// { dg-do compile { target c++20 } }
> +
> +template<class T> constexpr bool always_true = true;
> +
> +template<class T> concept C = always_true<T>;
> +template<class T> concept D = C<T> || true;
> +
> +template<template<C> class TT> struct example { };
> +template<template<D> class UU> using example_t = example<UU>;
> +
> +template<class T>
> +struct A {
> +  template<template<C> class TT> struct example { };
> +
> +  template<template<D> class UU> using example_t = example<UU>;
> +
> +  template<class U>
> +  struct B {
> +    template<template<D> class UU> using example_t = example<UU>;
> +  };
> +};
> +
> +template struct A<int>::B<int>;
> diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-ttp6.C b/gcc/testsuite/g++.dg/cpp2a/concepts-ttp6.C
> new file mode 100644
> index 00000000000..7832cabc7d8
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-ttp6.C
> @@ -0,0 +1,17 @@
> +// PR c++/111485
> +// { dg-do compile { target c++20 } }
> +
> +template<class T, bool V> constexpr bool always_true = true;
> +
> +template<class T, bool V> concept C = always_true<T, V>;
> +
> +template<bool V, template<class T> requires C<T, V> class TT>
> +void f();
> +
> +template<class T> requires C<T, true>
> +struct A;
> +
> +int main() {
> +  f<true, A>();
> +  f<false, A>(); // { dg-error "no match|constraint" }
> +}



More information about the Gcc-patches mailing list