Author: Hans Wennborg Date: 2020-03-27T10:47:19+01:00 New Revision: eb85e90350e93a64279139e7eca9ca40c8fbf5eb
URL: https://github.com/llvm/llvm-project/commit/eb85e90350e93a64279139e7eca9ca40c8fbf5eb DIFF: https://github.com/llvm/llvm-project/commit/eb85e90350e93a64279139e7eca9ca40c8fbf5eb.diff LOG: clang-format: Fix pointer alignment for overloaded operators (PR45107) This fixes a regression from D69573 which broke the following example: $ echo 'operator C<T>*();' | bin/clang-format --style=Chromium operator C<T> *(); (There should be no space before the asterisk.) It seems the problem is in TokenAnnotator::spaceRequiredBetween(), which only looked at the token to the left of the * to see if it was a type or not. That code only handled simple types or identifiers, not templates or qualified types. This patch addresses that. Differential revision: https://reviews.llvm.org/D76850 Added: Modified: clang/lib/Format/TokenAnnotator.cpp clang/unittests/Format/FormatTest.cpp Removed: ################################################################################ diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index f2666a8bd171..8a1e247463d5 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2799,20 +2799,38 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, 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<T>*() + // operator std::Foo*() + // operator C<T>::D<U>*() + // 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 index a6f35ba27069..fe16eeaba53c 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -15386,6 +15386,13 @@ TEST_F(FormatTest, OperatorSpacing) { verifyFormat("Foo::operator&&();", Style); verifyFormat("operator&&(int(&&)(), class Foo);", Style); + // PR45107 + verifyFormat("operator Vector<String>&();", Style); + verifyFormat("operator foo::Bar*();", Style); + verifyFormat("operator const Foo<X>::Bar<Y>*();", Style); + verifyFormat("operator/*a*/ const /*b*/ Foo /*c*/<X> /*d*/ ::Bar<Y>*();", + Style); + Style.PointerAlignment = FormatStyle::PAS_Middle; verifyFormat("Foo::operator*();", Style); verifyFormat("Foo::operator void *();", Style); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits