In the three-parameter version of satisfy_declaration_constraints, when
't' isn't the most general template, then 't' doesn't correspond with
the augmented template arguments 'args', and so the instantiation
context that we push via push_tinst_level isn't quite correct.  This
manifests as misleading diagnostic context lines during satisfaction
failure as in the testcase below for which without this patch we emit
  In substitution of '... static void A<int>::f<U>() [with U = int]'
and with this patch we emit
  In substitution of '... static void A<T>::f<U>() [with U = char; T = int]'.

This patch fixes this by passing the most general template to
push_tinst_level.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?

gcc/cp/ChangeLog:

        PR c++/99214
        * constraint.cc (get_normalized_constraints_from_decl): Fix
        formatting.
        (satisfy_declaration_constraints): Be lazy about augmenting
        'args'.  Pass the most general template to push_tinst_level.

gcc/testsuite/ChangeLog:

        PR c++/99214
        * g++.dg/concepts/diagnostic16.C: New test.
---
 gcc/cp/constraint.cc                         | 16 ++++++++--------
 gcc/testsuite/g++.dg/concepts/diagnostic16.C | 15 +++++++++++++++
 2 files changed, 23 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/concepts/diagnostic16.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 31e0fb5079a..88963e687a7 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -910,11 +910,9 @@ get_normalized_constraints_from_decl (tree d, bool diag = 
false)
      accepting the latter causes the template parameter level of U
      to be reduced in a way that makes it overly difficult substitute
      concrete arguments (i.e., eventually {int, int} during satisfaction.  */
-  if (tmpl)
-  {
-    if (DECL_LANG_SPECIFIC(tmpl) && !DECL_TEMPLATE_SPECIALIZATION (tmpl))
-      tmpl = most_general_template (tmpl);
-  }
+  if (tmpl && DECL_LANG_SPECIFIC (tmpl)
+      && !DECL_TEMPLATE_SPECIALIZATION (tmpl))
+    tmpl = most_general_template (tmpl);
 
   /* If we're not diagnosing errors, use cached constraints, if any.  */
   if (!diag)
@@ -3157,12 +3155,14 @@ satisfy_declaration_constraints (tree t, tree args, 
sat_info info)
 
   gcc_assert (TREE_CODE (t) == TEMPLATE_DECL);
 
-  args = add_outermost_template_args (t, args);
-
   tree result = boolean_true_node;
   if (tree norm = normalize_template_requirements (t, info.noisy ()))
     {
-      if (!push_tinst_level (t, args))
+      args = add_outermost_template_args (t, args);
+      tree gen_tmpl = t;
+      if (DECL_LANG_SPECIFIC (t) && !DECL_TEMPLATE_SPECIALIZATION (t))
+       gen_tmpl = most_general_template (t);
+      if (!push_tinst_level (gen_tmpl, args))
        return result;
       tree pattern = DECL_TEMPLATE_RESULT (t);
       push_access_scope (pattern);
diff --git a/gcc/testsuite/g++.dg/concepts/diagnostic16.C 
b/gcc/testsuite/g++.dg/concepts/diagnostic16.C
new file mode 100644
index 00000000000..b8d586e9a21
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/diagnostic16.C
@@ -0,0 +1,15 @@
+// PR c++/99214
+// { dg-do compile { target c++20 } }
+
+template <class T>
+struct A {
+  template <class U> static void f() requires ([] { return U::fail; }()); // { 
dg-error "fail" }
+  template <class U> static void f();
+};
+
+int main() {
+  A<int>::f<char>();
+}
+
+// This matches the context line "In substitution of '... [with U = char; T = 
int]'"
+// { dg-message "U = char; T = int" "" { target *-*-* } 0 }
-- 
2.30.1.602.g966e671106

Reply via email to