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<int>::f<U>() ... [with U = char]'.
This patch fixes this by passing the original 'args' to push_tinst_level,
which ought to properly correspond to 't'.
PR c++/99214
gcc/cp/ChangeLog:
* constraint.cc (satisfy_declaration_constraints): Pass the
original ARGS to push_tinst_level.
gcc/testsuite/ChangeLog:
* g++.dg/concepts/diagnostic20.C: New test.
Reviewed-by: Jason Merrill <jason@redhat.com>
static tree
satisfy_declaration_constraints (tree t, tree args, sat_info info)
{
+ tree orig_args = args;
+
/* Update the declaration for diagnostics. */
info.in_decl = t;
tree result = boolean_true_node;
if (tree norm = get_normalized_constraints_from_decl (t, info.noisy ()))
{
- if (!push_tinst_level (t, args))
+ if (!push_tinst_level (t, orig_args))
return result;
tree pattern = DECL_TEMPLATE_RESULT (t);
push_to_top_level ();
--- /dev/null
+// 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" }
+}
+
+// { dg-message "In substitution of '\[^\r\n\]* \\\[with U = char\\\]'" "" { target *-*-* } 0 }