summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Format/TokenAnnotator.cpp34
-rw-r--r--clang/unittests/Format/FormatTest.cpp90
2 files changed, 117 insertions, 7 deletions
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 3bd415ebd69..d3c9dd56f97 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -950,9 +950,9 @@ private:
if (CurrentToken->isOneOf(tok::star, tok::amp))
CurrentToken->Type = TT_PointerOrReference;
consumeToken();
- if (CurrentToken &&
- CurrentToken->Previous->isOneOf(TT_BinaryOperator, TT_UnaryOperator,
- tok::comma))
+ if (CurrentToken && CurrentToken->Previous->isOneOf(
+ TT_BinaryOperator, TT_UnaryOperator, tok::comma,
+ tok::star, tok::arrow, tok::amp, tok::ampamp))
CurrentToken->Previous->Type = TT_OverloadedOperator;
}
if (CurrentToken) {
@@ -1344,8 +1344,12 @@ private:
Contexts.back().IsExpression = false;
} else if (Current.is(tok::kw_new)) {
Contexts.back().CanBeExpression = false;
- } else if (Current.isOneOf(tok::semi, tok::exclaim)) {
+ } else if (Current.is(tok::semi) ||
+ (Current.is(tok::exclaim) && Current.Previous &&
+ !Current.Previous->is(tok::kw_operator))) {
// This should be the condition or increment in a for-loop.
+ // But not operator !() (can't use TT_OverloadedOperator here as its not
+ // been annotated yet).
Contexts.back().IsExpression = true;
}
}
@@ -2155,11 +2159,22 @@ static bool isFunctionDeclarationName(const FormatToken &Current,
continue;
if (Next->isOneOf(tok::kw_new, tok::kw_delete)) {
// For 'new[]' and 'delete[]'.
- if (Next->Next && Next->Next->is(tok::l_square) && Next->Next->Next &&
- Next->Next->Next->is(tok::r_square))
+ if (Next->Next &&
+ Next->Next->startsSequence(tok::l_square, tok::r_square))
Next = Next->Next->Next;
continue;
}
+ if (Next->startsSequence(tok::l_square, tok::r_square)) {
+ // For operator[]().
+ Next = Next->Next;
+ continue;
+ }
+ if ((Next->isSimpleTypeSpecifier() || Next->is(tok::identifier)) &&
+ Next->Next && Next->Next->isOneOf(tok::star, tok::amp, tok::ampamp)) {
+ // For operator void*(), operator char*(), operator Foo*().
+ Next = Next->Next;
+ continue;
+ }
break;
}
@@ -2673,6 +2688,13 @@ 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()) &&
+ Left.Previous && Left.Previous->is(tok::kw_operator))
+ // Space between the type and the *
+ // operator void*(), operator char*(), operator Foo*() dependant
+ // on PointerAlignment style.
+ return (Style.PointerAlignment == FormatStyle::PAS_Right);
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 eacb389400b..cef2b0b2755 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -6134,7 +6134,48 @@ TEST_F(FormatTest, ReturnTypeBreakingStyle) {
"void\n"
"A::operator>>() {}\n"
"void\n"
- "A::operator+() {}\n",
+ "A::operator+() {}\n"
+ "void\n"
+ "A::operator*() {}\n"
+ "void\n"
+ "A::operator->() {}\n"
+ "void\n"
+ "A::operator void *() {}\n"
+ "void\n"
+ "A::operator void &() {}\n"
+ "void\n"
+ "A::operator void &&() {}\n"
+ "void\n"
+ "A::operator char *() {}\n"
+ "void\n"
+ "A::operator[]() {}\n"
+ "void\n"
+ "A::operator!() {}\n",
+ Style);
+ verifyFormat("constexpr auto\n"
+ "operator()() const -> reference {}\n"
+ "constexpr auto\n"
+ "operator>>() const -> reference {}\n"
+ "constexpr auto\n"
+ "operator+() const -> reference {}\n"
+ "constexpr auto\n"
+ "operator*() const -> reference {}\n"
+ "constexpr auto\n"
+ "operator->() const -> reference {}\n"
+ "constexpr auto\n"
+ "operator++() const -> reference {}\n"
+ "constexpr auto\n"
+ "operator void *() const -> reference {}\n"
+ "constexpr auto\n"
+ "operator void &() const -> reference {}\n"
+ "constexpr auto\n"
+ "operator void &&() const -> reference {}\n"
+ "constexpr auto\n"
+ "operator char *() const -> reference {}\n"
+ "constexpr auto\n"
+ "operator!() const -> reference {}\n"
+ "constexpr auto\n"
+ "operator[]() const -> reference {}\n",
Style);
verifyFormat("void *operator new(std::size_t s);", // No break here.
Style);
@@ -14755,6 +14796,53 @@ TEST_F(FormatTest, STLWhileNotDefineChed) {
"#endif // while");
}
+TEST_F(FormatTest, OperatorSpacing) {
+ FormatStyle Style = getLLVMStyle();
+ Style.PointerAlignment = FormatStyle::PAS_Right;
+ verifyFormat("Foo::operator*();", Style);
+ verifyFormat("Foo::operator void *();", Style);
+ verifyFormat("Foo::operator()(void *);", Style);
+ verifyFormat("Foo::operator*(void *);", Style);
+ verifyFormat("Foo::operator*();", Style);
+ verifyFormat("operator*(int (*)(), class Foo);", Style);
+
+ verifyFormat("Foo::operator&();", Style);
+ verifyFormat("Foo::operator void &();", Style);
+ verifyFormat("Foo::operator()(void &);", Style);
+ verifyFormat("Foo::operator&(void &);", Style);
+ verifyFormat("Foo::operator&();", Style);
+ verifyFormat("operator&(int (&)(), class Foo);", Style);
+
+ verifyFormat("Foo::operator&&();", Style);
+ verifyFormat("Foo::operator void &&();", Style);
+ verifyFormat("Foo::operator()(void &&);", Style);
+ verifyFormat("Foo::operator&&(void &&);", Style);
+ verifyFormat("Foo::operator&&();", Style);
+ verifyFormat("operator&&(int(&&)(), class Foo);", Style);
+
+ Style.PointerAlignment = FormatStyle::PAS_Left;
+ verifyFormat("Foo::operator*();", Style);
+ verifyFormat("Foo::operator void*();", Style);
+ verifyFormat("Foo::operator()(void*);", Style);
+ verifyFormat("Foo::operator*(void*);", Style);
+ verifyFormat("Foo::operator*();", Style);
+ verifyFormat("operator*(int (*)(), class Foo);", Style);
+
+ verifyFormat("Foo::operator&();", Style);
+ verifyFormat("Foo::operator void&();", Style);
+ verifyFormat("Foo::operator()(void&);", Style);
+ verifyFormat("Foo::operator&(void&);", Style);
+ verifyFormat("Foo::operator&();", Style);
+ verifyFormat("operator&(int (&)(), class Foo);", Style);
+
+ verifyFormat("Foo::operator&&();", Style);
+ verifyFormat("Foo::operator void&&();", Style);
+ verifyFormat("Foo::operator()(void&&);", Style);
+ verifyFormat("Foo::operator&&(void&&);", Style);
+ verifyFormat("Foo::operator&&();", Style);
+ verifyFormat("operator&&(int(&&)(), class Foo);", Style);
+}
+
} // namespace
} // namespace format
} // namespace clang
OpenPOWER on IntegriCloud