Fix the diagnostic about attribute placement for scoped enumerations
authoripriyanshi1708 <priyanshiagarwal1708@gmail.com>
Wed, 26 Apr 2023 19:18:40 +0000 (15:18 -0400)
committerAaron Ballman <aaron@aaronballman.com>
Wed, 26 Apr 2023 19:18:40 +0000 (15:18 -0400)
Fixed the error message for attribute placement. Earlier it was showing
'place it after "enum"' but it should be 'place it after "enum class"'
which I have fixed in this patch.

Fixes https://github.com/llvm/llvm-project/issues/61660
Differential Revision: https://reviews.llvm.org/D147989

clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaDecl.cpp
clang/test/SemaCXX/attr-declspec-ignored.cpp

index 7dfca82..8606f14 100644 (file)
@@ -331,6 +331,8 @@ Bug Fixes to Compiler Builtins
 
 Bug Fixes to Attribute Support
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+- Fixed a bug where attribute annotations on type specifiers (enums, classes, structs, unions, and scoped enums) were not properly ignored, resulting in misleading warning messages. Now, such attribute annotations are correctly ignored.
+(`#61660 <https://github.com/llvm/llvm-project/issues/61660>`_)
 
 Bug Fixes to C++ Support
 ^^^^^^^^^^^^^^^^^^^^^^^^
index 18a0154..9080d07 100644 (file)
@@ -2666,7 +2666,7 @@ def err_invalid_constexpr : Error<
 def err_invalid_constexpr_member : Error<"non-static data member cannot be "
   "constexpr%select{; did you intend to make it %select{const|static}0?|}1">;
 def err_constexpr_tag : Error<
-  "%select{class|struct|interface|union|enum}0 "
+  "%select{class|struct|interface|union|enum|enum class|enum struct}0 "
   "cannot be marked %sub{select_constexpr_spec_kind}1">;
 def err_constexpr_dtor : Error<
   "destructor cannot be declared %sub{select_constexpr_spec_kind}0">;
@@ -3423,7 +3423,7 @@ def warn_type_attribute_deprecated_on_decl : Warning<
   InGroup<DeprecatedAttributes>;
 def warn_declspec_attribute_ignored : Warning<
   "attribute %0 is ignored, place it after "
-  "\"%select{class|struct|interface|union|enum}1\" to apply attribute to "
+  "\"%select{class|struct|interface|union|enum|enum class|enum struct}1\" to apply attribute to "
   "type declaration">, InGroup<IgnoredAttributes>;
 def warn_attribute_precede_definition : Warning<
   "attribute declaration must precede definition">,
@@ -6928,7 +6928,7 @@ def warn_standalone_specifier : Warning<"'%0' ignored on this declaration">,
 def ext_standalone_specifier : ExtWarn<"'%0' is not permitted on a declaration "
   "of a type">, InGroup<MissingDeclarations>;
 def err_standalone_class_nested_name_specifier : Error<
-  "forward declaration of %select{class|struct|interface|union|enum}0 cannot "
+  "forward declaration of %select{class|struct|interface|union|enum|enum class|enum struct}0 cannot "
   "have a nested name specifier">;
 def err_typecheck_sclass_func : Error<"illegal storage class on function">;
 def err_static_block_func : Error<
index 719215d..4cdf298 100644 (file)
@@ -5033,7 +5033,8 @@ void Sema::setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec,
   TagFromDeclSpec->setTypedefNameForAnonDecl(NewTD);
 }
 
-static unsigned GetDiagnosticTypeSpecifierID(DeclSpec::TST T) {
+static unsigned GetDiagnosticTypeSpecifierID(const DeclSpec &DS) {
+  DeclSpec::TST T = DS.getTypeSpecType();
   switch (T) {
   case DeclSpec::TST_class:
     return 0;
@@ -5044,12 +5045,17 @@ static unsigned GetDiagnosticTypeSpecifierID(DeclSpec::TST T) {
   case DeclSpec::TST_union:
     return 3;
   case DeclSpec::TST_enum:
+    if (const auto *ED = dyn_cast<EnumDecl>(DS.getRepAsDecl())) {
+      if (ED->isScopedUsingClassTag())
+        return 5;
+      if (ED->isScoped())
+        return 6;
+    }
     return 4;
   default:
     llvm_unreachable("unexpected type specifier");
   }
 }
-
 /// 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.
@@ -5107,7 +5113,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
     // the declaration of a function or function template
     if (Tag)
       Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_tag)
-          << GetDiagnosticTypeSpecifierID(DS.getTypeSpecType())
+          << GetDiagnosticTypeSpecifierID(DS)
           << static_cast<int>(DS.getConstexprSpecifier());
     else
       Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_wrong_decl_kind)
@@ -5141,7 +5147,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
     //
     // Per C++ [dcl.enum]p1, an opaque-enum-declaration can't either.
     Diag(SS.getBeginLoc(), diag::err_standalone_class_nested_name_specifier)
-        << GetDiagnosticTypeSpecifierID(DS.getTypeSpecType()) << SS.getRange();
+        << GetDiagnosticTypeSpecifierID(DS) << SS.getRange();
     return nullptr;
   }
 
@@ -5306,10 +5312,10 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
         TypeSpecType == DeclSpec::TST_enum) {
       for (const ParsedAttr &AL : DS.getAttributes())
         Diag(AL.getLoc(), diag::warn_declspec_attribute_ignored)
-            << AL << GetDiagnosticTypeSpecifierID(TypeSpecType);
+            << AL << GetDiagnosticTypeSpecifierID(DS);
       for (const ParsedAttr &AL : DeclAttrs)
         Diag(AL.getLoc(), diag::warn_declspec_attribute_ignored)
-            << AL << GetDiagnosticTypeSpecifierID(TypeSpecType);
+            << AL << GetDiagnosticTypeSpecifierID(DS);
     }
   }
 
index f46e391..dfea8cc 100644 (file)
@@ -9,6 +9,10 @@ namespace test1 {
   // 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}}
+  __attribute__((visibility("hidden")))  __attribute__((aligned)) enum class EC {}; // expected-warning{{attribute 'visibility' is ignored, place it after "enum class" to apply attribute to type declaration}} \
+  // expected-warning{{attribute 'aligned' is ignored, place it after "enum class" to apply attribute to type declaration}}
+  __attribute__((visibility("hidden")))  __attribute__((aligned)) enum struct ES {}; // expected-warning{{attribute 'visibility' is ignored, place it after "enum struct" to apply attribute to type declaration}} \
+  // expected-warning{{attribute 'aligned' is ignored, place it after "enum struct" to apply attribute to type declaration}}
 
   // Test that we get the same warnings for type declarations nested in a record.
   struct X {
@@ -20,7 +24,11 @@ namespace test1 {
     // 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}}
-
+    __attribute__((visibility("hidden")))  __attribute__((aligned)) enum class EC {}; // expected-warning{{attribute 'visibility' is ignored, place it after "enum class" to apply attribute to type declaration}} \
+    // expected-warning{{attribute 'aligned' is ignored, place it after "enum class" to apply attribute to type declaration}}
+    __attribute__((visibility("hidden")))  __attribute__((aligned)) enum struct ES {}; // expected-warning{{attribute 'visibility' is ignored, place it after "enum struct" to apply attribute to type declaration}} \
+    // expected-warning{{attribute 'aligned' is ignored, place it after "enum struct" 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.)
@@ -32,6 +40,10 @@ namespace test1 {
     // 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}}
+    [[gnu::visibility("hidden")]]  [[gnu::aligned]] enum class I {}; // expected-warning{{attribute 'visibility' is ignored, place it after "enum class" to apply attribute to type declaration}} \
+    // expected-warning{{attribute 'aligned' is ignored, place it after "enum class" to apply attribute to type declaration}}
+    [[gnu::visibility("hidden")]]  [[gnu::aligned]] enum struct J {}; // expected-warning{{attribute 'visibility' is ignored, place it after "enum struct" to apply attribute to type declaration}} \
+    // expected-warning{{attribute 'aligned' is ignored, place it after "enum struct" to apply attribute to type declaration}}
   };
 }
 
@@ -40,16 +52,22 @@ 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;
+  __attribute__((visibility("hidden")))  __attribute__((aligned)) enum class EC {} ec;
+  __attribute__((visibility("hidden")))  __attribute__((aligned)) enum struct ES {} es;
 
   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;
+    __attribute__((visibility("hidden")))  __attribute__((aligned)) enum class EC {} ec;
+    __attribute__((visibility("hidden")))  __attribute__((aligned)) enum struct ES {} es;
 
     [[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;
+    [[gnu::visibility("hidden")]]  [[gnu::aligned]] enum class I {} i;
+    [[gnu::visibility("hidden")]]  [[gnu::aligned]] enum struct J {} j;
   };
 }