Here during constraint checking for the inner call to A<0>::f<0>,
substitution into the PARM_DECL d in the atomic constraint yields the
wrong local specialization because local_specializations at this point
is nonempty, and contains specializations for the caller A<0>::f<1>.
This patch makes us call push_to_top_level during satisfaction, which'll
temporarily clear local_specializations for us.
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.
{
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 ();
}
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 ();
}
--- /dev/null
+// 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>();
+}