Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? -- >8 -- 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. --- gcc/cp/parser.cc | 1 - gcc/testsuite/g++.dg/cpp2a/fn-template11.C | 2 +- gcc/testsuite/g++.dg/template/fn-template1.C | 12 ++++++++++++ gcc/testsuite/g++.dg/template/fn-template2.C | 9 +++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/fn-template1.C create mode 100644 gcc/testsuite/g++.dg/template/fn-template2.C diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 0578aad1b1c..84b36a21767 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 1a6b6882900..ca25403f39b 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 00000000000..14b98836880 --- /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 00000000000..c7c31dd9b30 --- /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." } +} base-commit: 4e9ee99647ebb9a7cab1497d78477f75d1157ac5 -- 2.48.1