[clang] [clang-format] Fix a bug in parsing C-style cast lambda (PR #136099)
Owen Pan via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 18 20:05:16 PDT 2025
https://github.com/owenca updated https://github.com/llvm/llvm-project/pull/136099
>From 53033b278f89a508d079614eadd58b103211d5dd Mon Sep 17 00:00:00 2001
From: Owen Pan <owenpiano at gmail.com>
Date: Thu, 17 Apr 2025 00:35:19 -0700
Subject: [PATCH 1/2] [clang-format] Fix a bug in parsing C-style cast lambda
Fix #135959
---
clang/lib/Format/UnwrappedLineParser.cpp | 3 ++-
clang/unittests/Format/TokenAnnotatorTest.cpp | 5 +++++
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index b9430d4389feb..4442e965e0f51 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -2371,7 +2371,8 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
if ((Previous && ((Previous->Tok.getIdentifierInfo() &&
!Previous->isOneOf(tok::kw_return, tok::kw_co_await,
tok::kw_co_yield, tok::kw_co_return)) ||
- Previous->closesScope())) ||
+ (Previous->closesScope() &&
+ !Previous->endsSequence(tok::r_paren, tok::greater)))) ||
LeftSquare->isCppStructuredBinding(IsCpp)) {
return false;
}
diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp
index 2c7319ccefec2..7a07fbd0250be 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -2159,6 +2159,11 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
// FIXME:
// EXPECT_TOKEN(Tokens[13], tok::l_paren, TT_LambdaDefinitionLParen);
EXPECT_TOKEN(Tokens[17], tok::l_brace, TT_LambdaLBrace);
+
+ Tokens = annotate("auto foo{(std::function<int()>)[] { return 0; }};");
+ ASSERT_EQ(Tokens.size(), 23u) << Tokens;
+ EXPECT_TOKEN(Tokens[13], tok::l_square, TT_LambdaLSquare);
+ EXPECT_TOKEN(Tokens[15], tok::l_brace, TT_LambdaLBrace);
}
TEST_F(TokenAnnotatorTest, UnderstandsFunctionAnnotations) {
>From 3dd4a35e22fd58f89bb83016a66ceb112043a529 Mon Sep 17 00:00:00 2001
From: Owen Pan <owenpiano at gmail.com>
Date: Fri, 18 Apr 2025 20:04:13 -0700
Subject: [PATCH 2/2] Also handle casting to function pointer types
---
clang/lib/Format/UnwrappedLineParser.cpp | 25 +++++++++++++------
clang/unittests/Format/TokenAnnotatorTest.cpp | 5 ++++
2 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 4442e965e0f51..df58e5ef4d6a3 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -2368,14 +2368,25 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
const FormatToken *Previous = FormatTok->Previous;
const FormatToken *LeftSquare = FormatTok;
nextToken();
- if ((Previous && ((Previous->Tok.getIdentifierInfo() &&
- !Previous->isOneOf(tok::kw_return, tok::kw_co_await,
- tok::kw_co_yield, tok::kw_co_return)) ||
- (Previous->closesScope() &&
- !Previous->endsSequence(tok::r_paren, tok::greater)))) ||
- LeftSquare->isCppStructuredBinding(IsCpp)) {
- return false;
+ if (Previous) {
+ if (Previous->Tok.getIdentifierInfo() &&
+ !Previous->isOneOf(tok::kw_return, tok::kw_co_await, tok::kw_co_yield,
+ tok::kw_co_return)) {
+ return false;
+ }
+ if (Previous->closesScope()) {
+ // Not a potential C-style cast.
+ if (Previous->isNot(tok::r_paren))
+ return false;
+ const auto *BeforeRParen = Previous->getPreviousNonComment();
+ // Lambdas can be cast to function types only, e.g. `std::function<int()>`
+ // and `int (*)()`.
+ if (!BeforeRParen || !BeforeRParen->isOneOf(tok::greater, tok::r_paren))
+ return false;
+ }
}
+ if (LeftSquare->isCppStructuredBinding(IsCpp))
+ return false;
if (FormatTok->is(tok::l_square) || tok::isLiteral(FormatTok->Tok.getKind()))
return false;
if (FormatTok->is(tok::r_square)) {
diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp
index 7a07fbd0250be..596594b0cf49c 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -2164,6 +2164,11 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
ASSERT_EQ(Tokens.size(), 23u) << Tokens;
EXPECT_TOKEN(Tokens[13], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[15], tok::l_brace, TT_LambdaLBrace);
+
+ Tokens = annotate("auto foo{(int (*)())[] { return 0; }};");
+ ASSERT_EQ(Tokens.size(), 21u) << Tokens;
+ EXPECT_TOKEN(Tokens[11], tok::l_square, TT_LambdaLSquare);
+ EXPECT_TOKEN(Tokens[13], tok::l_brace, TT_LambdaLBrace);
}
TEST_F(TokenAnnotatorTest, UnderstandsFunctionAnnotations) {
More information about the cfe-commits
mailing list