diff --git a/clang/lib/Format/QualifierAlignmentFixer.cpp b/clang/lib/Format/QualifierAlignmentFixer.cpp index 5a89225c7fc86f..ec19a385376834 100644 --- a/clang/lib/Format/QualifierAlignmentFixer.cpp +++ b/clang/lib/Format/QualifierAlignmentFixer.cpp @@ -204,9 +204,9 @@ static void rotateTokens(const SourceManager &SourceMgr, replaceToken(SourceMgr, Fixes, Range, NewText); } -FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight( +const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight( const SourceManager &SourceMgr, const AdditionalKeywords &Keywords, - tooling::Replacements &Fixes, FormatToken *Tok, + tooling::Replacements &Fixes, const FormatToken *Tok, const std::string &Qualifier, tok::TokenKind QualifierType) { // We only need to think about streams that begin with a qualifier. if (!Tok->is(QualifierType)) @@ -281,16 +281,16 @@ FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight( return Tok; } -FormatToken *LeftRightQualifierAlignmentFixer::analyzeLeft( +const FormatToken *LeftRightQualifierAlignmentFixer::analyzeLeft( const SourceManager &SourceMgr, const AdditionalKeywords &Keywords, - tooling::Replacements &Fixes, FormatToken *Tok, + tooling::Replacements &Fixes, const FormatToken *Tok, const std::string &Qualifier, tok::TokenKind QualifierType) { // if Tok is an identifier and possibly a macro then don't convert. if (LeftRightQualifierAlignmentFixer::isPossibleMacro(Tok)) return Tok; - FormatToken *Qual = Tok; - FormatToken *LastQual = Qual; + const FormatToken *Qual = Tok; + const FormatToken *LastQual = Qual; while (Qual && isQualifierOrType(Qual, ConfiguredQualifierTokens)) { LastQual = Qual; Qual = Qual->Next; @@ -326,7 +326,7 @@ FormatToken *LeftRightQualifierAlignmentFixer::analyzeLeft( Tok->Previous->isOneOf(tok::star, tok::ampamp, tok::amp)) { return Tok; } - FormatToken *Next = Tok->Next; + const FormatToken *Next = Tok->Next; // The case `std::Foo const` -> `const std::Foo &&` while (Next && Next->isOneOf(tok::identifier, tok::coloncolon)) Next = Next->Next; @@ -334,6 +334,8 @@ FormatToken *LeftRightQualifierAlignmentFixer::analyzeLeft( Next->Previous->startsSequence(tok::identifier, TT_TemplateOpener)) { // Read from to the end of the TemplateOpener to // TemplateCloser const ArrayRef a; const ArrayRef &a; + if (Next->is(tok::comment) && Next->getNextNonComment()) + Next = Next->getNextNonComment(); assert(Next->MatchingParen && "Missing template closer"); Next = Next->MatchingParen->Next; @@ -398,7 +400,8 @@ LeftRightQualifierAlignmentFixer::analyze( FormatToken *First = AnnotatedLines[I]->First; const auto *Last = AnnotatedLines[I]->Last; - for (auto *Tok = First; Tok && Tok != Last && Tok->Next; Tok = Tok->Next) { + for (const auto *Tok = First; Tok && Tok != Last && Tok->Next; + Tok = Tok->Next) { if (Tok->is(tok::comment)) continue; if (RightAlign) diff --git a/clang/lib/Format/QualifierAlignmentFixer.h b/clang/lib/Format/QualifierAlignmentFixer.h index 7abd25687564b3..30ef96b8b0a7cc 100644 --- a/clang/lib/Format/QualifierAlignmentFixer.h +++ b/clang/lib/Format/QualifierAlignmentFixer.h @@ -72,17 +72,19 @@ class LeftRightQualifierAlignmentFixer : public TokenAnalyzer { static tok::TokenKind getTokenFromQualifier(const std::string &Qualifier); - FormatToken *analyzeRight(const SourceManager &SourceMgr, - const AdditionalKeywords &Keywords, - tooling::Replacements &Fixes, FormatToken *Tok, - const std::string &Qualifier, - tok::TokenKind QualifierType); - - FormatToken *analyzeLeft(const SourceManager &SourceMgr, - const AdditionalKeywords &Keywords, - tooling::Replacements &Fixes, FormatToken *Tok, - const std::string &Qualifier, - tok::TokenKind QualifierType); + const FormatToken *analyzeRight(const SourceManager &SourceMgr, + const AdditionalKeywords &Keywords, + tooling::Replacements &Fixes, + const FormatToken *Tok, + const std::string &Qualifier, + tok::TokenKind QualifierType); + + const FormatToken *analyzeLeft(const SourceManager &SourceMgr, + const AdditionalKeywords &Keywords, + tooling::Replacements &Fixes, + const FormatToken *Tok, + const std::string &Qualifier, + tok::TokenKind QualifierType); // is the Token a simple or qualifier type static bool isQualifierOrType(const FormatToken *Tok, diff --git a/clang/unittests/Format/QualifierFixerTest.cpp b/clang/unittests/Format/QualifierFixerTest.cpp index e3d0a9a0e26074..0517de2820d9dc 100755 --- a/clang/unittests/Format/QualifierFixerTest.cpp +++ b/clang/unittests/Format/QualifierFixerTest.cpp @@ -818,5 +818,45 @@ TEST_F(QualifierFixerTest, NoOpQualifierReplacements) { EXPECT_EQ(ReplacementCount, 0); } +TEST_F(QualifierFixerTest, QualifierTemplates) { + FormatStyle Style = getLLVMStyle(); + Style.QualifierAlignment = FormatStyle::QAS_Custom; + Style.QualifierOrder = {"static", "const", "type"}; + + ReplacementCount = 0; + EXPECT_EQ(ReplacementCount, 0); + verifyFormat("using A = B<>;", Style); + verifyFormat("using A = B /**/<>;", Style); + verifyFormat("template using A = B, 1>;", Style); + verifyFormat("template using A = B /**/, 1>;", Style); + verifyFormat("template using A = B /* */, 1>;", Style); + verifyFormat("template using A = B /*foo*/, 1>;", Style); + verifyFormat("template using A = B /**/ /**/, 1>;", Style); + verifyFormat("template using A = B, 1>;", Style); + verifyFormat("template using A = /**/ B, 1>;", Style); + EXPECT_EQ(ReplacementCount, 0); + verifyFormat("template \n" + "using A = B // foo\n" + " , 1>;", + Style); + + ReplacementCount = 0; + Style.QualifierOrder = {"type", "static", "const"}; + verifyFormat("using A = B<>;", Style); + verifyFormat("using A = B /**/<>;", Style); + verifyFormat("template using A = B, 1>;", Style); + verifyFormat("template using A = B /**/, 1>;", Style); + verifyFormat("template using A = B /* */, 1>;", Style); + verifyFormat("template using A = B /*foo*/, 1>;", Style); + verifyFormat("template using A = B /**/ /**/, 1>;", Style); + verifyFormat("template using A = B, 1>;", Style); + verifyFormat("template using A = /**/ B, 1>;", Style); + EXPECT_EQ(ReplacementCount, 0); + verifyFormat("template \n" + "using A = B // foo\n" + " , 1>;", + Style); +} + } // namespace format } // namespace clang