From 5d2624e53a6036d4ef29f7150637957c16cd519b Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Wed, 6 Feb 2013 06:20:11 +0000 Subject: [PATCH] Formatter: No space after & and * in front of ObjC message expressions. 1. let determineStarAmp() check of unary operators before checking for "is next '['". That check was added in r173150, and the test from that revision passes either way. 2. change determineStarAmp() to categorize '*' and '&' after '=' as unary operator. 3. don't let parseSquare() overwrite the type of a '*' or '&' before the start of an objc message expression if has the role of unary operator. llvm-svn: 174489 --- clang/lib/Format/TokenAnnotator.cpp | 16 ++++++++++------ clang/unittests/Format/FormatTest.cpp | 5 ++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index a90134115f7b..e1f6de390349 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -224,15 +224,19 @@ public: if (CurrentToken->is(tok::r_square)) { if (!CurrentToken->Children.empty() && CurrentToken->Children[0].is(tok::l_paren)) { - // An ObjC method call can't be followed by an open parenthesis. + // An ObjC method call is rarely followed by an open parenthesis. // FIXME: Do we incorrectly label ":" with this? StartsObjCMethodExpr = false; Left->Type = TT_Unknown; } if (StartsObjCMethodExpr) { objCSelector.markEnd(*CurrentToken); + // determineStarAmpUsage() thinks that '*' '[' is allocating an + // array of pointers, but if '[' starts a selector then '*' is a + // binary operator. if (Left->Parent != NULL && - (Left->Parent->is(tok::star) || Left->Parent->is(tok::amp))) + (Left->Parent->is(tok::star) || Left->Parent->is(tok::amp)) && + Left->Parent->Type == TT_PointerOrReference) Left->Parent->Type = TT_BinaryOperator; } Left->MatchingParen = CurrentToken; @@ -607,16 +611,16 @@ private: if (NextToken == NULL) return TT_Unknown; - if (NextToken->is(tok::l_square)) - return TT_PointerOrReference; - if (PrevToken->is(tok::l_paren) || PrevToken->is(tok::l_square) || PrevToken->is(tok::l_brace) || PrevToken->is(tok::comma) || PrevToken->is(tok::kw_return) || PrevToken->is(tok::colon) || - PrevToken->Type == TT_BinaryOperator || + PrevToken->is(tok::equal) || PrevToken->Type == TT_BinaryOperator || PrevToken->Type == TT_UnaryOperator || PrevToken->Type == TT_CastRParen) return TT_UnaryOperator; + if (NextToken->is(tok::l_square)) + return TT_PointerOrReference; + if (PrevToken->FormatTok.Tok.isLiteral() || PrevToken->is(tok::r_paren) || PrevToken->is(tok::r_square) || NextToken->FormatTok.Tok.isLiteral() || isUnaryOperator(*NextToken) || NextToken->is(tok::l_paren) || diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index fc52e834aab8..fbe5f30f70bf 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -2245,9 +2245,8 @@ TEST_F(FormatTest, FormatObjCMethodExpr) { verifyFormat("int a = --[foo bar:baz];"); verifyFormat("int a = sizeof [foo bar:baz];"); verifyFormat("int a = alignof [foo bar:baz];"); - // FIXME: no space after & and *. - verifyFormat("int a = & [foo bar:baz];"); - verifyFormat("int a = * [foo bar:baz];"); + verifyFormat("int a = &[foo bar:baz];"); + verifyFormat("int a = *[foo bar:baz];"); // FIXME: Make casts work, without breaking f()[4]. //verifyFormat("int a = (int) [foo bar:baz];");