Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -756,64 +756,7 @@ else Current.Type = TT_BlockComment; } else if (Current.is(tok::r_paren)) { - // FIXME: Pull cast detection into its own function. - FormatToken *LeftOfParens = NULL; - if (Current.MatchingParen) - LeftOfParens = Current.MatchingParen->getPreviousNonComment(); - bool IsCast = false; - bool ParensAreEmpty = Current.Previous == Current.MatchingParen; - bool ParensAreType = !Current.Previous || - Current.Previous->Type == TT_PointerOrReference || - Current.Previous->Type == TT_TemplateCloser || - Current.Previous->isSimpleTypeSpecifier(); - bool ParensCouldEndDecl = - Current.Next && - Current.Next->isOneOf(tok::equal, tok::semi, tok::l_brace); - bool IsSizeOfOrAlignOf = - LeftOfParens && - LeftOfParens->isOneOf(tok::kw_sizeof, tok::kw_alignof); - if (ParensAreType && !ParensCouldEndDecl && !IsSizeOfOrAlignOf && - ((Contexts.size() > 1 && - Contexts[Contexts.size() - 2].IsExpression) || - (Current.Next && Current.Next->isBinaryOperator()))) - IsCast = true; - else if (Current.Next && Current.Next->isNot(tok::string_literal) && - (Current.Next->Tok.isLiteral() || - Current.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof))) - IsCast = true; - // If there is an identifier after the (), it is likely a cast, unless - // there is also an identifier before the (). - else if (LeftOfParens && - (LeftOfParens->Tok.getIdentifierInfo() == NULL || - LeftOfParens->is(tok::kw_return)) && - LeftOfParens->Type != TT_OverloadedOperator && - LeftOfParens->isNot(tok::at) && - LeftOfParens->Type != TT_TemplateCloser && Current.Next) { - if (Current.Next->isOneOf(tok::identifier, tok::numeric_constant)) { - IsCast = true; - } else { - // Use heuristics to recognize c style casting. - FormatToken *Prev = Current.Previous; - if (Prev && Prev->isOneOf(tok::amp, tok::star)) - Prev = Prev->Previous; - - if (Prev && Current.Next && Current.Next->Next) { - bool NextIsUnary = Current.Next->isUnaryOperator() || - Current.Next->isOneOf(tok::amp, tok::star); - IsCast = NextIsUnary && - Current.Next->Next->isOneOf(tok::identifier, - tok::numeric_constant); - } - - for (; Prev != Current.MatchingParen; Prev = Prev->Previous) { - if (!Prev || !Prev->isOneOf(tok::kw_const, tok::identifier)) { - IsCast = false; - break; - } - } - } - } - if (IsCast && !ParensAreEmpty) + if (rParenEndsCast(Current)) Current.Type = TT_CastRParen; } else if (Current.is(tok::at) && Current.Next) { switch (Current.Next->Tok.getObjCKeywordID()) { @@ -874,6 +817,63 @@ PreviousNotConst->isSimpleTypeSpecifier(); } + /// \brief Determine whether ')' is ending a cast. + bool rParenEndsCast(const FormatToken &Tok) { + FormatToken *LeftOfParens = NULL; + if (Tok.MatchingParen) + LeftOfParens = Tok.MatchingParen->getPreviousNonComment(); + bool IsCast = false; + bool ParensAreEmpty = Tok.Previous == Tok.MatchingParen; + bool ParensAreType = !Tok.Previous || + Tok.Previous->Type == TT_PointerOrReference || + Tok.Previous->Type == TT_TemplateCloser || + Tok.Previous->isSimpleTypeSpecifier(); + bool ParensCouldEndDecl = + Tok.Next && Tok.Next->isOneOf(tok::equal, tok::semi, tok::l_brace); + bool IsSizeOfOrAlignOf = + LeftOfParens && LeftOfParens->isOneOf(tok::kw_sizeof, tok::kw_alignof); + if (ParensAreType && !ParensCouldEndDecl && !IsSizeOfOrAlignOf && + ((Contexts.size() > 1 && Contexts[Contexts.size() - 2].IsExpression) || + (Tok.Next && Tok.Next->isBinaryOperator()))) + IsCast = true; + else if (Tok.Next && Tok.Next->isNot(tok::string_literal) && + (Tok.Next->Tok.isLiteral() || + Tok.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof))) + IsCast = true; + // If there is an identifier after the (), it is likely a cast, unless + // there is also an identifier before the (). + else if (LeftOfParens && (LeftOfParens->Tok.getIdentifierInfo() == NULL || + LeftOfParens->is(tok::kw_return)) && + LeftOfParens->Type != TT_OverloadedOperator && + LeftOfParens->isNot(tok::at) && + LeftOfParens->Type != TT_TemplateCloser && Tok.Next) { + if (Tok.Next->isOneOf(tok::identifier, tok::numeric_constant)) { + IsCast = true; + } else { + // Use heuristics to recognize c style casting. + FormatToken *Prev = Tok.Previous; + if (Prev && Prev->isOneOf(tok::amp, tok::star)) + Prev = Prev->Previous; + + if (Prev && Tok.Next && Tok.Next->Next) { + bool NextIsUnary = Tok.Next->isUnaryOperator() || + Tok.Next->isOneOf(tok::amp, tok::star); + IsCast = + NextIsUnary && + Tok.Next->Next->isOneOf(tok::identifier, tok::numeric_constant); + } + + for (; Prev != Tok.MatchingParen; Prev = Prev->Previous) { + if (!Prev || !Prev->isOneOf(tok::kw_const, tok::identifier)) { + IsCast = false; + break; + } + } + } + } + return IsCast && !ParensAreEmpty; + } + /// \brief Return the type of the given token assuming it is * or &. TokenType determineStarAmpUsage(const FormatToken &Tok, bool IsExpression, bool InTemplateArgument) {