From b893368fd4fdf40b7778df8d0b17312def1a8156 Mon Sep 17 00:00:00 2001 From: ipriyanshi1708 Date: Wed, 26 Apr 2023 15:18:40 -0400 Subject: [PATCH] Fix the diagnostic about attribute placement for scoped enumerations 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 | 2 ++ clang/include/clang/Basic/DiagnosticSemaKinds.td | 6 +++--- clang/lib/Sema/SemaDecl.cpp | 18 ++++++++++++------ clang/test/SemaCXX/attr-declspec-ignored.cpp | 20 +++++++++++++++++++- 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 7dfca82..8606f147 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -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 `_) Bug Fixes to C++ Support ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 18a0154..9080d07 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -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; 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; 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; 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< diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 719215d..4cdf298 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -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(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(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); } } diff --git a/clang/test/SemaCXX/attr-declspec-ignored.cpp b/clang/test/SemaCXX/attr-declspec-ignored.cpp index f46e391..dfea8cc 100644 --- a/clang/test/SemaCXX/attr-declspec-ignored.cpp +++ b/clang/test/SemaCXX/attr-declspec-ignored.cpp @@ -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; }; } -- 2.7.4