On Wed, 9 Apr 2025, Patrick Palka wrote:
> On Wed, 5 Mar 2025, Jason Merrill wrote:
>
> > On 3/5/25 10:13 AM, Patrick Palka wrote:
> > > On Tue, 4 Mar 2025, Jason Merrill wrote:
> > >
> > > > On 3/4/25 2:49 PM, Patrick Palka wrote:
> > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK
> > > > > for trunk/14?
> > > > >
> > > > > -- >8 --
> > > > >
> > > > > In the three-parameter version of satisfy_declaration_constraints,
> > > > > when
> > > > > 't' isn't the most general template, then 't' won't correspond with
> > > > > 'args' after we augment the latter via add_outermost_template_args,
> > > > > and
> > > > > so the instantiation context that we push via push_tinst_level isn't
> > > > > quite correct: 'args' is a complete set of template arguments, but 't'
> > > > > is not necessarily the most general template. This manifests as
> > > > > misleading diagnostic context lines when issuing a hard error (or a
> > > > > constraint recursion error) that occurred during satisfaction, e.g.
> > > > > for
> > > > > the below testcase without this patch we emit:
> > > > > In substitution of '... void A<int>::f<U>() [with U = int]'
> > > > > and with this patch we emit:
> > > > > In substitution of '... void A<T>::f<U>() [with U = char; T =
> > > > > int]'.
> > > > >
> > > > > This patch fixes this by always passing the most general template to
> > > > > push_tinst_level.
> > > >
> > > > That soungs good, but getting it by passing it back from
> > > > get_normalized_constraints_from_decl seems confusing; I'd think we
> > > > should
> > > > calculate it in parallel to changing args to correspond to that
> > > > template.
> > >
> > > Hmm, won't that mean duplicating the template adjustment logic in
> > > get_normalized_constraints_from_decl, which seems undesirable? The
> > > function has many callers, some of which are for satisfaction where
> > > targs are involved, and the rest are for subsumption where no targs are
> > > involved, so I don't see a clean way of refactoring the code to avoid
> > > duplication of the template adjustment logic. Right now the targ
> > > adjustment logic is unfortunately duplicated across both overloads
> > > of satisfy_declaration_constraints and it seems undesirable to add
> > > more duplication.
> >
> > Fair enough. Incidentally, I wonder why the two-parm overload doesn't call
> > the three-parm overload?
> >
> > > Maybe one way to reduce the duplication would be to go the other way and
> > > move the targ adjustment logic to get_normalized_constraints_from_decl
> > > as well (so that it has two out-parameters, 'gen_d' and 'gen_args').
> > > The proposed patch then would be an incremental step towards that.
> >
> > That makes sense, passing back something suitable for
> > add_outermost_template_args.
>
> I tried combining the two overloads, and/or moving the targ adjustment
> logic to get_normalized_constraints_from_decl, but I couldn't arrive at
> a formulation that worked and I was happy with (i.e. didn't lead to more
> code duplication than the original appproach).
>
> In the meantime I noticed that this bug is more pervasive than I
> thought, and leads to wrong diagnostic context lines printed even in the
> case of ordinary satisfaction failure -- however the wrong diagnostic
> lines are more annoying/noticable during a hard error or constraint
> recursion where there's likely no other useful diagnostic lines that
> might have the correct args printed.
>
> So I adjusted the testcase in the original patch accordingly. Could the
> following go in for now?
>
> I also attached a diff of the output of all our concepts testcases
> currently, before/after this patch. Each change seems like a clear
> improvement/correction to me.
Oops, that was not a complete diff of all the concepts tests, here is a
more complete one.
>
> -- >8 --
>
> Subject: [PATCH] c++: wrong targs in satisfaction diagnostic context line
> [PR99214]
>
> In the three-parameter version of satisfy_declaration_constraints, when
> 't' isn't the most general template, then 't' won't correspond with
> 'args' after we augment the latter via add_outermost_template_args, and
> so the instantiation context that we push via push_tinst_level isn't
> quite correct: 'args' is a complete set of template arguments, but 't'
> is not necessarily the most general template. This manifests as
> misleading diagnostic context lines when issuing a satisfaction failure
> error, e.g. the below testcase without this patch we emit:
> In substitution of '... void A<int>::f<U>() [with U = int]'
> and with this patch we emit:
> In substitution of '... void A<T>::f<U>() [with U = char; T = int]'.
>
> This patch fixes this by always passing the most general template to
> push_tinst_level.
>
> PR c++/99214
>
> gcc/cp/ChangeLog:
>
> * constraint.cc (get_normalized_constraints_from_decl): New
> optional out-parameter GEN_D.
> (satisfy_declaration_constraints): Use it to pass the most
> general version of T to push_tinst_level.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/concepts/diagnostic20.C: New test.
> ---
> gcc/cp/constraint.cc | 15 +++++++++++----
> gcc/testsuite/g++.dg/concepts/diagnostic20.C | 14 ++++++++++++++
> 2 files changed, 25 insertions(+), 4 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/concepts/diagnostic20.C
>
> diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> index a9caba8e2cc7..f688a99c5fd7 100644
> --- a/gcc/cp/constraint.cc
> +++ b/gcc/cp/constraint.cc
> @@ -648,10 +648,13 @@ get_normalized_constraints_from_info (tree ci, tree
> in_decl, bool diag = false)
> return t;
> }
>
> -/* Returns the normalized constraints for the declaration D. */
> +/* Returns the normalized constraints for the declaration D.
> + If GEN_D is non-NULL, sets *GEN_D to the most general version
> + of D that ultimately owns its constraints. */
>
> static tree
> -get_normalized_constraints_from_decl (tree d, bool diag = false)
> +get_normalized_constraints_from_decl (tree d, bool diag = false,
> + tree *gen_d = nullptr)
> {
> tree tmpl;
> tree decl;
> @@ -716,6 +719,8 @@ get_normalized_constraints_from_decl (tree d, bool diag =
> false)
> tmpl = most_general_template (tmpl);
>
> d = tmpl ? tmpl : decl;
> + if (gen_d)
> + *gen_d = d;
>
> /* If we're not diagnosing errors, use cached constraints, if any. */
> if (!diag)
> @@ -2730,9 +2735,11 @@ satisfy_declaration_constraints (tree t, tree args,
> sat_info info)
> return boolean_true_node;
>
> tree result = boolean_true_node;
> - if (tree norm = get_normalized_constraints_from_decl (t, info.noisy ()))
> + tree gen_t;
> + if (tree norm = get_normalized_constraints_from_decl (t, info.noisy (),
> + &gen_t))
> {
> - if (!push_tinst_level (t, args))
> + if (!push_tinst_level (gen_t, args))
> return result;
> tree pattern = DECL_TEMPLATE_RESULT (t);
> push_to_top_level ();
> diff --git a/gcc/testsuite/g++.dg/concepts/diagnostic20.C
> b/gcc/testsuite/g++.dg/concepts/diagnostic20.C
> new file mode 100644
> index 000000000000..d88000b342c3
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/concepts/diagnostic20.C
> @@ -0,0 +1,14 @@
> +// PR c++/99214
> +// { dg-do compile { target c++20 } }
> +
> +template <class T>
> +struct A {
> + template <class U> static void f() requires requires { T::fail; };
> +};
> +
> +int main() {
> + A<int>::f<char>(); // { dg-error "no match" }
> +}
> +
> +// This matches the context line "In substitution of '... [with U = char; T
> = int]'"
> +// { dg-message "U = char; T = int" "" { target *-*-* } 0 }
> --
> 2.49.0.221.g485f5f8636
> diff --git a/output-old.log b/output-new.log
index db26b86de4b2..14bf67ee0580 100644
--- a/output-old.log
+++ b/output-new.log
@@ -476,7 +476,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^~
./concepts/generic-fn-err.C:29:10: note: template argument deduction/substitution failed:
./concepts/generic-fn-err.C:29:10: note: constraints not satisfied
-./concepts/generic-fn-err.C: In substitution of âtemplate<class auto:6> requires C<auto:6> void S2<S>::f2(auto:6) [with auto:6 = S]â:
+./concepts/generic-fn-err.C: In substitution of âtemplate<class T> template<class auto:6> requires C<auto:6> void S2<T>::f2(auto:6) [with auto:6 = int; T = S]â:
./concepts/generic-fn-err.C:45:8: required from here
45 | s2.f2(0); // { dg-error "matching" }
| ~~~~~^~~
@@ -493,7 +493,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^~
./concepts/generic-fn-err.C:32:10: note: template argument deduction/substitution failed:
./concepts/generic-fn-err.C:32:10: note: constraints not satisfied
-./concepts/generic-fn-err.C: In substitution of âtemplate<class auto:8> requires C<auto:8> void S2<S>::h2(auto:8) [with auto:8 = S]â:
+./concepts/generic-fn-err.C: In substitution of âtemplate<class T> template<class auto:8> requires C<auto:8> void S2<T>::h2(auto:8) [with auto:8 = int; T = S]â:
./concepts/generic-fn-err.C:46:8: required from here
46 | s2.h2(0); // { dg-error "matching" }
| ~~~~~^~~
@@ -510,7 +510,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^
./concepts/generic-fn-err.C:35:12: note: template argument deduction/substitution failed:
./concepts/generic-fn-err.C:35:12: note: constraints not satisfied
-./concepts/generic-fn-err.C: In substitution of âtemplate<class U> requires C<U> void S2<S>::g(S, U) [with U = S]â:
+./concepts/generic-fn-err.C: In substitution of âtemplate<class T> template<class U> requires C<U> void S2<T>::g(T, U) [with U = int; T = S]â:
./concepts/generic-fn-err.C:48:7: required from here
48 | s2.g(s, 0); // { dg-error "matching" }
| ~~~~^~~~~~
@@ -578,7 +578,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
./concepts/variadic2.C:12:15: note: candidate 2: âconstexpr int f(Ts ...) [with Ts = {int}]â
12 | constexpr int f(Ts...) { return 1; } // #2
| ^
-./concepts/diagnostic20a.C: In substitution of âtemplate<class U> static void A<int>::f() requires (<lambda>)() [with U = int]â:
+./concepts/diagnostic20a.C: In substitution of âtemplate<class T> template<class U> static void A<T>::f() requires (<lambda>)() [with U = char; T = int]â:
./concepts/diagnostic20a.C:10:18: required from here
10 | A<int>::f<char>(); // { dg-error "no match" }
| ~~~~~~~~~~~~~~~^~
@@ -886,7 +886,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
./concepts/inherit-ctor3.C:10:7: note: constraints not satisfied
10 | S1(U x) { }
| ^~
-./concepts/inherit-ctor3.C: In substitution of âtemplate<class U> requires C<U> S1<X>::S1(U) [with U = X]â:
+./concepts/inherit-ctor3.C: In substitution of âtemplate<class T> template<class U> requires C<U> S1<T>::S1(U) [with U = int; T = X]â:
./concepts/inherit-ctor3.C:21:13: required from here
21 | S2<X> s1(0); // { dg-error "no matching function" }
| ^
@@ -1019,7 +1019,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^
./concepts/placeholder4.C:17:25: note: template argument deduction/substitution failed:
./concepts/placeholder4.C:17:25: note: constraints not satisfied
-./concepts/placeholder4.C: In substitution of âtemplate<int t, class c> requires C<c> static constexpr bool A<int>::f() [with int t = int; c = <missing>]â:
+./concepts/placeholder4.C: In substitution of âtemplate<class T> template<T t, class c> requires C<c> static constexpr bool A<T>::f() [with T t = 1; c = double; T = int]â:
./concepts/placeholder4.C:20:34: required from here
20 | static_assert(A<int>::f<1,double>(), ""); // { dg-error "" }
| ~~~~~~~~~~~~~~~~~~~^~
@@ -1814,7 +1814,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^
./concepts/diagnostic20.C:6:34: note: template argument deduction/substitution failed:
./concepts/diagnostic20.C:6:34: note: constraints not satisfied
-./concepts/diagnostic20.C: In substitution of âtemplate<class U> static void A<int>::f() requires requires{T::fail;} [with U = int]â:
+./concepts/diagnostic20.C: In substitution of âtemplate<class T> template<class U> static void A<T>::f() requires requires{T::fail;} [with U = char; T = int]â:
./concepts/diagnostic20.C:10:18: required from here
10 | A<int>::f<char>(); // { dg-error "no match" }
| ~~~~~~~~~~~~~~~^~
@@ -2513,7 +2513,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^
./cpp2a/concepts-lambda11.C:10:3: note: template argument deduction/substitution failed:
./cpp2a/concepts-lambda11.C:10:3: note: constraints not satisfied
-./cpp2a/concepts-lambda11.C: In substitution of âtemplate<int M> foo<0>()::<lambda()> [with int M = 0]â:
+./cpp2a/concepts-lambda11.C: In substitution of âtemplate<int N> template<int M> foo()::<lambda()> [with int M = 1; int N = 0]â:
./cpp2a/concepts-lambda11.C:10:40: required from âauto foo() [with int N = 0]â
10 | [] <int M=1> () requires (N == M) { }(); // { dg-error "no match" }
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
@@ -2712,7 +2712,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^~
./cpp2a/concepts-memfun-err.C:19:24: note: template argument deduction/substitution failed:
./cpp2a/concepts-memfun-err.C:19:24: note: constraints not satisfied
-./cpp2a/concepts-memfun-err.C: In substitution of âtemplate<class U> requires C<U> void S1<int>::h1(U) [with U = int]â:
+./cpp2a/concepts-memfun-err.C: In substitution of âtemplate<class T> template<class U> requires C<U> void S1<T>::h1(U) [with U = int; T = int]â:
./cpp2a/concepts-memfun-err.C:34:8: required from here
34 | si.h1(0); // { dg-error "matching" }
| ~~~~~^~~
@@ -2914,7 +2914,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^~~~~~
./cpp2a/concepts-explicit-spec7.C:18:6: note: template argument deduction/substitution failed:
./cpp2a/concepts-explicit-spec7.C:18:6: note: constraints not satisfied
-./cpp2a/concepts-explicit-spec7.C: In substitution of âtemplate<int N> static void A<int>::f() requires N == 42 [with int N = int]â:
+./cpp2a/concepts-explicit-spec7.C: In substitution of âtemplate<class T> template<int N> static void A<T>::f() requires N == 42 [with int N = 43; T = int]â:
./cpp2a/concepts-explicit-spec7.C:27:16: required from here
27 | A<int>::f<43>(); // { dg-error "no match" }
| ~~~~~~~~~~~~~^~
@@ -2931,7 +2931,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^~~~~~
./cpp2a/concepts-explicit-spec7.C:23:6: note: template argument deduction/substitution failed:
./cpp2a/concepts-explicit-spec7.C:23:6: note: constraints not satisfied
-./cpp2a/concepts-explicit-spec7.C: In substitution of âtemplate<int N> static void A<int>::B<int>::g() requires T(N) == 42 [with int N = int]â:
+./cpp2a/concepts-explicit-spec7.C: In substitution of âtemplate<class T> template<class U> template<int N> static void A<T>::B<U>::g() requires T(N) == 42 [with int N = 43; U = int; T = int]â:
./cpp2a/concepts-explicit-spec7.C:29:24: required from here
29 | A<int>::B<int>::g<43>(); // { dg-error "no match" }
| ~~~~~~~~~~~~~~~~~~~~~^~
@@ -3262,7 +3262,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
./cpp2a/concepts-inherit-ctor4.C:8:19: note: constraints not satisfied
8 | template<C U> S1(U x) { }
| ^~
-./cpp2a/concepts-inherit-ctor4.C: In substitution of âtemplate<class U> requires C<U> S1<int>::S1(U) [with U = int]â:
+./cpp2a/concepts-inherit-ctor4.C: In substitution of âtemplate<class T> template<class U> requires C<U> S1<T>::S1(U) [with U = int; T = int]â:
./cpp2a/concepts-inherit-ctor4.C:17:14: required from here
17 | S2<int> s(0); // { dg-error "no matching function" }
| ^
@@ -3337,7 +3337,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^
./cpp2a/concepts-fn1.C:96:52: note: template argument deduction/substitution failed:
./cpp2a/concepts-fn1.C:96:52: note: constraints not satisfied
-./cpp2a/concepts-fn1.C: In substitution of âtemplate<class U> requires Classes<T, U> void S<X>::h(U) [with U = X]â:
+./cpp2a/concepts-fn1.C: In substitution of âtemplate<class T> template<class U> requires Classes<T, U> void S<T>::h(U) [with U = int; T = X]â:
./cpp2a/concepts-fn1.C:106:7: required from here
106 | s1.h(0); // { dg-error "no matching function" }
| ~~~~^~~
@@ -4240,7 +4240,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^
./cpp2a/concepts-friend12.C:11:15: note: template argument deduction/substitution failed:
./cpp2a/concepts-friend12.C:11:15: note: constraints not satisfied
-./cpp2a/concepts-friend12.C: In substitution of âtemplate<class ... Us> requires (C<Ts, Us> && ...) void f(A<int>, A<Us ...>) [with Us = {int}]â:
+./cpp2a/concepts-friend12.C: In substitution of âtemplate<class ... Ts> template<class ... Us> requires (C<Ts, Us> && ...) void f(A<Ts>, A<Us ...>) [with Us = {char}; Ts = {int}]â:
./cpp2a/concepts-friend12.C:20:4: required from here
20 | f(x, z); // { dg-error "no match" }
| ~^~~~~~
@@ -4265,7 +4265,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^
./cpp2a/concepts-this1.C:10:8: note: template argument deduction/substitution failed:
./cpp2a/concepts-this1.C:10:8: note: constraints not satisfied
-./cpp2a/concepts-this1.C: In substitution of âtemplate<class U> requires requires{((A<T, <template-parameter-1-2> >*)(void)0)->A<T, <template-parameter-1-2> >::val.x;} void A<C>::f(U) [with U = C]â:
+./cpp2a/concepts-this1.C: In substitution of âtemplate<class T, class> template<class U> requires requires{((A<T, <template-parameter-1-2> >*)(void)0)->A<T, <template-parameter-1-2> >::val.x;} void A<T, <template-parameter-1-2> >::f(U) [with U = int; T = C; <template-parameter-1-2> = void]â:
./cpp2a/concepts-this1.C:27:11: required from here
27 | A<C>().f(0); // { dg-error "no match" }
| ~~~~~~~~^~~
@@ -4321,7 +4321,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^
./cpp2a/concepts-lambda12.C:9:12: note: template argument deduction/substitution failed:
./cpp2a/concepts-lambda12.C:9:12: note: constraints not satisfied
-./cpp2a/concepts-lambda12.C: In substitution of âtemplate<class auto:1> requires different_than<auto:1, B> diff<int>(int)::<lambda(auto:1)> [with auto:1 = int]â:
+./cpp2a/concepts-lambda12.C: In substitution of âtemplate<class B> template<class auto:1> requires different_than<auto:1, B> diff(B)::<lambda(auto:1)> [with auto:1 = int; B = int]â:
./cpp2a/concepts-lambda12.C:14:13: required from here
14 | diff(42)(42); // { dg-error "no match" }
| ~~~~~~~~^~~~
@@ -4356,7 +4356,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
15 | int y = A<int>::v<char>; // { dg-error "invalid" }
| ^~~~~~~
./cpp2a/concepts-var-templ1b.C:15:17: note: constraints not satisfied
-./cpp2a/concepts-var-templ1b.C: In substitution of âtemplate<class> int A<int>::v< <template-parameter-1-1> > [with <template-parameter-1-1> = int]â:
+./cpp2a/concepts-var-templ1b.C: In substitution of âtemplate<class T> template<class> requires C< <template-parameter-2-1>, T> int A<T>::v< <template-parameter-2-1> > [with <template-parameter-2-1> = char; T = int]â:
./cpp2a/concepts-var-templ1b.C:15:17: required from here
./cpp2a/concepts-var-templ1b.C:4:36: required for the satisfaction of âC< <template-parameter-2-1>, T>â [with <template-parameter-2-1> = char; T = int]
./cpp2a/concepts-var-templ1b.C:4:40: note: âcharâ is not the same as âintâ
@@ -4505,7 +4505,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^
./cpp2a/concepts-lambda2.C:32:5: note: template argument deduction/substitution failed:
./cpp2a/concepts-lambda2.C:32:5: note: constraints not satisfied
-./cpp2a/concepts-lambda2.C: In substitution of âtemplate<class R> requires IsNotTiny<R> Bar<long long int>::<lambda(R)> [with R = long long int]â:
+./cpp2a/concepts-lambda2.C: In substitution of âtemplate<class T> template<class R> requires IsNotTiny<R> Bar<T>::<lambda(R)> [with R = char; T = long long int]â:
./cpp2a/concepts-lambda2.C:32:39: required from âconstexpr const auto Bar<long long int>::aâ
32 | []<IsNotTiny R>(R t) { return t; }('a'); // { dg-error "no match" }
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
@@ -4561,7 +4561,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^
./cpp2a/concepts-lambda2.C:34:5: note: template argument deduction/substitution failed:
./cpp2a/concepts-lambda2.C:34:5: note: constraints not satisfied
-./cpp2a/concepts-lambda2.C: In substitution of âtemplate<class R> requires IsNotTiny<R> Bar<long long int>::<lambda(R)> [with R = long long int]â:
+./cpp2a/concepts-lambda2.C: In substitution of âtemplate<class T> template<class R> requires IsNotTiny<R> Bar<T>::<lambda(R)> [with R = char; T = long long int]â:
./cpp2a/concepts-lambda2.C:34:39: required from here
34 | []<IsNotTiny R>(R t) { return t; }('b'); // { dg-error "no match" }
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
@@ -4602,7 +4602,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^
./cpp2a/concepts-lambda2.C:44:3: note: template argument deduction/substitution failed:
./cpp2a/concepts-lambda2.C:44:3: note: constraints not satisfied
-./cpp2a/concepts-lambda2.C: In substitution of âtemplate<class R> requires IsNotTiny<R> <lambda(R)> [with R = char]â:
+./cpp2a/concepts-lambda2.C: In substitution of âtemplate<class S> template<class R> requires IsNotTiny<R> <lambda(R)> [with R = char; S = char]â:
./cpp2a/concepts-lambda2.C:44:37: required from âchar c<char>â
44 | []<IsNotTiny R>(R t) { return t; }('c'); // { dg-error "no match" }
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
@@ -5026,7 +5026,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^
./cpp2a/concepts-lambda2.C:22:8: note: template argument deduction/substitution failed:
./cpp2a/concepts-lambda2.C:22:8: note: constraints not satisfied
-./cpp2a/concepts-lambda2.C: In substitution of âtemplate<class S> requires IsNotTiny<S> auto Foo<int>::b() [with S = int]â:
+./cpp2a/concepts-lambda2.C: In substitution of âtemplate<class T> template<class S> requires IsNotTiny<S> auto Foo<T>::b() [with S = char; T = int]â:
./cpp2a/concepts-lambda2.C:136:15: required from here
136 | foo1.b<char>(); // { dg-error "no match" }
| ~~~~~~~~~~~~^~
@@ -5045,7 +5045,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^
./cpp2a/concepts-lambda2.C:24:12: note: template argument deduction/substitution failed:
./cpp2a/concepts-lambda2.C:24:12: note: constraints not satisfied
-./cpp2a/concepts-lambda2.C: In substitution of âtemplate<class auto:2> requires False<auto:2> Foo<int>::b<long long int>()::<lambda(auto:2)> [with auto:2 = int]â:
+./cpp2a/concepts-lambda2.C: In substitution of âtemplate<class T> template<class S> template<class auto:2> requires False<auto:2> Foo<T>::b()::<lambda(auto:2)> [with auto:2 = int; S = long long int; T = int]â:
./cpp2a/concepts-lambda2.C:137:22: required from here
137 | foo1.b<long long>()(5); // { dg-error "no match" }
| ~~~~~~~~~~~~~~~~~~~^~~
@@ -5062,7 +5062,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^
./cpp2a/concepts-lambda2.C:22:8: note: template argument deduction/substitution failed:
./cpp2a/concepts-lambda2.C:22:8: note: constraints not satisfied
-./cpp2a/concepts-lambda2.C: In substitution of âtemplate<class S> requires IsNotTiny<S> auto Foo<double>::b() [with S = double]â:
+./cpp2a/concepts-lambda2.C: In substitution of âtemplate<class T> template<class S> requires IsNotTiny<S> auto Foo<T>::b() [with S = char; T = double]â:
./cpp2a/concepts-lambda2.C:142:15: required from here
142 | foo2.b<char>(); // { dg-error "no match" }
| ~~~~~~~~~~~~^~
@@ -5081,7 +5081,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^
./cpp2a/concepts-lambda2.C:24:12: note: template argument deduction/substitution failed:
./cpp2a/concepts-lambda2.C:24:12: note: constraints not satisfied
-./cpp2a/concepts-lambda2.C: In substitution of âtemplate<class auto:2> requires False<auto:2> Foo<double>::b<long long int>()::<lambda(auto:2)> [with auto:2 = double]â:
+./cpp2a/concepts-lambda2.C: In substitution of âtemplate<class T> template<class S> template<class auto:2> requires False<auto:2> Foo<T>::b()::<lambda(auto:2)> [with auto:2 = int; S = long long int; T = double]â:
./cpp2a/concepts-lambda2.C:143:22: required from here
143 | foo2.b<long long>()(5); // { dg-error "no match" }
| ~~~~~~~~~~~~~~~~~~~^~~
@@ -5188,7 +5188,7 @@ compilation terminated.
| ^~~~~~
./cpp2a/concepts-pr68093-1.C:7:15: note: template argument deduction/substitution failed:
./cpp2a/concepts-pr68093-1.C:7:15: note: constraints not satisfied
-./cpp2a/concepts-pr68093-1.C: In substitution of âtemplate<class t2> requires false void foobar(S<double>, t2) [with t2 = double]â:
+./cpp2a/concepts-pr68093-1.C: In substitution of âtemplate<class t> template<class t2> requires false void foobar(S<t>, t2) [with t2 = int; t = double]â:
./cpp2a/concepts-pr68093-1.C:12:9: required from here
12 | foobar(S<double>{}, int{}); // { dg-error "" }
| ~~~~~~^~~~~~~~~~~~~~~~~~~~
@@ -5278,7 +5278,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^
./cpp2a/concepts-uneval5.C:9:8: note: template argument deduction/substitution failed:
./cpp2a/concepts-uneval5.C:9:8: note: constraints not satisfied
-./cpp2a/concepts-uneval5.C: In substitution of âtemplate<int J> void A<0>::f(A<J>) requires A<I>::f::d.i != A<I>::i [with int J = 0]â:
+./cpp2a/concepts-uneval5.C: In substitution of âtemplate<int I> template<int J> void A<I>::f(A<J>) requires A<I>::f::d.i != A<I>::i [with int J = 0; int I = 0]â:
./cpp2a/concepts-uneval5.C:10:9: required from âvoid A<I>::f(A<J>) requires A<I>::f::d.i != A<I>::i [with int J = 1; int I = 0]â
10 | f<I>(); // { dg-error "no match" }
| ~~~~^~
@@ -5761,7 +5761,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
./cpp2a/concepts-inherit-ctor11.C:11:5: note: constraints not satisfied
11 | alphabet_tuple_base(component_type) {}
| ^~~~~~~~~~~~~~~~~~~
-./cpp2a/concepts-inherit-ctor11.C: In substitution of âtemplate<class component_type> requires __is_same(component_type, component_types) alphabet_tuple_base<rna4>::alphabet_tuple_base(component_type) [with component_type = rna4]â:
+./cpp2a/concepts-inherit-ctor11.C: In substitution of âtemplate<class component_types> template<class component_type> requires __is_same(component_type, component_types) alphabet_tuple_base<component_types>::alphabet_tuple_base(component_type) [with component_type = dna4; component_types = rna4]â:
./cpp2a/concepts-inherit-ctor11.C:20:31: required from here
20 | structured_rna<rna4> t2{dna4{}}; // { dg-error "no match" }
| ^
@@ -5974,7 +5974,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^~
./cpp2a/concepts-fn3.C:24:8: note: template argument deduction/substitution failed:
./cpp2a/concepts-fn3.C:24:8: note: constraints not satisfied
-./cpp2a/concepts-fn3.C: In substitution of âtemplate<class ... auto:4> requires (... && integral<auto:4>) void S<void>::f1(auto:4 ...) [with auto:4 = void]â:
+./cpp2a/concepts-fn3.C: In substitution of âtemplate<class T> template<class ... auto:4> requires (... && integral<auto:4>) void S<T>::f1(auto:4 ...) [with auto:4 = {int, int, unsigned int}; T = void]â:
./cpp2a/concepts-fn3.C:43:7: required from here
43 | s.f1(1, 2, 3u); // { dg-error "no matching function" }
| ~~~~^~~~~~~~~~
@@ -5991,7 +5991,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^~
./cpp2a/concepts-fn3.C:25:8: note: template argument deduction/substitution failed:
./cpp2a/concepts-fn3.C:25:8: note: constraints not satisfied
-./cpp2a/concepts-fn3.C: In substitution of âtemplate<class ... auto:5> requires (... && all_integral<auto:5>) void S<void>::f2(auto:5 ...) [with auto:5 = void]â:
+./cpp2a/concepts-fn3.C: In substitution of âtemplate<class T> template<class ... auto:5> requires (... && all_integral<auto:5>) void S<T>::f2(auto:5 ...) [with auto:5 = {int, int, unsigned int}; T = void]â:
./cpp2a/concepts-fn3.C:45:7: required from here
45 | s.f2(1, 2, 3u); // { dg-error "no matching function" }
| ~~~~^~~~~~~~~~
@@ -6008,7 +6008,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^~
./cpp2a/concepts-fn3.C:28:8: note: template argument deduction/substitution failed:
./cpp2a/concepts-fn3.C:28:8: note: constraints not satisfied
-./cpp2a/concepts-fn3.C: In substitution of âtemplate<class U, class ... auto:6> requires (type<U>) && true && ((... && integral<auto:6>)) void S<void>::f3(U, auto:6 ...) [with U = void; auto:6 = <missing>]â:
+./cpp2a/concepts-fn3.C: In substitution of âtemplate<class T> template<class U, class ... auto:6> requires (type<U>) && true && ((... && integral<auto:6>)) void S<T>::f3(U, auto:6 ...) [with U = int; auto:6 = {int, unsigned int}; T = void]â:
./cpp2a/concepts-fn3.C:47:7: required from here
47 | s.f3(1, 2, 3u); // { dg-error "no matching function" }
| ~~~~^~~~~~~~~~
@@ -6227,7 +6227,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^
./cpp2a/concepts-lambda16.C:7:12: note: template argument deduction/substitution failed:
./cpp2a/concepts-lambda16.C:7:12: note: constraints not satisfied
-./cpp2a/concepts-lambda16.C: In substitution of âtemplate<class V> A<int>::<lambda(U)>::<lambda(V)> [with V = int]â:
+./cpp2a/concepts-lambda16.C: In substitution of âtemplate<class T> template<class U> template<class V> A<T>::<lambda(U)>::<lambda(V)> [with V = std::nullptr_t; U = int; T = int]â:
./cpp2a/concepts-lambda16.C:45:15: required from here
45 | A<int>::a(0)(nullptr); // { dg-error "no match" }
| ~~~~~~~~~~~~^~~~~~~~~
@@ -6248,7 +6248,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^
./cpp2a/concepts-lambda16.C:12:12: note: template argument deduction/substitution failed:
./cpp2a/concepts-lambda16.C:12:12: note: constraints not satisfied
-./cpp2a/concepts-lambda16.C: In substitution of âtemplate<class V> A<int>::<lambda(U)>::<lambda(V)> [with V = int]â:
+./cpp2a/concepts-lambda16.C: In substitution of âtemplate<class T> template<class W> template<class U> template<class V> A<T>::<lambda(U)>::<lambda(V)> [with V = std::nullptr_t; U = int; W = int; T = int]â:
./cpp2a/concepts-lambda16.C:48:20: required from here
48 | A<int>::b<int>(0)(nullptr); // { dg-error "no match" }
| ~~~~~~~~~~~~~~~~~^~~~~~~~~
@@ -6268,7 +6268,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^
./cpp2a/concepts-lambda16.C:17:14: note: template argument deduction/substitution failed:
./cpp2a/concepts-lambda16.C:17:14: note: constraints not satisfied
-./cpp2a/concepts-lambda16.C: In substitution of âtemplate<class V> A<int>::f()::<lambda(U)>::<lambda(V)> [with V = int]â:
+./cpp2a/concepts-lambda16.C: In substitution of âtemplate<class T> template<class U> template<class V> A<T>::f()::<lambda(U)>::<lambda(V)> [with V = std::nullptr_t; U = int; T = int]â:
./cpp2a/concepts-lambda16.C:51:17: required from here
51 | A<int>::f()(0)(nullptr); // { dg-error "no match" }
| ~~~~~~~~~~~~~~^~~~~~~~~
@@ -6288,7 +6288,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^
./cpp2a/concepts-lambda16.C:24:14: note: template argument deduction/substitution failed:
./cpp2a/concepts-lambda16.C:24:14: note: constraints not satisfied
-./cpp2a/concepts-lambda16.C: In substitution of âtemplate<class V> A<int>::g<int>()::<lambda(U)>::<lambda(V)> [with V = int]â:
+./cpp2a/concepts-lambda16.C: In substitution of âtemplate<class T> template<class W> template<class U> template<class V> A<T>::g()::<lambda(U)>::<lambda(V)> [with V = std::nullptr_t; U = int; W = int; T = int]â:
./cpp2a/concepts-lambda16.C:54:22: required from here
54 | A<int>::g<int>()(0)(nullptr); // { dg-error "no match" }
| ~~~~~~~~~~~~~~~~~~~^~~~~~~~~
@@ -6308,7 +6308,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^
./cpp2a/concepts-lambda16.C:31:10: note: template argument deduction/substitution failed:
./cpp2a/concepts-lambda16.C:31:10: note: constraints not satisfied
-./cpp2a/concepts-lambda16.C: In substitution of âtemplate<class V> <lambda(U)>::<lambda(V)> [with V = int]â:
+./cpp2a/concepts-lambda16.C: In substitution of âtemplate<class T> template<class U> template<class V> <lambda(U)>::<lambda(V)> [with V = std::nullptr_t; U = int; T = int]â:
./cpp2a/concepts-lambda16.C:57:12: required from here
57 | a<int>(0)(nullptr); // { dg-error "no match" }
| ~~~~~~~~~^~~~~~~~~
@@ -6655,7 +6655,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^~
./cpp2a/concepts-requires18.C:36:8: note: template argument deduction/substitution failed:
./cpp2a/concepts-requires18.C:36:8: note: constraints not satisfied
-./cpp2a/concepts-requires18.C: In substitution of âtemplate<class U> requires c1<U> void data<char>::f1() [with U = char]â:
+./cpp2a/concepts-requires18.C: In substitution of âtemplate<class T> template<class U> requires c1<U> void data<T>::f1() [with U = void; T = char]â:
./cpp2a/concepts-requires18.C:79:13: required from here
79 | x.f1<void>(); // { dg-error "no matching function" }
| ~~~~~~~~~~^~
@@ -6673,7 +6673,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^~
./cpp2a/concepts-requires18.C:40:8: note: template argument deduction/substitution failed:
./cpp2a/concepts-requires18.C:40:8: note: constraints not satisfied
-./cpp2a/concepts-requires18.C: In substitution of âtemplate<class U> requires requires{requires(integer<U>) || (subst<U&>);} void data<char>::f2() [with U = char]â:
+./cpp2a/concepts-requires18.C: In substitution of âtemplate<class T> template<class U> requires requires{requires(integer<U>) || (subst<U&>);} void data<T>::f2() [with U = void; T = char]â:
./cpp2a/concepts-requires18.C:82:13: required from here
82 | x.f2<void>(); // { dg-error "no matching function" }
| ~~~~~~~~~~^~
@@ -7131,7 +7131,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
./cpp2a/concepts-conv3a.C:7:38: required from âstruct Error<int>â
7 | struct Error { static constexpr auto value = T::value; }; // { dg-error "not a member" }
| ^~~~~
-./cpp2a/concepts-conv3a.C:12:63: required by substitution of âtemplate<class U> B<int>::operator U() requires Error<T>::value [with U = int]â
+./cpp2a/concepts-conv3a.C:12:63: required by substitution of âtemplate<class T> template<class U> B<T>::operator U() requires Error<T>::value [with U = const A; T = int]â
12 | struct B { template <class U> operator U() requires Error<T>::value; };
| ^~~~~
./cpp2a/concepts-conv3a.C:15:33: required from here
@@ -7363,8 +7363,8 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
./cpp2a/concepts-pr100589.C:9:14: error: invalid use of constrained âautoâ type
9 | using type = false_concept auto() -> int; // { dg-error "invalid use of constrained 'auto' type" }
| ^~~~~~~~~~~~~
-./cpp2a/concepts-recursive-sat4.C: In substitution of âtemplate<class T> requires C<T, Rep> void operator*(T, Int<int>) [with T = int]â:
-./cpp2a/concepts-recursive-sat4.C:5:64: required by substitution of âtemplate<class T> requires C<T, Rep> void operator*(Int<int>, T) [with T = int]â
+./cpp2a/concepts-recursive-sat4.C: In substitution of âtemplate<class Rep> template<class T> requires C<T, Rep> void operator*(T, Int<Rep>) [with T = Int<int>; Rep = int]â:
+./cpp2a/concepts-recursive-sat4.C:5:64: required by substitution of âtemplate<class Rep> template<class T> requires C<T, Rep> void operator*(Int<Rep>, T) [with T = Int<int>; Rep = int]â
5 | template <class T, class U> concept C = requires(T t, U u) { t * u; };
| ~~^~~
./cpp2a/concepts-recursive-sat4.C:15:25: required from here
@@ -7669,7 +7669,7 @@ cc1plus: note: set â-fconcepts-diagnostics-depth=â to at least 2 for more de
| ^
./cpp2a/concepts-return-req4.C:15:15: note: template argument deduction/substitution failed:
./cpp2a/concepts-return-req4.C:15:15: note: constraints not satisfied
-./cpp2a/concepts-return-req4.C: In substitution of âtemplate<class ...> requires requires{{1} -> decltype(auto) [requires ::is_same<<placeholder>, T>];} static void A<bool>::f() [with <template-parameter-1-1> = bool]â:
+./cpp2a/concepts-return-req4.C: In substitution of âtemplate<class T> template<class ...> requires requires{{1} -> decltype(auto) [requires ::is_same<<placeholder>, T>];} static void A<T>::f() [with <template-parameter-2-1> = {}; T = bool]â:
./cpp2a/concepts-return-req4.C:23:13: required from here
23 | A<bool>::f(); // { dg-error "no match" }
| ~~~~~~~~~~^~