https://gcc.gnu.org/g:3605e057040ead00c072c20bfbb8f26636f8295e

commit r15-7728-g3605e057040ead00c072c20bfbb8f26636f8295e
Author: Marek Polacek <pola...@redhat.com>
Date:   Thu Feb 20 14:35:25 2025 -0500

    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.

Diff:
---
 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(-)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 9f619b111673..69c27aa7b6e3 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 1a6b68829002..ca25403f39b6 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 000000000000..14b98836880a
--- /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 000000000000..c7c31dd9b302
--- /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." }
+}

Reply via email to