https://gcc.gnu.org/g:9d5c276dfb5f5812e0fa7b46e84beaca36295c6d

commit r17-482-g9d5c276dfb5f5812e0fa7b46e84beaca36295c6d
Author: [email protected] <[email protected]>
Date:   Wed May 13 00:48:45 2026 -0400

    c++/reflection: reject invalid annotation on class [PR123609]
    
    Some errors while parsing attributes on class are ignored due to tentative
    parsing, this patch redo parsing to reject it.
    
            PR c++/123609
    
    gcc/cp/ChangeLog:
    
            * parser.cc (cp_parser_class_head): Re-parse attributes
            that caused a tentative parsing failure.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp0x/attr-nodiscard1.C: Adjust expected errors.
            * g++.dg/reflect/annotations19.C: New test.
    
    Co-authored-by: Jason Merrill <[email protected]>

Diff:
---
 gcc/cp/parser.cc                             | 15 +++++++++++++++
 gcc/testsuite/g++.dg/cpp0x/attr-nodiscard1.C |  4 ++--
 gcc/testsuite/g++.dg/reflect/annotations19.C |  5 +++++
 3 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index c08f4cee920d..c7708f15f39b 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -30295,7 +30295,13 @@ cp_parser_class_head (cp_parser* parser,
   location_t class_head_start_location = input_location;
 
   /* Parse the attributes.  */
+  /* Save tokens for some unhandled error (PR123609).  */
+  cp_token_position attribute_error_position = 0;
+  if (!cp_parser_error_occurred (parser))
+    attribute_error_position = cp_lexer_token_position (parser->lexer, false);
   attributes = cp_parser_attributes_opt (parser);
+  if (!cp_parser_error_occurred (parser))
+    attribute_error_position = 0;
 
   /* If the next token is `::', that is invalid -- but sometimes
      people do try to write:
@@ -30437,6 +30443,15 @@ cp_parser_class_head (cp_parser* parser,
   /* At this point, we're going ahead with the class-specifier, even
      if some other problem occurs.  */
   cp_parser_commit_to_tentative_parse (parser);
+  /* Some errors while parsing attributes are ignored due to tentative parsing,
+     redo parsing to reject it.  */
+  if (attribute_error_position)
+    {
+      auto current_position = cp_lexer_token_position (parser->lexer, false);
+      cp_lexer_set_token_position (parser->lexer, attribute_error_position);
+      cp_parser_attributes_opt (parser);
+      cp_lexer_set_token_position (parser->lexer, current_position);
+    }
   /* Issue the error about the overly-qualified name now.  */
   if (qualified_p)
     {
diff --git a/gcc/testsuite/g++.dg/cpp0x/attr-nodiscard1.C 
b/gcc/testsuite/g++.dg/cpp0x/attr-nodiscard1.C
index 5abdd380f9d2..5b97d0b61044 100644
--- a/gcc/testsuite/g++.dg/cpp0x/attr-nodiscard1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/attr-nodiscard1.C
@@ -10,9 +10,9 @@ foo (int n)
 {
   struct [[nodiscard]] S1 {};
   struct [[nodiscard ("foobar")]] S2 {};
-  struct [[nodiscard (0)]] S3 {};              // { dg-error "'nodiscard' 
attribute argument must be a string constant" }
+  struct [[nodiscard (0)]] S3 {};              // { dg-error "'nodiscard' 
attribute argument must be a string constant|expected string-literal" }
   struct [[nodiscard ("foo", "bar", "baz")]] S4 {};    // { dg-error "wrong 
number of arguments specified for 'nodiscard' attribute" }
-  struct [[nodiscard (0, 1, 2)]] S5 {};                // { dg-error "wrong 
number of arguments specified for 'nodiscard' attribute" }
+  struct [[nodiscard (0, 1, 2)]] S5 {};                // { dg-error "wrong 
number of arguments specified for 'nodiscard' attribute|expected 
string-literal" }
 
   auto a = [] [[nodiscard]] () {};
   auto b = [] constexpr [[nodiscard]] {};      // { dg-warning "'nodiscard' 
attribute can only be applied to functions or to class or enumeration types" }
diff --git a/gcc/testsuite/g++.dg/reflect/annotations19.C 
b/gcc/testsuite/g++.dg/reflect/annotations19.C
new file mode 100644
index 000000000000..2408aec809c6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/annotations19.C
@@ -0,0 +1,5 @@
+// PR c++/123609
+// { dg-do compile { target c++26 } }
+
+struct [[=]] S {};                     // { dg-error "expected 
primary-expression before ']' token" }
+[[=]] int a;                           // { dg-error "expected 
primary-expression before ']' token" }

Reply via email to