aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2025-02-20 14:35:25 -0500
committerMarek Polacek <polacek@redhat.com>2025-02-27 10:53:19 -0500
commit3605e057040ead00c072c20bfbb8f26636f8295e (patch)
tree9ccc1c2dcd4ea4919786c17f83085e4f6e05e604
parent767a7a06915651da173b6751959a47487351ed3a (diff)
downloadgcc-3605e057040ead00c072c20bfbb8f26636f8295e.zip
gcc-3605e057040ead00c072c20bfbb8f26636f8295e.tar.gz
gcc-3605e057040ead00c072c20bfbb8f26636f8295e.tar.bz2
c++: too many errors with sneaky template [PR118516]
Since C++20 P0846, a name followed by a < can be treated as a template-name even though name lookup did not find a template-name. That happens in this test with "i < foo ()": for (int id = 0; i < foo(); ++id); and results in a raft of errors about non-constant foo(). The problem is that the require_potential_constant_expression call in cp_parser_template_argument emits errors even when we're parsing tentatively. So we repeat the error when we're trying to parse as a nested-name-specifier, type-name, etc. Guarding the call with !cp_parser_uncommitted_to_tentative_parse_p would mean that require_potential_constant_expression never gets called. But we don't need the call at all as far as I can tell. Stuff like template<int N> struct S { }; int foo () { return 4; } void g () { S<foo()> s; } gets diagnosed in convert_nontype_argument. In fact, with this patch, we only emit "call to non-constexpr function" once. (That is, in C++17 only; C++14 uses a different path.) PR c++/118516 gcc/cp/ChangeLog: * parser.cc (cp_parser_template_argument): Don't call require_potential_constant_expression. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/fn-template11.C: * g++.dg/template/fn-template1.C: New test. * g++.dg/template/fn-template2.C: New test.
-rw-r--r--gcc/cp/parser.cc1
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/fn-template11.C2
-rw-r--r--gcc/testsuite/g++.dg/template/fn-template1.C12
-rw-r--r--gcc/testsuite/g++.dg/template/fn-template2.C9
4 files changed, 22 insertions, 2 deletions
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 9f619b1..69c27aa 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -20315,7 +20315,6 @@ cp_parser_template_argument (cp_parser* parser)
/* With C++17 generalized non-type template arguments we need to handle
lvalue constant expressions, too. */
argument = cp_parser_assignment_expression (parser);
- require_potential_constant_expression (argument);
}
if (!maybe_type_id)
diff --git a/gcc/testsuite/g++.dg/cpp2a/fn-template11.C b/gcc/testsuite/g++.dg/cpp2a/fn-template11.C
index 1a6b688..ca25403 100644
--- a/gcc/testsuite/g++.dg/cpp2a/fn-template11.C
+++ b/gcc/testsuite/g++.dg/cpp2a/fn-template11.C
@@ -7,5 +7,5 @@ int nonconst ();
int foo ()
{
return blah < // { dg-error "not declared" }
- nonconst (), nonconst (); // { dg-error "call to non-.constexpr. function" }
+ nonconst (), nonconst ();
}
diff --git a/gcc/testsuite/g++.dg/template/fn-template1.C b/gcc/testsuite/g++.dg/template/fn-template1.C
new file mode 100644
index 0000000..14b9883
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/fn-template1.C
@@ -0,0 +1,12 @@
+// PR c++/118516
+// { dg-do compile }
+// Like cpp2a/fn-template11.C but with blah declared.
+
+int nonconst ();
+
+int foo ()
+{
+ int blah = 20;
+ return blah <
+ nonconst (), nonconst ();
+}
diff --git a/gcc/testsuite/g++.dg/template/fn-template2.C b/gcc/testsuite/g++.dg/template/fn-template2.C
new file mode 100644
index 0000000..c7c31dd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/fn-template2.C
@@ -0,0 +1,9 @@
+// PR c++/118516
+// { dg-do compile }
+
+int foo();
+int main()
+{
+ for (int id = 0; i < // { dg-error "not declared in this scope" }
+ foo(); ++id); // { dg-bogus "call to non-.constexpr." }
+}