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 <owenpi...@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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits