diff --git a/clang/lib/Format/QualifierAlignmentFixer.cpp b/clang/lib/Format/QualifierAlignmentFixer.cpp --- a/clang/lib/Format/QualifierAlignmentFixer.cpp +++ b/clang/lib/Format/QualifierAlignmentFixer.cpp @@ -216,6 +216,29 @@ if (LeftRightQualifierAlignmentFixer::isPossibleMacro(Tok->Next)) return Tok; + auto AnalyzeTemplate = + [&](const FormatToken *Tok, + const FormatToken *StartTemplate) -> const FormatToken * { + // Read from the TemplateOpener to TemplateCloser. + FormatToken *EndTemplate = StartTemplate->MatchingParen; + if (EndTemplate) { + // Move to the end of any template class members e.g. + // `Foo::iterator`. + if (EndTemplate->startsSequence(TT_TemplateCloser, tok::coloncolon, + tok::identifier)) { + EndTemplate = EndTemplate->Next->Next; + } + } + if (EndTemplate && EndTemplate->Next && + !EndTemplate->Next->isOneOf(tok::equal, tok::l_paren)) { + insertQualifierAfter(SourceMgr, Fixes, EndTemplate, Qualifier); + // Remove the qualifier. + removeToken(SourceMgr, Fixes, Tok); + return Tok; + } + return nullptr; + }; + FormatToken *Qual = Tok->Next; FormatToken *LastQual = Qual; while (Qual && isQualifierOrType(Qual, ConfiguredQualifierTokens)) { @@ -233,27 +256,24 @@ return Tok; } else if (Tok->startsSequence(QualifierType, tok::identifier, TT_TemplateOpener)) { - // Read from the TemplateOpener to - // TemplateCloser as in const ArrayRef a; const ArrayRef &a; - FormatToken *EndTemplate = Tok->Next->Next->MatchingParen; - if (EndTemplate) { - // Move to the end of any template class members e.g. - // `Foo::iterator`. - if (EndTemplate->startsSequence(TT_TemplateCloser, tok::coloncolon, - tok::identifier)) { - EndTemplate = EndTemplate->Next->Next; - } - } - if (EndTemplate && EndTemplate->Next && - !EndTemplate->Next->isOneOf(tok::equal, tok::l_paren)) { - insertQualifierAfter(SourceMgr, Fixes, EndTemplate, Qualifier); - // Remove the qualifier. - removeToken(SourceMgr, Fixes, Tok); - return Tok; - } - } else if (Tok->startsSequence(QualifierType, tok::identifier)) { + // `const ArrayRef a;` + // `const ArrayRef &a;` + const FormatToken *NewTok = AnalyzeTemplate(Tok, Tok->Next->Next); + if (NewTok) + return NewTok; + } else if (Tok->startsSequence(QualifierType, tok::coloncolon, + tok::identifier, TT_TemplateOpener)) { + // `const ::ArrayRef a;` + // `const ::ArrayRef &a;` + const FormatToken *NewTok = AnalyzeTemplate(Tok, Tok->Next->Next->Next); + if (NewTok) + return NewTok; + } else if (Tok->startsSequence(QualifierType, tok::identifier) || + Tok->startsSequence(QualifierType, tok::coloncolon, + tok::identifier)) { FormatToken *Next = Tok->Next; // The case `const Foo` -> `Foo const` + // The case `const ::Foo` -> `::Foo const` // The case `const Foo *` -> `Foo const *` // The case `const Foo &` -> `Foo const &` // The case `const Foo &&` -> `Foo const &&` @@ -331,7 +351,9 @@ Tok->Next->Next && Tok->Next->Next->is(QualifierType)) { rotateTokens(SourceMgr, Fixes, Tok->Next, Tok->Next->Next, /*Left=*/true); } - if (Tok->startsSequence(tok::identifier) && Tok->Next) { + if ((Tok->startsSequence(tok::coloncolon, tok::identifier) || + Tok->is(tok::identifier)) && + Tok->Next) { if (Tok->Previous && Tok->Previous->isOneOf(tok::star, tok::ampamp, tok::amp)) { return Tok; diff --git a/clang/unittests/Format/QualifierFixerTest.cpp b/clang/unittests/Format/QualifierFixerTest.cpp --- a/clang/unittests/Format/QualifierFixerTest.cpp +++ b/clang/unittests/Format/QualifierFixerTest.cpp @@ -318,6 +318,8 @@ verifyFormat("Foo const &a", "const Foo &a", Style); verifyFormat("Foo::iterator const &a", "const Foo::iterator &a", Style); + verifyFormat("::Foo::iterator const &a", "const ::Foo::iterator &a", + Style); verifyFormat("Foo(int a, " "unsigned b, // c-style args\n" @@ -355,6 +357,8 @@ verifyFormat("void fn(Foo const &i);", "void fn(const Foo &i);", Style); verifyFormat("void fns(ns::S const &s);", "void fns(const ns::S &s);", Style); + verifyFormat("void fns(::ns::S const &s);", "void fns(const ::ns::S &s);", + Style); verifyFormat("void fn(ns::Foo const &i);", "void fn(const ns::Foo &i);", Style); verifyFormat("void fns(ns::ns2::S const &s);", @@ -445,6 +449,8 @@ verifyFormat("const Foo &a", "Foo const &a", Style); verifyFormat("const Foo::iterator &a", "Foo::iterator const &a", Style); + verifyFormat("const ::Foo::iterator &a", "::Foo::iterator const &a", + Style); verifyFormat("const int a;", "int const a;", Style); verifyFormat("const int *a;", "int const *a;", Style); @@ -508,6 +514,8 @@ verifyFormat("void fn(const Foo &i);", "void fn(Foo const &i);", Style); verifyFormat("void fns(const ns::S &s);", "void fns(ns::S const &s);", Style); + verifyFormat("void fns(const ::ns::S &s);", "void fns(::ns::S const &s);", + Style); verifyFormat("void fn(const ns::Foo &i);", "void fn(ns::Foo const &i);", Style); verifyFormat("void fns(const ns::ns2::S &s);",