Author: djasper Date: Mon Nov 23 09:55:55 2015 New Revision: 253873 URL: http://llvm.org/viewvc/llvm-project?rev=253873&view=rev Log: clang-format: Signficantly refactor the cast detection.
No functional changes intended. Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=253873&r1=253872&r2=253873&view=diff ============================================================================== --- cfe/trunk/lib/Format/TokenAnnotator.cpp (original) +++ cfe/trunk/lib/Format/TokenAnnotator.cpp Mon Nov 23 09:55:55 2015 @@ -1057,74 +1057,85 @@ private: /// \brief Determine whether ')' is ending a cast. bool rParenEndsCast(const FormatToken &Tok) { - FormatToken *LeftOfParens = nullptr; - if (Tok.MatchingParen) - LeftOfParens = Tok.MatchingParen->getPreviousNonComment(); + // C-style casts are only used in C++ and Java. + if (Style.Language != FormatStyle::LK_Cpp && + Style.Language != FormatStyle::LK_Java) + return false; + // Empty parens aren't casts and there are no casts at the end of the line. + if (Tok.Previous == Tok.MatchingParen || !Tok.Next || !Tok.MatchingParen) + return false; + + FormatToken *LeftOfParens = Tok.MatchingParen->getPreviousNonComment(); if (LeftOfParens) { + // If there is an identifier (or with a few exceptions a keyword) right + // before the parentheses, this is unlikely to be a cast. if (LeftOfParens->Tok.getIdentifierInfo() && !LeftOfParens->isOneOf(Keywords.kw_in, tok::kw_return, tok::kw_case, tok::kw_delete)) return false; - if (LeftOfParens->isOneOf(tok::kw_sizeof, tok::kw_alignof, tok::at, - tok::r_square, TT_OverloadedOperator, + + // Certain other tokens right before the parentheses are also signals that + // this cannot be a cast. + if (LeftOfParens->isOneOf(tok::at, tok::r_square, TT_OverloadedOperator, TT_TemplateCloser)) return false; - if (LeftOfParens->is(tok::r_paren) && LeftOfParens->MatchingParen) - LeftOfParens = LeftOfParens->MatchingParen->Previous; } - if (Tok.Next) { - if (Tok.Next->is(tok::question)) - return false; - if (Style.Language == FormatStyle::LK_JavaScript && - Tok.Next->is(Keywords.kw_in)) - return false; - if (Style.Language == FormatStyle::LK_Java && Tok.Next->is(tok::l_paren)) - return true; - } - bool IsCast = false; - bool ParensAreEmpty = Tok.Previous == Tok.MatchingParen; + + if (Tok.Next->is(tok::question)) + return false; + + // As Java has no function types, a "(" after the ")" likely means that this + // is a cast. + if (Style.Language == FormatStyle::LK_Java && Tok.Next->is(tok::l_paren)) + return true; + + // If a (non-string) literal follows, this is likely a cast. + if (Tok.Next->isNot(tok::string_literal) && + (Tok.Next->Tok.isLiteral() || + Tok.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof))) + return true; + + // Heuristically try to determine whether the parentheses contain a type. bool ParensAreType = !Tok.Previous || Tok.Previous->isOneOf(TT_PointerOrReference, TT_TemplateCloser) || Tok.Previous->isSimpleTypeSpecifier(); bool ParensCouldEndDecl = - Tok.Next && Tok.Next->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater); if (ParensAreType && !ParensCouldEndDecl && (Contexts.size() > 1 && Contexts[Contexts.size() - 2].IsExpression)) - 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; - else if (LeftOfParens && 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->is(tok::plus) && - 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, tok::coloncolon)) { - IsCast = false; - break; - } - } - } + return true; + + // At this point, we heuristically assume that there are no casts at the + // start of the line. We assume that we have found most cases where there + // are by the logic above, e.g. "(void)x;". + if (!LeftOfParens) + return false; + + // If the following token is an identifier, this is a cast. All cases where + // this can be something else are handled above. + if (Tok.Next->is(tok::identifier)) + return true; + + if (!Tok.Next->Next) + return false; + + // If the next token after the parenthesis is a unary operator, assume + // that this is cast, unless there are unexpected tokens inside the + // parenthesis. + bool NextIsUnary = + Tok.Next->isUnaryOperator() || Tok.Next->isOneOf(tok::amp, tok::star); + if (!NextIsUnary || Tok.Next->is(tok::plus) || + !Tok.Next->Next->isOneOf(tok::identifier, tok::numeric_constant)) + return false; + // Search for unexpected tokens. + for (FormatToken *Prev = Tok.Previous; Prev != Tok.MatchingParen; + Prev = Prev->Previous) { + if (!Prev->isOneOf(tok::kw_const, tok::identifier, tok::coloncolon)) + return false; } - return IsCast && !ParensAreEmpty; + return true; } /// \brief Return the type of the given token assuming it is * or &. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits