Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -142,8 +142,32 @@ bool StartsObjCMethodExpr = false; if (CurrentToken->is(tok::caret)) { - // (^ can start a block type. - Left->Type = TT_ObjCBlockLParen; + // The following are valid ObjC block types and block variables: + // + // int (^)(char, float) + // int (^block)(char, float) + // int (^arrayOfTenBlocks[10])(char, float) + // int (^arrayOfManyBlocks[(kLen + 42)])(char, float) + const FormatToken *Next = CurrentToken->getNextNonComment(); + int ParenDepth = 1; + // Handle nested parens in case we have an array of blocks with + // a parenthesized length. + while (Next) { + if (Next->is(tok::l_paren)) + ++ParenDepth; + else if (Next->is(tok::r_paren)) + --ParenDepth; + if (ParenDepth == 0) + break; + Next = Next->getNextNonComment(); + } + if (Next) { + const FormatToken *NextNext = Next->getNextNonComment(); + // If we have an opening paren at the end of (^...)( we assume + // we have an Objective-C block. + if (NextNext && NextNext->is(tok::l_paren)) + Left->Type = TT_ObjCBlockLParen; + } } else if (FormatToken *MaybeSel = Left->Previous) { // @selector( starts a selector. if (MaybeSel->isObjCAtKeyword(tok::objc_selector) && MaybeSel->Previous && Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -12128,6 +12128,22 @@ EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "[[foo::bar, ...]]")); } +TEST_F(FormatTest, GuessLanguageWithCaret) { + EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "FOO(^);")); + EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "FOO(^, Bar);")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "int(^)(char, float);")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "int(^foo)(char, float);")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "int(^foo[10])(char, float);")); + EXPECT_EQ(FormatStyle::LK_ObjC, + guessLanguage("foo.h", "int(^foo[kNumEntries])(char, float);")); + EXPECT_EQ( + FormatStyle::LK_ObjC, + guessLanguage("foo.h", "int(^foo[(kNumEntries + 10)])(char, float);")); +} + } // end namespace } // end namespace format } // end namespace clang Index: unittests/Format/FormatTestObjC.cpp =================================================================== --- unittests/Format/FormatTestObjC.cpp +++ unittests/Format/FormatTestObjC.cpp @@ -845,6 +845,15 @@ verifyFormat("@ /*foo*/ interface"); } +TEST_F(FormatTestObjC, ObjCBlockTypesAndVariables) { + verifyFormat("void DoStuffWithBlockType(int (^)(char));"); + verifyFormat("int (^foo)(char, float);"); + verifyFormat("int (^foo[10])(char, float);"); + verifyFormat("int (^foo[kNumEntries])(char, float);"); + verifyFormat("int (^foo[kNumEntries + 10])(char, float);"); + verifyFormat("int (^foo[(kNumEntries + 10)])(char, float);"); +} + TEST_F(FormatTestObjC, ObjCSnippets) { verifyFormat("@autoreleasepool {\n" " foo();\n"