mboehme created this revision.
Herald added a project: All.
mboehme requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Before D126061 <https://reviews.llvm.org/D126061>, Clang would warn about this
code
struct X {
[[deprecated]] struct Y {};
};
with the warning
attribute 'deprecated' is ignored, place it after "struct" to apply attribute
to type declaration
D126061 <https://reviews.llvm.org/D126061> inadvertently caused this warning to
no longer be emitted. This patch
restores the previous behavior.
The reason for the bug is that after D126061
<https://reviews.llvm.org/D126061>, C++11 attributes applied to a
member declaration are no longer placed in `DS.getAttributes()` but are instead
tracked in a separate list (`DeclAttrs`). In the case of a free-standing
decl-specifier-seq, we would simply ignore the contents of this list. Instead,
we now pass the list on to `Sema::ParsedFreeStandingDeclSpec()` so that it can
issue the appropriate warning.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D128499
Files:
clang/include/clang/Sema/Sema.h
clang/lib/Parse/ParseDeclCXX.cpp
clang/lib/Parse/ParseTemplate.cpp
clang/lib/Sema/SemaDecl.cpp
clang/test/SemaCXX/attr-declspec-ignored.cpp
Index: clang/test/SemaCXX/attr-declspec-ignored.cpp
===================================================================
--- clang/test/SemaCXX/attr-declspec-ignored.cpp
+++ clang/test/SemaCXX/attr-declspec-ignored.cpp
@@ -9,6 +9,30 @@
// expected-warning{{attribute 'aligned' is ignored, place it after "union" to apply attribute to type declaration}}
__attribute__((visibility("hidden"))) __attribute__((aligned)) enum D {D}; // expected-warning{{attribute 'visibility' is ignored, place it after "enum" to apply attribute to type declaration}} \
// expected-warning{{attribute 'aligned' is ignored, place it after "enum" to apply attribute to type declaration}}
+
+ // Test that we get the same warnings for type declarations nested in a record.
+ struct X {
+ __attribute__((visibility("hidden"))) __attribute__((aligned)) class A; // expected-warning{{attribute 'visibility' is ignored, place it after "class" to apply attribute to type declaration}} \
+ // expected-warning{{attribute 'aligned' is ignored, place it after "class" to apply attribute to type declaration}}
+ __attribute__((visibility("hidden"))) __attribute__((aligned)) struct B; // expected-warning{{attribute 'visibility' is ignored, place it after "struct" to apply attribute to type declaration}} \
+ // expected-warning{{attribute 'aligned' is ignored, place it after "struct" to apply attribute to type declaration}}
+ __attribute__((visibility("hidden"))) __attribute__((aligned)) union C; // expected-warning{{attribute 'visibility' is ignored, place it after "union" to apply attribute to type declaration}} \
+ // expected-warning{{attribute 'aligned' is ignored, place it after "union" to apply attribute to type declaration}}
+ __attribute__((visibility("hidden"))) __attribute__((aligned)) enum D {D}; // expected-warning{{attribute 'visibility' is ignored, place it after "enum" to apply attribute to type declaration}} \
+ // expected-warning{{attribute 'aligned' is ignored, place it after "enum" to apply attribute to type declaration}}
+
+ // Also test [[]] attribute syntax. (On a non-nested declaration, these
+ // generate a hard "misplaced attributes" error, which we test for
+ // elsewhere.)
+ [[gnu::visibility("hidden")]] [[gnu::aligned]] class E; // expected-warning{{attribute 'visibility' is ignored, place it after "class" to apply attribute to type declaration}} \
+ // expected-warning{{attribute 'aligned' is ignored, place it after "class" to apply attribute to type declaration}}
+ [[gnu::visibility("hidden")]] [[gnu::aligned]] struct F; // expected-warning{{attribute 'visibility' is ignored, place it after "struct" to apply attribute to type declaration}} \
+ // expected-warning{{attribute 'aligned' is ignored, place it after "struct" to apply attribute to type declaration}}
+ [[gnu::visibility("hidden")]] [[gnu::aligned]] union G; // expected-warning{{attribute 'visibility' is ignored, place it after "union" to apply attribute to type declaration}} \
+ // expected-warning{{attribute 'aligned' is ignored, place it after "union" to apply attribute to type declaration}}
+ [[gnu::visibility("hidden")]] [[gnu::aligned]] enum H {H}; // expected-warning{{attribute 'visibility' is ignored, place it after "enum" to apply attribute to type declaration}} \
+ // expected-warning{{attribute 'aligned' is ignored, place it after "enum" to apply attribute to type declaration}}
+ };
}
namespace test2 {
@@ -16,4 +40,16 @@
__attribute__((visibility("hidden"))) __attribute__((aligned)) struct B {} b;
__attribute__((visibility("hidden"))) __attribute__((aligned)) union C {} c;
__attribute__((visibility("hidden"))) __attribute__((aligned)) enum D {D} d;
+
+ struct X {
+ __attribute__((visibility("hidden"))) __attribute__((aligned)) class A {} a;
+ __attribute__((visibility("hidden"))) __attribute__((aligned)) struct B {} b;
+ __attribute__((visibility("hidden"))) __attribute__((aligned)) union C {} c;
+ __attribute__((visibility("hidden"))) __attribute__((aligned)) enum D {D} d;
+
+ [[gnu::visibility("hidden")]] [[gnu::aligned]] class E {} e;
+ [[gnu::visibility("hidden")]] [[gnu::aligned]] struct F {} f;
+ [[gnu::visibility("hidden")]] [[gnu::aligned]] union G {} g;
+ [[gnu::visibility("hidden")]] [[gnu::aligned]] enum H {H} h;
+ };
}
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -4632,7 +4632,8 @@
Decl *
Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
RecordDecl *&AnonRecord) {
- return ParsedFreeStandingDeclSpec(S, AS, DS, MultiTemplateParamsArg(), false,
+ return ParsedFreeStandingDeclSpec(S, AS, DS, ParsedAttributesView::none(),
+ MultiTemplateParamsArg(), false,
AnonRecord);
}
@@ -4846,11 +4847,12 @@
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
/// no declarator (e.g. "struct foo;") is parsed. It also accepts template
/// parameters to cope with template friend declarations.
-Decl *
-Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
- MultiTemplateParamsArg TemplateParams,
- bool IsExplicitInstantiation,
- RecordDecl *&AnonRecord) {
+Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
+ DeclSpec &DS,
+ const ParsedAttributesView &DeclAttrs,
+ MultiTemplateParamsArg TemplateParams,
+ bool IsExplicitInstantiation,
+ RecordDecl *&AnonRecord) {
Decl *TagD = nullptr;
TagDecl *Tag = nullptr;
if (DS.getTypeSpecType() == DeclSpec::TST_class ||
@@ -5089,7 +5091,7 @@
// Warn about ignored type attributes, for example:
// __attribute__((aligned)) struct A;
// Attributes should be placed after tag to apply to type declaration.
- if (!DS.getAttributes().empty()) {
+ if (!DS.getAttributes().empty() || !DeclAttrs.empty()) {
DeclSpec::TST TypeSpecType = DS.getTypeSpecType();
if (TypeSpecType == DeclSpec::TST_class ||
TypeSpecType == DeclSpec::TST_struct ||
@@ -5099,6 +5101,9 @@
for (const ParsedAttr &AL : DS.getAttributes())
Diag(AL.getLoc(), diag::warn_declspec_attribute_ignored)
<< AL << GetDiagnosticTypeSpecifierID(TypeSpecType);
+ for (const ParsedAttr &AL : DeclAttrs)
+ Diag(AL.getLoc(), diag::warn_declspec_attribute_ignored)
+ << AL << GetDiagnosticTypeSpecifierID(TypeSpecType);
}
}
Index: clang/lib/Parse/ParseTemplate.cpp
===================================================================
--- clang/lib/Parse/ParseTemplate.cpp
+++ clang/lib/Parse/ParseTemplate.cpp
@@ -231,7 +231,7 @@
DeclEnd = ConsumeToken();
RecordDecl *AnonRecord = nullptr;
Decl *Decl = Actions.ParsedFreeStandingDeclSpec(
- getCurScope(), AS, DS,
+ getCurScope(), AS, DS, ParsedAttributesView::none(),
TemplateInfo.TemplateParams ? *TemplateInfo.TemplateParams
: MultiTemplateParamsArg(),
TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation,
Index: clang/lib/Parse/ParseDeclCXX.cpp
===================================================================
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -2766,7 +2766,7 @@
RecordDecl *AnonRecord = nullptr;
Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(
- getCurScope(), AS, DS, TemplateParams, false, AnonRecord);
+ getCurScope(), AS, DS, DeclAttrs, TemplateParams, false, AnonRecord);
DS.complete(TheDecl);
if (AnonRecord) {
Decl* decls[] = {AnonRecord, TheDecl};
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -3112,6 +3112,7 @@
Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
RecordDecl *&AnonRecord);
Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
+ const ParsedAttributesView &DeclAttrs,
MultiTemplateParamsArg TemplateParams,
bool IsExplicitInstantiation,
RecordDecl *&AnonRecord);
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits