[clang] [clang-format] Handle __attribute/__declspec/AttributeMacro consistently (PR #67518)
Owen Pan via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 26 22:15:12 PDT 2023
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/67518
None
>From 44165f4df433a668e4f4c2db730a66ce2acbc64b Mon Sep 17 00:00:00 2001
From: Owen Pan <owenpiano at gmail.com>
Date: Tue, 26 Sep 2023 20:43:55 -0700
Subject: [PATCH] [clang-format] Handle __attribute/__declspec/AttributeMacro
consistently
---
clang/lib/Format/FormatToken.h | 36 +++++++++----------
.../lib/Format/NamespaceEndCommentsFixer.cpp | 2 +-
clang/lib/Format/TokenAnnotator.cpp | 23 ++++++------
clang/lib/Format/UnwrappedLineParser.cpp | 6 ++--
clang/unittests/Format/TokenAnnotatorTest.cpp | 13 +++++++
5 files changed, 46 insertions(+), 34 deletions(-)
diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index 986849abd8f9206..dbd3a6e70f037ef 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -618,6 +618,10 @@ struct FormatToken {
bool isStringLiteral() const { return tok::isStringLiteral(Tok.getKind()); }
+ bool isAttribute() const {
+ return isOneOf(tok::kw___attribute, tok::kw___declspec, TT_AttributeMacro);
+ }
+
bool isObjCAtKeyword(tok::ObjCKeywordKind Kind) const {
return Tok.isObjCAtKeyword(Kind);
}
@@ -633,9 +637,10 @@ struct FormatToken {
bool canBePointerOrReferenceQualifier() const {
return isOneOf(tok::kw_const, tok::kw_restrict, tok::kw_volatile,
- tok::kw___attribute, tok::kw__Nonnull, tok::kw__Nullable,
+ tok::kw__Nonnull, tok::kw__Nullable,
tok::kw__Null_unspecified, tok::kw___ptr32, tok::kw___ptr64,
- tok::kw___funcref, TT_AttributeMacro);
+ tok::kw___funcref) ||
+ isAttribute();
}
/// Determine whether the token is a simple-type-specifier.
@@ -708,25 +713,16 @@ struct FormatToken {
/// Returns \c true if this is a keyword that can be used
/// like a function call (e.g. sizeof, typeid, ...).
bool isFunctionLikeKeyword() const {
- switch (Tok.getKind()) {
- case tok::kw_throw:
- case tok::kw_typeid:
- case tok::kw_return:
- case tok::kw_sizeof:
- case tok::kw_alignof:
- case tok::kw_alignas:
- case tok::kw_decltype:
- case tok::kw_noexcept:
- case tok::kw_static_assert:
- case tok::kw__Atomic:
- case tok::kw___attribute:
-#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
-#include "clang/Basic/TransformTypeTraits.def"
- case tok::kw_requires:
+ if (isAttribute())
return true;
- default:
- return false;
- }
+
+ return isOneOf(tok::kw_throw, tok::kw_typeid, tok::kw_return,
+ tok::kw_sizeof, tok::kw_alignof, tok::kw_alignas,
+ tok::kw_decltype, tok::kw_noexcept, tok::kw_static_assert,
+ tok::kw__Atomic,
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait,
+#include "clang/Basic/TransformTypeTraits.def"
+ tok::kw_requires);
}
/// Returns \c true if this is a string literal that's like a label,
diff --git a/clang/lib/Format/NamespaceEndCommentsFixer.cpp b/clang/lib/Format/NamespaceEndCommentsFixer.cpp
index aed31db87495406..08f8d6840fe00a8 100644
--- a/clang/lib/Format/NamespaceEndCommentsFixer.cpp
+++ b/clang/lib/Format/NamespaceEndCommentsFixer.cpp
@@ -48,7 +48,7 @@ processTokens(const FormatToken *Tok, tok::TokenKind StartTok,
const FormatToken *skipAttribute(const FormatToken *Tok) {
if (!Tok)
return nullptr;
- if (Tok->is(tok::kw___attribute)) {
+ if (Tok->isAttribute()) {
Tok = Tok->getNextNonComment();
Tok = processTokens(Tok, tok::l_paren, tok::r_paren, nullptr);
} else if (Tok->is(tok::l_square)) {
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 95d039b459b43e8..ba90e0184917344 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -376,7 +376,7 @@ class AnnotatingParser {
// Infer the role of the l_paren based on the previous token if we haven't
// detected one yet.
if (PrevNonComment && OpeningParen.is(TT_Unknown)) {
- if (PrevNonComment->is(tok::kw___attribute)) {
+ if (PrevNonComment->isAttribute()) {
OpeningParen.setType(TT_AttributeLParen);
} else if (PrevNonComment->isOneOf(TT_TypenameMacro, tok::kw_decltype,
tok::kw_typeof,
@@ -1207,11 +1207,13 @@ class AnnotatingParser {
return false;
if (Line.MustBeDeclaration && Contexts.size() == 1 &&
!Contexts.back().IsExpression && !Line.startsWith(TT_ObjCProperty) &&
- !Tok->isOneOf(TT_TypeDeclarationParen, TT_RequiresExpressionLParen) &&
- (!Tok->Previous ||
- !Tok->Previous->isOneOf(tok::kw___attribute, TT_RequiresClause,
- TT_LeadingJavaAnnotation))) {
- Line.MightBeFunctionDecl = true;
+ !Tok->isOneOf(TT_TypeDeclarationParen, TT_RequiresExpressionLParen)) {
+ if (const auto *Previous = Tok->Previous;
+ !Previous ||
+ (!Previous->isAttribute() &&
+ !Previous->isOneOf(TT_RequiresClause, TT_LeadingJavaAnnotation))) {
+ Line.MightBeFunctionDecl = true;
+ }
}
break;
case tok::l_square:
@@ -2389,7 +2391,7 @@ class AnnotatingParser {
assert(T->MatchingParen->is(tok::l_paren));
assert(T->MatchingParen->is(TT_AttributeLParen));
if (const auto *Tok = T->MatchingParen->Previous;
- Tok && Tok->is(tok::kw___attribute)) {
+ Tok && Tok->isAttribute()) {
T = Tok->Previous;
continue;
}
@@ -5607,10 +5609,11 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
tok::less, tok::coloncolon);
}
- if (Right.is(tok::kw___attribute) ||
- (Right.is(tok::l_square) && Right.is(TT_AttributeSquare))) {
+ if (Right.isAttribute())
+ return true;
+
+ if (Right.is(tok::l_square) && Right.is(TT_AttributeSquare))
return Left.isNot(TT_AttributeSquare);
- }
if (Left.is(tok::identifier) && Right.is(tok::string_literal))
return true;
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 53310d44c709af5..a927daf5665f606 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -354,7 +354,7 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace,
bool SwitchLabelEncountered = false;
do {
- if (FormatTok->getType() == TT_AttributeMacro) {
+ if (FormatTok->isAttribute()) {
nextToken();
continue;
}
@@ -2658,7 +2658,7 @@ static void markOptionalBraces(FormatToken *LeftBrace) {
void UnwrappedLineParser::handleAttributes() {
// Handle AttributeMacro, e.g. `if (x) UNLIKELY`.
- if (FormatTok->is(TT_AttributeMacro))
+ if (FormatTok->isAttribute())
nextToken();
else if (FormatTok->is(tok::l_square))
handleCppAttributes();
@@ -3832,8 +3832,8 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
// it is often token-pasted.
// An [[attribute]] can be before the identifier.
while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash,
- tok::kw___attribute, tok::kw___declspec,
tok::kw_alignas, tok::l_square) ||
+ FormatTok->isAttribute() ||
((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) &&
FormatTok->isOneOf(tok::period, tok::comma))) {
if (Style.isJavaScript() &&
diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp
index 204b00dd09f04d1..ab3ecd86cea5e03 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -2079,6 +2079,19 @@ TEST_F(TokenAnnotatorTest, UnderstandsAttributes) {
EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_Unknown);
EXPECT_TOKEN(Tokens[6], tok::r_paren, TT_Unknown);
EXPECT_TOKEN(Tokens[7], tok::r_paren, TT_AttributeRParen);
+
+ Tokens = annotate("bool foo __declspec(dllimport);");
+ ASSERT_EQ(Tokens.size(), 8u) << Tokens;
+ EXPECT_TOKEN(Tokens[3], tok::l_paren, TT_AttributeLParen);
+ EXPECT_TOKEN(Tokens[5], tok::r_paren, TT_AttributeRParen);
+
+ FormatStyle Style = getLLVMStyle();
+ Style.AttributeMacros.push_back("FOO");
+ Tokens = annotate("bool foo FOO(unused);", Style);
+ ASSERT_EQ(Tokens.size(), 8u) << Tokens;
+ EXPECT_TOKEN(Tokens[2], tok::identifier, TT_AttributeMacro);
+ EXPECT_TOKEN(Tokens[3], tok::l_paren, TT_AttributeLParen);
+ EXPECT_TOKEN(Tokens[5], tok::r_paren, TT_AttributeRParen);
}
} // namespace
More information about the cfe-commits
mailing list