diff options
author | Faisal Vali <faisalv@yahoo.com> | 2017-12-25 22:23:20 +0000 |
---|---|---|
committer | Faisal Vali <faisalv@yahoo.com> | 2017-12-25 22:23:20 +0000 |
commit | c5089c08d4cd4e8b36034c1fdae056e3f5f239ab (patch) | |
tree | 61c4b4df854c9950257ef4a043c9e7840ea130b5 /clang | |
parent | 99bbb213b50142d792e59996c56886c1b1e06118 (diff) | |
download | bcm5719-llvm-c5089c08d4cd4e8b36034c1fdae056e3f5f239ab.tar.gz bcm5719-llvm-c5089c08d4cd4e8b36034c1fdae056e3f5f239ab.zip |
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
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Basic/DiagnosticParseKinds.td | 1 | ||||
-rw-r--r-- | clang/include/clang/Parse/Parser.h | 11 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Parse/Parser.cpp | 26 | ||||
-rw-r--r-- | clang/test/Parser/c2x-attributes.c | 6 | ||||
-rw-r--r-- | clang/test/Parser/cxx-decl.cpp | 2 | ||||
-rw-r--r-- | clang/test/Parser/cxx0x-attributes.cpp | 9 |
7 files changed, 55 insertions, 14 deletions
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index a8d6955da3c..7936cdd96f8 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -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">; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 8f5b20c2bd7..4a25c70956a 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -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 diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 9fe4309ca12..2a999399fb5 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -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, diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 72d653797c6..8aa50a2c7f2 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -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, diff --git a/clang/test/Parser/c2x-attributes.c b/clang/test/Parser/c2x-attributes.c index 1be69f1ca28..f261dee200a 100644 --- a/clang/test/Parser/c2x-attributes.c +++ b/clang/test/Parser/c2x-attributes.c @@ -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; diff --git a/clang/test/Parser/cxx-decl.cpp b/clang/test/Parser/cxx-decl.cpp index 58ad08079c1..1a24520b8f5 100644 --- a/clang/test/Parser/cxx-decl.cpp +++ b/clang/test/Parser/cxx-decl.cpp @@ -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 { diff --git a/clang/test/Parser/cxx0x-attributes.cpp b/clang/test/Parser/cxx0x-attributes.cpp index 4e3a2e4685e..e01491db413 100644 --- a/clang/test/Parser/cxx0x-attributes.cpp +++ b/clang/test/Parser/cxx0x-attributes.cpp @@ -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; |