summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorFaisal Vali <faisalv@yahoo.com>2017-12-25 22:23:20 +0000
committerFaisal Vali <faisalv@yahoo.com>2017-12-25 22:23:20 +0000
commitc5089c08d4cd4e8b36034c1fdae056e3f5f239ab (patch)
tree61c4b4df854c9950257ef4a043c9e7840ea130b5 /clang
parent99bbb213b50142d792e59996c56886c1b1e06118 (diff)
downloadbcm5719-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.td1
-rw-r--r--clang/include/clang/Parse/Parser.h11
-rw-r--r--clang/lib/Parse/ParseDecl.cpp14
-rw-r--r--clang/lib/Parse/Parser.cpp26
-rw-r--r--clang/test/Parser/c2x-attributes.c6
-rw-r--r--clang/test/Parser/cxx-decl.cpp2
-rw-r--r--clang/test/Parser/cxx0x-attributes.cpp9
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;
OpenPOWER on IntegriCloud