[clang] 1b4800c - [clang][parser] Set source ranges for GNU-style attributes
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Sat Apr 3 22:59:49 PDT 2021
Author: Timm Bäder
Date: 2021-04-04T07:59:22+02:00
New Revision: 1b4800c2625912d16867d27e5eec3af27af31557
URL: https://github.com/llvm/llvm-project/commit/1b4800c2625912d16867d27e5eec3af27af31557
DIFF: https://github.com/llvm/llvm-project/commit/1b4800c2625912d16867d27e5eec3af27af31557.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/lib/Parse/ParseDeclCXX.cpp
clang/test/AST/sourceranges.cpp
clang/test/Parser/cxx0x-attributes.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 b67e541836d5..6f6d4697e6d0 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 9cbee28d612a..471a1ecfac9b 100644
--- a/clang/include/clang/Sema/ParsedAttr.h
+++ b/clang/include/clang/Sema/ParsedAttr.h
@@ -1048,6 +1048,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 104b1b54f578..eb567f528a1c 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/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 829ed179f54c..017550cdf34f 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1852,7 +1852,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
} else if (TUK == Sema::TUK_Reference ||
(TUK == Sema::TUK_Friend &&
TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) {
- ProhibitAttributes(attrs);
+ ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,
+ /*DiagnoseEmptyAttrs=*/true);
TypeResult = Actions.ActOnTagTemplateIdType(TUK, TagType, StartLoc,
SS,
TemplateId->TemplateKWLoc,
@@ -1924,7 +1925,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TagType, StartLoc, SS, Name, NameLoc, attrs);
} else if (TUK == Sema::TUK_Friend &&
TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) {
- ProhibitAttributes(attrs);
+ ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,
+ /*DiagnoseEmptyAttrs=*/true);
TagOrTempResult = Actions.ActOnTemplatedFriendTag(
getCurScope(), DS.getFriendSpecLoc(), TagType, StartLoc, SS, Name,
diff --git a/clang/test/AST/sourceranges.cpp b/clang/test/AST/sourceranges.cpp
index a38ec3207ae4..cd1095c69afc 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/Parser/cxx0x-attributes.cpp b/clang/test/Parser/cxx0x-attributes.cpp
index c9b27c1a7b89..6ecbb5af14a4 100644
--- a/clang/test/Parser/cxx0x-attributes.cpp
+++ b/clang/test/Parser/cxx0x-attributes.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -Wc++14-compat -Wc++14-extensions -Wc++17-extensions %s
+// RUN: %clang_cc1 -fcxx-exceptions -fdeclspec -fexceptions -fsyntax-only -verify -std=c++11 -Wc++14-compat -Wc++14-extensions -Wc++17-extensions %s
// Need std::initializer_list
namespace std {
@@ -368,6 +368,22 @@ int fallthru(int n) {
return n;
}
+template<typename T> struct TemplateStruct {};
+class FriendClassesWithAttributes {
+ // We allow GNU-style attributes here
+ template <class _Tp, class _Alloc> friend class __attribute__((__type_visibility__("default"))) vector;
+ template <class _Tp, class _Alloc> friend class __declspec(code_seg("whatever")) vector2;
+ // But not C++11 ones
+ template <class _Tp, class _Alloc> friend class[[]] vector3; // expected-error {{an attribute list cannot appear here}}
+ template <class _Tp, class _Alloc> friend class [[clang::__type_visibility__(("default"))]] vector4; // expected-error {{an attribute list cannot appear here}}
+
+ // Also allowed
+ friend struct __attribute__((__type_visibility__("default"))) TemplateStruct<FriendClassesWithAttributes>;
+ friend struct __declspec(code_seg("whatever")) TemplateStruct<FriendClassesWithAttributes>;
+ friend struct[[]] TemplateStruct<FriendClassesWithAttributes>; // expected-error {{an attribute list cannot appear here}}
+ friend struct [[clang::__type_visibility__("default")]] TemplateStruct<FriendClassesWithAttributes>; // expected-error {{an attribute list cannot appear here}}
+};
+
#define attr_name bitand
#define attr_name_2(x) x
#define attr_name_3(x, y) x##y
diff --git a/clang/test/SemaCXX/switch-implicit-fallthrough.cpp b/clang/test/SemaCXX/switch-implicit-fallthrough.cpp
index e6ae0d55b588..9676664a7a30 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;
More information about the cfe-commits
mailing list