diff --git a/clang/lib/Format/QualifierAlignmentFixer.cpp b/clang/lib/Format/QualifierAlignmentFixer.cpp index 441a37a4902b7..823a6e5c8054d 100644 --- a/clang/lib/Format/QualifierAlignmentFixer.cpp +++ b/clang/lib/Format/QualifierAlignmentFixer.cpp @@ -169,6 +169,18 @@ static bool isQualifier(const FormatToken *const Tok) { case tok::kw_constexpr: case tok::kw_restrict: case tok::kw_friend: + case tok::kw_typedef: + case tok::kw_consteval: + case tok::kw_constinit: + case tok::kw_thread_local: + case tok::kw_extern: + case tok::kw_mutable: + case tok::kw_signed: + case tok::kw_unsigned: + case tok::kw_long: + case tok::kw_short: + case tok::kw_decltype: + case tok::kw_explicit: return true; default: return false; @@ -529,6 +541,18 @@ tok::TokenKind LeftRightQualifierAlignmentFixer::getTokenFromQualifier( .Case("constexpr", tok::kw_constexpr) .Case("restrict", tok::kw_restrict) .Case("friend", tok::kw_friend) + .Case("typedef", tok::kw_typedef) + .Case("consteval", tok::kw_consteval) + .Case("constinit", tok::kw_constinit) + .Case("thread_local", tok::kw_thread_local) + .Case("extern", tok::kw_extern) + .Case("mutable", tok::kw_mutable) + .Case("signed", tok::kw_signed) + .Case("unsigned", tok::kw_unsigned) + .Case("long", tok::kw_long) + .Case("short", tok::kw_short) + .Case("decltype", tok::kw_decltype) + .Case("explicit", tok::kw_explicit) .Default(tok::identifier); } diff --git a/clang/unittests/Format/QualifierFixerTest.cpp b/clang/unittests/Format/QualifierFixerTest.cpp index f42f2e307f713..090a97607c02d 100644 --- a/clang/unittests/Format/QualifierFixerTest.cpp +++ b/clang/unittests/Format/QualifierFixerTest.cpp @@ -50,6 +50,30 @@ TEST_F(QualifierFixerTest, RotateTokens) { tok::kw_restrict); EXPECT_EQ(LeftRightQualifierAlignmentFixer::getTokenFromQualifier("friend"), tok::kw_friend); + EXPECT_EQ(LeftRightQualifierAlignmentFixer::getTokenFromQualifier("typedef"), + tok::kw_typedef); + EXPECT_EQ(LeftRightQualifierAlignmentFixer::getTokenFromQualifier("consteval"), + tok::kw_consteval); + EXPECT_EQ(LeftRightQualifierAlignmentFixer::getTokenFromQualifier("constinit"), + tok::kw_constinit); + EXPECT_EQ(LeftRightQualifierAlignmentFixer::getTokenFromQualifier("thread_local"), + tok::kw_thread_local); + EXPECT_EQ(LeftRightQualifierAlignmentFixer::getTokenFromQualifier("extern"), + tok::kw_extern); + EXPECT_EQ(LeftRightQualifierAlignmentFixer::getTokenFromQualifier("mutable"), + tok::kw_mutable); + EXPECT_EQ(LeftRightQualifierAlignmentFixer::getTokenFromQualifier("signed"), + tok::kw_signed); + EXPECT_EQ(LeftRightQualifierAlignmentFixer::getTokenFromQualifier("unsigned"), + tok::kw_unsigned); + EXPECT_EQ(LeftRightQualifierAlignmentFixer::getTokenFromQualifier("long"), + tok::kw_long); + EXPECT_EQ(LeftRightQualifierAlignmentFixer::getTokenFromQualifier("short"), + tok::kw_short); + EXPECT_EQ(LeftRightQualifierAlignmentFixer::getTokenFromQualifier("decltype"), + tok::kw_decltype); + EXPECT_EQ(LeftRightQualifierAlignmentFixer::getTokenFromQualifier("explicit"), + tok::kw_explicit); } TEST_F(QualifierFixerTest, FailQualifierInvalidConfiguration) { @@ -1057,48 +1081,37 @@ TEST_F(QualifierFixerTest, IsQualifierType) { ConfiguredTokens.push_back(tok::kw_restrict); ConfiguredTokens.push_back(tok::kw_constexpr); ConfiguredTokens.push_back(tok::kw_friend); + ConfiguredTokens.push_back(tok::kw_typedef); + ConfiguredTokens.push_back(tok::kw_consteval); + ConfiguredTokens.push_back(tok::kw_constinit); + ConfiguredTokens.push_back(tok::kw_thread_local); + ConfiguredTokens.push_back(tok::kw_extern); + ConfiguredTokens.push_back(tok::kw_mutable); + ConfiguredTokens.push_back(tok::kw_signed); + ConfiguredTokens.push_back(tok::kw_unsigned); + ConfiguredTokens.push_back(tok::kw_long); + ConfiguredTokens.push_back(tok::kw_short); + ConfiguredTokens.push_back(tok::kw_decltype); + ConfiguredTokens.push_back(tok::kw_explicit); TestLexer lexer{Allocator, Buffers}; const auto LangOpts = getFormattingLangOpts(); auto Tokens = lexer.lex( - "const static inline auto restrict int double long constexpr friend"); - ASSERT_EQ(Tokens.size(), 11u) << Tokens; - - EXPECT_TRUE( - isConfiguredQualifierOrType(Tokens[0], ConfiguredTokens, LangOpts)); - EXPECT_TRUE( - isConfiguredQualifierOrType(Tokens[1], ConfiguredTokens, LangOpts)); - EXPECT_TRUE( - isConfiguredQualifierOrType(Tokens[2], ConfiguredTokens, LangOpts)); - EXPECT_TRUE( - isConfiguredQualifierOrType(Tokens[3], ConfiguredTokens, LangOpts)); - EXPECT_TRUE( - isConfiguredQualifierOrType(Tokens[4], ConfiguredTokens, LangOpts)); - EXPECT_TRUE( - isConfiguredQualifierOrType(Tokens[5], ConfiguredTokens, LangOpts)); - EXPECT_TRUE( - isConfiguredQualifierOrType(Tokens[6], ConfiguredTokens, LangOpts)); - EXPECT_TRUE( - isConfiguredQualifierOrType(Tokens[7], ConfiguredTokens, LangOpts)); - EXPECT_TRUE( - isConfiguredQualifierOrType(Tokens[8], ConfiguredTokens, LangOpts)); - EXPECT_TRUE( - isConfiguredQualifierOrType(Tokens[9], ConfiguredTokens, LangOpts)); - - EXPECT_TRUE(isQualifierOrType(Tokens[0], LangOpts)); - EXPECT_TRUE(isQualifierOrType(Tokens[1], LangOpts)); - EXPECT_TRUE(isQualifierOrType(Tokens[2], LangOpts)); - EXPECT_TRUE(isQualifierOrType(Tokens[3], LangOpts)); - EXPECT_TRUE(isQualifierOrType(Tokens[4], LangOpts)); - EXPECT_TRUE(isQualifierOrType(Tokens[5], LangOpts)); - EXPECT_TRUE(isQualifierOrType(Tokens[6], LangOpts)); - EXPECT_TRUE(isQualifierOrType(Tokens[7], LangOpts)); - EXPECT_TRUE(isQualifierOrType(Tokens[8], LangOpts)); - EXPECT_TRUE(isQualifierOrType(Tokens[9], LangOpts)); + "const static inline restrict int double long constexpr friend " + "typedef consteval constinit thread_local extern mutable signed unsigned short decltype explicit"); + ASSERT_EQ(Tokens.size(), 20u) << Tokens; + + // Test that all tokens are recognized + for (size_t i = 0; i < 20; ++i) { + EXPECT_TRUE(isConfiguredQualifierOrType(Tokens[i], ConfiguredTokens, LangOpts)) + << "Token " << i << " should be recognized"; + EXPECT_TRUE(isQualifierOrType(Tokens[i], LangOpts)) + << "Token " << i << " should be recognized by isQualifierOrType"; + } auto NotTokens = lexer.lex("for while do Foo Bar "); - ASSERT_EQ(NotTokens.size(), 6u) << Tokens; + ASSERT_EQ(NotTokens.size(), 6u) << NotTokens; EXPECT_FALSE( isConfiguredQualifierOrType(NotTokens[0], ConfiguredTokens, LangOpts)); @@ -1384,6 +1397,65 @@ TEST_F(QualifierFixerTest, TemplatesLeft) { "TemplateType t;", Style); } +TEST_F(QualifierFixerTest, NewQualifierSupport) { + FormatStyle Style = getLLVMStyle(); + Style.QualifierAlignment = FormatStyle::QAS_Custom; + + // Test typedef qualifier + Style.QualifierOrder = {"typedef", "type"}; + verifyFormat("typedef int MyInt;", Style); + + // Test consteval qualifier + Style.QualifierOrder = {"consteval", "type"}; + verifyFormat("consteval int func();", "int consteval func();", Style); + + // Test constinit qualifier + Style.QualifierOrder = {"constinit", "static", "type"}; + verifyFormat("constinit static int var = 10;", "static constinit int var = 10;", Style); + + // Test thread_local qualifier + Style.QualifierOrder = {"thread_local", "static", "type"}; + verifyFormat("thread_local static int counter;", "static thread_local int counter;", Style); + + // Test extern qualifier + Style.QualifierOrder = {"extern", "type"}; + verifyFormat("extern int global_var;", "int extern global_var;", Style); + + // Test mutable qualifier + Style.QualifierOrder = {"mutable", "type"}; + verifyFormat("mutable int cache;", "int mutable cache;", Style); + + // Test signed/unsigned qualifiers + Style.QualifierOrder = {"signed", "type"}; + verifyFormat("signed int num;", "int signed num;", Style); + Style.QualifierOrder = {"unsigned", "type"}; + verifyFormat("unsigned int num;", "int unsigned num;", Style); + + // Test long/short qualifiers + Style.QualifierOrder = {"long", "type"}; + verifyFormat("long int num;", "int long num;", Style); + Style.QualifierOrder = {"short", "type"}; + verifyFormat("short int num;", "int short num;", Style); + + // Test decltype qualifier + Style.QualifierOrder = {"decltype", "type"}; + // Note: decltype is typically used with parentheses and doesn't usually get reordered + // This test mainly verifies it's recognized as a qualifier + + // Test explicit qualifier + Style.QualifierOrder = {"explicit", "type"}; + // Note: explicit is typically used with constructors and doesn't usually get reordered + // This test mainly verifies it's recognized as a qualifier + + // Test complex combination with new qualifiers + Style.QualifierOrder = {"extern", "thread_local", "static", "constexpr", + "inline", "unsigned", "long", "type", + "const", "volatile"}; + + verifyFormat("extern thread_local static constexpr inline unsigned long int const volatile var;", + "volatile const extern constexpr thread_local static inline unsigned long int var;", Style); +} + TEST_F(QualifierFixerTest, Ranges) { FormatStyle Style = getLLVMStyle(); Style.QualifierAlignment = FormatStyle::QAS_Custom;