[clang] 8686610 - [Clang] Fix: Restore warning inadvertently removed by D126061.

Martin Boehme via cfe-commits cfe-commits at lists.llvm.org
Mon Jun 27 23:53:06 PDT 2022


Author: Martin Boehme
Date: 2022-06-28T08:52:58+02:00
New Revision: 86866107b89c0515d197ec70292ce776bce5a04b

URL: https://github.com/llvm/llvm-project/commit/86866107b89c0515d197ec70292ce776bce5a04b
DIFF: https://github.com/llvm/llvm-project/commit/86866107b89c0515d197ec70292ce776bce5a04b.diff

LOG: [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

Added: 
    

Modified: 
    clang/include/clang/Sema/Sema.h
    clang/lib/Parse/ParseDecl.cpp
    clang/lib/Parse/ParseDeclCXX.cpp
    clang/lib/Parse/ParseTemplate.cpp
    clang/lib/Parse/Parser.cpp
    clang/lib/Sema/SemaDecl.cpp
    clang/test/SemaCXX/attr-declspec-ignored.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 8b8b1b2e2e864..6434435567e19 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3117,8 +3117,10 @@ class Sema final {
   void ActOnTranslationUnitScope(Scope *S);
 
   Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
+                                   const ParsedAttributesView &DeclAttrs,
                                    RecordDecl *&AnonRecord);
   Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
+                                   const ParsedAttributesView &DeclAttrs,
                                    MultiTemplateParamsArg TemplateParams,
                                    bool IsExplicitInstantiation,
                                    RecordDecl *&AnonRecord);

diff  --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index a90d5d9cc4856..cc0a0bb54a030 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -1863,8 +1863,8 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(
     DeclEnd = Tok.getLocation();
     if (RequireSemi) ConsumeToken();
     RecordDecl *AnonRecord = nullptr;
-    Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none,
-                                                       DS, AnonRecord);
+    Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(
+        getCurScope(), AS_none, DS, ParsedAttributesView::none(), AnonRecord);
     DS.complete(TheDecl);
     if (AnonRecord) {
       Decl* decls[] = {AnonRecord, TheDecl};
@@ -4358,8 +4358,8 @@ void Parser::ParseStructDeclaration(
     // declarator list is omitted."
     ProhibitAttributes(Attrs);
     RecordDecl *AnonRecord = nullptr;
-    Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none,
-                                                       DS, AnonRecord);
+    Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(
+        getCurScope(), AS_none, DS, ParsedAttributesView::none(), AnonRecord);
     assert(!AnonRecord && "Did not expect anonymous struct or union here");
     DS.complete(TheDecl);
     return;

diff  --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 8b55b4c57aa65..143b373e9ea54 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -2766,7 +2766,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
 
     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};

diff  --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index 97be8115989e2..e32ea6003b84e 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -231,7 +231,7 @@ Decl *Parser::ParseSingleDeclarationAfterTemplate(
     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,

diff  --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 7fad3b2388ce3..b2bacc7a5d89b 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -1113,8 +1113,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclOrFunctionDefInternal(
     ProhibitAttributes(Attrs, CorrectLocationForAttributes);
     ConsumeToken();
     RecordDecl *AnonRecord = nullptr;
-    Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none,
-                                                       DS, AnonRecord);
+    Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(
+        getCurScope(), AS_none, DS, ParsedAttributesView::none(), AnonRecord);
     DS.complete(TheDecl);
     if (AnonRecord) {
       Decl* decls[] = {AnonRecord, TheDecl};

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index da138bc8eb85e..44f04d38d57e9 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -4629,11 +4629,12 @@ bool Sema::checkVarDeclRedefinition(VarDecl *Old, VarDecl *New) {
 
 /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
 /// no declarator (e.g. "struct foo;") is parsed.
-Decl *
-Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
-                                 RecordDecl *&AnonRecord) {
-  return ParsedFreeStandingDeclSpec(S, AS, DS, MultiTemplateParamsArg(), false,
-                                    AnonRecord);
+Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
+                                       DeclSpec &DS,
+                                       const ParsedAttributesView &DeclAttrs,
+                                       RecordDecl *&AnonRecord) {
+  return ParsedFreeStandingDeclSpec(
+      S, AS, DS, DeclAttrs, MultiTemplateParamsArg(), false, AnonRecord);
 }
 
 // The MS ABI changed between VS2013 and VS2015 with regard to numbers used to
@@ -4846,11 +4847,12 @@ static unsigned GetDiagnosticTypeSpecifierID(DeclSpec::TST T) {
 /// 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 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
   // 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 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
       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);
     }
   }
 

diff  --git a/clang/test/SemaCXX/attr-declspec-ignored.cpp b/clang/test/SemaCXX/attr-declspec-ignored.cpp
index 0503750da1606..f46e3910c56d7 100644
--- a/clang/test/SemaCXX/attr-declspec-ignored.cpp
+++ b/clang/test/SemaCXX/attr-declspec-ignored.cpp
@@ -6,9 +6,33 @@ namespace test1 {
   __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}} 
+  // 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 @@ namespace test2 {
   __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;
+  };
 }


        


More information about the cfe-commits mailing list