On 3/4/25 2:49 PM, Patrick Palka wrote:
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.
That soungs good, but getting it by passing it back from
get_normalized_constraints_from_decl seems confusing; I'd think we
should calculate it in parallel to changing args to correspond to that
template.
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 }