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 @@ -1970,6 +1970,12 @@ if (Current.getPrecedence() == prec::Assignment) Contexts.back().VerilogAssignmentFound = true; } + if (AutoFound && Current.is(tok::equal) && Current.Previous && + Current.Previous->isNot(tok::kw_operator)) { + // AutoFound is only used for function declarations with `auto`. This + // looks like a variable declaration, so unset it. + AutoFound = false; + } Current.setType(TT_BinaryOperator); } else if (Current.is(tok::comment)) { if (Current.TokenText.startswith("/*")) { 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 @@ -1468,6 +1468,72 @@ EXPECT_TOKEN(Tokens[9], tok::colon, TT_GenericSelectionColon); } +TEST_F(TokenAnnotatorTest, UnderstandsTrailingReturnArrow) { + auto Tokens = annotate("auto f() -> int;"); + ASSERT_EQ(Tokens.size(), 8u) << Tokens; + EXPECT_TOKEN(Tokens[4], tok::arrow, TT_TrailingReturnArrow); + + Tokens = annotate("auto operator->() -> int;"); + ASSERT_EQ(Tokens.size(), 9u) << Tokens; + EXPECT_TOKEN(Tokens[2], tok::arrow, TT_OverloadedOperator); + EXPECT_TOKEN(Tokens[5], tok::arrow, TT_TrailingReturnArrow); + + Tokens = annotate("auto operator++(int) -> int;"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[6], tok::arrow, TT_TrailingReturnArrow); + + Tokens = annotate("auto operator=() -> int;"); + ASSERT_EQ(Tokens.size(), 9u) << Tokens; + EXPECT_TOKEN(Tokens[5], tok::arrow, TT_TrailingReturnArrow); + + Tokens = annotate("auto operator=(int) -> int;"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[6], tok::arrow, TT_TrailingReturnArrow); + + Tokens = annotate("auto foo() -> auto { return Val; }"); + ASSERT_EQ(Tokens.size(), 12u) << Tokens; + EXPECT_TOKEN(Tokens[4], tok::arrow, TT_TrailingReturnArrow); + + Tokens = annotate("struct S { auto bar() const -> int; };"); + ASSERT_EQ(Tokens.size(), 14u) << Tokens; + EXPECT_TOKEN(Tokens[8], tok::arrow, TT_TrailingReturnArrow); + + // Not trailing return arrows + Tokens = annotate("auto a = b->c;"); + ASSERT_EQ(Tokens.size(), 8u) << Tokens; + EXPECT_TOKEN(Tokens[4], tok::arrow, TT_Unknown); + + Tokens = annotate("auto a = (b)->c;"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[6], tok::arrow, TT_Unknown); + + Tokens = annotate("auto a = b()->c;"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[6], tok::arrow, TT_Unknown); + + Tokens = annotate("auto a = b->c();"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[4], tok::arrow, TT_Unknown); + + Tokens = annotate("decltype(auto) a = b()->c;"); + ASSERT_EQ(Tokens.size(), 13u) << Tokens; + EXPECT_TOKEN(Tokens[9], tok::arrow, TT_Unknown); + + Tokens = annotate("void f() { auto a = b->c(); }"); + ASSERT_EQ(Tokens.size(), 16u) << Tokens; + EXPECT_TOKEN(Tokens[9], tok::arrow, TT_Unknown); + + Tokens = annotate("void f() { auto a = b()->c; }"); + ASSERT_EQ(Tokens.size(), 16u) << Tokens; + EXPECT_TOKEN(Tokens[11], tok::arrow, TT_Unknown); + + // Mixed + Tokens = annotate("auto f() -> int { auto a = b()->c; }"); + ASSERT_EQ(Tokens.size(), 18u) << Tokens; + EXPECT_TOKEN(Tokens[4], tok::arrow, TT_TrailingReturnArrow); + EXPECT_TOKEN(Tokens[13], tok::arrow, TT_Unknown); +} + TEST_F(TokenAnnotatorTest, UnderstandsVerilogOperators) { auto Annotate = [this](llvm::StringRef Code) { return annotate(Code, getLLVMStyle(FormatStyle::LK_Verilog));