tbaeder updated this revision to Diff 249574.
tbaeder added a comment.

Updated according to Aaron's comments. I'm not sure about changing the 
`DeclSpec` member and moving `ParsedAttributesWithRange` to ParsedAttr.h.

Tests included.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D75844/new/

https://reviews.llvm.org/D75844

Files:
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/DeclSpec.h
  clang/include/clang/Sema/ParsedAttr.h
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExprCXX.cpp
  clang/lib/Parse/ParseObjc.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/test/AST/sourceranges.cpp
  clang/test/SemaCXX/switch-implicit-fallthrough.cpp

Index: clang/test/SemaCXX/switch-implicit-fallthrough.cpp
===================================================================
--- clang/test/SemaCXX/switch-implicit-fallthrough.cpp
+++ clang/test/SemaCXX/switch-implicit-fallthrough.cpp
@@ -107,6 +107,11 @@
       break;
     case 25: // no warning here, there's no fall-through
       break;
+    case 26:
+      return 0;
+    __attribute__((fallthrough)); // expected-warning{{fallthrough annotation in unreachable code}}
+    case 27:
+      break;
   }
 
   return n;
Index: clang/test/AST/sourceranges.cpp
===================================================================
--- clang/test/AST/sourceranges.cpp
+++ clang/test/AST/sourceranges.cpp
@@ -108,6 +108,25 @@
   }
 }
 
+// CHECK-1Z: NamespaceDecl {{.*}} attributed_case
+namespace attributed_case {
+  void f(int n) {
+    switch(n) {
+      case 0:
+        n--;
+        // CHECK: AttributedStmt {{.*}} <line:[[@LINE+2]]:9, line:[[@LINE+5]]:11>
+        // CHECK: FallThroughAttr {{.*}} <line:[[@LINE+1]]:24>
+        __attribute__((fallthrough))
+        // CHECK: FallThroughAttr {{.*}} <line:[[@LINE+1]]:26>
+          __attribute__((fallthrough))
+          ;
+      case 1:
+        n++;
+        break;
+    }
+  }
+}
+
 #if __cplusplus >= 201703L
 // CHECK-1Z: FunctionDecl {{.*}} construct_with_init_list
 std::map<int, int> construct_with_init_list() {
Index: clang/lib/Parse/ParseStmt.cpp
===================================================================
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -2493,7 +2493,7 @@
   Braces.consumeClose();
 }
 
-bool Parser::ParseOpenCLUnrollHintAttribute(ParsedAttributes &Attrs) {
+bool Parser::ParseOpenCLUnrollHintAttribute(ParsedAttributesWithRange &Attrs) {
   MaybeParseGNUAttributes(Attrs);
 
   if (Attrs.empty())
Index: clang/lib/Parse/ParseObjc.cpp
===================================================================
--- clang/lib/Parse/ParseObjc.cpp
+++ clang/lib/Parse/ParseObjc.cpp
@@ -25,7 +25,7 @@
 
 /// Skips attributes after an Objective-C @ directive. Emits a diagnostic.
 void Parser::MaybeSkipAttributes(tok::ObjCKeywordKind Kind) {
-  ParsedAttributes attrs(AttrFactory);
+  ParsedAttributesWithRange attrs(AttrFactory);
   if (Tok.is(tok::kw___attribute)) {
     if (Kind == tok::objc_interface || Kind == tok::objc_protocol)
       Diag(Tok, diag::err_objc_postfix_attribute_hint)
@@ -1348,7 +1348,7 @@
                                    nullptr);
 
   // If attributes exist before the method, parse them.
-  ParsedAttributes methodAttrs(AttrFactory);
+  ParsedAttributesWithRange methodAttrs(AttrFactory);
   if (getLangOpts().ObjC)
     MaybeParseGNUAttributes(methodAttrs);
   MaybeParseCXX11Attributes(methodAttrs);
@@ -1397,7 +1397,7 @@
 
   AttributePool allParamAttrs(AttrFactory);
   while (1) {
-    ParsedAttributes paramAttrs(AttrFactory);
+    ParsedAttributesWithRange paramAttrs(AttrFactory);
     Sema::ObjCArgInfo ArgInfo;
 
     // Each iteration parses a single keyword argument.
Index: clang/lib/Parse/ParseExprCXX.cpp
===================================================================
--- clang/lib/Parse/ParseExprCXX.cpp
+++ clang/lib/Parse/ParseExprCXX.cpp
@@ -1234,7 +1234,7 @@
   TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
   Actions.PushLambdaScope();
 
-  ParsedAttributes Attr(AttrFactory);
+  ParsedAttributesWithRange Attr(AttrFactory);
   SourceLocation DeclLoc = Tok.getLocation();
   if (getLangOpts().CUDA) {
     // In CUDA code, GNU attributes are allowed to appear immediately after the
Index: clang/lib/Parse/ParseDeclCXX.cpp
===================================================================
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -516,7 +516,7 @@
 Decl *Parser::ParseUsingDirective(DeclaratorContext Context,
                                   SourceLocation UsingLoc,
                                   SourceLocation &DeclEnd,
-                                  ParsedAttributes &attrs) {
+                                  ParsedAttributesWithRange &attrs) {
   assert(Tok.is(tok::kw_namespace) && "Not 'namespace' token");
 
   // Eat 'namespace'.
@@ -3050,7 +3050,7 @@
   T.skipToEnd();
 
   // Parse and discard any trailing attributes.
-  ParsedAttributes Attrs(AttrFactory);
+  ParsedAttributesWithRange Attrs(AttrFactory);
   if (Tok.is(tok::kw___attribute))
     MaybeParseGNUAttributes(Attrs);
 }
@@ -3343,7 +3343,7 @@
   }
 
   // If attributes exist after class contents, parse them.
-  ParsedAttributes attrs(AttrFactory);
+  ParsedAttributesWithRange attrs(AttrFactory);
   MaybeParseGNUAttributes(attrs);
 
   if (TagDecl)
Index: clang/lib/Parse/ParseDecl.cpp
===================================================================
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -143,12 +143,15 @@
 ///    ',' or ')' are ignored, otherwise they produce a parse error.
 ///
 /// We follow the C++ model, but don't allow junk after the identifier.
-void Parser::ParseGNUAttributes(ParsedAttributes &attrs,
+void Parser::ParseGNUAttributes(ParsedAttributesWithRange &attrs,
                                 SourceLocation *endLoc,
                                 LateParsedAttrList *LateAttrs,
                                 Declarator *D) {
   assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!");
 
+  if (attrs.Range.getBegin().isInvalid())
+    attrs.Range.setBegin(Tok.getLocation());
+
   while (Tok.is(tok::kw___attribute)) {
     SourceLocation AttrTokLoc = ConsumeToken();
     unsigned OldNumAttrs = attrs.size();
@@ -241,6 +244,9 @@
       }
     }
   }
+
+  if (attrs.Range.getEnd().isInvalid())
+    attrs.Range.setEnd(Tok.getLocation());
 }
 
 /// Determine whether the given attribute has an identifier argument.
@@ -4318,7 +4324,7 @@
 
   T.consumeClose();
 
-  ParsedAttributes attrs(AttrFactory);
+  ParsedAttributesWithRange attrs(AttrFactory);
   // If attributes exist after struct contents, parse them.
   MaybeParseGNUAttributes(attrs);
 
@@ -4826,7 +4832,7 @@
   T.consumeClose();
 
   // If attributes exist after the identifier list, parse them.
-  ParsedAttributes attrs(AttrFactory);
+  ParsedAttributesWithRange attrs(AttrFactory);
   MaybeParseGNUAttributes(attrs);
 
   Actions.ActOnEnumBody(StartLoc, T.getRange(), EnumDecl, EnumConstantDecls,
@@ -6244,7 +6250,7 @@
   // In either case, we need to eat any attributes to be able to determine what
   // sort of paren this is.
   //
-  ParsedAttributes attrs(AttrFactory);
+  ParsedAttributesWithRange attrs(AttrFactory);
   bool RequiresArg = false;
   if (Tok.is(tok::kw___attribute)) {
     ParseGNUAttributes(attrs);
Index: clang/include/clang/Sema/ParsedAttr.h
===================================================================
--- clang/include/clang/Sema/ParsedAttr.h
+++ clang/include/clang/Sema/ParsedAttr.h
@@ -1001,6 +1001,19 @@
   mutable AttributePool pool;
 };
 
+struct ParsedAttributesWithRange : ParsedAttributes {
+  ParsedAttributesWithRange(AttributeFactory &factory)
+    : ParsedAttributes(factory) {}
+
+  void clear() {
+    ParsedAttributes::clear();
+    Range = SourceRange();
+  }
+
+  SourceRange Range;
+};
+
+
 /// These constants match the enumerated choices of
 /// err_attribute_argument_n_type and err_attribute_argument_type.
 enum AttributeArgumentNType {
Index: clang/include/clang/Sema/DeclSpec.h
===================================================================
--- clang/include/clang/Sema/DeclSpec.h
+++ clang/include/clang/Sema/DeclSpec.h
@@ -377,7 +377,7 @@
   ExplicitSpecifier FS_explicit_specifier;
 
   // attributes.
-  ParsedAttributes Attrs;
+  ParsedAttributesWithRange Attrs;
 
   // Scope specifier for the type spec, if applicable.
   CXXScopeSpec TypeScope;
@@ -784,8 +784,8 @@
 
   bool hasAttributes() const { return !Attrs.empty(); }
 
-  ParsedAttributes &getAttributes() { return Attrs; }
-  const ParsedAttributes &getAttributes() const { return Attrs; }
+  ParsedAttributesWithRange &getAttributes() { return Attrs; }
+  const ParsedAttributesWithRange &getAttributes() const { return Attrs; }
 
   void takeAttributesFrom(ParsedAttributes &attrs) {
     Attrs.takeAllFrom(attrs);
Index: clang/include/clang/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -1507,17 +1507,6 @@
 
   //===--------------------------------------------------------------------===//
   // C99 6.9: External Definitions.
-  struct ParsedAttributesWithRange : ParsedAttributes {
-    ParsedAttributesWithRange(AttributeFactory &factory)
-      : ParsedAttributes(factory) {}
-
-    void clear() {
-      ParsedAttributes::clear();
-      Range = SourceRange();
-    }
-
-    SourceRange Range;
-  };
   struct ParsedAttributesViewWithRange : ParsedAttributesView {
     ParsedAttributesViewWithRange() : ParsedAttributesView() {}
     void clearListOnly() {
@@ -2535,19 +2524,19 @@
   void MaybeParseGNUAttributes(Declarator &D,
                                LateParsedAttrList *LateAttrs = nullptr) {
     if (Tok.is(tok::kw___attribute)) {
-      ParsedAttributes attrs(AttrFactory);
+      ParsedAttributesWithRange attrs(AttrFactory);
       SourceLocation endLoc;
       ParseGNUAttributes(attrs, &endLoc, LateAttrs, &D);
       D.takeAttributes(attrs, endLoc);
     }
   }
-  void MaybeParseGNUAttributes(ParsedAttributes &attrs,
+  void MaybeParseGNUAttributes(ParsedAttributesWithRange &attrs,
                                SourceLocation *endLoc = nullptr,
                                LateParsedAttrList *LateAttrs = nullptr) {
     if (Tok.is(tok::kw___attribute))
       ParseGNUAttributes(attrs, endLoc, LateAttrs);
   }
-  void ParseGNUAttributes(ParsedAttributes &attrs,
+  void ParseGNUAttributes(ParsedAttributesWithRange &attrs,
                           SourceLocation *endLoc = nullptr,
                           LateParsedAttrList *LateAttrs = nullptr,
                           Declarator *D = nullptr);
@@ -2631,14 +2620,14 @@
   /// Parses opencl_unroll_hint attribute if language is OpenCL v2.0
   /// or higher.
   /// \return false if error happens.
-  bool MaybeParseOpenCLUnrollHintAttribute(ParsedAttributes &Attrs) {
+  bool MaybeParseOpenCLUnrollHintAttribute(ParsedAttributesWithRange &Attrs) {
     if (getLangOpts().OpenCL)
       return ParseOpenCLUnrollHintAttribute(Attrs);
     return true;
   }
   /// Parses opencl_unroll_hint attribute.
   /// \return false if error happens.
-  bool ParseOpenCLUnrollHintAttribute(ParsedAttributes &Attrs);
+  bool ParseOpenCLUnrollHintAttribute(ParsedAttributesWithRange &Attrs);
   void ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs);
 
   VersionTuple ParseVersionTuple(SourceRange &Range);
@@ -2830,7 +2819,7 @@
   Decl *ParseUsingDirective(DeclaratorContext Context,
                             SourceLocation UsingLoc,
                             SourceLocation &DeclEnd,
-                            ParsedAttributes &attrs);
+                            ParsedAttributesWithRange &attrs);
 
   struct UsingDeclarator {
     SourceLocation TypenameLoc;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to