mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-25 19:26:06 +00:00
Add a fixit for attributes incorrectly placed prior to 'struct/class/enum' keyword.
Suggest moving the following erroneous attrib list (based on location) [[]] struct X; to struct [[]] X; Additionally, added a fixme for the current implementation that diagnoses misplaced attributes to consider using the newly introduced diagnostic (that I think is more user-friendly). llvm-svn: 321449
This commit is contained in:
parent
99bbb213b5
commit
c5089c08d4
@ -587,6 +587,7 @@ def ext_using_attribute_ns : ExtWarn<
|
||||
def err_using_attribute_ns_conflict : Error<
|
||||
"attribute with scope specifier cannot follow default scope specifier">;
|
||||
def err_attributes_not_allowed : Error<"an attribute list cannot appear here">;
|
||||
def err_attributes_misplaced : Error<"misplaced attributes; expected attributes here">;
|
||||
def err_l_square_l_square_not_attribute : Error<
|
||||
"C++11 only allows consecutive left square brackets when "
|
||||
"introducing an attribute">;
|
||||
|
@ -2200,13 +2200,16 @@ private:
|
||||
|
||||
void stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs,
|
||||
DeclSpec &DS, Sema::TagUseKind TUK);
|
||||
|
||||
void ProhibitAttributes(ParsedAttributesWithRange &attrs) {
|
||||
|
||||
// FixItLoc = possible correct location for the attributes
|
||||
void ProhibitAttributes(ParsedAttributesWithRange &attrs,
|
||||
SourceLocation FixItLoc = SourceLocation()) {
|
||||
if (!attrs.Range.isValid()) return;
|
||||
DiagnoseProhibitedAttributes(attrs);
|
||||
DiagnoseProhibitedAttributes(attrs, FixItLoc);
|
||||
attrs.clear();
|
||||
}
|
||||
void DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs);
|
||||
void DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs,
|
||||
SourceLocation FixItLoc);
|
||||
|
||||
// Forbid C++11 and C2x attributes that appear on certain syntactic locations
|
||||
// which standard permits but we don't supported yet, for example, attributes
|
||||
|
@ -1548,15 +1548,21 @@ void Parser::DiagnoseMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs,
|
||||
SourceLocation Loc = Tok.getLocation();
|
||||
ParseCXX11Attributes(Attrs);
|
||||
CharSourceRange AttrRange(SourceRange(Loc, Attrs.Range.getEnd()), true);
|
||||
|
||||
// FIXME: use err_attributes_misplaced
|
||||
Diag(Loc, diag::err_attributes_not_allowed)
|
||||
<< FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange)
|
||||
<< FixItHint::CreateRemoval(AttrRange);
|
||||
}
|
||||
|
||||
void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) {
|
||||
Diag(attrs.Range.getBegin(), diag::err_attributes_not_allowed)
|
||||
<< attrs.Range;
|
||||
void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs,
|
||||
const SourceLocation CorrectLocation) {
|
||||
if (CorrectLocation.isValid()) {
|
||||
CharSourceRange AttrRange(attrs.Range, true);
|
||||
Diag(CorrectLocation, diag::err_attributes_misplaced)
|
||||
<< FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange)
|
||||
<< FixItHint::CreateRemoval(AttrRange);
|
||||
} else
|
||||
Diag(attrs.Range.getBegin(), diag::err_attributes_not_allowed) << attrs.Range;
|
||||
}
|
||||
|
||||
void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs,
|
||||
|
@ -930,7 +930,31 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
|
||||
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
|
||||
// declaration-specifiers init-declarator-list[opt] ';'
|
||||
if (Tok.is(tok::semi)) {
|
||||
ProhibitAttributes(attrs);
|
||||
auto LengthOfTSTToken = [](DeclSpec::TST TKind) {
|
||||
assert(DeclSpec::isDeclRep(TKind));
|
||||
switch(TKind) {
|
||||
case DeclSpec::TST_class:
|
||||
return 5;
|
||||
case DeclSpec::TST_struct:
|
||||
return 6;
|
||||
case DeclSpec::TST_union:
|
||||
return 5;
|
||||
case DeclSpec::TST_enum:
|
||||
return 4;
|
||||
case DeclSpec::TST_interface:
|
||||
return 9;
|
||||
default:
|
||||
llvm_unreachable("we only expect to get the length of the class/struct/union/enum");
|
||||
}
|
||||
|
||||
};
|
||||
// Suggest correct location to fix '[[attrib]] struct' to 'struct [[attrib]]'
|
||||
SourceLocation CorrectLocationForAttributes =
|
||||
DeclSpec::isDeclRep(DS.getTypeSpecType())
|
||||
? DS.getTypeSpecTypeLoc().getLocWithOffset(
|
||||
LengthOfTSTToken(DS.getTypeSpecType()))
|
||||
: SourceLocation();
|
||||
ProhibitAttributes(attrs, CorrectLocationForAttributes);
|
||||
ConsumeToken();
|
||||
RecordDecl *AnonRecord = nullptr;
|
||||
Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none,
|
||||
|
@ -7,7 +7,7 @@ enum [[]] E {
|
||||
};
|
||||
|
||||
enum [[]] { Four };
|
||||
[[]] enum E2 { Five }; // expected-error {{an attribute list cannot appear here}}
|
||||
[[]] enum E2 { Five }; // expected-error {{misplaced attributes}}
|
||||
|
||||
// FIXME: this diagnostic can be improved.
|
||||
enum { [[]] Six }; // expected-error {{expected identifier}}
|
||||
@ -24,7 +24,7 @@ struct [[]] S1 {
|
||||
int o [[]] : 12;
|
||||
};
|
||||
|
||||
[[]] struct S2 { int a; }; // expected-error {{an attribute list cannot appear here}}
|
||||
[[]] struct S2 { int a; }; // expected-error {{misplaced attributes}}
|
||||
struct S3 [[]] { int a; }; // expected-error {{an attribute list cannot appear here}}
|
||||
|
||||
union [[]] U {
|
||||
@ -32,7 +32,7 @@ union [[]] U {
|
||||
[[]] int i;
|
||||
};
|
||||
|
||||
[[]] union U2 { double d; }; // expected-error {{an attribute list cannot appear here}}
|
||||
[[]] union U2 { double d; }; // expected-error {{misplaced attributes}}
|
||||
union U3 [[]] { double d; }; // expected-error {{an attribute list cannot appear here}}
|
||||
|
||||
struct [[]] IncompleteStruct;
|
||||
|
@ -199,7 +199,7 @@ namespace PR15017 {
|
||||
// expected-error@-2 {{expected expression}}
|
||||
// expected-error@-3 {{expected unqualified-id}}
|
||||
#else
|
||||
// expected-error@-5 {{an attribute list cannot appear here}}
|
||||
// expected-error@-5 {{misplaced attributes}}
|
||||
#endif
|
||||
|
||||
namespace test7 {
|
||||
|
@ -64,6 +64,13 @@ struct MemberFnOrder {
|
||||
struct [[]] struct_attr;
|
||||
class [[]] class_attr {};
|
||||
union [[]] union_attr;
|
||||
enum [[]] E { };
|
||||
namespace test_misplacement {
|
||||
[[]] struct struct_attr2; //expected-error{{misplaced attributes}}
|
||||
[[]] class class_attr2; //expected-error{{misplaced attributes}}
|
||||
[[]] union union_attr2; //expected-error{{misplaced attributes}}
|
||||
[[]] enum E2 { }; //expected-error{{misplaced attributes}}
|
||||
}
|
||||
|
||||
// Checks attributes placed at wrong syntactic locations of class specifiers.
|
||||
class [[]] [[]]
|
||||
@ -91,7 +98,7 @@ class C final [[deprecated(l]] {}); // expected-error {{use of undeclared identi
|
||||
class D final alignas ([l) {}]{}); // expected-error {{expected ',' or ']' in lambda capture list}} expected-error {{an attribute list cannot appear here}}
|
||||
|
||||
[[]] struct with_init_declarators {} init_declarator;
|
||||
[[]] struct no_init_declarators; // expected-error {{an attribute list cannot appear here}}
|
||||
[[]] struct no_init_declarators; // expected-error {{misplaced attributes}}
|
||||
template<typename> [[]] struct no_init_declarators_template; // expected-error {{an attribute list cannot appear here}}
|
||||
void fn_with_structs() {
|
||||
[[]] struct with_init_declarators {} init_declarator;
|
||||
|
Loading…
x
Reference in New Issue
Block a user