[PATCH] c++: Fix call to push_tinst_level during satisfaction [PR99214]

Patrick Palka ppalka@redhat.com
Thu Feb 25 06:37:12 GMT 2021


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



More information about the Gcc-patches mailing list