https://gcc.gnu.org/g:8b83820b68f358e21c740c0fcfb984e294f81ede

commit r15-6330-g8b83820b68f358e21c740c0fcfb984e294f81ede
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Wed Dec 18 11:55:59 2024 +0100

    c++: Handle attributes on exception declarations [PR110345]
    
    This is a continuation of the series for the ignorability of standard
    attributes.
    
    I've added a test for assume attribute diagnostics appertaining to various
    entities (mostly invalid) and while doing that, I've discovered that
    attributes on exception declarations were mostly ignored, this patch
    adds the missing cp_decl_attributes call and also in the
    cp_parser_type_specifier_seq case differentiates between attributes and
    std_attributes to be able to differentiate between attributes which apply
    to the declaration using type-specifier-seq and attributes after the type
    specifiers.
    
    2024-12-18  Jakub Jelinek  <ja...@redhat.com>
    
            PR c++/110345
            * parser.cc (cp_parser_type_specifier_seq): Chain cxx11_attribute_p
            attributes after any type specifier in the is_declaration case
            to std_attributes rather than attributes.  Set also ds_attribute
            or ds_std_attribute locations if not yet set.
            (cp_parser_exception_declaration): Pass &type_specifiers.attributes
            instead of NULL as last argument, call cp_decl_attributes.
    
            * g++.dg/cpp0x/attr-assume1.C: New test.

Diff:
---
 gcc/cp/parser.cc                          |  28 +++++-
 gcc/testsuite/g++.dg/cpp0x/attr-assume1.C | 151 ++++++++++++++++++++++++++++++
 2 files changed, 175 insertions(+), 4 deletions(-)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 815901b31eb5..3f4b1e9e3e35 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -25642,9 +25642,24 @@ cp_parser_type_specifier_seq (cp_parser* parser,
                  || tok->type == CPP_EQ || tok->type == CPP_OPEN_BRACE)
                break;
            }
-         type_specifier_seq->attributes
-           = attr_chainon (type_specifier_seq->attributes,
-                           cp_parser_attributes_opt (parser));
+         location_t attr_loc = cp_lexer_peek_token (parser->lexer)->location;
+         tree attrs = cp_parser_attributes_opt (parser);
+         if (seen_type_specifier
+             && is_declaration
+             && cxx11_attribute_p (attrs))
+           {
+             type_specifier_seq->std_attributes
+               = attr_chainon (type_specifier_seq->std_attributes, attrs);
+             if (type_specifier_seq->locations[ds_std_attribute] == 0)
+               type_specifier_seq->locations[ds_std_attribute] = attr_loc;
+           }
+         else
+           {
+             type_specifier_seq->attributes
+               = attr_chainon (type_specifier_seq->attributes, attrs);
+             if (type_specifier_seq->locations[ds_attribute] == 0)
+               type_specifier_seq->locations[ds_attribute] = attr_loc;
+           }
          continue;
        }
 
@@ -29927,7 +29942,12 @@ cp_parser_exception_declaration (cp_parser* parser)
   if (!type_specifiers.any_specifiers_p)
     return error_mark_node;
 
-  return grokdeclarator (declarator, &type_specifiers, CATCHPARM, 1, NULL);
+  tree decl = grokdeclarator (declarator, &type_specifiers, CATCHPARM, 1,
+                             &type_specifiers.attributes);
+  if (decl != error_mark_node && type_specifiers.attributes)
+    cplus_decl_attributes (&decl, type_specifiers.attributes, 0);
+
+  return decl;
 }
 
 /* Parse a throw-expression.
diff --git a/gcc/testsuite/g++.dg/cpp0x/attr-assume1.C 
b/gcc/testsuite/g++.dg/cpp0x/attr-assume1.C
new file mode 100644
index 000000000000..4aee2a2596ab
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/attr-assume1.C
@@ -0,0 +1,151 @@
+// C++ 26 P2552R3 - On the ignorability of standard attributes
+// { dg-do compile { target c++11 } }
+
+int arr[2];
+struct S { int a, b; };
+S arr2[2];
+
+void
+foo (int n)
+{
+  [[assume (n > 0)]];
+  [[assume]];                                  // { dg-error "wrong number of 
arguments specified for 'assume' attribute" }
+  [[assume ("abc")]];
+  [[assume (1, 2, 3)]];                                // { dg-error "wrong 
number of arguments specified for 'assume' attribute" }
+
+  [[assume (true)]] int x1;                    // { dg-error "'assume' 
attribute ignored" }
+
+  auto a = [] [[assume (true)]] () {};         // { dg-error "'assume' 
attribute ignored" }
+  auto b = [] constexpr [[assume (true)]] {};  // { dg-error "'assume' 
attribute ignored" }
+                                               // { dg-error "parameter 
declaration before lambda declaration specifiers only optional with" "" { 
target c++20_down } .-1 }
+                                               // { dg-error "'constexpr' 
lambda only available with" "" { target c++14_down } .-2 }
+  auto c = [] noexcept [[assume (true)]] {};   // { dg-error "'assume' 
attribute ignored" }
+                                               // { dg-error "parameter 
declaration before lambda exception specification only optional with" "" { 
target c++20_down } .-1 }
+  auto d = [] () [[assume (true)]] {};         // { dg-error "'assume' 
attribute ignored" }
+  auto e = new int [n] [[assume (true)]];      // { dg-warning "attributes 
ignored on outermost array type in new expression" }
+  auto e2 = new int [n] [[assume (true)]] [42];        // { dg-warning 
"attributes ignored on outermost array type in new expression" }
+  auto f = new int [n][42] [[assume (true)]];  // { dg-error "'assume' 
attribute ignored" }
+  [[assume (true)]];
+  [[assume (true)]] {}                         // { dg-warning "attributes at 
the beginning of statement are ignored" }
+  [[assume (true)]] if (true) {}               // { dg-warning "attributes at 
the beginning of statement are ignored" }
+  [[assume (true)]] while (false) {}           // { dg-warning "attributes at 
the beginning of statement are ignored" }
+  [[assume (true)]] goto lab;                  // { dg-warning "attributes at 
the beginning of statement are ignored" }
+  [[assume (true)]] lab:;                      // { dg-error "'assume' 
attribute ignored" }
+  [[assume (true)]] try {} catch (int) {}      // { dg-warning "attributes at 
the beginning of statement are ignored" }
+  if ([[assume (true)]] int x = 0) {}          // { dg-error "'assume' 
attribute ignored" }
+  switch (n)
+    {
+    [[assume (true)]] case 1:                  // { dg-error "'assume' 
attribute ignored" }
+    [[assume (true)]] break;                   // { dg-warning "attributes at 
the beginning of statement are ignored" }
+    [[assume (true)]] default:                 // { dg-error "'assume' 
attribute ignored" }
+        break;
+    }
+  for ([[assume (true)]] auto a : arr) {}      // { dg-error "'assume' 
attribute ignored" }
+  for ([[assume (true)]] auto [a, b] : arr2) {}        // { dg-error "'assume' 
attribute ignored" }
+                                               // { dg-error "structured 
bindings only available with" "" { target c++14_down } .-1 }
+  [[assume (true)]] asm ("");                  // { dg-warning "attributes 
ignored on 'asm' declaration" }
+  try {} catch ([[assume (true)]] int x) {}    // { dg-error "'assume' 
attribute ignored" }
+  try {} catch ([[assume (true)]] int) {}      // { dg-error "'assume' 
attribute ignored" }
+  try {} catch (int [[assume (true)]] x) {}    // { dg-warning "attribute 
ignored" }
+  try {} catch (int [[assume (true)]]) {}      // { dg-warning "attribute 
ignored" }
+  try {} catch (int x [[assume (true)]]) {}    // { dg-error "'assume' 
attribute ignored" }
+}
+
+[[assume (true)]] int bar ();                  // { dg-error "'assume' 
attribute ignored" }
+using foobar [[assume (true)]] = int;          // { dg-error "'assume' 
attribute ignored" }
+[[assume (true)]] int a;                       // { dg-error "'assume' 
attribute ignored" }
+[[assume (true)]] auto [b, c] = arr;           // { dg-error "'assume' 
attribute ignored" }
+                                               // { dg-error "structured 
bindings only available with" "" { target c++14_down } .-1 }
+[[assume (true)]];                             // { dg-warning "attribute 
ignored" }
+inline [[assume (true)]] void baz () {}                // { dg-warning 
"attribute ignored" }
+                                               // { dg-error "standard 
attributes in middle of decl-specifiers" "" { target *-*-* } .-1 }
+constexpr [[assume (true)]] int qux () { return 0; }   // { dg-warning 
"attribute ignored" }
+                                               // { dg-error "standard 
attributes in middle of decl-specifiers" "" { target *-*-* } .-1 }
+int [[assume (true)]] d;                       // { dg-warning "attribute 
ignored" }
+int const [[assume (true)]] e = 1;             // { dg-warning "attribute 
ignored" }
+struct A {} [[assume (true)]];                 // { dg-warning "attribute 
ignored in declaration of 'struct A'" }
+struct A [[assume (true)]];                    // { dg-warning "attribute 
ignored" }
+struct A [[assume (true)]] a1;                 // { dg-warning "attribute 
ignored" }
+A [[assume (true)]] a2;                                // { dg-warning 
"attribute ignored" }
+enum B { B0 } [[assume (true)]];               // { dg-warning "attribute 
ignored in declaration of 'enum B'" }
+enum B [[assume (true)]];                      // { dg-warning "attribute 
ignored" }
+enum B [[assume (true)]] b1;                   // { dg-warning "attribute 
ignored" }
+B [[assume (true)]] b2;                                // { dg-warning 
"attribute ignored" }
+struct [[assume (true)]] C {};                 // { dg-error "'assume' 
attribute ignored" }
+int f [[assume (true)]];                       // { dg-error "'assume' 
attribute ignored" }
+int g[2] [[assume (true)]];                    // { dg-error "'assume' 
attribute ignored" }
+int g2 [[assume (true)]] [2];                  // { dg-error "'assume' 
attribute ignored" }
+int corge () [[assume (true)]];                        // { dg-error "'assume' 
attribute ignored" }
+int *[[assume (true)]] h;                      // { dg-error "'assume' 
attribute ignored" }
+int & [[assume (true)]] i = f;                 // { dg-error "'assume' 
attribute ignored" }
+int && [[assume (true)]] j = 0;                        // { dg-error "'assume' 
attribute ignored" }
+int S::* [[assume (true)]] k;                  // { dg-error "'assume' 
attribute ignored" }
+auto l = sizeof (int [2] [[assume (true)]]);   // { dg-error "'assume' 
attribute ignored" }
+int freddy ([[assume (true)]] int a,           // { dg-error "'assume' 
attribute ignored" }
+           [[assume (true)]] int,              // { dg-error "'assume' 
attribute ignored" }
+           [[assume (true)]] int c = 0,        // { dg-error "'assume' 
attribute ignored" }
+           [[assume (true)]] int = 0);         // { dg-error "'assume' 
attribute ignored" }
+void
+corge ([[assume (true)]] int a,                        // { dg-error "'assume' 
attribute ignored" }
+       [[assume (true)]] int,                  // { dg-error "'assume' 
attribute ignored" }
+       [[assume (true)]] int c = 0,            // { dg-error "'assume' 
attribute ignored" }
+       [[assume (true)]] int = 0)              // { dg-error "'assume' 
attribute ignored" }
+{
+}
+[[assume (true)]] void
+garply ()                                      // { dg-error "'assume' 
attribute ignored" }
+{
+}
+int grault (int [[assume (true)]] a,           // { dg-warning "attribute 
ignored" }
+           int [[assume (true)]],              // { dg-warning "attribute 
ignored" }
+           int [[assume (true)]] c = 0,        // { dg-warning "attribute 
ignored" }
+           int [[assume (true)]] = 0);         // { dg-warning "attribute 
ignored" }
+void
+waldo (int [[assume (true)]] a,                        // { dg-warning 
"attribute ignored" }
+       int [[assume (true)]],                  // { dg-warning "attribute 
ignored" }
+       int [[assume (true)]] c = 0,            // { dg-warning "attribute 
ignored" }
+       int [[assume (true)]] = 0)              // { dg-warning "attribute 
ignored" }
+{
+}
+int plugh (int a [[assume (true)]],            // { dg-error "'assume' 
attribute ignored" }
+           int b [[assume (true)]] = 0);       // { dg-error "'assume' 
attribute ignored" }
+void
+thud (int a [[assume (true)]],                 // { dg-error "'assume' 
attribute ignored" }
+      int b [[assume (true)]] = 0)             // { dg-error "'assume' 
attribute ignored" }
+{
+}
+enum [[assume (true)]] D { D0 };               // { dg-error "'assume' 
attribute ignored" }
+enum class [[assume (true)]] E { E0 };         // { dg-error "'assume' 
attribute ignored" }
+enum F {};
+enum [[assume (true)]] F;                      // { dg-warning "type 
attributes ignored after type is already defined" }
+enum G {
+  G0 [[assume (true)]],                                // { dg-error "'assume' 
attribute ignored" }
+  G1 [[assume (true)]] = 2                     // { dg-error "'assume' 
attribute ignored" }
+};
+namespace [[assume (true)]] H { using H0 = int; }      // { dg-warning 
"'assume' attribute directive ignored" } */
+namespace [[assume (true)]] {}                 // { dg-warning "'assume' 
attribute directive ignored" }
+[[assume (true)]] using namespace H;           // { dg-warning "'assume' 
attribute directive ignored" }
+struct [[assume (true)]] I                     // { dg-error "'assume' 
attribute ignored" }
+{
+  [[assume (true)]];                           // { dg-error "declaration does 
not declare anything" }
+  [[assume (true)]] int i;                     // { dg-error "'assume' 
attribute ignored" }
+  [[assume (true)]] int foo ();                        // { dg-error "'assume' 
attribute ignored" }
+  [[assume (true)]] int bar () { return 1; }   // { dg-error "'assume' 
attribute ignored" }
+  [[assume (true)]] int : 0;                   // { dg-error "'assume' 
attribute ignored" }
+  [[assume (true)]] int i2 : 5;                        // { dg-error "'assume' 
attribute ignored" }
+  [[assume (true)]] static int i3;             // { dg-error "'assume' 
attribute ignored" }
+  static int i4;
+};
+[[assume (true)]] int I::i4 = 0;               // { dg-error "'assume' 
attribute ignored" }
+struct J : [[assume (true)]] C {};             // { dg-warning "attributes on 
base specifiers are ignored" }
+#if __cpp_concepts >= 201907L
+template <typename T>
+concept K [[assume (true)]] = requires { true; };      // { dg-error "'assume' 
attribute ignored" "" { target c++20 } }
+#endif
+typedef int L [[assume (true)]];               // { dg-error "'assume' 
attribute ignored" }
+template <typename T>
+struct M {};
+template <>
+struct [[assume (true)]] M<int> { int m; };    // { dg-error "'assume' 
attribute ignored" }
+typedef int N[2] [[assume (true)]];            // { dg-error "'assume' 
attribute ignored" }
+typedef int O [[assume (true)]] [2];           // { dg-error "'assume' 
attribute ignored" }

Reply via email to