This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG3f3620e5c9ee: [clang-format] Correctly annotate
*/&/&& in operator function calls (authored by owenpan).
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D154184/new/
https://reviews.llvm.org/D154184
Files:
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/FormatTest.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp
Index: clang/unittests/Format/TokenAnnotatorTest.cpp
===================================================================
--- clang/unittests/Format/TokenAnnotatorTest.cpp
+++ clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -594,61 +594,59 @@
TEST_F(TokenAnnotatorTest, UnderstandsOverloadedOperators) {
auto Tokens = annotate("x.operator+()");
ASSERT_EQ(Tokens.size(), 7u) << Tokens;
- EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_FunctionDeclarationName);
+ EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_Unknown);
EXPECT_TOKEN(Tokens[3], tok::plus, TT_OverloadedOperator);
EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_OverloadedOperatorLParen);
Tokens = annotate("x.operator=()");
ASSERT_EQ(Tokens.size(), 7u) << Tokens;
- EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_FunctionDeclarationName);
+ EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_Unknown);
EXPECT_TOKEN(Tokens[3], tok::equal, TT_OverloadedOperator);
EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_OverloadedOperatorLParen);
Tokens = annotate("x.operator+=()");
ASSERT_EQ(Tokens.size(), 7u) << Tokens;
- EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_FunctionDeclarationName);
+ EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_Unknown);
EXPECT_TOKEN(Tokens[3], tok::plusequal, TT_OverloadedOperator);
EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_OverloadedOperatorLParen);
Tokens = annotate("x.operator,()");
ASSERT_EQ(Tokens.size(), 7u) << Tokens;
- EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_FunctionDeclarationName);
+ EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_Unknown);
EXPECT_TOKEN(Tokens[3], tok::comma, TT_OverloadedOperator);
EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_OverloadedOperatorLParen);
Tokens = annotate("x.operator()()");
ASSERT_EQ(Tokens.size(), 8u) << Tokens;
- EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_FunctionDeclarationName);
+ EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_Unknown);
EXPECT_TOKEN(Tokens[3], tok::l_paren, TT_OverloadedOperator);
EXPECT_TOKEN(Tokens[4], tok::r_paren, TT_OverloadedOperator);
EXPECT_TOKEN(Tokens[5], tok::l_paren, TT_OverloadedOperatorLParen);
Tokens = annotate("x.operator[]()");
ASSERT_EQ(Tokens.size(), 8u) << Tokens;
- EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_FunctionDeclarationName);
+ EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_Unknown);
// EXPECT_TOKEN(Tokens[3], tok::l_square, TT_OverloadedOperator);
// EXPECT_TOKEN(Tokens[4], tok::r_square, TT_OverloadedOperator);
EXPECT_TOKEN(Tokens[5], tok::l_paren, TT_OverloadedOperatorLParen);
Tokens = annotate("x.operator\"\"_a()");
ASSERT_EQ(Tokens.size(), 7u) << Tokens;
- EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_FunctionDeclarationName);
+ EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_Unknown);
EXPECT_TOKEN(Tokens[3], tok::string_literal, TT_OverloadedOperator);
EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_OverloadedOperatorLParen);
Tokens = annotate("x.operator\"\" _a()");
ASSERT_EQ(Tokens.size(), 8u) << Tokens;
- // FIXME
- // EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_FunctionDeclarationName);
+ EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_Unknown);
EXPECT_TOKEN(Tokens[3], tok::string_literal, TT_OverloadedOperator);
EXPECT_TOKEN(Tokens[5], tok::l_paren, TT_OverloadedOperatorLParen);
Tokens = annotate("x.operator\"\"if()");
ASSERT_EQ(Tokens.size(), 7u) << Tokens;
- EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_FunctionDeclarationName);
+ EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_Unknown);
EXPECT_TOKEN(Tokens[3], tok::string_literal, TT_OverloadedOperator);
EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_OverloadedOperatorLParen);
Tokens = annotate("x.operator\"\"s()");
ASSERT_EQ(Tokens.size(), 7u) << Tokens;
- EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_FunctionDeclarationName);
+ EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_Unknown);
EXPECT_TOKEN(Tokens[3], tok::string_literal, TT_OverloadedOperator);
EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_OverloadedOperatorLParen);
Tokens = annotate("x.operator\"\" s()");
ASSERT_EQ(Tokens.size(), 8u) << Tokens;
- // FIXME
- // EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_FunctionDeclarationName);
+ EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_Unknown);
EXPECT_TOKEN(Tokens[3], tok::string_literal, TT_OverloadedOperator);
EXPECT_TOKEN(Tokens[5], tok::l_paren, TT_OverloadedOperatorLParen);
@@ -678,20 +676,44 @@
EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_OverloadedOperatorLParen);
EXPECT_TOKEN(Tokens[8], tok::star, TT_PointerOrReference);
+ Tokens = annotate("class Foo {\n"
+ " int c = operator+(a * b);\n"
+ "}");
+ ASSERT_EQ(Tokens.size(), 16u) << Tokens;
+ EXPECT_TOKEN(Tokens[6], tok::kw_operator, TT_Unknown);
+ EXPECT_TOKEN(Tokens[7], tok::plus, TT_OverloadedOperator);
+ EXPECT_TOKEN(Tokens[8], tok::l_paren, TT_OverloadedOperatorLParen);
+ EXPECT_TOKEN(Tokens[10], tok::star, TT_BinaryOperator);
+
Tokens = annotate("void foo() {\n"
" operator+(a * b);\n"
"}");
ASSERT_EQ(Tokens.size(), 15u) << Tokens;
+ EXPECT_TOKEN(Tokens[5], tok::kw_operator, TT_Unknown);
EXPECT_TOKEN(Tokens[6], tok::plus, TT_OverloadedOperator);
EXPECT_TOKEN(Tokens[7], tok::l_paren, TT_OverloadedOperatorLParen);
EXPECT_TOKEN(Tokens[9], tok::star, TT_BinaryOperator);
+ Tokens = annotate("return operator+(a * b, c & d) + operator+(a && b && c);");
+ ASSERT_EQ(Tokens.size(), 24u) << Tokens;
+ EXPECT_TOKEN(Tokens[1], tok::kw_operator, TT_Unknown);
+ EXPECT_TOKEN(Tokens[2], tok::plus, TT_OverloadedOperator);
+ EXPECT_TOKEN(Tokens[3], tok::l_paren, TT_OverloadedOperatorLParen);
+ EXPECT_TOKEN(Tokens[5], tok::star, TT_BinaryOperator);
+ EXPECT_TOKEN(Tokens[9], tok::amp, TT_BinaryOperator);
+ EXPECT_TOKEN(Tokens[13], tok::kw_operator, TT_Unknown);
+ EXPECT_TOKEN(Tokens[14], tok::plus, TT_OverloadedOperator);
+ EXPECT_TOKEN(Tokens[15], tok::l_paren, TT_OverloadedOperatorLParen);
+ EXPECT_TOKEN(Tokens[17], tok::ampamp, TT_BinaryOperator);
+ EXPECT_TOKEN(Tokens[19], tok::ampamp, TT_BinaryOperator);
+
Tokens = annotate("class Foo {\n"
" void foo() {\n"
" operator+(a * b);\n"
" }\n"
"}");
ASSERT_EQ(Tokens.size(), 19u) << Tokens;
+ EXPECT_TOKEN(Tokens[8], tok::kw_operator, TT_Unknown);
EXPECT_TOKEN(Tokens[9], tok::plus, TT_OverloadedOperator);
EXPECT_TOKEN(Tokens[10], tok::l_paren, TT_OverloadedOperatorLParen);
EXPECT_TOKEN(Tokens[12], tok::star, TT_BinaryOperator);
Index: clang/unittests/Format/FormatTest.cpp
===================================================================
--- clang/unittests/Format/FormatTest.cpp
+++ clang/unittests/Format/FormatTest.cpp
@@ -11580,13 +11580,11 @@
" }",
getLLVMStyleWithColumns(50)));
-// FIXME: We should be able to figure out this is an operator call
-#if 0
verifyFormat("#define FOO \\\n"
" void foo() { \\\n"
" operator+(a * b); \\\n"
- " }", getLLVMStyleWithColumns(25));
-#endif
+ " }",
+ getLLVMStyleWithColumns(25));
// FIXME: We cannot handle this case yet; we might be able to figure out that
// foo<x> d > v; doesn't make sense.
Index: clang/lib/Format/TokenAnnotator.cpp
===================================================================
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -310,14 +310,9 @@
// If faced with "a.operator*(argument)" or "a->operator*(argument)",
// i.e. the operator is called as a member function,
// then the argument must be an expression.
- // If faced with "operator+(argument)", i.e. the operator is called as
- // a free function, then the argument is an expression only if the current
- // line can't be a declaration.
- bool IsOperatorCallSite =
- (Prev->Previous &&
- Prev->Previous->isOneOf(tok::period, tok::arrow)) ||
- (!Line.MustBeDeclaration && !Line.InMacroBody);
- Contexts.back().IsExpression = IsOperatorCallSite;
+ bool OperatorCalledAsMemberFunction =
+ Prev->Previous && Prev->Previous->isOneOf(tok::period, tok::arrow);
+ Contexts.back().IsExpression = OperatorCalledAsMemberFunction;
} else if (OpeningParen.is(TT_VerilogInstancePortLParen)) {
Contexts.back().IsExpression = true;
Contexts.back().ContextType = Context::VerilogInstancePortList;
@@ -3133,6 +3128,7 @@
// function declaration.
static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
const AnnotatedLine &Line) {
+ assert(Current.Previous);
auto skipOperatorName = [](const FormatToken *Next) -> const FormatToken * {
for (; Next; Next = Next->Next) {
if (Next->is(TT_OverloadedOperatorLParen))
@@ -3171,7 +3167,12 @@
// Find parentheses of parameter list.
const FormatToken *Next = Current.Next;
if (Current.is(tok::kw_operator)) {
- if (Current.Previous && Current.Previous->is(tok::coloncolon))
+ const auto *Previous = Current.Previous;
+ if (Previous->Tok.getIdentifierInfo() &&
+ !Previous->isOneOf(tok::kw_return, tok::kw_co_return)) {
+ return true;
+ }
+ if (!Previous->isOneOf(tok::star, tok::amp, tok::ampamp))
return false;
Next = skipOperatorName(Next);
} else {
@@ -3302,9 +3303,11 @@
if (AlignArrayOfStructures)
calculateArrayInitializerColumnList(Line);
+ bool LineIsFunctionDeclaration = false;
for (FormatToken *Tok = Current, *AfterLastAttribute = nullptr; Tok;
Tok = Tok->Next) {
if (isFunctionDeclarationName(Style.isCpp(), *Tok, Line)) {
+ LineIsFunctionDeclaration = true;
Tok->setType(TT_FunctionDeclarationName);
if (AfterLastAttribute &&
mustBreakAfterAttributes(*AfterLastAttribute, Style)) {
@@ -3317,6 +3320,33 @@
AfterLastAttribute = Tok;
}
+ if (Style.isCpp() && !LineIsFunctionDeclaration) {
+ // Annotate */&/&& in `operator` function calls as binary operators.
+ for (const auto *Tok = Line.First; Tok; Tok = Tok->Next) {
+ if (Tok->isNot(tok::kw_operator))
+ continue;
+ do {
+ Tok = Tok->Next;
+ } while (Tok && Tok->isNot(TT_OverloadedOperatorLParen));
+ if (!Tok)
+ break;
+ const auto *LeftParen = Tok;
+ for (Tok = Tok->Next; Tok && Tok != LeftParen->MatchingParen;
+ Tok = Tok->Next) {
+ if (Tok->isNot(tok::identifier))
+ continue;
+ auto *Next = Tok->Next;
+ const bool NextIsBinaryOperator =
+ Next && Next->isOneOf(tok::star, tok::amp, tok::ampamp) &&
+ Next->Next && Next->Next->is(tok::identifier);
+ if (!NextIsBinaryOperator)
+ continue;
+ Next->setType(TT_BinaryOperator);
+ Tok = Next;
+ }
+ }
+ }
+
while (Current) {
const FormatToken *Prev = Current->Previous;
if (Current->is(TT_LineComment)) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits