Here during constraint checking for the recursive call to 'f', substitution into the PARM_DECL 'd' in the atomic constraint gives us the wrong local specialization because local_specializations at this point contains entities associated with the _outer_ call to 'f'.
This patch fixes this by calling push_to_top_level during constraint checking, which'll clear local_specializations for us. Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk/11? Also tested on cmcstl2 and range-v3. PR c++/103714 gcc/cp/ChangeLog: * constraint.cc (satisfy_declaration_constraints): Do push_to_top_level and pop_from_top_level around the call to satisfy_normalized_constraints. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-uneval5.C: New test. --- gcc/cp/constraint.cc | 4 ++++ gcc/testsuite/g++.dg/cpp2a/concepts-uneval5.C | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-uneval5.C diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 566f4e38fac..9b0348dfdd6 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -3186,9 +3186,11 @@ satisfy_declaration_constraints (tree t, sat_info info) { if (!push_tinst_level (t)) return result; + push_to_top_level (); push_access_scope (t); result = satisfy_normalized_constraints (norm, args, info); pop_access_scope (t); + pop_from_top_level (); pop_tinst_level (); } @@ -3244,9 +3246,11 @@ satisfy_declaration_constraints (tree t, tree args, sat_info info) if (!push_tinst_level (t, args)) return result; tree pattern = DECL_TEMPLATE_RESULT (t); + push_to_top_level (); push_access_scope (pattern); result = satisfy_normalized_constraints (norm, args, info); pop_access_scope (pattern); + pop_from_top_level (); pop_tinst_level (); } diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-uneval5.C b/gcc/testsuite/g++.dg/cpp2a/concepts-uneval5.C new file mode 100644 index 00000000000..a315a59b828 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-uneval5.C @@ -0,0 +1,17 @@ +// PR c++/103714 +// { dg-do compile { target c++20 } } + +template<int I> +struct A { + static const int i = I; + + template<int J> + void f(A<J> d = {}) requires (d.i != i) { + f<I>(); // { dg-error "no match" } + } +}; + +int main() { + A<0> a; + a.f<1>(); +} -- 2.34.1.182.ge773545c7f