Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -141,10 +141,7 @@ Contexts.size() == 2 && Contexts[0].ColonIsForRangeExpr; bool StartsObjCMethodExpr = false; - if (CurrentToken->is(tok::caret)) { - // (^ can start a block type. - Left->Type = TT_ObjCBlockLParen; - } else if (FormatToken *MaybeSel = Left->Previous) { + if (FormatToken *MaybeSel = Left->Previous) { // @selector( starts a selector. if (MaybeSel->isObjCAtKeyword(tok::objc_selector) && MaybeSel->Previous && MaybeSel->Previous->is(tok::at)) { @@ -210,8 +207,16 @@ Left->Type = TT_ObjCMethodExpr; } + // MightBeFunctionType and ProbablyFunctionType are used for + // function pointer and reference types as well as Objective-C + // block types: + // + // void (*FunctionPointer)(void); + // void (&FunctionReference)(void); + // void (^ObjCBlock)(void); bool MightBeFunctionType = !Contexts[Contexts.size() - 2].IsExpression; - bool ProbablyFunctionType = CurrentToken->isOneOf(tok::star, tok::amp); + bool ProbablyFunctionType = + CurrentToken->isOneOf(tok::star, tok::amp, tok::caret); bool HasMultipleLines = false; bool HasMultipleParametersOnALine = false; bool MightBeObjCForRangeLoop = @@ -248,7 +253,8 @@ if (MightBeFunctionType && ProbablyFunctionType && CurrentToken->Next && (CurrentToken->Next->is(tok::l_paren) || (CurrentToken->Next->is(tok::l_square) && Line.MustBeDeclaration))) - Left->Type = TT_FunctionTypeLParen; + Left->Type = Left->Next->is(tok::caret) ? TT_ObjCBlockLParen + : TT_FunctionTypeLParen; Left->MatchingParen = CurrentToken; CurrentToken->MatchingParen = Left; 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"