[clang] eb85e90 - clang-format: Fix pointer alignment for overloaded operators (PR45107)
Hans Wennborg via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 27 02:54:16 PDT 2020
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);
More information about the cfe-commits
mailing list