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
^^^^^^^^^^^^^^^^^^^^^^^^
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">;
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">,
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<
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;
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.
// 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)
//
// 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;
}
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);
}
}
// 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 {
// 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.)
// 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}}
};
}
__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;
};
}