Author: andre Date: 2026-09-04T16:29:15Z New Revision: c7ba46e37d78cb39c3940f255ec907930f85e577
URL: https://github.com/llvm/llvm-project/commit/c7ba46e37d78cb39c3940f255ec907930f85e577 DIFF: https://github.com/llvm/llvm-project/commit/c7ba46e37d78cb39c3940f255ec907930f85e577.diff LOG: [clang-format] Parse ObjC generics in block literal return types (#220995) The unwrapped line parser handled a block literal's return type as a single identifier or type keyword followed by optional stars. A return type carrying ObjC generics or a protocol qualifier, such as `^NSArray<NSString *> *(int x) { ... }` or `^id<Proto>(int x) { ... }`, was therefore not recognized as a block, and its body was treated as a function body instead. This collapsed the body like a short function and, with `RemoveSemicolon: true`, dropped the semicolon terminating the enclosing statement, producing code that no longer compiles. Skip a balanced angle-bracket list after the return type before looking for the parameter list and body. Fixes #219713 Assisted-by: Claude Code Added: Modified: clang/lib/Format/UnwrappedLineParser.cpp clang/unittests/Format/TokenAnnotatorTest.cpp Removed: ################################################################################ diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 810512c1a7477..f2ea03b86aae4 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -1975,6 +1975,11 @@ void UnwrappedLineParser::parseStructuralElement( // Block return type. if (FormatTok->Tok.isAnyIdentifier() || FormatTok->isTypeName(LangOpts)) { nextToken(); + // Return types: ObjC generics and protocol qualifiers are ok too. + if (FormatTok->is(tok::less)) { + nextToken(); + parseBracedList(/*IsAngleBracket=*/true); + } // Return types: pointers are ok too. while (FormatTok->is(tok::star)) nextToken(); diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index b71147aaf1bc2..f5ff5229f7232 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -2074,6 +2074,30 @@ TEST_F(TokenAnnotatorTest, UnderstandsObjCBlock) { ASSERT_EQ(Tokens.size(), 27u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::identifier, TT_Unknown); // Not CtorDtorDeclName. EXPECT_TOKEN(Tokens[1], tok::l_paren, TT_ObjCBlockLParen); + + Tokens = annotate("id p = ^NSArray<NSString *> *() {\n" + " return nil;\n" + "};"); + ASSERT_EQ(Tokens.size(), 19u) << Tokens; + EXPECT_TOKEN(Tokens[12], tok::l_brace, TT_ObjCBlockLBrace); + + Tokens = annotate("id p = ^NSArray<NSArray<NSString *> *> *(int) {\n" + " return nil;\n" + "};"); + ASSERT_EQ(Tokens.size(), 24u) << Tokens; + EXPECT_TOKEN(Tokens[17], tok::l_brace, TT_ObjCBlockLBrace); + + Tokens = annotate("id p = ^id<Proto>(int x) {\n" + " return nil;\n" + "};"); + ASSERT_EQ(Tokens.size(), 19u) << Tokens; + EXPECT_TOKEN(Tokens[12], tok::l_brace, TT_ObjCBlockLBrace); + + Tokens = annotate("id p = ^NSDictionary<NSString *, NSString *> *(int x) {\n" + " return nil;\n" + "};"); + ASSERT_EQ(Tokens.size(), 24u) << Tokens; + EXPECT_TOKEN(Tokens[17], tok::l_brace, TT_ObjCBlockLBrace); } TEST_F(TokenAnnotatorTest, UnderstandsObjCMethodExpr) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
