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.

        PR c++/99214

gcc/cp/ChangeLog:

        * constraint.cc (get_normalized_constraints_from_decl): New
        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 | 15 +++++++++++++++
 2 files changed, 26 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 a9caba8e2cc..f688a99c5fd 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 00000000000..b8d586e9a21
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/diagnostic20.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.49.0.rc0.57.gdb91954e18

Reply via email to