r321449 - Add a fixit for attributes incorrectly placed prior to 'struct/class/enum' keyword.

Faisal Vali via cfe-commits cfe-commits at lists.llvm.org
Mon Dec 25 14:23:21 PST 2017


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 at -2 {{expected expression}}
 // expected-error at -3 {{expected unqualified-id}}
 #else
-// expected-error at -5 {{an attribute list cannot appear here}}
+// expected-error at -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;




More information about the cfe-commits mailing list