Author: faisalv Date: Mon Dec 25 14:23:20 2017 New Revision: 321449 URL: http://llvm.org/viewvc/llvm-project?rev=321449&view=rev Log: 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). Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td cfe/trunk/include/clang/Parse/Parser.h cfe/trunk/lib/Parse/ParseDecl.cpp cfe/trunk/lib/Parse/Parser.cpp cfe/trunk/test/Parser/c2x-attributes.c cfe/trunk/test/Parser/cxx-decl.cpp cfe/trunk/test/Parser/cxx0x-attributes.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=321449&r1=321448&r2=321449&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Mon Dec 25 14:23:20 2017 @@ -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">; Modified: cfe/trunk/include/clang/Parse/Parser.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=321449&r1=321448&r2=321449&view=diff ============================================================================== --- cfe/trunk/include/clang/Parse/Parser.h (original) +++ cfe/trunk/include/clang/Parse/Parser.h Mon Dec 25 14:23:20 2017 @@ -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 Modified: cfe/trunk/lib/Parse/ParseDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=321449&r1=321448&r2=321449&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseDecl.cpp (original) +++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Dec 25 14:23:20 2017 @@ -1548,15 +1548,21 @@ void Parser::DiagnoseMisplacedCXX11Attri 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, Modified: cfe/trunk/lib/Parse/Parser.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=321449&r1=321448&r2=321449&view=diff ============================================================================== --- cfe/trunk/lib/Parse/Parser.cpp (original) +++ cfe/trunk/lib/Parse/Parser.cpp Mon Dec 25 14:23:20 2017 @@ -930,7 +930,31 @@ Parser::ParseDeclOrFunctionDefInternal(P // 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, Modified: cfe/trunk/test/Parser/c2x-attributes.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/c2x-attributes.c?rev=321449&r1=321448&r2=321449&view=diff ============================================================================== --- cfe/trunk/test/Parser/c2x-attributes.c (original) +++ cfe/trunk/test/Parser/c2x-attributes.c Mon Dec 25 14:23:20 2017 @@ -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; Modified: cfe/trunk/test/Parser/cxx-decl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-decl.cpp?rev=321449&r1=321448&r2=321449&view=diff ============================================================================== --- cfe/trunk/test/Parser/cxx-decl.cpp (original) +++ cfe/trunk/test/Parser/cxx-decl.cpp Mon Dec 25 14:23:20 2017 @@ -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 { Modified: cfe/trunk/test/Parser/cxx0x-attributes.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-attributes.cpp?rev=321449&r1=321448&r2=321449&view=diff ============================================================================== --- cfe/trunk/test/Parser/cxx0x-attributes.cpp (original) +++ cfe/trunk/test/Parser/cxx0x-attributes.cpp Mon Dec 25 14:23:20 2017 @@ -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]] {}); // e 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; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits