diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/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)) { diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp --- a/clang/unittests/Format/FormatTest.cpp +++ b/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 d > v; doesn't make sense. diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/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);