diff options
-rw-r--r-- | clang/include/clang/Parse/Parser.h | 64 | ||||
-rw-r--r-- | clang/include/clang/Sema/ParsedAttr.h | 21 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 28 | ||||
-rw-r--r-- | clang/test/AST/sourceranges.cpp | 18 | ||||
-rw-r--r-- | clang/test/SemaCXX/switch-implicit-fallthrough.cpp | 7 |
5 files changed, 99 insertions, 39 deletions
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index b67e541..6f6d469 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1572,27 +1572,6 @@ private: //===--------------------------------------------------------------------===// // 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() { - ParsedAttributesView::clearListOnly(); - Range = SourceRange(); - } - - SourceRange Range; - }; - DeclGroupPtrTy ParseExternalDeclaration(ParsedAttributesWithRange &attrs, ParsingDeclSpec *DS = nullptr); bool isDeclarationAfterDeclarator(); @@ -2725,17 +2704,50 @@ private: D.takeAttributes(attrs, endLoc); } } - bool MaybeParseGNUAttributes(ParsedAttributes &attrs, - SourceLocation *endLoc = nullptr, + + /// Parses GNU-style attributes and returns them without source range + /// information. + /// + /// This API is discouraged. Use the version that takes a + /// ParsedAttributesWithRange instead. + bool MaybeParseGNUAttributes(ParsedAttributes &Attrs, + SourceLocation *EndLoc = nullptr, LateParsedAttrList *LateAttrs = nullptr) { if (Tok.is(tok::kw___attribute)) { - ParseGNUAttributes(attrs, endLoc, LateAttrs); + ParsedAttributesWithRange AttrsWithRange(AttrFactory); + ParseGNUAttributes(Attrs, EndLoc, LateAttrs); + Attrs.takeAllFrom(AttrsWithRange); return true; } return false; } - void ParseGNUAttributes(ParsedAttributes &attrs, - SourceLocation *endLoc = nullptr, + + bool MaybeParseGNUAttributes(ParsedAttributesWithRange &Attrs, + SourceLocation *EndLoc = nullptr, + LateParsedAttrList *LateAttrs = nullptr) { + if (Tok.is(tok::kw___attribute)) { + ParseGNUAttributes(Attrs, EndLoc, LateAttrs); + return true; + } + return false; + } + + /// Parses GNU-style attributes and returns them without source range + /// information. + /// + /// This API is discouraged. Use the version that takes a + /// ParsedAttributesWithRange instead. + void ParseGNUAttributes(ParsedAttributes &Attrs, + SourceLocation *EndLoc = nullptr, + LateParsedAttrList *LateAttrs = nullptr, + Declarator *D = nullptr) { + ParsedAttributesWithRange AttrsWithRange(AttrFactory); + ParseGNUAttributes(AttrsWithRange, EndLoc, LateAttrs, D); + Attrs.takeAllFrom(AttrsWithRange); + } + + void ParseGNUAttributes(ParsedAttributesWithRange &Attrs, + SourceLocation *EndLoc = nullptr, LateParsedAttrList *LateAttrs = nullptr, Declarator *D = nullptr); void ParseGNUAttributeArgs(IdentifierInfo *AttrName, diff --git a/clang/include/clang/Sema/ParsedAttr.h b/clang/include/clang/Sema/ParsedAttr.h index a3d82fc..fb086e3 100644 --- a/clang/include/clang/Sema/ParsedAttr.h +++ b/clang/include/clang/Sema/ParsedAttr.h @@ -1034,6 +1034,27 @@ private: mutable AttributePool pool; }; +struct ParsedAttributesWithRange : ParsedAttributes { + ParsedAttributesWithRange(AttributeFactory &factory) + : ParsedAttributes(factory) {} + + void clear() { + ParsedAttributes::clear(); + Range = SourceRange(); + } + + SourceRange Range; +}; +struct ParsedAttributesViewWithRange : ParsedAttributesView { + ParsedAttributesViewWithRange() : ParsedAttributesView() {} + void clearListOnly() { + ParsedAttributesView::clearListOnly(); + Range = SourceRange(); + } + + SourceRange Range; +}; + /// These constants match the enumerated choices of /// err_attribute_argument_n_type and err_attribute_argument_type. enum AttributeArgumentNType { diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 104b1b5..eb567f5 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -162,15 +162,19 @@ void Parser::ParseAttributes(unsigned WhichAttrKinds, /// ',' 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, - SourceLocation *endLoc, - LateParsedAttrList *LateAttrs, - Declarator *D) { +void Parser::ParseGNUAttributes(ParsedAttributesWithRange &Attrs, + SourceLocation *EndLoc, + LateParsedAttrList *LateAttrs, Declarator *D) { assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!"); + SourceLocation StartLoc = Tok.getLocation(), Loc; + + if (!EndLoc) + EndLoc = &Loc; + while (Tok.is(tok::kw___attribute)) { SourceLocation AttrTokLoc = ConsumeToken(); - unsigned OldNumAttrs = attrs.size(); + unsigned OldNumAttrs = Attrs.size(); unsigned OldNumLateAttrs = LateAttrs ? LateAttrs->size() : 0; if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, @@ -198,14 +202,14 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, SourceLocation AttrNameLoc = ConsumeToken(); if (Tok.isNot(tok::l_paren)) { - attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, + Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, ParsedAttr::AS_GNU); continue; } // Handle "parameterized" attributes if (!LateAttrs || !isAttributeLateParsed(*AttrName)) { - ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc, nullptr, + ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, nullptr, SourceLocation(), ParsedAttr::AS_GNU, D); continue; } @@ -238,8 +242,8 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, SourceLocation Loc = Tok.getLocation(); if (ExpectAndConsume(tok::r_paren)) SkipUntil(tok::r_paren, StopAtSemi); - if (endLoc) - *endLoc = Loc; + if (EndLoc) + *EndLoc = Loc; // If this was declared in a macro, attach the macro IdentifierInfo to the // parsed attribute. @@ -251,8 +255,8 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, Lexer::getSourceText(ExpansionRange, SM, PP.getLangOpts()); IdentifierInfo *MacroII = PP.getIdentifierInfo(FoundName); - for (unsigned i = OldNumAttrs; i < attrs.size(); ++i) - attrs[i].setMacroIdentifier(MacroII, ExpansionRange.getBegin()); + for (unsigned i = OldNumAttrs; i < Attrs.size(); ++i) + Attrs[i].setMacroIdentifier(MacroII, ExpansionRange.getBegin()); if (LateAttrs) { for (unsigned i = OldNumLateAttrs; i < LateAttrs->size(); ++i) @@ -260,6 +264,8 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, } } } + + Attrs.Range = SourceRange(StartLoc, *EndLoc); } /// Determine whether the given attribute has an identifier argument. diff --git a/clang/test/AST/sourceranges.cpp b/clang/test/AST/sourceranges.cpp index a38ec32..cd1095c 100644 --- a/clang/test/AST/sourceranges.cpp +++ b/clang/test/AST/sourceranges.cpp @@ -108,6 +108,24 @@ namespace attributed_decl { }
}
+// CHECK-1Z: NamespaceDecl {{.*}} attributed_case
+namespace attributed_case {
+void f(int n) {
+ switch (n) {
+ case 0:
+ n--;
+ // CHECK: AttributedStmt {{.*}} <line:[[@LINE+2]]:5, line:[[@LINE+4]]:35>
+ // CHECK: FallThroughAttr {{.*}} <line:[[@LINE+1]]:20>
+ __attribute__((fallthrough))
+ // CHECK: FallThroughAttr {{.*}} <line:[[@LINE+1]]:22>
+ __attribute__((fallthrough));
+ case 1:
+ n++;
+ break;
+ }
+}
+} // namespace attributed_case
+
// CHECK: NamespaceDecl {{.*}} attributed_stmt
namespace attributed_stmt {
// In DO_PRAGMA and _Pragma cases, `LoopHintAttr` comes from <scratch space>
diff --git a/clang/test/SemaCXX/switch-implicit-fallthrough.cpp b/clang/test/SemaCXX/switch-implicit-fallthrough.cpp index e6ae0d5..9676664 100644 --- a/clang/test/SemaCXX/switch-implicit-fallthrough.cpp +++ b/clang/test/SemaCXX/switch-implicit-fallthrough.cpp @@ -185,9 +185,12 @@ int fallthrough_position(int n) { return 1; [[clang::fallthrough]]; // expected-warning{{fallthrough annotation in unreachable code}} case 222: + return 2; + __attribute__((fallthrough)); // expected-warning{{fallthrough annotation in unreachable code}} + case 223: n += 400; - case 223: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}} - ; + case 224: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}} + ; } long p = static_cast<long>(n) * n; |