owenpan created this revision. owenpan added reviewers: MyDeveloperDay, HazardyKnusperkeks, rymiel. Herald added projects: All, clang, clang-format. Herald added a subscriber: cfe-commits. owenpan requested review of this revision.
A left square can start a lambda only if it's not preceded by an identifier other than `return` and `co-wait`/`co-yield`/`co-return`. Fixes https://github.com/llvm/llvm-project/issues/54245. Fixes https://github.com/llvm/llvm-project/issues/61786. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D147295 Files: clang/lib/Format/UnwrappedLineParser.cpp clang/unittests/Format/TokenAnnotatorTest.cpp Index: clang/unittests/Format/TokenAnnotatorTest.cpp =================================================================== --- clang/unittests/Format/TokenAnnotatorTest.cpp +++ clang/unittests/Format/TokenAnnotatorTest.cpp @@ -382,6 +382,32 @@ Tokens = annotate("struct [[deprecated]] [[nodiscard]] C { int i; };"); EXPECT_EQ(Tokens.size(), 19u) << Tokens; EXPECT_TOKEN(Tokens[12], tok::l_brace, TT_StructLBrace); + + Tokens = annotate("template <typename T> struct S<const T[N]> {};"); + EXPECT_EQ(Tokens.size(), 18u) << Tokens; + EXPECT_TOKEN(Tokens[7], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[10], tok::l_square, TT_ArraySubscriptLSquare); + EXPECT_TOKEN(Tokens[13], tok::greater, TT_TemplateCloser); + EXPECT_TOKEN(Tokens[14], tok::l_brace, TT_StructLBrace); + + Tokens = annotate("template <typename T> struct S<T const[N]> {};"); + EXPECT_EQ(Tokens.size(), 18u) << Tokens; + EXPECT_TOKEN(Tokens[7], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[10], tok::l_square, TT_ArraySubscriptLSquare); + EXPECT_TOKEN(Tokens[13], tok::greater, TT_TemplateCloser); + EXPECT_TOKEN(Tokens[14], tok::l_brace, TT_StructLBrace); + + Tokens = annotate("template <typename T, unsigned n> struct S<T const[n]> {\n" + " void f(T const (&a)[n]);\n" + "};"); + EXPECT_EQ(Tokens.size(), 35u) << Tokens; + EXPECT_TOKEN(Tokens[10], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[13], tok::l_square, TT_ArraySubscriptLSquare); + EXPECT_TOKEN(Tokens[16], tok::greater, TT_TemplateCloser); + EXPECT_TOKEN(Tokens[17], tok::l_brace, TT_StructLBrace); + EXPECT_TOKEN(Tokens[23], tok::l_paren, TT_FunctionTypeLParen); + EXPECT_TOKEN(Tokens[24], tok::amp, TT_UnaryOperator); + EXPECT_TOKEN(Tokens[27], tok::l_square, TT_ArraySubscriptLSquare); } TEST_F(TokenAnnotatorTest, UnderstandsUnions) { @@ -1193,6 +1219,16 @@ EXPECT_TOKEN(Tokens[9], tok::l_brace, TT_ObjCBlockLBrace); } +TEST_F(TokenAnnotatorTest, UnderstandsObjCMethodExpr) { + auto Tokens = annotate("void f() {\n" + " //\n" + " BOOL a = [b.c n] > 1;\n" + "}"); + EXPECT_EQ(Tokens.size(), 20u) << Tokens; + EXPECT_TOKEN(Tokens[9], tok::l_square, TT_ObjCMethodExpr); + EXPECT_TOKEN(Tokens[15], tok::greater, TT_BinaryOperator); +} + TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { auto Tokens = annotate("[]() constexpr {}"); ASSERT_EQ(Tokens.size(), 8u) << Tokens; Index: clang/lib/Format/UnwrappedLineParser.cpp =================================================================== --- clang/lib/Format/UnwrappedLineParser.cpp +++ clang/lib/Format/UnwrappedLineParser.cpp @@ -2231,11 +2231,11 @@ const FormatToken *Previous = FormatTok->Previous; const FormatToken *LeftSquare = FormatTok; nextToken(); - if (Previous && - (Previous->isOneOf(tok::identifier, tok::kw_operator, tok::kw_new, - tok::kw_delete, tok::l_square) || - LeftSquare->isCppStructuredBinding(Style) || Previous->closesScope() || - Previous->isSimpleTypeSpecifier())) { + if ((Previous && ((Previous->Tok.getIdentifierInfo() && + !Previous->isOneOf(tok::kw_return, tok::kw_co_await, + tok::kw_co_yield, tok::kw_co_return)) || + Previous->closesScope())) || + LeftSquare->isCppStructuredBinding(Style)) { return false; } if (FormatTok->is(tok::l_square)) @@ -3784,7 +3784,7 @@ // Don't try parsing a lambda if we had a closing parenthesis before, // it was probably a pointer to an array: int (*)[]. if (!tryToParseLambda()) - break; + continue; } else { parseSquare(); continue;
Index: clang/unittests/Format/TokenAnnotatorTest.cpp =================================================================== --- clang/unittests/Format/TokenAnnotatorTest.cpp +++ clang/unittests/Format/TokenAnnotatorTest.cpp @@ -382,6 +382,32 @@ Tokens = annotate("struct [[deprecated]] [[nodiscard]] C { int i; };"); EXPECT_EQ(Tokens.size(), 19u) << Tokens; EXPECT_TOKEN(Tokens[12], tok::l_brace, TT_StructLBrace); + + Tokens = annotate("template <typename T> struct S<const T[N]> {};"); + EXPECT_EQ(Tokens.size(), 18u) << Tokens; + EXPECT_TOKEN(Tokens[7], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[10], tok::l_square, TT_ArraySubscriptLSquare); + EXPECT_TOKEN(Tokens[13], tok::greater, TT_TemplateCloser); + EXPECT_TOKEN(Tokens[14], tok::l_brace, TT_StructLBrace); + + Tokens = annotate("template <typename T> struct S<T const[N]> {};"); + EXPECT_EQ(Tokens.size(), 18u) << Tokens; + EXPECT_TOKEN(Tokens[7], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[10], tok::l_square, TT_ArraySubscriptLSquare); + EXPECT_TOKEN(Tokens[13], tok::greater, TT_TemplateCloser); + EXPECT_TOKEN(Tokens[14], tok::l_brace, TT_StructLBrace); + + Tokens = annotate("template <typename T, unsigned n> struct S<T const[n]> {\n" + " void f(T const (&a)[n]);\n" + "};"); + EXPECT_EQ(Tokens.size(), 35u) << Tokens; + EXPECT_TOKEN(Tokens[10], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[13], tok::l_square, TT_ArraySubscriptLSquare); + EXPECT_TOKEN(Tokens[16], tok::greater, TT_TemplateCloser); + EXPECT_TOKEN(Tokens[17], tok::l_brace, TT_StructLBrace); + EXPECT_TOKEN(Tokens[23], tok::l_paren, TT_FunctionTypeLParen); + EXPECT_TOKEN(Tokens[24], tok::amp, TT_UnaryOperator); + EXPECT_TOKEN(Tokens[27], tok::l_square, TT_ArraySubscriptLSquare); } TEST_F(TokenAnnotatorTest, UnderstandsUnions) { @@ -1193,6 +1219,16 @@ EXPECT_TOKEN(Tokens[9], tok::l_brace, TT_ObjCBlockLBrace); } +TEST_F(TokenAnnotatorTest, UnderstandsObjCMethodExpr) { + auto Tokens = annotate("void f() {\n" + " //\n" + " BOOL a = [b.c n] > 1;\n" + "}"); + EXPECT_EQ(Tokens.size(), 20u) << Tokens; + EXPECT_TOKEN(Tokens[9], tok::l_square, TT_ObjCMethodExpr); + EXPECT_TOKEN(Tokens[15], tok::greater, TT_BinaryOperator); +} + TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { auto Tokens = annotate("[]() constexpr {}"); ASSERT_EQ(Tokens.size(), 8u) << Tokens; Index: clang/lib/Format/UnwrappedLineParser.cpp =================================================================== --- clang/lib/Format/UnwrappedLineParser.cpp +++ clang/lib/Format/UnwrappedLineParser.cpp @@ -2231,11 +2231,11 @@ const FormatToken *Previous = FormatTok->Previous; const FormatToken *LeftSquare = FormatTok; nextToken(); - if (Previous && - (Previous->isOneOf(tok::identifier, tok::kw_operator, tok::kw_new, - tok::kw_delete, tok::l_square) || - LeftSquare->isCppStructuredBinding(Style) || Previous->closesScope() || - Previous->isSimpleTypeSpecifier())) { + if ((Previous && ((Previous->Tok.getIdentifierInfo() && + !Previous->isOneOf(tok::kw_return, tok::kw_co_await, + tok::kw_co_yield, tok::kw_co_return)) || + Previous->closesScope())) || + LeftSquare->isCppStructuredBinding(Style)) { return false; } if (FormatTok->is(tok::l_square)) @@ -3784,7 +3784,7 @@ // Don't try parsing a lambda if we had a closing parenthesis before, // it was probably a pointer to an array: int (*)[]. if (!tryToParseLambda()) - break; + continue; } else { parseSquare(); continue;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits