Author: Timm Bäder Date: 2021-04-01T17:25:23+02:00 New Revision: 1ea9fa8c507ec360cf43faf46d13b149e37c950d
URL: https://github.com/llvm/llvm-project/commit/1ea9fa8c507ec360cf43faf46d13b149e37c950d DIFF: https://github.com/llvm/llvm-project/commit/1ea9fa8c507ec360cf43faf46d13b149e37c950d.diff LOG: [clang][parser] Set source ranges for GNU-style attributes Set the source ranges for parsed GNU-style attributes in ParseGNUAttributes(), the same way that ParseCXX11Attributes() does it. Differential Revision: https://reviews.llvm.org/D75844 Added: Modified: clang/include/clang/Parse/Parser.h clang/include/clang/Sema/ParsedAttr.h clang/lib/Parse/ParseDecl.cpp clang/test/AST/sourceranges.cpp clang/test/SemaCXX/switch-implicit-fallthrough.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index b67e541836d59..6f6d4697e6d09 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1572,27 +1572,6 @@ class Parser : public CodeCompletionHandler { //===--------------------------------------------------------------------===// // 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 @@ class Parser : public CodeCompletionHandler { 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 a3d82fcd84f7a..fb086e3c1e50f 100644 --- a/clang/include/clang/Sema/ParsedAttr.h +++ b/clang/include/clang/Sema/ParsedAttr.h @@ -1034,6 +1034,27 @@ class ParsedAttributes : public ParsedAttributesView { 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 104b1b54f5785..eb567f528a1cd 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 a38ec3207ae4f..cd1095c69afc3 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 e6ae0d55b5884..9676664a7a30a 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; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits