Skip to content

Commit 7ae6db9

Browse files
zmodemtstellar
authored andcommitted
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 (cherry picked from commit eb85e90)
1 parent db810b6 commit 7ae6db9

File tree

2 files changed

+39
-14
lines changed

2 files changed

+39
-14
lines changed

clang/lib/Format/TokenAnnotator.cpp

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2705,20 +2705,38 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
27052705
tok::l_square));
27062706
if (Right.is(tok::star) && Left.is(tok::l_paren))
27072707
return false;
2708-
if (Right.isOneOf(tok::star, tok::amp, tok::ampamp) &&
2709-
(Left.is(tok::identifier) || Left.isSimpleTypeSpecifier()) &&
2710-
// Space between the type and the * in:
2711-
// operator void*()
2712-
// operator char*()
2713-
// operator /*comment*/ const char*()
2714-
// operator volatile /*comment*/ char*()
2715-
// operator Foo*()
2716-
// dependent on PointerAlignment style.
2717-
Left.Previous &&
2718-
(Left.Previous->endsSequence(tok::kw_operator) ||
2719-
Left.Previous->endsSequence(tok::kw_const, tok::kw_operator) ||
2720-
Left.Previous->endsSequence(tok::kw_volatile, tok::kw_operator)))
2721-
return (Style.PointerAlignment != FormatStyle::PAS_Left);
2708+
if (Right.isOneOf(tok::star, tok::amp, tok::ampamp)) {
2709+
const FormatToken *Previous = &Left;
2710+
while (Previous && !Previous->is(tok::kw_operator)) {
2711+
if (Previous->is(tok::identifier) || Previous->isSimpleTypeSpecifier()) {
2712+
Previous = Previous->getPreviousNonComment();
2713+
continue;
2714+
}
2715+
if (Previous->is(TT_TemplateCloser) && Previous->MatchingParen) {
2716+
Previous = Previous->MatchingParen->getPreviousNonComment();
2717+
continue;
2718+
}
2719+
if (Previous->is(tok::coloncolon)) {
2720+
Previous = Previous->getPreviousNonComment();
2721+
continue;
2722+
}
2723+
break;
2724+
}
2725+
// Space between the type and the * in:
2726+
// operator void*()
2727+
// operator char*()
2728+
// operator /*comment*/ const char*()
2729+
// operator volatile /*comment*/ char*()
2730+
// operator Foo*()
2731+
// operator C<T>*()
2732+
// operator std::Foo*()
2733+
// operator C<T>::D<U>*()
2734+
// dependent on PointerAlignment style.
2735+
if (Previous && (Previous->endsSequence(tok::kw_operator) ||
2736+
Previous->endsSequence(tok::kw_const, tok::kw_operator) ||
2737+
Previous->endsSequence(tok::kw_volatile, tok::kw_operator)))
2738+
return (Style.PointerAlignment != FormatStyle::PAS_Left);
2739+
}
27222740
const auto SpaceRequiredForArrayInitializerLSquare =
27232741
[](const FormatToken &LSquareTok, const FormatStyle &Style) {
27242742
return Style.SpacesInContainerLiterals ||

clang/unittests/Format/FormatTest.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15036,6 +15036,13 @@ TEST_F(FormatTest, OperatorSpacing) {
1503615036
verifyFormat("Foo::operator&&();", Style);
1503715037
verifyFormat("operator&&(int(&&)(), class Foo);", Style);
1503815038

15039+
// PR45107
15040+
verifyFormat("operator Vector<String>&();", Style);
15041+
verifyFormat("operator foo::Bar*();", Style);
15042+
verifyFormat("operator const Foo<X>::Bar<Y>*();", Style);
15043+
verifyFormat("operator/*a*/ const /*b*/ Foo /*c*/<X> /*d*/ ::Bar<Y>*();",
15044+
Style);
15045+
1503915046
Style.PointerAlignment = FormatStyle::PAS_Middle;
1504015047
verifyFormat("Foo::operator*();", Style);
1504115048
verifyFormat("Foo::operator void *();", Style);

0 commit comments

Comments
 (0)