Skip to content

Commit 8686610

Browse files
committed
[Clang] Fix: Restore warning inadvertently removed by D126061.
Before 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 inadvertently caused this warning to no longer be emitted. This patch restores the previous behavior. The reason for the bug is that after 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. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D128499
1 parent 527ef8c commit 8686610

File tree

7 files changed

+63
-20
lines changed

7 files changed

+63
-20
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3117,8 +3117,10 @@ class Sema final {
31173117
void ActOnTranslationUnitScope(Scope *S);
31183118

31193119
Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
3120+
const ParsedAttributesView &DeclAttrs,
31203121
RecordDecl *&AnonRecord);
31213122
Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
3123+
const ParsedAttributesView &DeclAttrs,
31223124
MultiTemplateParamsArg TemplateParams,
31233125
bool IsExplicitInstantiation,
31243126
RecordDecl *&AnonRecord);

clang/lib/Parse/ParseDecl.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1863,8 +1863,8 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(
18631863
DeclEnd = Tok.getLocation();
18641864
if (RequireSemi) ConsumeToken();
18651865
RecordDecl *AnonRecord = nullptr;
1866-
Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none,
1867-
DS, AnonRecord);
1866+
Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(
1867+
getCurScope(), AS_none, DS, ParsedAttributesView::none(), AnonRecord);
18681868
DS.complete(TheDecl);
18691869
if (AnonRecord) {
18701870
Decl* decls[] = {AnonRecord, TheDecl};
@@ -4358,8 +4358,8 @@ void Parser::ParseStructDeclaration(
43584358
// declarator list is omitted."
43594359
ProhibitAttributes(Attrs);
43604360
RecordDecl *AnonRecord = nullptr;
4361-
Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none,
4362-
DS, AnonRecord);
4361+
Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(
4362+
getCurScope(), AS_none, DS, ParsedAttributesView::none(), AnonRecord);
43634363
assert(!AnonRecord && "Did not expect anonymous struct or union here");
43644364
DS.complete(TheDecl);
43654365
return;

clang/lib/Parse/ParseDeclCXX.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2766,7 +2766,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
27662766

27672767
RecordDecl *AnonRecord = nullptr;
27682768
Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(
2769-
getCurScope(), AS, DS, TemplateParams, false, AnonRecord);
2769+
getCurScope(), AS, DS, DeclAttrs, TemplateParams, false, AnonRecord);
27702770
DS.complete(TheDecl);
27712771
if (AnonRecord) {
27722772
Decl* decls[] = {AnonRecord, TheDecl};

clang/lib/Parse/ParseTemplate.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ Decl *Parser::ParseSingleDeclarationAfterTemplate(
231231
DeclEnd = ConsumeToken();
232232
RecordDecl *AnonRecord = nullptr;
233233
Decl *Decl = Actions.ParsedFreeStandingDeclSpec(
234-
getCurScope(), AS, DS,
234+
getCurScope(), AS, DS, ParsedAttributesView::none(),
235235
TemplateInfo.TemplateParams ? *TemplateInfo.TemplateParams
236236
: MultiTemplateParamsArg(),
237237
TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation,

clang/lib/Parse/Parser.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,8 +1113,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclOrFunctionDefInternal(
11131113
ProhibitAttributes(Attrs, CorrectLocationForAttributes);
11141114
ConsumeToken();
11151115
RecordDecl *AnonRecord = nullptr;
1116-
Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none,
1117-
DS, AnonRecord);
1116+
Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(
1117+
getCurScope(), AS_none, DS, ParsedAttributesView::none(), AnonRecord);
11181118
DS.complete(TheDecl);
11191119
if (AnonRecord) {
11201120
Decl* decls[] = {AnonRecord, TheDecl};

clang/lib/Sema/SemaDecl.cpp

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4629,11 +4629,12 @@ bool Sema::checkVarDeclRedefinition(VarDecl *Old, VarDecl *New) {
46294629

46304630
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
46314631
/// no declarator (e.g. "struct foo;") is parsed.
4632-
Decl *
4633-
Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
4634-
RecordDecl *&AnonRecord) {
4635-
return ParsedFreeStandingDeclSpec(S, AS, DS, MultiTemplateParamsArg(), false,
4636-
AnonRecord);
4632+
Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
4633+
DeclSpec &DS,
4634+
const ParsedAttributesView &DeclAttrs,
4635+
RecordDecl *&AnonRecord) {
4636+
return ParsedFreeStandingDeclSpec(
4637+
S, AS, DS, DeclAttrs, MultiTemplateParamsArg(), false, AnonRecord);
46374638
}
46384639

46394640
// The MS ABI changed between VS2013 and VS2015 with regard to numbers used to
@@ -4846,11 +4847,12 @@ static unsigned GetDiagnosticTypeSpecifierID(DeclSpec::TST T) {
48464847
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
48474848
/// no declarator (e.g. "struct foo;") is parsed. It also accepts template
48484849
/// parameters to cope with template friend declarations.
4849-
Decl *
4850-
Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
4851-
MultiTemplateParamsArg TemplateParams,
4852-
bool IsExplicitInstantiation,
4853-
RecordDecl *&AnonRecord) {
4850+
Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
4851+
DeclSpec &DS,
4852+
const ParsedAttributesView &DeclAttrs,
4853+
MultiTemplateParamsArg TemplateParams,
4854+
bool IsExplicitInstantiation,
4855+
RecordDecl *&AnonRecord) {
48544856
Decl *TagD = nullptr;
48554857
TagDecl *Tag = nullptr;
48564858
if (DS.getTypeSpecType() == DeclSpec::TST_class ||
@@ -5089,7 +5091,7 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
50895091
// Warn about ignored type attributes, for example:
50905092
// __attribute__((aligned)) struct A;
50915093
// Attributes should be placed after tag to apply to type declaration.
5092-
if (!DS.getAttributes().empty()) {
5094+
if (!DS.getAttributes().empty() || !DeclAttrs.empty()) {
50935095
DeclSpec::TST TypeSpecType = DS.getTypeSpecType();
50945096
if (TypeSpecType == DeclSpec::TST_class ||
50955097
TypeSpecType == DeclSpec::TST_struct ||
@@ -5099,6 +5101,9 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
50995101
for (const ParsedAttr &AL : DS.getAttributes())
51005102
Diag(AL.getLoc(), diag::warn_declspec_attribute_ignored)
51015103
<< AL << GetDiagnosticTypeSpecifierID(TypeSpecType);
5104+
for (const ParsedAttr &AL : DeclAttrs)
5105+
Diag(AL.getLoc(), diag::warn_declspec_attribute_ignored)
5106+
<< AL << GetDiagnosticTypeSpecifierID(TypeSpecType);
51025107
}
51035108
}
51045109

clang/test/SemaCXX/attr-declspec-ignored.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,50 @@ namespace test1 {
66
__attribute__((visibility("hidden"))) __attribute__((aligned)) struct B; // expected-warning{{attribute 'visibility' is ignored, place it after "struct" to apply attribute to type declaration}} \
77
// expected-warning{{attribute 'aligned' is ignored, place it after "struct" to apply attribute to type declaration}}
88
__attribute__((visibility("hidden"))) __attribute__((aligned)) union C; // expected-warning{{attribute 'visibility' is ignored, place it after "union" to apply attribute to type declaration}} \
9-
// expected-warning{{attribute 'aligned' is ignored, place it after "union" to apply attribute to type declaration}}
9+
// expected-warning{{attribute 'aligned' is ignored, place it after "union" to apply attribute to type declaration}}
1010
__attribute__((visibility("hidden"))) __attribute__((aligned)) enum D {D}; // expected-warning{{attribute 'visibility' is ignored, place it after "enum" to apply attribute to type declaration}} \
1111
// expected-warning{{attribute 'aligned' is ignored, place it after "enum" to apply attribute to type declaration}}
12+
13+
// Test that we get the same warnings for type declarations nested in a record.
14+
struct X {
15+
__attribute__((visibility("hidden"))) __attribute__((aligned)) class A; // expected-warning{{attribute 'visibility' is ignored, place it after "class" to apply attribute to type declaration}} \
16+
// expected-warning{{attribute 'aligned' is ignored, place it after "class" to apply attribute to type declaration}}
17+
__attribute__((visibility("hidden"))) __attribute__((aligned)) struct B; // expected-warning{{attribute 'visibility' is ignored, place it after "struct" to apply attribute to type declaration}} \
18+
// expected-warning{{attribute 'aligned' is ignored, place it after "struct" to apply attribute to type declaration}}
19+
__attribute__((visibility("hidden"))) __attribute__((aligned)) union C; // expected-warning{{attribute 'visibility' is ignored, place it after "union" to apply attribute to type declaration}} \
20+
// expected-warning{{attribute 'aligned' is ignored, place it after "union" to apply attribute to type declaration}}
21+
__attribute__((visibility("hidden"))) __attribute__((aligned)) enum D {D}; // expected-warning{{attribute 'visibility' is ignored, place it after "enum" to apply attribute to type declaration}} \
22+
// expected-warning{{attribute 'aligned' is ignored, place it after "enum" to apply attribute to type declaration}}
23+
24+
// Also test [[]] attribute syntax. (On a non-nested declaration, these
25+
// generate a hard "misplaced attributes" error, which we test for
26+
// elsewhere.)
27+
[[gnu::visibility("hidden")]] [[gnu::aligned]] class E; // expected-warning{{attribute 'visibility' is ignored, place it after "class" to apply attribute to type declaration}} \
28+
// expected-warning{{attribute 'aligned' is ignored, place it after "class" to apply attribute to type declaration}}
29+
[[gnu::visibility("hidden")]] [[gnu::aligned]] struct F; // expected-warning{{attribute 'visibility' is ignored, place it after "struct" to apply attribute to type declaration}} \
30+
// expected-warning{{attribute 'aligned' is ignored, place it after "struct" to apply attribute to type declaration}}
31+
[[gnu::visibility("hidden")]] [[gnu::aligned]] union G; // expected-warning{{attribute 'visibility' is ignored, place it after "union" to apply attribute to type declaration}} \
32+
// expected-warning{{attribute 'aligned' is ignored, place it after "union" to apply attribute to type declaration}}
33+
[[gnu::visibility("hidden")]] [[gnu::aligned]] enum H {H}; // expected-warning{{attribute 'visibility' is ignored, place it after "enum" to apply attribute to type declaration}} \
34+
// expected-warning{{attribute 'aligned' is ignored, place it after "enum" to apply attribute to type declaration}}
35+
};
1236
}
1337

1438
namespace test2 {
1539
__attribute__((visibility("hidden"))) __attribute__((aligned)) class A {} a;
1640
__attribute__((visibility("hidden"))) __attribute__((aligned)) struct B {} b;
1741
__attribute__((visibility("hidden"))) __attribute__((aligned)) union C {} c;
1842
__attribute__((visibility("hidden"))) __attribute__((aligned)) enum D {D} d;
43+
44+
struct X {
45+
__attribute__((visibility("hidden"))) __attribute__((aligned)) class A {} a;
46+
__attribute__((visibility("hidden"))) __attribute__((aligned)) struct B {} b;
47+
__attribute__((visibility("hidden"))) __attribute__((aligned)) union C {} c;
48+
__attribute__((visibility("hidden"))) __attribute__((aligned)) enum D {D} d;
49+
50+
[[gnu::visibility("hidden")]] [[gnu::aligned]] class E {} e;
51+
[[gnu::visibility("hidden")]] [[gnu::aligned]] struct F {} f;
52+
[[gnu::visibility("hidden")]] [[gnu::aligned]] union G {} g;
53+
[[gnu::visibility("hidden")]] [[gnu::aligned]] enum H {H} h;
54+
};
1955
}

0 commit comments

Comments
 (0)