diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2799,20 +2799,38 @@ tok::l_square)); if (Right.is(tok::star) && Left.is(tok::l_paren)) return false; - if (Right.isOneOf(tok::star, tok::amp, tok::ampamp) && - (Left.is(tok::identifier) || Left.isSimpleTypeSpecifier()) && - // Space between the type and the * in: - // operator void*() - // operator char*() - // operator /*comment*/ const char*() - // operator volatile /*comment*/ char*() - // operator Foo*() - // dependent on PointerAlignment style. - Left.Previous && - (Left.Previous->endsSequence(tok::kw_operator) || - Left.Previous->endsSequence(tok::kw_const, tok::kw_operator) || - Left.Previous->endsSequence(tok::kw_volatile, tok::kw_operator))) - return (Style.PointerAlignment != FormatStyle::PAS_Left); + if (Right.isOneOf(tok::star, tok::amp, tok::ampamp)) { + const FormatToken *Previous = &Left; + while (Previous && !Previous->is(tok::kw_operator)) { + if (Previous->is(tok::identifier) || Previous->isSimpleTypeSpecifier()) { + Previous = Previous->getPreviousNonComment(); + continue; + } + if (Previous->is(TT_TemplateCloser) && Previous->MatchingParen) { + Previous = Previous->MatchingParen->getPreviousNonComment(); + continue; + } + if (Previous->is(tok::coloncolon)) { + Previous = Previous->getPreviousNonComment(); + continue; + } + break; + } + // Space between the type and the * in: + // operator void*() + // operator char*() + // operator /*comment*/ const char*() + // operator volatile /*comment*/ char*() + // operator Foo*() + // operator C*() + // operator std::Foo*() + // operator C::D*() + // dependent on PointerAlignment style. + if (Previous && (Previous->endsSequence(tok::kw_operator) || + Previous->endsSequence(tok::kw_const, tok::kw_operator) || + Previous->endsSequence(tok::kw_volatile, tok::kw_operator))) + return (Style.PointerAlignment != FormatStyle::PAS_Left); + } const auto SpaceRequiredForArrayInitializerLSquare = [](const FormatToken &LSquareTok, const FormatStyle &Style) { return Style.SpacesInContainerLiterals || diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -15386,6 +15386,13 @@ verifyFormat("Foo::operator&&();", Style); verifyFormat("operator&&(int(&&)(), class Foo);", Style); + // PR45107 + verifyFormat("operator Vector&();", Style); + verifyFormat("operator foo::Bar*();", Style); + verifyFormat("operator const Foo::Bar*();", Style); + verifyFormat("operator/*a*/ const /*b*/ Foo /*c*/ /*d*/ ::Bar*();", + Style); + Style.PointerAlignment = FormatStyle::PAS_Middle; verifyFormat("Foo::operator*();", Style); verifyFormat("Foo::operator void *();", Style);