Message ID | ZtmsMAWx8JD9wlEN@tucnak |
---|---|
State | New |
Headers | show |
Series | [RFC] c++: Add alignas further test coverage [PR110345] | expand |
On 9/5/24 9:03 AM, Jakub Jelinek wrote: > Hi! > > I've tried to do the same thing I did for normal standard attributes > also for alignas, but there are way too many cases which are silently > accepted although my reading of: > > "An alignment-specifier may be applied to a variable or to a class data member, > but it shall not be applied to a bit-field, a function parameter, or an > exception-declaration ([except.handle]). > An alignment-specifier may also be applied to the declaration of a class (in > an elaborated-type-specifier ([dcl.type.elab]) or class-head ([class]), > respectively)." > > I've marked the spots where I'd expect some pedwarn with // FIXME. > Clearly we accept it e.g. on bit-fields, exception-declarations, enum > declarations, functions, to e.g. array/reference etc. types, ... > > Is some of this intentional? Allowing it for functions and enums seems consistent with the GNU aligned attribute, I'd complain only when -pedantic. I think we might want to pedwarn about standard attribute syntax appertaining to a type (other than between the class/enum key and name) when !affects_type_identity. But that seems like a separate issue. Does GNU aligned on a bit-field do anything useful? Allowing it on an exception-declaration is a bug, those should be treated the same as parameters. > Though, trying clang trunk, it diagnoses all the // FIXME lines. > > 2024-09-05 Jakub Jelinek <jakub@redhat.com> > > PR c++/110345 > * g++.dg/cpp0x/alignas21.C: New test. > > --- gcc/testsuite/g++.dg/cpp0x/alignas21.C.jj 2024-09-05 14:16:44.366395041 +0200 > +++ gcc/testsuite/g++.dg/cpp0x/alignas21.C 2024-09-05 14:42:42.690465771 +0200 > @@ -0,0 +1,156 @@ > +// 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) > +{ > + alignas (int) int x1; > + alignas ("foobar") int x2; // { dg-error "'alignas' argument has non-integral type 'const char \\\[7\\\]'" } > + alignas (0) int x3; // { dg-warning "requested alignment '0' is not a positive power of 2" } > + alignas ("foo", "bar", "baz") int x4; // { dg-error "'alignas' argument has non-integral type 'const char \\\[4\\\]'" } > + // { dg-error "expected '\\\)' before ',' token" "" { target *-*-* } .-1 } > + // { dg-error "expected declaration before ',' token" "" { target *-*-* } .-2 } > + // { dg-error "expected primary-expression before ',' token" "" { target *-*-* } .-3 } > + alignas (0, 1, 2) int x5; // { dg-error "expected '\\\)' before ',' token" } > + // { dg-error "expected declaration before ',' token" "" { target *-*-* } .-1 } > + // { dg-error "expected primary-expression before ',' token" "" { target *-*-* } .-2 } > + > + auto a = [] alignas (int) () {}; // FIXME > + auto b = [] constexpr alignas (int) {}; // FIXME > + // { 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 alignas (int) {}; // FIXME > + // { dg-error "parameter declaration before lambda exception specification only optional with" "" { target c++20_down } .-1 } > + auto d = [] () alignas (int) {}; // FIXME > + auto e = new int [n] alignas (int); // { dg-warning "attributes ignored on outermost array type in new expression" } > + auto e2 = new int [n] alignas (int) [42]; // { dg-warning "attributes ignored on outermost array type in new expression" } > + auto f = new int [n][42] alignas (int); // FIXME > + alignas (int); // { dg-warning "attributes at the beginning of statement are ignored" } > + alignas (int) {} // { dg-warning "attributes at the beginning of statement are ignored" } > + alignas (int) if (true) {} // { dg-warning "attributes at the beginning of statement are ignored" } > + alignas (int) while (false) {} // { dg-warning "attributes at the beginning of statement are ignored" } > + alignas (int) goto lab; // { dg-warning "attributes at the beginning of statement are ignored" } > + alignas (int) lab:; // { dg-error "alignment may not be specified for 'lab'" } > + alignas (int) try {} catch (int) {} // { dg-warning "attributes at the beginning of statement are ignored" } > + if (alignas (int) int x = 0) {} > + switch (n) > + { > + alignas (int) case 1: // { dg-error "alignment may not be specified for" } > + alignas (int) break; // { dg-warning "attributes at the beginning of statement are ignored" } > + alignas (int) default: // { dg-error "alignment may not be specified for" } > + break; > + } > + for (alignas (int) auto a : arr) {} > + for (alignas (int) auto [a, b] : arr2) {} // { dg-error "structured bindings only available with" "" { target c++14_down } } > + alignas (int) asm (""); // { dg-warning "attributes ignored on 'asm' declaration" } > + try {} catch (alignas (int) int x) {} // FIXME > + try {} catch (alignas (int) int) {} // FIXME > + try {} catch (int alignas (int) x) {} // { dg-warning "attribute ignored" } > + try {} catch (int alignas (int)) {} // { dg-warning "attribute ignored" } > + try {} catch (int x alignas (int)) {} // FIXME > +} > + > +alignas (int) int bar (); // FIXME > +using foobar alignas (int) = int; // FIXME > +alignas (int) int a; > +alignas (int) auto [b, c] = arr; // { dg-error "structured bindings only available with" "" { target c++14_down } } > +alignas (int); // { dg-warning "attribute ignored" } > +inline alignas (int) void baz () {} // { dg-warning "attribute ignored" } > + // { dg-error "standard attributes in middle of decl-specifiers" "" { target *-*-* } .-1 } > +constexpr alignas (int) int qux () { return 0; } // { dg-warning "attribute ignored" } > + // { dg-error "standard attributes in middle of decl-specifiers" "" { target *-*-* } .-1 } > +int alignas (int) d; // { dg-warning "attribute ignored" } > +int const alignas (int) e = 1; // { dg-warning "attribute ignored" } > +struct A {} alignas (int); // { dg-warning "attribute ignored in declaration of 'struct A'" } > +struct A alignas (int); // { dg-warning "attribute ignored" } > +struct A alignas (int) a1; // { dg-warning "attribute ignored" } > +A alignas (int) a2; // { dg-warning "attribute ignored" } > +enum B { B0 } alignas (int); // { dg-warning "attribute ignored in declaration of 'enum B'" } > +enum B alignas (int); // { dg-warning "attribute ignored" } > +enum B alignas (int) b1; // { dg-warning "attribute ignored" } > +B alignas (int) b2; // { dg-warning "attribute ignored" } > +struct alignas (int) C {}; > +int f alignas (int); > +int g[2] alignas (int); // FIXME > +int g2 alignas (int) [2]; > +int corge () alignas (int); // FIXME > +int *alignas (int) h; // FIXME > +int & alignas (int) i = f; // FIXME > +int && alignas (int) j = 0; // FIXME > +int S::* alignas (int) k; // FIXME > +auto l = sizeof (int [2] alignas (int)); // FIXME > +int freddy (alignas (int) int a, // { dg-error "alignment may not be specified for 'a'" } > + alignas (int) int, // { dg-error "alignment may not be specified for '<anonymous>'" } > + alignas (int) int c = 0, // { dg-error "alignment may not be specified for 'c'" } > + alignas (int) int = 0); // { dg-error "alignment may not be specified for '<anonymous>'" } > +void > +corge (alignas (int) int a, // { dg-error "alignment may not be specified for 'a'" } > + alignas (int) int, // { dg-error "alignment may not be specified for '<anonymous>'" } > + alignas (int) int c = 0, // { dg-error "alignment may not be specified for 'c'" } > + alignas (int) int = 0) // { dg-error "alignment may not be specified for '<anonymous>'" } > +{ > +} > +alignas (int) void // FIXME > +garply () > +{ > +} > +int grault (int alignas (int) a, // { dg-warning "attribute ignored" } > + int alignas (int), // { dg-warning "attribute ignored" } > + int alignas (int) c = 0, // { dg-warning "attribute ignored" } > + int alignas (int) = 0); // { dg-warning "attribute ignored" } > +void > +waldo (int alignas (int) a, // { dg-warning "attribute ignored" } > + int alignas (int), // { dg-warning "attribute ignored" } > + int alignas (int) c = 0, // { dg-warning "attribute ignored" } > + int alignas (int) = 0) // { dg-warning "attribute ignored" } > +{ > +} > +int plugh (int a alignas (int), // { dg-error "alignment may not be specified for 'a'" } > + int b alignas (int) = 0); // { dg-error "alignment may not be specified for 'b'" } > +void > +thud (int a alignas (int), // { dg-error "alignment may not be specified for 'a'" } > + int b alignas (int) = 0) // { dg-error "alignment may not be specified for 'b'" } > +{ > +} > +enum alignas (int) D { D0 }; // FIXME > +enum class alignas (int) E { E0 }; // FIXME > +enum F {}; > +enum alignas (int) F; // { dg-warning "type attributes ignored after type is already defined" } > +enum G { > + G0 alignas (int), // { dg-error "alignment may not be specified for 'G0'" } > + G1 alignas (int) = 2 // { dg-error "alignment may not be specified for 'G1'" } > +}; > +namespace alignas (int) H { using H0 = int; } // { dg-error "expected identifier before 'alignas'" } > + // { dg-error "H' does not name a type" "" { target *-*-* } .-1 } > +namespace alignas (int) {} // { dg-error "expected identifier before 'alignas'" } > + // { dg-error "expected unqualified-id before '\\\{' token" "" { target *-*-* } .-1 } > +alignas (int) using namespace H; > + // { dg-error "'H' is not a namespace-name" "" { target *-*-* } .-1 } > +struct alignas (int) I > +{ > + alignas (int); // { dg-error "declaration does not declare anything" } > + alignas (int) int i; > + alignas (int) int foo (); // FIXME > + alignas (int) int bar () { return 1; } // FIXME > + alignas (int) int : 0; // FIXME > + alignas (int) int i2 : 5; // FIXME > + alignas (int) static int i3; > + static int i4; > +}; > +alignas (int) int I::i4 = 0; > +struct J : alignas (int) C {}; // { dg-warning "attributes on base specifiers are ignored" } > +#if __cpp_concepts >= 201907L > +template <typename T> > +concept K alignas (int) = requires { true; }; // { dg-error "alignment may not be specified for 'K'" "" { target c++20 } } > +#endif > +typedef int L alignas (int); > +template <typename T> > +struct M {}; > +template <> > +struct alignas (int) M<int> { int m; }; > +typedef int N[2] alignas (int); // FIXME > +typedef int O alignas (int) [2]; // FIXME > > Jakub >
--- gcc/testsuite/g++.dg/cpp0x/alignas21.C.jj 2024-09-05 14:16:44.366395041 +0200 +++ gcc/testsuite/g++.dg/cpp0x/alignas21.C 2024-09-05 14:42:42.690465771 +0200 @@ -0,0 +1,156 @@ +// 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) +{ + alignas (int) int x1; + alignas ("foobar") int x2; // { dg-error "'alignas' argument has non-integral type 'const char \\\[7\\\]'" } + alignas (0) int x3; // { dg-warning "requested alignment '0' is not a positive power of 2" } + alignas ("foo", "bar", "baz") int x4; // { dg-error "'alignas' argument has non-integral type 'const char \\\[4\\\]'" } + // { dg-error "expected '\\\)' before ',' token" "" { target *-*-* } .-1 } + // { dg-error "expected declaration before ',' token" "" { target *-*-* } .-2 } + // { dg-error "expected primary-expression before ',' token" "" { target *-*-* } .-3 } + alignas (0, 1, 2) int x5; // { dg-error "expected '\\\)' before ',' token" } + // { dg-error "expected declaration before ',' token" "" { target *-*-* } .-1 } + // { dg-error "expected primary-expression before ',' token" "" { target *-*-* } .-2 } + + auto a = [] alignas (int) () {}; // FIXME + auto b = [] constexpr alignas (int) {}; // FIXME + // { 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 alignas (int) {}; // FIXME + // { dg-error "parameter declaration before lambda exception specification only optional with" "" { target c++20_down } .-1 } + auto d = [] () alignas (int) {}; // FIXME + auto e = new int [n] alignas (int); // { dg-warning "attributes ignored on outermost array type in new expression" } + auto e2 = new int [n] alignas (int) [42]; // { dg-warning "attributes ignored on outermost array type in new expression" } + auto f = new int [n][42] alignas (int); // FIXME + alignas (int); // { dg-warning "attributes at the beginning of statement are ignored" } + alignas (int) {} // { dg-warning "attributes at the beginning of statement are ignored" } + alignas (int) if (true) {} // { dg-warning "attributes at the beginning of statement are ignored" } + alignas (int) while (false) {} // { dg-warning "attributes at the beginning of statement are ignored" } + alignas (int) goto lab; // { dg-warning "attributes at the beginning of statement are ignored" } + alignas (int) lab:; // { dg-error "alignment may not be specified for 'lab'" } + alignas (int) try {} catch (int) {} // { dg-warning "attributes at the beginning of statement are ignored" } + if (alignas (int) int x = 0) {} + switch (n) + { + alignas (int) case 1: // { dg-error "alignment may not be specified for" } + alignas (int) break; // { dg-warning "attributes at the beginning of statement are ignored" } + alignas (int) default: // { dg-error "alignment may not be specified for" } + break; + } + for (alignas (int) auto a : arr) {} + for (alignas (int) auto [a, b] : arr2) {} // { dg-error "structured bindings only available with" "" { target c++14_down } } + alignas (int) asm (""); // { dg-warning "attributes ignored on 'asm' declaration" } + try {} catch (alignas (int) int x) {} // FIXME + try {} catch (alignas (int) int) {} // FIXME + try {} catch (int alignas (int) x) {} // { dg-warning "attribute ignored" } + try {} catch (int alignas (int)) {} // { dg-warning "attribute ignored" } + try {} catch (int x alignas (int)) {} // FIXME +} + +alignas (int) int bar (); // FIXME +using foobar alignas (int) = int; // FIXME +alignas (int) int a; +alignas (int) auto [b, c] = arr; // { dg-error "structured bindings only available with" "" { target c++14_down } } +alignas (int); // { dg-warning "attribute ignored" } +inline alignas (int) void baz () {} // { dg-warning "attribute ignored" } + // { dg-error "standard attributes in middle of decl-specifiers" "" { target *-*-* } .-1 } +constexpr alignas (int) int qux () { return 0; } // { dg-warning "attribute ignored" } + // { dg-error "standard attributes in middle of decl-specifiers" "" { target *-*-* } .-1 } +int alignas (int) d; // { dg-warning "attribute ignored" } +int const alignas (int) e = 1; // { dg-warning "attribute ignored" } +struct A {} alignas (int); // { dg-warning "attribute ignored in declaration of 'struct A'" } +struct A alignas (int); // { dg-warning "attribute ignored" } +struct A alignas (int) a1; // { dg-warning "attribute ignored" } +A alignas (int) a2; // { dg-warning "attribute ignored" } +enum B { B0 } alignas (int); // { dg-warning "attribute ignored in declaration of 'enum B'" } +enum B alignas (int); // { dg-warning "attribute ignored" } +enum B alignas (int) b1; // { dg-warning "attribute ignored" } +B alignas (int) b2; // { dg-warning "attribute ignored" } +struct alignas (int) C {}; +int f alignas (int); +int g[2] alignas (int); // FIXME +int g2 alignas (int) [2]; +int corge () alignas (int); // FIXME +int *alignas (int) h; // FIXME +int & alignas (int) i = f; // FIXME +int && alignas (int) j = 0; // FIXME +int S::* alignas (int) k; // FIXME +auto l = sizeof (int [2] alignas (int)); // FIXME +int freddy (alignas (int) int a, // { dg-error "alignment may not be specified for 'a'" } + alignas (int) int, // { dg-error "alignment may not be specified for '<anonymous>'" } + alignas (int) int c = 0, // { dg-error "alignment may not be specified for 'c'" } + alignas (int) int = 0); // { dg-error "alignment may not be specified for '<anonymous>'" } +void +corge (alignas (int) int a, // { dg-error "alignment may not be specified for 'a'" } + alignas (int) int, // { dg-error "alignment may not be specified for '<anonymous>'" } + alignas (int) int c = 0, // { dg-error "alignment may not be specified for 'c'" } + alignas (int) int = 0) // { dg-error "alignment may not be specified for '<anonymous>'" } +{ +} +alignas (int) void // FIXME +garply () +{ +} +int grault (int alignas (int) a, // { dg-warning "attribute ignored" } + int alignas (int), // { dg-warning "attribute ignored" } + int alignas (int) c = 0, // { dg-warning "attribute ignored" } + int alignas (int) = 0); // { dg-warning "attribute ignored" } +void +waldo (int alignas (int) a, // { dg-warning "attribute ignored" } + int alignas (int), // { dg-warning "attribute ignored" } + int alignas (int) c = 0, // { dg-warning "attribute ignored" } + int alignas (int) = 0) // { dg-warning "attribute ignored" } +{ +} +int plugh (int a alignas (int), // { dg-error "alignment may not be specified for 'a'" } + int b alignas (int) = 0); // { dg-error "alignment may not be specified for 'b'" } +void +thud (int a alignas (int), // { dg-error "alignment may not be specified for 'a'" } + int b alignas (int) = 0) // { dg-error "alignment may not be specified for 'b'" } +{ +} +enum alignas (int) D { D0 }; // FIXME +enum class alignas (int) E { E0 }; // FIXME +enum F {}; +enum alignas (int) F; // { dg-warning "type attributes ignored after type is already defined" } +enum G { + G0 alignas (int), // { dg-error "alignment may not be specified for 'G0'" } + G1 alignas (int) = 2 // { dg-error "alignment may not be specified for 'G1'" } +}; +namespace alignas (int) H { using H0 = int; } // { dg-error "expected identifier before 'alignas'" } + // { dg-error "H' does not name a type" "" { target *-*-* } .-1 } +namespace alignas (int) {} // { dg-error "expected identifier before 'alignas'" } + // { dg-error "expected unqualified-id before '\\\{' token" "" { target *-*-* } .-1 } +alignas (int) using namespace H; + // { dg-error "'H' is not a namespace-name" "" { target *-*-* } .-1 } +struct alignas (int) I +{ + alignas (int); // { dg-error "declaration does not declare anything" } + alignas (int) int i; + alignas (int) int foo (); // FIXME + alignas (int) int bar () { return 1; } // FIXME + alignas (int) int : 0; // FIXME + alignas (int) int i2 : 5; // FIXME + alignas (int) static int i3; + static int i4; +}; +alignas (int) int I::i4 = 0; +struct J : alignas (int) C {}; // { dg-warning "attributes on base specifiers are ignored" } +#if __cpp_concepts >= 201907L +template <typename T> +concept K alignas (int) = requires { true; }; // { dg-error "alignment may not be specified for 'K'" "" { target c++20 } } +#endif +typedef int L alignas (int); +template <typename T> +struct M {}; +template <> +struct alignas (int) M<int> { int m; }; +typedef int N[2] alignas (int); // FIXME +typedef int O alignas (int) [2]; // FIXME