10b57cec5SDimitry Andric //===--- TokenAnnotator.cpp - Format C++ code -----------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// 90b57cec5SDimitry Andric /// \file 100b57cec5SDimitry Andric /// This file implements a token annotator, i.e. creates 110b57cec5SDimitry Andric /// \c AnnotatedTokens out of \c FormatTokens with required extra information. 120b57cec5SDimitry Andric /// 130b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "TokenAnnotator.h" 160b57cec5SDimitry Andric #include "FormatToken.h" 170b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h" 18a7dea167SDimitry Andric #include "clang/Basic/TokenKinds.h" 190b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 200b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric #define DEBUG_TYPE "format-token-annotator" 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric namespace clang { 250b57cec5SDimitry Andric namespace format { 260b57cec5SDimitry Andric 275f757f3fSDimitry Andric static bool mustBreakAfterAttributes(const FormatToken &Tok, 285f757f3fSDimitry Andric const FormatStyle &Style) { 295f757f3fSDimitry Andric switch (Style.BreakAfterAttributes) { 305f757f3fSDimitry Andric case FormatStyle::ABS_Always: 315f757f3fSDimitry Andric return true; 325f757f3fSDimitry Andric case FormatStyle::ABS_Leave: 335f757f3fSDimitry Andric return Tok.NewlinesBefore > 0; 345f757f3fSDimitry Andric default: 355f757f3fSDimitry Andric return false; 365f757f3fSDimitry Andric } 375f757f3fSDimitry Andric } 385f757f3fSDimitry Andric 390b57cec5SDimitry Andric namespace { 400b57cec5SDimitry Andric 4181ad6265SDimitry Andric /// Returns \c true if the line starts with a token that can start a statement 4281ad6265SDimitry Andric /// with an initializer. 4381ad6265SDimitry Andric static bool startsWithInitStatement(const AnnotatedLine &Line) { 4481ad6265SDimitry Andric return Line.startsWith(tok::kw_for) || Line.startsWith(tok::kw_if) || 4581ad6265SDimitry Andric Line.startsWith(tok::kw_switch); 4681ad6265SDimitry Andric } 4781ad6265SDimitry Andric 480b57cec5SDimitry Andric /// Returns \c true if the token can be used as an identifier in 49e8d8bef9SDimitry Andric /// an Objective-C \c \@selector, \c false otherwise. 500b57cec5SDimitry Andric /// 510b57cec5SDimitry Andric /// Because getFormattingLangOpts() always lexes source code as 520b57cec5SDimitry Andric /// Objective-C++, C++ keywords like \c new and \c delete are 530b57cec5SDimitry Andric /// lexed as tok::kw_*, not tok::identifier, even for Objective-C. 540b57cec5SDimitry Andric /// 550b57cec5SDimitry Andric /// For Objective-C and Objective-C++, both identifiers and keywords 560b57cec5SDimitry Andric /// are valid inside @selector(...) (or a macro which 570b57cec5SDimitry Andric /// invokes @selector(...)). So, we allow treat any identifier or 580b57cec5SDimitry Andric /// keyword as a potential Objective-C selector component. 590b57cec5SDimitry Andric static bool canBeObjCSelectorComponent(const FormatToken &Tok) { 6006c3fb27SDimitry Andric return Tok.Tok.getIdentifierInfo(); 610b57cec5SDimitry Andric } 620b57cec5SDimitry Andric 63a7dea167SDimitry Andric /// With `Left` being '(', check if we're at either `[...](` or 64a7dea167SDimitry Andric /// `[...]<...>(`, where the [ opens a lambda capture list. 65a7dea167SDimitry Andric static bool isLambdaParameterList(const FormatToken *Left) { 66a7dea167SDimitry Andric // Skip <...> if present. 67a7dea167SDimitry Andric if (Left->Previous && Left->Previous->is(tok::greater) && 68a7dea167SDimitry Andric Left->Previous->MatchingParen && 6981ad6265SDimitry Andric Left->Previous->MatchingParen->is(TT_TemplateOpener)) { 70a7dea167SDimitry Andric Left = Left->Previous->MatchingParen; 7181ad6265SDimitry Andric } 72a7dea167SDimitry Andric 73a7dea167SDimitry Andric // Check for `[...]`. 74a7dea167SDimitry Andric return Left->Previous && Left->Previous->is(tok::r_square) && 75a7dea167SDimitry Andric Left->Previous->MatchingParen && 76a7dea167SDimitry Andric Left->Previous->MatchingParen->is(TT_LambdaLSquare); 77a7dea167SDimitry Andric } 78a7dea167SDimitry Andric 7916d6b3b3SDimitry Andric /// Returns \c true if the token is followed by a boolean condition, \c false 8016d6b3b3SDimitry Andric /// otherwise. 8116d6b3b3SDimitry Andric static bool isKeywordWithCondition(const FormatToken &Tok) { 8216d6b3b3SDimitry Andric return Tok.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while, tok::kw_switch, 8316d6b3b3SDimitry Andric tok::kw_constexpr, tok::kw_catch); 8416d6b3b3SDimitry Andric } 8516d6b3b3SDimitry Andric 86bdd1243dSDimitry Andric /// Returns \c true if the token starts a C++ attribute, \c false otherwise. 87bdd1243dSDimitry Andric static bool isCppAttribute(bool IsCpp, const FormatToken &Tok) { 88bdd1243dSDimitry Andric if (!IsCpp || !Tok.startsSequence(tok::l_square, tok::l_square)) 89bdd1243dSDimitry Andric return false; 90bdd1243dSDimitry Andric // The first square bracket is part of an ObjC array literal 91bdd1243dSDimitry Andric if (Tok.Previous && Tok.Previous->is(tok::at)) 92bdd1243dSDimitry Andric return false; 93bdd1243dSDimitry Andric const FormatToken *AttrTok = Tok.Next->Next; 94bdd1243dSDimitry Andric if (!AttrTok) 95bdd1243dSDimitry Andric return false; 96bdd1243dSDimitry Andric // C++17 '[[using ns: foo, bar(baz, blech)]]' 97bdd1243dSDimitry Andric // We assume nobody will name an ObjC variable 'using'. 98bdd1243dSDimitry Andric if (AttrTok->startsSequence(tok::kw_using, tok::identifier, tok::colon)) 99bdd1243dSDimitry Andric return true; 100bdd1243dSDimitry Andric if (AttrTok->isNot(tok::identifier)) 101bdd1243dSDimitry Andric return false; 102bdd1243dSDimitry Andric while (AttrTok && !AttrTok->startsSequence(tok::r_square, tok::r_square)) { 103bdd1243dSDimitry Andric // ObjC message send. We assume nobody will use : in a C++11 attribute 104bdd1243dSDimitry Andric // specifier parameter, although this is technically valid: 105bdd1243dSDimitry Andric // [[foo(:)]]. 106bdd1243dSDimitry Andric if (AttrTok->is(tok::colon) || 107bdd1243dSDimitry Andric AttrTok->startsSequence(tok::identifier, tok::identifier) || 108bdd1243dSDimitry Andric AttrTok->startsSequence(tok::r_paren, tok::identifier)) { 109bdd1243dSDimitry Andric return false; 110bdd1243dSDimitry Andric } 111bdd1243dSDimitry Andric if (AttrTok->is(tok::ellipsis)) 112bdd1243dSDimitry Andric return true; 113bdd1243dSDimitry Andric AttrTok = AttrTok->Next; 114bdd1243dSDimitry Andric } 115bdd1243dSDimitry Andric return AttrTok && AttrTok->startsSequence(tok::r_square, tok::r_square); 116bdd1243dSDimitry Andric } 117bdd1243dSDimitry Andric 1180b57cec5SDimitry Andric /// A parser that gathers additional information about tokens. 1190b57cec5SDimitry Andric /// 1200b57cec5SDimitry Andric /// The \c TokenAnnotator tries to match parenthesis and square brakets and 1210b57cec5SDimitry Andric /// store a parenthesis levels. It also tries to resolve matching "<" and ">" 1220b57cec5SDimitry Andric /// into template parameter lists. 1230b57cec5SDimitry Andric class AnnotatingParser { 1240b57cec5SDimitry Andric public: 1250b57cec5SDimitry Andric AnnotatingParser(const FormatStyle &Style, AnnotatedLine &Line, 12606c3fb27SDimitry Andric const AdditionalKeywords &Keywords, 12706c3fb27SDimitry Andric SmallVector<ScopeType> &Scopes) 1280b57cec5SDimitry Andric : Style(Style), Line(Line), CurrentToken(Line.First), AutoFound(false), 1290fca6ea1SDimitry Andric IsCpp(Style.isCpp()), LangOpts(getFormattingLangOpts(Style)), 1300fca6ea1SDimitry Andric Keywords(Keywords), Scopes(Scopes), TemplateDeclarationDepth(0) { 1310fca6ea1SDimitry Andric assert(IsCpp == LangOpts.CXXOperatorNames); 1320b57cec5SDimitry Andric Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/false)); 13304eeddc0SDimitry Andric resetTokenMetadata(); 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric private: 13706c3fb27SDimitry Andric ScopeType getScopeType(const FormatToken &Token) const { 13806c3fb27SDimitry Andric switch (Token.getType()) { 13906c3fb27SDimitry Andric case TT_FunctionLBrace: 14006c3fb27SDimitry Andric case TT_LambdaLBrace: 14106c3fb27SDimitry Andric return ST_Function; 14206c3fb27SDimitry Andric case TT_ClassLBrace: 14306c3fb27SDimitry Andric case TT_StructLBrace: 14406c3fb27SDimitry Andric case TT_UnionLBrace: 14506c3fb27SDimitry Andric return ST_Class; 14606c3fb27SDimitry Andric default: 14706c3fb27SDimitry Andric return ST_Other; 14806c3fb27SDimitry Andric } 14906c3fb27SDimitry Andric } 15006c3fb27SDimitry Andric 1510b57cec5SDimitry Andric bool parseAngle() { 1520b57cec5SDimitry Andric if (!CurrentToken || !CurrentToken->Previous) 1530b57cec5SDimitry Andric return false; 1545f757f3fSDimitry Andric if (NonTemplateLess.count(CurrentToken->Previous) > 0) 1550b57cec5SDimitry Andric return false; 1560b57cec5SDimitry Andric 15752418fc2SDimitry Andric if (const auto &Previous = *CurrentToken->Previous; // The '<'. 15852418fc2SDimitry Andric Previous.Previous) { 1590b57cec5SDimitry Andric if (Previous.Previous->Tok.isLiteral()) 1600b57cec5SDimitry Andric return false; 16106c3fb27SDimitry Andric if (Previous.Previous->is(tok::r_brace)) 16206c3fb27SDimitry Andric return false; 1630b57cec5SDimitry Andric if (Previous.Previous->is(tok::r_paren) && Contexts.size() > 1 && 1640b57cec5SDimitry Andric (!Previous.Previous->MatchingParen || 1655f757f3fSDimitry Andric Previous.Previous->MatchingParen->isNot( 16681ad6265SDimitry Andric TT_OverloadedOperatorLParen))) { 1670b57cec5SDimitry Andric return false; 1680b57cec5SDimitry Andric } 1695f757f3fSDimitry Andric if (Previous.Previous->is(tok::kw_operator) && 1705f757f3fSDimitry Andric CurrentToken->is(tok::l_paren)) { 1715f757f3fSDimitry Andric return false; 1725f757f3fSDimitry Andric } 17381ad6265SDimitry Andric } 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric FormatToken *Left = CurrentToken->Previous; 1760b57cec5SDimitry Andric Left->ParentBracket = Contexts.back().ContextKind; 1770b57cec5SDimitry Andric ScopedContextCreator ContextCreator(*this, tok::less, 12); 1780b57cec5SDimitry Andric Contexts.back().IsExpression = false; 17952418fc2SDimitry Andric 18052418fc2SDimitry Andric const auto *BeforeLess = Left->Previous; 18152418fc2SDimitry Andric 1820b57cec5SDimitry Andric // If there's a template keyword before the opening angle bracket, this is a 1830b57cec5SDimitry Andric // template parameter, not an argument. 18452418fc2SDimitry Andric if (BeforeLess && BeforeLess->isNot(tok::kw_template)) 18581ad6265SDimitry Andric Contexts.back().ContextType = Context::TemplateArgument; 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric if (Style.Language == FormatStyle::LK_Java && 18881ad6265SDimitry Andric CurrentToken->is(tok::question)) { 1890b57cec5SDimitry Andric next(); 19081ad6265SDimitry Andric } 1910b57cec5SDimitry Andric 192*5deeebd8SDimitry Andric for (bool SeenTernaryOperator = false, MaybeAngles = true; CurrentToken;) { 19352418fc2SDimitry Andric const bool InExpr = Contexts[Contexts.size() - 2].IsExpression; 1940b57cec5SDimitry Andric if (CurrentToken->is(tok::greater)) { 19552418fc2SDimitry Andric const auto *Next = CurrentToken->Next; 196*5deeebd8SDimitry Andric if (CurrentToken->isNot(TT_TemplateCloser)) { 19716d6b3b3SDimitry Andric // Try to do a better job at looking for ">>" within the condition of 198fe6060f1SDimitry Andric // a statement. Conservatively insert spaces between consecutive ">" 199*5deeebd8SDimitry Andric // tokens to prevent splitting right shift operators and potentially 200fe6060f1SDimitry Andric // altering program semantics. This check is overly conservative and 201fe6060f1SDimitry Andric // will prevent spaces from being inserted in select nested template 202fe6060f1SDimitry Andric // parameter cases, but should not alter program semantics. 20352418fc2SDimitry Andric if (Next && Next->is(tok::greater) && 20416d6b3b3SDimitry Andric Left->ParentBracket != tok::less && 205fe6060f1SDimitry Andric CurrentToken->getStartOfNonWhitespace() == 20652418fc2SDimitry Andric Next->getStartOfNonWhitespace().getLocWithOffset(-1)) { 20752418fc2SDimitry Andric return false; 20852418fc2SDimitry Andric } 20952418fc2SDimitry Andric if (InExpr && SeenTernaryOperator && 21052418fc2SDimitry Andric (!Next || !Next->isOneOf(tok::l_paren, tok::l_brace))) { 21116d6b3b3SDimitry Andric return false; 21281ad6265SDimitry Andric } 213*5deeebd8SDimitry Andric if (!MaybeAngles) 214*5deeebd8SDimitry Andric return false; 215*5deeebd8SDimitry Andric } 2160b57cec5SDimitry Andric Left->MatchingParen = CurrentToken; 2170b57cec5SDimitry Andric CurrentToken->MatchingParen = Left; 2180b57cec5SDimitry Andric // In TT_Proto, we must distignuish between: 2190b57cec5SDimitry Andric // map<key, value> 2200b57cec5SDimitry Andric // msg < item: data > 2210b57cec5SDimitry Andric // msg: < item: data > 2220b57cec5SDimitry Andric // In TT_TextProto, map<key, value> does not occur. 2230b57cec5SDimitry Andric if (Style.Language == FormatStyle::LK_TextProto || 22452418fc2SDimitry Andric (Style.Language == FormatStyle::LK_Proto && BeforeLess && 22552418fc2SDimitry Andric BeforeLess->isOneOf(TT_SelectorName, TT_DictLiteral))) { 2265ffd83dbSDimitry Andric CurrentToken->setType(TT_DictLiteral); 22781ad6265SDimitry Andric } else { 2285ffd83dbSDimitry Andric CurrentToken->setType(TT_TemplateCloser); 22906c3fb27SDimitry Andric CurrentToken->Tok.setLength(1); 23081ad6265SDimitry Andric } 23152418fc2SDimitry Andric if (Next && Next->Tok.isLiteral()) 23206c3fb27SDimitry Andric return false; 2330b57cec5SDimitry Andric next(); 2340b57cec5SDimitry Andric return true; 2350b57cec5SDimitry Andric } 2360b57cec5SDimitry Andric if (CurrentToken->is(tok::question) && 2370b57cec5SDimitry Andric Style.Language == FormatStyle::LK_Java) { 2380b57cec5SDimitry Andric next(); 2390b57cec5SDimitry Andric continue; 2400b57cec5SDimitry Andric } 2410fca6ea1SDimitry Andric if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace)) 2420b57cec5SDimitry Andric return false; 24352418fc2SDimitry Andric const auto &Prev = *CurrentToken->Previous; 2440b57cec5SDimitry Andric // If a && or || is found and interpreted as a binary operator, this set 2450b57cec5SDimitry Andric // of angles is likely part of something like "a < b && c > d". If the 2460b57cec5SDimitry Andric // angles are inside an expression, the ||/&& might also be a binary 2470b57cec5SDimitry Andric // operator that was misinterpreted because we are parsing template 2480b57cec5SDimitry Andric // parameters. 2490b57cec5SDimitry Andric // FIXME: This is getting out of hand, write a decent parser. 250*5deeebd8SDimitry Andric if (MaybeAngles && InExpr && !Line.startsWith(tok::kw_template) && 25152418fc2SDimitry Andric Prev.is(TT_BinaryOperator)) { 25252418fc2SDimitry Andric const auto Precedence = Prev.getPrecedence(); 25352418fc2SDimitry Andric if (Precedence > prec::Conditional && Precedence < prec::Relational) 254*5deeebd8SDimitry Andric MaybeAngles = false; 25581ad6265SDimitry Andric } 2566c4b055cSDimitry Andric if (Prev.isOneOf(tok::question, tok::colon) && !Style.isProto()) 25752418fc2SDimitry Andric SeenTernaryOperator = true; 2580b57cec5SDimitry Andric updateParameterCount(Left, CurrentToken); 2590b57cec5SDimitry Andric if (Style.Language == FormatStyle::LK_Proto) { 2600b57cec5SDimitry Andric if (FormatToken *Previous = CurrentToken->getPreviousNonComment()) { 2610b57cec5SDimitry Andric if (CurrentToken->is(tok::colon) || 2620b57cec5SDimitry Andric (CurrentToken->isOneOf(tok::l_brace, tok::less) && 26381ad6265SDimitry Andric Previous->isNot(tok::colon))) { 2645ffd83dbSDimitry Andric Previous->setType(TT_SelectorName); 2650b57cec5SDimitry Andric } 2660b57cec5SDimitry Andric } 26781ad6265SDimitry Andric } 2680fca6ea1SDimitry Andric if (Style.isTableGen()) { 2690fca6ea1SDimitry Andric if (CurrentToken->isOneOf(tok::comma, tok::equal)) { 2700fca6ea1SDimitry Andric // They appear as separators. Unless they are not in class definition. 2710fca6ea1SDimitry Andric next(); 2720fca6ea1SDimitry Andric continue; 2730fca6ea1SDimitry Andric } 2740fca6ea1SDimitry Andric // In angle, there must be Value like tokens. Types are also able to be 2750fca6ea1SDimitry Andric // parsed in the same way with Values. 2760fca6ea1SDimitry Andric if (!parseTableGenValue()) 2770fca6ea1SDimitry Andric return false; 2780fca6ea1SDimitry Andric continue; 2790fca6ea1SDimitry Andric } 2800b57cec5SDimitry Andric if (!consumeToken()) 2810b57cec5SDimitry Andric return false; 2820b57cec5SDimitry Andric } 2830b57cec5SDimitry Andric return false; 2840b57cec5SDimitry Andric } 2850b57cec5SDimitry Andric 2865ffd83dbSDimitry Andric bool parseUntouchableParens() { 2875ffd83dbSDimitry Andric while (CurrentToken) { 2885ffd83dbSDimitry Andric CurrentToken->Finalized = true; 2895ffd83dbSDimitry Andric switch (CurrentToken->Tok.getKind()) { 2905ffd83dbSDimitry Andric case tok::l_paren: 2915ffd83dbSDimitry Andric next(); 2925ffd83dbSDimitry Andric if (!parseUntouchableParens()) 2935ffd83dbSDimitry Andric return false; 2945ffd83dbSDimitry Andric continue; 2955ffd83dbSDimitry Andric case tok::r_paren: 2965ffd83dbSDimitry Andric next(); 2975ffd83dbSDimitry Andric return true; 2985ffd83dbSDimitry Andric default: 2995ffd83dbSDimitry Andric // no-op 3005ffd83dbSDimitry Andric break; 3015ffd83dbSDimitry Andric } 3025ffd83dbSDimitry Andric next(); 3035ffd83dbSDimitry Andric } 3045ffd83dbSDimitry Andric return false; 3055ffd83dbSDimitry Andric } 3065ffd83dbSDimitry Andric 3070b57cec5SDimitry Andric bool parseParens(bool LookForDecls = false) { 3080b57cec5SDimitry Andric if (!CurrentToken) 3090b57cec5SDimitry Andric return false; 31081ad6265SDimitry Andric assert(CurrentToken->Previous && "Unknown previous token"); 31181ad6265SDimitry Andric FormatToken &OpeningParen = *CurrentToken->Previous; 31281ad6265SDimitry Andric assert(OpeningParen.is(tok::l_paren)); 31381ad6265SDimitry Andric FormatToken *PrevNonComment = OpeningParen.getPreviousNonComment(); 31481ad6265SDimitry Andric OpeningParen.ParentBracket = Contexts.back().ContextKind; 3150b57cec5SDimitry Andric ScopedContextCreator ContextCreator(*this, tok::l_paren, 1); 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric // FIXME: This is a bit of a hack. Do better. 3180b57cec5SDimitry Andric Contexts.back().ColonIsForRangeExpr = 3190b57cec5SDimitry Andric Contexts.size() == 2 && Contexts[0].ColonIsForRangeExpr; 3200b57cec5SDimitry Andric 32181ad6265SDimitry Andric if (OpeningParen.Previous && 32281ad6265SDimitry Andric OpeningParen.Previous->is(TT_UntouchableMacroFunc)) { 32381ad6265SDimitry Andric OpeningParen.Finalized = true; 3245ffd83dbSDimitry Andric return parseUntouchableParens(); 3255ffd83dbSDimitry Andric } 3265ffd83dbSDimitry Andric 3270b57cec5SDimitry Andric bool StartsObjCMethodExpr = false; 328bdd1243dSDimitry Andric if (!Style.isVerilog()) { 32981ad6265SDimitry Andric if (FormatToken *MaybeSel = OpeningParen.Previous) { 3300b57cec5SDimitry Andric // @selector( starts a selector. 331bdd1243dSDimitry Andric if (MaybeSel->isObjCAtKeyword(tok::objc_selector) && 332bdd1243dSDimitry Andric MaybeSel->Previous && MaybeSel->Previous->is(tok::at)) { 3330b57cec5SDimitry Andric StartsObjCMethodExpr = true; 3340b57cec5SDimitry Andric } 3350b57cec5SDimitry Andric } 336bdd1243dSDimitry Andric } 3370b57cec5SDimitry Andric 33881ad6265SDimitry Andric if (OpeningParen.is(TT_OverloadedOperatorLParen)) { 339fe6060f1SDimitry Andric // Find the previous kw_operator token. 34081ad6265SDimitry Andric FormatToken *Prev = &OpeningParen; 3415f757f3fSDimitry Andric while (Prev->isNot(tok::kw_operator)) { 342fe6060f1SDimitry Andric Prev = Prev->Previous; 343fe6060f1SDimitry Andric assert(Prev && "Expect a kw_operator prior to the OperatorLParen!"); 344fe6060f1SDimitry Andric } 345fe6060f1SDimitry Andric 346fe6060f1SDimitry Andric // If faced with "a.operator*(argument)" or "a->operator*(argument)", 347fe6060f1SDimitry Andric // i.e. the operator is called as a member function, 348fe6060f1SDimitry Andric // then the argument must be an expression. 349fe6060f1SDimitry Andric bool OperatorCalledAsMemberFunction = 350fe6060f1SDimitry Andric Prev->Previous && Prev->Previous->isOneOf(tok::period, tok::arrow); 351fe6060f1SDimitry Andric Contexts.back().IsExpression = OperatorCalledAsMemberFunction; 35206c3fb27SDimitry Andric } else if (OpeningParen.is(TT_VerilogInstancePortLParen)) { 35306c3fb27SDimitry Andric Contexts.back().IsExpression = true; 35406c3fb27SDimitry Andric Contexts.back().ContextType = Context::VerilogInstancePortList; 3550eae32dcSDimitry Andric } else if (Style.isJavaScript() && 3560b57cec5SDimitry Andric (Line.startsWith(Keywords.kw_type, tok::identifier) || 3570b57cec5SDimitry Andric Line.startsWith(tok::kw_export, Keywords.kw_type, 3580b57cec5SDimitry Andric tok::identifier))) { 3590b57cec5SDimitry Andric // type X = (...); 3600b57cec5SDimitry Andric // export type X = (...); 3610b57cec5SDimitry Andric Contexts.back().IsExpression = false; 36281ad6265SDimitry Andric } else if (OpeningParen.Previous && 36306c3fb27SDimitry Andric (OpeningParen.Previous->isOneOf( 36406c3fb27SDimitry Andric tok::kw_static_assert, tok::kw_noexcept, tok::kw_explicit, 36506c3fb27SDimitry Andric tok::kw_while, tok::l_paren, tok::comma, 36606c3fb27SDimitry Andric TT_BinaryOperator) || 36781ad6265SDimitry Andric OpeningParen.Previous->isIf())) { 3680b57cec5SDimitry Andric // static_assert, if and while usually contain expressions. 3690b57cec5SDimitry Andric Contexts.back().IsExpression = true; 37081ad6265SDimitry Andric } else if (Style.isJavaScript() && OpeningParen.Previous && 37181ad6265SDimitry Andric (OpeningParen.Previous->is(Keywords.kw_function) || 37281ad6265SDimitry Andric (OpeningParen.Previous->endsSequence(tok::identifier, 3730b57cec5SDimitry Andric Keywords.kw_function)))) { 3740b57cec5SDimitry Andric // function(...) or function f(...) 3750b57cec5SDimitry Andric Contexts.back().IsExpression = false; 37681ad6265SDimitry Andric } else if (Style.isJavaScript() && OpeningParen.Previous && 37781ad6265SDimitry Andric OpeningParen.Previous->is(TT_JsTypeColon)) { 3780b57cec5SDimitry Andric // let x: (SomeType); 3790b57cec5SDimitry Andric Contexts.back().IsExpression = false; 38081ad6265SDimitry Andric } else if (isLambdaParameterList(&OpeningParen)) { 3810b57cec5SDimitry Andric // This is a parameter list of a lambda expression. 3820b57cec5SDimitry Andric Contexts.back().IsExpression = false; 383bdd1243dSDimitry Andric } else if (OpeningParen.is(TT_RequiresExpressionLParen)) { 384bdd1243dSDimitry Andric Contexts.back().IsExpression = false; 385bdd1243dSDimitry Andric } else if (OpeningParen.Previous && 386bdd1243dSDimitry Andric OpeningParen.Previous->is(tok::kw__Generic)) { 387bdd1243dSDimitry Andric Contexts.back().ContextType = Context::C11GenericSelection; 388bdd1243dSDimitry Andric Contexts.back().IsExpression = true; 38952418fc2SDimitry Andric } else if (Line.InPPDirective && 39052418fc2SDimitry Andric (!OpeningParen.Previous || 39152418fc2SDimitry Andric OpeningParen.Previous->isNot(tok::identifier))) { 39252418fc2SDimitry Andric Contexts.back().IsExpression = true; 3930b57cec5SDimitry Andric } else if (Contexts[Contexts.size() - 2].CaretFound) { 3940b57cec5SDimitry Andric // This is the parameter list of an ObjC block. 3950b57cec5SDimitry Andric Contexts.back().IsExpression = false; 39681ad6265SDimitry Andric } else if (OpeningParen.Previous && 39781ad6265SDimitry Andric OpeningParen.Previous->is(TT_ForEachMacro)) { 3980b57cec5SDimitry Andric // The first argument to a foreach macro is a declaration. 39981ad6265SDimitry Andric Contexts.back().ContextType = Context::ForEachMacro; 4000b57cec5SDimitry Andric Contexts.back().IsExpression = false; 40181ad6265SDimitry Andric } else if (OpeningParen.Previous && OpeningParen.Previous->MatchingParen && 402bdd1243dSDimitry Andric OpeningParen.Previous->MatchingParen->isOneOf( 403bdd1243dSDimitry Andric TT_ObjCBlockLParen, TT_FunctionTypeLParen)) { 4040b57cec5SDimitry Andric Contexts.back().IsExpression = false; 40552418fc2SDimitry Andric } else if (!Line.MustBeDeclaration && !Line.InPPDirective) { 4060b57cec5SDimitry Andric bool IsForOrCatch = 40781ad6265SDimitry Andric OpeningParen.Previous && 40881ad6265SDimitry Andric OpeningParen.Previous->isOneOf(tok::kw_for, tok::kw_catch); 4090b57cec5SDimitry Andric Contexts.back().IsExpression = !IsForOrCatch; 4100b57cec5SDimitry Andric } 4110b57cec5SDimitry Andric 4120fca6ea1SDimitry Andric if (Style.isTableGen()) { 4130fca6ea1SDimitry Andric if (FormatToken *Prev = OpeningParen.Previous) { 4140fca6ea1SDimitry Andric if (Prev->is(TT_TableGenCondOperator)) { 4150fca6ea1SDimitry Andric Contexts.back().IsTableGenCondOpe = true; 4160fca6ea1SDimitry Andric Contexts.back().IsExpression = true; 4170fca6ea1SDimitry Andric } else if (Contexts.size() > 1 && 4180fca6ea1SDimitry Andric Contexts[Contexts.size() - 2].IsTableGenBangOpe) { 4190fca6ea1SDimitry Andric // Hack to handle bang operators. The parent context's flag 4200fca6ea1SDimitry Andric // was set by parseTableGenSimpleValue(). 4210fca6ea1SDimitry Andric // We have to specify the context outside because the prev of "(" may 4220fca6ea1SDimitry Andric // be ">", not the bang operator in this case. 4230fca6ea1SDimitry Andric Contexts.back().IsTableGenBangOpe = true; 4240fca6ea1SDimitry Andric Contexts.back().IsExpression = true; 4250fca6ea1SDimitry Andric } else { 4260fca6ea1SDimitry Andric // Otherwise, this paren seems DAGArg. 4270fca6ea1SDimitry Andric if (!parseTableGenDAGArg()) 4280fca6ea1SDimitry Andric return false; 4290fca6ea1SDimitry Andric return parseTableGenDAGArgAndList(&OpeningParen); 4300fca6ea1SDimitry Andric } 4310fca6ea1SDimitry Andric } 4320fca6ea1SDimitry Andric } 4330fca6ea1SDimitry Andric 434e8d8bef9SDimitry Andric // Infer the role of the l_paren based on the previous token if we haven't 435bdd1243dSDimitry Andric // detected one yet. 43681ad6265SDimitry Andric if (PrevNonComment && OpeningParen.is(TT_Unknown)) { 4375f757f3fSDimitry Andric if (PrevNonComment->isAttribute()) { 4385f757f3fSDimitry Andric OpeningParen.setType(TT_AttributeLParen); 439e8d8bef9SDimitry Andric } else if (PrevNonComment->isOneOf(TT_TypenameMacro, tok::kw_decltype, 440bdd1243dSDimitry Andric tok::kw_typeof, 441bdd1243dSDimitry Andric #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait, 442bdd1243dSDimitry Andric #include "clang/Basic/TransformTypeTraits.def" 443bdd1243dSDimitry Andric tok::kw__Atomic)) { 44481ad6265SDimitry Andric OpeningParen.setType(TT_TypeDeclarationParen); 445e8d8bef9SDimitry Andric // decltype() and typeof() usually contain expressions. 446e8d8bef9SDimitry Andric if (PrevNonComment->isOneOf(tok::kw_decltype, tok::kw_typeof)) 447e8d8bef9SDimitry Andric Contexts.back().IsExpression = true; 448e8d8bef9SDimitry Andric } 449e8d8bef9SDimitry Andric } 450e8d8bef9SDimitry Andric 4510b57cec5SDimitry Andric if (StartsObjCMethodExpr) { 4520b57cec5SDimitry Andric Contexts.back().ColonIsObjCMethodExpr = true; 45381ad6265SDimitry Andric OpeningParen.setType(TT_ObjCMethodExpr); 4540b57cec5SDimitry Andric } 4550b57cec5SDimitry Andric 4560b57cec5SDimitry Andric // MightBeFunctionType and ProbablyFunctionType are used for 4570b57cec5SDimitry Andric // function pointer and reference types as well as Objective-C 4580b57cec5SDimitry Andric // block types: 4590b57cec5SDimitry Andric // 4600b57cec5SDimitry Andric // void (*FunctionPointer)(void); 4610b57cec5SDimitry Andric // void (&FunctionReference)(void); 4624824e7fdSDimitry Andric // void (&&FunctionReference)(void); 4630b57cec5SDimitry Andric // void (^ObjCBlock)(void); 4640b57cec5SDimitry Andric bool MightBeFunctionType = !Contexts[Contexts.size() - 2].IsExpression; 4650b57cec5SDimitry Andric bool ProbablyFunctionType = 4665f757f3fSDimitry Andric CurrentToken->isPointerOrReference() || CurrentToken->is(tok::caret); 4670b57cec5SDimitry Andric bool HasMultipleLines = false; 4680b57cec5SDimitry Andric bool HasMultipleParametersOnALine = false; 4690b57cec5SDimitry Andric bool MightBeObjCForRangeLoop = 47081ad6265SDimitry Andric OpeningParen.Previous && OpeningParen.Previous->is(tok::kw_for); 4710b57cec5SDimitry Andric FormatToken *PossibleObjCForInToken = nullptr; 4720b57cec5SDimitry Andric while (CurrentToken) { 4730b57cec5SDimitry Andric // LookForDecls is set when "if (" has been seen. Check for 4740b57cec5SDimitry Andric // 'identifier' '*' 'identifier' followed by not '=' -- this 4750b57cec5SDimitry Andric // '*' has to be a binary operator but determineStarAmpUsage() will 4760b57cec5SDimitry Andric // categorize it as an unary operator, so set the right type here. 4770b57cec5SDimitry Andric if (LookForDecls && CurrentToken->Next) { 4780b57cec5SDimitry Andric FormatToken *Prev = CurrentToken->getPreviousNonComment(); 4790b57cec5SDimitry Andric if (Prev) { 4800b57cec5SDimitry Andric FormatToken *PrevPrev = Prev->getPreviousNonComment(); 4810b57cec5SDimitry Andric FormatToken *Next = CurrentToken->Next; 4820b57cec5SDimitry Andric if (PrevPrev && PrevPrev->is(tok::identifier) && 4835f757f3fSDimitry Andric PrevPrev->isNot(TT_TypeName) && Prev->isPointerOrReference() && 4849e7101a8SDimitry Andric CurrentToken->is(tok::identifier) && Next->isNot(tok::equal)) { 4855ffd83dbSDimitry Andric Prev->setType(TT_BinaryOperator); 4860b57cec5SDimitry Andric LookForDecls = false; 4870b57cec5SDimitry Andric } 4880b57cec5SDimitry Andric } 4890b57cec5SDimitry Andric } 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric if (CurrentToken->Previous->is(TT_PointerOrReference) && 4920b57cec5SDimitry Andric CurrentToken->Previous->Previous->isOneOf(tok::l_paren, 49381ad6265SDimitry Andric tok::coloncolon)) { 4940b57cec5SDimitry Andric ProbablyFunctionType = true; 49581ad6265SDimitry Andric } 4960b57cec5SDimitry Andric if (CurrentToken->is(tok::comma)) 4970b57cec5SDimitry Andric MightBeFunctionType = false; 4980b57cec5SDimitry Andric if (CurrentToken->Previous->is(TT_BinaryOperator)) 4990b57cec5SDimitry Andric Contexts.back().IsExpression = true; 5000b57cec5SDimitry Andric if (CurrentToken->is(tok::r_paren)) { 50181ad6265SDimitry Andric if (OpeningParen.isNot(TT_CppCastLParen) && MightBeFunctionType && 50281ad6265SDimitry Andric ProbablyFunctionType && CurrentToken->Next && 5030b57cec5SDimitry Andric (CurrentToken->Next->is(tok::l_paren) || 50481ad6265SDimitry Andric (CurrentToken->Next->is(tok::l_square) && 50581ad6265SDimitry Andric Line.MustBeDeclaration))) { 50681ad6265SDimitry Andric OpeningParen.setType(OpeningParen.Next->is(tok::caret) 50781ad6265SDimitry Andric ? TT_ObjCBlockLParen 5085ffd83dbSDimitry Andric : TT_FunctionTypeLParen); 50981ad6265SDimitry Andric } 51081ad6265SDimitry Andric OpeningParen.MatchingParen = CurrentToken; 51181ad6265SDimitry Andric CurrentToken->MatchingParen = &OpeningParen; 5120b57cec5SDimitry Andric 5130b57cec5SDimitry Andric if (CurrentToken->Next && CurrentToken->Next->is(tok::l_brace) && 51481ad6265SDimitry Andric OpeningParen.Previous && OpeningParen.Previous->is(tok::l_paren)) { 5150b57cec5SDimitry Andric // Detect the case where macros are used to generate lambdas or 5160b57cec5SDimitry Andric // function bodies, e.g.: 517fe6060f1SDimitry Andric // auto my_lambda = MACRO((Type *type, int i) { .. body .. }); 51881ad6265SDimitry Andric for (FormatToken *Tok = &OpeningParen; Tok != CurrentToken; 51981ad6265SDimitry Andric Tok = Tok->Next) { 5205f757f3fSDimitry Andric if (Tok->is(TT_BinaryOperator) && Tok->isPointerOrReference()) 5215ffd83dbSDimitry Andric Tok->setType(TT_PointerOrReference); 5220b57cec5SDimitry Andric } 5230b57cec5SDimitry Andric } 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric if (StartsObjCMethodExpr) { 5265ffd83dbSDimitry Andric CurrentToken->setType(TT_ObjCMethodExpr); 5270b57cec5SDimitry Andric if (Contexts.back().FirstObjCSelectorName) { 5280b57cec5SDimitry Andric Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = 5290b57cec5SDimitry Andric Contexts.back().LongestObjCSelectorName; 5300b57cec5SDimitry Andric } 5310b57cec5SDimitry Andric } 5320b57cec5SDimitry Andric 5335f757f3fSDimitry Andric if (OpeningParen.is(TT_AttributeLParen)) 5345f757f3fSDimitry Andric CurrentToken->setType(TT_AttributeRParen); 53581ad6265SDimitry Andric if (OpeningParen.is(TT_TypeDeclarationParen)) 536e8d8bef9SDimitry Andric CurrentToken->setType(TT_TypeDeclarationParen); 53781ad6265SDimitry Andric if (OpeningParen.Previous && 53881ad6265SDimitry Andric OpeningParen.Previous->is(TT_JavaAnnotation)) { 5395ffd83dbSDimitry Andric CurrentToken->setType(TT_JavaAnnotation); 54081ad6265SDimitry Andric } 54181ad6265SDimitry Andric if (OpeningParen.Previous && 54281ad6265SDimitry Andric OpeningParen.Previous->is(TT_LeadingJavaAnnotation)) { 5435ffd83dbSDimitry Andric CurrentToken->setType(TT_LeadingJavaAnnotation); 54481ad6265SDimitry Andric } 54581ad6265SDimitry Andric if (OpeningParen.Previous && 54681ad6265SDimitry Andric OpeningParen.Previous->is(TT_AttributeSquare)) { 5475ffd83dbSDimitry Andric CurrentToken->setType(TT_AttributeSquare); 54881ad6265SDimitry Andric } 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric if (!HasMultipleLines) 55181ad6265SDimitry Andric OpeningParen.setPackingKind(PPK_Inconclusive); 5520b57cec5SDimitry Andric else if (HasMultipleParametersOnALine) 55381ad6265SDimitry Andric OpeningParen.setPackingKind(PPK_BinPacked); 5540b57cec5SDimitry Andric else 55581ad6265SDimitry Andric OpeningParen.setPackingKind(PPK_OnePerLine); 5560b57cec5SDimitry Andric 5570b57cec5SDimitry Andric next(); 5580b57cec5SDimitry Andric return true; 5590b57cec5SDimitry Andric } 5600b57cec5SDimitry Andric if (CurrentToken->isOneOf(tok::r_square, tok::r_brace)) 5610b57cec5SDimitry Andric return false; 5620b57cec5SDimitry Andric 56381ad6265SDimitry Andric if (CurrentToken->is(tok::l_brace) && OpeningParen.is(TT_ObjCBlockLParen)) 56481ad6265SDimitry Andric OpeningParen.setType(TT_Unknown); 5650b57cec5SDimitry Andric if (CurrentToken->is(tok::comma) && CurrentToken->Next && 5660b57cec5SDimitry Andric !CurrentToken->Next->HasUnescapedNewline && 56781ad6265SDimitry Andric !CurrentToken->Next->isTrailingComment()) { 5680b57cec5SDimitry Andric HasMultipleParametersOnALine = true; 56981ad6265SDimitry Andric } 570fe6060f1SDimitry Andric bool ProbablyFunctionTypeLParen = 571fe6060f1SDimitry Andric (CurrentToken->is(tok::l_paren) && CurrentToken->Next && 572fe6060f1SDimitry Andric CurrentToken->Next->isOneOf(tok::star, tok::amp, tok::caret)); 5730b57cec5SDimitry Andric if ((CurrentToken->Previous->isOneOf(tok::kw_const, tok::kw_auto) || 5740fca6ea1SDimitry Andric CurrentToken->Previous->isTypeName(LangOpts)) && 575fe6060f1SDimitry Andric !(CurrentToken->is(tok::l_brace) || 57681ad6265SDimitry Andric (CurrentToken->is(tok::l_paren) && !ProbablyFunctionTypeLParen))) { 5770b57cec5SDimitry Andric Contexts.back().IsExpression = false; 57881ad6265SDimitry Andric } 5790b57cec5SDimitry Andric if (CurrentToken->isOneOf(tok::semi, tok::colon)) { 5800b57cec5SDimitry Andric MightBeObjCForRangeLoop = false; 5810b57cec5SDimitry Andric if (PossibleObjCForInToken) { 5825ffd83dbSDimitry Andric PossibleObjCForInToken->setType(TT_Unknown); 5830b57cec5SDimitry Andric PossibleObjCForInToken = nullptr; 5840b57cec5SDimitry Andric } 5850b57cec5SDimitry Andric } 5860b57cec5SDimitry Andric if (MightBeObjCForRangeLoop && CurrentToken->is(Keywords.kw_in)) { 5870b57cec5SDimitry Andric PossibleObjCForInToken = CurrentToken; 5885ffd83dbSDimitry Andric PossibleObjCForInToken->setType(TT_ObjCForIn); 5890b57cec5SDimitry Andric } 5900b57cec5SDimitry Andric // When we discover a 'new', we set CanBeExpression to 'false' in order to 5910b57cec5SDimitry Andric // parse the type correctly. Reset that after a comma. 5920b57cec5SDimitry Andric if (CurrentToken->is(tok::comma)) 5930b57cec5SDimitry Andric Contexts.back().CanBeExpression = true; 5940b57cec5SDimitry Andric 5950fca6ea1SDimitry Andric if (Style.isTableGen()) { 5960fca6ea1SDimitry Andric if (CurrentToken->is(tok::comma)) { 5970fca6ea1SDimitry Andric if (Contexts.back().IsTableGenCondOpe) 5980fca6ea1SDimitry Andric CurrentToken->setType(TT_TableGenCondOperatorComma); 5990fca6ea1SDimitry Andric next(); 6000fca6ea1SDimitry Andric } else if (CurrentToken->is(tok::colon)) { 6010fca6ea1SDimitry Andric if (Contexts.back().IsTableGenCondOpe) 6020fca6ea1SDimitry Andric CurrentToken->setType(TT_TableGenCondOperatorColon); 6030fca6ea1SDimitry Andric next(); 6040fca6ea1SDimitry Andric } 6050fca6ea1SDimitry Andric // In TableGen there must be Values in parens. 6060fca6ea1SDimitry Andric if (!parseTableGenValue()) 6070fca6ea1SDimitry Andric return false; 6080fca6ea1SDimitry Andric continue; 6090fca6ea1SDimitry Andric } 6100fca6ea1SDimitry Andric 6110b57cec5SDimitry Andric FormatToken *Tok = CurrentToken; 6120b57cec5SDimitry Andric if (!consumeToken()) 6130b57cec5SDimitry Andric return false; 61481ad6265SDimitry Andric updateParameterCount(&OpeningParen, Tok); 6150b57cec5SDimitry Andric if (CurrentToken && CurrentToken->HasUnescapedNewline) 6160b57cec5SDimitry Andric HasMultipleLines = true; 6170b57cec5SDimitry Andric } 6180b57cec5SDimitry Andric return false; 6190b57cec5SDimitry Andric } 6200b57cec5SDimitry Andric 6210b57cec5SDimitry Andric bool isCSharpAttributeSpecifier(const FormatToken &Tok) { 6220b57cec5SDimitry Andric if (!Style.isCSharp()) 6230b57cec5SDimitry Andric return false; 6240b57cec5SDimitry Andric 6255ffd83dbSDimitry Andric // `identifier[i]` is not an attribute. 6265ffd83dbSDimitry Andric if (Tok.Previous && Tok.Previous->is(tok::identifier)) 6275ffd83dbSDimitry Andric return false; 6285ffd83dbSDimitry Andric 6295ffd83dbSDimitry Andric // Chains of [] in `identifier[i][j][k]` are not attributes. 6305ffd83dbSDimitry Andric if (Tok.Previous && Tok.Previous->is(tok::r_square)) { 6315ffd83dbSDimitry Andric auto *MatchingParen = Tok.Previous->MatchingParen; 6325ffd83dbSDimitry Andric if (!MatchingParen || MatchingParen->is(TT_ArraySubscriptLSquare)) 6335ffd83dbSDimitry Andric return false; 6345ffd83dbSDimitry Andric } 6355ffd83dbSDimitry Andric 6360b57cec5SDimitry Andric const FormatToken *AttrTok = Tok.Next; 6370b57cec5SDimitry Andric if (!AttrTok) 6380b57cec5SDimitry Andric return false; 6390b57cec5SDimitry Andric 6400b57cec5SDimitry Andric // Just an empty declaration e.g. string []. 6410b57cec5SDimitry Andric if (AttrTok->is(tok::r_square)) 6420b57cec5SDimitry Andric return false; 6430b57cec5SDimitry Andric 6440b57cec5SDimitry Andric // Move along the tokens inbetween the '[' and ']' e.g. [STAThread]. 64581ad6265SDimitry Andric while (AttrTok && AttrTok->isNot(tok::r_square)) 6460b57cec5SDimitry Andric AttrTok = AttrTok->Next; 6470b57cec5SDimitry Andric 6480b57cec5SDimitry Andric if (!AttrTok) 6490b57cec5SDimitry Andric return false; 6500b57cec5SDimitry Andric 6515ffd83dbSDimitry Andric // Allow an attribute to be the only content of a file. 6520b57cec5SDimitry Andric AttrTok = AttrTok->Next; 6530b57cec5SDimitry Andric if (!AttrTok) 6545ffd83dbSDimitry Andric return true; 6550b57cec5SDimitry Andric 6560b57cec5SDimitry Andric // Limit this to being an access modifier that follows. 6570fca6ea1SDimitry Andric if (AttrTok->isAccessSpecifierKeyword() || 6580fca6ea1SDimitry Andric AttrTok->isOneOf(tok::comment, tok::kw_class, tok::kw_static, 6595ffd83dbSDimitry Andric tok::l_square, Keywords.kw_internal)) { 6600b57cec5SDimitry Andric return true; 6610b57cec5SDimitry Andric } 662a7dea167SDimitry Andric 663a7dea167SDimitry Andric // incase its a [XXX] retval func(.... 664a7dea167SDimitry Andric if (AttrTok->Next && 66581ad6265SDimitry Andric AttrTok->Next->startsSequence(tok::identifier, tok::l_paren)) { 666a7dea167SDimitry Andric return true; 66781ad6265SDimitry Andric } 668a7dea167SDimitry Andric 6690b57cec5SDimitry Andric return false; 6700b57cec5SDimitry Andric } 6710b57cec5SDimitry Andric 6720b57cec5SDimitry Andric bool parseSquare() { 6730b57cec5SDimitry Andric if (!CurrentToken) 6740b57cec5SDimitry Andric return false; 6750b57cec5SDimitry Andric 6760b57cec5SDimitry Andric // A '[' could be an index subscript (after an identifier or after 6770b57cec5SDimitry Andric // ')' or ']'), it could be the start of an Objective-C method 6780b57cec5SDimitry Andric // expression, it could the start of an Objective-C array literal, 6790b57cec5SDimitry Andric // or it could be a C++ attribute specifier [[foo::bar]]. 6800b57cec5SDimitry Andric FormatToken *Left = CurrentToken->Previous; 6810b57cec5SDimitry Andric Left->ParentBracket = Contexts.back().ContextKind; 6820b57cec5SDimitry Andric FormatToken *Parent = Left->getPreviousNonComment(); 6830b57cec5SDimitry Andric 6840b57cec5SDimitry Andric // Cases where '>' is followed by '['. 6850b57cec5SDimitry Andric // In C++, this can happen either in array of templates (foo<int>[10]) 6860b57cec5SDimitry Andric // or when array is a nested template type (unique_ptr<type1<type2>[]>). 6870b57cec5SDimitry Andric bool CppArrayTemplates = 6880fca6ea1SDimitry Andric IsCpp && Parent && Parent->is(TT_TemplateCloser) && 6890b57cec5SDimitry Andric (Contexts.back().CanBeExpression || Contexts.back().IsExpression || 69081ad6265SDimitry Andric Contexts.back().ContextType == Context::TemplateArgument); 6910b57cec5SDimitry Andric 692bdd1243dSDimitry Andric const bool IsInnerSquare = Contexts.back().InCpp11AttributeSpecifier; 693bdd1243dSDimitry Andric const bool IsCpp11AttributeSpecifier = 6940fca6ea1SDimitry Andric isCppAttribute(IsCpp, *Left) || IsInnerSquare; 6950b57cec5SDimitry Andric 6960b57cec5SDimitry Andric // Treat C# Attributes [STAThread] much like C++ attributes [[...]]. 6975ffd83dbSDimitry Andric bool IsCSharpAttributeSpecifier = 6980b57cec5SDimitry Andric isCSharpAttributeSpecifier(*Left) || 6990b57cec5SDimitry Andric Contexts.back().InCSharpAttributeSpecifier; 7000b57cec5SDimitry Andric 7010b57cec5SDimitry Andric bool InsideInlineASM = Line.startsWith(tok::kw_asm); 7020fca6ea1SDimitry Andric bool IsCppStructuredBinding = Left->isCppStructuredBinding(IsCpp); 7030b57cec5SDimitry Andric bool StartsObjCMethodExpr = 7040b57cec5SDimitry Andric !IsCppStructuredBinding && !InsideInlineASM && !CppArrayTemplates && 7050fca6ea1SDimitry Andric IsCpp && !IsCpp11AttributeSpecifier && !IsCSharpAttributeSpecifier && 7060fca6ea1SDimitry Andric Contexts.back().CanBeExpression && Left->isNot(TT_LambdaLSquare) && 7070b57cec5SDimitry Andric !CurrentToken->isOneOf(tok::l_brace, tok::r_square) && 7080b57cec5SDimitry Andric (!Parent || 7090b57cec5SDimitry Andric Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren, 7100b57cec5SDimitry Andric tok::kw_return, tok::kw_throw) || 7110b57cec5SDimitry Andric Parent->isUnaryOperator() || 7120b57cec5SDimitry Andric // FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen. 7130b57cec5SDimitry Andric Parent->isOneOf(TT_ObjCForIn, TT_CastRParen) || 7140b57cec5SDimitry Andric (getBinOpPrecedence(Parent->Tok.getKind(), true, true) > 7150b57cec5SDimitry Andric prec::Unknown)); 7160b57cec5SDimitry Andric bool ColonFound = false; 7170b57cec5SDimitry Andric 7180b57cec5SDimitry Andric unsigned BindingIncrease = 1; 7190b57cec5SDimitry Andric if (IsCppStructuredBinding) { 7205ffd83dbSDimitry Andric Left->setType(TT_StructuredBindingLSquare); 7210b57cec5SDimitry Andric } else if (Left->is(TT_Unknown)) { 7220b57cec5SDimitry Andric if (StartsObjCMethodExpr) { 7235ffd83dbSDimitry Andric Left->setType(TT_ObjCMethodExpr); 7245ffd83dbSDimitry Andric } else if (InsideInlineASM) { 7255ffd83dbSDimitry Andric Left->setType(TT_InlineASMSymbolicNameLSquare); 7260b57cec5SDimitry Andric } else if (IsCpp11AttributeSpecifier) { 7275ffd83dbSDimitry Andric Left->setType(TT_AttributeSquare); 728bdd1243dSDimitry Andric if (!IsInnerSquare && Left->Previous) 729bdd1243dSDimitry Andric Left->Previous->EndsCppAttributeGroup = false; 7300eae32dcSDimitry Andric } else if (Style.isJavaScript() && Parent && 7310b57cec5SDimitry Andric Contexts.back().ContextKind == tok::l_brace && 7320b57cec5SDimitry Andric Parent->isOneOf(tok::l_brace, tok::comma)) { 7335ffd83dbSDimitry Andric Left->setType(TT_JsComputedPropertyName); 7340fca6ea1SDimitry Andric } else if (IsCpp && Contexts.back().ContextKind == tok::l_brace && 7350b57cec5SDimitry Andric Parent && Parent->isOneOf(tok::l_brace, tok::comma)) { 7365ffd83dbSDimitry Andric Left->setType(TT_DesignatedInitializerLSquare); 7375ffd83dbSDimitry Andric } else if (IsCSharpAttributeSpecifier) { 7385ffd83dbSDimitry Andric Left->setType(TT_AttributeSquare); 7390b57cec5SDimitry Andric } else if (CurrentToken->is(tok::r_square) && Parent && 7400b57cec5SDimitry Andric Parent->is(TT_TemplateCloser)) { 7415ffd83dbSDimitry Andric Left->setType(TT_ArraySubscriptLSquare); 7425f757f3fSDimitry Andric } else if (Style.isProto()) { 7430b57cec5SDimitry Andric // Square braces in LK_Proto can either be message field attributes: 7440b57cec5SDimitry Andric // 7450b57cec5SDimitry Andric // optional Aaa aaa = 1 [ 7460b57cec5SDimitry Andric // (aaa) = aaa 7470b57cec5SDimitry Andric // ]; 7480b57cec5SDimitry Andric // 7490b57cec5SDimitry Andric // extensions 123 [ 7500b57cec5SDimitry Andric // (aaa) = aaa 7510b57cec5SDimitry Andric // ]; 7520b57cec5SDimitry Andric // 7530b57cec5SDimitry Andric // or text proto extensions (in options): 7540b57cec5SDimitry Andric // 7550b57cec5SDimitry Andric // option (Aaa.options) = { 7560b57cec5SDimitry Andric // [type.type/type] { 7570b57cec5SDimitry Andric // key: value 7580b57cec5SDimitry Andric // } 7590b57cec5SDimitry Andric // } 7600b57cec5SDimitry Andric // 7610b57cec5SDimitry Andric // or repeated fields (in options): 7620b57cec5SDimitry Andric // 7630b57cec5SDimitry Andric // option (Aaa.options) = { 7640b57cec5SDimitry Andric // keys: [ 1, 2, 3 ] 7650b57cec5SDimitry Andric // } 7660b57cec5SDimitry Andric // 7670b57cec5SDimitry Andric // In the first and the third case we want to spread the contents inside 7680b57cec5SDimitry Andric // the square braces; in the second we want to keep them inline. 7695ffd83dbSDimitry Andric Left->setType(TT_ArrayInitializerLSquare); 7700b57cec5SDimitry Andric if (!Left->endsSequence(tok::l_square, tok::numeric_constant, 7710b57cec5SDimitry Andric tok::equal) && 7720b57cec5SDimitry Andric !Left->endsSequence(tok::l_square, tok::numeric_constant, 7730b57cec5SDimitry Andric tok::identifier) && 7740b57cec5SDimitry Andric !Left->endsSequence(tok::l_square, tok::colon, TT_SelectorName)) { 7755ffd83dbSDimitry Andric Left->setType(TT_ProtoExtensionLSquare); 7760b57cec5SDimitry Andric BindingIncrease = 10; 7770b57cec5SDimitry Andric } 7780b57cec5SDimitry Andric } else if (!CppArrayTemplates && Parent && 7790b57cec5SDimitry Andric Parent->isOneOf(TT_BinaryOperator, TT_TemplateCloser, tok::at, 7800b57cec5SDimitry Andric tok::comma, tok::l_paren, tok::l_square, 7810b57cec5SDimitry Andric tok::question, tok::colon, tok::kw_return, 7820b57cec5SDimitry Andric // Should only be relevant to JavaScript: 7830b57cec5SDimitry Andric tok::kw_default)) { 7845ffd83dbSDimitry Andric Left->setType(TT_ArrayInitializerLSquare); 7850b57cec5SDimitry Andric } else { 7860b57cec5SDimitry Andric BindingIncrease = 10; 7875ffd83dbSDimitry Andric Left->setType(TT_ArraySubscriptLSquare); 7880b57cec5SDimitry Andric } 7890b57cec5SDimitry Andric } 7900b57cec5SDimitry Andric 7910b57cec5SDimitry Andric ScopedContextCreator ContextCreator(*this, tok::l_square, BindingIncrease); 7920b57cec5SDimitry Andric Contexts.back().IsExpression = true; 7930eae32dcSDimitry Andric if (Style.isJavaScript() && Parent && Parent->is(TT_JsTypeColon)) 7940b57cec5SDimitry Andric Contexts.back().IsExpression = false; 7950b57cec5SDimitry Andric 7960b57cec5SDimitry Andric Contexts.back().ColonIsObjCMethodExpr = StartsObjCMethodExpr; 7970b57cec5SDimitry Andric Contexts.back().InCpp11AttributeSpecifier = IsCpp11AttributeSpecifier; 7985ffd83dbSDimitry Andric Contexts.back().InCSharpAttributeSpecifier = IsCSharpAttributeSpecifier; 7990b57cec5SDimitry Andric 8000b57cec5SDimitry Andric while (CurrentToken) { 8010b57cec5SDimitry Andric if (CurrentToken->is(tok::r_square)) { 802bdd1243dSDimitry Andric if (IsCpp11AttributeSpecifier) { 8035ffd83dbSDimitry Andric CurrentToken->setType(TT_AttributeSquare); 804bdd1243dSDimitry Andric if (!IsInnerSquare) 805bdd1243dSDimitry Andric CurrentToken->EndsCppAttributeGroup = true; 806bdd1243dSDimitry Andric } 80781ad6265SDimitry Andric if (IsCSharpAttributeSpecifier) { 8085ffd83dbSDimitry Andric CurrentToken->setType(TT_AttributeSquare); 80981ad6265SDimitry Andric } else if (((CurrentToken->Next && 8100b57cec5SDimitry Andric CurrentToken->Next->is(tok::l_paren)) || 8110b57cec5SDimitry Andric (CurrentToken->Previous && 8120b57cec5SDimitry Andric CurrentToken->Previous->Previous == Left)) && 8130b57cec5SDimitry Andric Left->is(TT_ObjCMethodExpr)) { 8140b57cec5SDimitry Andric // An ObjC method call is rarely followed by an open parenthesis. It 8150b57cec5SDimitry Andric // also can't be composed of just one token, unless it's a macro that 8160b57cec5SDimitry Andric // will be expanded to more tokens. 8170b57cec5SDimitry Andric // FIXME: Do we incorrectly label ":" with this? 8180b57cec5SDimitry Andric StartsObjCMethodExpr = false; 8195ffd83dbSDimitry Andric Left->setType(TT_Unknown); 8200b57cec5SDimitry Andric } 8210b57cec5SDimitry Andric if (StartsObjCMethodExpr && CurrentToken->Previous != Left) { 8225ffd83dbSDimitry Andric CurrentToken->setType(TT_ObjCMethodExpr); 8230b57cec5SDimitry Andric // If we haven't seen a colon yet, make sure the last identifier 8240b57cec5SDimitry Andric // before the r_square is tagged as a selector name component. 8250b57cec5SDimitry Andric if (!ColonFound && CurrentToken->Previous && 8260b57cec5SDimitry Andric CurrentToken->Previous->is(TT_Unknown) && 82781ad6265SDimitry Andric canBeObjCSelectorComponent(*CurrentToken->Previous)) { 8285ffd83dbSDimitry Andric CurrentToken->Previous->setType(TT_SelectorName); 82981ad6265SDimitry Andric } 8300b57cec5SDimitry Andric // determineStarAmpUsage() thinks that '*' '[' is allocating an 8310b57cec5SDimitry Andric // array of pointers, but if '[' starts a selector then '*' is a 8320b57cec5SDimitry Andric // binary operator. 8330b57cec5SDimitry Andric if (Parent && Parent->is(TT_PointerOrReference)) 83481ad6265SDimitry Andric Parent->overwriteFixedType(TT_BinaryOperator); 8350b57cec5SDimitry Andric } 8360b57cec5SDimitry Andric // An arrow after an ObjC method expression is not a lambda arrow. 8370fca6ea1SDimitry Andric if (CurrentToken->is(TT_ObjCMethodExpr) && CurrentToken->Next && 8386c4b055cSDimitry Andric CurrentToken->Next->is(TT_LambdaArrow)) { 83981ad6265SDimitry Andric CurrentToken->Next->overwriteFixedType(TT_Unknown); 84081ad6265SDimitry Andric } 8410b57cec5SDimitry Andric Left->MatchingParen = CurrentToken; 8420b57cec5SDimitry Andric CurrentToken->MatchingParen = Left; 8430b57cec5SDimitry Andric // FirstObjCSelectorName is set when a colon is found. This does 8440b57cec5SDimitry Andric // not work, however, when the method has no parameters. 8450b57cec5SDimitry Andric // Here, we set FirstObjCSelectorName when the end of the method call is 8460b57cec5SDimitry Andric // reached, in case it was not set already. 8470b57cec5SDimitry Andric if (!Contexts.back().FirstObjCSelectorName) { 8480b57cec5SDimitry Andric FormatToken *Previous = CurrentToken->getPreviousNonComment(); 8490b57cec5SDimitry Andric if (Previous && Previous->is(TT_SelectorName)) { 8500b57cec5SDimitry Andric Previous->ObjCSelectorNameParts = 1; 8510b57cec5SDimitry Andric Contexts.back().FirstObjCSelectorName = Previous; 8520b57cec5SDimitry Andric } 8530b57cec5SDimitry Andric } else { 8540b57cec5SDimitry Andric Left->ParameterCount = 8550b57cec5SDimitry Andric Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts; 8560b57cec5SDimitry Andric } 8570b57cec5SDimitry Andric if (Contexts.back().FirstObjCSelectorName) { 8580b57cec5SDimitry Andric Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = 8590b57cec5SDimitry Andric Contexts.back().LongestObjCSelectorName; 8600b57cec5SDimitry Andric if (Left->BlockParameterCount > 1) 8610b57cec5SDimitry Andric Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = 0; 8620b57cec5SDimitry Andric } 8630fca6ea1SDimitry Andric if (Style.isTableGen() && Left->is(TT_TableGenListOpener)) 8640fca6ea1SDimitry Andric CurrentToken->setType(TT_TableGenListCloser); 8650b57cec5SDimitry Andric next(); 8660b57cec5SDimitry Andric return true; 8670b57cec5SDimitry Andric } 8680b57cec5SDimitry Andric if (CurrentToken->isOneOf(tok::r_paren, tok::r_brace)) 8690b57cec5SDimitry Andric return false; 8700b57cec5SDimitry Andric if (CurrentToken->is(tok::colon)) { 8710b57cec5SDimitry Andric if (IsCpp11AttributeSpecifier && 8720b57cec5SDimitry Andric CurrentToken->endsSequence(tok::colon, tok::identifier, 8730b57cec5SDimitry Andric tok::kw_using)) { 8740b57cec5SDimitry Andric // Remember that this is a [[using ns: foo]] C++ attribute, so we 8750b57cec5SDimitry Andric // don't add a space before the colon (unlike other colons). 8765ffd83dbSDimitry Andric CurrentToken->setType(TT_AttributeColon); 877bdd1243dSDimitry Andric } else if (!Style.isVerilog() && !Line.InPragmaDirective && 878bdd1243dSDimitry Andric Left->isOneOf(TT_ArraySubscriptLSquare, 8790b57cec5SDimitry Andric TT_DesignatedInitializerLSquare)) { 8805ffd83dbSDimitry Andric Left->setType(TT_ObjCMethodExpr); 8810b57cec5SDimitry Andric StartsObjCMethodExpr = true; 8820b57cec5SDimitry Andric Contexts.back().ColonIsObjCMethodExpr = true; 88381ad6265SDimitry Andric if (Parent && Parent->is(tok::r_paren)) { 8840b57cec5SDimitry Andric // FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen. 8855ffd83dbSDimitry Andric Parent->setType(TT_CastRParen); 8860b57cec5SDimitry Andric } 88781ad6265SDimitry Andric } 8880b57cec5SDimitry Andric ColonFound = true; 8890b57cec5SDimitry Andric } 8900b57cec5SDimitry Andric if (CurrentToken->is(tok::comma) && Left->is(TT_ObjCMethodExpr) && 89181ad6265SDimitry Andric !ColonFound) { 8925ffd83dbSDimitry Andric Left->setType(TT_ArrayInitializerLSquare); 89381ad6265SDimitry Andric } 8940b57cec5SDimitry Andric FormatToken *Tok = CurrentToken; 8950fca6ea1SDimitry Andric if (Style.isTableGen()) { 8960fca6ea1SDimitry Andric if (CurrentToken->isOneOf(tok::comma, tok::minus, tok::ellipsis)) { 8970fca6ea1SDimitry Andric // '-' and '...' appears as a separator in slice. 8980fca6ea1SDimitry Andric next(); 8990fca6ea1SDimitry Andric } else { 9000fca6ea1SDimitry Andric // In TableGen there must be a list of Values in square brackets. 9010fca6ea1SDimitry Andric // It must be ValueList or SliceElements. 9020fca6ea1SDimitry Andric if (!parseTableGenValue()) 9030fca6ea1SDimitry Andric return false; 9040fca6ea1SDimitry Andric } 9050fca6ea1SDimitry Andric updateParameterCount(Left, Tok); 9060fca6ea1SDimitry Andric continue; 9070fca6ea1SDimitry Andric } 9080b57cec5SDimitry Andric if (!consumeToken()) 9090b57cec5SDimitry Andric return false; 9100b57cec5SDimitry Andric updateParameterCount(Left, Tok); 9110b57cec5SDimitry Andric } 9120b57cec5SDimitry Andric return false; 9130b57cec5SDimitry Andric } 9140b57cec5SDimitry Andric 9150fca6ea1SDimitry Andric void skipToNextNonComment() { 9160fca6ea1SDimitry Andric next(); 9170fca6ea1SDimitry Andric while (CurrentToken && CurrentToken->is(tok::comment)) 9180fca6ea1SDimitry Andric next(); 9190fca6ea1SDimitry Andric } 9200fca6ea1SDimitry Andric 9210fca6ea1SDimitry Andric // Simplified parser for TableGen Value. Returns true on success. 9220fca6ea1SDimitry Andric // It consists of SimpleValues, SimpleValues with Suffixes, and Value followed 9230fca6ea1SDimitry Andric // by '#', paste operator. 9240fca6ea1SDimitry Andric // There also exists the case the Value is parsed as NameValue. 9250fca6ea1SDimitry Andric // In this case, the Value ends if '{' is found. 9260fca6ea1SDimitry Andric bool parseTableGenValue(bool ParseNameMode = false) { 9270fca6ea1SDimitry Andric if (!CurrentToken) 9280fca6ea1SDimitry Andric return false; 9290fca6ea1SDimitry Andric while (CurrentToken->is(tok::comment)) 9300fca6ea1SDimitry Andric next(); 9310fca6ea1SDimitry Andric if (!parseTableGenSimpleValue()) 9320fca6ea1SDimitry Andric return false; 9330fca6ea1SDimitry Andric if (!CurrentToken) 9340fca6ea1SDimitry Andric return true; 9350fca6ea1SDimitry Andric // Value "#" [Value] 9360fca6ea1SDimitry Andric if (CurrentToken->is(tok::hash)) { 9370fca6ea1SDimitry Andric if (CurrentToken->Next && 9380fca6ea1SDimitry Andric CurrentToken->Next->isOneOf(tok::colon, tok::semi, tok::l_brace)) { 9390fca6ea1SDimitry Andric // Trailing paste operator. 9400fca6ea1SDimitry Andric // These are only the allowed cases in TGParser::ParseValue(). 9410fca6ea1SDimitry Andric CurrentToken->setType(TT_TableGenTrailingPasteOperator); 9420fca6ea1SDimitry Andric next(); 9430fca6ea1SDimitry Andric return true; 9440fca6ea1SDimitry Andric } 9450fca6ea1SDimitry Andric FormatToken *HashTok = CurrentToken; 9460fca6ea1SDimitry Andric skipToNextNonComment(); 9470fca6ea1SDimitry Andric HashTok->setType(TT_Unknown); 9480fca6ea1SDimitry Andric if (!parseTableGenValue(ParseNameMode)) 9490fca6ea1SDimitry Andric return false; 9500fca6ea1SDimitry Andric } 9510fca6ea1SDimitry Andric // In name mode, '{' is regarded as the end of the value. 9520fca6ea1SDimitry Andric // See TGParser::ParseValue in TGParser.cpp 9530fca6ea1SDimitry Andric if (ParseNameMode && CurrentToken->is(tok::l_brace)) 9540fca6ea1SDimitry Andric return true; 9550fca6ea1SDimitry Andric // These tokens indicates this is a value with suffixes. 9560fca6ea1SDimitry Andric if (CurrentToken->isOneOf(tok::l_brace, tok::l_square, tok::period)) { 9570fca6ea1SDimitry Andric CurrentToken->setType(TT_TableGenValueSuffix); 9580fca6ea1SDimitry Andric FormatToken *Suffix = CurrentToken; 9590fca6ea1SDimitry Andric skipToNextNonComment(); 9600fca6ea1SDimitry Andric if (Suffix->is(tok::l_square)) 9610fca6ea1SDimitry Andric return parseSquare(); 9620fca6ea1SDimitry Andric if (Suffix->is(tok::l_brace)) { 9630fca6ea1SDimitry Andric Scopes.push_back(getScopeType(*Suffix)); 9640fca6ea1SDimitry Andric return parseBrace(); 9650fca6ea1SDimitry Andric } 9660fca6ea1SDimitry Andric } 9670fca6ea1SDimitry Andric return true; 9680fca6ea1SDimitry Andric } 9690fca6ea1SDimitry Andric 9700fca6ea1SDimitry Andric // TokVarName ::= "$" ualpha (ualpha | "0"..."9")* 9710fca6ea1SDimitry Andric // Appears as a part of DagArg. 9720fca6ea1SDimitry Andric // This does not change the current token on fail. 9730fca6ea1SDimitry Andric bool tryToParseTableGenTokVar() { 9740fca6ea1SDimitry Andric if (!CurrentToken) 9750fca6ea1SDimitry Andric return false; 9760fca6ea1SDimitry Andric if (CurrentToken->is(tok::identifier) && 9770fca6ea1SDimitry Andric CurrentToken->TokenText.front() == '$') { 9780fca6ea1SDimitry Andric skipToNextNonComment(); 9790fca6ea1SDimitry Andric return true; 9800fca6ea1SDimitry Andric } 9810fca6ea1SDimitry Andric return false; 9820fca6ea1SDimitry Andric } 9830fca6ea1SDimitry Andric 9840fca6ea1SDimitry Andric // DagArg ::= Value [":" TokVarName] | TokVarName 9850fca6ea1SDimitry Andric // Appears as a part of SimpleValue6. 9860fca6ea1SDimitry Andric bool parseTableGenDAGArg(bool AlignColon = false) { 9870fca6ea1SDimitry Andric if (tryToParseTableGenTokVar()) 9880fca6ea1SDimitry Andric return true; 9890fca6ea1SDimitry Andric if (parseTableGenValue()) { 9900fca6ea1SDimitry Andric if (CurrentToken && CurrentToken->is(tok::colon)) { 9910fca6ea1SDimitry Andric if (AlignColon) 9920fca6ea1SDimitry Andric CurrentToken->setType(TT_TableGenDAGArgListColonToAlign); 9930fca6ea1SDimitry Andric else 9940fca6ea1SDimitry Andric CurrentToken->setType(TT_TableGenDAGArgListColon); 9950fca6ea1SDimitry Andric skipToNextNonComment(); 9960fca6ea1SDimitry Andric return tryToParseTableGenTokVar(); 9970fca6ea1SDimitry Andric } 9980fca6ea1SDimitry Andric return true; 9990fca6ea1SDimitry Andric } 10000fca6ea1SDimitry Andric return false; 10010fca6ea1SDimitry Andric } 10020fca6ea1SDimitry Andric 10030fca6ea1SDimitry Andric // Judge if the token is a operator ID to insert line break in DAGArg. 10040fca6ea1SDimitry Andric // That is, TableGenBreakingDAGArgOperators is empty (by the definition of the 10050fca6ea1SDimitry Andric // option) or the token is in the list. 10060fca6ea1SDimitry Andric bool isTableGenDAGArgBreakingOperator(const FormatToken &Tok) { 10070fca6ea1SDimitry Andric auto &Opes = Style.TableGenBreakingDAGArgOperators; 10080fca6ea1SDimitry Andric // If the list is empty, all operators are breaking operators. 10090fca6ea1SDimitry Andric if (Opes.empty()) 10100fca6ea1SDimitry Andric return true; 10110fca6ea1SDimitry Andric // Otherwise, the operator is limited to normal identifiers. 10120fca6ea1SDimitry Andric if (Tok.isNot(tok::identifier) || 10130fca6ea1SDimitry Andric Tok.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator)) { 10140fca6ea1SDimitry Andric return false; 10150fca6ea1SDimitry Andric } 10160fca6ea1SDimitry Andric // The case next is colon, it is not a operator of identifier. 10170fca6ea1SDimitry Andric if (!Tok.Next || Tok.Next->is(tok::colon)) 10180fca6ea1SDimitry Andric return false; 10190fca6ea1SDimitry Andric return std::find(Opes.begin(), Opes.end(), Tok.TokenText.str()) != 10200fca6ea1SDimitry Andric Opes.end(); 10210fca6ea1SDimitry Andric } 10220fca6ea1SDimitry Andric 10230fca6ea1SDimitry Andric // SimpleValue6 ::= "(" DagArg [DagArgList] ")" 10240fca6ea1SDimitry Andric // This parses SimpleValue 6's inside part of "(" ")" 10250fca6ea1SDimitry Andric bool parseTableGenDAGArgAndList(FormatToken *Opener) { 10260fca6ea1SDimitry Andric FormatToken *FirstTok = CurrentToken; 10270fca6ea1SDimitry Andric if (!parseTableGenDAGArg()) 10280fca6ea1SDimitry Andric return false; 10290fca6ea1SDimitry Andric bool BreakInside = false; 10300fca6ea1SDimitry Andric if (Style.TableGenBreakInsideDAGArg != FormatStyle::DAS_DontBreak) { 10310fca6ea1SDimitry Andric // Specialized detection for DAGArgOperator, that determines the way of 10320fca6ea1SDimitry Andric // line break for this DAGArg elements. 10330fca6ea1SDimitry Andric if (isTableGenDAGArgBreakingOperator(*FirstTok)) { 10340fca6ea1SDimitry Andric // Special case for identifier DAGArg operator. 10350fca6ea1SDimitry Andric BreakInside = true; 10360fca6ea1SDimitry Andric Opener->setType(TT_TableGenDAGArgOpenerToBreak); 10370fca6ea1SDimitry Andric if (FirstTok->isOneOf(TT_TableGenBangOperator, 10380fca6ea1SDimitry Andric TT_TableGenCondOperator)) { 10390fca6ea1SDimitry Andric // Special case for bang/cond operators. Set the whole operator as 10400fca6ea1SDimitry Andric // the DAGArg operator. Always break after it. 10410fca6ea1SDimitry Andric CurrentToken->Previous->setType(TT_TableGenDAGArgOperatorToBreak); 10420fca6ea1SDimitry Andric } else if (FirstTok->is(tok::identifier)) { 10430fca6ea1SDimitry Andric if (Style.TableGenBreakInsideDAGArg == FormatStyle::DAS_BreakAll) 10440fca6ea1SDimitry Andric FirstTok->setType(TT_TableGenDAGArgOperatorToBreak); 10450fca6ea1SDimitry Andric else 10460fca6ea1SDimitry Andric FirstTok->setType(TT_TableGenDAGArgOperatorID); 10470fca6ea1SDimitry Andric } 10480fca6ea1SDimitry Andric } 10490fca6ea1SDimitry Andric } 10500fca6ea1SDimitry Andric // Parse the [DagArgList] part 10510fca6ea1SDimitry Andric bool FirstDAGArgListElm = true; 10520fca6ea1SDimitry Andric while (CurrentToken) { 10530fca6ea1SDimitry Andric if (!FirstDAGArgListElm && CurrentToken->is(tok::comma)) { 10540fca6ea1SDimitry Andric CurrentToken->setType(BreakInside ? TT_TableGenDAGArgListCommaToBreak 10550fca6ea1SDimitry Andric : TT_TableGenDAGArgListComma); 10560fca6ea1SDimitry Andric skipToNextNonComment(); 10570fca6ea1SDimitry Andric } 10580fca6ea1SDimitry Andric if (CurrentToken && CurrentToken->is(tok::r_paren)) { 10590fca6ea1SDimitry Andric CurrentToken->setType(TT_TableGenDAGArgCloser); 10600fca6ea1SDimitry Andric Opener->MatchingParen = CurrentToken; 10610fca6ea1SDimitry Andric CurrentToken->MatchingParen = Opener; 10620fca6ea1SDimitry Andric skipToNextNonComment(); 10630fca6ea1SDimitry Andric return true; 10640fca6ea1SDimitry Andric } 10650fca6ea1SDimitry Andric if (!parseTableGenDAGArg( 10660fca6ea1SDimitry Andric BreakInside && 10670fca6ea1SDimitry Andric Style.AlignConsecutiveTableGenBreakingDAGArgColons.Enabled)) { 10680fca6ea1SDimitry Andric return false; 10690fca6ea1SDimitry Andric } 10700fca6ea1SDimitry Andric FirstDAGArgListElm = false; 10710fca6ea1SDimitry Andric } 10720fca6ea1SDimitry Andric return false; 10730fca6ea1SDimitry Andric } 10740fca6ea1SDimitry Andric 10750fca6ea1SDimitry Andric bool parseTableGenSimpleValue() { 10760fca6ea1SDimitry Andric assert(Style.isTableGen()); 10770fca6ea1SDimitry Andric if (!CurrentToken) 10780fca6ea1SDimitry Andric return false; 10790fca6ea1SDimitry Andric FormatToken *Tok = CurrentToken; 10800fca6ea1SDimitry Andric skipToNextNonComment(); 10810fca6ea1SDimitry Andric // SimpleValue 1, 2, 3: Literals 10820fca6ea1SDimitry Andric if (Tok->isOneOf(tok::numeric_constant, tok::string_literal, 10830fca6ea1SDimitry Andric TT_TableGenMultiLineString, tok::kw_true, tok::kw_false, 10840fca6ea1SDimitry Andric tok::question, tok::kw_int)) { 10850fca6ea1SDimitry Andric return true; 10860fca6ea1SDimitry Andric } 10870fca6ea1SDimitry Andric // SimpleValue 4: ValueList, Type 10880fca6ea1SDimitry Andric if (Tok->is(tok::l_brace)) { 10890fca6ea1SDimitry Andric Scopes.push_back(getScopeType(*Tok)); 10900fca6ea1SDimitry Andric return parseBrace(); 10910fca6ea1SDimitry Andric } 10920fca6ea1SDimitry Andric // SimpleValue 5: List initializer 10930fca6ea1SDimitry Andric if (Tok->is(tok::l_square)) { 10940fca6ea1SDimitry Andric Tok->setType(TT_TableGenListOpener); 10950fca6ea1SDimitry Andric if (!parseSquare()) 10960fca6ea1SDimitry Andric return false; 10970fca6ea1SDimitry Andric if (Tok->is(tok::less)) { 10980fca6ea1SDimitry Andric CurrentToken->setType(TT_TemplateOpener); 10990fca6ea1SDimitry Andric return parseAngle(); 11000fca6ea1SDimitry Andric } 11010fca6ea1SDimitry Andric return true; 11020fca6ea1SDimitry Andric } 11030fca6ea1SDimitry Andric // SimpleValue 6: DAGArg [DAGArgList] 11040fca6ea1SDimitry Andric // SimpleValue6 ::= "(" DagArg [DagArgList] ")" 11050fca6ea1SDimitry Andric if (Tok->is(tok::l_paren)) { 11060fca6ea1SDimitry Andric Tok->setType(TT_TableGenDAGArgOpener); 11070fca6ea1SDimitry Andric return parseTableGenDAGArgAndList(Tok); 11080fca6ea1SDimitry Andric } 11090fca6ea1SDimitry Andric // SimpleValue 9: Bang operator 11100fca6ea1SDimitry Andric if (Tok->is(TT_TableGenBangOperator)) { 11110fca6ea1SDimitry Andric if (CurrentToken && CurrentToken->is(tok::less)) { 11120fca6ea1SDimitry Andric CurrentToken->setType(TT_TemplateOpener); 11130fca6ea1SDimitry Andric skipToNextNonComment(); 11140fca6ea1SDimitry Andric if (!parseAngle()) 11150fca6ea1SDimitry Andric return false; 11160fca6ea1SDimitry Andric } 11170fca6ea1SDimitry Andric if (!CurrentToken || CurrentToken->isNot(tok::l_paren)) 11180fca6ea1SDimitry Andric return false; 11190fca6ea1SDimitry Andric skipToNextNonComment(); 11200fca6ea1SDimitry Andric // FIXME: Hack using inheritance to child context 11210fca6ea1SDimitry Andric Contexts.back().IsTableGenBangOpe = true; 11220fca6ea1SDimitry Andric bool Result = parseParens(); 11230fca6ea1SDimitry Andric Contexts.back().IsTableGenBangOpe = false; 11240fca6ea1SDimitry Andric return Result; 11250fca6ea1SDimitry Andric } 11260fca6ea1SDimitry Andric // SimpleValue 9: Cond operator 11270fca6ea1SDimitry Andric if (Tok->is(TT_TableGenCondOperator)) { 11280fca6ea1SDimitry Andric Tok = CurrentToken; 11290fca6ea1SDimitry Andric skipToNextNonComment(); 11300fca6ea1SDimitry Andric if (!Tok || Tok->isNot(tok::l_paren)) 11310fca6ea1SDimitry Andric return false; 11320fca6ea1SDimitry Andric bool Result = parseParens(); 11330fca6ea1SDimitry Andric return Result; 11340fca6ea1SDimitry Andric } 11350fca6ea1SDimitry Andric // We have to check identifier at the last because the kind of bang/cond 11360fca6ea1SDimitry Andric // operators are also identifier. 11370fca6ea1SDimitry Andric // SimpleValue 7: Identifiers 11380fca6ea1SDimitry Andric if (Tok->is(tok::identifier)) { 11390fca6ea1SDimitry Andric // SimpleValue 8: Anonymous record 11400fca6ea1SDimitry Andric if (CurrentToken && CurrentToken->is(tok::less)) { 11410fca6ea1SDimitry Andric CurrentToken->setType(TT_TemplateOpener); 11420fca6ea1SDimitry Andric skipToNextNonComment(); 11430fca6ea1SDimitry Andric return parseAngle(); 11440fca6ea1SDimitry Andric } 11450fca6ea1SDimitry Andric return true; 11460fca6ea1SDimitry Andric } 11470fca6ea1SDimitry Andric 11480fca6ea1SDimitry Andric return false; 11490fca6ea1SDimitry Andric } 11500fca6ea1SDimitry Andric 1151fe6060f1SDimitry Andric bool couldBeInStructArrayInitializer() const { 1152fe6060f1SDimitry Andric if (Contexts.size() < 2) 1153fe6060f1SDimitry Andric return false; 1154fe6060f1SDimitry Andric // We want to back up no more then 2 context levels i.e. 1155fe6060f1SDimitry Andric // . { { <- 1156fe6060f1SDimitry Andric const auto End = std::next(Contexts.rbegin(), 2); 1157fe6060f1SDimitry Andric auto Last = Contexts.rbegin(); 1158fe6060f1SDimitry Andric unsigned Depth = 0; 115981ad6265SDimitry Andric for (; Last != End; ++Last) 1160fe6060f1SDimitry Andric if (Last->ContextKind == tok::l_brace) 1161fe6060f1SDimitry Andric ++Depth; 1162fe6060f1SDimitry Andric return Depth == 2 && Last->ContextKind != tok::l_brace; 1163fe6060f1SDimitry Andric } 1164fe6060f1SDimitry Andric 11650b57cec5SDimitry Andric bool parseBrace() { 116681ad6265SDimitry Andric if (!CurrentToken) 116781ad6265SDimitry Andric return true; 116881ad6265SDimitry Andric 116981ad6265SDimitry Andric assert(CurrentToken->Previous); 117081ad6265SDimitry Andric FormatToken &OpeningBrace = *CurrentToken->Previous; 117181ad6265SDimitry Andric assert(OpeningBrace.is(tok::l_brace)); 117281ad6265SDimitry Andric OpeningBrace.ParentBracket = Contexts.back().ContextKind; 11730b57cec5SDimitry Andric 11740b57cec5SDimitry Andric if (Contexts.back().CaretFound) 117581ad6265SDimitry Andric OpeningBrace.overwriteFixedType(TT_ObjCBlockLBrace); 11760b57cec5SDimitry Andric Contexts.back().CaretFound = false; 11770b57cec5SDimitry Andric 11780b57cec5SDimitry Andric ScopedContextCreator ContextCreator(*this, tok::l_brace, 1); 11790b57cec5SDimitry Andric Contexts.back().ColonIsDictLiteral = true; 118081ad6265SDimitry Andric if (OpeningBrace.is(BK_BracedInit)) 11810b57cec5SDimitry Andric Contexts.back().IsExpression = true; 118281ad6265SDimitry Andric if (Style.isJavaScript() && OpeningBrace.Previous && 118381ad6265SDimitry Andric OpeningBrace.Previous->is(TT_JsTypeColon)) { 11840b57cec5SDimitry Andric Contexts.back().IsExpression = false; 118581ad6265SDimitry Andric } 11865f757f3fSDimitry Andric if (Style.isVerilog() && 11875f757f3fSDimitry Andric (!OpeningBrace.getPreviousNonComment() || 11885f757f3fSDimitry Andric OpeningBrace.getPreviousNonComment()->isNot(Keywords.kw_apostrophe))) { 11895f757f3fSDimitry Andric Contexts.back().VerilogMayBeConcatenation = true; 11905f757f3fSDimitry Andric } 11910fca6ea1SDimitry Andric if (Style.isTableGen()) 11920fca6ea1SDimitry Andric Contexts.back().ColonIsDictLiteral = false; 11930b57cec5SDimitry Andric 1194fe6060f1SDimitry Andric unsigned CommaCount = 0; 11950b57cec5SDimitry Andric while (CurrentToken) { 11960b57cec5SDimitry Andric if (CurrentToken->is(tok::r_brace)) { 119706c3fb27SDimitry Andric assert(!Scopes.empty()); 119806c3fb27SDimitry Andric assert(Scopes.back() == getScopeType(OpeningBrace)); 119906c3fb27SDimitry Andric Scopes.pop_back(); 120081ad6265SDimitry Andric assert(OpeningBrace.Optional == CurrentToken->Optional); 120181ad6265SDimitry Andric OpeningBrace.MatchingParen = CurrentToken; 120281ad6265SDimitry Andric CurrentToken->MatchingParen = &OpeningBrace; 1203fe6060f1SDimitry Andric if (Style.AlignArrayOfStructures != FormatStyle::AIAS_None) { 120481ad6265SDimitry Andric if (OpeningBrace.ParentBracket == tok::l_brace && 1205fe6060f1SDimitry Andric couldBeInStructArrayInitializer() && CommaCount > 0) { 120681ad6265SDimitry Andric Contexts.back().ContextType = Context::StructArrayInitializer; 1207fe6060f1SDimitry Andric } 1208fe6060f1SDimitry Andric } 12090b57cec5SDimitry Andric next(); 12100b57cec5SDimitry Andric return true; 12110b57cec5SDimitry Andric } 12120b57cec5SDimitry Andric if (CurrentToken->isOneOf(tok::r_paren, tok::r_square)) 12130b57cec5SDimitry Andric return false; 121481ad6265SDimitry Andric updateParameterCount(&OpeningBrace, CurrentToken); 12150b57cec5SDimitry Andric if (CurrentToken->isOneOf(tok::colon, tok::l_brace, tok::less)) { 12160b57cec5SDimitry Andric FormatToken *Previous = CurrentToken->getPreviousNonComment(); 12170b57cec5SDimitry Andric if (Previous->is(TT_JsTypeOptionalQuestion)) 12180b57cec5SDimitry Andric Previous = Previous->getPreviousNonComment(); 12190fca6ea1SDimitry Andric if ((CurrentToken->is(tok::colon) && !Style.isTableGen() && 12200fca6ea1SDimitry Andric (!Contexts.back().ColonIsDictLiteral || !IsCpp)) || 12215f757f3fSDimitry Andric Style.isProto()) { 122281ad6265SDimitry Andric OpeningBrace.setType(TT_DictLiteral); 12230b57cec5SDimitry Andric if (Previous->Tok.getIdentifierInfo() || 122481ad6265SDimitry Andric Previous->is(tok::string_literal)) { 12255ffd83dbSDimitry Andric Previous->setType(TT_SelectorName); 12260b57cec5SDimitry Andric } 122781ad6265SDimitry Andric } 12280fca6ea1SDimitry Andric if (CurrentToken->is(tok::colon) && OpeningBrace.is(TT_Unknown) && 12290fca6ea1SDimitry Andric !Style.isTableGen()) { 123081ad6265SDimitry Andric OpeningBrace.setType(TT_DictLiteral); 12310fca6ea1SDimitry Andric } else if (Style.isJavaScript()) { 123281ad6265SDimitry Andric OpeningBrace.overwriteFixedType(TT_DictLiteral); 12330b57cec5SDimitry Andric } 12340fca6ea1SDimitry Andric } 1235fe6060f1SDimitry Andric if (CurrentToken->is(tok::comma)) { 12360eae32dcSDimitry Andric if (Style.isJavaScript()) 123781ad6265SDimitry Andric OpeningBrace.overwriteFixedType(TT_DictLiteral); 1238fe6060f1SDimitry Andric ++CommaCount; 1239fe6060f1SDimitry Andric } 12400b57cec5SDimitry Andric if (!consumeToken()) 12410b57cec5SDimitry Andric return false; 12420b57cec5SDimitry Andric } 12430b57cec5SDimitry Andric return true; 12440b57cec5SDimitry Andric } 12450b57cec5SDimitry Andric 12460b57cec5SDimitry Andric void updateParameterCount(FormatToken *Left, FormatToken *Current) { 12470b57cec5SDimitry Andric // For ObjC methods, the number of parameters is calculated differently as 12480b57cec5SDimitry Andric // method declarations have a different structure (the parameters are not 12490b57cec5SDimitry Andric // inside a bracket scope). 1250e8d8bef9SDimitry Andric if (Current->is(tok::l_brace) && Current->is(BK_Block)) 12510b57cec5SDimitry Andric ++Left->BlockParameterCount; 12520b57cec5SDimitry Andric if (Current->is(tok::comma)) { 12530b57cec5SDimitry Andric ++Left->ParameterCount; 12540b57cec5SDimitry Andric if (!Left->Role) 12550b57cec5SDimitry Andric Left->Role.reset(new CommaSeparatedList(Style)); 12560b57cec5SDimitry Andric Left->Role->CommaFound(Current); 12570b57cec5SDimitry Andric } else if (Left->ParameterCount == 0 && Current->isNot(tok::comment)) { 12580b57cec5SDimitry Andric Left->ParameterCount = 1; 12590b57cec5SDimitry Andric } 12600b57cec5SDimitry Andric } 12610b57cec5SDimitry Andric 12620b57cec5SDimitry Andric bool parseConditional() { 12630b57cec5SDimitry Andric while (CurrentToken) { 12640b57cec5SDimitry Andric if (CurrentToken->is(tok::colon)) { 12655ffd83dbSDimitry Andric CurrentToken->setType(TT_ConditionalExpr); 12660b57cec5SDimitry Andric next(); 12670b57cec5SDimitry Andric return true; 12680b57cec5SDimitry Andric } 12690b57cec5SDimitry Andric if (!consumeToken()) 12700b57cec5SDimitry Andric return false; 12710b57cec5SDimitry Andric } 12720b57cec5SDimitry Andric return false; 12730b57cec5SDimitry Andric } 12740b57cec5SDimitry Andric 12750b57cec5SDimitry Andric bool parseTemplateDeclaration() { 12760fca6ea1SDimitry Andric if (!CurrentToken || CurrentToken->isNot(tok::less)) 12770fca6ea1SDimitry Andric return false; 12780fca6ea1SDimitry Andric 12795ffd83dbSDimitry Andric CurrentToken->setType(TT_TemplateOpener); 12800b57cec5SDimitry Andric next(); 12810fca6ea1SDimitry Andric 12820fca6ea1SDimitry Andric TemplateDeclarationDepth++; 12830fca6ea1SDimitry Andric const bool WellFormed = parseAngle(); 12840fca6ea1SDimitry Andric TemplateDeclarationDepth--; 12850fca6ea1SDimitry Andric if (!WellFormed) 12860b57cec5SDimitry Andric return false; 12870fca6ea1SDimitry Andric 12880fca6ea1SDimitry Andric if (CurrentToken && TemplateDeclarationDepth == 0) 12890b57cec5SDimitry Andric CurrentToken->Previous->ClosesTemplateDeclaration = true; 12900fca6ea1SDimitry Andric 12910b57cec5SDimitry Andric return true; 12920b57cec5SDimitry Andric } 12930b57cec5SDimitry Andric 12940b57cec5SDimitry Andric bool consumeToken() { 12950fca6ea1SDimitry Andric if (IsCpp) { 12965f757f3fSDimitry Andric const auto *Prev = CurrentToken->getPreviousNonComment(); 12975f757f3fSDimitry Andric if (Prev && Prev->is(tok::r_square) && Prev->is(TT_AttributeSquare) && 12985f757f3fSDimitry Andric CurrentToken->isOneOf(tok::kw_if, tok::kw_switch, tok::kw_case, 12995f757f3fSDimitry Andric tok::kw_default, tok::kw_for, tok::kw_while) && 13005f757f3fSDimitry Andric mustBreakAfterAttributes(*CurrentToken, Style)) { 13015f757f3fSDimitry Andric CurrentToken->MustBreakBefore = true; 13025f757f3fSDimitry Andric } 13035f757f3fSDimitry Andric } 13040b57cec5SDimitry Andric FormatToken *Tok = CurrentToken; 13050b57cec5SDimitry Andric next(); 1306bdd1243dSDimitry Andric // In Verilog primitives' state tables, `:`, `?`, and `-` aren't normal 1307bdd1243dSDimitry Andric // operators. 1308bdd1243dSDimitry Andric if (Tok->is(TT_VerilogTableItem)) 1309bdd1243dSDimitry Andric return true; 13100fca6ea1SDimitry Andric // Multi-line string itself is a single annotated token. 13110fca6ea1SDimitry Andric if (Tok->is(TT_TableGenMultiLineString)) 13120fca6ea1SDimitry Andric return true; 13130b57cec5SDimitry Andric switch (Tok->Tok.getKind()) { 13140b57cec5SDimitry Andric case tok::plus: 13150b57cec5SDimitry Andric case tok::minus: 13160b57cec5SDimitry Andric if (!Tok->Previous && Line.MustBeDeclaration) 13175ffd83dbSDimitry Andric Tok->setType(TT_ObjCMethodSpecifier); 13180b57cec5SDimitry Andric break; 13190b57cec5SDimitry Andric case tok::colon: 13200b57cec5SDimitry Andric if (!Tok->Previous) 13210b57cec5SDimitry Andric return false; 132206c3fb27SDimitry Andric // Goto labels and case labels are already identified in 132306c3fb27SDimitry Andric // UnwrappedLineParser. 132406c3fb27SDimitry Andric if (Tok->isTypeFinalized()) 132506c3fb27SDimitry Andric break; 13260b57cec5SDimitry Andric // Colons from ?: are handled in parseConditional(). 13270eae32dcSDimitry Andric if (Style.isJavaScript()) { 13280b57cec5SDimitry Andric if (Contexts.back().ColonIsForRangeExpr || // colon in for loop 13290b57cec5SDimitry Andric (Contexts.size() == 1 && // switch/case labels 13300b57cec5SDimitry Andric !Line.First->isOneOf(tok::kw_enum, tok::kw_case)) || 13310b57cec5SDimitry Andric Contexts.back().ContextKind == tok::l_paren || // function params 13320b57cec5SDimitry Andric Contexts.back().ContextKind == tok::l_square || // array type 13330b57cec5SDimitry Andric (!Contexts.back().IsExpression && 13340b57cec5SDimitry Andric Contexts.back().ContextKind == tok::l_brace) || // object type 13350b57cec5SDimitry Andric (Contexts.size() == 1 && 13360b57cec5SDimitry Andric Line.MustBeDeclaration)) { // method/property declaration 13370b57cec5SDimitry Andric Contexts.back().IsExpression = false; 13385ffd83dbSDimitry Andric Tok->setType(TT_JsTypeColon); 13395ffd83dbSDimitry Andric break; 13405ffd83dbSDimitry Andric } 13415ffd83dbSDimitry Andric } else if (Style.isCSharp()) { 13425ffd83dbSDimitry Andric if (Contexts.back().InCSharpAttributeSpecifier) { 13435ffd83dbSDimitry Andric Tok->setType(TT_AttributeColon); 13445ffd83dbSDimitry Andric break; 13455ffd83dbSDimitry Andric } 13465ffd83dbSDimitry Andric if (Contexts.back().ContextKind == tok::l_paren) { 13475ffd83dbSDimitry Andric Tok->setType(TT_CSharpNamedArgumentColon); 13480b57cec5SDimitry Andric break; 13490b57cec5SDimitry Andric } 1350bdd1243dSDimitry Andric } else if (Style.isVerilog() && Tok->isNot(TT_BinaryOperator)) { 1351bdd1243dSDimitry Andric // The distribution weight operators are labeled 1352bdd1243dSDimitry Andric // TT_BinaryOperator by the lexer. 1353bdd1243dSDimitry Andric if (Keywords.isVerilogEnd(*Tok->Previous) || 1354bdd1243dSDimitry Andric Keywords.isVerilogBegin(*Tok->Previous)) { 1355bdd1243dSDimitry Andric Tok->setType(TT_VerilogBlockLabelColon); 1356bdd1243dSDimitry Andric } else if (Contexts.back().ContextKind == tok::l_square) { 1357bdd1243dSDimitry Andric Tok->setType(TT_BitFieldColon); 1358bdd1243dSDimitry Andric } else if (Contexts.back().ColonIsDictLiteral) { 1359bdd1243dSDimitry Andric Tok->setType(TT_DictLiteral); 1360bdd1243dSDimitry Andric } else if (Contexts.size() == 1) { 1361bdd1243dSDimitry Andric // In Verilog a case label doesn't have the case keyword. We 1362bdd1243dSDimitry Andric // assume a colon following an expression is a case label. 1363bdd1243dSDimitry Andric // Colons from ?: are annotated in parseConditional(). 136406c3fb27SDimitry Andric Tok->setType(TT_CaseLabelColon); 1365bdd1243dSDimitry Andric if (Line.Level > 1 || (!Line.InPPDirective && Line.Level > 0)) 1366bdd1243dSDimitry Andric --Line.Level; 1367bdd1243dSDimitry Andric } 1368bdd1243dSDimitry Andric break; 13690b57cec5SDimitry Andric } 13704824e7fdSDimitry Andric if (Line.First->isOneOf(Keywords.kw_module, Keywords.kw_import) || 13714824e7fdSDimitry Andric Line.First->startsSequence(tok::kw_export, Keywords.kw_module) || 13724824e7fdSDimitry Andric Line.First->startsSequence(tok::kw_export, Keywords.kw_import)) { 13734824e7fdSDimitry Andric Tok->setType(TT_ModulePartitionColon); 13740fca6ea1SDimitry Andric } else if (Line.First->is(tok::kw_asm)) { 13750fca6ea1SDimitry Andric Tok->setType(TT_InlineASMColon); 13765f757f3fSDimitry Andric } else if (Contexts.back().ColonIsDictLiteral || Style.isProto()) { 13775ffd83dbSDimitry Andric Tok->setType(TT_DictLiteral); 13780b57cec5SDimitry Andric if (Style.Language == FormatStyle::LK_TextProto) { 13790b57cec5SDimitry Andric if (FormatToken *Previous = Tok->getPreviousNonComment()) 13805ffd83dbSDimitry Andric Previous->setType(TT_SelectorName); 13810b57cec5SDimitry Andric } 13820b57cec5SDimitry Andric } else if (Contexts.back().ColonIsObjCMethodExpr || 13830b57cec5SDimitry Andric Line.startsWith(TT_ObjCMethodSpecifier)) { 13845ffd83dbSDimitry Andric Tok->setType(TT_ObjCMethodExpr); 13850b57cec5SDimitry Andric const FormatToken *BeforePrevious = Tok->Previous->Previous; 13860b57cec5SDimitry Andric // Ensure we tag all identifiers in method declarations as 13870b57cec5SDimitry Andric // TT_SelectorName. 13880b57cec5SDimitry Andric bool UnknownIdentifierInMethodDeclaration = 13890b57cec5SDimitry Andric Line.startsWith(TT_ObjCMethodSpecifier) && 13900b57cec5SDimitry Andric Tok->Previous->is(tok::identifier) && Tok->Previous->is(TT_Unknown); 13910b57cec5SDimitry Andric if (!BeforePrevious || 13920b57cec5SDimitry Andric // FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen. 13930b57cec5SDimitry Andric !(BeforePrevious->is(TT_CastRParen) || 13940b57cec5SDimitry Andric (BeforePrevious->is(TT_ObjCMethodExpr) && 13950b57cec5SDimitry Andric BeforePrevious->is(tok::colon))) || 13960b57cec5SDimitry Andric BeforePrevious->is(tok::r_square) || 13970b57cec5SDimitry Andric Contexts.back().LongestObjCSelectorName == 0 || 13980b57cec5SDimitry Andric UnknownIdentifierInMethodDeclaration) { 13995ffd83dbSDimitry Andric Tok->Previous->setType(TT_SelectorName); 140081ad6265SDimitry Andric if (!Contexts.back().FirstObjCSelectorName) { 14010b57cec5SDimitry Andric Contexts.back().FirstObjCSelectorName = Tok->Previous; 140281ad6265SDimitry Andric } else if (Tok->Previous->ColumnWidth > 140381ad6265SDimitry Andric Contexts.back().LongestObjCSelectorName) { 14040b57cec5SDimitry Andric Contexts.back().LongestObjCSelectorName = 14050b57cec5SDimitry Andric Tok->Previous->ColumnWidth; 140681ad6265SDimitry Andric } 14070b57cec5SDimitry Andric Tok->Previous->ParameterIndex = 14080b57cec5SDimitry Andric Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts; 14090b57cec5SDimitry Andric ++Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts; 14100b57cec5SDimitry Andric } 14110b57cec5SDimitry Andric } else if (Contexts.back().ColonIsForRangeExpr) { 14125ffd83dbSDimitry Andric Tok->setType(TT_RangeBasedForLoopColon); 1413bdd1243dSDimitry Andric } else if (Contexts.back().ContextType == Context::C11GenericSelection) { 1414bdd1243dSDimitry Andric Tok->setType(TT_GenericSelectionColon); 14150b57cec5SDimitry Andric } else if (CurrentToken && CurrentToken->is(tok::numeric_constant)) { 14165ffd83dbSDimitry Andric Tok->setType(TT_BitFieldColon); 14170b57cec5SDimitry Andric } else if (Contexts.size() == 1 && 1418e8d8bef9SDimitry Andric !Line.First->isOneOf(tok::kw_enum, tok::kw_case, 1419e8d8bef9SDimitry Andric tok::kw_default)) { 14205ffd83dbSDimitry Andric FormatToken *Prev = Tok->getPreviousNonComment(); 14214824e7fdSDimitry Andric if (!Prev) 14224824e7fdSDimitry Andric break; 1423fcaf7f86SDimitry Andric if (Prev->isOneOf(tok::r_paren, tok::kw_noexcept) || 1424fcaf7f86SDimitry Andric Prev->ClosesRequiresClause) { 14255ffd83dbSDimitry Andric Tok->setType(TT_CtorInitializerColon); 142681ad6265SDimitry Andric } else if (Prev->is(tok::kw_try)) { 14275ffd83dbSDimitry Andric // Member initializer list within function try block. 14285ffd83dbSDimitry Andric FormatToken *PrevPrev = Prev->getPreviousNonComment(); 14294824e7fdSDimitry Andric if (!PrevPrev) 14304824e7fdSDimitry Andric break; 14315ffd83dbSDimitry Andric if (PrevPrev && PrevPrev->isOneOf(tok::r_paren, tok::kw_noexcept)) 14325ffd83dbSDimitry Andric Tok->setType(TT_CtorInitializerColon); 143381ad6265SDimitry Andric } else { 14345ffd83dbSDimitry Andric Tok->setType(TT_InheritanceColon); 14350fca6ea1SDimitry Andric if (Prev->isAccessSpecifierKeyword()) 14360fca6ea1SDimitry Andric Line.Type = LT_AccessModifier; 143781ad6265SDimitry Andric } 14380b57cec5SDimitry Andric } else if (canBeObjCSelectorComponent(*Tok->Previous) && Tok->Next && 14390b57cec5SDimitry Andric (Tok->Next->isOneOf(tok::r_paren, tok::comma) || 14400b57cec5SDimitry Andric (canBeObjCSelectorComponent(*Tok->Next) && Tok->Next->Next && 14410b57cec5SDimitry Andric Tok->Next->Next->is(tok::colon)))) { 14420b57cec5SDimitry Andric // This handles a special macro in ObjC code where selectors including 14430b57cec5SDimitry Andric // the colon are passed as macro arguments. 14445ffd83dbSDimitry Andric Tok->setType(TT_ObjCMethodExpr); 14450b57cec5SDimitry Andric } 14460b57cec5SDimitry Andric break; 14470b57cec5SDimitry Andric case tok::pipe: 14480b57cec5SDimitry Andric case tok::amp: 14490b57cec5SDimitry Andric // | and & in declarations/type expressions represent union and 14500b57cec5SDimitry Andric // intersection types, respectively. 14510eae32dcSDimitry Andric if (Style.isJavaScript() && !Contexts.back().IsExpression) 14525ffd83dbSDimitry Andric Tok->setType(TT_JsTypeOperator); 14530b57cec5SDimitry Andric break; 14540b57cec5SDimitry Andric case tok::kw_if: 14550fca6ea1SDimitry Andric if (Style.isTableGen()) { 14560fca6ea1SDimitry Andric // In TableGen it has the form 'if' <value> 'then'. 14570fca6ea1SDimitry Andric if (!parseTableGenValue()) 14580fca6ea1SDimitry Andric return false; 14590fca6ea1SDimitry Andric if (CurrentToken && CurrentToken->is(Keywords.kw_then)) 14600fca6ea1SDimitry Andric next(); // skip then 14610fca6ea1SDimitry Andric break; 14620fca6ea1SDimitry Andric } 146381ad6265SDimitry Andric if (CurrentToken && 146481ad6265SDimitry Andric CurrentToken->isOneOf(tok::kw_constexpr, tok::identifier)) { 14650b57cec5SDimitry Andric next(); 146681ad6265SDimitry Andric } 1467bdd1243dSDimitry Andric [[fallthrough]]; 146881ad6265SDimitry Andric case tok::kw_while: 14690b57cec5SDimitry Andric if (CurrentToken && CurrentToken->is(tok::l_paren)) { 14700b57cec5SDimitry Andric next(); 14710b57cec5SDimitry Andric if (!parseParens(/*LookForDecls=*/true)) 14720b57cec5SDimitry Andric return false; 14730b57cec5SDimitry Andric } 14740b57cec5SDimitry Andric break; 14750b57cec5SDimitry Andric case tok::kw_for: 14760eae32dcSDimitry Andric if (Style.isJavaScript()) { 14770b57cec5SDimitry Andric // x.for and {for: ...} 14780b57cec5SDimitry Andric if ((Tok->Previous && Tok->Previous->is(tok::period)) || 147981ad6265SDimitry Andric (Tok->Next && Tok->Next->is(tok::colon))) { 14800b57cec5SDimitry Andric break; 148181ad6265SDimitry Andric } 14820b57cec5SDimitry Andric // JS' for await ( ... 14830b57cec5SDimitry Andric if (CurrentToken && CurrentToken->is(Keywords.kw_await)) 14840b57cec5SDimitry Andric next(); 14850b57cec5SDimitry Andric } 14860fca6ea1SDimitry Andric if (IsCpp && CurrentToken && CurrentToken->is(tok::kw_co_await)) 14874824e7fdSDimitry Andric next(); 14880b57cec5SDimitry Andric Contexts.back().ColonIsForRangeExpr = true; 148981ad6265SDimitry Andric if (!CurrentToken || CurrentToken->isNot(tok::l_paren)) 149081ad6265SDimitry Andric return false; 14910b57cec5SDimitry Andric next(); 14920b57cec5SDimitry Andric if (!parseParens()) 14930b57cec5SDimitry Andric return false; 14940b57cec5SDimitry Andric break; 14950b57cec5SDimitry Andric case tok::l_paren: 14960b57cec5SDimitry Andric // When faced with 'operator()()', the kw_operator handler incorrectly 14970b57cec5SDimitry Andric // marks the first l_paren as a OverloadedOperatorLParen. Here, we make 14980b57cec5SDimitry Andric // the first two parens OverloadedOperators and the second l_paren an 14990b57cec5SDimitry Andric // OverloadedOperatorLParen. 15000b57cec5SDimitry Andric if (Tok->Previous && Tok->Previous->is(tok::r_paren) && 15010b57cec5SDimitry Andric Tok->Previous->MatchingParen && 15020b57cec5SDimitry Andric Tok->Previous->MatchingParen->is(TT_OverloadedOperatorLParen)) { 15035ffd83dbSDimitry Andric Tok->Previous->setType(TT_OverloadedOperator); 15045ffd83dbSDimitry Andric Tok->Previous->MatchingParen->setType(TT_OverloadedOperator); 15055ffd83dbSDimitry Andric Tok->setType(TT_OverloadedOperatorLParen); 15060b57cec5SDimitry Andric } 15070b57cec5SDimitry Andric 150806c3fb27SDimitry Andric if (Style.isVerilog()) { 150906c3fb27SDimitry Andric // Identify the parameter list and port list in a module instantiation. 151006c3fb27SDimitry Andric // This is still needed when we already have 151106c3fb27SDimitry Andric // UnwrappedLineParser::parseVerilogHierarchyHeader because that 151206c3fb27SDimitry Andric // function is only responsible for the definition, not the 151306c3fb27SDimitry Andric // instantiation. 151406c3fb27SDimitry Andric auto IsInstancePort = [&]() { 151506c3fb27SDimitry Andric const FormatToken *Prev = Tok->getPreviousNonComment(); 151606c3fb27SDimitry Andric const FormatToken *PrevPrev; 151706c3fb27SDimitry Andric // In the following example all 4 left parentheses will be treated as 151806c3fb27SDimitry Andric // 'TT_VerilogInstancePortLParen'. 151906c3fb27SDimitry Andric // 152006c3fb27SDimitry Andric // module_x instance_1(port_1); // Case A. 152106c3fb27SDimitry Andric // module_x #(parameter_1) // Case B. 152206c3fb27SDimitry Andric // instance_2(port_1), // Case C. 152306c3fb27SDimitry Andric // instance_3(port_1); // Case D. 152406c3fb27SDimitry Andric if (!Prev || !(PrevPrev = Prev->getPreviousNonComment())) 152506c3fb27SDimitry Andric return false; 152606c3fb27SDimitry Andric // Case A. 152706c3fb27SDimitry Andric if (Keywords.isVerilogIdentifier(*Prev) && 152806c3fb27SDimitry Andric Keywords.isVerilogIdentifier(*PrevPrev)) { 152906c3fb27SDimitry Andric return true; 153006c3fb27SDimitry Andric } 153106c3fb27SDimitry Andric // Case B. 153206c3fb27SDimitry Andric if (Prev->is(Keywords.kw_verilogHash) && 153306c3fb27SDimitry Andric Keywords.isVerilogIdentifier(*PrevPrev)) { 153406c3fb27SDimitry Andric return true; 153506c3fb27SDimitry Andric } 153606c3fb27SDimitry Andric // Case C. 153706c3fb27SDimitry Andric if (Keywords.isVerilogIdentifier(*Prev) && PrevPrev->is(tok::r_paren)) 153806c3fb27SDimitry Andric return true; 153906c3fb27SDimitry Andric // Case D. 154006c3fb27SDimitry Andric if (Keywords.isVerilogIdentifier(*Prev) && PrevPrev->is(tok::comma)) { 154106c3fb27SDimitry Andric const FormatToken *PrevParen = PrevPrev->getPreviousNonComment(); 154206c3fb27SDimitry Andric if (PrevParen->is(tok::r_paren) && PrevParen->MatchingParen && 154306c3fb27SDimitry Andric PrevParen->MatchingParen->is(TT_VerilogInstancePortLParen)) { 154406c3fb27SDimitry Andric return true; 154506c3fb27SDimitry Andric } 154606c3fb27SDimitry Andric } 154706c3fb27SDimitry Andric return false; 154806c3fb27SDimitry Andric }; 154906c3fb27SDimitry Andric 155006c3fb27SDimitry Andric if (IsInstancePort()) 155106c3fb27SDimitry Andric Tok->setFinalizedType(TT_VerilogInstancePortLParen); 155206c3fb27SDimitry Andric } 155306c3fb27SDimitry Andric 15540b57cec5SDimitry Andric if (!parseParens()) 15550b57cec5SDimitry Andric return false; 15560b57cec5SDimitry Andric if (Line.MustBeDeclaration && Contexts.size() == 1 && 15570b57cec5SDimitry Andric !Contexts.back().IsExpression && !Line.startsWith(TT_ObjCProperty) && 15580fca6ea1SDimitry Andric !Line.startsWith(tok::l_paren) && 15595f757f3fSDimitry Andric !Tok->isOneOf(TT_TypeDeclarationParen, TT_RequiresExpressionLParen)) { 15605f757f3fSDimitry Andric if (const auto *Previous = Tok->Previous; 15615f757f3fSDimitry Andric !Previous || 15625f757f3fSDimitry Andric (!Previous->isAttribute() && 15635f757f3fSDimitry Andric !Previous->isOneOf(TT_RequiresClause, TT_LeadingJavaAnnotation))) { 15640b57cec5SDimitry Andric Line.MightBeFunctionDecl = true; 15650fca6ea1SDimitry Andric Tok->MightBeFunctionDeclParen = true; 156681ad6265SDimitry Andric } 15675f757f3fSDimitry Andric } 15680b57cec5SDimitry Andric break; 15690b57cec5SDimitry Andric case tok::l_square: 15700fca6ea1SDimitry Andric if (Style.isTableGen()) 15710fca6ea1SDimitry Andric Tok->setType(TT_TableGenListOpener); 15720b57cec5SDimitry Andric if (!parseSquare()) 15730b57cec5SDimitry Andric return false; 15740b57cec5SDimitry Andric break; 15750b57cec5SDimitry Andric case tok::l_brace: 15760b57cec5SDimitry Andric if (Style.Language == FormatStyle::LK_TextProto) { 15770b57cec5SDimitry Andric FormatToken *Previous = Tok->getPreviousNonComment(); 15780fca6ea1SDimitry Andric if (Previous && Previous->isNot(TT_DictLiteral)) 15795ffd83dbSDimitry Andric Previous->setType(TT_SelectorName); 15800b57cec5SDimitry Andric } 158106c3fb27SDimitry Andric Scopes.push_back(getScopeType(*Tok)); 15820b57cec5SDimitry Andric if (!parseBrace()) 15830b57cec5SDimitry Andric return false; 15840b57cec5SDimitry Andric break; 15850b57cec5SDimitry Andric case tok::less: 15860b57cec5SDimitry Andric if (parseAngle()) { 15875ffd83dbSDimitry Andric Tok->setType(TT_TemplateOpener); 15880b57cec5SDimitry Andric // In TT_Proto, we must distignuish between: 15890b57cec5SDimitry Andric // map<key, value> 15900b57cec5SDimitry Andric // msg < item: data > 15910b57cec5SDimitry Andric // msg: < item: data > 15920b57cec5SDimitry Andric // In TT_TextProto, map<key, value> does not occur. 15930b57cec5SDimitry Andric if (Style.Language == FormatStyle::LK_TextProto || 15940b57cec5SDimitry Andric (Style.Language == FormatStyle::LK_Proto && Tok->Previous && 15950b57cec5SDimitry Andric Tok->Previous->isOneOf(TT_SelectorName, TT_DictLiteral))) { 15965ffd83dbSDimitry Andric Tok->setType(TT_DictLiteral); 15970b57cec5SDimitry Andric FormatToken *Previous = Tok->getPreviousNonComment(); 15980fca6ea1SDimitry Andric if (Previous && Previous->isNot(TT_DictLiteral)) 15995ffd83dbSDimitry Andric Previous->setType(TT_SelectorName); 16000b57cec5SDimitry Andric } 16010fca6ea1SDimitry Andric if (Style.isTableGen()) 16020fca6ea1SDimitry Andric Tok->setType(TT_TemplateOpener); 16030b57cec5SDimitry Andric } else { 16045ffd83dbSDimitry Andric Tok->setType(TT_BinaryOperator); 16050b57cec5SDimitry Andric NonTemplateLess.insert(Tok); 16060b57cec5SDimitry Andric CurrentToken = Tok; 16070b57cec5SDimitry Andric next(); 16080b57cec5SDimitry Andric } 16090b57cec5SDimitry Andric break; 16100b57cec5SDimitry Andric case tok::r_paren: 16110b57cec5SDimitry Andric case tok::r_square: 16120b57cec5SDimitry Andric return false; 16130b57cec5SDimitry Andric case tok::r_brace: 161406c3fb27SDimitry Andric // Don't pop scope when encountering unbalanced r_brace. 161506c3fb27SDimitry Andric if (!Scopes.empty()) 161606c3fb27SDimitry Andric Scopes.pop_back(); 16170b57cec5SDimitry Andric // Lines can start with '}'. 16180b57cec5SDimitry Andric if (Tok->Previous) 16190b57cec5SDimitry Andric return false; 16200b57cec5SDimitry Andric break; 16210b57cec5SDimitry Andric case tok::greater: 1622*5deeebd8SDimitry Andric if (Style.Language != FormatStyle::LK_TextProto && Tok->is(TT_Unknown)) 16235ffd83dbSDimitry Andric Tok->setType(TT_BinaryOperator); 1624a7dea167SDimitry Andric if (Tok->Previous && Tok->Previous->is(TT_TemplateCloser)) 1625a7dea167SDimitry Andric Tok->SpacesRequiredBefore = 1; 16260b57cec5SDimitry Andric break; 16270b57cec5SDimitry Andric case tok::kw_operator: 16285f757f3fSDimitry Andric if (Style.isProto()) 16290b57cec5SDimitry Andric break; 16300b57cec5SDimitry Andric while (CurrentToken && 16310b57cec5SDimitry Andric !CurrentToken->isOneOf(tok::l_paren, tok::semi, tok::r_paren)) { 16320b57cec5SDimitry Andric if (CurrentToken->isOneOf(tok::star, tok::amp)) 16335ffd83dbSDimitry Andric CurrentToken->setType(TT_PointerOrReference); 163406c3fb27SDimitry Andric auto Next = CurrentToken->getNextNonComment(); 163506c3fb27SDimitry Andric if (!Next) 163606c3fb27SDimitry Andric break; 163706c3fb27SDimitry Andric if (Next->is(tok::less)) 163806c3fb27SDimitry Andric next(); 163906c3fb27SDimitry Andric else 16400b57cec5SDimitry Andric consumeToken(); 1641bdd1243dSDimitry Andric if (!CurrentToken) 16425ffd83dbSDimitry Andric break; 164306c3fb27SDimitry Andric auto Previous = CurrentToken->getPreviousNonComment(); 164406c3fb27SDimitry Andric assert(Previous); 164506c3fb27SDimitry Andric if (CurrentToken->is(tok::comma) && Previous->isNot(tok::kw_operator)) 164606c3fb27SDimitry Andric break; 164706c3fb27SDimitry Andric if (Previous->isOneOf(TT_BinaryOperator, TT_UnaryOperator, tok::comma, 164806c3fb27SDimitry Andric tok::star, tok::arrow, tok::amp, tok::ampamp) || 1649bdd1243dSDimitry Andric // User defined literal. 16505f757f3fSDimitry Andric Previous->TokenText.starts_with("\"\"")) { 165106c3fb27SDimitry Andric Previous->setType(TT_OverloadedOperator); 165206c3fb27SDimitry Andric if (CurrentToken->isOneOf(tok::less, tok::greater)) 165306c3fb27SDimitry Andric break; 16540b57cec5SDimitry Andric } 165581ad6265SDimitry Andric } 16565ffd83dbSDimitry Andric if (CurrentToken && CurrentToken->is(tok::l_paren)) 16575ffd83dbSDimitry Andric CurrentToken->setType(TT_OverloadedOperatorLParen); 16585ffd83dbSDimitry Andric if (CurrentToken && CurrentToken->Previous->is(TT_BinaryOperator)) 16595ffd83dbSDimitry Andric CurrentToken->Previous->setType(TT_OverloadedOperator); 16600b57cec5SDimitry Andric break; 16610b57cec5SDimitry Andric case tok::question: 16620eae32dcSDimitry Andric if (Style.isJavaScript() && Tok->Next && 16630b57cec5SDimitry Andric Tok->Next->isOneOf(tok::semi, tok::comma, tok::colon, tok::r_paren, 166406c3fb27SDimitry Andric tok::r_brace, tok::r_square)) { 16650b57cec5SDimitry Andric // Question marks before semicolons, colons, etc. indicate optional 16660b57cec5SDimitry Andric // types (fields, parameters), e.g. 16670b57cec5SDimitry Andric // function(x?: string, y?) {...} 16680b57cec5SDimitry Andric // class X { y?; } 16695ffd83dbSDimitry Andric Tok->setType(TT_JsTypeOptionalQuestion); 16700b57cec5SDimitry Andric break; 16710b57cec5SDimitry Andric } 16720b57cec5SDimitry Andric // Declarations cannot be conditional expressions, this can only be part 16730b57cec5SDimitry Andric // of a type declaration. 16740b57cec5SDimitry Andric if (Line.MustBeDeclaration && !Contexts.back().IsExpression && 167581ad6265SDimitry Andric Style.isJavaScript()) { 16760b57cec5SDimitry Andric break; 167781ad6265SDimitry Andric } 16785ffd83dbSDimitry Andric if (Style.isCSharp()) { 16795ffd83dbSDimitry Andric // `Type?)`, `Type?>`, `Type? name;` and `Type? name =` can only be 16805ffd83dbSDimitry Andric // nullable types. 168106c3fb27SDimitry Andric 168206c3fb27SDimitry Andric // `Type?)`, `Type?>`, `Type? name;` 168306c3fb27SDimitry Andric if (Tok->Next && 168406c3fb27SDimitry Andric (Tok->Next->startsSequence(tok::question, tok::r_paren) || 168506c3fb27SDimitry Andric Tok->Next->startsSequence(tok::question, tok::greater) || 168606c3fb27SDimitry Andric Tok->Next->startsSequence(tok::question, tok::identifier, 168706c3fb27SDimitry Andric tok::semi))) { 168806c3fb27SDimitry Andric Tok->setType(TT_CSharpNullable); 168906c3fb27SDimitry Andric break; 169006c3fb27SDimitry Andric } 169106c3fb27SDimitry Andric 169206c3fb27SDimitry Andric // `Type? name =` 169306c3fb27SDimitry Andric if (Tok->Next && Tok->Next->is(tok::identifier) && Tok->Next->Next && 169406c3fb27SDimitry Andric Tok->Next->Next->is(tok::equal)) { 169506c3fb27SDimitry Andric Tok->setType(TT_CSharpNullable); 169606c3fb27SDimitry Andric break; 169706c3fb27SDimitry Andric } 169806c3fb27SDimitry Andric 16995ffd83dbSDimitry Andric // Line.MustBeDeclaration will be true for `Type? name;`. 170006c3fb27SDimitry Andric // But not 170106c3fb27SDimitry Andric // cond ? "A" : "B"; 170206c3fb27SDimitry Andric // cond ? id : "B"; 170306c3fb27SDimitry Andric // cond ? cond2 ? "A" : "B" : "C"; 170406c3fb27SDimitry Andric if (!Contexts.back().IsExpression && Line.MustBeDeclaration && 170506c3fb27SDimitry Andric (!Tok->Next || 170606c3fb27SDimitry Andric !Tok->Next->isOneOf(tok::identifier, tok::string_literal) || 170706c3fb27SDimitry Andric !Tok->Next->Next || 170806c3fb27SDimitry Andric !Tok->Next->Next->isOneOf(tok::colon, tok::question))) { 17095ffd83dbSDimitry Andric Tok->setType(TT_CSharpNullable); 17105ffd83dbSDimitry Andric break; 17115ffd83dbSDimitry Andric } 17125ffd83dbSDimitry Andric } 17130b57cec5SDimitry Andric parseConditional(); 17140b57cec5SDimitry Andric break; 17150b57cec5SDimitry Andric case tok::kw_template: 17160b57cec5SDimitry Andric parseTemplateDeclaration(); 17170b57cec5SDimitry Andric break; 17180b57cec5SDimitry Andric case tok::comma: 171981ad6265SDimitry Andric switch (Contexts.back().ContextType) { 172081ad6265SDimitry Andric case Context::CtorInitializer: 17215ffd83dbSDimitry Andric Tok->setType(TT_CtorInitializerComma); 172281ad6265SDimitry Andric break; 172381ad6265SDimitry Andric case Context::InheritanceList: 17245ffd83dbSDimitry Andric Tok->setType(TT_InheritanceComma); 172581ad6265SDimitry Andric break; 172606c3fb27SDimitry Andric case Context::VerilogInstancePortList: 172706c3fb27SDimitry Andric Tok->setFinalizedType(TT_VerilogInstancePortComma); 172806c3fb27SDimitry Andric break; 172981ad6265SDimitry Andric default: 173006c3fb27SDimitry Andric if (Style.isVerilog() && Contexts.size() == 1 && 173106c3fb27SDimitry Andric Line.startsWith(Keywords.kw_assign)) { 173206c3fb27SDimitry Andric Tok->setFinalizedType(TT_VerilogAssignComma); 173306c3fb27SDimitry Andric } else if (Contexts.back().FirstStartOfName && 173481ad6265SDimitry Andric (Contexts.size() == 1 || startsWithInitStatement(Line))) { 17350b57cec5SDimitry Andric Contexts.back().FirstStartOfName->PartOfMultiVariableDeclStmt = true; 17360b57cec5SDimitry Andric Line.IsMultiVariableDeclStmt = true; 17370b57cec5SDimitry Andric } 173881ad6265SDimitry Andric break; 173981ad6265SDimitry Andric } 174081ad6265SDimitry Andric if (Contexts.back().ContextType == Context::ForEachMacro) 17410b57cec5SDimitry Andric Contexts.back().IsExpression = true; 17420b57cec5SDimitry Andric break; 1743bdd1243dSDimitry Andric case tok::kw_default: 1744bdd1243dSDimitry Andric // Unindent case labels. 1745bdd1243dSDimitry Andric if (Style.isVerilog() && Keywords.isVerilogEndOfLabel(*Tok) && 1746bdd1243dSDimitry Andric (Line.Level > 1 || (!Line.InPPDirective && Line.Level > 0))) { 1747bdd1243dSDimitry Andric --Line.Level; 1748bdd1243dSDimitry Andric } 1749bdd1243dSDimitry Andric break; 17500b57cec5SDimitry Andric case tok::identifier: 17510b57cec5SDimitry Andric if (Tok->isOneOf(Keywords.kw___has_include, 17520b57cec5SDimitry Andric Keywords.kw___has_include_next)) { 17530b57cec5SDimitry Andric parseHasInclude(); 17540b57cec5SDimitry Andric } 17555ffd83dbSDimitry Andric if (Style.isCSharp() && Tok->is(Keywords.kw_where) && Tok->Next && 17565ffd83dbSDimitry Andric Tok->Next->isNot(tok::l_paren)) { 17575ffd83dbSDimitry Andric Tok->setType(TT_CSharpGenericTypeConstraint); 17585ffd83dbSDimitry Andric parseCSharpGenericTypeConstraint(); 175906c3fb27SDimitry Andric if (!Tok->getPreviousNonComment()) 1760bdd1243dSDimitry Andric Line.IsContinuation = true; 17615ffd83dbSDimitry Andric } 17620fca6ea1SDimitry Andric if (Style.isTableGen()) { 17630fca6ea1SDimitry Andric if (Tok->is(Keywords.kw_assert)) { 17640fca6ea1SDimitry Andric if (!parseTableGenValue()) 17650fca6ea1SDimitry Andric return false; 17660fca6ea1SDimitry Andric } else if (Tok->isOneOf(Keywords.kw_def, Keywords.kw_defm) && 17670fca6ea1SDimitry Andric (!Tok->Next || 17680fca6ea1SDimitry Andric !Tok->Next->isOneOf(tok::colon, tok::l_brace))) { 17690fca6ea1SDimitry Andric // The case NameValue appears. 17700fca6ea1SDimitry Andric if (!parseTableGenValue(true)) 17710fca6ea1SDimitry Andric return false; 17720fca6ea1SDimitry Andric } 17730fca6ea1SDimitry Andric } 17740b57cec5SDimitry Andric break; 177581ad6265SDimitry Andric case tok::arrow: 17766c4b055cSDimitry Andric if (Tok->isNot(TT_LambdaArrow) && Tok->Previous && 17776c4b055cSDimitry Andric Tok->Previous->is(tok::kw_noexcept)) { 177881ad6265SDimitry Andric Tok->setType(TT_TrailingReturnArrow); 17796c4b055cSDimitry Andric } 1780bdd1243dSDimitry Andric break; 17810fca6ea1SDimitry Andric case tok::equal: 17820fca6ea1SDimitry Andric // In TableGen, there must be a value after "="; 17830fca6ea1SDimitry Andric if (Style.isTableGen() && !parseTableGenValue()) 17840fca6ea1SDimitry Andric return false; 17850fca6ea1SDimitry Andric break; 17860b57cec5SDimitry Andric default: 17870b57cec5SDimitry Andric break; 17880b57cec5SDimitry Andric } 17890b57cec5SDimitry Andric return true; 17900b57cec5SDimitry Andric } 17910b57cec5SDimitry Andric 17925ffd83dbSDimitry Andric void parseCSharpGenericTypeConstraint() { 17935ffd83dbSDimitry Andric int OpenAngleBracketsCount = 0; 17945ffd83dbSDimitry Andric while (CurrentToken) { 17955ffd83dbSDimitry Andric if (CurrentToken->is(tok::less)) { 17965ffd83dbSDimitry Andric // parseAngle is too greedy and will consume the whole line. 17975ffd83dbSDimitry Andric CurrentToken->setType(TT_TemplateOpener); 17985ffd83dbSDimitry Andric ++OpenAngleBracketsCount; 17995ffd83dbSDimitry Andric next(); 18005ffd83dbSDimitry Andric } else if (CurrentToken->is(tok::greater)) { 18015ffd83dbSDimitry Andric CurrentToken->setType(TT_TemplateCloser); 18025ffd83dbSDimitry Andric --OpenAngleBracketsCount; 18035ffd83dbSDimitry Andric next(); 18045ffd83dbSDimitry Andric } else if (CurrentToken->is(tok::comma) && OpenAngleBracketsCount == 0) { 18055ffd83dbSDimitry Andric // We allow line breaks after GenericTypeConstraintComma's 18065ffd83dbSDimitry Andric // so do not flag commas in Generics as GenericTypeConstraintComma's. 18075ffd83dbSDimitry Andric CurrentToken->setType(TT_CSharpGenericTypeConstraintComma); 18085ffd83dbSDimitry Andric next(); 18095ffd83dbSDimitry Andric } else if (CurrentToken->is(Keywords.kw_where)) { 18105ffd83dbSDimitry Andric CurrentToken->setType(TT_CSharpGenericTypeConstraint); 18115ffd83dbSDimitry Andric next(); 18125ffd83dbSDimitry Andric } else if (CurrentToken->is(tok::colon)) { 18135ffd83dbSDimitry Andric CurrentToken->setType(TT_CSharpGenericTypeConstraintColon); 18145ffd83dbSDimitry Andric next(); 18155ffd83dbSDimitry Andric } else { 18165ffd83dbSDimitry Andric next(); 18175ffd83dbSDimitry Andric } 18185ffd83dbSDimitry Andric } 18195ffd83dbSDimitry Andric } 18205ffd83dbSDimitry Andric 18210b57cec5SDimitry Andric void parseIncludeDirective() { 18220b57cec5SDimitry Andric if (CurrentToken && CurrentToken->is(tok::less)) { 18230b57cec5SDimitry Andric next(); 18240b57cec5SDimitry Andric while (CurrentToken) { 18250b57cec5SDimitry Andric // Mark tokens up to the trailing line comments as implicit string 18260b57cec5SDimitry Andric // literals. 18270b57cec5SDimitry Andric if (CurrentToken->isNot(tok::comment) && 18285f757f3fSDimitry Andric !CurrentToken->TokenText.starts_with("//")) { 18295ffd83dbSDimitry Andric CurrentToken->setType(TT_ImplicitStringLiteral); 183081ad6265SDimitry Andric } 18310b57cec5SDimitry Andric next(); 18320b57cec5SDimitry Andric } 18330b57cec5SDimitry Andric } 18340b57cec5SDimitry Andric } 18350b57cec5SDimitry Andric 18360b57cec5SDimitry Andric void parseWarningOrError() { 18370b57cec5SDimitry Andric next(); 18380b57cec5SDimitry Andric // We still want to format the whitespace left of the first token of the 18390b57cec5SDimitry Andric // warning or error. 18400b57cec5SDimitry Andric next(); 18410b57cec5SDimitry Andric while (CurrentToken) { 18425ffd83dbSDimitry Andric CurrentToken->setType(TT_ImplicitStringLiteral); 18430b57cec5SDimitry Andric next(); 18440b57cec5SDimitry Andric } 18450b57cec5SDimitry Andric } 18460b57cec5SDimitry Andric 18470b57cec5SDimitry Andric void parsePragma() { 18480b57cec5SDimitry Andric next(); // Consume "pragma". 18490b57cec5SDimitry Andric if (CurrentToken && 185081ad6265SDimitry Andric CurrentToken->isOneOf(Keywords.kw_mark, Keywords.kw_option, 185181ad6265SDimitry Andric Keywords.kw_region)) { 1852bdd1243dSDimitry Andric bool IsMarkOrRegion = 1853bdd1243dSDimitry Andric CurrentToken->isOneOf(Keywords.kw_mark, Keywords.kw_region); 185481ad6265SDimitry Andric next(); 18550b57cec5SDimitry Andric next(); // Consume first token (so we fix leading whitespace). 18560b57cec5SDimitry Andric while (CurrentToken) { 1857bdd1243dSDimitry Andric if (IsMarkOrRegion || CurrentToken->Previous->is(TT_BinaryOperator)) 18585ffd83dbSDimitry Andric CurrentToken->setType(TT_ImplicitStringLiteral); 18590b57cec5SDimitry Andric next(); 18600b57cec5SDimitry Andric } 18610b57cec5SDimitry Andric } 18620b57cec5SDimitry Andric } 18630b57cec5SDimitry Andric 18640b57cec5SDimitry Andric void parseHasInclude() { 18655f757f3fSDimitry Andric if (!CurrentToken || CurrentToken->isNot(tok::l_paren)) 18660b57cec5SDimitry Andric return; 18670b57cec5SDimitry Andric next(); // '(' 18680b57cec5SDimitry Andric parseIncludeDirective(); 18690b57cec5SDimitry Andric next(); // ')' 18700b57cec5SDimitry Andric } 18710b57cec5SDimitry Andric 18720b57cec5SDimitry Andric LineType parsePreprocessorDirective() { 18730b57cec5SDimitry Andric bool IsFirstToken = CurrentToken->IsFirst; 18740b57cec5SDimitry Andric LineType Type = LT_PreprocessorDirective; 18750b57cec5SDimitry Andric next(); 18760b57cec5SDimitry Andric if (!CurrentToken) 18770b57cec5SDimitry Andric return Type; 18780b57cec5SDimitry Andric 18790eae32dcSDimitry Andric if (Style.isJavaScript() && IsFirstToken) { 18800b57cec5SDimitry Andric // JavaScript files can contain shebang lines of the form: 18810b57cec5SDimitry Andric // #!/usr/bin/env node 18820b57cec5SDimitry Andric // Treat these like C++ #include directives. 18830b57cec5SDimitry Andric while (CurrentToken) { 18840b57cec5SDimitry Andric // Tokens cannot be comments here. 18855ffd83dbSDimitry Andric CurrentToken->setType(TT_ImplicitStringLiteral); 18860b57cec5SDimitry Andric next(); 18870b57cec5SDimitry Andric } 18880b57cec5SDimitry Andric return LT_ImportStatement; 18890b57cec5SDimitry Andric } 18900b57cec5SDimitry Andric 189181ad6265SDimitry Andric if (CurrentToken->is(tok::numeric_constant)) { 18920b57cec5SDimitry Andric CurrentToken->SpacesRequiredBefore = 1; 18930b57cec5SDimitry Andric return Type; 18940b57cec5SDimitry Andric } 18950b57cec5SDimitry Andric // Hashes in the middle of a line can lead to any strange token 18960b57cec5SDimitry Andric // sequence. 18970b57cec5SDimitry Andric if (!CurrentToken->Tok.getIdentifierInfo()) 18980b57cec5SDimitry Andric return Type; 189981ad6265SDimitry Andric // In Verilog macro expansions start with a backtick just like preprocessor 190081ad6265SDimitry Andric // directives. Thus we stop if the word is not a preprocessor directive. 190181ad6265SDimitry Andric if (Style.isVerilog() && !Keywords.isVerilogPPDirective(*CurrentToken)) 190281ad6265SDimitry Andric return LT_Invalid; 19030b57cec5SDimitry Andric switch (CurrentToken->Tok.getIdentifierInfo()->getPPKeywordID()) { 19040b57cec5SDimitry Andric case tok::pp_include: 19050b57cec5SDimitry Andric case tok::pp_include_next: 19060b57cec5SDimitry Andric case tok::pp_import: 19070b57cec5SDimitry Andric next(); 19080b57cec5SDimitry Andric parseIncludeDirective(); 19090b57cec5SDimitry Andric Type = LT_ImportStatement; 19100b57cec5SDimitry Andric break; 19110b57cec5SDimitry Andric case tok::pp_error: 19120b57cec5SDimitry Andric case tok::pp_warning: 19130b57cec5SDimitry Andric parseWarningOrError(); 19140b57cec5SDimitry Andric break; 19150b57cec5SDimitry Andric case tok::pp_pragma: 19160b57cec5SDimitry Andric parsePragma(); 19170b57cec5SDimitry Andric break; 19180b57cec5SDimitry Andric case tok::pp_if: 19190b57cec5SDimitry Andric case tok::pp_elif: 19200b57cec5SDimitry Andric Contexts.back().IsExpression = true; 1921a7dea167SDimitry Andric next(); 19220fca6ea1SDimitry Andric if (CurrentToken) 19230fca6ea1SDimitry Andric CurrentToken->SpacesRequiredBefore = true; 19240b57cec5SDimitry Andric parseLine(); 19250b57cec5SDimitry Andric break; 19260b57cec5SDimitry Andric default: 19270b57cec5SDimitry Andric break; 19280b57cec5SDimitry Andric } 19290b57cec5SDimitry Andric while (CurrentToken) { 19300b57cec5SDimitry Andric FormatToken *Tok = CurrentToken; 19310b57cec5SDimitry Andric next(); 193281ad6265SDimitry Andric if (Tok->is(tok::l_paren)) { 19330b57cec5SDimitry Andric parseParens(); 193481ad6265SDimitry Andric } else if (Tok->isOneOf(Keywords.kw___has_include, 193581ad6265SDimitry Andric Keywords.kw___has_include_next)) { 19360b57cec5SDimitry Andric parseHasInclude(); 19370b57cec5SDimitry Andric } 193881ad6265SDimitry Andric } 19390b57cec5SDimitry Andric return Type; 19400b57cec5SDimitry Andric } 19410b57cec5SDimitry Andric 19420b57cec5SDimitry Andric public: 19430b57cec5SDimitry Andric LineType parseLine() { 1944a7dea167SDimitry Andric if (!CurrentToken) 1945a7dea167SDimitry Andric return LT_Invalid; 19460b57cec5SDimitry Andric NonTemplateLess.clear(); 1947bdd1243dSDimitry Andric if (!Line.InMacroBody && CurrentToken->is(tok::hash)) { 194881ad6265SDimitry Andric // We were not yet allowed to use C++17 optional when this was being 194981ad6265SDimitry Andric // written. So we used LT_Invalid to mark that the line is not a 195081ad6265SDimitry Andric // preprocessor directive. 195181ad6265SDimitry Andric auto Type = parsePreprocessorDirective(); 195281ad6265SDimitry Andric if (Type != LT_Invalid) 195381ad6265SDimitry Andric return Type; 195481ad6265SDimitry Andric } 19550b57cec5SDimitry Andric 19560b57cec5SDimitry Andric // Directly allow to 'import <string-literal>' to support protocol buffer 19570b57cec5SDimitry Andric // definitions (github.com/google/protobuf) or missing "#" (either way we 19580b57cec5SDimitry Andric // should not break the line). 19590b57cec5SDimitry Andric IdentifierInfo *Info = CurrentToken->Tok.getIdentifierInfo(); 19600b57cec5SDimitry Andric if ((Style.Language == FormatStyle::LK_Java && 19610b57cec5SDimitry Andric CurrentToken->is(Keywords.kw_package)) || 1962bdd1243dSDimitry Andric (!Style.isVerilog() && Info && 1963bdd1243dSDimitry Andric Info->getPPKeywordID() == tok::pp_import && CurrentToken->Next && 19640b57cec5SDimitry Andric CurrentToken->Next->isOneOf(tok::string_literal, tok::identifier, 19650b57cec5SDimitry Andric tok::kw_static))) { 19660b57cec5SDimitry Andric next(); 19670b57cec5SDimitry Andric parseIncludeDirective(); 19680b57cec5SDimitry Andric return LT_ImportStatement; 19690b57cec5SDimitry Andric } 19700b57cec5SDimitry Andric 19710b57cec5SDimitry Andric // If this line starts and ends in '<' and '>', respectively, it is likely 19720b57cec5SDimitry Andric // part of "#define <a/b.h>". 19730b57cec5SDimitry Andric if (CurrentToken->is(tok::less) && Line.Last->is(tok::greater)) { 19740b57cec5SDimitry Andric parseIncludeDirective(); 19750b57cec5SDimitry Andric return LT_ImportStatement; 19760b57cec5SDimitry Andric } 19770b57cec5SDimitry Andric 19780b57cec5SDimitry Andric // In .proto files, top-level options and package statements are very 19790b57cec5SDimitry Andric // similar to import statements and should not be line-wrapped. 19800b57cec5SDimitry Andric if (Style.Language == FormatStyle::LK_Proto && Line.Level == 0 && 19810b57cec5SDimitry Andric CurrentToken->isOneOf(Keywords.kw_option, Keywords.kw_package)) { 19820b57cec5SDimitry Andric next(); 19830b57cec5SDimitry Andric if (CurrentToken && CurrentToken->is(tok::identifier)) { 19840b57cec5SDimitry Andric while (CurrentToken) 19850b57cec5SDimitry Andric next(); 19860b57cec5SDimitry Andric return LT_ImportStatement; 19870b57cec5SDimitry Andric } 19880b57cec5SDimitry Andric } 19890b57cec5SDimitry Andric 19900b57cec5SDimitry Andric bool KeywordVirtualFound = false; 19910b57cec5SDimitry Andric bool ImportStatement = false; 19920b57cec5SDimitry Andric 19930b57cec5SDimitry Andric // import {...} from '...'; 19940eae32dcSDimitry Andric if (Style.isJavaScript() && CurrentToken->is(Keywords.kw_import)) 19950b57cec5SDimitry Andric ImportStatement = true; 19960b57cec5SDimitry Andric 19970b57cec5SDimitry Andric while (CurrentToken) { 19980b57cec5SDimitry Andric if (CurrentToken->is(tok::kw_virtual)) 19990b57cec5SDimitry Andric KeywordVirtualFound = true; 20000eae32dcSDimitry Andric if (Style.isJavaScript()) { 20010b57cec5SDimitry Andric // export {...} from '...'; 20020b57cec5SDimitry Andric // An export followed by "from 'some string';" is a re-export from 20030b57cec5SDimitry Andric // another module identified by a URI and is treated as a 20040b57cec5SDimitry Andric // LT_ImportStatement (i.e. prevent wraps on it for long URIs). 20050b57cec5SDimitry Andric // Just "export {...};" or "export class ..." should not be treated as 20060b57cec5SDimitry Andric // an import in this sense. 20070b57cec5SDimitry Andric if (Line.First->is(tok::kw_export) && 20080b57cec5SDimitry Andric CurrentToken->is(Keywords.kw_from) && CurrentToken->Next && 200981ad6265SDimitry Andric CurrentToken->Next->isStringLiteral()) { 20100b57cec5SDimitry Andric ImportStatement = true; 201181ad6265SDimitry Andric } 20120b57cec5SDimitry Andric if (isClosureImportStatement(*CurrentToken)) 20130b57cec5SDimitry Andric ImportStatement = true; 20140b57cec5SDimitry Andric } 20150b57cec5SDimitry Andric if (!consumeToken()) 20160b57cec5SDimitry Andric return LT_Invalid; 20170b57cec5SDimitry Andric } 20180fca6ea1SDimitry Andric if (Line.Type == LT_AccessModifier) 20190fca6ea1SDimitry Andric return LT_AccessModifier; 20200b57cec5SDimitry Andric if (KeywordVirtualFound) 20210b57cec5SDimitry Andric return LT_VirtualFunctionDecl; 20220b57cec5SDimitry Andric if (ImportStatement) 20230b57cec5SDimitry Andric return LT_ImportStatement; 20240b57cec5SDimitry Andric 20250b57cec5SDimitry Andric if (Line.startsWith(TT_ObjCMethodSpecifier)) { 202681ad6265SDimitry Andric if (Contexts.back().FirstObjCSelectorName) { 20270b57cec5SDimitry Andric Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = 20280b57cec5SDimitry Andric Contexts.back().LongestObjCSelectorName; 202981ad6265SDimitry Andric } 20300b57cec5SDimitry Andric return LT_ObjCMethodDecl; 20310b57cec5SDimitry Andric } 20320b57cec5SDimitry Andric 203381ad6265SDimitry Andric for (const auto &ctx : Contexts) 203481ad6265SDimitry Andric if (ctx.ContextType == Context::StructArrayInitializer) 2035fe6060f1SDimitry Andric return LT_ArrayOfStructInitializer; 2036fe6060f1SDimitry Andric 20370b57cec5SDimitry Andric return LT_Other; 20380b57cec5SDimitry Andric } 20390b57cec5SDimitry Andric 20400b57cec5SDimitry Andric private: 20410b57cec5SDimitry Andric bool isClosureImportStatement(const FormatToken &Tok) { 20420b57cec5SDimitry Andric // FIXME: Closure-library specific stuff should not be hard-coded but be 20430b57cec5SDimitry Andric // configurable. 20440b57cec5SDimitry Andric return Tok.TokenText == "goog" && Tok.Next && Tok.Next->is(tok::period) && 20450b57cec5SDimitry Andric Tok.Next->Next && 20460b57cec5SDimitry Andric (Tok.Next->Next->TokenText == "module" || 20470b57cec5SDimitry Andric Tok.Next->Next->TokenText == "provide" || 20480b57cec5SDimitry Andric Tok.Next->Next->TokenText == "require" || 20490b57cec5SDimitry Andric Tok.Next->Next->TokenText == "requireType" || 20500b57cec5SDimitry Andric Tok.Next->Next->TokenText == "forwardDeclare") && 20510b57cec5SDimitry Andric Tok.Next->Next->Next && Tok.Next->Next->Next->is(tok::l_paren); 20520b57cec5SDimitry Andric } 20530b57cec5SDimitry Andric 205404eeddc0SDimitry Andric void resetTokenMetadata() { 205504eeddc0SDimitry Andric if (!CurrentToken) 20560b57cec5SDimitry Andric return; 20570b57cec5SDimitry Andric 20580b57cec5SDimitry Andric // Reset token type in case we have already looked at it and then 20590b57cec5SDimitry Andric // recovered from an error (e.g. failure to find the matching >). 206081ad6265SDimitry Andric if (!CurrentToken->isTypeFinalized() && 206181ad6265SDimitry Andric !CurrentToken->isOneOf( 2062fe6060f1SDimitry Andric TT_LambdaLSquare, TT_LambdaLBrace, TT_AttributeMacro, TT_IfMacro, 2063e8d8bef9SDimitry Andric TT_ForEachMacro, TT_TypenameMacro, TT_FunctionLBrace, 2064fe6060f1SDimitry Andric TT_ImplicitStringLiteral, TT_InlineASMBrace, TT_FatArrow, 20656c4b055cSDimitry Andric TT_LambdaArrow, TT_NamespaceMacro, TT_OverloadedOperator, 20666c4b055cSDimitry Andric TT_RegexLiteral, TT_TemplateString, TT_ObjCStringLiteral, 20676c4b055cSDimitry Andric TT_UntouchableMacroFunc, TT_StatementAttributeLikeMacro, 20686c4b055cSDimitry Andric TT_FunctionLikeOrFreestandingMacro, TT_ClassLBrace, TT_EnumLBrace, 20696c4b055cSDimitry Andric TT_RecordLBrace, TT_StructLBrace, TT_UnionLBrace, TT_RequiresClause, 207081ad6265SDimitry Andric TT_RequiresClauseInARequiresExpression, TT_RequiresExpression, 207181ad6265SDimitry Andric TT_RequiresExpressionLParen, TT_RequiresExpressionLBrace, 20725f757f3fSDimitry Andric TT_BracedListLBrace)) { 20735ffd83dbSDimitry Andric CurrentToken->setType(TT_Unknown); 207481ad6265SDimitry Andric } 20750b57cec5SDimitry Andric CurrentToken->Role.reset(); 20760b57cec5SDimitry Andric CurrentToken->MatchingParen = nullptr; 20770b57cec5SDimitry Andric CurrentToken->FakeLParens.clear(); 20780b57cec5SDimitry Andric CurrentToken->FakeRParens = 0; 20790b57cec5SDimitry Andric } 20800b57cec5SDimitry Andric 20810b57cec5SDimitry Andric void next() { 208204eeddc0SDimitry Andric if (!CurrentToken) 208304eeddc0SDimitry Andric return; 208404eeddc0SDimitry Andric 20850b57cec5SDimitry Andric CurrentToken->NestingLevel = Contexts.size() - 1; 20860b57cec5SDimitry Andric CurrentToken->BindingStrength = Contexts.back().BindingStrength; 20870b57cec5SDimitry Andric modifyContext(*CurrentToken); 20880b57cec5SDimitry Andric determineTokenType(*CurrentToken); 20890b57cec5SDimitry Andric CurrentToken = CurrentToken->Next; 20900b57cec5SDimitry Andric 209104eeddc0SDimitry Andric resetTokenMetadata(); 20920b57cec5SDimitry Andric } 20930b57cec5SDimitry Andric 20940b57cec5SDimitry Andric /// A struct to hold information valid in a specific context, e.g. 20950b57cec5SDimitry Andric /// a pair of parenthesis. 20960b57cec5SDimitry Andric struct Context { 20970b57cec5SDimitry Andric Context(tok::TokenKind ContextKind, unsigned BindingStrength, 20980b57cec5SDimitry Andric bool IsExpression) 20990b57cec5SDimitry Andric : ContextKind(ContextKind), BindingStrength(BindingStrength), 21000b57cec5SDimitry Andric IsExpression(IsExpression) {} 21010b57cec5SDimitry Andric 21020b57cec5SDimitry Andric tok::TokenKind ContextKind; 21030b57cec5SDimitry Andric unsigned BindingStrength; 21040b57cec5SDimitry Andric bool IsExpression; 21050b57cec5SDimitry Andric unsigned LongestObjCSelectorName = 0; 21060b57cec5SDimitry Andric bool ColonIsForRangeExpr = false; 21070b57cec5SDimitry Andric bool ColonIsDictLiteral = false; 21080b57cec5SDimitry Andric bool ColonIsObjCMethodExpr = false; 21090b57cec5SDimitry Andric FormatToken *FirstObjCSelectorName = nullptr; 21100b57cec5SDimitry Andric FormatToken *FirstStartOfName = nullptr; 21110b57cec5SDimitry Andric bool CanBeExpression = true; 21120b57cec5SDimitry Andric bool CaretFound = false; 21130b57cec5SDimitry Andric bool InCpp11AttributeSpecifier = false; 21140b57cec5SDimitry Andric bool InCSharpAttributeSpecifier = false; 211506c3fb27SDimitry Andric bool VerilogAssignmentFound = false; 21165f757f3fSDimitry Andric // Whether the braces may mean concatenation instead of structure or array 21175f757f3fSDimitry Andric // literal. 21185f757f3fSDimitry Andric bool VerilogMayBeConcatenation = false; 21190fca6ea1SDimitry Andric bool IsTableGenDAGArg = false; 21200fca6ea1SDimitry Andric bool IsTableGenBangOpe = false; 21210fca6ea1SDimitry Andric bool IsTableGenCondOpe = false; 212281ad6265SDimitry Andric enum { 212381ad6265SDimitry Andric Unknown, 212481ad6265SDimitry Andric // Like the part after `:` in a constructor. 212581ad6265SDimitry Andric // Context(...) : IsExpression(IsExpression) 212681ad6265SDimitry Andric CtorInitializer, 212781ad6265SDimitry Andric // Like in the parentheses in a foreach. 212881ad6265SDimitry Andric ForEachMacro, 212981ad6265SDimitry Andric // Like the inheritance list in a class declaration. 213081ad6265SDimitry Andric // class Input : public IO 213181ad6265SDimitry Andric InheritanceList, 213281ad6265SDimitry Andric // Like in the braced list. 213381ad6265SDimitry Andric // int x[] = {}; 213481ad6265SDimitry Andric StructArrayInitializer, 213581ad6265SDimitry Andric // Like in `static_cast<int>`. 213681ad6265SDimitry Andric TemplateArgument, 2137bdd1243dSDimitry Andric // C11 _Generic selection. 2138bdd1243dSDimitry Andric C11GenericSelection, 213906c3fb27SDimitry Andric // Like in the outer parentheses in `ffnand ff1(.q());`. 214006c3fb27SDimitry Andric VerilogInstancePortList, 214181ad6265SDimitry Andric } ContextType = Unknown; 21420b57cec5SDimitry Andric }; 21430b57cec5SDimitry Andric 21440b57cec5SDimitry Andric /// Puts a new \c Context onto the stack \c Contexts for the lifetime 21450b57cec5SDimitry Andric /// of each instance. 21460b57cec5SDimitry Andric struct ScopedContextCreator { 21470b57cec5SDimitry Andric AnnotatingParser &P; 21480b57cec5SDimitry Andric 21490b57cec5SDimitry Andric ScopedContextCreator(AnnotatingParser &P, tok::TokenKind ContextKind, 21500b57cec5SDimitry Andric unsigned Increase) 21510b57cec5SDimitry Andric : P(P) { 21520b57cec5SDimitry Andric P.Contexts.push_back(Context(ContextKind, 21530b57cec5SDimitry Andric P.Contexts.back().BindingStrength + Increase, 21540b57cec5SDimitry Andric P.Contexts.back().IsExpression)); 21550b57cec5SDimitry Andric } 21560b57cec5SDimitry Andric 2157fe6060f1SDimitry Andric ~ScopedContextCreator() { 2158fe6060f1SDimitry Andric if (P.Style.AlignArrayOfStructures != FormatStyle::AIAS_None) { 215981ad6265SDimitry Andric if (P.Contexts.back().ContextType == Context::StructArrayInitializer) { 2160fe6060f1SDimitry Andric P.Contexts.pop_back(); 216181ad6265SDimitry Andric P.Contexts.back().ContextType = Context::StructArrayInitializer; 2162fe6060f1SDimitry Andric return; 2163fe6060f1SDimitry Andric } 2164fe6060f1SDimitry Andric } 2165fe6060f1SDimitry Andric P.Contexts.pop_back(); 2166fe6060f1SDimitry Andric } 21670b57cec5SDimitry Andric }; 21680b57cec5SDimitry Andric 21690b57cec5SDimitry Andric void modifyContext(const FormatToken &Current) { 217081ad6265SDimitry Andric auto AssignmentStartsExpression = [&]() { 217181ad6265SDimitry Andric if (Current.getPrecedence() != prec::Assignment) 217281ad6265SDimitry Andric return false; 217381ad6265SDimitry Andric 217481ad6265SDimitry Andric if (Line.First->isOneOf(tok::kw_using, tok::kw_return)) 217581ad6265SDimitry Andric return false; 217681ad6265SDimitry Andric if (Line.First->is(tok::kw_template)) { 217781ad6265SDimitry Andric assert(Current.Previous); 217881ad6265SDimitry Andric if (Current.Previous->is(tok::kw_operator)) { 217981ad6265SDimitry Andric // `template ... operator=` cannot be an expression. 218081ad6265SDimitry Andric return false; 218181ad6265SDimitry Andric } 218281ad6265SDimitry Andric 218381ad6265SDimitry Andric // `template` keyword can start a variable template. 218481ad6265SDimitry Andric const FormatToken *Tok = Line.First->getNextNonComment(); 218581ad6265SDimitry Andric assert(Tok); // Current token is on the same line. 218681ad6265SDimitry Andric if (Tok->isNot(TT_TemplateOpener)) { 218781ad6265SDimitry Andric // Explicit template instantiations do not have `<>`. 218881ad6265SDimitry Andric return false; 218981ad6265SDimitry Andric } 219081ad6265SDimitry Andric 219106c3fb27SDimitry Andric // This is the default value of a template parameter, determine if it's 219206c3fb27SDimitry Andric // type or non-type. 219306c3fb27SDimitry Andric if (Contexts.back().ContextKind == tok::less) { 219406c3fb27SDimitry Andric assert(Current.Previous->Previous); 219506c3fb27SDimitry Andric return !Current.Previous->Previous->isOneOf(tok::kw_typename, 219606c3fb27SDimitry Andric tok::kw_class); 219706c3fb27SDimitry Andric } 219806c3fb27SDimitry Andric 219981ad6265SDimitry Andric Tok = Tok->MatchingParen; 220081ad6265SDimitry Andric if (!Tok) 220181ad6265SDimitry Andric return false; 220281ad6265SDimitry Andric Tok = Tok->getNextNonComment(); 220381ad6265SDimitry Andric if (!Tok) 220481ad6265SDimitry Andric return false; 220581ad6265SDimitry Andric 2206bdd1243dSDimitry Andric if (Tok->isOneOf(tok::kw_class, tok::kw_enum, tok::kw_struct, 2207bdd1243dSDimitry Andric tok::kw_using)) { 220881ad6265SDimitry Andric return false; 220981ad6265SDimitry Andric } 221081ad6265SDimitry Andric 221181ad6265SDimitry Andric return true; 221281ad6265SDimitry Andric } 221381ad6265SDimitry Andric 22140b57cec5SDimitry Andric // Type aliases use `type X = ...;` in TypeScript and can be exported 22150b57cec5SDimitry Andric // using `export type ...`. 221681ad6265SDimitry Andric if (Style.isJavaScript() && 22170b57cec5SDimitry Andric (Line.startsWith(Keywords.kw_type, tok::identifier) || 22180b57cec5SDimitry Andric Line.startsWith(tok::kw_export, Keywords.kw_type, 221981ad6265SDimitry Andric tok::identifier))) { 222081ad6265SDimitry Andric return false; 222181ad6265SDimitry Andric } 222281ad6265SDimitry Andric 222381ad6265SDimitry Andric return !Current.Previous || Current.Previous->isNot(tok::kw_operator); 222481ad6265SDimitry Andric }; 222581ad6265SDimitry Andric 222681ad6265SDimitry Andric if (AssignmentStartsExpression()) { 22270b57cec5SDimitry Andric Contexts.back().IsExpression = true; 22280b57cec5SDimitry Andric if (!Line.startsWith(TT_UnaryOperator)) { 22290b57cec5SDimitry Andric for (FormatToken *Previous = Current.Previous; 22300b57cec5SDimitry Andric Previous && Previous->Previous && 22310b57cec5SDimitry Andric !Previous->Previous->isOneOf(tok::comma, tok::semi); 22320b57cec5SDimitry Andric Previous = Previous->Previous) { 223306c3fb27SDimitry Andric if (Previous->isOneOf(tok::r_square, tok::r_paren, tok::greater)) { 22340b57cec5SDimitry Andric Previous = Previous->MatchingParen; 22350b57cec5SDimitry Andric if (!Previous) 22360b57cec5SDimitry Andric break; 22370b57cec5SDimitry Andric } 22380b57cec5SDimitry Andric if (Previous->opensScope()) 22390b57cec5SDimitry Andric break; 22400b57cec5SDimitry Andric if (Previous->isOneOf(TT_BinaryOperator, TT_UnaryOperator) && 22415f757f3fSDimitry Andric Previous->isPointerOrReference() && Previous->Previous && 22425f757f3fSDimitry Andric Previous->Previous->isNot(tok::equal)) { 22435ffd83dbSDimitry Andric Previous->setType(TT_PointerOrReference); 22440b57cec5SDimitry Andric } 22450b57cec5SDimitry Andric } 224681ad6265SDimitry Andric } 22470b57cec5SDimitry Andric } else if (Current.is(tok::lessless) && 22485f757f3fSDimitry Andric (!Current.Previous || 22495f757f3fSDimitry Andric Current.Previous->isNot(tok::kw_operator))) { 22500b57cec5SDimitry Andric Contexts.back().IsExpression = true; 22510b57cec5SDimitry Andric } else if (Current.isOneOf(tok::kw_return, tok::kw_throw)) { 22520b57cec5SDimitry Andric Contexts.back().IsExpression = true; 22530b57cec5SDimitry Andric } else if (Current.is(TT_TrailingReturnArrow)) { 22540b57cec5SDimitry Andric Contexts.back().IsExpression = false; 22556c4b055cSDimitry Andric } else if (Current.isOneOf(TT_LambdaArrow, Keywords.kw_assert)) { 22560b57cec5SDimitry Andric Contexts.back().IsExpression = Style.Language == FormatStyle::LK_Java; 22570b57cec5SDimitry Andric } else if (Current.Previous && 22580b57cec5SDimitry Andric Current.Previous->is(TT_CtorInitializerColon)) { 22590b57cec5SDimitry Andric Contexts.back().IsExpression = true; 226081ad6265SDimitry Andric Contexts.back().ContextType = Context::CtorInitializer; 22610b57cec5SDimitry Andric } else if (Current.Previous && Current.Previous->is(TT_InheritanceColon)) { 226281ad6265SDimitry Andric Contexts.back().ContextType = Context::InheritanceList; 22630b57cec5SDimitry Andric } else if (Current.isOneOf(tok::r_paren, tok::greater, tok::comma)) { 22640b57cec5SDimitry Andric for (FormatToken *Previous = Current.Previous; 22650b57cec5SDimitry Andric Previous && Previous->isOneOf(tok::star, tok::amp); 226681ad6265SDimitry Andric Previous = Previous->Previous) { 22675ffd83dbSDimitry Andric Previous->setType(TT_PointerOrReference); 226881ad6265SDimitry Andric } 226981ad6265SDimitry Andric if (Line.MustBeDeclaration && 227081ad6265SDimitry Andric Contexts.front().ContextType != Context::CtorInitializer) { 22710b57cec5SDimitry Andric Contexts.back().IsExpression = false; 227281ad6265SDimitry Andric } 22730b57cec5SDimitry Andric } else if (Current.is(tok::kw_new)) { 22740b57cec5SDimitry Andric Contexts.back().CanBeExpression = false; 2275480093f4SDimitry Andric } else if (Current.is(tok::semi) || 2276480093f4SDimitry Andric (Current.is(tok::exclaim) && Current.Previous && 22775f757f3fSDimitry Andric Current.Previous->isNot(tok::kw_operator))) { 22780b57cec5SDimitry Andric // This should be the condition or increment in a for-loop. 2279480093f4SDimitry Andric // But not operator !() (can't use TT_OverloadedOperator here as its not 2280480093f4SDimitry Andric // been annotated yet). 22810b57cec5SDimitry Andric Contexts.back().IsExpression = true; 22820b57cec5SDimitry Andric } 22830b57cec5SDimitry Andric } 22840b57cec5SDimitry Andric 2285480093f4SDimitry Andric static FormatToken *untilMatchingParen(FormatToken *Current) { 2286480093f4SDimitry Andric // Used when `MatchingParen` is not yet established. 2287480093f4SDimitry Andric int ParenLevel = 0; 2288480093f4SDimitry Andric while (Current) { 2289480093f4SDimitry Andric if (Current->is(tok::l_paren)) 229004eeddc0SDimitry Andric ++ParenLevel; 2291480093f4SDimitry Andric if (Current->is(tok::r_paren)) 229204eeddc0SDimitry Andric --ParenLevel; 2293480093f4SDimitry Andric if (ParenLevel < 1) 2294480093f4SDimitry Andric break; 2295480093f4SDimitry Andric Current = Current->Next; 2296480093f4SDimitry Andric } 2297480093f4SDimitry Andric return Current; 2298480093f4SDimitry Andric } 2299480093f4SDimitry Andric 2300480093f4SDimitry Andric static bool isDeductionGuide(FormatToken &Current) { 2301480093f4SDimitry Andric // Look for a deduction guide template<T> A(...) -> A<...>; 2302480093f4SDimitry Andric if (Current.Previous && Current.Previous->is(tok::r_paren) && 2303480093f4SDimitry Andric Current.startsSequence(tok::arrow, tok::identifier, tok::less)) { 2304480093f4SDimitry Andric // Find the TemplateCloser. 2305480093f4SDimitry Andric FormatToken *TemplateCloser = Current.Next->Next; 2306480093f4SDimitry Andric int NestingLevel = 0; 2307480093f4SDimitry Andric while (TemplateCloser) { 2308480093f4SDimitry Andric // Skip over an expressions in parens A<(3 < 2)>; 2309480093f4SDimitry Andric if (TemplateCloser->is(tok::l_paren)) { 2310480093f4SDimitry Andric // No Matching Paren yet so skip to matching paren 2311480093f4SDimitry Andric TemplateCloser = untilMatchingParen(TemplateCloser); 23124824e7fdSDimitry Andric if (!TemplateCloser) 23134824e7fdSDimitry Andric break; 2314480093f4SDimitry Andric } 2315480093f4SDimitry Andric if (TemplateCloser->is(tok::less)) 231604eeddc0SDimitry Andric ++NestingLevel; 2317480093f4SDimitry Andric if (TemplateCloser->is(tok::greater)) 231804eeddc0SDimitry Andric --NestingLevel; 2319480093f4SDimitry Andric if (NestingLevel < 1) 2320480093f4SDimitry Andric break; 2321480093f4SDimitry Andric TemplateCloser = TemplateCloser->Next; 2322480093f4SDimitry Andric } 2323480093f4SDimitry Andric // Assuming we have found the end of the template ensure its followed 2324480093f4SDimitry Andric // with a semi-colon. 2325480093f4SDimitry Andric if (TemplateCloser && TemplateCloser->Next && 2326480093f4SDimitry Andric TemplateCloser->Next->is(tok::semi) && 2327480093f4SDimitry Andric Current.Previous->MatchingParen) { 2328480093f4SDimitry Andric // Determine if the identifier `A` prior to the A<..>; is the same as 2329480093f4SDimitry Andric // prior to the A(..) 2330480093f4SDimitry Andric FormatToken *LeadingIdentifier = 2331480093f4SDimitry Andric Current.Previous->MatchingParen->Previous; 2332480093f4SDimitry Andric 2333bdd1243dSDimitry Andric return LeadingIdentifier && 233481ad6265SDimitry Andric LeadingIdentifier->TokenText == Current.Next->TokenText; 2335480093f4SDimitry Andric } 2336480093f4SDimitry Andric } 2337480093f4SDimitry Andric return false; 2338480093f4SDimitry Andric } 2339480093f4SDimitry Andric 23400b57cec5SDimitry Andric void determineTokenType(FormatToken &Current) { 23415f757f3fSDimitry Andric if (Current.isNot(TT_Unknown)) { 23420b57cec5SDimitry Andric // The token type is already known. 23430b57cec5SDimitry Andric return; 234481ad6265SDimitry Andric } 23450b57cec5SDimitry Andric 23460eae32dcSDimitry Andric if ((Style.isJavaScript() || Style.isCSharp()) && 2347fe6060f1SDimitry Andric Current.is(tok::exclaim)) { 2348fe6060f1SDimitry Andric if (Current.Previous) { 2349fe6060f1SDimitry Andric bool IsIdentifier = 23500eae32dcSDimitry Andric Style.isJavaScript() 23510fca6ea1SDimitry Andric ? Keywords.isJavaScriptIdentifier( 2352fe6060f1SDimitry Andric *Current.Previous, /* AcceptIdentifierName= */ true) 2353fe6060f1SDimitry Andric : Current.Previous->is(tok::identifier); 2354fe6060f1SDimitry Andric if (IsIdentifier || 23555ffd83dbSDimitry Andric Current.Previous->isOneOf( 235681ad6265SDimitry Andric tok::kw_default, tok::kw_namespace, tok::r_paren, tok::r_square, 235781ad6265SDimitry Andric tok::r_brace, tok::kw_false, tok::kw_true, Keywords.kw_type, 235881ad6265SDimitry Andric Keywords.kw_get, Keywords.kw_init, Keywords.kw_set) || 2359fe6060f1SDimitry Andric Current.Previous->Tok.isLiteral()) { 2360fe6060f1SDimitry Andric Current.setType(TT_NonNullAssertion); 23610b57cec5SDimitry Andric return; 23620b57cec5SDimitry Andric } 2363fe6060f1SDimitry Andric } 23640b57cec5SDimitry Andric if (Current.Next && 23650b57cec5SDimitry Andric Current.Next->isOneOf(TT_BinaryOperator, Keywords.kw_as)) { 2366fe6060f1SDimitry Andric Current.setType(TT_NonNullAssertion); 23670b57cec5SDimitry Andric return; 23680b57cec5SDimitry Andric } 23690b57cec5SDimitry Andric } 23700b57cec5SDimitry Andric 23710b57cec5SDimitry Andric // Line.MightBeFunctionDecl can only be true after the parentheses of a 23720b57cec5SDimitry Andric // function declaration have been found. In this case, 'Current' is a 23730b57cec5SDimitry Andric // trailing token of this declaration and thus cannot be a name. 23740fca6ea1SDimitry Andric if ((Style.isJavaScript() || Style.Language == FormatStyle::LK_Java) && 23750fca6ea1SDimitry Andric Current.is(Keywords.kw_instanceof)) { 23765ffd83dbSDimitry Andric Current.setType(TT_BinaryOperator); 23770b57cec5SDimitry Andric } else if (isStartOfName(Current) && 23780b57cec5SDimitry Andric (!Line.MightBeFunctionDecl || Current.NestingLevel != 0)) { 23790b57cec5SDimitry Andric Contexts.back().FirstStartOfName = &Current; 23805ffd83dbSDimitry Andric Current.setType(TT_StartOfName); 23810b57cec5SDimitry Andric } else if (Current.is(tok::semi)) { 23820b57cec5SDimitry Andric // Reset FirstStartOfName after finding a semicolon so that a for loop 23830b57cec5SDimitry Andric // with multiple increment statements is not confused with a for loop 23840b57cec5SDimitry Andric // having multiple variable declarations. 23850b57cec5SDimitry Andric Contexts.back().FirstStartOfName = nullptr; 23860b57cec5SDimitry Andric } else if (Current.isOneOf(tok::kw_auto, tok::kw___auto_type)) { 23870b57cec5SDimitry Andric AutoFound = true; 23880b57cec5SDimitry Andric } else if (Current.is(tok::arrow) && 23890b57cec5SDimitry Andric Style.Language == FormatStyle::LK_Java) { 23906c4b055cSDimitry Andric Current.setType(TT_LambdaArrow); 23915f757f3fSDimitry Andric } else if (Current.is(tok::arrow) && Style.isVerilog()) { 23925f757f3fSDimitry Andric // The implication operator. 23935f757f3fSDimitry Andric Current.setType(TT_BinaryOperator); 239406c3fb27SDimitry Andric } else if (Current.is(tok::arrow) && AutoFound && 23955f757f3fSDimitry Andric Line.MightBeFunctionDecl && Current.NestingLevel == 0 && 23960eae32dcSDimitry Andric !Current.Previous->isOneOf(tok::kw_operator, tok::identifier)) { 2397a7dea167SDimitry Andric // not auto operator->() -> xxx; 23985ffd83dbSDimitry Andric Current.setType(TT_TrailingReturnArrow); 2399e8d8bef9SDimitry Andric } else if (Current.is(tok::arrow) && Current.Previous && 2400e8d8bef9SDimitry Andric Current.Previous->is(tok::r_brace)) { 2401349cc55cSDimitry Andric // Concept implicit conversion constraint needs to be treated like 2402e8d8bef9SDimitry Andric // a trailing return type ... } -> <type>. 2403e8d8bef9SDimitry Andric Current.setType(TT_TrailingReturnArrow); 2404480093f4SDimitry Andric } else if (isDeductionGuide(Current)) { 2405480093f4SDimitry Andric // Deduction guides trailing arrow " A(...) -> A<T>;". 24065ffd83dbSDimitry Andric Current.setType(TT_TrailingReturnArrow); 24075f757f3fSDimitry Andric } else if (Current.isPointerOrReference()) { 24085ffd83dbSDimitry Andric Current.setType(determineStarAmpUsage( 24095ffd83dbSDimitry Andric Current, 24105ffd83dbSDimitry Andric Contexts.back().CanBeExpression && Contexts.back().IsExpression, 241181ad6265SDimitry Andric Contexts.back().ContextType == Context::TemplateArgument)); 2412bdd1243dSDimitry Andric } else if (Current.isOneOf(tok::minus, tok::plus, tok::caret) || 2413bdd1243dSDimitry Andric (Style.isVerilog() && Current.is(tok::pipe))) { 24145ffd83dbSDimitry Andric Current.setType(determinePlusMinusCaretUsage(Current)); 24150b57cec5SDimitry Andric if (Current.is(TT_UnaryOperator) && Current.is(tok::caret)) 24160b57cec5SDimitry Andric Contexts.back().CaretFound = true; 24170b57cec5SDimitry Andric } else if (Current.isOneOf(tok::minusminus, tok::plusplus)) { 24185ffd83dbSDimitry Andric Current.setType(determineIncrementUsage(Current)); 24190b57cec5SDimitry Andric } else if (Current.isOneOf(tok::exclaim, tok::tilde)) { 24205ffd83dbSDimitry Andric Current.setType(TT_UnaryOperator); 24210b57cec5SDimitry Andric } else if (Current.is(tok::question)) { 24220eae32dcSDimitry Andric if (Style.isJavaScript() && Line.MustBeDeclaration && 24230eae32dcSDimitry Andric !Contexts.back().IsExpression) { 24240b57cec5SDimitry Andric // In JavaScript, `interface X { foo?(): bar; }` is an optional method 24250b57cec5SDimitry Andric // on the interface, not a ternary expression. 24265ffd83dbSDimitry Andric Current.setType(TT_JsTypeOptionalQuestion); 24270fca6ea1SDimitry Andric } else if (Style.isTableGen()) { 24280fca6ea1SDimitry Andric // In TableGen, '?' is just an identifier like token. 24290fca6ea1SDimitry Andric Current.setType(TT_Unknown); 24300b57cec5SDimitry Andric } else { 24315ffd83dbSDimitry Andric Current.setType(TT_ConditionalExpr); 24320b57cec5SDimitry Andric } 24330b57cec5SDimitry Andric } else if (Current.isBinaryOperator() && 24340b57cec5SDimitry Andric (!Current.Previous || Current.Previous->isNot(tok::l_square)) && 24355f757f3fSDimitry Andric (Current.isNot(tok::greater) && 24360b57cec5SDimitry Andric Style.Language != FormatStyle::LK_TextProto)) { 243706c3fb27SDimitry Andric if (Style.isVerilog()) { 243806c3fb27SDimitry Andric if (Current.is(tok::lessequal) && Contexts.size() == 1 && 243906c3fb27SDimitry Andric !Contexts.back().VerilogAssignmentFound) { 244006c3fb27SDimitry Andric // In Verilog `<=` is assignment if in its own statement. It is a 244106c3fb27SDimitry Andric // statement instead of an expression, that is it can not be chained. 244206c3fb27SDimitry Andric Current.ForcedPrecedence = prec::Assignment; 244306c3fb27SDimitry Andric Current.setFinalizedType(TT_BinaryOperator); 244406c3fb27SDimitry Andric } 244506c3fb27SDimitry Andric if (Current.getPrecedence() == prec::Assignment) 244606c3fb27SDimitry Andric Contexts.back().VerilogAssignmentFound = true; 244706c3fb27SDimitry Andric } 24485ffd83dbSDimitry Andric Current.setType(TT_BinaryOperator); 24490b57cec5SDimitry Andric } else if (Current.is(tok::comment)) { 24505f757f3fSDimitry Andric if (Current.TokenText.starts_with("/*")) { 24515f757f3fSDimitry Andric if (Current.TokenText.ends_with("*/")) { 24525ffd83dbSDimitry Andric Current.setType(TT_BlockComment); 245381ad6265SDimitry Andric } else { 24540b57cec5SDimitry Andric // The lexer has for some reason determined a comment here. But we 24550b57cec5SDimitry Andric // cannot really handle it, if it isn't properly terminated. 24560b57cec5SDimitry Andric Current.Tok.setKind(tok::unknown); 245781ad6265SDimitry Andric } 24580b57cec5SDimitry Andric } else { 24595ffd83dbSDimitry Andric Current.setType(TT_LineComment); 24600b57cec5SDimitry Andric } 24615f757f3fSDimitry Andric } else if (Current.is(tok::string_literal)) { 24625f757f3fSDimitry Andric if (Style.isVerilog() && Contexts.back().VerilogMayBeConcatenation && 24635f757f3fSDimitry Andric Current.getPreviousNonComment() && 24645f757f3fSDimitry Andric Current.getPreviousNonComment()->isOneOf(tok::comma, tok::l_brace) && 24655f757f3fSDimitry Andric Current.getNextNonComment() && 24665f757f3fSDimitry Andric Current.getNextNonComment()->isOneOf(tok::comma, tok::r_brace)) { 24675f757f3fSDimitry Andric Current.setType(TT_StringInConcatenation); 24685f757f3fSDimitry Andric } 246981ad6265SDimitry Andric } else if (Current.is(tok::l_paren)) { 247081ad6265SDimitry Andric if (lParenStartsCppCast(Current)) 247181ad6265SDimitry Andric Current.setType(TT_CppCastLParen); 24720b57cec5SDimitry Andric } else if (Current.is(tok::r_paren)) { 24730b57cec5SDimitry Andric if (rParenEndsCast(Current)) 24745ffd83dbSDimitry Andric Current.setType(TT_CastRParen); 24750b57cec5SDimitry Andric if (Current.MatchingParen && Current.Next && 24760b57cec5SDimitry Andric !Current.Next->isBinaryOperator() && 24770fca6ea1SDimitry Andric !Current.Next->isOneOf( 24780fca6ea1SDimitry Andric tok::semi, tok::colon, tok::l_brace, tok::l_paren, tok::comma, 24790fca6ea1SDimitry Andric tok::period, tok::arrow, tok::coloncolon, tok::kw_noexcept)) { 24805f757f3fSDimitry Andric if (FormatToken *AfterParen = Current.MatchingParen->Next; 24815f757f3fSDimitry Andric AfterParen && AfterParen->isNot(tok::caret)) { 24825f757f3fSDimitry Andric // Make sure this isn't the return type of an Obj-C block declaration. 24835f757f3fSDimitry Andric if (FormatToken *BeforeParen = Current.MatchingParen->Previous; 24845f757f3fSDimitry Andric BeforeParen && BeforeParen->is(tok::identifier) && 24855f757f3fSDimitry Andric BeforeParen->isNot(TT_TypenameMacro) && 24860b57cec5SDimitry Andric BeforeParen->TokenText == BeforeParen->TokenText.upper() && 24870b57cec5SDimitry Andric (!BeforeParen->Previous || 24885f757f3fSDimitry Andric BeforeParen->Previous->ClosesTemplateDeclaration || 24895f757f3fSDimitry Andric BeforeParen->Previous->ClosesRequiresClause)) { 24905ffd83dbSDimitry Andric Current.setType(TT_FunctionAnnotationRParen); 24910b57cec5SDimitry Andric } 24920b57cec5SDimitry Andric } 249381ad6265SDimitry Andric } 24940eae32dcSDimitry Andric } else if (Current.is(tok::at) && Current.Next && !Style.isJavaScript() && 24950b57cec5SDimitry Andric Style.Language != FormatStyle::LK_Java) { 24960b57cec5SDimitry Andric // In Java & JavaScript, "@..." is a decorator or annotation. In ObjC, it 24970b57cec5SDimitry Andric // marks declarations and properties that need special formatting. 24980b57cec5SDimitry Andric switch (Current.Next->Tok.getObjCKeywordID()) { 24990b57cec5SDimitry Andric case tok::objc_interface: 25000b57cec5SDimitry Andric case tok::objc_implementation: 25010b57cec5SDimitry Andric case tok::objc_protocol: 25025ffd83dbSDimitry Andric Current.setType(TT_ObjCDecl); 25030b57cec5SDimitry Andric break; 25040b57cec5SDimitry Andric case tok::objc_property: 25055ffd83dbSDimitry Andric Current.setType(TT_ObjCProperty); 25060b57cec5SDimitry Andric break; 25070b57cec5SDimitry Andric default: 25080b57cec5SDimitry Andric break; 25090b57cec5SDimitry Andric } 25100b57cec5SDimitry Andric } else if (Current.is(tok::period)) { 25110b57cec5SDimitry Andric FormatToken *PreviousNoComment = Current.getPreviousNonComment(); 25120b57cec5SDimitry Andric if (PreviousNoComment && 251381ad6265SDimitry Andric PreviousNoComment->isOneOf(tok::comma, tok::l_brace)) { 25145ffd83dbSDimitry Andric Current.setType(TT_DesignatedInitializerPeriod); 251581ad6265SDimitry Andric } else if (Style.Language == FormatStyle::LK_Java && Current.Previous && 25160b57cec5SDimitry Andric Current.Previous->isOneOf(TT_JavaAnnotation, 25170b57cec5SDimitry Andric TT_LeadingJavaAnnotation)) { 25185ffd83dbSDimitry Andric Current.setType(Current.Previous->getType()); 25190b57cec5SDimitry Andric } 25200b57cec5SDimitry Andric } else if (canBeObjCSelectorComponent(Current) && 25210b57cec5SDimitry Andric // FIXME(bug 36976): ObjC return types shouldn't use 25220b57cec5SDimitry Andric // TT_CastRParen. 25230b57cec5SDimitry Andric Current.Previous && Current.Previous->is(TT_CastRParen) && 25240b57cec5SDimitry Andric Current.Previous->MatchingParen && 25250b57cec5SDimitry Andric Current.Previous->MatchingParen->Previous && 25260b57cec5SDimitry Andric Current.Previous->MatchingParen->Previous->is( 25270b57cec5SDimitry Andric TT_ObjCMethodSpecifier)) { 25280b57cec5SDimitry Andric // This is the first part of an Objective-C selector name. (If there's no 25290b57cec5SDimitry Andric // colon after this, this is the only place which annotates the identifier 25300b57cec5SDimitry Andric // as a selector.) 25315ffd83dbSDimitry Andric Current.setType(TT_SelectorName); 2532e8d8bef9SDimitry Andric } else if (Current.isOneOf(tok::identifier, tok::kw_const, tok::kw_noexcept, 2533e8d8bef9SDimitry Andric tok::kw_requires) && 25340b57cec5SDimitry Andric Current.Previous && 2535bdd1243dSDimitry Andric !Current.Previous->isOneOf(tok::equal, tok::at, 2536bdd1243dSDimitry Andric TT_CtorInitializerComma, 2537bdd1243dSDimitry Andric TT_CtorInitializerColon) && 25380b57cec5SDimitry Andric Line.MightBeFunctionDecl && Contexts.size() == 1) { 25390b57cec5SDimitry Andric // Line.MightBeFunctionDecl can only be true after the parentheses of a 25400b57cec5SDimitry Andric // function declaration have been found. 25415ffd83dbSDimitry Andric Current.setType(TT_TrailingAnnotation); 25420b57cec5SDimitry Andric } else if ((Style.Language == FormatStyle::LK_Java || 25430eae32dcSDimitry Andric Style.isJavaScript()) && 25440b57cec5SDimitry Andric Current.Previous) { 25450b57cec5SDimitry Andric if (Current.Previous->is(tok::at) && 25460b57cec5SDimitry Andric Current.isNot(Keywords.kw_interface)) { 25470b57cec5SDimitry Andric const FormatToken &AtToken = *Current.Previous; 25480b57cec5SDimitry Andric const FormatToken *Previous = AtToken.getPreviousNonComment(); 25490b57cec5SDimitry Andric if (!Previous || Previous->is(TT_LeadingJavaAnnotation)) 25505ffd83dbSDimitry Andric Current.setType(TT_LeadingJavaAnnotation); 25510b57cec5SDimitry Andric else 25525ffd83dbSDimitry Andric Current.setType(TT_JavaAnnotation); 25530b57cec5SDimitry Andric } else if (Current.Previous->is(tok::period) && 25540b57cec5SDimitry Andric Current.Previous->isOneOf(TT_JavaAnnotation, 25550b57cec5SDimitry Andric TT_LeadingJavaAnnotation)) { 25565ffd83dbSDimitry Andric Current.setType(Current.Previous->getType()); 25570b57cec5SDimitry Andric } 25580b57cec5SDimitry Andric } 25590b57cec5SDimitry Andric } 25600b57cec5SDimitry Andric 25610b57cec5SDimitry Andric /// Take a guess at whether \p Tok starts a name of a function or 25620b57cec5SDimitry Andric /// variable declaration. 25630b57cec5SDimitry Andric /// 25640b57cec5SDimitry Andric /// This is a heuristic based on whether \p Tok is an identifier following 25650b57cec5SDimitry Andric /// something that is likely a type. 25660b57cec5SDimitry Andric bool isStartOfName(const FormatToken &Tok) { 256706c3fb27SDimitry Andric // Handled in ExpressionParser for Verilog. 256806c3fb27SDimitry Andric if (Style.isVerilog()) 256906c3fb27SDimitry Andric return false; 257006c3fb27SDimitry Andric 25710b57cec5SDimitry Andric if (Tok.isNot(tok::identifier) || !Tok.Previous) 25720b57cec5SDimitry Andric return false; 25730b57cec5SDimitry Andric 25745f757f3fSDimitry Andric if (const auto *NextNonComment = Tok.getNextNonComment(); 25755f757f3fSDimitry Andric (!NextNonComment && !Line.InMacroBody) || 25765f757f3fSDimitry Andric (NextNonComment && 25775f757f3fSDimitry Andric (NextNonComment->isPointerOrReference() || 25787a6dacacSDimitry Andric NextNonComment->is(tok::string_literal) || 25797a6dacacSDimitry Andric (Line.InPragmaDirective && NextNonComment->is(tok::identifier))))) { 25805f757f3fSDimitry Andric return false; 25815f757f3fSDimitry Andric } 25825f757f3fSDimitry Andric 25830b57cec5SDimitry Andric if (Tok.Previous->isOneOf(TT_LeadingJavaAnnotation, Keywords.kw_instanceof, 258481ad6265SDimitry Andric Keywords.kw_as)) { 25850b57cec5SDimitry Andric return false; 258681ad6265SDimitry Andric } 25870eae32dcSDimitry Andric if (Style.isJavaScript() && Tok.Previous->is(Keywords.kw_in)) 25880b57cec5SDimitry Andric return false; 25890b57cec5SDimitry Andric 25900b57cec5SDimitry Andric // Skip "const" as it does not have an influence on whether this is a name. 25910b57cec5SDimitry Andric FormatToken *PreviousNotConst = Tok.getPreviousNonComment(); 25920eae32dcSDimitry Andric 25930eae32dcSDimitry Andric // For javascript const can be like "let" or "var" 25940eae32dcSDimitry Andric if (!Style.isJavaScript()) 25950b57cec5SDimitry Andric while (PreviousNotConst && PreviousNotConst->is(tok::kw_const)) 25960b57cec5SDimitry Andric PreviousNotConst = PreviousNotConst->getPreviousNonComment(); 25970b57cec5SDimitry Andric 25980b57cec5SDimitry Andric if (!PreviousNotConst) 25990b57cec5SDimitry Andric return false; 26000b57cec5SDimitry Andric 260181ad6265SDimitry Andric if (PreviousNotConst->ClosesRequiresClause) 260281ad6265SDimitry Andric return false; 260381ad6265SDimitry Andric 26047a6dacacSDimitry Andric if (Style.isTableGen()) { 26057a6dacacSDimitry Andric // keywords such as let and def* defines names. 26067a6dacacSDimitry Andric if (Keywords.isTableGenDefinition(*PreviousNotConst)) 26077a6dacacSDimitry Andric return true; 26080fca6ea1SDimitry Andric // Otherwise C++ style declarations is available only inside the brace. 26090fca6ea1SDimitry Andric if (Contexts.back().ContextKind != tok::l_brace) 26100fca6ea1SDimitry Andric return false; 26117a6dacacSDimitry Andric } 26127a6dacacSDimitry Andric 26130b57cec5SDimitry Andric bool IsPPKeyword = PreviousNotConst->is(tok::identifier) && 26140b57cec5SDimitry Andric PreviousNotConst->Previous && 26150b57cec5SDimitry Andric PreviousNotConst->Previous->is(tok::hash); 26160b57cec5SDimitry Andric 261781ad6265SDimitry Andric if (PreviousNotConst->is(TT_TemplateCloser)) { 26180b57cec5SDimitry Andric return PreviousNotConst && PreviousNotConst->MatchingParen && 26190b57cec5SDimitry Andric PreviousNotConst->MatchingParen->Previous && 26200b57cec5SDimitry Andric PreviousNotConst->MatchingParen->Previous->isNot(tok::period) && 26210b57cec5SDimitry Andric PreviousNotConst->MatchingParen->Previous->isNot(tok::kw_template); 262281ad6265SDimitry Andric } 26230b57cec5SDimitry Andric 26245f757f3fSDimitry Andric if ((PreviousNotConst->is(tok::r_paren) && 26255f757f3fSDimitry Andric PreviousNotConst->is(TT_TypeDeclarationParen)) || 26265f757f3fSDimitry Andric PreviousNotConst->is(TT_AttributeRParen)) { 26270b57cec5SDimitry Andric return true; 262881ad6265SDimitry Andric } 26290b57cec5SDimitry Andric 26300eae32dcSDimitry Andric // If is a preprocess keyword like #define. 26310eae32dcSDimitry Andric if (IsPPKeyword) 26320eae32dcSDimitry Andric return false; 26330eae32dcSDimitry Andric 26340eae32dcSDimitry Andric // int a or auto a. 26350fca6ea1SDimitry Andric if (PreviousNotConst->isOneOf(tok::identifier, tok::kw_auto) && 26360fca6ea1SDimitry Andric PreviousNotConst->isNot(TT_StatementAttributeLikeMacro)) { 26370eae32dcSDimitry Andric return true; 26380fca6ea1SDimitry Andric } 26390eae32dcSDimitry Andric 26400eae32dcSDimitry Andric // *a or &a or &&a. 26410eae32dcSDimitry Andric if (PreviousNotConst->is(TT_PointerOrReference)) 26420eae32dcSDimitry Andric return true; 26430eae32dcSDimitry Andric 26440eae32dcSDimitry Andric // MyClass a; 26450fca6ea1SDimitry Andric if (PreviousNotConst->isTypeName(LangOpts)) 26460eae32dcSDimitry Andric return true; 26470eae32dcSDimitry Andric 2648bdd1243dSDimitry Andric // type[] a in Java 2649bdd1243dSDimitry Andric if (Style.Language == FormatStyle::LK_Java && 2650bdd1243dSDimitry Andric PreviousNotConst->is(tok::r_square)) { 2651bdd1243dSDimitry Andric return true; 2652bdd1243dSDimitry Andric } 2653bdd1243dSDimitry Andric 26540eae32dcSDimitry Andric // const a = in JavaScript. 265581ad6265SDimitry Andric return Style.isJavaScript() && PreviousNotConst->is(tok::kw_const); 265681ad6265SDimitry Andric } 265781ad6265SDimitry Andric 265881ad6265SDimitry Andric /// Determine whether '(' is starting a C++ cast. 265981ad6265SDimitry Andric bool lParenStartsCppCast(const FormatToken &Tok) { 266081ad6265SDimitry Andric // C-style casts are only used in C++. 26610fca6ea1SDimitry Andric if (!IsCpp) 266281ad6265SDimitry Andric return false; 266381ad6265SDimitry Andric 266481ad6265SDimitry Andric FormatToken *LeftOfParens = Tok.getPreviousNonComment(); 266581ad6265SDimitry Andric if (LeftOfParens && LeftOfParens->is(TT_TemplateCloser) && 266681ad6265SDimitry Andric LeftOfParens->MatchingParen) { 266781ad6265SDimitry Andric auto *Prev = LeftOfParens->MatchingParen->getPreviousNonComment(); 266881ad6265SDimitry Andric if (Prev && 266981ad6265SDimitry Andric Prev->isOneOf(tok::kw_const_cast, tok::kw_dynamic_cast, 267081ad6265SDimitry Andric tok::kw_reinterpret_cast, tok::kw_static_cast)) { 267181ad6265SDimitry Andric // FIXME: Maybe we should handle identifiers ending with "_cast", 267281ad6265SDimitry Andric // e.g. any_cast? 267381ad6265SDimitry Andric return true; 267481ad6265SDimitry Andric } 267581ad6265SDimitry Andric } 267681ad6265SDimitry Andric return false; 26770b57cec5SDimitry Andric } 26780b57cec5SDimitry Andric 26790b57cec5SDimitry Andric /// Determine whether ')' is ending a cast. 26800b57cec5SDimitry Andric bool rParenEndsCast(const FormatToken &Tok) { 26810fca6ea1SDimitry Andric assert(Tok.is(tok::r_paren)); 26820fca6ea1SDimitry Andric 26830fca6ea1SDimitry Andric if (!Tok.MatchingParen || !Tok.Previous) 26840b57cec5SDimitry Andric return false; 26850fca6ea1SDimitry Andric 26860fca6ea1SDimitry Andric // C-style casts are only used in C++, C# and Java. 26870fca6ea1SDimitry Andric if (!IsCpp && !Style.isCSharp() && Style.Language != FormatStyle::LK_Java) 26880fca6ea1SDimitry Andric return false; 26890fca6ea1SDimitry Andric 26900fca6ea1SDimitry Andric const auto *LParen = Tok.MatchingParen; 26910fca6ea1SDimitry Andric const auto *BeforeRParen = Tok.Previous; 26920fca6ea1SDimitry Andric const auto *AfterRParen = Tok.Next; 26930b57cec5SDimitry Andric 26940b57cec5SDimitry Andric // Empty parens aren't casts and there are no casts at the end of the line. 26950fca6ea1SDimitry Andric if (BeforeRParen == LParen || !AfterRParen) 26960b57cec5SDimitry Andric return false; 26970b57cec5SDimitry Andric 26980fca6ea1SDimitry Andric if (LParen->is(TT_OverloadedOperatorLParen)) 2699bdd1243dSDimitry Andric return false; 2700bdd1243dSDimitry Andric 27010fca6ea1SDimitry Andric auto *LeftOfParens = LParen->getPreviousNonComment(); 27020b57cec5SDimitry Andric if (LeftOfParens) { 270304eeddc0SDimitry Andric // If there is a closing parenthesis left of the current 270404eeddc0SDimitry Andric // parentheses, look past it as these might be chained casts. 270504eeddc0SDimitry Andric if (LeftOfParens->is(tok::r_paren) && 270604eeddc0SDimitry Andric LeftOfParens->isNot(TT_CastRParen)) { 27070b57cec5SDimitry Andric if (!LeftOfParens->MatchingParen || 270881ad6265SDimitry Andric !LeftOfParens->MatchingParen->Previous) { 27090b57cec5SDimitry Andric return false; 271081ad6265SDimitry Andric } 27110b57cec5SDimitry Andric LeftOfParens = LeftOfParens->MatchingParen->Previous; 27120b57cec5SDimitry Andric } 27130b57cec5SDimitry Andric 271481ad6265SDimitry Andric if (LeftOfParens->is(tok::r_square)) { 271581ad6265SDimitry Andric // delete[] (void *)ptr; 271681ad6265SDimitry Andric auto MayBeArrayDelete = [](FormatToken *Tok) -> FormatToken * { 271781ad6265SDimitry Andric if (Tok->isNot(tok::r_square)) 271881ad6265SDimitry Andric return nullptr; 271981ad6265SDimitry Andric 272081ad6265SDimitry Andric Tok = Tok->getPreviousNonComment(); 272181ad6265SDimitry Andric if (!Tok || Tok->isNot(tok::l_square)) 272281ad6265SDimitry Andric return nullptr; 272381ad6265SDimitry Andric 272481ad6265SDimitry Andric Tok = Tok->getPreviousNonComment(); 272581ad6265SDimitry Andric if (!Tok || Tok->isNot(tok::kw_delete)) 272681ad6265SDimitry Andric return nullptr; 272781ad6265SDimitry Andric return Tok; 272881ad6265SDimitry Andric }; 272981ad6265SDimitry Andric if (FormatToken *MaybeDelete = MayBeArrayDelete(LeftOfParens)) 273081ad6265SDimitry Andric LeftOfParens = MaybeDelete; 273181ad6265SDimitry Andric } 273281ad6265SDimitry Andric 273304eeddc0SDimitry Andric // The Condition directly below this one will see the operator arguments 273404eeddc0SDimitry Andric // as a (void *foo) cast. 273504eeddc0SDimitry Andric // void operator delete(void *foo) ATTRIB; 273604eeddc0SDimitry Andric if (LeftOfParens->Tok.getIdentifierInfo() && LeftOfParens->Previous && 273781ad6265SDimitry Andric LeftOfParens->Previous->is(tok::kw_operator)) { 273804eeddc0SDimitry Andric return false; 273981ad6265SDimitry Andric } 274004eeddc0SDimitry Andric 27410b57cec5SDimitry Andric // If there is an identifier (or with a few exceptions a keyword) right 27420b57cec5SDimitry Andric // before the parentheses, this is unlikely to be a cast. 27430b57cec5SDimitry Andric if (LeftOfParens->Tok.getIdentifierInfo() && 27440b57cec5SDimitry Andric !LeftOfParens->isOneOf(Keywords.kw_in, tok::kw_return, tok::kw_case, 2745bdd1243dSDimitry Andric tok::kw_delete, tok::kw_throw)) { 27460b57cec5SDimitry Andric return false; 274781ad6265SDimitry Andric } 27480b57cec5SDimitry Andric 27490b57cec5SDimitry Andric // Certain other tokens right before the parentheses are also signals that 27500b57cec5SDimitry Andric // this cannot be a cast. 27510b57cec5SDimitry Andric if (LeftOfParens->isOneOf(tok::at, tok::r_square, TT_OverloadedOperator, 275281ad6265SDimitry Andric TT_TemplateCloser, tok::ellipsis)) { 27530b57cec5SDimitry Andric return false; 27540b57cec5SDimitry Andric } 275581ad6265SDimitry Andric } 27560b57cec5SDimitry Andric 27570fca6ea1SDimitry Andric if (AfterRParen->is(tok::question) || 27580fca6ea1SDimitry Andric (AfterRParen->is(tok::ampamp) && !BeforeRParen->isTypeName(LangOpts))) { 27590b57cec5SDimitry Andric return false; 27600fca6ea1SDimitry Andric } 27610b57cec5SDimitry Andric 27625ffd83dbSDimitry Andric // `foreach((A a, B b) in someList)` should not be seen as a cast. 27630fca6ea1SDimitry Andric if (AfterRParen->is(Keywords.kw_in) && Style.isCSharp()) 27645ffd83dbSDimitry Andric return false; 27655ffd83dbSDimitry Andric 2766a7dea167SDimitry Andric // Functions which end with decorations like volatile, noexcept are unlikely 2767a7dea167SDimitry Andric // to be casts. 27680fca6ea1SDimitry Andric if (AfterRParen->isOneOf(tok::kw_noexcept, tok::kw_volatile, tok::kw_const, 2769e8d8bef9SDimitry Andric tok::kw_requires, tok::kw_throw, tok::arrow, 2770e8d8bef9SDimitry Andric Keywords.kw_override, Keywords.kw_final) || 27710fca6ea1SDimitry Andric isCppAttribute(IsCpp, *AfterRParen)) { 2772a7dea167SDimitry Andric return false; 277381ad6265SDimitry Andric } 2774a7dea167SDimitry Andric 27750b57cec5SDimitry Andric // As Java has no function types, a "(" after the ")" likely means that this 27760b57cec5SDimitry Andric // is a cast. 27770fca6ea1SDimitry Andric if (Style.Language == FormatStyle::LK_Java && AfterRParen->is(tok::l_paren)) 27780b57cec5SDimitry Andric return true; 27790b57cec5SDimitry Andric 27800b57cec5SDimitry Andric // If a (non-string) literal follows, this is likely a cast. 27810fca6ea1SDimitry Andric if (AfterRParen->isOneOf(tok::kw_sizeof, tok::kw_alignof) || 27820fca6ea1SDimitry Andric (AfterRParen->Tok.isLiteral() && 27830fca6ea1SDimitry Andric AfterRParen->isNot(tok::string_literal))) { 27840b57cec5SDimitry Andric return true; 278581ad6265SDimitry Andric } 27860b57cec5SDimitry Andric 27870b57cec5SDimitry Andric // Heuristically try to determine whether the parentheses contain a type. 27880fca6ea1SDimitry Andric auto IsQualifiedPointerOrReference = [](const FormatToken *T, 27890fca6ea1SDimitry Andric const LangOptions &LangOpts) { 2790e8d8bef9SDimitry Andric // This is used to handle cases such as x = (foo *const)&y; 27910fca6ea1SDimitry Andric assert(!T->isTypeName(LangOpts) && "Should have already been checked"); 2792e8d8bef9SDimitry Andric // Strip trailing qualifiers such as const or volatile when checking 2793e8d8bef9SDimitry Andric // whether the parens could be a cast to a pointer/reference type. 2794e8d8bef9SDimitry Andric while (T) { 27955f757f3fSDimitry Andric if (T->is(TT_AttributeRParen)) { 2796e8d8bef9SDimitry Andric // Handle `x = (foo *__attribute__((foo)))&v;`: 27975f757f3fSDimitry Andric assert(T->is(tok::r_paren)); 27985f757f3fSDimitry Andric assert(T->MatchingParen); 27995f757f3fSDimitry Andric assert(T->MatchingParen->is(tok::l_paren)); 28005f757f3fSDimitry Andric assert(T->MatchingParen->is(TT_AttributeLParen)); 28015f757f3fSDimitry Andric if (const auto *Tok = T->MatchingParen->Previous; 28025f757f3fSDimitry Andric Tok && Tok->isAttribute()) { 28035f757f3fSDimitry Andric T = Tok->Previous; 2804e8d8bef9SDimitry Andric continue; 2805e8d8bef9SDimitry Andric } 2806e8d8bef9SDimitry Andric } else if (T->is(TT_AttributeSquare)) { 2807e8d8bef9SDimitry Andric // Handle `x = (foo *[[clang::foo]])&v;`: 2808e8d8bef9SDimitry Andric if (T->MatchingParen && T->MatchingParen->Previous) { 2809e8d8bef9SDimitry Andric T = T->MatchingParen->Previous; 2810e8d8bef9SDimitry Andric continue; 2811e8d8bef9SDimitry Andric } 2812e8d8bef9SDimitry Andric } else if (T->canBePointerOrReferenceQualifier()) { 2813e8d8bef9SDimitry Andric T = T->Previous; 2814e8d8bef9SDimitry Andric continue; 2815e8d8bef9SDimitry Andric } 2816e8d8bef9SDimitry Andric break; 2817e8d8bef9SDimitry Andric } 2818e8d8bef9SDimitry Andric return T && T->is(TT_PointerOrReference); 2819e8d8bef9SDimitry Andric }; 28200b57cec5SDimitry Andric bool ParensAreType = 28210fca6ea1SDimitry Andric BeforeRParen->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) || 28220fca6ea1SDimitry Andric BeforeRParen->isTypeName(LangOpts) || 28230fca6ea1SDimitry Andric IsQualifiedPointerOrReference(BeforeRParen, LangOpts); 28240b57cec5SDimitry Andric bool ParensCouldEndDecl = 28250fca6ea1SDimitry Andric AfterRParen->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater); 28260b57cec5SDimitry Andric if (ParensAreType && !ParensCouldEndDecl) 28270b57cec5SDimitry Andric return true; 28280b57cec5SDimitry Andric 28290b57cec5SDimitry Andric // At this point, we heuristically assume that there are no casts at the 28300b57cec5SDimitry Andric // start of the line. We assume that we have found most cases where there 28310b57cec5SDimitry Andric // are by the logic above, e.g. "(void)x;". 28320b57cec5SDimitry Andric if (!LeftOfParens) 28330b57cec5SDimitry Andric return false; 28340b57cec5SDimitry Andric 28350b57cec5SDimitry Andric // Certain token types inside the parentheses mean that this can't be a 28360b57cec5SDimitry Andric // cast. 28370fca6ea1SDimitry Andric for (const auto *Token = LParen->Next; Token != &Tok; Token = Token->Next) 28380b57cec5SDimitry Andric if (Token->is(TT_BinaryOperator)) 28390b57cec5SDimitry Andric return false; 28400b57cec5SDimitry Andric 28410b57cec5SDimitry Andric // If the following token is an identifier or 'this', this is a cast. All 28420b57cec5SDimitry Andric // cases where this can be something else are handled above. 28430fca6ea1SDimitry Andric if (AfterRParen->isOneOf(tok::identifier, tok::kw_this)) 28440b57cec5SDimitry Andric return true; 28450b57cec5SDimitry Andric 284623408297SDimitry Andric // Look for a cast `( x ) (`. 28470fca6ea1SDimitry Andric if (AfterRParen->is(tok::l_paren) && BeforeRParen->Previous) { 28480fca6ea1SDimitry Andric if (BeforeRParen->is(tok::identifier) && 28490fca6ea1SDimitry Andric BeforeRParen->Previous->is(tok::l_paren)) { 2850e8d8bef9SDimitry Andric return true; 285123408297SDimitry Andric } 285281ad6265SDimitry Andric } 2853e8d8bef9SDimitry Andric 28540fca6ea1SDimitry Andric if (!AfterRParen->Next) 28550b57cec5SDimitry Andric return false; 28560b57cec5SDimitry Andric 28570fca6ea1SDimitry Andric if (AfterRParen->is(tok::l_brace) && 28580fca6ea1SDimitry Andric AfterRParen->getBlockKind() == BK_BracedInit) { 28590fca6ea1SDimitry Andric return true; 28600fca6ea1SDimitry Andric } 28610fca6ea1SDimitry Andric 28620b57cec5SDimitry Andric // If the next token after the parenthesis is a unary operator, assume 28630b57cec5SDimitry Andric // that this is cast, unless there are unexpected tokens inside the 28640b57cec5SDimitry Andric // parenthesis. 28650fca6ea1SDimitry Andric const bool NextIsAmpOrStar = AfterRParen->isOneOf(tok::amp, tok::star); 28660fca6ea1SDimitry Andric if (!(AfterRParen->isUnaryOperator() || NextIsAmpOrStar) || 28670fca6ea1SDimitry Andric AfterRParen->is(tok::plus) || 28680fca6ea1SDimitry Andric !AfterRParen->Next->isOneOf(tok::identifier, tok::numeric_constant)) { 28690b57cec5SDimitry Andric return false; 287081ad6265SDimitry Andric } 28710fca6ea1SDimitry Andric 287206c3fb27SDimitry Andric if (NextIsAmpOrStar && 28730fca6ea1SDimitry Andric (AfterRParen->Next->is(tok::numeric_constant) || Line.InPPDirective)) { 287406c3fb27SDimitry Andric return false; 287506c3fb27SDimitry Andric } 28760fca6ea1SDimitry Andric 28770fca6ea1SDimitry Andric if (Line.InPPDirective && AfterRParen->is(tok::minus)) 2878b3edf446SDimitry Andric return false; 28790fca6ea1SDimitry Andric 28800b57cec5SDimitry Andric // Search for unexpected tokens. 288162987288SDimitry Andric for (auto *Prev = BeforeRParen; Prev != LParen; Prev = Prev->Previous) { 288262987288SDimitry Andric if (Prev->is(tok::r_paren)) { 28836c4b055cSDimitry Andric if (Prev->is(TT_CastRParen)) 28846c4b055cSDimitry Andric return false; 288562987288SDimitry Andric Prev = Prev->MatchingParen; 288662987288SDimitry Andric if (!Prev) 288762987288SDimitry Andric return false; 288862987288SDimitry Andric if (Prev->is(TT_FunctionTypeLParen)) 288962987288SDimitry Andric break; 289062987288SDimitry Andric continue; 289162987288SDimitry Andric } 28920b57cec5SDimitry Andric if (!Prev->isOneOf(tok::kw_const, tok::identifier, tok::coloncolon)) 28930b57cec5SDimitry Andric return false; 289462987288SDimitry Andric } 28950fca6ea1SDimitry Andric 28960b57cec5SDimitry Andric return true; 28970b57cec5SDimitry Andric } 28980b57cec5SDimitry Andric 289981ad6265SDimitry Andric /// Returns true if the token is used as a unary operator. 290081ad6265SDimitry Andric bool determineUnaryOperatorByUsage(const FormatToken &Tok) { 290181ad6265SDimitry Andric const FormatToken *PrevToken = Tok.getPreviousNonComment(); 290281ad6265SDimitry Andric if (!PrevToken) 290381ad6265SDimitry Andric return true; 290481ad6265SDimitry Andric 290581ad6265SDimitry Andric // These keywords are deliberately not included here because they may 290681ad6265SDimitry Andric // precede only one of unary star/amp and plus/minus but not both. They are 290781ad6265SDimitry Andric // either included in determineStarAmpUsage or determinePlusMinusCaretUsage. 290881ad6265SDimitry Andric // 290981ad6265SDimitry Andric // @ - It may be followed by a unary `-` in Objective-C literals. We don't 291081ad6265SDimitry Andric // know how they can be followed by a star or amp. 291181ad6265SDimitry Andric if (PrevToken->isOneOf( 291281ad6265SDimitry Andric TT_ConditionalExpr, tok::l_paren, tok::comma, tok::colon, tok::semi, 291381ad6265SDimitry Andric tok::equal, tok::question, tok::l_square, tok::l_brace, 291481ad6265SDimitry Andric tok::kw_case, tok::kw_co_await, tok::kw_co_return, tok::kw_co_yield, 291581ad6265SDimitry Andric tok::kw_delete, tok::kw_return, tok::kw_throw)) { 291681ad6265SDimitry Andric return true; 291781ad6265SDimitry Andric } 291881ad6265SDimitry Andric 291981ad6265SDimitry Andric // We put sizeof here instead of only in determineStarAmpUsage. In the cases 292081ad6265SDimitry Andric // where the unary `+` operator is overloaded, it is reasonable to write 292181ad6265SDimitry Andric // things like `sizeof +x`. Like commit 446d6ec996c6c3. 292281ad6265SDimitry Andric if (PrevToken->is(tok::kw_sizeof)) 292381ad6265SDimitry Andric return true; 292481ad6265SDimitry Andric 292581ad6265SDimitry Andric // A sequence of leading unary operators. 292681ad6265SDimitry Andric if (PrevToken->isOneOf(TT_CastRParen, TT_UnaryOperator)) 292781ad6265SDimitry Andric return true; 292881ad6265SDimitry Andric 292981ad6265SDimitry Andric // There can't be two consecutive binary operators. 293081ad6265SDimitry Andric if (PrevToken->is(TT_BinaryOperator)) 293181ad6265SDimitry Andric return true; 293281ad6265SDimitry Andric 293381ad6265SDimitry Andric return false; 293481ad6265SDimitry Andric } 293581ad6265SDimitry Andric 29360b57cec5SDimitry Andric /// Return the type of the given token assuming it is * or &. 29370b57cec5SDimitry Andric TokenType determineStarAmpUsage(const FormatToken &Tok, bool IsExpression, 29380b57cec5SDimitry Andric bool InTemplateArgument) { 29390eae32dcSDimitry Andric if (Style.isJavaScript()) 29400b57cec5SDimitry Andric return TT_BinaryOperator; 29410b57cec5SDimitry Andric 29425ffd83dbSDimitry Andric // && in C# must be a binary operator. 29435ffd83dbSDimitry Andric if (Style.isCSharp() && Tok.is(tok::ampamp)) 29445ffd83dbSDimitry Andric return TT_BinaryOperator; 29455ffd83dbSDimitry Andric 294606c3fb27SDimitry Andric if (Style.isVerilog()) { 294706c3fb27SDimitry Andric // In Verilog, `*` can only be a binary operator. `&` can be either unary 294806c3fb27SDimitry Andric // or binary. `*` also includes `*>` in module path declarations in 294906c3fb27SDimitry Andric // specify blocks because merged tokens take the type of the first one by 295006c3fb27SDimitry Andric // default. 295106c3fb27SDimitry Andric if (Tok.is(tok::star)) 295206c3fb27SDimitry Andric return TT_BinaryOperator; 295306c3fb27SDimitry Andric return determineUnaryOperatorByUsage(Tok) ? TT_UnaryOperator 295406c3fb27SDimitry Andric : TT_BinaryOperator; 295506c3fb27SDimitry Andric } 295606c3fb27SDimitry Andric 29570b57cec5SDimitry Andric const FormatToken *PrevToken = Tok.getPreviousNonComment(); 29580b57cec5SDimitry Andric if (!PrevToken) 29590b57cec5SDimitry Andric return TT_UnaryOperator; 296006c3fb27SDimitry Andric if (PrevToken->is(TT_TypeName)) 296106c3fb27SDimitry Andric return TT_PointerOrReference; 29620fca6ea1SDimitry Andric if (PrevToken->isOneOf(tok::kw_new, tok::kw_delete) && Tok.is(tok::ampamp)) 29630fca6ea1SDimitry Andric return TT_BinaryOperator; 29640b57cec5SDimitry Andric 29650b57cec5SDimitry Andric const FormatToken *NextToken = Tok.getNextNonComment(); 296681ad6265SDimitry Andric 296781ad6265SDimitry Andric if (InTemplateArgument && NextToken && NextToken->is(tok::kw_noexcept)) 296881ad6265SDimitry Andric return TT_BinaryOperator; 296981ad6265SDimitry Andric 29700b57cec5SDimitry Andric if (!NextToken || 29715f757f3fSDimitry Andric NextToken->isOneOf(tok::arrow, tok::equal, tok::comma, tok::r_paren, 29725f757f3fSDimitry Andric TT_RequiresClause) || 29735f757f3fSDimitry Andric (NextToken->is(tok::kw_noexcept) && !IsExpression) || 2974e8d8bef9SDimitry Andric NextToken->canBePointerOrReferenceQualifier() || 297581ad6265SDimitry Andric (NextToken->is(tok::l_brace) && !NextToken->getNextNonComment())) { 29760b57cec5SDimitry Andric return TT_PointerOrReference; 297781ad6265SDimitry Andric } 29780b57cec5SDimitry Andric 29790b57cec5SDimitry Andric if (PrevToken->is(tok::coloncolon)) 29800b57cec5SDimitry Andric return TT_PointerOrReference; 29810b57cec5SDimitry Andric 2982e8d8bef9SDimitry Andric if (PrevToken->is(tok::r_paren) && PrevToken->is(TT_TypeDeclarationParen)) 2983e8d8bef9SDimitry Andric return TT_PointerOrReference; 2984e8d8bef9SDimitry Andric 298581ad6265SDimitry Andric if (determineUnaryOperatorByUsage(Tok)) 29860b57cec5SDimitry Andric return TT_UnaryOperator; 29870b57cec5SDimitry Andric 29880b57cec5SDimitry Andric if (NextToken->is(tok::l_square) && NextToken->isNot(TT_LambdaLSquare)) 29890b57cec5SDimitry Andric return TT_PointerOrReference; 29900b57cec5SDimitry Andric if (NextToken->is(tok::kw_operator) && !IsExpression) 29910b57cec5SDimitry Andric return TT_PointerOrReference; 29920b57cec5SDimitry Andric if (NextToken->isOneOf(tok::comma, tok::semi)) 29930b57cec5SDimitry Andric return TT_PointerOrReference; 29940b57cec5SDimitry Andric 299581ad6265SDimitry Andric // After right braces, star tokens are likely to be pointers to struct, 299681ad6265SDimitry Andric // union, or class. 299781ad6265SDimitry Andric // struct {} *ptr; 2998fcaf7f86SDimitry Andric // This by itself is not sufficient to distinguish from multiplication 2999fcaf7f86SDimitry Andric // following a brace-initialized expression, as in: 3000fcaf7f86SDimitry Andric // int i = int{42} * 2; 3001fcaf7f86SDimitry Andric // In the struct case, the part of the struct declaration until the `{` and 3002fcaf7f86SDimitry Andric // the `}` are put on separate unwrapped lines; in the brace-initialized 3003fcaf7f86SDimitry Andric // case, the matching `{` is on the same unwrapped line, so check for the 3004fcaf7f86SDimitry Andric // presence of the matching brace to distinguish between those. 3005fcaf7f86SDimitry Andric if (PrevToken->is(tok::r_brace) && Tok.is(tok::star) && 3006bdd1243dSDimitry Andric !PrevToken->MatchingParen) { 300781ad6265SDimitry Andric return TT_PointerOrReference; 3008bdd1243dSDimitry Andric } 3009bdd1243dSDimitry Andric 3010bdd1243dSDimitry Andric if (PrevToken->endsSequence(tok::r_square, tok::l_square, tok::kw_delete)) 3011bdd1243dSDimitry Andric return TT_UnaryOperator; 301281ad6265SDimitry Andric 30130b57cec5SDimitry Andric if (PrevToken->Tok.isLiteral() || 30140b57cec5SDimitry Andric PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::kw_true, 301581ad6265SDimitry Andric tok::kw_false, tok::r_brace)) { 301681ad6265SDimitry Andric return TT_BinaryOperator; 301781ad6265SDimitry Andric } 301881ad6265SDimitry Andric 301981ad6265SDimitry Andric const FormatToken *NextNonParen = NextToken; 302081ad6265SDimitry Andric while (NextNonParen && NextNonParen->is(tok::l_paren)) 302181ad6265SDimitry Andric NextNonParen = NextNonParen->getNextNonComment(); 302281ad6265SDimitry Andric if (NextNonParen && (NextNonParen->Tok.isLiteral() || 302381ad6265SDimitry Andric NextNonParen->isOneOf(tok::kw_true, tok::kw_false) || 302481ad6265SDimitry Andric NextNonParen->isUnaryOperator())) { 302581ad6265SDimitry Andric return TT_BinaryOperator; 302681ad6265SDimitry Andric } 302781ad6265SDimitry Andric 302881ad6265SDimitry Andric // If we know we're in a template argument, there are no named declarations. 302981ad6265SDimitry Andric // Thus, having an identifier on the right-hand side indicates a binary 303081ad6265SDimitry Andric // operator. 303181ad6265SDimitry Andric if (InTemplateArgument && NextToken->Tok.isAnyIdentifier()) 30320b57cec5SDimitry Andric return TT_BinaryOperator; 30330b57cec5SDimitry Andric 30345f757f3fSDimitry Andric // "&&" followed by "(", "*", or "&" is quite unlikely to be two successive 30355f757f3fSDimitry Andric // unary "&". 30365f757f3fSDimitry Andric if (Tok.is(tok::ampamp) && 30375f757f3fSDimitry Andric NextToken->isOneOf(tok::l_paren, tok::star, tok::amp)) { 30380b57cec5SDimitry Andric return TT_BinaryOperator; 30395f757f3fSDimitry Andric } 30400b57cec5SDimitry Andric 30410b57cec5SDimitry Andric // This catches some cases where evaluation order is used as control flow: 30420b57cec5SDimitry Andric // aaa && aaa->f(); 30435ffd83dbSDimitry Andric if (NextToken->Tok.isAnyIdentifier()) { 30440b57cec5SDimitry Andric const FormatToken *NextNextToken = NextToken->getNextNonComment(); 30450b57cec5SDimitry Andric if (NextNextToken && NextNextToken->is(tok::arrow)) 30460b57cec5SDimitry Andric return TT_BinaryOperator; 30475ffd83dbSDimitry Andric } 30480b57cec5SDimitry Andric 30490b57cec5SDimitry Andric // It is very unlikely that we are going to find a pointer or reference type 30500b57cec5SDimitry Andric // definition on the RHS of an assignment. 30510b57cec5SDimitry Andric if (IsExpression && !Contexts.back().CaretFound) 30520b57cec5SDimitry Andric return TT_BinaryOperator; 30530b57cec5SDimitry Andric 305406c3fb27SDimitry Andric // Opeartors at class scope are likely pointer or reference members. 305506c3fb27SDimitry Andric if (!Scopes.empty() && Scopes.back() == ST_Class) 305606c3fb27SDimitry Andric return TT_PointerOrReference; 305706c3fb27SDimitry Andric 305806c3fb27SDimitry Andric // Tokens that indicate member access or chained operator& use. 305906c3fb27SDimitry Andric auto IsChainedOperatorAmpOrMember = [](const FormatToken *token) { 306006c3fb27SDimitry Andric return !token || token->isOneOf(tok::amp, tok::period, tok::arrow, 306106c3fb27SDimitry Andric tok::arrowstar, tok::periodstar); 306206c3fb27SDimitry Andric }; 306306c3fb27SDimitry Andric 306406c3fb27SDimitry Andric // It's more likely that & represents operator& than an uninitialized 306506c3fb27SDimitry Andric // reference. 306606c3fb27SDimitry Andric if (Tok.is(tok::amp) && PrevToken && PrevToken->Tok.isAnyIdentifier() && 306706c3fb27SDimitry Andric IsChainedOperatorAmpOrMember(PrevToken->getPreviousNonComment()) && 306806c3fb27SDimitry Andric NextToken && NextToken->Tok.isAnyIdentifier()) { 306906c3fb27SDimitry Andric if (auto NextNext = NextToken->getNextNonComment(); 307006c3fb27SDimitry Andric NextNext && 307106c3fb27SDimitry Andric (IsChainedOperatorAmpOrMember(NextNext) || NextNext->is(tok::semi))) { 307206c3fb27SDimitry Andric return TT_BinaryOperator; 307306c3fb27SDimitry Andric } 307406c3fb27SDimitry Andric } 307506c3fb27SDimitry Andric 30760b57cec5SDimitry Andric return TT_PointerOrReference; 30770b57cec5SDimitry Andric } 30780b57cec5SDimitry Andric 30790b57cec5SDimitry Andric TokenType determinePlusMinusCaretUsage(const FormatToken &Tok) { 308081ad6265SDimitry Andric if (determineUnaryOperatorByUsage(Tok)) 308181ad6265SDimitry Andric return TT_UnaryOperator; 308281ad6265SDimitry Andric 30830b57cec5SDimitry Andric const FormatToken *PrevToken = Tok.getPreviousNonComment(); 30840b57cec5SDimitry Andric if (!PrevToken) 30850b57cec5SDimitry Andric return TT_UnaryOperator; 30860b57cec5SDimitry Andric 308781ad6265SDimitry Andric if (PrevToken->is(tok::at)) 30880b57cec5SDimitry Andric return TT_UnaryOperator; 30890b57cec5SDimitry Andric 30900b57cec5SDimitry Andric // Fall back to marking the token as binary operator. 30910b57cec5SDimitry Andric return TT_BinaryOperator; 30920b57cec5SDimitry Andric } 30930b57cec5SDimitry Andric 30940b57cec5SDimitry Andric /// Determine whether ++/-- are pre- or post-increments/-decrements. 30950b57cec5SDimitry Andric TokenType determineIncrementUsage(const FormatToken &Tok) { 30960b57cec5SDimitry Andric const FormatToken *PrevToken = Tok.getPreviousNonComment(); 30970b57cec5SDimitry Andric if (!PrevToken || PrevToken->is(TT_CastRParen)) 30980b57cec5SDimitry Andric return TT_UnaryOperator; 30990b57cec5SDimitry Andric if (PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::identifier)) 31000b57cec5SDimitry Andric return TT_TrailingUnaryOperator; 31010b57cec5SDimitry Andric 31020b57cec5SDimitry Andric return TT_UnaryOperator; 31030b57cec5SDimitry Andric } 31040b57cec5SDimitry Andric 31050b57cec5SDimitry Andric SmallVector<Context, 8> Contexts; 31060b57cec5SDimitry Andric 31070b57cec5SDimitry Andric const FormatStyle &Style; 31080b57cec5SDimitry Andric AnnotatedLine &Line; 31090b57cec5SDimitry Andric FormatToken *CurrentToken; 31100b57cec5SDimitry Andric bool AutoFound; 31110fca6ea1SDimitry Andric bool IsCpp; 31120fca6ea1SDimitry Andric LangOptions LangOpts; 31130b57cec5SDimitry Andric const AdditionalKeywords &Keywords; 31140b57cec5SDimitry Andric 311506c3fb27SDimitry Andric SmallVector<ScopeType> &Scopes; 311606c3fb27SDimitry Andric 31170b57cec5SDimitry Andric // Set of "<" tokens that do not open a template parameter list. If parseAngle 31180b57cec5SDimitry Andric // determines that a specific token can't be a template opener, it will make 31190b57cec5SDimitry Andric // same decision irrespective of the decisions for tokens leading up to it. 31200b57cec5SDimitry Andric // Store this information to prevent this from causing exponential runtime. 31210b57cec5SDimitry Andric llvm::SmallPtrSet<FormatToken *, 16> NonTemplateLess; 31220fca6ea1SDimitry Andric 31230fca6ea1SDimitry Andric int TemplateDeclarationDepth; 31240b57cec5SDimitry Andric }; 31250b57cec5SDimitry Andric 31260b57cec5SDimitry Andric static const int PrecedenceUnaryOperator = prec::PointerToMember + 1; 31270b57cec5SDimitry Andric static const int PrecedenceArrowAndPeriod = prec::PointerToMember + 2; 31280b57cec5SDimitry Andric 31290b57cec5SDimitry Andric /// Parses binary expressions by inserting fake parenthesis based on 31300b57cec5SDimitry Andric /// operator precedence. 31310b57cec5SDimitry Andric class ExpressionParser { 31320b57cec5SDimitry Andric public: 31330b57cec5SDimitry Andric ExpressionParser(const FormatStyle &Style, const AdditionalKeywords &Keywords, 31340b57cec5SDimitry Andric AnnotatedLine &Line) 313581ad6265SDimitry Andric : Style(Style), Keywords(Keywords), Line(Line), Current(Line.First) {} 31360b57cec5SDimitry Andric 31370b57cec5SDimitry Andric /// Parse expressions with the given operator precedence. 31380b57cec5SDimitry Andric void parse(int Precedence = 0) { 31390b57cec5SDimitry Andric // Skip 'return' and ObjC selector colons as they are not part of a binary 31400b57cec5SDimitry Andric // expression. 31410b57cec5SDimitry Andric while (Current && (Current->is(tok::kw_return) || 31420b57cec5SDimitry Andric (Current->is(tok::colon) && 314381ad6265SDimitry Andric Current->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral)))) { 31440b57cec5SDimitry Andric next(); 314581ad6265SDimitry Andric } 31460b57cec5SDimitry Andric 31470b57cec5SDimitry Andric if (!Current || Precedence > PrecedenceArrowAndPeriod) 31480b57cec5SDimitry Andric return; 31490b57cec5SDimitry Andric 31500b57cec5SDimitry Andric // Conditional expressions need to be parsed separately for proper nesting. 31510b57cec5SDimitry Andric if (Precedence == prec::Conditional) { 31520b57cec5SDimitry Andric parseConditionalExpr(); 31530b57cec5SDimitry Andric return; 31540b57cec5SDimitry Andric } 31550b57cec5SDimitry Andric 31560b57cec5SDimitry Andric // Parse unary operators, which all have a higher precedence than binary 31570b57cec5SDimitry Andric // operators. 31580b57cec5SDimitry Andric if (Precedence == PrecedenceUnaryOperator) { 31590b57cec5SDimitry Andric parseUnaryOperator(); 31600b57cec5SDimitry Andric return; 31610b57cec5SDimitry Andric } 31620b57cec5SDimitry Andric 31630b57cec5SDimitry Andric FormatToken *Start = Current; 31640b57cec5SDimitry Andric FormatToken *LatestOperator = nullptr; 31650b57cec5SDimitry Andric unsigned OperatorIndex = 0; 316606c3fb27SDimitry Andric // The first name of the current type in a port list. 316706c3fb27SDimitry Andric FormatToken *VerilogFirstOfType = nullptr; 31680b57cec5SDimitry Andric 31690b57cec5SDimitry Andric while (Current) { 317006c3fb27SDimitry Andric // In Verilog ports in a module header that don't have a type take the 317106c3fb27SDimitry Andric // type of the previous one. For example, 317206c3fb27SDimitry Andric // module a(output b, 317306c3fb27SDimitry Andric // c, 317406c3fb27SDimitry Andric // output d); 317506c3fb27SDimitry Andric // In this case there need to be fake parentheses around b and c. 317606c3fb27SDimitry Andric if (Style.isVerilog() && Precedence == prec::Comma) { 317706c3fb27SDimitry Andric VerilogFirstOfType = 317806c3fb27SDimitry Andric verilogGroupDecl(VerilogFirstOfType, LatestOperator); 317906c3fb27SDimitry Andric } 318006c3fb27SDimitry Andric 31810b57cec5SDimitry Andric // Consume operators with higher precedence. 31820b57cec5SDimitry Andric parse(Precedence + 1); 31830b57cec5SDimitry Andric 31840b57cec5SDimitry Andric int CurrentPrecedence = getCurrentPrecedence(); 31850b57cec5SDimitry Andric 31860eae32dcSDimitry Andric if (Precedence == CurrentPrecedence && Current && 31870eae32dcSDimitry Andric Current->is(TT_SelectorName)) { 31880b57cec5SDimitry Andric if (LatestOperator) 31890b57cec5SDimitry Andric addFakeParenthesis(Start, prec::Level(Precedence)); 31900b57cec5SDimitry Andric Start = Current; 31910b57cec5SDimitry Andric } 31920b57cec5SDimitry Andric 31935f757f3fSDimitry Andric if ((Style.isCSharp() || Style.isJavaScript() || 31945f757f3fSDimitry Andric Style.Language == FormatStyle::LK_Java) && 31955f757f3fSDimitry Andric Precedence == prec::Additive && Current) { 31965f757f3fSDimitry Andric // A string can be broken without parentheses around it when it is 31975f757f3fSDimitry Andric // already in a sequence of strings joined by `+` signs. 31985f757f3fSDimitry Andric FormatToken *Prev = Current->getPreviousNonComment(); 31995f757f3fSDimitry Andric if (Prev && Prev->is(tok::string_literal) && 32005f757f3fSDimitry Andric (Prev == Start || Prev->endsSequence(tok::string_literal, tok::plus, 32015f757f3fSDimitry Andric TT_StringInConcatenation))) { 32025f757f3fSDimitry Andric Prev->setType(TT_StringInConcatenation); 32035f757f3fSDimitry Andric } 32045f757f3fSDimitry Andric } 32055f757f3fSDimitry Andric 320606c3fb27SDimitry Andric // At the end of the line or when an operator with lower precedence is 32070b57cec5SDimitry Andric // found, insert fake parenthesis and return. 32080b57cec5SDimitry Andric if (!Current || 32090b57cec5SDimitry Andric (Current->closesScope() && 32100b57cec5SDimitry Andric (Current->MatchingParen || Current->is(TT_TemplateString))) || 32110b57cec5SDimitry Andric (CurrentPrecedence != -1 && CurrentPrecedence < Precedence) || 32120b57cec5SDimitry Andric (CurrentPrecedence == prec::Conditional && 32130b57cec5SDimitry Andric Precedence == prec::Assignment && Current->is(tok::colon))) { 32140b57cec5SDimitry Andric break; 32150b57cec5SDimitry Andric } 32160b57cec5SDimitry Andric 32170b57cec5SDimitry Andric // Consume scopes: (), [], <> and {} 321881ad6265SDimitry Andric // In addition to that we handle require clauses as scope, so that the 321981ad6265SDimitry Andric // constraints in that are correctly indented. 322081ad6265SDimitry Andric if (Current->opensScope() || 322181ad6265SDimitry Andric Current->isOneOf(TT_RequiresClause, 322281ad6265SDimitry Andric TT_RequiresClauseInARequiresExpression)) { 32230b57cec5SDimitry Andric // In fragment of a JavaScript template string can look like '}..${' and 32240b57cec5SDimitry Andric // thus close a scope and open a new one at the same time. 32250b57cec5SDimitry Andric while (Current && (!Current->closesScope() || Current->opensScope())) { 32260b57cec5SDimitry Andric next(); 32270b57cec5SDimitry Andric parse(); 32280b57cec5SDimitry Andric } 32290b57cec5SDimitry Andric next(); 32300b57cec5SDimitry Andric } else { 32310b57cec5SDimitry Andric // Operator found. 32320b57cec5SDimitry Andric if (CurrentPrecedence == Precedence) { 32330b57cec5SDimitry Andric if (LatestOperator) 32340b57cec5SDimitry Andric LatestOperator->NextOperator = Current; 32350b57cec5SDimitry Andric LatestOperator = Current; 32360b57cec5SDimitry Andric Current->OperatorIndex = OperatorIndex; 32370b57cec5SDimitry Andric ++OperatorIndex; 32380b57cec5SDimitry Andric } 32390b57cec5SDimitry Andric next(/*SkipPastLeadingComments=*/Precedence > 0); 32400b57cec5SDimitry Andric } 32410b57cec5SDimitry Andric } 32420b57cec5SDimitry Andric 324306c3fb27SDimitry Andric // Group variables of the same type. 324406c3fb27SDimitry Andric if (Style.isVerilog() && Precedence == prec::Comma && VerilogFirstOfType) 324506c3fb27SDimitry Andric addFakeParenthesis(VerilogFirstOfType, prec::Comma); 324606c3fb27SDimitry Andric 32470b57cec5SDimitry Andric if (LatestOperator && (Current || Precedence > 0)) { 324881ad6265SDimitry Andric // The requires clauses do not neccessarily end in a semicolon or a brace, 324981ad6265SDimitry Andric // but just go over to struct/class or a function declaration, we need to 325081ad6265SDimitry Andric // intervene so that the fake right paren is inserted correctly. 325181ad6265SDimitry Andric auto End = 325281ad6265SDimitry Andric (Start->Previous && 325381ad6265SDimitry Andric Start->Previous->isOneOf(TT_RequiresClause, 325481ad6265SDimitry Andric TT_RequiresClauseInARequiresExpression)) 325581ad6265SDimitry Andric ? [this]() { 325681ad6265SDimitry Andric auto Ret = Current ? Current : Line.Last; 325781ad6265SDimitry Andric while (!Ret->ClosesRequiresClause && Ret->Previous) 325881ad6265SDimitry Andric Ret = Ret->Previous; 325981ad6265SDimitry Andric return Ret; 326081ad6265SDimitry Andric }() 326181ad6265SDimitry Andric : nullptr; 326281ad6265SDimitry Andric 32630b57cec5SDimitry Andric if (Precedence == PrecedenceArrowAndPeriod) { 32640b57cec5SDimitry Andric // Call expressions don't have a binary operator precedence. 326581ad6265SDimitry Andric addFakeParenthesis(Start, prec::Unknown, End); 32660b57cec5SDimitry Andric } else { 326781ad6265SDimitry Andric addFakeParenthesis(Start, prec::Level(Precedence), End); 32680b57cec5SDimitry Andric } 32690b57cec5SDimitry Andric } 32700b57cec5SDimitry Andric } 32710b57cec5SDimitry Andric 32720b57cec5SDimitry Andric private: 32730b57cec5SDimitry Andric /// Gets the precedence (+1) of the given token for binary operators 32740b57cec5SDimitry Andric /// and other tokens that we treat like binary operators. 32750b57cec5SDimitry Andric int getCurrentPrecedence() { 32760b57cec5SDimitry Andric if (Current) { 32770b57cec5SDimitry Andric const FormatToken *NextNonComment = Current->getNextNonComment(); 32780b57cec5SDimitry Andric if (Current->is(TT_ConditionalExpr)) 32790b57cec5SDimitry Andric return prec::Conditional; 32800b57cec5SDimitry Andric if (NextNonComment && Current->is(TT_SelectorName) && 32810b57cec5SDimitry Andric (NextNonComment->isOneOf(TT_DictLiteral, TT_JsTypeColon) || 32825f757f3fSDimitry Andric (Style.isProto() && NextNonComment->is(tok::less)))) { 32830b57cec5SDimitry Andric return prec::Assignment; 328481ad6265SDimitry Andric } 32850b57cec5SDimitry Andric if (Current->is(TT_JsComputedPropertyName)) 32860b57cec5SDimitry Andric return prec::Assignment; 32876c4b055cSDimitry Andric if (Current->is(TT_LambdaArrow)) 32880b57cec5SDimitry Andric return prec::Comma; 3289fe6060f1SDimitry Andric if (Current->is(TT_FatArrow)) 32900b57cec5SDimitry Andric return prec::Assignment; 32910b57cec5SDimitry Andric if (Current->isOneOf(tok::semi, TT_InlineASMColon, TT_SelectorName) || 32920b57cec5SDimitry Andric (Current->is(tok::comment) && NextNonComment && 329381ad6265SDimitry Andric NextNonComment->is(TT_SelectorName))) { 32940b57cec5SDimitry Andric return 0; 329581ad6265SDimitry Andric } 32960b57cec5SDimitry Andric if (Current->is(TT_RangeBasedForLoopColon)) 32970b57cec5SDimitry Andric return prec::Comma; 32980eae32dcSDimitry Andric if ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) && 329981ad6265SDimitry Andric Current->is(Keywords.kw_instanceof)) { 33000b57cec5SDimitry Andric return prec::Relational; 330181ad6265SDimitry Andric } 33020eae32dcSDimitry Andric if (Style.isJavaScript() && 330381ad6265SDimitry Andric Current->isOneOf(Keywords.kw_in, Keywords.kw_as)) { 33040b57cec5SDimitry Andric return prec::Relational; 330581ad6265SDimitry Andric } 33060b57cec5SDimitry Andric if (Current->is(TT_BinaryOperator) || Current->is(tok::comma)) 33070b57cec5SDimitry Andric return Current->getPrecedence(); 3308bdd1243dSDimitry Andric if (Current->isOneOf(tok::period, tok::arrow) && 3309bdd1243dSDimitry Andric Current->isNot(TT_TrailingReturnArrow)) { 33100b57cec5SDimitry Andric return PrecedenceArrowAndPeriod; 3311bdd1243dSDimitry Andric } 33120eae32dcSDimitry Andric if ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) && 33130b57cec5SDimitry Andric Current->isOneOf(Keywords.kw_extends, Keywords.kw_implements, 331481ad6265SDimitry Andric Keywords.kw_throws)) { 33150b57cec5SDimitry Andric return 0; 33160b57cec5SDimitry Andric } 3317bdd1243dSDimitry Andric // In Verilog case labels are not on separate lines straight out of 3318bdd1243dSDimitry Andric // UnwrappedLineParser. The colon is not part of an expression. 3319bdd1243dSDimitry Andric if (Style.isVerilog() && Current->is(tok::colon)) 3320bdd1243dSDimitry Andric return 0; 332181ad6265SDimitry Andric } 33220b57cec5SDimitry Andric return -1; 33230b57cec5SDimitry Andric } 33240b57cec5SDimitry Andric 332581ad6265SDimitry Andric void addFakeParenthesis(FormatToken *Start, prec::Level Precedence, 332681ad6265SDimitry Andric FormatToken *End = nullptr) { 3327297eecfbSDimitry Andric // Do not assign fake parenthesis to tokens that are part of an 3328297eecfbSDimitry Andric // unexpanded macro call. The line within the macro call contains 3329297eecfbSDimitry Andric // the parenthesis and commas, and we will not find operators within 3330297eecfbSDimitry Andric // that structure. 3331297eecfbSDimitry Andric if (Start->MacroParent) 3332297eecfbSDimitry Andric return; 3333297eecfbSDimitry Andric 33340b57cec5SDimitry Andric Start->FakeLParens.push_back(Precedence); 33350b57cec5SDimitry Andric if (Precedence > prec::Unknown) 33360b57cec5SDimitry Andric Start->StartsBinaryExpression = true; 333781ad6265SDimitry Andric if (!End && Current) 333881ad6265SDimitry Andric End = Current->getPreviousNonComment(); 333981ad6265SDimitry Andric if (End) { 334081ad6265SDimitry Andric ++End->FakeRParens; 33410b57cec5SDimitry Andric if (Precedence > prec::Unknown) 334281ad6265SDimitry Andric End->EndsBinaryExpression = true; 33430b57cec5SDimitry Andric } 33440b57cec5SDimitry Andric } 33450b57cec5SDimitry Andric 33460b57cec5SDimitry Andric /// Parse unary operator expressions and surround them with fake 33470b57cec5SDimitry Andric /// parentheses if appropriate. 33480b57cec5SDimitry Andric void parseUnaryOperator() { 33490b57cec5SDimitry Andric llvm::SmallVector<FormatToken *, 2> Tokens; 33500b57cec5SDimitry Andric while (Current && Current->is(TT_UnaryOperator)) { 33510b57cec5SDimitry Andric Tokens.push_back(Current); 33520b57cec5SDimitry Andric next(); 33530b57cec5SDimitry Andric } 33540b57cec5SDimitry Andric parse(PrecedenceArrowAndPeriod); 335581ad6265SDimitry Andric for (FormatToken *Token : llvm::reverse(Tokens)) { 33560b57cec5SDimitry Andric // The actual precedence doesn't matter. 33570b57cec5SDimitry Andric addFakeParenthesis(Token, prec::Unknown); 33580b57cec5SDimitry Andric } 335981ad6265SDimitry Andric } 33600b57cec5SDimitry Andric 33610b57cec5SDimitry Andric void parseConditionalExpr() { 336281ad6265SDimitry Andric while (Current && Current->isTrailingComment()) 33630b57cec5SDimitry Andric next(); 33640b57cec5SDimitry Andric FormatToken *Start = Current; 33650b57cec5SDimitry Andric parse(prec::LogicalOr); 33665f757f3fSDimitry Andric if (!Current || Current->isNot(tok::question)) 33670b57cec5SDimitry Andric return; 33680b57cec5SDimitry Andric next(); 33690b57cec5SDimitry Andric parse(prec::Assignment); 33700b57cec5SDimitry Andric if (!Current || Current->isNot(TT_ConditionalExpr)) 33710b57cec5SDimitry Andric return; 33720b57cec5SDimitry Andric next(); 33730b57cec5SDimitry Andric parse(prec::Assignment); 33740b57cec5SDimitry Andric addFakeParenthesis(Start, prec::Conditional); 33750b57cec5SDimitry Andric } 33760b57cec5SDimitry Andric 33770b57cec5SDimitry Andric void next(bool SkipPastLeadingComments = true) { 33780b57cec5SDimitry Andric if (Current) 33790b57cec5SDimitry Andric Current = Current->Next; 33800b57cec5SDimitry Andric while (Current && 33810b57cec5SDimitry Andric (Current->NewlinesBefore == 0 || SkipPastLeadingComments) && 338281ad6265SDimitry Andric Current->isTrailingComment()) { 33830b57cec5SDimitry Andric Current = Current->Next; 33840b57cec5SDimitry Andric } 338581ad6265SDimitry Andric } 33860b57cec5SDimitry Andric 338706c3fb27SDimitry Andric // Add fake parenthesis around declarations of the same type for example in a 338806c3fb27SDimitry Andric // module prototype. Return the first port / variable of the current type. 338906c3fb27SDimitry Andric FormatToken *verilogGroupDecl(FormatToken *FirstOfType, 339006c3fb27SDimitry Andric FormatToken *PreviousComma) { 339106c3fb27SDimitry Andric if (!Current) 339206c3fb27SDimitry Andric return nullptr; 339306c3fb27SDimitry Andric 339406c3fb27SDimitry Andric FormatToken *Start = Current; 339506c3fb27SDimitry Andric 339606c3fb27SDimitry Andric // Skip attributes. 339706c3fb27SDimitry Andric while (Start->startsSequence(tok::l_paren, tok::star)) { 339806c3fb27SDimitry Andric if (!(Start = Start->MatchingParen) || 339906c3fb27SDimitry Andric !(Start = Start->getNextNonComment())) { 340006c3fb27SDimitry Andric return nullptr; 340106c3fb27SDimitry Andric } 340206c3fb27SDimitry Andric } 340306c3fb27SDimitry Andric 340406c3fb27SDimitry Andric FormatToken *Tok = Start; 340506c3fb27SDimitry Andric 340606c3fb27SDimitry Andric if (Tok->is(Keywords.kw_assign)) 340706c3fb27SDimitry Andric Tok = Tok->getNextNonComment(); 340806c3fb27SDimitry Andric 340906c3fb27SDimitry Andric // Skip any type qualifiers to find the first identifier. It may be either a 341006c3fb27SDimitry Andric // new type name or a variable name. There can be several type qualifiers 341106c3fb27SDimitry Andric // preceding a variable name, and we can not tell them apart by looking at 341206c3fb27SDimitry Andric // the word alone since a macro can be defined as either a type qualifier or 341306c3fb27SDimitry Andric // a variable name. Thus we use the last word before the dimensions instead 341406c3fb27SDimitry Andric // of the first word as the candidate for the variable or type name. 341506c3fb27SDimitry Andric FormatToken *First = nullptr; 341606c3fb27SDimitry Andric while (Tok) { 341706c3fb27SDimitry Andric FormatToken *Next = Tok->getNextNonComment(); 341806c3fb27SDimitry Andric 341906c3fb27SDimitry Andric if (Tok->is(tok::hash)) { 342006c3fb27SDimitry Andric // Start of a macro expansion. 342106c3fb27SDimitry Andric First = Tok; 342206c3fb27SDimitry Andric Tok = Next; 342306c3fb27SDimitry Andric if (Tok) 342406c3fb27SDimitry Andric Tok = Tok->getNextNonComment(); 342506c3fb27SDimitry Andric } else if (Tok->is(tok::hashhash)) { 342606c3fb27SDimitry Andric // Concatenation. Skip. 342706c3fb27SDimitry Andric Tok = Next; 342806c3fb27SDimitry Andric if (Tok) 342906c3fb27SDimitry Andric Tok = Tok->getNextNonComment(); 343006c3fb27SDimitry Andric } else if (Keywords.isVerilogQualifier(*Tok) || 343106c3fb27SDimitry Andric Keywords.isVerilogIdentifier(*Tok)) { 343206c3fb27SDimitry Andric First = Tok; 343306c3fb27SDimitry Andric Tok = Next; 343406c3fb27SDimitry Andric // The name may have dots like `interface_foo.modport_foo`. 343506c3fb27SDimitry Andric while (Tok && Tok->isOneOf(tok::period, tok::coloncolon) && 343606c3fb27SDimitry Andric (Tok = Tok->getNextNonComment())) { 343706c3fb27SDimitry Andric if (Keywords.isVerilogIdentifier(*Tok)) 343806c3fb27SDimitry Andric Tok = Tok->getNextNonComment(); 343906c3fb27SDimitry Andric } 344006c3fb27SDimitry Andric } else if (!Next) { 344106c3fb27SDimitry Andric Tok = nullptr; 344206c3fb27SDimitry Andric } else if (Tok->is(tok::l_paren)) { 344306c3fb27SDimitry Andric // Make sure the parenthesized list is a drive strength. Otherwise the 344406c3fb27SDimitry Andric // statement may be a module instantiation in which case we have already 344506c3fb27SDimitry Andric // found the instance name. 344606c3fb27SDimitry Andric if (Next->isOneOf( 344706c3fb27SDimitry Andric Keywords.kw_highz0, Keywords.kw_highz1, Keywords.kw_large, 344806c3fb27SDimitry Andric Keywords.kw_medium, Keywords.kw_pull0, Keywords.kw_pull1, 344906c3fb27SDimitry Andric Keywords.kw_small, Keywords.kw_strong0, Keywords.kw_strong1, 345006c3fb27SDimitry Andric Keywords.kw_supply0, Keywords.kw_supply1, Keywords.kw_weak0, 345106c3fb27SDimitry Andric Keywords.kw_weak1)) { 345206c3fb27SDimitry Andric Tok->setType(TT_VerilogStrength); 345306c3fb27SDimitry Andric Tok = Tok->MatchingParen; 345406c3fb27SDimitry Andric if (Tok) { 345506c3fb27SDimitry Andric Tok->setType(TT_VerilogStrength); 345606c3fb27SDimitry Andric Tok = Tok->getNextNonComment(); 345706c3fb27SDimitry Andric } 345806c3fb27SDimitry Andric } else { 345906c3fb27SDimitry Andric break; 346006c3fb27SDimitry Andric } 34610fca6ea1SDimitry Andric } else if (Tok->is(Keywords.kw_verilogHash)) { 34620fca6ea1SDimitry Andric // Delay control. 346306c3fb27SDimitry Andric if (Next->is(tok::l_paren)) 346406c3fb27SDimitry Andric Next = Next->MatchingParen; 346506c3fb27SDimitry Andric if (Next) 346606c3fb27SDimitry Andric Tok = Next->getNextNonComment(); 346706c3fb27SDimitry Andric } else { 346806c3fb27SDimitry Andric break; 346906c3fb27SDimitry Andric } 347006c3fb27SDimitry Andric } 347106c3fb27SDimitry Andric 347206c3fb27SDimitry Andric // Find the second identifier. If it exists it will be the name. 347306c3fb27SDimitry Andric FormatToken *Second = nullptr; 347406c3fb27SDimitry Andric // Dimensions. 347506c3fb27SDimitry Andric while (Tok && Tok->is(tok::l_square) && (Tok = Tok->MatchingParen)) 347606c3fb27SDimitry Andric Tok = Tok->getNextNonComment(); 347706c3fb27SDimitry Andric if (Tok && (Tok->is(tok::hash) || Keywords.isVerilogIdentifier(*Tok))) 347806c3fb27SDimitry Andric Second = Tok; 347906c3fb27SDimitry Andric 348006c3fb27SDimitry Andric // If the second identifier doesn't exist and there are qualifiers, the type 348106c3fb27SDimitry Andric // is implied. 348206c3fb27SDimitry Andric FormatToken *TypedName = nullptr; 348306c3fb27SDimitry Andric if (Second) { 348406c3fb27SDimitry Andric TypedName = Second; 348506c3fb27SDimitry Andric if (First && First->is(TT_Unknown)) 348606c3fb27SDimitry Andric First->setType(TT_VerilogDimensionedTypeName); 348706c3fb27SDimitry Andric } else if (First != Start) { 348806c3fb27SDimitry Andric // If 'First' is null, then this isn't a declaration, 'TypedName' gets set 348906c3fb27SDimitry Andric // to null as intended. 349006c3fb27SDimitry Andric TypedName = First; 349106c3fb27SDimitry Andric } 349206c3fb27SDimitry Andric 349306c3fb27SDimitry Andric if (TypedName) { 349406c3fb27SDimitry Andric // This is a declaration with a new type. 349506c3fb27SDimitry Andric if (TypedName->is(TT_Unknown)) 349606c3fb27SDimitry Andric TypedName->setType(TT_StartOfName); 349706c3fb27SDimitry Andric // Group variables of the previous type. 349806c3fb27SDimitry Andric if (FirstOfType && PreviousComma) { 349906c3fb27SDimitry Andric PreviousComma->setType(TT_VerilogTypeComma); 350006c3fb27SDimitry Andric addFakeParenthesis(FirstOfType, prec::Comma, PreviousComma->Previous); 350106c3fb27SDimitry Andric } 350206c3fb27SDimitry Andric 350306c3fb27SDimitry Andric FirstOfType = TypedName; 350406c3fb27SDimitry Andric 350506c3fb27SDimitry Andric // Don't let higher precedence handle the qualifiers. For example if we 350606c3fb27SDimitry Andric // have: 350706c3fb27SDimitry Andric // parameter x = 0 350806c3fb27SDimitry Andric // We skip `parameter` here. This way the fake parentheses for the 350906c3fb27SDimitry Andric // assignment will be around `x = 0`. 351006c3fb27SDimitry Andric while (Current && Current != FirstOfType) { 351106c3fb27SDimitry Andric if (Current->opensScope()) { 351206c3fb27SDimitry Andric next(); 351306c3fb27SDimitry Andric parse(); 351406c3fb27SDimitry Andric } 351506c3fb27SDimitry Andric next(); 351606c3fb27SDimitry Andric } 351706c3fb27SDimitry Andric } 351806c3fb27SDimitry Andric 351906c3fb27SDimitry Andric return FirstOfType; 352006c3fb27SDimitry Andric } 352106c3fb27SDimitry Andric 35220b57cec5SDimitry Andric const FormatStyle &Style; 35230b57cec5SDimitry Andric const AdditionalKeywords &Keywords; 352481ad6265SDimitry Andric const AnnotatedLine &Line; 35250b57cec5SDimitry Andric FormatToken *Current; 35260b57cec5SDimitry Andric }; 35270b57cec5SDimitry Andric 35280b57cec5SDimitry Andric } // end anonymous namespace 35290b57cec5SDimitry Andric 35300b57cec5SDimitry Andric void TokenAnnotator::setCommentLineLevels( 353181ad6265SDimitry Andric SmallVectorImpl<AnnotatedLine *> &Lines) const { 35320b57cec5SDimitry Andric const AnnotatedLine *NextNonCommentLine = nullptr; 353304eeddc0SDimitry Andric for (AnnotatedLine *Line : llvm::reverse(Lines)) { 353404eeddc0SDimitry Andric assert(Line->First); 35350b57cec5SDimitry Andric 35360b57cec5SDimitry Andric // If the comment is currently aligned with the line immediately following 35370b57cec5SDimitry Andric // it, that's probably intentional and we should keep it. 35385c16e71dSDimitry Andric if (NextNonCommentLine && NextNonCommentLine->First->NewlinesBefore < 2 && 35395c16e71dSDimitry Andric Line->isComment() && !isClangFormatOff(Line->First->TokenText) && 35400b57cec5SDimitry Andric NextNonCommentLine->First->OriginalColumn == 354104eeddc0SDimitry Andric Line->First->OriginalColumn) { 3542bdd1243dSDimitry Andric const bool PPDirectiveOrImportStmt = 3543bdd1243dSDimitry Andric NextNonCommentLine->Type == LT_PreprocessorDirective || 3544bdd1243dSDimitry Andric NextNonCommentLine->Type == LT_ImportStatement; 3545bdd1243dSDimitry Andric if (PPDirectiveOrImportStmt) 3546bdd1243dSDimitry Andric Line->Type = LT_CommentAbovePPDirective; 35470b57cec5SDimitry Andric // Align comments for preprocessor lines with the # in column 0 if 35480b57cec5SDimitry Andric // preprocessor lines are not indented. Otherwise, align with the next 35490b57cec5SDimitry Andric // line. 3550bdd1243dSDimitry Andric Line->Level = Style.IndentPPDirectives != FormatStyle::PPDIS_BeforeHash && 3551bdd1243dSDimitry Andric PPDirectiveOrImportStmt 35520b57cec5SDimitry Andric ? 0 35530b57cec5SDimitry Andric : NextNonCommentLine->Level; 35540b57cec5SDimitry Andric } else { 355504eeddc0SDimitry Andric NextNonCommentLine = Line->First->isNot(tok::r_brace) ? Line : nullptr; 35560b57cec5SDimitry Andric } 35570b57cec5SDimitry Andric 355804eeddc0SDimitry Andric setCommentLineLevels(Line->Children); 35590b57cec5SDimitry Andric } 35600b57cec5SDimitry Andric } 35610b57cec5SDimitry Andric 35620b57cec5SDimitry Andric static unsigned maxNestingDepth(const AnnotatedLine &Line) { 35630b57cec5SDimitry Andric unsigned Result = 0; 356406c3fb27SDimitry Andric for (const auto *Tok = Line.First; Tok; Tok = Tok->Next) 35650b57cec5SDimitry Andric Result = std::max(Result, Tok->NestingLevel); 35660b57cec5SDimitry Andric return Result; 35670b57cec5SDimitry Andric } 35680b57cec5SDimitry Andric 35695f757f3fSDimitry Andric // Returns the name of a function with no return type, e.g. a constructor or 35705f757f3fSDimitry Andric // destructor. 35710fca6ea1SDimitry Andric static FormatToken *getFunctionName(const AnnotatedLine &Line, 35720fca6ea1SDimitry Andric FormatToken *&OpeningParen) { 35735f757f3fSDimitry Andric for (FormatToken *Tok = Line.getFirstNonComment(), *Name = nullptr; Tok; 35745f757f3fSDimitry Andric Tok = Tok->getNextNonComment()) { 35755f757f3fSDimitry Andric // Skip C++11 attributes both before and after the function name. 35765f757f3fSDimitry Andric if (Tok->is(tok::l_square) && Tok->is(TT_AttributeSquare)) { 35775f757f3fSDimitry Andric Tok = Tok->MatchingParen; 35785f757f3fSDimitry Andric if (!Tok) 35795f757f3fSDimitry Andric break; 35805f757f3fSDimitry Andric continue; 35815f757f3fSDimitry Andric } 35820eae32dcSDimitry Andric 35835f757f3fSDimitry Andric // Make sure the name is followed by a pair of parentheses. 35845f757f3fSDimitry Andric if (Name) { 35850fca6ea1SDimitry Andric if (Tok->is(tok::l_paren) && Tok->isNot(TT_FunctionTypeLParen) && 35860fca6ea1SDimitry Andric Tok->MatchingParen) { 35870fca6ea1SDimitry Andric OpeningParen = Tok; 35880fca6ea1SDimitry Andric return Name; 35890fca6ea1SDimitry Andric } 35900fca6ea1SDimitry Andric return nullptr; 35915f757f3fSDimitry Andric } 35925f757f3fSDimitry Andric 35935f757f3fSDimitry Andric // Skip keywords that may precede the constructor/destructor name. 35945f757f3fSDimitry Andric if (Tok->isOneOf(tok::kw_friend, tok::kw_inline, tok::kw_virtual, 35955f757f3fSDimitry Andric tok::kw_constexpr, tok::kw_consteval, tok::kw_explicit)) { 35965f757f3fSDimitry Andric continue; 35975f757f3fSDimitry Andric } 35985f757f3fSDimitry Andric 35995f757f3fSDimitry Andric // A qualified name may start from the global namespace. 36005f757f3fSDimitry Andric if (Tok->is(tok::coloncolon)) { 36015f757f3fSDimitry Andric Tok = Tok->Next; 36025f757f3fSDimitry Andric if (!Tok) 36035f757f3fSDimitry Andric break; 36045f757f3fSDimitry Andric } 36055f757f3fSDimitry Andric 36065f757f3fSDimitry Andric // Skip to the unqualified part of the name. 36075f757f3fSDimitry Andric while (Tok->startsSequence(tok::identifier, tok::coloncolon)) { 36085f757f3fSDimitry Andric assert(Tok->Next); 36095f757f3fSDimitry Andric Tok = Tok->Next->Next; 36105f757f3fSDimitry Andric if (!Tok) 36115f757f3fSDimitry Andric return nullptr; 36125f757f3fSDimitry Andric } 36135f757f3fSDimitry Andric 36145f757f3fSDimitry Andric // Skip the `~` if a destructor name. 36155f757f3fSDimitry Andric if (Tok->is(tok::tilde)) { 36165f757f3fSDimitry Andric Tok = Tok->Next; 36175f757f3fSDimitry Andric if (!Tok) 36185f757f3fSDimitry Andric break; 36195f757f3fSDimitry Andric } 36205f757f3fSDimitry Andric 36215f757f3fSDimitry Andric // Make sure the name is not already annotated, e.g. as NamespaceMacro. 36225f757f3fSDimitry Andric if (Tok->isNot(tok::identifier) || Tok->isNot(TT_Unknown)) 36235f757f3fSDimitry Andric break; 36245f757f3fSDimitry Andric 36255f757f3fSDimitry Andric Name = Tok; 36265f757f3fSDimitry Andric } 36275f757f3fSDimitry Andric 36285f757f3fSDimitry Andric return nullptr; 36295f757f3fSDimitry Andric } 36305f757f3fSDimitry Andric 36315f757f3fSDimitry Andric // Checks if Tok is a constructor/destructor name qualified by its class name. 36325f757f3fSDimitry Andric static bool isCtorOrDtorName(const FormatToken *Tok) { 36335f757f3fSDimitry Andric assert(Tok && Tok->is(tok::identifier)); 36345f757f3fSDimitry Andric const auto *Prev = Tok->Previous; 36355f757f3fSDimitry Andric 36365f757f3fSDimitry Andric if (Prev && Prev->is(tok::tilde)) 36375f757f3fSDimitry Andric Prev = Prev->Previous; 36385f757f3fSDimitry Andric 36395f757f3fSDimitry Andric if (!Prev || !Prev->endsSequence(tok::coloncolon, tok::identifier)) 36405f757f3fSDimitry Andric return false; 36415f757f3fSDimitry Andric 36425f757f3fSDimitry Andric assert(Prev->Previous); 36435f757f3fSDimitry Andric return Prev->Previous->TokenText == Tok->TokenText; 36445f757f3fSDimitry Andric } 36455f757f3fSDimitry Andric 36465f757f3fSDimitry Andric void TokenAnnotator::annotate(AnnotatedLine &Line) { 364706c3fb27SDimitry Andric AnnotatingParser Parser(Style, Line, Keywords, Scopes); 36480b57cec5SDimitry Andric Line.Type = Parser.parseLine(); 36490b57cec5SDimitry Andric 36505f757f3fSDimitry Andric for (auto &Child : Line.Children) 36515f757f3fSDimitry Andric annotate(*Child); 36525f757f3fSDimitry Andric 36530b57cec5SDimitry Andric // With very deep nesting, ExpressionParser uses lots of stack and the 36540b57cec5SDimitry Andric // formatting algorithm is very slow. We're not going to do a good job here 36550b57cec5SDimitry Andric // anyway - it's probably generated code being formatted by mistake. 36560b57cec5SDimitry Andric // Just skip the whole line. 36570b57cec5SDimitry Andric if (maxNestingDepth(Line) > 50) 36580b57cec5SDimitry Andric Line.Type = LT_Invalid; 36590b57cec5SDimitry Andric 36600b57cec5SDimitry Andric if (Line.Type == LT_Invalid) 36610b57cec5SDimitry Andric return; 36620b57cec5SDimitry Andric 36630b57cec5SDimitry Andric ExpressionParser ExprParser(Style, Keywords, Line); 36640b57cec5SDimitry Andric ExprParser.parse(); 36650b57cec5SDimitry Andric 36660fca6ea1SDimitry Andric if (IsCpp) { 36670fca6ea1SDimitry Andric FormatToken *OpeningParen = nullptr; 36680fca6ea1SDimitry Andric auto *Tok = getFunctionName(Line, OpeningParen); 36695f757f3fSDimitry Andric if (Tok && ((!Scopes.empty() && Scopes.back() == ST_Class) || 36705f757f3fSDimitry Andric Line.endsWith(TT_FunctionLBrace) || isCtorOrDtorName(Tok))) { 36715f757f3fSDimitry Andric Tok->setFinalizedType(TT_CtorDtorDeclName); 36720fca6ea1SDimitry Andric assert(OpeningParen); 36730fca6ea1SDimitry Andric OpeningParen->setFinalizedType(TT_FunctionDeclarationLParen); 36745f757f3fSDimitry Andric } 36755f757f3fSDimitry Andric } 36765f757f3fSDimitry Andric 36770b57cec5SDimitry Andric if (Line.startsWith(TT_ObjCMethodSpecifier)) 36780b57cec5SDimitry Andric Line.Type = LT_ObjCMethodDecl; 36790b57cec5SDimitry Andric else if (Line.startsWith(TT_ObjCDecl)) 36800b57cec5SDimitry Andric Line.Type = LT_ObjCDecl; 36810b57cec5SDimitry Andric else if (Line.startsWith(TT_ObjCProperty)) 36820b57cec5SDimitry Andric Line.Type = LT_ObjCProperty; 36830b57cec5SDimitry Andric 36845f757f3fSDimitry Andric auto *First = Line.First; 36855f757f3fSDimitry Andric First->SpacesRequiredBefore = 1; 36865f757f3fSDimitry Andric First->CanBreakBefore = First->MustBreakBefore; 36870b57cec5SDimitry Andric } 36880b57cec5SDimitry Andric 36890b57cec5SDimitry Andric // This function heuristically determines whether 'Current' starts the name of a 36900b57cec5SDimitry Andric // function declaration. 36910fca6ea1SDimitry Andric static bool isFunctionDeclarationName(const LangOptions &LangOpts, 36920fca6ea1SDimitry Andric const FormatToken &Current, 36935f757f3fSDimitry Andric const AnnotatedLine &Line, 36945f757f3fSDimitry Andric FormatToken *&ClosingParen) { 369506c3fb27SDimitry Andric assert(Current.Previous); 36965f757f3fSDimitry Andric 36975f757f3fSDimitry Andric if (Current.is(TT_FunctionDeclarationName)) 36985f757f3fSDimitry Andric return true; 36995f757f3fSDimitry Andric 370006c3fb27SDimitry Andric if (!Current.Tok.getIdentifierInfo()) 370106c3fb27SDimitry Andric return false; 370206c3fb27SDimitry Andric 37030fca6ea1SDimitry Andric const auto &Previous = *Current.Previous; 37040fca6ea1SDimitry Andric 37050fca6ea1SDimitry Andric if (const auto *PrevPrev = Previous.Previous; 37060fca6ea1SDimitry Andric PrevPrev && PrevPrev->is(TT_ObjCDecl)) { 37070fca6ea1SDimitry Andric return false; 37080fca6ea1SDimitry Andric } 37090fca6ea1SDimitry Andric 37100fca6ea1SDimitry Andric auto skipOperatorName = 37110fca6ea1SDimitry Andric [&LangOpts](const FormatToken *Next) -> const FormatToken * { 37120b57cec5SDimitry Andric for (; Next; Next = Next->Next) { 37130b57cec5SDimitry Andric if (Next->is(TT_OverloadedOperatorLParen)) 37140b57cec5SDimitry Andric return Next; 37150b57cec5SDimitry Andric if (Next->is(TT_OverloadedOperator)) 37160b57cec5SDimitry Andric continue; 37170b57cec5SDimitry Andric if (Next->isOneOf(tok::kw_new, tok::kw_delete)) { 37180b57cec5SDimitry Andric // For 'new[]' and 'delete[]'. 3719480093f4SDimitry Andric if (Next->Next && 372081ad6265SDimitry Andric Next->Next->startsSequence(tok::l_square, tok::r_square)) { 37210b57cec5SDimitry Andric Next = Next->Next->Next; 372281ad6265SDimitry Andric } 37230b57cec5SDimitry Andric continue; 37240b57cec5SDimitry Andric } 3725480093f4SDimitry Andric if (Next->startsSequence(tok::l_square, tok::r_square)) { 3726480093f4SDimitry Andric // For operator[](). 3727480093f4SDimitry Andric Next = Next->Next; 3728480093f4SDimitry Andric continue; 3729480093f4SDimitry Andric } 37300fca6ea1SDimitry Andric if ((Next->isTypeName(LangOpts) || Next->is(tok::identifier)) && 37315f757f3fSDimitry Andric Next->Next && Next->Next->isPointerOrReference()) { 3732480093f4SDimitry Andric // For operator void*(), operator char*(), operator Foo*(). 3733480093f4SDimitry Andric Next = Next->Next; 3734480093f4SDimitry Andric continue; 3735480093f4SDimitry Andric } 3736d65cd7a5SDimitry Andric if (Next->is(TT_TemplateOpener) && Next->MatchingParen) { 3737d65cd7a5SDimitry Andric Next = Next->MatchingParen; 3738d65cd7a5SDimitry Andric continue; 3739d65cd7a5SDimitry Andric } 37400b57cec5SDimitry Andric 37410b57cec5SDimitry Andric break; 37420b57cec5SDimitry Andric } 37430b57cec5SDimitry Andric return nullptr; 37440b57cec5SDimitry Andric }; 37450b57cec5SDimitry Andric 37460fca6ea1SDimitry Andric const auto *Next = Current.Next; 37470fca6ea1SDimitry Andric const bool IsCpp = LangOpts.CXXOperatorNames; 37480fca6ea1SDimitry Andric 37490b57cec5SDimitry Andric // Find parentheses of parameter list. 37500b57cec5SDimitry Andric if (Current.is(tok::kw_operator)) { 37510fca6ea1SDimitry Andric if (Previous.Tok.getIdentifierInfo() && 37520fca6ea1SDimitry Andric !Previous.isOneOf(tok::kw_return, tok::kw_co_return)) { 375306c3fb27SDimitry Andric return true; 375406c3fb27SDimitry Andric } 37550fca6ea1SDimitry Andric if (Previous.is(tok::r_paren) && Previous.is(TT_TypeDeclarationParen)) { 37560fca6ea1SDimitry Andric assert(Previous.MatchingParen); 37570fca6ea1SDimitry Andric assert(Previous.MatchingParen->is(tok::l_paren)); 37580fca6ea1SDimitry Andric assert(Previous.MatchingParen->is(TT_TypeDeclarationParen)); 3759b121cb00SDimitry Andric return true; 3760b121cb00SDimitry Andric } 37610fca6ea1SDimitry Andric if (!Previous.isPointerOrReference() && Previous.isNot(TT_TemplateCloser)) 37620b57cec5SDimitry Andric return false; 37630b57cec5SDimitry Andric Next = skipOperatorName(Next); 37640b57cec5SDimitry Andric } else { 37655f757f3fSDimitry Andric if (Current.isNot(TT_StartOfName) || Current.NestingLevel != 0) 37660b57cec5SDimitry Andric return false; 37670b57cec5SDimitry Andric for (; Next; Next = Next->Next) { 3768bdd1243dSDimitry Andric if (Next->is(TT_TemplateOpener) && Next->MatchingParen) { 37690b57cec5SDimitry Andric Next = Next->MatchingParen; 37700b57cec5SDimitry Andric } else if (Next->is(tok::coloncolon)) { 37710b57cec5SDimitry Andric Next = Next->Next; 37720b57cec5SDimitry Andric if (!Next) 37730b57cec5SDimitry Andric return false; 37740b57cec5SDimitry Andric if (Next->is(tok::kw_operator)) { 37750b57cec5SDimitry Andric Next = skipOperatorName(Next->Next); 37760b57cec5SDimitry Andric break; 37770b57cec5SDimitry Andric } 37785f757f3fSDimitry Andric if (Next->isNot(tok::identifier)) 37790b57cec5SDimitry Andric return false; 3780bdd1243dSDimitry Andric } else if (isCppAttribute(IsCpp, *Next)) { 3781bdd1243dSDimitry Andric Next = Next->MatchingParen; 3782bdd1243dSDimitry Andric if (!Next) 3783bdd1243dSDimitry Andric return false; 37840b57cec5SDimitry Andric } else if (Next->is(tok::l_paren)) { 37850b57cec5SDimitry Andric break; 37860b57cec5SDimitry Andric } else { 37870b57cec5SDimitry Andric return false; 37880b57cec5SDimitry Andric } 37890b57cec5SDimitry Andric } 37900b57cec5SDimitry Andric } 37910b57cec5SDimitry Andric 37920b57cec5SDimitry Andric // Check whether parameter list can belong to a function declaration. 37935f757f3fSDimitry Andric if (!Next || Next->isNot(tok::l_paren) || !Next->MatchingParen) 37940b57cec5SDimitry Andric return false; 37955f757f3fSDimitry Andric ClosingParen = Next->MatchingParen; 37965f757f3fSDimitry Andric assert(ClosingParen->is(tok::r_paren)); 3797349cc55cSDimitry Andric // If the lines ends with "{", this is likely a function definition. 37980b57cec5SDimitry Andric if (Line.Last->is(tok::l_brace)) 37990b57cec5SDimitry Andric return true; 38005f757f3fSDimitry Andric if (Next->Next == ClosingParen) 38010b57cec5SDimitry Andric return true; // Empty parentheses. 38020b57cec5SDimitry Andric // If there is an &/&& after the r_paren, this is likely a function. 38035f757f3fSDimitry Andric if (ClosingParen->Next && ClosingParen->Next->is(TT_PointerOrReference)) 38040b57cec5SDimitry Andric return true; 38058c6f6c0cSDimitry Andric 38068c6f6c0cSDimitry Andric // Check for K&R C function definitions (and C++ function definitions with 38078c6f6c0cSDimitry Andric // unnamed parameters), e.g.: 3808fe6060f1SDimitry Andric // int f(i) 3809fe6060f1SDimitry Andric // { 3810fe6060f1SDimitry Andric // return i + 1; 3811fe6060f1SDimitry Andric // } 38128c6f6c0cSDimitry Andric // bool g(size_t = 0, bool b = false) 38138c6f6c0cSDimitry Andric // { 38148c6f6c0cSDimitry Andric // return !b; 38158c6f6c0cSDimitry Andric // } 38168c6f6c0cSDimitry Andric if (IsCpp && Next->Next && Next->Next->is(tok::identifier) && 381781ad6265SDimitry Andric !Line.endsWith(tok::semi)) { 3818fe6060f1SDimitry Andric return true; 381981ad6265SDimitry Andric } 38208c6f6c0cSDimitry Andric 38215f757f3fSDimitry Andric for (const FormatToken *Tok = Next->Next; Tok && Tok != ClosingParen; 38220b57cec5SDimitry Andric Tok = Tok->Next) { 3823e8d8bef9SDimitry Andric if (Tok->is(TT_TypeDeclarationParen)) 3824e8d8bef9SDimitry Andric return true; 38250b57cec5SDimitry Andric if (Tok->isOneOf(tok::l_paren, TT_TemplateOpener) && Tok->MatchingParen) { 38260b57cec5SDimitry Andric Tok = Tok->MatchingParen; 38270b57cec5SDimitry Andric continue; 38280b57cec5SDimitry Andric } 38290fca6ea1SDimitry Andric if (Tok->is(tok::kw_const) || Tok->isTypeName(LangOpts) || 38300fca6ea1SDimitry Andric Tok->isOneOf(TT_PointerOrReference, TT_StartOfName, tok::ellipsis)) { 38310b57cec5SDimitry Andric return true; 383281ad6265SDimitry Andric } 38335f757f3fSDimitry Andric if (Tok->isOneOf(tok::l_brace, TT_ObjCMethodExpr) || Tok->Tok.isLiteral()) 38340b57cec5SDimitry Andric return false; 38350b57cec5SDimitry Andric } 38360b57cec5SDimitry Andric return false; 38370b57cec5SDimitry Andric } 38380b57cec5SDimitry Andric 38390b57cec5SDimitry Andric bool TokenAnnotator::mustBreakForReturnType(const AnnotatedLine &Line) const { 38400b57cec5SDimitry Andric assert(Line.MightBeFunctionDecl); 38410b57cec5SDimitry Andric 38420fca6ea1SDimitry Andric if ((Style.BreakAfterReturnType == FormatStyle::RTBS_TopLevel || 38430fca6ea1SDimitry Andric Style.BreakAfterReturnType == FormatStyle::RTBS_TopLevelDefinitions) && 384481ad6265SDimitry Andric Line.Level > 0) { 38450b57cec5SDimitry Andric return false; 384681ad6265SDimitry Andric } 38470b57cec5SDimitry Andric 38480fca6ea1SDimitry Andric switch (Style.BreakAfterReturnType) { 38490b57cec5SDimitry Andric case FormatStyle::RTBS_None: 38500fca6ea1SDimitry Andric case FormatStyle::RTBS_Automatic: 38510fca6ea1SDimitry Andric case FormatStyle::RTBS_ExceptShortType: 38520b57cec5SDimitry Andric return false; 38530b57cec5SDimitry Andric case FormatStyle::RTBS_All: 38540b57cec5SDimitry Andric case FormatStyle::RTBS_TopLevel: 38550b57cec5SDimitry Andric return true; 38560b57cec5SDimitry Andric case FormatStyle::RTBS_AllDefinitions: 38570b57cec5SDimitry Andric case FormatStyle::RTBS_TopLevelDefinitions: 38580b57cec5SDimitry Andric return Line.mightBeFunctionDefinition(); 38590b57cec5SDimitry Andric } 38600b57cec5SDimitry Andric 38610b57cec5SDimitry Andric return false; 38620b57cec5SDimitry Andric } 38630b57cec5SDimitry Andric 386481ad6265SDimitry Andric void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const { 386504eeddc0SDimitry Andric for (AnnotatedLine *ChildLine : Line.Children) 386604eeddc0SDimitry Andric calculateFormattingInformation(*ChildLine); 38670b57cec5SDimitry Andric 3868dfa39133SDimitry Andric auto *First = Line.First; 3869dfa39133SDimitry Andric First->TotalLength = First->IsMultiline 3870dfa39133SDimitry Andric ? Style.ColumnLimit 3871dfa39133SDimitry Andric : Line.FirstStartColumn + First->ColumnWidth; 3872dfa39133SDimitry Andric FormatToken *Current = First->Next; 38730b57cec5SDimitry Andric bool InFunctionDecl = Line.MightBeFunctionDecl; 3874fe6060f1SDimitry Andric bool AlignArrayOfStructures = 3875fe6060f1SDimitry Andric (Style.AlignArrayOfStructures != FormatStyle::AIAS_None && 3876fe6060f1SDimitry Andric Line.Type == LT_ArrayOfStructInitializer); 3877fe6060f1SDimitry Andric if (AlignArrayOfStructures) 3878fe6060f1SDimitry Andric calculateArrayInitializerColumnList(Line); 3879fe6060f1SDimitry Andric 38805f757f3fSDimitry Andric bool SeenName = false; 388106c3fb27SDimitry Andric bool LineIsFunctionDeclaration = false; 38825f757f3fSDimitry Andric FormatToken *ClosingParen = nullptr; 38835f757f3fSDimitry Andric FormatToken *AfterLastAttribute = nullptr; 38845f757f3fSDimitry Andric 38855f757f3fSDimitry Andric for (auto *Tok = Current; Tok; Tok = Tok->Next) { 38865f757f3fSDimitry Andric if (Tok->is(TT_StartOfName)) 38875f757f3fSDimitry Andric SeenName = true; 3888bdd1243dSDimitry Andric if (Tok->Previous->EndsCppAttributeGroup) 3889bdd1243dSDimitry Andric AfterLastAttribute = Tok; 38905f757f3fSDimitry Andric if (const bool IsCtorOrDtor = Tok->is(TT_CtorDtorDeclName); 38915f757f3fSDimitry Andric IsCtorOrDtor || 38920fca6ea1SDimitry Andric isFunctionDeclarationName(LangOpts, *Tok, Line, ClosingParen)) { 3893dfa39133SDimitry Andric if (!IsCtorOrDtor) 38945f757f3fSDimitry Andric Tok->setFinalizedType(TT_FunctionDeclarationName); 3895dfa39133SDimitry Andric LineIsFunctionDeclaration = true; 38965f757f3fSDimitry Andric SeenName = true; 38970fca6ea1SDimitry Andric if (ClosingParen) { 38980fca6ea1SDimitry Andric auto *OpeningParen = ClosingParen->MatchingParen; 38990fca6ea1SDimitry Andric assert(OpeningParen); 39000fca6ea1SDimitry Andric if (OpeningParen->is(TT_Unknown)) 39010fca6ea1SDimitry Andric OpeningParen->setType(TT_FunctionDeclarationLParen); 39020fca6ea1SDimitry Andric } 39035f757f3fSDimitry Andric break; 39045f757f3fSDimitry Andric } 3905bdd1243dSDimitry Andric } 3906bdd1243dSDimitry Andric 3907dfa39133SDimitry Andric if (IsCpp && (LineIsFunctionDeclaration || First->is(TT_CtorDtorDeclName)) && 39085f757f3fSDimitry Andric Line.endsWith(tok::semi, tok::r_brace)) { 39095f757f3fSDimitry Andric auto *Tok = Line.Last->Previous; 39105f757f3fSDimitry Andric while (Tok->isNot(tok::r_brace)) 39115f757f3fSDimitry Andric Tok = Tok->Previous; 39125f757f3fSDimitry Andric if (auto *LBrace = Tok->MatchingParen; LBrace) { 39135f757f3fSDimitry Andric assert(LBrace->is(tok::l_brace)); 39145f757f3fSDimitry Andric Tok->setBlockKind(BK_Block); 39155f757f3fSDimitry Andric LBrace->setBlockKind(BK_Block); 39165f757f3fSDimitry Andric LBrace->setFinalizedType(TT_FunctionLBrace); 39175f757f3fSDimitry Andric } 39185f757f3fSDimitry Andric } 39195f757f3fSDimitry Andric 39205f757f3fSDimitry Andric if (IsCpp && SeenName && AfterLastAttribute && 39215f757f3fSDimitry Andric mustBreakAfterAttributes(*AfterLastAttribute, Style)) { 39225f757f3fSDimitry Andric AfterLastAttribute->MustBreakBefore = true; 39235f757f3fSDimitry Andric if (LineIsFunctionDeclaration) 39245f757f3fSDimitry Andric Line.ReturnTypeWrapped = true; 39255f757f3fSDimitry Andric } 39265f757f3fSDimitry Andric 39275f757f3fSDimitry Andric if (IsCpp) { 39285f757f3fSDimitry Andric if (!LineIsFunctionDeclaration) { 392906c3fb27SDimitry Andric // Annotate */&/&& in `operator` function calls as binary operators. 3930dfa39133SDimitry Andric for (const auto *Tok = First; Tok; Tok = Tok->Next) { 393106c3fb27SDimitry Andric if (Tok->isNot(tok::kw_operator)) 393206c3fb27SDimitry Andric continue; 393306c3fb27SDimitry Andric do { 393406c3fb27SDimitry Andric Tok = Tok->Next; 393506c3fb27SDimitry Andric } while (Tok && Tok->isNot(TT_OverloadedOperatorLParen)); 39360fca6ea1SDimitry Andric if (!Tok || !Tok->MatchingParen) 393706c3fb27SDimitry Andric break; 393806c3fb27SDimitry Andric const auto *LeftParen = Tok; 393906c3fb27SDimitry Andric for (Tok = Tok->Next; Tok && Tok != LeftParen->MatchingParen; 394006c3fb27SDimitry Andric Tok = Tok->Next) { 394106c3fb27SDimitry Andric if (Tok->isNot(tok::identifier)) 394206c3fb27SDimitry Andric continue; 394306c3fb27SDimitry Andric auto *Next = Tok->Next; 394406c3fb27SDimitry Andric const bool NextIsBinaryOperator = 39455f757f3fSDimitry Andric Next && Next->isPointerOrReference() && Next->Next && 39465f757f3fSDimitry Andric Next->Next->is(tok::identifier); 394706c3fb27SDimitry Andric if (!NextIsBinaryOperator) 394806c3fb27SDimitry Andric continue; 394906c3fb27SDimitry Andric Next->setType(TT_BinaryOperator); 395006c3fb27SDimitry Andric Tok = Next; 395106c3fb27SDimitry Andric } 395206c3fb27SDimitry Andric } 39535f757f3fSDimitry Andric } else if (ClosingParen) { 39545f757f3fSDimitry Andric for (auto *Tok = ClosingParen->Next; Tok; Tok = Tok->Next) { 39555678d1d9SDimitry Andric if (Tok->is(TT_CtorInitializerColon)) 39565678d1d9SDimitry Andric break; 39575f757f3fSDimitry Andric if (Tok->is(tok::arrow)) { 39585f757f3fSDimitry Andric Tok->setType(TT_TrailingReturnArrow); 39595f757f3fSDimitry Andric break; 39605f757f3fSDimitry Andric } 39615f757f3fSDimitry Andric if (Tok->isNot(TT_TrailingAnnotation)) 39625f757f3fSDimitry Andric continue; 39635f757f3fSDimitry Andric const auto *Next = Tok->Next; 39645f757f3fSDimitry Andric if (!Next || Next->isNot(tok::l_paren)) 39655f757f3fSDimitry Andric continue; 39665f757f3fSDimitry Andric Tok = Next->MatchingParen; 39675f757f3fSDimitry Andric if (!Tok) 39685f757f3fSDimitry Andric break; 39695f757f3fSDimitry Andric } 39705f757f3fSDimitry Andric } 397106c3fb27SDimitry Andric } 397206c3fb27SDimitry Andric 39730b57cec5SDimitry Andric while (Current) { 397404eeddc0SDimitry Andric const FormatToken *Prev = Current->Previous; 39750b57cec5SDimitry Andric if (Current->is(TT_LineComment)) { 397681ad6265SDimitry Andric if (Prev->is(BK_BracedInit) && Prev->opensScope()) { 3977a7dea167SDimitry Andric Current->SpacesRequiredBefore = 397806c3fb27SDimitry Andric (Style.Cpp11BracedListStyle && !Style.SpacesInParensOptions.Other) 397906c3fb27SDimitry Andric ? 0 398006c3fb27SDimitry Andric : 1; 398106c3fb27SDimitry Andric } else if (Prev->is(TT_VerilogMultiLineListLParen)) { 398206c3fb27SDimitry Andric Current->SpacesRequiredBefore = 0; 398381ad6265SDimitry Andric } else { 39840b57cec5SDimitry Andric Current->SpacesRequiredBefore = Style.SpacesBeforeTrailingComments; 398581ad6265SDimitry Andric } 39860b57cec5SDimitry Andric 39870b57cec5SDimitry Andric // If we find a trailing comment, iterate backwards to determine whether 39880b57cec5SDimitry Andric // it seems to relate to a specific parameter. If so, break before that 39890b57cec5SDimitry Andric // parameter to avoid changing the comment's meaning. E.g. don't move 'b' 39900b57cec5SDimitry Andric // to the previous line in: 39910b57cec5SDimitry Andric // SomeFunction(a, 39920b57cec5SDimitry Andric // b, // comment 39930b57cec5SDimitry Andric // c); 39940b57cec5SDimitry Andric if (!Current->HasUnescapedNewline) { 39950b57cec5SDimitry Andric for (FormatToken *Parameter = Current->Previous; Parameter; 39960b57cec5SDimitry Andric Parameter = Parameter->Previous) { 39970b57cec5SDimitry Andric if (Parameter->isOneOf(tok::comment, tok::r_brace)) 39980b57cec5SDimitry Andric break; 39990b57cec5SDimitry Andric if (Parameter->Previous && Parameter->Previous->is(tok::comma)) { 40005f757f3fSDimitry Andric if (Parameter->Previous->isNot(TT_CtorInitializerComma) && 400181ad6265SDimitry Andric Parameter->HasUnescapedNewline) { 40020b57cec5SDimitry Andric Parameter->MustBreakBefore = true; 400381ad6265SDimitry Andric } 40040b57cec5SDimitry Andric break; 40050b57cec5SDimitry Andric } 40060b57cec5SDimitry Andric } 40070b57cec5SDimitry Andric } 40085f757f3fSDimitry Andric } else if (!Current->Finalized && Current->SpacesRequiredBefore == 0 && 40090b57cec5SDimitry Andric spaceRequiredBefore(Line, *Current)) { 40100b57cec5SDimitry Andric Current->SpacesRequiredBefore = 1; 40110b57cec5SDimitry Andric } 40120b57cec5SDimitry Andric 401381ad6265SDimitry Andric const auto &Children = Prev->Children; 401481ad6265SDimitry Andric if (!Children.empty() && Children.back()->Last->is(TT_LineComment)) { 401581ad6265SDimitry Andric Current->MustBreakBefore = true; 401681ad6265SDimitry Andric } else { 40170b57cec5SDimitry Andric Current->MustBreakBefore = 40180b57cec5SDimitry Andric Current->MustBreakBefore || mustBreakBefore(Line, *Current); 40190b57cec5SDimitry Andric if (!Current->MustBreakBefore && InFunctionDecl && 402081ad6265SDimitry Andric Current->is(TT_FunctionDeclarationName)) { 40210b57cec5SDimitry Andric Current->MustBreakBefore = mustBreakForReturnType(Line); 402281ad6265SDimitry Andric } 402381ad6265SDimitry Andric } 40240b57cec5SDimitry Andric 40250b57cec5SDimitry Andric Current->CanBreakBefore = 40260b57cec5SDimitry Andric Current->MustBreakBefore || canBreakBefore(Line, *Current); 40270b57cec5SDimitry Andric unsigned ChildSize = 0; 402804eeddc0SDimitry Andric if (Prev->Children.size() == 1) { 402904eeddc0SDimitry Andric FormatToken &LastOfChild = *Prev->Children[0]->Last; 40300b57cec5SDimitry Andric ChildSize = LastOfChild.isTrailingComment() ? Style.ColumnLimit 40310b57cec5SDimitry Andric : LastOfChild.TotalLength + 1; 40320b57cec5SDimitry Andric } 40330b57cec5SDimitry Andric if (Current->MustBreakBefore || Prev->Children.size() > 1 || 40340b57cec5SDimitry Andric (Prev->Children.size() == 1 && 40350b57cec5SDimitry Andric Prev->Children[0]->First->MustBreakBefore) || 403681ad6265SDimitry Andric Current->IsMultiline) { 40370b57cec5SDimitry Andric Current->TotalLength = Prev->TotalLength + Style.ColumnLimit; 403881ad6265SDimitry Andric } else { 40390b57cec5SDimitry Andric Current->TotalLength = Prev->TotalLength + Current->ColumnWidth + 40400b57cec5SDimitry Andric ChildSize + Current->SpacesRequiredBefore; 404181ad6265SDimitry Andric } 40420b57cec5SDimitry Andric 40430b57cec5SDimitry Andric if (Current->is(TT_CtorInitializerColon)) 40440b57cec5SDimitry Andric InFunctionDecl = false; 40450b57cec5SDimitry Andric 40460b57cec5SDimitry Andric // FIXME: Only calculate this if CanBreakBefore is true once static 40470b57cec5SDimitry Andric // initializers etc. are sorted out. 40480b57cec5SDimitry Andric // FIXME: Move magic numbers to a better place. 40490b57cec5SDimitry Andric 40500b57cec5SDimitry Andric // Reduce penalty for aligning ObjC method arguments using the colon 40510b57cec5SDimitry Andric // alignment as this is the canonical way (still prefer fitting everything 40520b57cec5SDimitry Andric // into one line if possible). Trying to fit a whole expression into one 40530b57cec5SDimitry Andric // line should not force other line breaks (e.g. when ObjC method 40540b57cec5SDimitry Andric // expression is a part of other expression). 40550b57cec5SDimitry Andric Current->SplitPenalty = splitPenalty(Line, *Current, InFunctionDecl); 40560b57cec5SDimitry Andric if (Style.Language == FormatStyle::LK_ObjC && 40570b57cec5SDimitry Andric Current->is(TT_SelectorName) && Current->ParameterIndex > 0) { 40580b57cec5SDimitry Andric if (Current->ParameterIndex == 1) 40590b57cec5SDimitry Andric Current->SplitPenalty += 5 * Current->BindingStrength; 40600b57cec5SDimitry Andric } else { 40610b57cec5SDimitry Andric Current->SplitPenalty += 20 * Current->BindingStrength; 40620b57cec5SDimitry Andric } 40630b57cec5SDimitry Andric 40640b57cec5SDimitry Andric Current = Current->Next; 40650b57cec5SDimitry Andric } 40660b57cec5SDimitry Andric 40670b57cec5SDimitry Andric calculateUnbreakableTailLengths(Line); 40680b57cec5SDimitry Andric unsigned IndentLevel = Line.Level; 4069dfa39133SDimitry Andric for (Current = First; Current; Current = Current->Next) { 40700b57cec5SDimitry Andric if (Current->Role) 40710b57cec5SDimitry Andric Current->Role->precomputeFormattingInfos(Current); 40720b57cec5SDimitry Andric if (Current->MatchingParen && 40734824e7fdSDimitry Andric Current->MatchingParen->opensBlockOrBlockTypeList(Style) && 40744824e7fdSDimitry Andric IndentLevel > 0) { 40750b57cec5SDimitry Andric --IndentLevel; 40760b57cec5SDimitry Andric } 40770b57cec5SDimitry Andric Current->IndentLevel = IndentLevel; 40780b57cec5SDimitry Andric if (Current->opensBlockOrBlockTypeList(Style)) 40790b57cec5SDimitry Andric ++IndentLevel; 40800b57cec5SDimitry Andric } 40810b57cec5SDimitry Andric 40820b57cec5SDimitry Andric LLVM_DEBUG({ printDebugInfo(Line); }); 40830b57cec5SDimitry Andric } 40840b57cec5SDimitry Andric 408581ad6265SDimitry Andric void TokenAnnotator::calculateUnbreakableTailLengths( 408681ad6265SDimitry Andric AnnotatedLine &Line) const { 40870b57cec5SDimitry Andric unsigned UnbreakableTailLength = 0; 40880b57cec5SDimitry Andric FormatToken *Current = Line.Last; 40890b57cec5SDimitry Andric while (Current) { 40900b57cec5SDimitry Andric Current->UnbreakableTailLength = UnbreakableTailLength; 40910b57cec5SDimitry Andric if (Current->CanBreakBefore || 40920b57cec5SDimitry Andric Current->isOneOf(tok::comment, tok::string_literal)) { 40930b57cec5SDimitry Andric UnbreakableTailLength = 0; 40940b57cec5SDimitry Andric } else { 40950b57cec5SDimitry Andric UnbreakableTailLength += 40960b57cec5SDimitry Andric Current->ColumnWidth + Current->SpacesRequiredBefore; 40970b57cec5SDimitry Andric } 40980b57cec5SDimitry Andric Current = Current->Previous; 40990b57cec5SDimitry Andric } 41000b57cec5SDimitry Andric } 41010b57cec5SDimitry Andric 410281ad6265SDimitry Andric void TokenAnnotator::calculateArrayInitializerColumnList( 410381ad6265SDimitry Andric AnnotatedLine &Line) const { 410481ad6265SDimitry Andric if (Line.First == Line.Last) 4105fe6060f1SDimitry Andric return; 4106fe6060f1SDimitry Andric auto *CurrentToken = Line.First; 4107fe6060f1SDimitry Andric CurrentToken->ArrayInitializerLineStart = true; 4108fe6060f1SDimitry Andric unsigned Depth = 0; 410906c3fb27SDimitry Andric while (CurrentToken && CurrentToken != Line.Last) { 4110fe6060f1SDimitry Andric if (CurrentToken->is(tok::l_brace)) { 4111fe6060f1SDimitry Andric CurrentToken->IsArrayInitializer = true; 411206c3fb27SDimitry Andric if (CurrentToken->Next) 4113fe6060f1SDimitry Andric CurrentToken->Next->MustBreakBefore = true; 4114fe6060f1SDimitry Andric CurrentToken = 4115fe6060f1SDimitry Andric calculateInitializerColumnList(Line, CurrentToken->Next, Depth + 1); 4116fe6060f1SDimitry Andric } else { 4117fe6060f1SDimitry Andric CurrentToken = CurrentToken->Next; 4118fe6060f1SDimitry Andric } 4119fe6060f1SDimitry Andric } 4120fe6060f1SDimitry Andric } 4121fe6060f1SDimitry Andric 4122fe6060f1SDimitry Andric FormatToken *TokenAnnotator::calculateInitializerColumnList( 412381ad6265SDimitry Andric AnnotatedLine &Line, FormatToken *CurrentToken, unsigned Depth) const { 412406c3fb27SDimitry Andric while (CurrentToken && CurrentToken != Line.Last) { 4125fe6060f1SDimitry Andric if (CurrentToken->is(tok::l_brace)) 4126fe6060f1SDimitry Andric ++Depth; 4127fe6060f1SDimitry Andric else if (CurrentToken->is(tok::r_brace)) 4128fe6060f1SDimitry Andric --Depth; 4129fe6060f1SDimitry Andric if (Depth == 2 && CurrentToken->isOneOf(tok::l_brace, tok::comma)) { 4130fe6060f1SDimitry Andric CurrentToken = CurrentToken->Next; 413106c3fb27SDimitry Andric if (!CurrentToken) 4132fe6060f1SDimitry Andric break; 4133fe6060f1SDimitry Andric CurrentToken->StartsColumn = true; 4134fe6060f1SDimitry Andric CurrentToken = CurrentToken->Previous; 4135fe6060f1SDimitry Andric } 4136fe6060f1SDimitry Andric CurrentToken = CurrentToken->Next; 4137fe6060f1SDimitry Andric } 4138fe6060f1SDimitry Andric return CurrentToken; 4139fe6060f1SDimitry Andric } 4140fe6060f1SDimitry Andric 41410b57cec5SDimitry Andric unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line, 41420b57cec5SDimitry Andric const FormatToken &Tok, 414381ad6265SDimitry Andric bool InFunctionDecl) const { 41440b57cec5SDimitry Andric const FormatToken &Left = *Tok.Previous; 41450b57cec5SDimitry Andric const FormatToken &Right = Tok; 41460b57cec5SDimitry Andric 41470b57cec5SDimitry Andric if (Left.is(tok::semi)) 41480b57cec5SDimitry Andric return 0; 41490b57cec5SDimitry Andric 4150bdd1243dSDimitry Andric // Language specific handling. 41510b57cec5SDimitry Andric if (Style.Language == FormatStyle::LK_Java) { 41520b57cec5SDimitry Andric if (Right.isOneOf(Keywords.kw_extends, Keywords.kw_throws)) 41530b57cec5SDimitry Andric return 1; 41540b57cec5SDimitry Andric if (Right.is(Keywords.kw_implements)) 41550b57cec5SDimitry Andric return 2; 41560b57cec5SDimitry Andric if (Left.is(tok::comma) && Left.NestingLevel == 0) 41570b57cec5SDimitry Andric return 3; 41580eae32dcSDimitry Andric } else if (Style.isJavaScript()) { 41590b57cec5SDimitry Andric if (Right.is(Keywords.kw_function) && Left.isNot(tok::comma)) 41600b57cec5SDimitry Andric return 100; 41610b57cec5SDimitry Andric if (Left.is(TT_JsTypeColon)) 41620b57cec5SDimitry Andric return 35; 41635f757f3fSDimitry Andric if ((Left.is(TT_TemplateString) && Left.TokenText.ends_with("${")) || 41645f757f3fSDimitry Andric (Right.is(TT_TemplateString) && Right.TokenText.starts_with("}"))) { 41650b57cec5SDimitry Andric return 100; 416681ad6265SDimitry Andric } 41670b57cec5SDimitry Andric // Prefer breaking call chains (".foo") over empty "{}", "[]" or "()". 41680b57cec5SDimitry Andric if (Left.opensScope() && Right.closesScope()) 41690b57cec5SDimitry Andric return 200; 41705f757f3fSDimitry Andric } else if (Style.Language == FormatStyle::LK_Proto) { 4171bdd1243dSDimitry Andric if (Right.is(tok::l_square)) 4172bdd1243dSDimitry Andric return 1; 4173bdd1243dSDimitry Andric if (Right.is(tok::period)) 4174bdd1243dSDimitry Andric return 500; 41750b57cec5SDimitry Andric } 41760b57cec5SDimitry Andric 41770b57cec5SDimitry Andric if (Right.is(tok::identifier) && Right.Next && Right.Next->is(TT_DictLiteral)) 41780b57cec5SDimitry Andric return 1; 41790b57cec5SDimitry Andric if (Right.is(tok::l_square)) { 41800b57cec5SDimitry Andric if (Left.is(tok::r_square)) 41810b57cec5SDimitry Andric return 200; 41820b57cec5SDimitry Andric // Slightly prefer formatting local lambda definitions like functions. 41830b57cec5SDimitry Andric if (Right.is(TT_LambdaLSquare) && Left.is(tok::equal)) 41840b57cec5SDimitry Andric return 35; 41850b57cec5SDimitry Andric if (!Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare, 41860b57cec5SDimitry Andric TT_ArrayInitializerLSquare, 418781ad6265SDimitry Andric TT_DesignatedInitializerLSquare, TT_AttributeSquare)) { 41880b57cec5SDimitry Andric return 500; 41890b57cec5SDimitry Andric } 419081ad6265SDimitry Andric } 41910b57cec5SDimitry Andric 4192bdd1243dSDimitry Andric if (Left.is(tok::coloncolon)) 41937a6dacacSDimitry Andric return Style.PenaltyBreakScopeResolution; 41940b57cec5SDimitry Andric if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName) || 41950b57cec5SDimitry Andric Right.is(tok::kw_operator)) { 41960b57cec5SDimitry Andric if (Line.startsWith(tok::kw_for) && Right.PartOfMultiVariableDeclStmt) 41970b57cec5SDimitry Andric return 3; 41980b57cec5SDimitry Andric if (Left.is(TT_StartOfName)) 41990b57cec5SDimitry Andric return 110; 42000b57cec5SDimitry Andric if (InFunctionDecl && Right.NestingLevel == 0) 42010b57cec5SDimitry Andric return Style.PenaltyReturnTypeOnItsOwnLine; 42020b57cec5SDimitry Andric return 200; 42030b57cec5SDimitry Andric } 42040b57cec5SDimitry Andric if (Right.is(TT_PointerOrReference)) 42050b57cec5SDimitry Andric return 190; 42066c4b055cSDimitry Andric if (Right.is(TT_LambdaArrow)) 42070b57cec5SDimitry Andric return 110; 42080b57cec5SDimitry Andric if (Left.is(tok::equal) && Right.is(tok::l_brace)) 42090b57cec5SDimitry Andric return 160; 42100b57cec5SDimitry Andric if (Left.is(TT_CastRParen)) 42110b57cec5SDimitry Andric return 100; 4212bdd1243dSDimitry Andric if (Left.isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union)) 42130b57cec5SDimitry Andric return 5000; 42140b57cec5SDimitry Andric if (Left.is(tok::comment)) 42150b57cec5SDimitry Andric return 1000; 42160b57cec5SDimitry Andric 42170b57cec5SDimitry Andric if (Left.isOneOf(TT_RangeBasedForLoopColon, TT_InheritanceColon, 421881ad6265SDimitry Andric TT_CtorInitializerColon)) { 42190b57cec5SDimitry Andric return 2; 422081ad6265SDimitry Andric } 42210b57cec5SDimitry Andric 42220b57cec5SDimitry Andric if (Right.isMemberAccess()) { 42230b57cec5SDimitry Andric // Breaking before the "./->" of a chained call/member access is reasonably 42240b57cec5SDimitry Andric // cheap, as formatting those with one call per line is generally 42250b57cec5SDimitry Andric // desirable. In particular, it should be cheaper to break before the call 42260b57cec5SDimitry Andric // than it is to break inside a call's parameters, which could lead to weird 42270b57cec5SDimitry Andric // "hanging" indents. The exception is the very last "./->" to support this 42280b57cec5SDimitry Andric // frequent pattern: 42290b57cec5SDimitry Andric // 42300b57cec5SDimitry Andric // aaaaaaaa.aaaaaaaa.bbbbbbb().ccccccccccccccccccccc( 42310b57cec5SDimitry Andric // dddddddd); 42320b57cec5SDimitry Andric // 42330b57cec5SDimitry Andric // which might otherwise be blown up onto many lines. Here, clang-format 42340b57cec5SDimitry Andric // won't produce "hanging" indents anyway as there is no other trailing 42350b57cec5SDimitry Andric // call. 42360b57cec5SDimitry Andric // 42370b57cec5SDimitry Andric // Also apply higher penalty is not a call as that might lead to a wrapping 42380b57cec5SDimitry Andric // like: 42390b57cec5SDimitry Andric // 42400b57cec5SDimitry Andric // aaaaaaa 42410b57cec5SDimitry Andric // .aaaaaaaaa.bbbbbbbb(cccccccc); 42420b57cec5SDimitry Andric return !Right.NextOperator || !Right.NextOperator->Previous->closesScope() 42430b57cec5SDimitry Andric ? 150 42440b57cec5SDimitry Andric : 35; 42450b57cec5SDimitry Andric } 42460b57cec5SDimitry Andric 42470b57cec5SDimitry Andric if (Right.is(TT_TrailingAnnotation) && 42480b57cec5SDimitry Andric (!Right.Next || Right.Next->isNot(tok::l_paren))) { 42490b57cec5SDimitry Andric // Moving trailing annotations to the next line is fine for ObjC method 42500b57cec5SDimitry Andric // declarations. 42510b57cec5SDimitry Andric if (Line.startsWith(TT_ObjCMethodSpecifier)) 42520b57cec5SDimitry Andric return 10; 42530b57cec5SDimitry Andric // Generally, breaking before a trailing annotation is bad unless it is 42540b57cec5SDimitry Andric // function-like. It seems to be especially preferable to keep standard 42550b57cec5SDimitry Andric // annotations (i.e. "const", "final" and "override") on the same line. 42560b57cec5SDimitry Andric // Use a slightly higher penalty after ")" so that annotations like 42570b57cec5SDimitry Andric // "const override" are kept together. 42580b57cec5SDimitry Andric bool is_short_annotation = Right.TokenText.size() < 10; 42590b57cec5SDimitry Andric return (Left.is(tok::r_paren) ? 100 : 120) + (is_short_annotation ? 50 : 0); 42600b57cec5SDimitry Andric } 42610b57cec5SDimitry Andric 42620b57cec5SDimitry Andric // In for-loops, prefer breaking at ',' and ';'. 42630b57cec5SDimitry Andric if (Line.startsWith(tok::kw_for) && Left.is(tok::equal)) 42640b57cec5SDimitry Andric return 4; 42650b57cec5SDimitry Andric 42660b57cec5SDimitry Andric // In Objective-C method expressions, prefer breaking before "param:" over 42670b57cec5SDimitry Andric // breaking after it. 42680b57cec5SDimitry Andric if (Right.is(TT_SelectorName)) 42690b57cec5SDimitry Andric return 0; 42700b57cec5SDimitry Andric if (Left.is(tok::colon) && Left.is(TT_ObjCMethodExpr)) 42710b57cec5SDimitry Andric return Line.MightBeFunctionDecl ? 50 : 500; 42720b57cec5SDimitry Andric 42730b57cec5SDimitry Andric // In Objective-C type declarations, avoid breaking after the category's 42740b57cec5SDimitry Andric // open paren (we'll prefer breaking after the protocol list's opening 42750b57cec5SDimitry Andric // angle bracket, if present). 42760b57cec5SDimitry Andric if (Line.Type == LT_ObjCDecl && Left.is(tok::l_paren) && Left.Previous && 427781ad6265SDimitry Andric Left.Previous->isOneOf(tok::identifier, tok::greater)) { 42780b57cec5SDimitry Andric return 500; 427981ad6265SDimitry Andric } 42800b57cec5SDimitry Andric 428104eeddc0SDimitry Andric if (Left.is(tok::l_paren) && Style.PenaltyBreakOpenParenthesis != 0) 428204eeddc0SDimitry Andric return Style.PenaltyBreakOpenParenthesis; 42830b57cec5SDimitry Andric if (Left.is(tok::l_paren) && InFunctionDecl && 428481ad6265SDimitry Andric Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign) { 42850b57cec5SDimitry Andric return 100; 428681ad6265SDimitry Andric } 42870b57cec5SDimitry Andric if (Left.is(tok::l_paren) && Left.Previous && 4288bdd1243dSDimitry Andric (Left.Previous->isOneOf(tok::kw_for, tok::kw__Generic) || 4289bdd1243dSDimitry Andric Left.Previous->isIf())) { 42900b57cec5SDimitry Andric return 1000; 429181ad6265SDimitry Andric } 42920b57cec5SDimitry Andric if (Left.is(tok::equal) && InFunctionDecl) 42930b57cec5SDimitry Andric return 110; 42940b57cec5SDimitry Andric if (Right.is(tok::r_brace)) 42950b57cec5SDimitry Andric return 1; 42960b57cec5SDimitry Andric if (Left.is(TT_TemplateOpener)) 42970b57cec5SDimitry Andric return 100; 42980b57cec5SDimitry Andric if (Left.opensScope()) { 4299e8d8bef9SDimitry Andric // If we aren't aligning after opening parens/braces we can always break 4300e8d8bef9SDimitry Andric // here unless the style does not want us to place all arguments on the 4301e8d8bef9SDimitry Andric // next line. 4302e8d8bef9SDimitry Andric if (Style.AlignAfterOpenBracket == FormatStyle::BAS_DontAlign && 430381ad6265SDimitry Andric (Left.ParameterCount <= 1 || Style.AllowAllArgumentsOnNextLine)) { 43040b57cec5SDimitry Andric return 0; 430581ad6265SDimitry Andric } 43060b57cec5SDimitry Andric if (Left.is(tok::l_brace) && !Style.Cpp11BracedListStyle) 43070b57cec5SDimitry Andric return 19; 43080b57cec5SDimitry Andric return Left.ParameterCount > 1 ? Style.PenaltyBreakBeforeFirstCallParameter 43090b57cec5SDimitry Andric : 19; 43100b57cec5SDimitry Andric } 43110b57cec5SDimitry Andric if (Left.is(TT_JavaAnnotation)) 43120b57cec5SDimitry Andric return 50; 43130b57cec5SDimitry Andric 4314a7dea167SDimitry Andric if (Left.is(TT_UnaryOperator)) 4315a7dea167SDimitry Andric return 60; 43160b57cec5SDimitry Andric if (Left.isOneOf(tok::plus, tok::comma) && Left.Previous && 43170b57cec5SDimitry Andric Left.Previous->isLabelString() && 431881ad6265SDimitry Andric (Left.NextOperator || Left.OperatorIndex != 0)) { 43190b57cec5SDimitry Andric return 50; 432081ad6265SDimitry Andric } 43210b57cec5SDimitry Andric if (Right.is(tok::plus) && Left.isLabelString() && 432281ad6265SDimitry Andric (Right.NextOperator || Right.OperatorIndex != 0)) { 43230b57cec5SDimitry Andric return 25; 432481ad6265SDimitry Andric } 43250b57cec5SDimitry Andric if (Left.is(tok::comma)) 43260b57cec5SDimitry Andric return 1; 43270b57cec5SDimitry Andric if (Right.is(tok::lessless) && Left.isLabelString() && 432881ad6265SDimitry Andric (Right.NextOperator || Right.OperatorIndex != 1)) { 43290b57cec5SDimitry Andric return 25; 433081ad6265SDimitry Andric } 43310b57cec5SDimitry Andric if (Right.is(tok::lessless)) { 43320b57cec5SDimitry Andric // Breaking at a << is really cheap. 43335f757f3fSDimitry Andric if (Left.isNot(tok::r_paren) || Right.OperatorIndex > 0) { 43340b57cec5SDimitry Andric // Slightly prefer to break before the first one in log-like statements. 43350b57cec5SDimitry Andric return 2; 433681ad6265SDimitry Andric } 43370b57cec5SDimitry Andric return 1; 43380b57cec5SDimitry Andric } 43390b57cec5SDimitry Andric if (Left.ClosesTemplateDeclaration) 43400b57cec5SDimitry Andric return Style.PenaltyBreakTemplateDeclaration; 434181ad6265SDimitry Andric if (Left.ClosesRequiresClause) 434281ad6265SDimitry Andric return 0; 43430b57cec5SDimitry Andric if (Left.is(TT_ConditionalExpr)) 43440b57cec5SDimitry Andric return prec::Conditional; 43450b57cec5SDimitry Andric prec::Level Level = Left.getPrecedence(); 43460b57cec5SDimitry Andric if (Level == prec::Unknown) 43470b57cec5SDimitry Andric Level = Right.getPrecedence(); 43480b57cec5SDimitry Andric if (Level == prec::Assignment) 43490b57cec5SDimitry Andric return Style.PenaltyBreakAssignment; 43500b57cec5SDimitry Andric if (Level != prec::Unknown) 43510b57cec5SDimitry Andric return Level; 43520b57cec5SDimitry Andric 43530b57cec5SDimitry Andric return 3; 43540b57cec5SDimitry Andric } 43550b57cec5SDimitry Andric 43560b57cec5SDimitry Andric bool TokenAnnotator::spaceRequiredBeforeParens(const FormatToken &Right) const { 435704eeddc0SDimitry Andric if (Style.SpaceBeforeParens == FormatStyle::SBPO_Always) 435804eeddc0SDimitry Andric return true; 435904eeddc0SDimitry Andric if (Right.is(TT_OverloadedOperatorLParen) && 436081ad6265SDimitry Andric Style.SpaceBeforeParensOptions.AfterOverloadedOperator) { 436104eeddc0SDimitry Andric return true; 436281ad6265SDimitry Andric } 436304eeddc0SDimitry Andric if (Style.SpaceBeforeParensOptions.BeforeNonEmptyParentheses && 436481ad6265SDimitry Andric Right.ParameterCount > 0) { 436504eeddc0SDimitry Andric return true; 436681ad6265SDimitry Andric } 436704eeddc0SDimitry Andric return false; 43680b57cec5SDimitry Andric } 43690b57cec5SDimitry Andric 43700b57cec5SDimitry Andric bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, 43710b57cec5SDimitry Andric const FormatToken &Left, 437281ad6265SDimitry Andric const FormatToken &Right) const { 437381ad6265SDimitry Andric if (Left.is(tok::kw_return) && 437481ad6265SDimitry Andric !Right.isOneOf(tok::semi, tok::r_paren, tok::hashhash)) { 43750b57cec5SDimitry Andric return true; 437681ad6265SDimitry Andric } 4377bdd1243dSDimitry Andric if (Left.is(tok::kw_throw) && Right.is(tok::l_paren) && Right.MatchingParen && 4378bdd1243dSDimitry Andric Right.MatchingParen->is(TT_CastRParen)) { 4379bdd1243dSDimitry Andric return true; 4380bdd1243dSDimitry Andric } 43810b57cec5SDimitry Andric if (Left.is(Keywords.kw_assert) && Style.Language == FormatStyle::LK_Java) 43820b57cec5SDimitry Andric return true; 43830b57cec5SDimitry Andric if (Style.ObjCSpaceAfterProperty && Line.Type == LT_ObjCProperty && 438481ad6265SDimitry Andric Left.Tok.getObjCKeywordID() == tok::objc_property) { 43850b57cec5SDimitry Andric return true; 438681ad6265SDimitry Andric } 43870b57cec5SDimitry Andric if (Right.is(tok::hashhash)) 43880b57cec5SDimitry Andric return Left.is(tok::hash); 43890b57cec5SDimitry Andric if (Left.isOneOf(tok::hashhash, tok::hash)) 43900b57cec5SDimitry Andric return Right.is(tok::hash); 43910fca6ea1SDimitry Andric if (Left.is(BK_Block) && Right.is(tok::r_brace) && 43920fca6ea1SDimitry Andric Right.MatchingParen == &Left && Line.Children.empty()) { 43930fca6ea1SDimitry Andric return Style.SpaceInEmptyBlock; 43940fca6ea1SDimitry Andric } 4395a7dea167SDimitry Andric if ((Left.is(tok::l_paren) && Right.is(tok::r_paren)) || 4396e8d8bef9SDimitry Andric (Left.is(tok::l_brace) && Left.isNot(BK_Block) && 439781ad6265SDimitry Andric Right.is(tok::r_brace) && Right.isNot(BK_Block))) { 439806c3fb27SDimitry Andric return Style.SpacesInParensOptions.InEmptyParentheses; 439981ad6265SDimitry Andric } 44000fca6ea1SDimitry Andric if (Style.SpacesInParens == FormatStyle::SIPO_Custom && 44010fca6ea1SDimitry Andric Style.SpacesInParensOptions.ExceptDoubleParentheses && 44020fca6ea1SDimitry Andric Left.is(tok::r_paren) && Right.is(tok::r_paren)) { 44030fca6ea1SDimitry Andric auto *InnerLParen = Left.MatchingParen; 44040fca6ea1SDimitry Andric if (InnerLParen && InnerLParen->Previous == Right.MatchingParen) { 44050fca6ea1SDimitry Andric InnerLParen->SpacesRequiredBefore = 0; 44060fca6ea1SDimitry Andric return false; 44070fca6ea1SDimitry Andric } 44080fca6ea1SDimitry Andric } 440906c3fb27SDimitry Andric if (Style.SpacesInParensOptions.InConditionalStatements) { 441081ad6265SDimitry Andric const FormatToken *LeftParen = nullptr; 441181ad6265SDimitry Andric if (Left.is(tok::l_paren)) 441281ad6265SDimitry Andric LeftParen = &Left; 441381ad6265SDimitry Andric else if (Right.is(tok::r_paren) && Right.MatchingParen) 441481ad6265SDimitry Andric LeftParen = Right.MatchingParen; 441506c3fb27SDimitry Andric if (LeftParen) { 441606c3fb27SDimitry Andric if (LeftParen->is(TT_ConditionLParen)) 441706c3fb27SDimitry Andric return true; 441806c3fb27SDimitry Andric if (LeftParen->Previous && isKeywordWithCondition(*LeftParen->Previous)) 4419480093f4SDimitry Andric return true; 442081ad6265SDimitry Andric } 4421480093f4SDimitry Andric } 4422e8d8bef9SDimitry Andric 4423bdd1243dSDimitry Andric // trailing return type 'auto': []() -> auto {}, auto foo() -> auto {} 4424bdd1243dSDimitry Andric if (Left.is(tok::kw_auto) && Right.isOneOf(TT_LambdaLBrace, TT_FunctionLBrace, 4425bdd1243dSDimitry Andric // function return type 'auto' 4426bdd1243dSDimitry Andric TT_FunctionTypeLParen)) { 4427bdd1243dSDimitry Andric return true; 4428bdd1243dSDimitry Andric } 4429bdd1243dSDimitry Andric 4430349cc55cSDimitry Andric // auto{x} auto(x) 4431349cc55cSDimitry Andric if (Left.is(tok::kw_auto) && Right.isOneOf(tok::l_paren, tok::l_brace)) 4432349cc55cSDimitry Andric return false; 4433349cc55cSDimitry Andric 44340fca6ea1SDimitry Andric const auto *BeforeLeft = Left.Previous; 44350fca6ea1SDimitry Andric 44364824e7fdSDimitry Andric // operator co_await(x) 44370fca6ea1SDimitry Andric if (Right.is(tok::l_paren) && Left.is(tok::kw_co_await) && BeforeLeft && 44380fca6ea1SDimitry Andric BeforeLeft->is(tok::kw_operator)) { 44394824e7fdSDimitry Andric return false; 444081ad6265SDimitry Andric } 44414824e7fdSDimitry Andric // co_await (x), co_yield (x), co_return (x) 44424824e7fdSDimitry Andric if (Left.isOneOf(tok::kw_co_await, tok::kw_co_yield, tok::kw_co_return) && 444381ad6265SDimitry Andric !Right.isOneOf(tok::semi, tok::r_paren)) { 44444824e7fdSDimitry Andric return true; 444581ad6265SDimitry Andric } 4446e8d8bef9SDimitry Andric 444781ad6265SDimitry Andric if (Left.is(tok::l_paren) || Right.is(tok::r_paren)) { 44480b57cec5SDimitry Andric return (Right.is(TT_CastRParen) || 44490b57cec5SDimitry Andric (Left.MatchingParen && Left.MatchingParen->is(TT_CastRParen))) 445006c3fb27SDimitry Andric ? Style.SpacesInParensOptions.InCStyleCasts 445106c3fb27SDimitry Andric : Style.SpacesInParensOptions.Other; 445281ad6265SDimitry Andric } 44530b57cec5SDimitry Andric if (Right.isOneOf(tok::semi, tok::comma)) 44540b57cec5SDimitry Andric return false; 44550b57cec5SDimitry Andric if (Right.is(tok::less) && Line.Type == LT_ObjCDecl) { 44560b57cec5SDimitry Andric bool IsLightweightGeneric = Right.MatchingParen && 44570b57cec5SDimitry Andric Right.MatchingParen->Next && 44580b57cec5SDimitry Andric Right.MatchingParen->Next->is(tok::colon); 44590b57cec5SDimitry Andric return !IsLightweightGeneric && Style.ObjCSpaceBeforeProtocolList; 44600b57cec5SDimitry Andric } 44610b57cec5SDimitry Andric if (Right.is(tok::less) && Left.is(tok::kw_template)) 44620b57cec5SDimitry Andric return Style.SpaceAfterTemplateKeyword; 44630b57cec5SDimitry Andric if (Left.isOneOf(tok::exclaim, tok::tilde)) 44640b57cec5SDimitry Andric return false; 44650b57cec5SDimitry Andric if (Left.is(tok::at) && 44660b57cec5SDimitry Andric Right.isOneOf(tok::identifier, tok::string_literal, tok::char_constant, 44670b57cec5SDimitry Andric tok::numeric_constant, tok::l_paren, tok::l_brace, 446881ad6265SDimitry Andric tok::kw_true, tok::kw_false)) { 44690b57cec5SDimitry Andric return false; 447081ad6265SDimitry Andric } 44710b57cec5SDimitry Andric if (Left.is(tok::colon)) 44725f757f3fSDimitry Andric return Left.isNot(TT_ObjCMethodExpr); 44736c4b055cSDimitry Andric if (Left.is(tok::coloncolon)) 44746c4b055cSDimitry Andric return false; 44750b57cec5SDimitry Andric if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less)) { 44760b57cec5SDimitry Andric if (Style.Language == FormatStyle::LK_TextProto || 44770b57cec5SDimitry Andric (Style.Language == FormatStyle::LK_Proto && 44780b57cec5SDimitry Andric (Left.is(TT_DictLiteral) || Right.is(TT_DictLiteral)))) { 44790b57cec5SDimitry Andric // Format empty list as `<>`. 44800b57cec5SDimitry Andric if (Left.is(tok::less) && Right.is(tok::greater)) 44810b57cec5SDimitry Andric return false; 44820b57cec5SDimitry Andric return !Style.Cpp11BracedListStyle; 44830b57cec5SDimitry Andric } 4484bdd1243dSDimitry Andric // Don't attempt to format operator<(), as it is handled later. 4485bdd1243dSDimitry Andric if (Right.isNot(TT_OverloadedOperatorLParen)) 44860b57cec5SDimitry Andric return false; 44870b57cec5SDimitry Andric } 448881ad6265SDimitry Andric if (Right.is(tok::ellipsis)) { 44890fca6ea1SDimitry Andric return Left.Tok.isLiteral() || (Left.is(tok::identifier) && BeforeLeft && 44900fca6ea1SDimitry Andric BeforeLeft->is(tok::kw_case)); 449181ad6265SDimitry Andric } 44920b57cec5SDimitry Andric if (Left.is(tok::l_square) && Right.is(tok::amp)) 4493480093f4SDimitry Andric return Style.SpacesInSquareBrackets; 44940b57cec5SDimitry Andric if (Right.is(TT_PointerOrReference)) { 44950b57cec5SDimitry Andric if (Left.is(tok::r_paren) && Line.MightBeFunctionDecl) { 44960b57cec5SDimitry Andric if (!Left.MatchingParen) 44970b57cec5SDimitry Andric return true; 44980b57cec5SDimitry Andric FormatToken *TokenBeforeMatchingParen = 44990b57cec5SDimitry Andric Left.MatchingParen->getPreviousNonComment(); 45005f757f3fSDimitry Andric if (!TokenBeforeMatchingParen || Left.isNot(TT_TypeDeclarationParen)) 45010b57cec5SDimitry Andric return true; 45020b57cec5SDimitry Andric } 4503349cc55cSDimitry Andric // Add a space if the previous token is a pointer qualifier or the closing 4504e8d8bef9SDimitry Andric // parenthesis of __attribute__(()) expression and the style requires spaces 4505e8d8bef9SDimitry Andric // after pointer qualifiers. 4506e8d8bef9SDimitry Andric if ((Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_After || 4507e8d8bef9SDimitry Andric Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both) && 45085f757f3fSDimitry Andric (Left.is(TT_AttributeRParen) || 450981ad6265SDimitry Andric Left.canBePointerOrReferenceQualifier())) { 4510e8d8bef9SDimitry Andric return true; 451181ad6265SDimitry Andric } 45120eae32dcSDimitry Andric if (Left.Tok.isLiteral()) 45130eae32dcSDimitry Andric return true; 45140eae32dcSDimitry Andric // for (auto a = 0, b = 0; const auto & c : {1, 2, 3}) 45150fca6ea1SDimitry Andric if (Left.isTypeOrIdentifier(LangOpts) && Right.Next && Right.Next->Next && 451681ad6265SDimitry Andric Right.Next->Next->is(TT_RangeBasedForLoopColon)) { 45170eae32dcSDimitry Andric return getTokenPointerOrReferenceAlignment(Right) != 45180eae32dcSDimitry Andric FormatStyle::PAS_Left; 451981ad6265SDimitry Andric } 452081ad6265SDimitry Andric return !Left.isOneOf(TT_PointerOrReference, tok::l_paren) && 452181ad6265SDimitry Andric (getTokenPointerOrReferenceAlignment(Right) != 452281ad6265SDimitry Andric FormatStyle::PAS_Left || 45230b57cec5SDimitry Andric (Line.IsMultiVariableDeclStmt && 45240b57cec5SDimitry Andric (Left.NestingLevel == 0 || 452581ad6265SDimitry Andric (Left.NestingLevel == 1 && startsWithInitStatement(Line))))); 45260b57cec5SDimitry Andric } 45270b57cec5SDimitry Andric if (Right.is(TT_FunctionTypeLParen) && Left.isNot(tok::l_paren) && 45285f757f3fSDimitry Andric (Left.isNot(TT_PointerOrReference) || 4529fe6060f1SDimitry Andric (getTokenPointerOrReferenceAlignment(Left) != FormatStyle::PAS_Right && 453081ad6265SDimitry Andric !Line.IsMultiVariableDeclStmt))) { 45310b57cec5SDimitry Andric return true; 453281ad6265SDimitry Andric } 4533e8d8bef9SDimitry Andric if (Left.is(TT_PointerOrReference)) { 4534349cc55cSDimitry Andric // Add a space if the next token is a pointer qualifier and the style 4535e8d8bef9SDimitry Andric // requires spaces before pointer qualifiers. 4536e8d8bef9SDimitry Andric if ((Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Before || 4537e8d8bef9SDimitry Andric Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both) && 453881ad6265SDimitry Andric Right.canBePointerOrReferenceQualifier()) { 4539e8d8bef9SDimitry Andric return true; 454081ad6265SDimitry Andric } 45410eae32dcSDimitry Andric // & 1 45420eae32dcSDimitry Andric if (Right.Tok.isLiteral()) 45430eae32dcSDimitry Andric return true; 45440eae32dcSDimitry Andric // & /* comment 45450eae32dcSDimitry Andric if (Right.is(TT_BlockComment)) 45460eae32dcSDimitry Andric return true; 45470eae32dcSDimitry Andric // foo() -> const Bar * override/final 454806c3fb27SDimitry Andric // S::foo() & noexcept/requires 454906c3fb27SDimitry Andric if (Right.isOneOf(Keywords.kw_override, Keywords.kw_final, tok::kw_noexcept, 455006c3fb27SDimitry Andric TT_RequiresClause) && 45515f757f3fSDimitry Andric Right.isNot(TT_StartOfName)) { 45520eae32dcSDimitry Andric return true; 455381ad6265SDimitry Andric } 45540eae32dcSDimitry Andric // & { 45550eae32dcSDimitry Andric if (Right.is(tok::l_brace) && Right.is(BK_Block)) 45560eae32dcSDimitry Andric return true; 45570eae32dcSDimitry Andric // for (auto a = 0, b = 0; const auto& c : {1, 2, 3}) 45580fca6ea1SDimitry Andric if (BeforeLeft && BeforeLeft->isTypeOrIdentifier(LangOpts) && Right.Next && 455981ad6265SDimitry Andric Right.Next->is(TT_RangeBasedForLoopColon)) { 45600eae32dcSDimitry Andric return getTokenPointerOrReferenceAlignment(Left) != 45610eae32dcSDimitry Andric FormatStyle::PAS_Right; 456281ad6265SDimitry Andric } 456381ad6265SDimitry Andric if (Right.isOneOf(TT_PointerOrReference, TT_ArraySubscriptLSquare, 456481ad6265SDimitry Andric tok::l_paren)) { 456581ad6265SDimitry Andric return false; 456681ad6265SDimitry Andric } 456781ad6265SDimitry Andric if (getTokenPointerOrReferenceAlignment(Left) == FormatStyle::PAS_Right) 456881ad6265SDimitry Andric return false; 456981ad6265SDimitry Andric // FIXME: Setting IsMultiVariableDeclStmt for the whole line is error-prone, 457081ad6265SDimitry Andric // because it does not take into account nested scopes like lambdas. 457181ad6265SDimitry Andric // In multi-variable declaration statements, attach */& to the variable 457281ad6265SDimitry Andric // independently of the style. However, avoid doing it if we are in a nested 457381ad6265SDimitry Andric // scope, e.g. lambda. We still need to special-case statements with 457481ad6265SDimitry Andric // initializers. 457581ad6265SDimitry Andric if (Line.IsMultiVariableDeclStmt && 457681ad6265SDimitry Andric (Left.NestingLevel == Line.First->NestingLevel || 457781ad6265SDimitry Andric ((Left.NestingLevel == Line.First->NestingLevel + 1) && 457881ad6265SDimitry Andric startsWithInitStatement(Line)))) { 457981ad6265SDimitry Andric return false; 458081ad6265SDimitry Andric } 45810fca6ea1SDimitry Andric if (!BeforeLeft) 45820fca6ea1SDimitry Andric return false; 45830fca6ea1SDimitry Andric if (BeforeLeft->is(tok::coloncolon)) { 45846c4b055cSDimitry Andric if (Left.isNot(tok::star)) 45856c4b055cSDimitry Andric return false; 45866c4b055cSDimitry Andric assert(Style.PointerAlignment != FormatStyle::PAS_Right); 45876c4b055cSDimitry Andric if (!Right.startsSequence(tok::identifier, tok::r_paren)) 45886c4b055cSDimitry Andric return true; 45896c4b055cSDimitry Andric assert(Right.Next); 45906c4b055cSDimitry Andric const auto *LParen = Right.Next->MatchingParen; 45916c4b055cSDimitry Andric return !LParen || LParen->isNot(TT_FunctionTypeLParen); 45920fca6ea1SDimitry Andric } 45930fca6ea1SDimitry Andric return !BeforeLeft->isOneOf(tok::l_paren, tok::l_square); 4594e8d8bef9SDimitry Andric } 4595349cc55cSDimitry Andric // Ensure right pointer alignment with ellipsis e.g. int *...P 45960fca6ea1SDimitry Andric if (Left.is(tok::ellipsis) && BeforeLeft && 45970fca6ea1SDimitry Andric BeforeLeft->isPointerOrReference()) { 45985ffd83dbSDimitry Andric return Style.PointerAlignment != FormatStyle::PAS_Right; 459981ad6265SDimitry Andric } 46005ffd83dbSDimitry Andric 46010b57cec5SDimitry Andric if (Right.is(tok::star) && Left.is(tok::l_paren)) 46020b57cec5SDimitry Andric return false; 46035f757f3fSDimitry Andric if (Left.is(tok::star) && Right.isPointerOrReference()) 4604d65cd7a5SDimitry Andric return false; 46055f757f3fSDimitry Andric if (Right.isPointerOrReference()) { 4606d65cd7a5SDimitry Andric const FormatToken *Previous = &Left; 46075f757f3fSDimitry Andric while (Previous && Previous->isNot(tok::kw_operator)) { 46080fca6ea1SDimitry Andric if (Previous->is(tok::identifier) || Previous->isTypeName(LangOpts)) { 4609d65cd7a5SDimitry Andric Previous = Previous->getPreviousNonComment(); 4610d65cd7a5SDimitry Andric continue; 4611d65cd7a5SDimitry Andric } 4612d65cd7a5SDimitry Andric if (Previous->is(TT_TemplateCloser) && Previous->MatchingParen) { 4613d65cd7a5SDimitry Andric Previous = Previous->MatchingParen->getPreviousNonComment(); 4614d65cd7a5SDimitry Andric continue; 4615d65cd7a5SDimitry Andric } 4616d65cd7a5SDimitry Andric if (Previous->is(tok::coloncolon)) { 4617d65cd7a5SDimitry Andric Previous = Previous->getPreviousNonComment(); 4618d65cd7a5SDimitry Andric continue; 4619d65cd7a5SDimitry Andric } 4620d65cd7a5SDimitry Andric break; 4621d65cd7a5SDimitry Andric } 46228c27c554SDimitry Andric // Space between the type and the * in: 46238c27c554SDimitry Andric // operator void*() 46248c27c554SDimitry Andric // operator char*() 4625fe6060f1SDimitry Andric // operator void const*() 4626fe6060f1SDimitry Andric // operator void volatile*() 46278c27c554SDimitry Andric // operator /*comment*/ const char*() 46288c27c554SDimitry Andric // operator volatile /*comment*/ char*() 46298c27c554SDimitry Andric // operator Foo*() 4630d65cd7a5SDimitry Andric // operator C<T>*() 4631d65cd7a5SDimitry Andric // operator std::Foo*() 4632d65cd7a5SDimitry Andric // operator C<T>::D<U>*() 46338c27c554SDimitry Andric // dependent on PointerAlignment style. 4634fe6060f1SDimitry Andric if (Previous) { 4635fe6060f1SDimitry Andric if (Previous->endsSequence(tok::kw_operator)) 463681ad6265SDimitry Andric return Style.PointerAlignment != FormatStyle::PAS_Left; 463781ad6265SDimitry Andric if (Previous->is(tok::kw_const) || Previous->is(tok::kw_volatile)) { 4638fe6060f1SDimitry Andric return (Style.PointerAlignment != FormatStyle::PAS_Left) || 4639fe6060f1SDimitry Andric (Style.SpaceAroundPointerQualifiers == 4640fe6060f1SDimitry Andric FormatStyle::SAPQ_After) || 4641fe6060f1SDimitry Andric (Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both); 4642fe6060f1SDimitry Andric } 4643d65cd7a5SDimitry Andric } 464481ad6265SDimitry Andric } 464506c3fb27SDimitry Andric if (Style.isCSharp() && Left.is(Keywords.kw_is) && Right.is(tok::l_square)) 464606c3fb27SDimitry Andric return true; 46470b57cec5SDimitry Andric const auto SpaceRequiredForArrayInitializerLSquare = 46480b57cec5SDimitry Andric [](const FormatToken &LSquareTok, const FormatStyle &Style) { 46490b57cec5SDimitry Andric return Style.SpacesInContainerLiterals || 46505f757f3fSDimitry Andric (Style.isProto() && !Style.Cpp11BracedListStyle && 46510b57cec5SDimitry Andric LSquareTok.endsSequence(tok::l_square, tok::colon, 46520b57cec5SDimitry Andric TT_SelectorName)); 46530b57cec5SDimitry Andric }; 465481ad6265SDimitry Andric if (Left.is(tok::l_square)) { 46550b57cec5SDimitry Andric return (Left.is(TT_ArrayInitializerLSquare) && Right.isNot(tok::r_square) && 46560b57cec5SDimitry Andric SpaceRequiredForArrayInitializerLSquare(Left, Style)) || 4657a7dea167SDimitry Andric (Left.isOneOf(TT_ArraySubscriptLSquare, TT_StructuredBindingLSquare, 4658a7dea167SDimitry Andric TT_LambdaLSquare) && 46590b57cec5SDimitry Andric Style.SpacesInSquareBrackets && Right.isNot(tok::r_square)); 466081ad6265SDimitry Andric } 466181ad6265SDimitry Andric if (Right.is(tok::r_square)) { 46620b57cec5SDimitry Andric return Right.MatchingParen && 46630b57cec5SDimitry Andric ((Right.MatchingParen->is(TT_ArrayInitializerLSquare) && 46640b57cec5SDimitry Andric SpaceRequiredForArrayInitializerLSquare(*Right.MatchingParen, 46650b57cec5SDimitry Andric Style)) || 46660b57cec5SDimitry Andric (Style.SpacesInSquareBrackets && 46670b57cec5SDimitry Andric Right.MatchingParen->isOneOf(TT_ArraySubscriptLSquare, 4668a7dea167SDimitry Andric TT_StructuredBindingLSquare, 46695f757f3fSDimitry Andric TT_LambdaLSquare))); 467081ad6265SDimitry Andric } 46710b57cec5SDimitry Andric if (Right.is(tok::l_square) && 46720b57cec5SDimitry Andric !Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare, 46730b57cec5SDimitry Andric TT_DesignatedInitializerLSquare, 46740b57cec5SDimitry Andric TT_StructuredBindingLSquare, TT_AttributeSquare) && 4675480093f4SDimitry Andric !Left.isOneOf(tok::numeric_constant, TT_DictLiteral) && 46765f757f3fSDimitry Andric !(Left.isNot(tok::r_square) && Style.SpaceBeforeSquareBrackets && 467781ad6265SDimitry Andric Right.is(TT_ArraySubscriptLSquare))) { 46780b57cec5SDimitry Andric return false; 467981ad6265SDimitry Andric } 46800b57cec5SDimitry Andric if (Left.is(tok::l_brace) && Right.is(tok::r_brace)) 46810b57cec5SDimitry Andric return !Left.Children.empty(); // No spaces in "{}". 4682e8d8bef9SDimitry Andric if ((Left.is(tok::l_brace) && Left.isNot(BK_Block)) || 46830b57cec5SDimitry Andric (Right.is(tok::r_brace) && Right.MatchingParen && 468481ad6265SDimitry Andric Right.MatchingParen->isNot(BK_Block))) { 46855f757f3fSDimitry Andric return !Style.Cpp11BracedListStyle || Style.SpacesInParensOptions.Other; 468681ad6265SDimitry Andric } 468781ad6265SDimitry Andric if (Left.is(TT_BlockComment)) { 46880b57cec5SDimitry Andric // No whitespace in x(/*foo=*/1), except for JavaScript. 46895f757f3fSDimitry Andric return Style.isJavaScript() || !Left.TokenText.ends_with("=*/"); 469081ad6265SDimitry Andric } 46915ffd83dbSDimitry Andric 46925ffd83dbSDimitry Andric // Space between template and attribute. 46935ffd83dbSDimitry Andric // e.g. template <typename T> [[nodiscard]] ... 46945ffd83dbSDimitry Andric if (Left.is(TT_TemplateCloser) && Right.is(TT_AttributeSquare)) 46955ffd83dbSDimitry Andric return true; 4696349cc55cSDimitry Andric // Space before parentheses common for all languages 46970b57cec5SDimitry Andric if (Right.is(tok::l_paren)) { 4698349cc55cSDimitry Andric if (Left.is(TT_TemplateCloser) && Right.isNot(TT_FunctionTypeLParen)) 4699349cc55cSDimitry Andric return spaceRequiredBeforeParens(Right); 470081ad6265SDimitry Andric if (Left.isOneOf(TT_RequiresClause, 470181ad6265SDimitry Andric TT_RequiresClauseInARequiresExpression)) { 470281ad6265SDimitry Andric return Style.SpaceBeforeParensOptions.AfterRequiresInClause || 470381ad6265SDimitry Andric spaceRequiredBeforeParens(Right); 470481ad6265SDimitry Andric } 470581ad6265SDimitry Andric if (Left.is(TT_RequiresExpression)) { 470681ad6265SDimitry Andric return Style.SpaceBeforeParensOptions.AfterRequiresInExpression || 470781ad6265SDimitry Andric spaceRequiredBeforeParens(Right); 470881ad6265SDimitry Andric } 47095f757f3fSDimitry Andric if (Left.is(TT_AttributeRParen) || 471081ad6265SDimitry Andric (Left.is(tok::r_square) && Left.is(TT_AttributeSquare))) { 47110b57cec5SDimitry Andric return true; 471281ad6265SDimitry Andric } 471381ad6265SDimitry Andric if (Left.is(TT_ForEachMacro)) { 471481ad6265SDimitry Andric return Style.SpaceBeforeParensOptions.AfterForeachMacros || 471581ad6265SDimitry Andric spaceRequiredBeforeParens(Right); 471681ad6265SDimitry Andric } 471781ad6265SDimitry Andric if (Left.is(TT_IfMacro)) { 471881ad6265SDimitry Andric return Style.SpaceBeforeParensOptions.AfterIfMacros || 471981ad6265SDimitry Andric spaceRequiredBeforeParens(Right); 472081ad6265SDimitry Andric } 47215f757f3fSDimitry Andric if (Style.SpaceBeforeParens == FormatStyle::SBPO_Custom && 47225f757f3fSDimitry Andric Left.isOneOf(tok::kw_new, tok::kw_delete) && 47235f757f3fSDimitry Andric Right.isNot(TT_OverloadedOperatorLParen) && 47245f757f3fSDimitry Andric !(Line.MightBeFunctionDecl && Left.is(TT_FunctionDeclarationName))) { 4725b3edf446SDimitry Andric return Style.SpaceBeforeParensOptions.AfterPlacementOperator; 47265f757f3fSDimitry Andric } 4727349cc55cSDimitry Andric if (Line.Type == LT_ObjCDecl) 4728349cc55cSDimitry Andric return true; 4729349cc55cSDimitry Andric if (Left.is(tok::semi)) 4730349cc55cSDimitry Andric return true; 4731349cc55cSDimitry Andric if (Left.isOneOf(tok::pp_elif, tok::kw_for, tok::kw_while, tok::kw_switch, 473281ad6265SDimitry Andric tok::kw_case, TT_ForEachMacro, TT_ObjCForIn) || 4733bdd1243dSDimitry Andric Left.isIf(Line.Type != LT_PreprocessorDirective) || 4734bdd1243dSDimitry Andric Right.is(TT_ConditionLParen)) { 4735349cc55cSDimitry Andric return Style.SpaceBeforeParensOptions.AfterControlStatements || 4736349cc55cSDimitry Andric spaceRequiredBeforeParens(Right); 473781ad6265SDimitry Andric } 47384824e7fdSDimitry Andric 47394824e7fdSDimitry Andric // TODO add Operator overloading specific Options to 47404824e7fdSDimitry Andric // SpaceBeforeParensOptions 47414824e7fdSDimitry Andric if (Right.is(TT_OverloadedOperatorLParen)) 47424824e7fdSDimitry Andric return spaceRequiredBeforeParens(Right); 4743349cc55cSDimitry Andric // Function declaration or definition 47440fca6ea1SDimitry Andric if (Line.MightBeFunctionDecl && Right.is(TT_FunctionDeclarationLParen)) { 47450fca6ea1SDimitry Andric if (spaceRequiredBeforeParens(Right)) 47460fca6ea1SDimitry Andric return true; 47470fca6ea1SDimitry Andric const auto &Options = Style.SpaceBeforeParensOptions; 47480fca6ea1SDimitry Andric return Line.mightBeFunctionDefinition() 47490fca6ea1SDimitry Andric ? Options.AfterFunctionDefinitionName 47500fca6ea1SDimitry Andric : Options.AfterFunctionDeclarationName; 475181ad6265SDimitry Andric } 4752349cc55cSDimitry Andric // Lambda 4753349cc55cSDimitry Andric if (Line.Type != LT_PreprocessorDirective && Left.is(tok::r_square) && 475481ad6265SDimitry Andric Left.MatchingParen && Left.MatchingParen->is(TT_LambdaLSquare)) { 4755349cc55cSDimitry Andric return Style.SpaceBeforeParensOptions.AfterFunctionDefinitionName || 4756349cc55cSDimitry Andric spaceRequiredBeforeParens(Right); 475781ad6265SDimitry Andric } 47580fca6ea1SDimitry Andric if (!BeforeLeft || !BeforeLeft->isOneOf(tok::period, tok::arrow)) { 475981ad6265SDimitry Andric if (Left.isOneOf(tok::kw_try, Keywords.kw___except, tok::kw_catch)) { 4760349cc55cSDimitry Andric return Style.SpaceBeforeParensOptions.AfterControlStatements || 4761349cc55cSDimitry Andric spaceRequiredBeforeParens(Right); 476281ad6265SDimitry Andric } 476381ad6265SDimitry Andric if (Left.isOneOf(tok::kw_new, tok::kw_delete)) { 47640fca6ea1SDimitry Andric return ((!Line.MightBeFunctionDecl || !BeforeLeft) && 476581ad6265SDimitry Andric Style.SpaceBeforeParens != FormatStyle::SBPO_Never) || 4766349cc55cSDimitry Andric spaceRequiredBeforeParens(Right); 4767349cc55cSDimitry Andric } 476881ad6265SDimitry Andric 476981ad6265SDimitry Andric if (Left.is(tok::r_square) && Left.MatchingParen && 477081ad6265SDimitry Andric Left.MatchingParen->Previous && 477181ad6265SDimitry Andric Left.MatchingParen->Previous->is(tok::kw_delete)) { 477281ad6265SDimitry Andric return (Style.SpaceBeforeParens != FormatStyle::SBPO_Never) || 477381ad6265SDimitry Andric spaceRequiredBeforeParens(Right); 477481ad6265SDimitry Andric } 477581ad6265SDimitry Andric } 477681ad6265SDimitry Andric // Handle builtins like identifiers. 4777349cc55cSDimitry Andric if (Line.Type != LT_PreprocessorDirective && 477881ad6265SDimitry Andric (Left.Tok.getIdentifierInfo() || Left.is(tok::r_paren))) { 4779349cc55cSDimitry Andric return spaceRequiredBeforeParens(Right); 478081ad6265SDimitry Andric } 4781349cc55cSDimitry Andric return false; 47820b57cec5SDimitry Andric } 47830b57cec5SDimitry Andric if (Left.is(tok::at) && Right.Tok.getObjCKeywordID() != tok::objc_not_keyword) 47840b57cec5SDimitry Andric return false; 478581ad6265SDimitry Andric if (Right.is(TT_UnaryOperator)) { 47860b57cec5SDimitry Andric return !Left.isOneOf(tok::l_paren, tok::l_square, tok::at) && 47870b57cec5SDimitry Andric (Left.isNot(tok::colon) || Left.isNot(TT_ObjCMethodExpr)); 478881ad6265SDimitry Andric } 478906c3fb27SDimitry Andric // No space between the variable name and the initializer list. 479006c3fb27SDimitry Andric // A a1{1}; 479106c3fb27SDimitry Andric // Verilog doesn't have such syntax, but it has word operators that are C++ 479206c3fb27SDimitry Andric // identifiers like `a inside {b, c}`. So the rule is not applicable. 479306c3fb27SDimitry Andric if (!Style.isVerilog() && 479406c3fb27SDimitry Andric (Left.isOneOf(tok::identifier, tok::greater, tok::r_square, 47950b57cec5SDimitry Andric tok::r_paren) || 47960fca6ea1SDimitry Andric Left.isTypeName(LangOpts)) && 47970b57cec5SDimitry Andric Right.is(tok::l_brace) && Right.getNextNonComment() && 479881ad6265SDimitry Andric Right.isNot(BK_Block)) { 47990b57cec5SDimitry Andric return false; 480081ad6265SDimitry Andric } 48010b57cec5SDimitry Andric if (Left.is(tok::period) || Right.is(tok::period)) 48020b57cec5SDimitry Andric return false; 48030eae32dcSDimitry Andric // u#str, U#str, L#str, u8#str 48040eae32dcSDimitry Andric // uR#str, UR#str, LR#str, u8R#str 48050eae32dcSDimitry Andric if (Right.is(tok::hash) && Left.is(tok::identifier) && 48060eae32dcSDimitry Andric (Left.TokenText == "L" || Left.TokenText == "u" || 48070eae32dcSDimitry Andric Left.TokenText == "U" || Left.TokenText == "u8" || 48080eae32dcSDimitry Andric Left.TokenText == "LR" || Left.TokenText == "uR" || 480981ad6265SDimitry Andric Left.TokenText == "UR" || Left.TokenText == "u8R")) { 48100b57cec5SDimitry Andric return false; 481181ad6265SDimitry Andric } 48120b57cec5SDimitry Andric if (Left.is(TT_TemplateCloser) && Left.MatchingParen && 48130b57cec5SDimitry Andric Left.MatchingParen->Previous && 48140b57cec5SDimitry Andric (Left.MatchingParen->Previous->is(tok::period) || 481581ad6265SDimitry Andric Left.MatchingParen->Previous->is(tok::coloncolon))) { 48160b57cec5SDimitry Andric // Java call to generic function with explicit type: 48170b57cec5SDimitry Andric // A.<B<C<...>>>DoSomething(); 48180b57cec5SDimitry Andric // A::<B<C<...>>>DoSomething(); // With a Java 8 method reference. 48190b57cec5SDimitry Andric return false; 482081ad6265SDimitry Andric } 48210b57cec5SDimitry Andric if (Left.is(TT_TemplateCloser) && Right.is(tok::l_square)) 48220b57cec5SDimitry Andric return false; 482381ad6265SDimitry Andric if (Left.is(tok::l_brace) && Left.endsSequence(TT_DictLiteral, tok::at)) { 48240b57cec5SDimitry Andric // Objective-C dictionary literal -> no space after opening brace. 48250b57cec5SDimitry Andric return false; 482681ad6265SDimitry Andric } 48270b57cec5SDimitry Andric if (Right.is(tok::r_brace) && Right.MatchingParen && 482881ad6265SDimitry Andric Right.MatchingParen->endsSequence(TT_DictLiteral, tok::at)) { 48290b57cec5SDimitry Andric // Objective-C dictionary literal -> no space before closing brace. 48300b57cec5SDimitry Andric return false; 483181ad6265SDimitry Andric } 48320fca6ea1SDimitry Andric if (Right.is(TT_TrailingAnnotation) && Right.isOneOf(tok::amp, tok::ampamp) && 4833a7dea167SDimitry Andric Left.isOneOf(tok::kw_const, tok::kw_volatile) && 483481ad6265SDimitry Andric (!Right.Next || Right.Next->is(tok::semi))) { 4835a7dea167SDimitry Andric // Match const and volatile ref-qualifiers without any additional 4836a7dea167SDimitry Andric // qualifiers such as 4837a7dea167SDimitry Andric // void Fn() const &; 4838fe6060f1SDimitry Andric return getTokenReferenceAlignment(Right) != FormatStyle::PAS_Left; 483981ad6265SDimitry Andric } 4840349cc55cSDimitry Andric 48410b57cec5SDimitry Andric return true; 48420b57cec5SDimitry Andric } 48430b57cec5SDimitry Andric 48440b57cec5SDimitry Andric bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, 484581ad6265SDimitry Andric const FormatToken &Right) const { 48460b57cec5SDimitry Andric const FormatToken &Left = *Right.Previous; 484704eeddc0SDimitry Andric 484804eeddc0SDimitry Andric // If the token is finalized don't touch it (as it could be in a 484904eeddc0SDimitry Andric // clang-format-off section). 485004eeddc0SDimitry Andric if (Left.Finalized) 485104eeddc0SDimitry Andric return Right.hasWhitespaceBefore(); 48524824e7fdSDimitry Andric 48530fca6ea1SDimitry Andric const bool IsVerilog = Style.isVerilog(); 48540fca6ea1SDimitry Andric assert(!IsVerilog || !IsCpp); 48550fca6ea1SDimitry Andric 485681ad6265SDimitry Andric // Never ever merge two words. 48570fca6ea1SDimitry Andric if (Keywords.isWordLike(Right, IsVerilog) && 48580fca6ea1SDimitry Andric Keywords.isWordLike(Left, IsVerilog)) { 485981ad6265SDimitry Andric return true; 48600fca6ea1SDimitry Andric } 48614824e7fdSDimitry Andric 48624824e7fdSDimitry Andric // Leave a space between * and /* to avoid C4138 `comment end` found outside 48634824e7fdSDimitry Andric // of comment. 48644824e7fdSDimitry Andric if (Left.is(tok::star) && Right.is(tok::comment)) 48654824e7fdSDimitry Andric return true; 48664824e7fdSDimitry Andric 48670fca6ea1SDimitry Andric if (IsCpp) { 486806c3fb27SDimitry Andric if (Left.is(TT_OverloadedOperator) && 486906c3fb27SDimitry Andric Right.isOneOf(TT_TemplateOpener, TT_TemplateCloser)) { 487006c3fb27SDimitry Andric return true; 487106c3fb27SDimitry Andric } 48721ac55f4cSDimitry Andric // Space between UDL and dot: auto b = 4s .count(); 48731ac55f4cSDimitry Andric if (Right.is(tok::period) && Left.is(tok::numeric_constant)) 48741ac55f4cSDimitry Andric return true; 48754824e7fdSDimitry Andric // Space between import <iostream>. 48764824e7fdSDimitry Andric // or import .....; 48774824e7fdSDimitry Andric if (Left.is(Keywords.kw_import) && Right.isOneOf(tok::less, tok::ellipsis)) 48784824e7fdSDimitry Andric return true; 487904eeddc0SDimitry Andric // Space between `module :` and `import :`. 48804824e7fdSDimitry Andric if (Left.isOneOf(Keywords.kw_module, Keywords.kw_import) && 488181ad6265SDimitry Andric Right.is(TT_ModulePartitionColon)) { 48824824e7fdSDimitry Andric return true; 488381ad6265SDimitry Andric } 48844824e7fdSDimitry Andric // No space between import foo:bar but keep a space between import :bar; 48854824e7fdSDimitry Andric if (Left.is(tok::identifier) && Right.is(TT_ModulePartitionColon)) 48864824e7fdSDimitry Andric return false; 48874824e7fdSDimitry Andric // No space between :bar; 48884824e7fdSDimitry Andric if (Left.is(TT_ModulePartitionColon) && 488981ad6265SDimitry Andric Right.isOneOf(tok::identifier, tok::kw_private)) { 48904824e7fdSDimitry Andric return false; 489181ad6265SDimitry Andric } 48924824e7fdSDimitry Andric if (Left.is(tok::ellipsis) && Right.is(tok::identifier) && 489381ad6265SDimitry Andric Line.First->is(Keywords.kw_import)) { 48944824e7fdSDimitry Andric return false; 489581ad6265SDimitry Andric } 489604eeddc0SDimitry Andric // Space in __attribute__((attr)) ::type. 48975f757f3fSDimitry Andric if (Left.isOneOf(TT_AttributeRParen, TT_AttributeMacro) && 48985f757f3fSDimitry Andric Right.is(tok::coloncolon)) { 489904eeddc0SDimitry Andric return true; 49005f757f3fSDimitry Andric } 49014824e7fdSDimitry Andric 49020b57cec5SDimitry Andric if (Left.is(tok::kw_operator)) 49030b57cec5SDimitry Andric return Right.is(tok::coloncolon); 4904e8d8bef9SDimitry Andric if (Right.is(tok::l_brace) && Right.is(BK_BracedInit) && 490581ad6265SDimitry Andric !Left.opensScope() && Style.SpaceBeforeCpp11BracedList) { 49060b57cec5SDimitry Andric return true; 490781ad6265SDimitry Andric } 490804eeddc0SDimitry Andric if (Left.is(tok::less) && Left.is(TT_OverloadedOperator) && 490981ad6265SDimitry Andric Right.is(TT_TemplateOpener)) { 491004eeddc0SDimitry Andric return true; 491181ad6265SDimitry Andric } 49120fca6ea1SDimitry Andric // C++ Core Guidelines suppression tag, e.g. `[[suppress(type.5)]]`. 49130fca6ea1SDimitry Andric if (Left.is(tok::identifier) && Right.is(tok::numeric_constant)) 49140fca6ea1SDimitry Andric return Right.TokenText[0] != '.'; 49150fca6ea1SDimitry Andric // `Left` is a keyword (including C++ alternative operator) or identifier. 49160fca6ea1SDimitry Andric if (Left.Tok.getIdentifierInfo() && Right.Tok.isLiteral()) 49170fca6ea1SDimitry Andric return true; 49185f757f3fSDimitry Andric } else if (Style.isProto()) { 49190b57cec5SDimitry Andric if (Right.is(tok::period) && 49200b57cec5SDimitry Andric Left.isOneOf(Keywords.kw_optional, Keywords.kw_required, 492181ad6265SDimitry Andric Keywords.kw_repeated, Keywords.kw_extend)) { 49220b57cec5SDimitry Andric return true; 492381ad6265SDimitry Andric } 49240b57cec5SDimitry Andric if (Right.is(tok::l_paren) && 492581ad6265SDimitry Andric Left.isOneOf(Keywords.kw_returns, Keywords.kw_option)) { 49260b57cec5SDimitry Andric return true; 492781ad6265SDimitry Andric } 49280b57cec5SDimitry Andric if (Right.isOneOf(tok::l_brace, tok::less) && Left.is(TT_SelectorName)) 49290b57cec5SDimitry Andric return true; 49300b57cec5SDimitry Andric // Slashes occur in text protocol extension syntax: [type/type] { ... }. 49310b57cec5SDimitry Andric if (Left.is(tok::slash) || Right.is(tok::slash)) 49320b57cec5SDimitry Andric return false; 49330b57cec5SDimitry Andric if (Left.MatchingParen && 49340b57cec5SDimitry Andric Left.MatchingParen->is(TT_ProtoExtensionLSquare) && 493581ad6265SDimitry Andric Right.isOneOf(tok::l_brace, tok::less)) { 49360b57cec5SDimitry Andric return !Style.Cpp11BracedListStyle; 493781ad6265SDimitry Andric } 49380b57cec5SDimitry Andric // A percent is probably part of a formatting specification, such as %lld. 49390b57cec5SDimitry Andric if (Left.is(tok::percent)) 49400b57cec5SDimitry Andric return false; 49410b57cec5SDimitry Andric // Preserve the existence of a space before a percent for cases like 0x%04x 49420b57cec5SDimitry Andric // and "%d %d" 49430b57cec5SDimitry Andric if (Left.is(tok::numeric_constant) && Right.is(tok::percent)) 494404eeddc0SDimitry Andric return Right.hasWhitespaceBefore(); 4945fe6060f1SDimitry Andric } else if (Style.isJson()) { 494606c3fb27SDimitry Andric if (Right.is(tok::colon) && Left.is(tok::string_literal)) 494706c3fb27SDimitry Andric return Style.SpaceBeforeJsonColon; 4948a7dea167SDimitry Andric } else if (Style.isCSharp()) { 49495ffd83dbSDimitry Andric // Require spaces around '{' and before '}' unless they appear in 49505ffd83dbSDimitry Andric // interpolated strings. Interpolated strings are merged into a single token 49515ffd83dbSDimitry Andric // so cannot have spaces inserted by this function. 49525ffd83dbSDimitry Andric 49535ffd83dbSDimitry Andric // No space between 'this' and '[' 49545ffd83dbSDimitry Andric if (Left.is(tok::kw_this) && Right.is(tok::l_square)) 49555ffd83dbSDimitry Andric return false; 49565ffd83dbSDimitry Andric 49575ffd83dbSDimitry Andric // No space between 'new' and '(' 49585ffd83dbSDimitry Andric if (Left.is(tok::kw_new) && Right.is(tok::l_paren)) 49595ffd83dbSDimitry Andric return false; 49605ffd83dbSDimitry Andric 49615ffd83dbSDimitry Andric // Space before { (including space within '{ {'). 49625ffd83dbSDimitry Andric if (Right.is(tok::l_brace)) 49635ffd83dbSDimitry Andric return true; 49645ffd83dbSDimitry Andric 49655ffd83dbSDimitry Andric // Spaces inside braces. 49665ffd83dbSDimitry Andric if (Left.is(tok::l_brace) && Right.isNot(tok::r_brace)) 49675ffd83dbSDimitry Andric return true; 49685ffd83dbSDimitry Andric 49695ffd83dbSDimitry Andric if (Left.isNot(tok::l_brace) && Right.is(tok::r_brace)) 49705ffd83dbSDimitry Andric return true; 49715ffd83dbSDimitry Andric 49725ffd83dbSDimitry Andric // Spaces around '=>'. 4973fe6060f1SDimitry Andric if (Left.is(TT_FatArrow) || Right.is(TT_FatArrow)) 49745ffd83dbSDimitry Andric return true; 49755ffd83dbSDimitry Andric 49765ffd83dbSDimitry Andric // No spaces around attribute target colons 49775ffd83dbSDimitry Andric if (Left.is(TT_AttributeColon) || Right.is(TT_AttributeColon)) 49785ffd83dbSDimitry Andric return false; 49795ffd83dbSDimitry Andric 4980a7dea167SDimitry Andric // space between type and variable e.g. Dictionary<string,string> foo; 4981a7dea167SDimitry Andric if (Left.is(TT_TemplateCloser) && Right.is(TT_StartOfName)) 4982a7dea167SDimitry Andric return true; 49835ffd83dbSDimitry Andric 49845ffd83dbSDimitry Andric // spaces inside square brackets. 49855ffd83dbSDimitry Andric if (Left.is(tok::l_square) || Right.is(tok::r_square)) 49865ffd83dbSDimitry Andric return Style.SpacesInSquareBrackets; 49875ffd83dbSDimitry Andric 49885ffd83dbSDimitry Andric // No space before ? in nullable types. 49895ffd83dbSDimitry Andric if (Right.is(TT_CSharpNullable)) 49905ffd83dbSDimitry Andric return false; 49915ffd83dbSDimitry Andric 4992fe6060f1SDimitry Andric // No space before null forgiving '!'. 4993fe6060f1SDimitry Andric if (Right.is(TT_NonNullAssertion)) 49945ffd83dbSDimitry Andric return false; 49955ffd83dbSDimitry Andric 49965ffd83dbSDimitry Andric // No space between consecutive commas '[,,]'. 49975ffd83dbSDimitry Andric if (Left.is(tok::comma) && Right.is(tok::comma)) 49985ffd83dbSDimitry Andric return false; 49995ffd83dbSDimitry Andric 50005ffd83dbSDimitry Andric // space after var in `var (key, value)` 50015ffd83dbSDimitry Andric if (Left.is(Keywords.kw_var) && Right.is(tok::l_paren)) 50025ffd83dbSDimitry Andric return true; 50035ffd83dbSDimitry Andric 5004a7dea167SDimitry Andric // space between keywords and paren e.g. "using (" 500581ad6265SDimitry Andric if (Right.is(tok::l_paren)) { 50065ffd83dbSDimitry Andric if (Left.isOneOf(tok::kw_using, Keywords.kw_async, Keywords.kw_when, 500781ad6265SDimitry Andric Keywords.kw_lock)) { 5008349cc55cSDimitry Andric return Style.SpaceBeforeParensOptions.AfterControlStatements || 50095ffd83dbSDimitry Andric spaceRequiredBeforeParens(Right); 501081ad6265SDimitry Andric } 501181ad6265SDimitry Andric } 5012e8d8bef9SDimitry Andric 5013e8d8bef9SDimitry Andric // space between method modifier and opening parenthesis of a tuple return 5014e8d8bef9SDimitry Andric // type 50150fca6ea1SDimitry Andric if ((Left.isAccessSpecifierKeyword() || 50160fca6ea1SDimitry Andric Left.isOneOf(tok::kw_virtual, tok::kw_extern, tok::kw_static, 5017e8d8bef9SDimitry Andric Keywords.kw_internal, Keywords.kw_abstract, 5018e8d8bef9SDimitry Andric Keywords.kw_sealed, Keywords.kw_override, 50190fca6ea1SDimitry Andric Keywords.kw_async, Keywords.kw_unsafe)) && 502081ad6265SDimitry Andric Right.is(tok::l_paren)) { 5021e8d8bef9SDimitry Andric return true; 502281ad6265SDimitry Andric } 50230eae32dcSDimitry Andric } else if (Style.isJavaScript()) { 5024fe6060f1SDimitry Andric if (Left.is(TT_FatArrow)) 50250b57cec5SDimitry Andric return true; 50260b57cec5SDimitry Andric // for await ( ... 50270b57cec5SDimitry Andric if (Right.is(tok::l_paren) && Left.is(Keywords.kw_await) && Left.Previous && 502881ad6265SDimitry Andric Left.Previous->is(tok::kw_for)) { 50290b57cec5SDimitry Andric return true; 503081ad6265SDimitry Andric } 50310b57cec5SDimitry Andric if (Left.is(Keywords.kw_async) && Right.is(tok::l_paren) && 50320b57cec5SDimitry Andric Right.MatchingParen) { 50330b57cec5SDimitry Andric const FormatToken *Next = Right.MatchingParen->getNextNonComment(); 50340b57cec5SDimitry Andric // An async arrow function, for example: `x = async () => foo();`, 50350b57cec5SDimitry Andric // as opposed to calling a function called async: `x = async();` 5036fe6060f1SDimitry Andric if (Next && Next->is(TT_FatArrow)) 50370b57cec5SDimitry Andric return true; 50380b57cec5SDimitry Andric } 50395f757f3fSDimitry Andric if ((Left.is(TT_TemplateString) && Left.TokenText.ends_with("${")) || 50405f757f3fSDimitry Andric (Right.is(TT_TemplateString) && Right.TokenText.starts_with("}"))) { 50410b57cec5SDimitry Andric return false; 504281ad6265SDimitry Andric } 50430b57cec5SDimitry Andric // In tagged template literals ("html`bar baz`"), there is no space between 50445ffd83dbSDimitry Andric // the tag identifier and the template string. 50450fca6ea1SDimitry Andric if (Keywords.isJavaScriptIdentifier(Left, 50465ffd83dbSDimitry Andric /* AcceptIdentifierName= */ false) && 504781ad6265SDimitry Andric Right.is(TT_TemplateString)) { 50480b57cec5SDimitry Andric return false; 504981ad6265SDimitry Andric } 50500b57cec5SDimitry Andric if (Right.is(tok::star) && 505181ad6265SDimitry Andric Left.isOneOf(Keywords.kw_function, Keywords.kw_yield)) { 50520b57cec5SDimitry Andric return false; 505381ad6265SDimitry Andric } 50540b57cec5SDimitry Andric if (Right.isOneOf(tok::l_brace, tok::l_square) && 50550b57cec5SDimitry Andric Left.isOneOf(Keywords.kw_function, Keywords.kw_yield, 505681ad6265SDimitry Andric Keywords.kw_extends, Keywords.kw_implements)) { 50570b57cec5SDimitry Andric return true; 505881ad6265SDimitry Andric } 50590b57cec5SDimitry Andric if (Right.is(tok::l_paren)) { 50600b57cec5SDimitry Andric // JS methods can use some keywords as names (e.g. `delete()`). 50610b57cec5SDimitry Andric if (Line.MustBeDeclaration && Left.Tok.getIdentifierInfo()) 50620b57cec5SDimitry Andric return false; 50630b57cec5SDimitry Andric // Valid JS method names can include keywords, e.g. `foo.delete()` or 50640b57cec5SDimitry Andric // `bar.instanceof()`. Recognize call positions by preceding period. 50650b57cec5SDimitry Andric if (Left.Previous && Left.Previous->is(tok::period) && 506681ad6265SDimitry Andric Left.Tok.getIdentifierInfo()) { 50670b57cec5SDimitry Andric return false; 506881ad6265SDimitry Andric } 50690b57cec5SDimitry Andric // Additional unary JavaScript operators that need a space after. 50700b57cec5SDimitry Andric if (Left.isOneOf(tok::kw_throw, Keywords.kw_await, Keywords.kw_typeof, 507181ad6265SDimitry Andric tok::kw_void)) { 50720b57cec5SDimitry Andric return true; 50730b57cec5SDimitry Andric } 5074a7dea167SDimitry Andric } 507581ad6265SDimitry Andric // `foo as const;` casts into a const type. 507681ad6265SDimitry Andric if (Left.endsSequence(tok::kw_const, Keywords.kw_as)) 507781ad6265SDimitry Andric return false; 50780b57cec5SDimitry Andric if ((Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in, 50790b57cec5SDimitry Andric tok::kw_const) || 50800b57cec5SDimitry Andric // "of" is only a keyword if it appears after another identifier 50810b57cec5SDimitry Andric // (e.g. as "const x of y" in a for loop), or after a destructuring 50820b57cec5SDimitry Andric // operation (const [x, y] of z, const {a, b} of c). 50830b57cec5SDimitry Andric (Left.is(Keywords.kw_of) && Left.Previous && 508481ad6265SDimitry Andric (Left.Previous->is(tok::identifier) || 50850b57cec5SDimitry Andric Left.Previous->isOneOf(tok::r_square, tok::r_brace)))) && 50865f757f3fSDimitry Andric (!Left.Previous || Left.Previous->isNot(tok::period))) { 50870b57cec5SDimitry Andric return true; 508881ad6265SDimitry Andric } 50890b57cec5SDimitry Andric if (Left.isOneOf(tok::kw_for, Keywords.kw_as) && Left.Previous && 509081ad6265SDimitry Andric Left.Previous->is(tok::period) && Right.is(tok::l_paren)) { 50910b57cec5SDimitry Andric return false; 509281ad6265SDimitry Andric } 50930b57cec5SDimitry Andric if (Left.is(Keywords.kw_as) && 509481ad6265SDimitry Andric Right.isOneOf(tok::l_square, tok::l_brace, tok::l_paren)) { 50950b57cec5SDimitry Andric return true; 509681ad6265SDimitry Andric } 50970b57cec5SDimitry Andric if (Left.is(tok::kw_default) && Left.Previous && 509881ad6265SDimitry Andric Left.Previous->is(tok::kw_export)) { 50990b57cec5SDimitry Andric return true; 510081ad6265SDimitry Andric } 51010b57cec5SDimitry Andric if (Left.is(Keywords.kw_is) && Right.is(tok::l_brace)) 51020b57cec5SDimitry Andric return true; 51030b57cec5SDimitry Andric if (Right.isOneOf(TT_JsTypeColon, TT_JsTypeOptionalQuestion)) 51040b57cec5SDimitry Andric return false; 51050b57cec5SDimitry Andric if (Left.is(TT_JsTypeOperator) || Right.is(TT_JsTypeOperator)) 51060b57cec5SDimitry Andric return false; 51070b57cec5SDimitry Andric if ((Left.is(tok::l_brace) || Right.is(tok::r_brace)) && 510881ad6265SDimitry Andric Line.First->isOneOf(Keywords.kw_import, tok::kw_export)) { 51090b57cec5SDimitry Andric return false; 511081ad6265SDimitry Andric } 51110b57cec5SDimitry Andric if (Left.is(tok::ellipsis)) 51120b57cec5SDimitry Andric return false; 51130b57cec5SDimitry Andric if (Left.is(TT_TemplateCloser) && 51140b57cec5SDimitry Andric !Right.isOneOf(tok::equal, tok::l_brace, tok::comma, tok::l_square, 511581ad6265SDimitry Andric Keywords.kw_implements, Keywords.kw_extends)) { 51160b57cec5SDimitry Andric // Type assertions ('<type>expr') are not followed by whitespace. Other 51170b57cec5SDimitry Andric // locations that should have whitespace following are identified by the 51180b57cec5SDimitry Andric // above set of follower tokens. 51190b57cec5SDimitry Andric return false; 512081ad6265SDimitry Andric } 5121fe6060f1SDimitry Andric if (Right.is(TT_NonNullAssertion)) 51220b57cec5SDimitry Andric return false; 5123fe6060f1SDimitry Andric if (Left.is(TT_NonNullAssertion) && 512481ad6265SDimitry Andric Right.isOneOf(Keywords.kw_as, Keywords.kw_in)) { 51250b57cec5SDimitry Andric return true; // "x! as string", "x! in y" 512681ad6265SDimitry Andric } 51270b57cec5SDimitry Andric } else if (Style.Language == FormatStyle::LK_Java) { 51280fca6ea1SDimitry Andric if (Left.is(TT_CaseLabelArrow) || Right.is(TT_CaseLabelArrow)) 51290fca6ea1SDimitry Andric return true; 51300b57cec5SDimitry Andric if (Left.is(tok::r_square) && Right.is(tok::l_brace)) 51310b57cec5SDimitry Andric return true; 51327a6dacacSDimitry Andric // spaces inside square brackets. 51337a6dacacSDimitry Andric if (Left.is(tok::l_square) || Right.is(tok::r_square)) 51347a6dacacSDimitry Andric return Style.SpacesInSquareBrackets; 51357a6dacacSDimitry Andric 513681ad6265SDimitry Andric if (Left.is(Keywords.kw_synchronized) && Right.is(tok::l_paren)) { 5137349cc55cSDimitry Andric return Style.SpaceBeforeParensOptions.AfterControlStatements || 5138349cc55cSDimitry Andric spaceRequiredBeforeParens(Right); 513981ad6265SDimitry Andric } 51400fca6ea1SDimitry Andric if ((Left.isAccessSpecifierKeyword() || 51410fca6ea1SDimitry Andric Left.isOneOf(tok::kw_static, Keywords.kw_final, Keywords.kw_abstract, 51420b57cec5SDimitry Andric Keywords.kw_native)) && 514381ad6265SDimitry Andric Right.is(TT_TemplateOpener)) { 51440b57cec5SDimitry Andric return true; 51450b57cec5SDimitry Andric } 51460fca6ea1SDimitry Andric } else if (IsVerilog) { 514706c3fb27SDimitry Andric // An escaped identifier ends with whitespace. 51480fca6ea1SDimitry Andric if (Left.is(tok::identifier) && Left.TokenText[0] == '\\') 514906c3fb27SDimitry Andric return true; 5150bdd1243dSDimitry Andric // Add space between things in a primitive's state table unless in a 5151bdd1243dSDimitry Andric // transition like `(0?)`. 5152bdd1243dSDimitry Andric if ((Left.is(TT_VerilogTableItem) && 5153bdd1243dSDimitry Andric !Right.isOneOf(tok::r_paren, tok::semi)) || 5154bdd1243dSDimitry Andric (Right.is(TT_VerilogTableItem) && Left.isNot(tok::l_paren))) { 5155bdd1243dSDimitry Andric const FormatToken *Next = Right.getNextNonComment(); 5156bdd1243dSDimitry Andric return !(Next && Next->is(tok::r_paren)); 5157bdd1243dSDimitry Andric } 515881ad6265SDimitry Andric // Don't add space within a delay like `#0`. 5159bdd1243dSDimitry Andric if (Left.isNot(TT_BinaryOperator) && 516081ad6265SDimitry Andric Left.isOneOf(Keywords.kw_verilogHash, Keywords.kw_verilogHashHash)) { 516181ad6265SDimitry Andric return false; 516281ad6265SDimitry Andric } 516381ad6265SDimitry Andric // Add space after a delay. 51645f757f3fSDimitry Andric if (Right.isNot(tok::semi) && 516581ad6265SDimitry Andric (Left.endsSequence(tok::numeric_constant, Keywords.kw_verilogHash) || 516681ad6265SDimitry Andric Left.endsSequence(tok::numeric_constant, 516781ad6265SDimitry Andric Keywords.kw_verilogHashHash) || 516881ad6265SDimitry Andric (Left.is(tok::r_paren) && Left.MatchingParen && 516981ad6265SDimitry Andric Left.MatchingParen->endsSequence(tok::l_paren, tok::at)))) { 517081ad6265SDimitry Andric return true; 517181ad6265SDimitry Andric } 5172bdd1243dSDimitry Andric // Don't add embedded spaces in a number literal like `16'h1?ax` or an array 5173bdd1243dSDimitry Andric // literal like `'{}`. 5174bdd1243dSDimitry Andric if (Left.is(Keywords.kw_apostrophe) || 5175bdd1243dSDimitry Andric (Left.is(TT_VerilogNumberBase) && Right.is(tok::numeric_constant))) { 5176bdd1243dSDimitry Andric return false; 5177bdd1243dSDimitry Andric } 51785f757f3fSDimitry Andric // Add spaces around the implication operator `->`. 51795f757f3fSDimitry Andric if (Left.is(tok::arrow) || Right.is(tok::arrow)) 51805f757f3fSDimitry Andric return true; 518106c3fb27SDimitry Andric // Don't add spaces between two at signs. Like in a coverage event. 518206c3fb27SDimitry Andric // Don't add spaces between at and a sensitivity list like 518306c3fb27SDimitry Andric // `@(posedge clk)`. 518406c3fb27SDimitry Andric if (Left.is(tok::at) && Right.isOneOf(tok::l_paren, tok::star, tok::at)) 518506c3fb27SDimitry Andric return false; 5186bdd1243dSDimitry Andric // Add space between the type name and dimension like `logic [1:0]`. 5187bdd1243dSDimitry Andric if (Right.is(tok::l_square) && 5188bdd1243dSDimitry Andric Left.isOneOf(TT_VerilogDimensionedTypeName, Keywords.kw_function)) { 5189bdd1243dSDimitry Andric return true; 5190bdd1243dSDimitry Andric } 51915f757f3fSDimitry Andric // In a tagged union expression, there should be a space after the tag. 51925f757f3fSDimitry Andric if (Right.isOneOf(tok::period, Keywords.kw_apostrophe) && 51935f757f3fSDimitry Andric Keywords.isVerilogIdentifier(Left) && Left.getPreviousNonComment() && 51945f757f3fSDimitry Andric Left.getPreviousNonComment()->is(Keywords.kw_tagged)) { 51955f757f3fSDimitry Andric return true; 51965f757f3fSDimitry Andric } 5197bdd1243dSDimitry Andric // Don't add spaces between a casting type and the quote or repetition count 51985f757f3fSDimitry Andric // and the brace. The case of tagged union expressions is handled by the 51995f757f3fSDimitry Andric // previous rule. 5200bdd1243dSDimitry Andric if ((Right.is(Keywords.kw_apostrophe) || 5201bdd1243dSDimitry Andric (Right.is(BK_BracedInit) && Right.is(tok::l_brace))) && 5202bdd1243dSDimitry Andric !(Left.isOneOf(Keywords.kw_assign, Keywords.kw_unique) || 5203bdd1243dSDimitry Andric Keywords.isVerilogWordOperator(Left)) && 5204bdd1243dSDimitry Andric (Left.isOneOf(tok::r_square, tok::r_paren, tok::r_brace, 5205bdd1243dSDimitry Andric tok::numeric_constant) || 5206bdd1243dSDimitry Andric Keywords.isWordLike(Left))) { 5207bdd1243dSDimitry Andric return false; 5208bdd1243dSDimitry Andric } 520906c3fb27SDimitry Andric // Don't add spaces in imports like `import foo::*;`. 521006c3fb27SDimitry Andric if ((Right.is(tok::star) && Left.is(tok::coloncolon)) || 521106c3fb27SDimitry Andric (Left.is(tok::star) && Right.is(tok::semi))) { 521206c3fb27SDimitry Andric return false; 521306c3fb27SDimitry Andric } 5214bdd1243dSDimitry Andric // Add space in attribute like `(* ASYNC_REG = "TRUE" *)`. 5215bdd1243dSDimitry Andric if (Left.endsSequence(tok::star, tok::l_paren) && Right.is(tok::identifier)) 5216bdd1243dSDimitry Andric return true; 521706c3fb27SDimitry Andric // Add space before drive strength like in `wire (strong1, pull0)`. 521806c3fb27SDimitry Andric if (Right.is(tok::l_paren) && Right.is(TT_VerilogStrength)) 521906c3fb27SDimitry Andric return true; 522006c3fb27SDimitry Andric // Don't add space in a streaming concatenation like `{>>{j}}`. 522106c3fb27SDimitry Andric if ((Left.is(tok::l_brace) && 522206c3fb27SDimitry Andric Right.isOneOf(tok::lessless, tok::greatergreater)) || 522306c3fb27SDimitry Andric (Left.endsSequence(tok::lessless, tok::l_brace) || 522406c3fb27SDimitry Andric Left.endsSequence(tok::greatergreater, tok::l_brace))) { 522506c3fb27SDimitry Andric return false; 522606c3fb27SDimitry Andric } 52270fca6ea1SDimitry Andric } else if (Style.isTableGen()) { 52280fca6ea1SDimitry Andric // Avoid to connect [ and {. [{ is start token of multiline string. 52290fca6ea1SDimitry Andric if (Left.is(tok::l_square) && Right.is(tok::l_brace)) 52300fca6ea1SDimitry Andric return true; 52310fca6ea1SDimitry Andric if (Left.is(tok::r_brace) && Right.is(tok::r_square)) 52320fca6ea1SDimitry Andric return true; 52330fca6ea1SDimitry Andric // Do not insert around colon in DAGArg and cond operator. 52340fca6ea1SDimitry Andric if (Right.isOneOf(TT_TableGenDAGArgListColon, 52350fca6ea1SDimitry Andric TT_TableGenDAGArgListColonToAlign) || 52360fca6ea1SDimitry Andric Left.isOneOf(TT_TableGenDAGArgListColon, 52370fca6ea1SDimitry Andric TT_TableGenDAGArgListColonToAlign)) { 52380fca6ea1SDimitry Andric return false; 523981ad6265SDimitry Andric } 52400fca6ea1SDimitry Andric if (Right.is(TT_TableGenCondOperatorColon)) 52410fca6ea1SDimitry Andric return false; 52420fca6ea1SDimitry Andric if (Left.isOneOf(TT_TableGenDAGArgOperatorID, 52430fca6ea1SDimitry Andric TT_TableGenDAGArgOperatorToBreak) && 52440fca6ea1SDimitry Andric Right.isNot(TT_TableGenDAGArgCloser)) { 52450fca6ea1SDimitry Andric return true; 52460fca6ea1SDimitry Andric } 52470fca6ea1SDimitry Andric // Do not insert bang operators and consequent openers. 52480fca6ea1SDimitry Andric if (Right.isOneOf(tok::l_paren, tok::less) && 52490fca6ea1SDimitry Andric Left.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator)) { 52500fca6ea1SDimitry Andric return false; 52510fca6ea1SDimitry Andric } 52520fca6ea1SDimitry Andric // Trailing paste requires space before '{' or ':', the case in name values. 52530fca6ea1SDimitry Andric // Not before ';', the case in normal values. 52540fca6ea1SDimitry Andric if (Left.is(TT_TableGenTrailingPasteOperator) && 52550fca6ea1SDimitry Andric Right.isOneOf(tok::l_brace, tok::colon)) { 52560fca6ea1SDimitry Andric return true; 52570fca6ea1SDimitry Andric } 52580fca6ea1SDimitry Andric // Otherwise paste operator does not prefer space around. 52590fca6ea1SDimitry Andric if (Left.is(tok::hash) || Right.is(tok::hash)) 52600fca6ea1SDimitry Andric return false; 52610fca6ea1SDimitry Andric // Sure not to connect after defining keywords. 52620fca6ea1SDimitry Andric if (Keywords.isTableGenDefinition(Left)) 52630fca6ea1SDimitry Andric return true; 52640fca6ea1SDimitry Andric } 52650fca6ea1SDimitry Andric 52660b57cec5SDimitry Andric if (Left.is(TT_ImplicitStringLiteral)) 526704eeddc0SDimitry Andric return Right.hasWhitespaceBefore(); 52680b57cec5SDimitry Andric if (Line.Type == LT_ObjCMethodDecl) { 52690b57cec5SDimitry Andric if (Left.is(TT_ObjCMethodSpecifier)) 52700b57cec5SDimitry Andric return true; 52715f757f3fSDimitry Andric if (Left.is(tok::r_paren) && Left.isNot(TT_AttributeRParen) && 52725f757f3fSDimitry Andric canBeObjCSelectorComponent(Right)) { 52730b57cec5SDimitry Andric // Don't space between ')' and <id> or ')' and 'new'. 'new' is not a 52740b57cec5SDimitry Andric // keyword in Objective-C, and '+ (instancetype)new;' is a standard class 52750b57cec5SDimitry Andric // method declaration. 52760b57cec5SDimitry Andric return false; 52770b57cec5SDimitry Andric } 527881ad6265SDimitry Andric } 52790b57cec5SDimitry Andric if (Line.Type == LT_ObjCProperty && 528081ad6265SDimitry Andric (Right.is(tok::equal) || Left.is(tok::equal))) { 52810b57cec5SDimitry Andric return false; 528281ad6265SDimitry Andric } 52830b57cec5SDimitry Andric 52846c4b055cSDimitry Andric if (Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow) || 52856c4b055cSDimitry Andric Left.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow)) { 52860b57cec5SDimitry Andric return true; 52876c4b055cSDimitry Andric } 52885f757f3fSDimitry Andric if (Left.is(tok::comma) && Right.isNot(TT_OverloadedOperatorLParen) && 528906c3fb27SDimitry Andric // In an unexpanded macro call we only find the parentheses and commas 529006c3fb27SDimitry Andric // in a line; the commas and closing parenthesis do not require a space. 529106c3fb27SDimitry Andric (Left.Children.empty() || !Left.MacroParent)) { 52920b57cec5SDimitry Andric return true; 529306c3fb27SDimitry Andric } 52940b57cec5SDimitry Andric if (Right.is(tok::comma)) 52950b57cec5SDimitry Andric return false; 52960b57cec5SDimitry Andric if (Right.is(TT_ObjCBlockLParen)) 52970b57cec5SDimitry Andric return true; 52980b57cec5SDimitry Andric if (Right.is(TT_CtorInitializerColon)) 52990b57cec5SDimitry Andric return Style.SpaceBeforeCtorInitializerColon; 53000b57cec5SDimitry Andric if (Right.is(TT_InheritanceColon) && !Style.SpaceBeforeInheritanceColon) 53010b57cec5SDimitry Andric return false; 53020b57cec5SDimitry Andric if (Right.is(TT_RangeBasedForLoopColon) && 530381ad6265SDimitry Andric !Style.SpaceBeforeRangeBasedForLoopColon) { 53040b57cec5SDimitry Andric return false; 530581ad6265SDimitry Andric } 530681ad6265SDimitry Andric if (Left.is(TT_BitFieldColon)) { 5307e8d8bef9SDimitry Andric return Style.BitFieldColonSpacing == FormatStyle::BFCS_Both || 5308e8d8bef9SDimitry Andric Style.BitFieldColonSpacing == FormatStyle::BFCS_After; 530981ad6265SDimitry Andric } 53100b57cec5SDimitry Andric if (Right.is(tok::colon)) { 531106c3fb27SDimitry Andric if (Right.is(TT_CaseLabelColon)) 5312bdd1243dSDimitry Andric return Style.SpaceBeforeCaseColon; 531306c3fb27SDimitry Andric if (Right.is(TT_GotoLabelColon)) 531406c3fb27SDimitry Andric return false; 531506c3fb27SDimitry Andric // `private:` and `public:`. 531606c3fb27SDimitry Andric if (!Right.getNextNonComment()) 53170b57cec5SDimitry Andric return false; 53180b57cec5SDimitry Andric if (Right.is(TT_ObjCMethodExpr)) 53190b57cec5SDimitry Andric return false; 53200b57cec5SDimitry Andric if (Left.is(tok::question)) 53210b57cec5SDimitry Andric return false; 53220b57cec5SDimitry Andric if (Right.is(TT_InlineASMColon) && Left.is(tok::coloncolon)) 53230b57cec5SDimitry Andric return false; 53240b57cec5SDimitry Andric if (Right.is(TT_DictLiteral)) 53250b57cec5SDimitry Andric return Style.SpacesInContainerLiterals; 53260b57cec5SDimitry Andric if (Right.is(TT_AttributeColon)) 53270b57cec5SDimitry Andric return false; 53285ffd83dbSDimitry Andric if (Right.is(TT_CSharpNamedArgumentColon)) 53295ffd83dbSDimitry Andric return false; 5330bdd1243dSDimitry Andric if (Right.is(TT_GenericSelectionColon)) 5331bdd1243dSDimitry Andric return false; 533281ad6265SDimitry Andric if (Right.is(TT_BitFieldColon)) { 5333e8d8bef9SDimitry Andric return Style.BitFieldColonSpacing == FormatStyle::BFCS_Both || 5334e8d8bef9SDimitry Andric Style.BitFieldColonSpacing == FormatStyle::BFCS_Before; 533581ad6265SDimitry Andric } 53360b57cec5SDimitry Andric return true; 53370b57cec5SDimitry Andric } 5338fe6060f1SDimitry Andric // Do not merge "- -" into "--". 5339fe6060f1SDimitry Andric if ((Left.isOneOf(tok::minus, tok::minusminus) && 5340fe6060f1SDimitry Andric Right.isOneOf(tok::minus, tok::minusminus)) || 5341fe6060f1SDimitry Andric (Left.isOneOf(tok::plus, tok::plusplus) && 534281ad6265SDimitry Andric Right.isOneOf(tok::plus, tok::plusplus))) { 5343fe6060f1SDimitry Andric return true; 534481ad6265SDimitry Andric } 5345a7dea167SDimitry Andric if (Left.is(TT_UnaryOperator)) { 5346480093f4SDimitry Andric // Lambda captures allow for a lone &, so "&]" needs to be properly 5347480093f4SDimitry Andric // handled. 5348480093f4SDimitry Andric if (Left.is(tok::amp) && Right.is(tok::r_square)) 5349480093f4SDimitry Andric return Style.SpacesInSquareBrackets; 53500fca6ea1SDimitry Andric return Style.SpaceAfterLogicalNot && Left.is(tok::exclaim); 5351a7dea167SDimitry Andric } 53520b57cec5SDimitry Andric 53530b57cec5SDimitry Andric // If the next token is a binary operator or a selector name, we have 53540b57cec5SDimitry Andric // incorrectly classified the parenthesis as a cast. FIXME: Detect correctly. 535581ad6265SDimitry Andric if (Left.is(TT_CastRParen)) { 53560b57cec5SDimitry Andric return Style.SpaceAfterCStyleCast || 53570b57cec5SDimitry Andric Right.isOneOf(TT_BinaryOperator, TT_SelectorName); 535881ad6265SDimitry Andric } 53590b57cec5SDimitry Andric 536004eeddc0SDimitry Andric auto ShouldAddSpacesInAngles = [this, &Right]() { 5361fe6060f1SDimitry Andric if (this->Style.SpacesInAngles == FormatStyle::SIAS_Always) 5362fe6060f1SDimitry Andric return true; 5363fe6060f1SDimitry Andric if (this->Style.SpacesInAngles == FormatStyle::SIAS_Leave) 536404eeddc0SDimitry Andric return Right.hasWhitespaceBefore(); 5365fe6060f1SDimitry Andric return false; 5366fe6060f1SDimitry Andric }; 5367fe6060f1SDimitry Andric 53680b57cec5SDimitry Andric if (Left.is(tok::greater) && Right.is(tok::greater)) { 53690b57cec5SDimitry Andric if (Style.Language == FormatStyle::LK_TextProto || 537081ad6265SDimitry Andric (Style.Language == FormatStyle::LK_Proto && Left.is(TT_DictLiteral))) { 53710b57cec5SDimitry Andric return !Style.Cpp11BracedListStyle; 537281ad6265SDimitry Andric } 53730b57cec5SDimitry Andric return Right.is(TT_TemplateCloser) && Left.is(TT_TemplateCloser) && 5374fe6060f1SDimitry Andric ((Style.Standard < FormatStyle::LS_Cpp11) || 5375fe6060f1SDimitry Andric ShouldAddSpacesInAngles()); 53760b57cec5SDimitry Andric } 53770b57cec5SDimitry Andric if (Right.isOneOf(tok::arrow, tok::arrowstar, tok::periodstar) || 53780b57cec5SDimitry Andric Left.isOneOf(tok::arrow, tok::period, tok::arrowstar, tok::periodstar) || 537981ad6265SDimitry Andric (Right.is(tok::period) && Right.isNot(TT_DesignatedInitializerPeriod))) { 53800b57cec5SDimitry Andric return false; 538181ad6265SDimitry Andric } 5382a7dea167SDimitry Andric if (!Style.SpaceBeforeAssignmentOperators && Left.isNot(TT_TemplateCloser) && 538381ad6265SDimitry Andric Right.getPrecedence() == prec::Assignment) { 53840b57cec5SDimitry Andric return false; 538581ad6265SDimitry Andric } 53860b57cec5SDimitry Andric if (Style.Language == FormatStyle::LK_Java && Right.is(tok::coloncolon) && 538781ad6265SDimitry Andric (Left.is(tok::identifier) || Left.is(tok::kw_this))) { 53880b57cec5SDimitry Andric return false; 538981ad6265SDimitry Andric } 539081ad6265SDimitry Andric if (Right.is(tok::coloncolon) && Left.is(tok::identifier)) { 53910b57cec5SDimitry Andric // Generally don't remove existing spaces between an identifier and "::". 53920b57cec5SDimitry Andric // The identifier might actually be a macro name such as ALWAYS_INLINE. If 53930b57cec5SDimitry Andric // this turns out to be too lenient, add analysis of the identifier itself. 539404eeddc0SDimitry Andric return Right.hasWhitespaceBefore(); 539581ad6265SDimitry Andric } 5396480093f4SDimitry Andric if (Right.is(tok::coloncolon) && 539781ad6265SDimitry Andric !Left.isOneOf(tok::l_brace, tok::comment, tok::l_paren)) { 53985ffd83dbSDimitry Andric // Put a space between < and :: in vector< ::std::string > 53990b57cec5SDimitry Andric return (Left.is(TT_TemplateOpener) && 5400fe6060f1SDimitry Andric ((Style.Standard < FormatStyle::LS_Cpp11) || 5401fe6060f1SDimitry Andric ShouldAddSpacesInAngles())) || 54020b57cec5SDimitry Andric !(Left.isOneOf(tok::l_paren, tok::r_paren, tok::l_square, 54035ffd83dbSDimitry Andric tok::kw___super, TT_TemplateOpener, 54045ffd83dbSDimitry Andric TT_TemplateCloser)) || 540506c3fb27SDimitry Andric (Left.is(tok::l_paren) && Style.SpacesInParensOptions.Other); 540681ad6265SDimitry Andric } 54070b57cec5SDimitry Andric if ((Left.is(TT_TemplateOpener)) != (Right.is(TT_TemplateCloser))) 5408fe6060f1SDimitry Andric return ShouldAddSpacesInAngles(); 54090b57cec5SDimitry Andric // Space before TT_StructuredBindingLSquare. 541081ad6265SDimitry Andric if (Right.is(TT_StructuredBindingLSquare)) { 54110b57cec5SDimitry Andric return !Left.isOneOf(tok::amp, tok::ampamp) || 5412fe6060f1SDimitry Andric getTokenReferenceAlignment(Left) != FormatStyle::PAS_Right; 541381ad6265SDimitry Andric } 54140b57cec5SDimitry Andric // Space before & or && following a TT_StructuredBindingLSquare. 54150b57cec5SDimitry Andric if (Right.Next && Right.Next->is(TT_StructuredBindingLSquare) && 541681ad6265SDimitry Andric Right.isOneOf(tok::amp, tok::ampamp)) { 5417fe6060f1SDimitry Andric return getTokenReferenceAlignment(Right) != FormatStyle::PAS_Left; 541881ad6265SDimitry Andric } 54195f757f3fSDimitry Andric if ((Right.is(TT_BinaryOperator) && Left.isNot(tok::l_paren)) || 54200b57cec5SDimitry Andric (Left.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) && 54215f757f3fSDimitry Andric Right.isNot(tok::r_paren))) { 54220b57cec5SDimitry Andric return true; 542381ad6265SDimitry Andric } 54240b57cec5SDimitry Andric if (Right.is(TT_TemplateOpener) && Left.is(tok::r_paren) && 542581ad6265SDimitry Andric Left.MatchingParen && 542681ad6265SDimitry Andric Left.MatchingParen->is(TT_OverloadedOperatorLParen)) { 54270b57cec5SDimitry Andric return false; 542881ad6265SDimitry Andric } 54290b57cec5SDimitry Andric if (Right.is(tok::less) && Left.isNot(tok::l_paren) && 5430bdd1243dSDimitry Andric Line.Type == LT_ImportStatement) { 54310b57cec5SDimitry Andric return true; 543281ad6265SDimitry Andric } 54330b57cec5SDimitry Andric if (Right.is(TT_TrailingUnaryOperator)) 54340b57cec5SDimitry Andric return false; 54350b57cec5SDimitry Andric if (Left.is(TT_RegexLiteral)) 54360b57cec5SDimitry Andric return false; 54370b57cec5SDimitry Andric return spaceRequiredBetween(Line, Left, Right); 54380b57cec5SDimitry Andric } 54390b57cec5SDimitry Andric 54400b57cec5SDimitry Andric // Returns 'true' if 'Tok' is a brace we'd want to break before in Allman style. 54410b57cec5SDimitry Andric static bool isAllmanBrace(const FormatToken &Tok) { 5442e8d8bef9SDimitry Andric return Tok.is(tok::l_brace) && Tok.is(BK_Block) && 54430b57cec5SDimitry Andric !Tok.isOneOf(TT_ObjCBlockLBrace, TT_LambdaLBrace, TT_DictLiteral); 54440b57cec5SDimitry Andric } 54450b57cec5SDimitry Andric 5446349cc55cSDimitry Andric // Returns 'true' if 'Tok' is a function argument. 54475ffd83dbSDimitry Andric static bool IsFunctionArgument(const FormatToken &Tok) { 54485ffd83dbSDimitry Andric return Tok.MatchingParen && Tok.MatchingParen->Next && 54495ffd83dbSDimitry Andric Tok.MatchingParen->Next->isOneOf(tok::comma, tok::r_paren); 54505ffd83dbSDimitry Andric } 54515ffd83dbSDimitry Andric 54525ffd83dbSDimitry Andric static bool 54535ffd83dbSDimitry Andric isItAnEmptyLambdaAllowed(const FormatToken &Tok, 54545ffd83dbSDimitry Andric FormatStyle::ShortLambdaStyle ShortLambdaOption) { 54555ffd83dbSDimitry Andric return Tok.Children.empty() && ShortLambdaOption != FormatStyle::SLS_None; 54565ffd83dbSDimitry Andric } 54575ffd83dbSDimitry Andric 54585ffd83dbSDimitry Andric static bool isAllmanLambdaBrace(const FormatToken &Tok) { 545981ad6265SDimitry Andric return Tok.is(tok::l_brace) && Tok.is(BK_Block) && 546081ad6265SDimitry Andric !Tok.isOneOf(TT_ObjCBlockLBrace, TT_DictLiteral); 54615ffd83dbSDimitry Andric } 54625ffd83dbSDimitry Andric 54630b57cec5SDimitry Andric bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, 546481ad6265SDimitry Andric const FormatToken &Right) const { 54650b57cec5SDimitry Andric const FormatToken &Left = *Right.Previous; 54660b57cec5SDimitry Andric if (Right.NewlinesBefore > 1 && Style.MaxEmptyLinesToKeep > 0) 54670b57cec5SDimitry Andric return true; 54680b57cec5SDimitry Andric 54690fca6ea1SDimitry Andric if (Style.BreakFunctionDefinitionParameters && Line.MightBeFunctionDecl && 54700fca6ea1SDimitry Andric Line.mightBeFunctionDefinition() && Left.MightBeFunctionDeclParen && 54710fca6ea1SDimitry Andric Left.ParameterCount > 0) { 54720fca6ea1SDimitry Andric return true; 54730fca6ea1SDimitry Andric } 54740fca6ea1SDimitry Andric 54750fca6ea1SDimitry Andric const auto *BeforeLeft = Left.Previous; 54760fca6ea1SDimitry Andric const auto *AfterRight = Right.Next; 54770fca6ea1SDimitry Andric 54785ffd83dbSDimitry Andric if (Style.isCSharp()) { 54790eae32dcSDimitry Andric if (Left.is(TT_FatArrow) && Right.is(tok::l_brace) && 548081ad6265SDimitry Andric Style.BraceWrapping.AfterFunction) { 54810eae32dcSDimitry Andric return true; 548281ad6265SDimitry Andric } 54835ffd83dbSDimitry Andric if (Right.is(TT_CSharpNamedArgumentColon) || 548481ad6265SDimitry Andric Left.is(TT_CSharpNamedArgumentColon)) { 54855ffd83dbSDimitry Andric return false; 548681ad6265SDimitry Andric } 54875ffd83dbSDimitry Andric if (Right.is(TT_CSharpGenericTypeConstraint)) 54885ffd83dbSDimitry Andric return true; 54890fca6ea1SDimitry Andric if (AfterRight && AfterRight->is(TT_FatArrow) && 54900eae32dcSDimitry Andric (Right.is(tok::numeric_constant) || 549181ad6265SDimitry Andric (Right.is(tok::identifier) && Right.TokenText == "_"))) { 54920eae32dcSDimitry Andric return true; 549381ad6265SDimitry Andric } 5494fe6060f1SDimitry Andric 5495fe6060f1SDimitry Andric // Break after C# [...] and before public/protected/private/internal. 5496fe6060f1SDimitry Andric if (Left.is(TT_AttributeSquare) && Left.is(tok::r_square) && 5497fe6060f1SDimitry Andric (Right.isAccessSpecifier(/*ColonRequired=*/false) || 549881ad6265SDimitry Andric Right.is(Keywords.kw_internal))) { 5499fe6060f1SDimitry Andric return true; 550081ad6265SDimitry Andric } 5501fe6060f1SDimitry Andric // Break between ] and [ but only when there are really 2 attributes. 5502fe6060f1SDimitry Andric if (Left.is(TT_AttributeSquare) && Right.is(TT_AttributeSquare) && 550381ad6265SDimitry Andric Left.is(tok::r_square) && Right.is(tok::l_square)) { 5504fe6060f1SDimitry Andric return true; 550581ad6265SDimitry Andric } 55060eae32dcSDimitry Andric } else if (Style.isJavaScript()) { 55070b57cec5SDimitry Andric // FIXME: This might apply to other languages and token kinds. 55080fca6ea1SDimitry Andric if (Right.is(tok::string_literal) && Left.is(tok::plus) && BeforeLeft && 55090fca6ea1SDimitry Andric BeforeLeft->is(tok::string_literal)) { 55100b57cec5SDimitry Andric return true; 551181ad6265SDimitry Andric } 55120b57cec5SDimitry Andric if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace) && Line.Level == 0 && 55130fca6ea1SDimitry Andric BeforeLeft && BeforeLeft->is(tok::equal) && 55140b57cec5SDimitry Andric Line.First->isOneOf(tok::identifier, Keywords.kw_import, tok::kw_export, 55150b57cec5SDimitry Andric tok::kw_const) && 55160b57cec5SDimitry Andric // kw_var/kw_let are pseudo-tokens that are tok::identifier, so match 55170b57cec5SDimitry Andric // above. 551881ad6265SDimitry Andric !Line.First->isOneOf(Keywords.kw_var, Keywords.kw_let)) { 55190b57cec5SDimitry Andric // Object literals on the top level of a file are treated as "enum-style". 55200b57cec5SDimitry Andric // Each key/value pair is put on a separate line, instead of bin-packing. 55210b57cec5SDimitry Andric return true; 552281ad6265SDimitry Andric } 55230b57cec5SDimitry Andric if (Left.is(tok::l_brace) && Line.Level == 0 && 55240b57cec5SDimitry Andric (Line.startsWith(tok::kw_enum) || 55250b57cec5SDimitry Andric Line.startsWith(tok::kw_const, tok::kw_enum) || 55260b57cec5SDimitry Andric Line.startsWith(tok::kw_export, tok::kw_enum) || 552781ad6265SDimitry Andric Line.startsWith(tok::kw_export, tok::kw_const, tok::kw_enum))) { 55280b57cec5SDimitry Andric // JavaScript top-level enum key/value pairs are put on separate lines 55290b57cec5SDimitry Andric // instead of bin-packing. 55300b57cec5SDimitry Andric return true; 553181ad6265SDimitry Andric } 55320fca6ea1SDimitry Andric if (Right.is(tok::r_brace) && Left.is(tok::l_brace) && BeforeLeft && 55330fca6ea1SDimitry Andric BeforeLeft->is(TT_FatArrow)) { 55345ffd83dbSDimitry Andric // JS arrow function (=> {...}). 55355ffd83dbSDimitry Andric switch (Style.AllowShortLambdasOnASingleLine) { 55365ffd83dbSDimitry Andric case FormatStyle::SLS_All: 55375ffd83dbSDimitry Andric return false; 55385ffd83dbSDimitry Andric case FormatStyle::SLS_None: 55395ffd83dbSDimitry Andric return true; 55405ffd83dbSDimitry Andric case FormatStyle::SLS_Empty: 55415ffd83dbSDimitry Andric return !Left.Children.empty(); 55425ffd83dbSDimitry Andric case FormatStyle::SLS_Inline: 55435ffd83dbSDimitry Andric // allow one-lining inline (e.g. in function call args) and empty arrow 55445ffd83dbSDimitry Andric // functions. 55455ffd83dbSDimitry Andric return (Left.NestingLevel == 0 && Line.Level == 0) && 55465ffd83dbSDimitry Andric !Left.Children.empty(); 55475ffd83dbSDimitry Andric } 55485ffd83dbSDimitry Andric llvm_unreachable("Unknown FormatStyle::ShortLambdaStyle enum"); 55495ffd83dbSDimitry Andric } 55505ffd83dbSDimitry Andric 55510b57cec5SDimitry Andric if (Right.is(tok::r_brace) && Left.is(tok::l_brace) && 555281ad6265SDimitry Andric !Left.Children.empty()) { 55530b57cec5SDimitry Andric // Support AllowShortFunctionsOnASingleLine for JavaScript. 55540b57cec5SDimitry Andric return Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_None || 55550b57cec5SDimitry Andric Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Empty || 55560b57cec5SDimitry Andric (Left.NestingLevel == 0 && Line.Level == 0 && 55570b57cec5SDimitry Andric Style.AllowShortFunctionsOnASingleLine & 55580b57cec5SDimitry Andric FormatStyle::SFS_InlineOnly); 555981ad6265SDimitry Andric } 55600b57cec5SDimitry Andric } else if (Style.Language == FormatStyle::LK_Java) { 55610fca6ea1SDimitry Andric if (Right.is(tok::plus) && Left.is(tok::string_literal) && AfterRight && 55620fca6ea1SDimitry Andric AfterRight->is(tok::string_literal)) { 55630b57cec5SDimitry Andric return true; 556481ad6265SDimitry Andric } 5565bdd1243dSDimitry Andric } else if (Style.isVerilog()) { 556606c3fb27SDimitry Andric // Break between assignments. 556706c3fb27SDimitry Andric if (Left.is(TT_VerilogAssignComma)) 556806c3fb27SDimitry Andric return true; 556906c3fb27SDimitry Andric // Break between ports of different types. 557006c3fb27SDimitry Andric if (Left.is(TT_VerilogTypeComma)) 557106c3fb27SDimitry Andric return true; 557206c3fb27SDimitry Andric // Break between ports in a module instantiation and after the parameter 557306c3fb27SDimitry Andric // list. 557406c3fb27SDimitry Andric if (Style.VerilogBreakBetweenInstancePorts && 557506c3fb27SDimitry Andric (Left.is(TT_VerilogInstancePortComma) || 557606c3fb27SDimitry Andric (Left.is(tok::r_paren) && Keywords.isVerilogIdentifier(Right) && 557706c3fb27SDimitry Andric Left.MatchingParen && 557806c3fb27SDimitry Andric Left.MatchingParen->is(TT_VerilogInstancePortLParen)))) { 557906c3fb27SDimitry Andric return true; 558006c3fb27SDimitry Andric } 5581bdd1243dSDimitry Andric // Break after labels. In Verilog labels don't have the 'case' keyword, so 5582bdd1243dSDimitry Andric // it is hard to identify them in UnwrappedLineParser. 5583bdd1243dSDimitry Andric if (!Keywords.isVerilogBegin(Right) && Keywords.isVerilogEndOfLabel(Left)) 5584bdd1243dSDimitry Andric return true; 55855f757f3fSDimitry Andric } else if (Style.BreakAdjacentStringLiterals && 55860fca6ea1SDimitry Andric (IsCpp || Style.isProto() || 55875f757f3fSDimitry Andric Style.Language == FormatStyle::LK_TableGen)) { 55880b57cec5SDimitry Andric if (Left.isStringLiteral() && Right.isStringLiteral()) 55890b57cec5SDimitry Andric return true; 55900b57cec5SDimitry Andric } 55910b57cec5SDimitry Andric 5592fe6060f1SDimitry Andric // Basic JSON newline processing. 5593fe6060f1SDimitry Andric if (Style.isJson()) { 5594fe6060f1SDimitry Andric // Always break after a JSON record opener. 5595fe6060f1SDimitry Andric // { 5596fe6060f1SDimitry Andric // } 5597fe6060f1SDimitry Andric if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace)) 5598fe6060f1SDimitry Andric return true; 5599bdd1243dSDimitry Andric // Always break after a JSON array opener based on BreakArrays. 5600bdd1243dSDimitry Andric if ((Left.is(TT_ArrayInitializerLSquare) && Left.is(tok::l_square) && 5601bdd1243dSDimitry Andric Right.isNot(tok::r_square)) || 5602bdd1243dSDimitry Andric Left.is(tok::comma)) { 5603bdd1243dSDimitry Andric if (Right.is(tok::l_brace)) 5604fe6060f1SDimitry Andric return true; 5605bdd1243dSDimitry Andric // scan to the right if an we see an object or an array inside 5606bdd1243dSDimitry Andric // then break. 5607bdd1243dSDimitry Andric for (const auto *Tok = &Right; Tok; Tok = Tok->Next) { 5608bdd1243dSDimitry Andric if (Tok->isOneOf(tok::l_brace, tok::l_square)) 5609bdd1243dSDimitry Andric return true; 5610bdd1243dSDimitry Andric if (Tok->isOneOf(tok::r_brace, tok::r_square)) 5611bdd1243dSDimitry Andric break; 561281ad6265SDimitry Andric } 5613bdd1243dSDimitry Andric return Style.BreakArrays; 5614bdd1243dSDimitry Andric } 56150fca6ea1SDimitry Andric } else if (Style.isTableGen()) { 56160fca6ea1SDimitry Andric // Break the comma in side cond operators. 56170fca6ea1SDimitry Andric // !cond(case1:1, 56180fca6ea1SDimitry Andric // case2:0); 56190fca6ea1SDimitry Andric if (Left.is(TT_TableGenCondOperatorComma)) 56200fca6ea1SDimitry Andric return true; 56210fca6ea1SDimitry Andric if (Left.is(TT_TableGenDAGArgOperatorToBreak) && 56220fca6ea1SDimitry Andric Right.isNot(TT_TableGenDAGArgCloser)) { 56230fca6ea1SDimitry Andric return true; 56240fca6ea1SDimitry Andric } 56250fca6ea1SDimitry Andric if (Left.is(TT_TableGenDAGArgListCommaToBreak)) 56260fca6ea1SDimitry Andric return true; 56270fca6ea1SDimitry Andric if (Right.is(TT_TableGenDAGArgCloser) && Right.MatchingParen && 56280fca6ea1SDimitry Andric Right.MatchingParen->is(TT_TableGenDAGArgOpenerToBreak) && 56290fca6ea1SDimitry Andric &Left != Right.MatchingParen->Next) { 56300fca6ea1SDimitry Andric // Check to avoid empty DAGArg such as (ins). 56310fca6ea1SDimitry Andric return Style.TableGenBreakInsideDAGArg == FormatStyle::DAS_BreakAll; 56320fca6ea1SDimitry Andric } 5633bdd1243dSDimitry Andric } 5634bdd1243dSDimitry Andric 5635bdd1243dSDimitry Andric if (Line.startsWith(tok::kw_asm) && Right.is(TT_InlineASMColon) && 5636bdd1243dSDimitry Andric Style.BreakBeforeInlineASMColon == FormatStyle::BBIAS_Always) { 5637fe6060f1SDimitry Andric return true; 5638fe6060f1SDimitry Andric } 5639fe6060f1SDimitry Andric 56400b57cec5SDimitry Andric // If the last token before a '}', ']', or ')' is a comma or a trailing 56410b57cec5SDimitry Andric // comment, the intention is to insert a line break after it in order to make 56420b57cec5SDimitry Andric // shuffling around entries easier. Import statements, especially in 56430b57cec5SDimitry Andric // JavaScript, can be an exception to this rule. 56440b57cec5SDimitry Andric if (Style.JavaScriptWrapImports || Line.Type != LT_ImportStatement) { 56450b57cec5SDimitry Andric const FormatToken *BeforeClosingBrace = nullptr; 56460b57cec5SDimitry Andric if ((Left.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) || 56470eae32dcSDimitry Andric (Style.isJavaScript() && Left.is(tok::l_paren))) && 564881ad6265SDimitry Andric Left.isNot(BK_Block) && Left.MatchingParen) { 56490b57cec5SDimitry Andric BeforeClosingBrace = Left.MatchingParen->Previous; 565081ad6265SDimitry Andric } else if (Right.MatchingParen && 56510b57cec5SDimitry Andric (Right.MatchingParen->isOneOf(tok::l_brace, 56520b57cec5SDimitry Andric TT_ArrayInitializerLSquare) || 565381ad6265SDimitry Andric (Style.isJavaScript() && 565481ad6265SDimitry Andric Right.MatchingParen->is(tok::l_paren)))) { 56550b57cec5SDimitry Andric BeforeClosingBrace = &Left; 565681ad6265SDimitry Andric } 56570b57cec5SDimitry Andric if (BeforeClosingBrace && (BeforeClosingBrace->is(tok::comma) || 565881ad6265SDimitry Andric BeforeClosingBrace->isTrailingComment())) { 56590b57cec5SDimitry Andric return true; 56600b57cec5SDimitry Andric } 566181ad6265SDimitry Andric } 56620b57cec5SDimitry Andric 566381ad6265SDimitry Andric if (Right.is(tok::comment)) { 5664e8d8bef9SDimitry Andric return Left.isNot(BK_BracedInit) && Left.isNot(TT_CtorInitializerColon) && 56650b57cec5SDimitry Andric (Right.NewlinesBefore > 0 && Right.HasUnescapedNewline); 566681ad6265SDimitry Andric } 56670b57cec5SDimitry Andric if (Left.isTrailingComment()) 56680b57cec5SDimitry Andric return true; 566904eeddc0SDimitry Andric if (Left.IsUnterminatedLiteral) 56700b57cec5SDimitry Andric return true; 56710fca6ea1SDimitry Andric 56720fca6ea1SDimitry Andric if (BeforeLeft && BeforeLeft->is(tok::lessless) && 56730fca6ea1SDimitry Andric Left.is(tok::string_literal) && Right.is(tok::lessless) && AfterRight && 56740fca6ea1SDimitry Andric AfterRight->is(tok::string_literal)) { 56750fca6ea1SDimitry Andric return Right.NewlinesBefore > 0; 56761db9f3b2SDimitry Andric } 56770fca6ea1SDimitry Andric 567881ad6265SDimitry Andric if (Right.is(TT_RequiresClause)) { 567981ad6265SDimitry Andric switch (Style.RequiresClausePosition) { 568081ad6265SDimitry Andric case FormatStyle::RCPS_OwnLine: 568181ad6265SDimitry Andric case FormatStyle::RCPS_WithFollowing: 568281ad6265SDimitry Andric return true; 568381ad6265SDimitry Andric default: 568481ad6265SDimitry Andric break; 568581ad6265SDimitry Andric } 568681ad6265SDimitry Andric } 5687e8d8bef9SDimitry Andric // Can break after template<> declaration 568804eeddc0SDimitry Andric if (Left.ClosesTemplateDeclaration && Left.MatchingParen && 568904eeddc0SDimitry Andric Left.MatchingParen->NestingLevel == 0) { 5690e8d8bef9SDimitry Andric // Put concepts on the next line e.g. 5691e8d8bef9SDimitry Andric // template<typename T> 5692e8d8bef9SDimitry Andric // concept ... 5693e8d8bef9SDimitry Andric if (Right.is(tok::kw_concept)) 569481ad6265SDimitry Andric return Style.BreakBeforeConceptDeclarations == FormatStyle::BBCDS_Always; 56950fca6ea1SDimitry Andric return Style.BreakTemplateDeclarations == FormatStyle::BTDS_Yes || 56960fca6ea1SDimitry Andric (Style.BreakTemplateDeclarations == FormatStyle::BTDS_Leave && 56970fca6ea1SDimitry Andric Right.NewlinesBefore > 0); 569881ad6265SDimitry Andric } 569981ad6265SDimitry Andric if (Left.ClosesRequiresClause && Right.isNot(tok::semi)) { 570081ad6265SDimitry Andric switch (Style.RequiresClausePosition) { 570181ad6265SDimitry Andric case FormatStyle::RCPS_OwnLine: 570281ad6265SDimitry Andric case FormatStyle::RCPS_WithPreceding: 570381ad6265SDimitry Andric return true; 570481ad6265SDimitry Andric default: 570581ad6265SDimitry Andric break; 570681ad6265SDimitry Andric } 5707e8d8bef9SDimitry Andric } 5708349cc55cSDimitry Andric if (Style.PackConstructorInitializers == FormatStyle::PCIS_Never) { 5709349cc55cSDimitry Andric if (Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon && 571081ad6265SDimitry Andric (Left.is(TT_CtorInitializerComma) || 571181ad6265SDimitry Andric Right.is(TT_CtorInitializerColon))) { 57120b57cec5SDimitry Andric return true; 571381ad6265SDimitry Andric } 5714349cc55cSDimitry Andric 5715349cc55cSDimitry Andric if (Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon && 571681ad6265SDimitry Andric Left.isOneOf(TT_CtorInitializerColon, TT_CtorInitializerComma)) { 5717349cc55cSDimitry Andric return true; 5718349cc55cSDimitry Andric } 571981ad6265SDimitry Andric } 5720349cc55cSDimitry Andric if (Style.PackConstructorInitializers < FormatStyle::PCIS_CurrentLine && 57210b57cec5SDimitry Andric Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma && 572281ad6265SDimitry Andric Right.isOneOf(TT_CtorInitializerComma, TT_CtorInitializerColon)) { 57230b57cec5SDimitry Andric return true; 572481ad6265SDimitry Andric } 572506c3fb27SDimitry Andric if (Style.PackConstructorInitializers == FormatStyle::PCIS_NextLineOnly) { 572606c3fb27SDimitry Andric if ((Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon || 572706c3fb27SDimitry Andric Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma) && 572806c3fb27SDimitry Andric Right.is(TT_CtorInitializerColon)) { 572906c3fb27SDimitry Andric return true; 573006c3fb27SDimitry Andric } 573106c3fb27SDimitry Andric 573206c3fb27SDimitry Andric if (Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon && 573306c3fb27SDimitry Andric Left.is(TT_CtorInitializerColon)) { 573406c3fb27SDimitry Andric return true; 573506c3fb27SDimitry Andric } 573606c3fb27SDimitry Andric } 57370b57cec5SDimitry Andric // Break only if we have multiple inheritance. 57380b57cec5SDimitry Andric if (Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma && 573981ad6265SDimitry Andric Right.is(TT_InheritanceComma)) { 57400b57cec5SDimitry Andric return true; 574181ad6265SDimitry Andric } 5742fe6060f1SDimitry Andric if (Style.BreakInheritanceList == FormatStyle::BILS_AfterComma && 574381ad6265SDimitry Andric Left.is(TT_InheritanceComma)) { 5744fe6060f1SDimitry Andric return true; 574581ad6265SDimitry Andric } 57465f757f3fSDimitry Andric if (Right.is(tok::string_literal) && Right.TokenText.starts_with("R\"")) { 57470b57cec5SDimitry Andric // Multiline raw string literals are special wrt. line breaks. The author 57480b57cec5SDimitry Andric // has made a deliberate choice and might have aligned the contents of the 57490b57cec5SDimitry Andric // string literal accordingly. Thus, we try keep existing line breaks. 57500b57cec5SDimitry Andric return Right.IsMultiline && Right.NewlinesBefore > 0; 575181ad6265SDimitry Andric } 57520fca6ea1SDimitry Andric if ((Left.is(tok::l_brace) || 57530fca6ea1SDimitry Andric (Left.is(tok::less) && BeforeLeft && BeforeLeft->is(tok::equal))) && 57540b57cec5SDimitry Andric Right.NestingLevel == 1 && Style.Language == FormatStyle::LK_Proto) { 57550b57cec5SDimitry Andric // Don't put enums or option definitions onto single lines in protocol 57560b57cec5SDimitry Andric // buffers. 57570b57cec5SDimitry Andric return true; 57580b57cec5SDimitry Andric } 57590b57cec5SDimitry Andric if (Right.is(TT_InlineASMBrace)) 57600b57cec5SDimitry Andric return Right.HasUnescapedNewline; 57615ffd83dbSDimitry Andric 5762349cc55cSDimitry Andric if (isAllmanBrace(Left) || isAllmanBrace(Right)) { 57635f757f3fSDimitry Andric auto *FirstNonComment = Line.getFirstNonComment(); 5764349cc55cSDimitry Andric bool AccessSpecifier = 57650fca6ea1SDimitry Andric FirstNonComment && (FirstNonComment->is(Keywords.kw_internal) || 57660fca6ea1SDimitry Andric FirstNonComment->isAccessSpecifierKeyword()); 5767349cc55cSDimitry Andric 5768349cc55cSDimitry Andric if (Style.BraceWrapping.AfterEnum) { 5769349cc55cSDimitry Andric if (Line.startsWith(tok::kw_enum) || 577081ad6265SDimitry Andric Line.startsWith(tok::kw_typedef, tok::kw_enum)) { 5771349cc55cSDimitry Andric return true; 577281ad6265SDimitry Andric } 5773349cc55cSDimitry Andric // Ensure BraceWrapping for `public enum A {`. 5774349cc55cSDimitry Andric if (AccessSpecifier && FirstNonComment->Next && 577581ad6265SDimitry Andric FirstNonComment->Next->is(tok::kw_enum)) { 5776349cc55cSDimitry Andric return true; 5777349cc55cSDimitry Andric } 577881ad6265SDimitry Andric } 5779349cc55cSDimitry Andric 5780349cc55cSDimitry Andric // Ensure BraceWrapping for `public interface A {`. 5781349cc55cSDimitry Andric if (Style.BraceWrapping.AfterClass && 5782349cc55cSDimitry Andric ((AccessSpecifier && FirstNonComment->Next && 5783349cc55cSDimitry Andric FirstNonComment->Next->is(Keywords.kw_interface)) || 578481ad6265SDimitry Andric Line.startsWith(Keywords.kw_interface))) { 5785349cc55cSDimitry Andric return true; 578681ad6265SDimitry Andric } 5787349cc55cSDimitry Andric 578806c3fb27SDimitry Andric // Don't attempt to interpret struct return types as structs. 578906c3fb27SDimitry Andric if (Right.isNot(TT_FunctionLBrace)) { 579006c3fb27SDimitry Andric return (Line.startsWith(tok::kw_class) && 579106c3fb27SDimitry Andric Style.BraceWrapping.AfterClass) || 579206c3fb27SDimitry Andric (Line.startsWith(tok::kw_struct) && 579306c3fb27SDimitry Andric Style.BraceWrapping.AfterStruct); 579406c3fb27SDimitry Andric } 5795349cc55cSDimitry Andric } 5796349cc55cSDimitry Andric 5797a7dea167SDimitry Andric if (Left.is(TT_ObjCBlockLBrace) && 579881ad6265SDimitry Andric Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) { 57990b57cec5SDimitry Andric return true; 580081ad6265SDimitry Andric } 58010b57cec5SDimitry Andric 5802349cc55cSDimitry Andric // Ensure wrapping after __attribute__((XX)) and @interface etc. 58035f757f3fSDimitry Andric if (Left.isOneOf(TT_AttributeRParen, TT_AttributeMacro) && 58045f757f3fSDimitry Andric Right.is(TT_ObjCDecl)) { 5805349cc55cSDimitry Andric return true; 58065f757f3fSDimitry Andric } 5807349cc55cSDimitry Andric 58080b57cec5SDimitry Andric if (Left.is(TT_LambdaLBrace)) { 58095ffd83dbSDimitry Andric if (IsFunctionArgument(Left) && 581081ad6265SDimitry Andric Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Inline) { 58110b57cec5SDimitry Andric return false; 581281ad6265SDimitry Andric } 58130b57cec5SDimitry Andric 58140b57cec5SDimitry Andric if (Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_None || 58150b57cec5SDimitry Andric Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Inline || 58160b57cec5SDimitry Andric (!Left.Children.empty() && 581781ad6265SDimitry Andric Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Empty)) { 58180b57cec5SDimitry Andric return true; 58190b57cec5SDimitry Andric } 582081ad6265SDimitry Andric } 58210b57cec5SDimitry Andric 5822fe6060f1SDimitry Andric if (Style.BraceWrapping.BeforeLambdaBody && Right.is(TT_LambdaLBrace) && 58235f757f3fSDimitry Andric (Left.isPointerOrReference() || Left.is(TT_TemplateCloser))) { 5824fe6060f1SDimitry Andric return true; 5825fe6060f1SDimitry Andric } 5826fe6060f1SDimitry Andric 58270b57cec5SDimitry Andric // Put multiple Java annotation on a new line. 58280eae32dcSDimitry Andric if ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) && 58290b57cec5SDimitry Andric Left.is(TT_LeadingJavaAnnotation) && 58300b57cec5SDimitry Andric Right.isNot(TT_LeadingJavaAnnotation) && Right.isNot(tok::l_paren) && 583181ad6265SDimitry Andric (Line.Last->is(tok::l_brace) || Style.BreakAfterJavaFieldAnnotations)) { 58320b57cec5SDimitry Andric return true; 583381ad6265SDimitry Andric } 58340b57cec5SDimitry Andric 58350b57cec5SDimitry Andric if (Right.is(TT_ProtoExtensionLSquare)) 58360b57cec5SDimitry Andric return true; 58370b57cec5SDimitry Andric 58380b57cec5SDimitry Andric // In text proto instances if a submessage contains at least 2 entries and at 58390b57cec5SDimitry Andric // least one of them is a submessage, like A { ... B { ... } ... }, 58400b57cec5SDimitry Andric // put all of the entries of A on separate lines by forcing the selector of 58410b57cec5SDimitry Andric // the submessage B to be put on a newline. 58420b57cec5SDimitry Andric // 58430b57cec5SDimitry Andric // Example: these can stay on one line: 58440b57cec5SDimitry Andric // a { scalar_1: 1 scalar_2: 2 } 58450b57cec5SDimitry Andric // a { b { key: value } } 58460b57cec5SDimitry Andric // 58470b57cec5SDimitry Andric // and these entries need to be on a new line even if putting them all in one 58480b57cec5SDimitry Andric // line is under the column limit: 58490b57cec5SDimitry Andric // a { 58500b57cec5SDimitry Andric // scalar: 1 58510b57cec5SDimitry Andric // b { key: value } 58520b57cec5SDimitry Andric // } 58530b57cec5SDimitry Andric // 58540b57cec5SDimitry Andric // We enforce this by breaking before a submessage field that has previous 58550b57cec5SDimitry Andric // siblings, *and* breaking before a field that follows a submessage field. 58560b57cec5SDimitry Andric // 58570b57cec5SDimitry Andric // Be careful to exclude the case [proto.ext] { ... } since the `]` is 58580b57cec5SDimitry Andric // the TT_SelectorName there, but we don't want to break inside the brackets. 58590b57cec5SDimitry Andric // 58600b57cec5SDimitry Andric // Another edge case is @submessage { key: value }, which is a common 58610b57cec5SDimitry Andric // substitution placeholder. In this case we want to keep `@` and `submessage` 58620b57cec5SDimitry Andric // together. 58630b57cec5SDimitry Andric // 58640b57cec5SDimitry Andric // We ensure elsewhere that extensions are always on their own line. 58655f757f3fSDimitry Andric if (Style.isProto() && Right.is(TT_SelectorName) && 58660fca6ea1SDimitry Andric Right.isNot(tok::r_square) && AfterRight) { 58670b57cec5SDimitry Andric // Keep `@submessage` together in: 58680b57cec5SDimitry Andric // @submessage { key: value } 586904eeddc0SDimitry Andric if (Left.is(tok::at)) 58700b57cec5SDimitry Andric return false; 58710b57cec5SDimitry Andric // Look for the scope opener after selector in cases like: 58720b57cec5SDimitry Andric // selector { ... 58730b57cec5SDimitry Andric // selector: { ... 58740b57cec5SDimitry Andric // selector: @base { ... 58750fca6ea1SDimitry Andric const auto *LBrace = AfterRight; 58760b57cec5SDimitry Andric if (LBrace && LBrace->is(tok::colon)) { 58770b57cec5SDimitry Andric LBrace = LBrace->Next; 58780b57cec5SDimitry Andric if (LBrace && LBrace->is(tok::at)) { 58790b57cec5SDimitry Andric LBrace = LBrace->Next; 58800b57cec5SDimitry Andric if (LBrace) 58810b57cec5SDimitry Andric LBrace = LBrace->Next; 58820b57cec5SDimitry Andric } 58830b57cec5SDimitry Andric } 58840b57cec5SDimitry Andric if (LBrace && 58850b57cec5SDimitry Andric // The scope opener is one of {, [, <: 58860b57cec5SDimitry Andric // selector { ... } 58870b57cec5SDimitry Andric // selector [ ... ] 58880b57cec5SDimitry Andric // selector < ... > 58890b57cec5SDimitry Andric // 58900b57cec5SDimitry Andric // In case of selector { ... }, the l_brace is TT_DictLiteral. 58910b57cec5SDimitry Andric // In case of an empty selector {}, the l_brace is not TT_DictLiteral, 58920b57cec5SDimitry Andric // so we check for immediately following r_brace. 58930b57cec5SDimitry Andric ((LBrace->is(tok::l_brace) && 58940b57cec5SDimitry Andric (LBrace->is(TT_DictLiteral) || 58950b57cec5SDimitry Andric (LBrace->Next && LBrace->Next->is(tok::r_brace)))) || 58960b57cec5SDimitry Andric LBrace->is(TT_ArrayInitializerLSquare) || LBrace->is(tok::less))) { 58970b57cec5SDimitry Andric // If Left.ParameterCount is 0, then this submessage entry is not the 58980b57cec5SDimitry Andric // first in its parent submessage, and we want to break before this entry. 58990b57cec5SDimitry Andric // If Left.ParameterCount is greater than 0, then its parent submessage 59000b57cec5SDimitry Andric // might contain 1 or more entries and we want to break before this entry 59010b57cec5SDimitry Andric // if it contains at least 2 entries. We deal with this case later by 59020b57cec5SDimitry Andric // detecting and breaking before the next entry in the parent submessage. 59030b57cec5SDimitry Andric if (Left.ParameterCount == 0) 59040b57cec5SDimitry Andric return true; 59050b57cec5SDimitry Andric // However, if this submessage is the first entry in its parent 59060b57cec5SDimitry Andric // submessage, Left.ParameterCount might be 1 in some cases. 59070b57cec5SDimitry Andric // We deal with this case later by detecting an entry 59080b57cec5SDimitry Andric // following a closing paren of this submessage. 59090b57cec5SDimitry Andric } 59100b57cec5SDimitry Andric 59110b57cec5SDimitry Andric // If this is an entry immediately following a submessage, it will be 59120b57cec5SDimitry Andric // preceded by a closing paren of that submessage, like in: 59130b57cec5SDimitry Andric // left---. .---right 59140b57cec5SDimitry Andric // v v 59150b57cec5SDimitry Andric // sub: { ... } key: value 59160b57cec5SDimitry Andric // If there was a comment between `}` an `key` above, then `key` would be 59170b57cec5SDimitry Andric // put on a new line anyways. 59180b57cec5SDimitry Andric if (Left.isOneOf(tok::r_brace, tok::greater, tok::r_square)) 59190b57cec5SDimitry Andric return true; 59200b57cec5SDimitry Andric } 59210b57cec5SDimitry Andric 59220b57cec5SDimitry Andric return false; 59230b57cec5SDimitry Andric } 59240b57cec5SDimitry Andric 59250b57cec5SDimitry Andric bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, 592681ad6265SDimitry Andric const FormatToken &Right) const { 59270b57cec5SDimitry Andric const FormatToken &Left = *Right.Previous; 59280b57cec5SDimitry Andric // Language-specific stuff. 59295ffd83dbSDimitry Andric if (Style.isCSharp()) { 59305ffd83dbSDimitry Andric if (Left.isOneOf(TT_CSharpNamedArgumentColon, TT_AttributeColon) || 593181ad6265SDimitry Andric Right.isOneOf(TT_CSharpNamedArgumentColon, TT_AttributeColon)) { 59325ffd83dbSDimitry Andric return false; 593381ad6265SDimitry Andric } 59345ffd83dbSDimitry Andric // Only break after commas for generic type constraints. 59355ffd83dbSDimitry Andric if (Line.First->is(TT_CSharpGenericTypeConstraint)) 59365ffd83dbSDimitry Andric return Left.is(TT_CSharpGenericTypeConstraintComma); 5937fe6060f1SDimitry Andric // Keep nullable operators attached to their identifiers. 593881ad6265SDimitry Andric if (Right.is(TT_CSharpNullable)) 5939fe6060f1SDimitry Andric return false; 59405ffd83dbSDimitry Andric } else if (Style.Language == FormatStyle::LK_Java) { 59410b57cec5SDimitry Andric if (Left.isOneOf(Keywords.kw_throws, Keywords.kw_extends, 594281ad6265SDimitry Andric Keywords.kw_implements)) { 59430b57cec5SDimitry Andric return false; 594481ad6265SDimitry Andric } 59450b57cec5SDimitry Andric if (Right.isOneOf(Keywords.kw_throws, Keywords.kw_extends, 594681ad6265SDimitry Andric Keywords.kw_implements)) { 59470b57cec5SDimitry Andric return true; 594881ad6265SDimitry Andric } 59490eae32dcSDimitry Andric } else if (Style.isJavaScript()) { 59500b57cec5SDimitry Andric const FormatToken *NonComment = Right.getPreviousNonComment(); 59510b57cec5SDimitry Andric if (NonComment && 59520fca6ea1SDimitry Andric (NonComment->isAccessSpecifierKeyword() || 59530b57cec5SDimitry Andric NonComment->isOneOf( 59540b57cec5SDimitry Andric tok::kw_return, Keywords.kw_yield, tok::kw_continue, tok::kw_break, 59550b57cec5SDimitry Andric tok::kw_throw, Keywords.kw_interface, Keywords.kw_type, 59560fca6ea1SDimitry Andric tok::kw_static, Keywords.kw_readonly, Keywords.kw_override, 59570fca6ea1SDimitry Andric Keywords.kw_abstract, Keywords.kw_get, Keywords.kw_set, 59580fca6ea1SDimitry Andric Keywords.kw_async, Keywords.kw_await))) { 59590b57cec5SDimitry Andric return false; // Otherwise automatic semicolon insertion would trigger. 596081ad6265SDimitry Andric } 59610b57cec5SDimitry Andric if (Right.NestingLevel == 0 && 59620b57cec5SDimitry Andric (Left.Tok.getIdentifierInfo() || 59630b57cec5SDimitry Andric Left.isOneOf(tok::r_square, tok::r_paren)) && 596481ad6265SDimitry Andric Right.isOneOf(tok::l_square, tok::l_paren)) { 59650b57cec5SDimitry Andric return false; // Otherwise automatic semicolon insertion would trigger. 596681ad6265SDimitry Andric } 5967fe6060f1SDimitry Andric if (NonComment && NonComment->is(tok::identifier) && 596881ad6265SDimitry Andric NonComment->TokenText == "asserts") { 5969fe6060f1SDimitry Andric return false; 597081ad6265SDimitry Andric } 5971fe6060f1SDimitry Andric if (Left.is(TT_FatArrow) && Right.is(tok::l_brace)) 59720b57cec5SDimitry Andric return false; 59730b57cec5SDimitry Andric if (Left.is(TT_JsTypeColon)) 59740b57cec5SDimitry Andric return true; 59750b57cec5SDimitry Andric // Don't wrap between ":" and "!" of a strict prop init ("field!: type;"). 59760b57cec5SDimitry Andric if (Left.is(tok::exclaim) && Right.is(tok::colon)) 59770b57cec5SDimitry Andric return false; 59780b57cec5SDimitry Andric // Look for is type annotations like: 59790b57cec5SDimitry Andric // function f(): a is B { ... } 59800b57cec5SDimitry Andric // Do not break before is in these cases. 59810b57cec5SDimitry Andric if (Right.is(Keywords.kw_is)) { 59820b57cec5SDimitry Andric const FormatToken *Next = Right.getNextNonComment(); 59830b57cec5SDimitry Andric // If `is` is followed by a colon, it's likely that it's a dict key, so 59840b57cec5SDimitry Andric // ignore it for this check. 59850b57cec5SDimitry Andric // For example this is common in Polymer: 59860b57cec5SDimitry Andric // Polymer({ 59870b57cec5SDimitry Andric // is: 'name', 59880b57cec5SDimitry Andric // ... 59890b57cec5SDimitry Andric // }); 59905f757f3fSDimitry Andric if (!Next || Next->isNot(tok::colon)) 59910b57cec5SDimitry Andric return false; 59920b57cec5SDimitry Andric } 59930b57cec5SDimitry Andric if (Left.is(Keywords.kw_in)) 59940b57cec5SDimitry Andric return Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None; 59950b57cec5SDimitry Andric if (Right.is(Keywords.kw_in)) 59960b57cec5SDimitry Andric return Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None; 59970b57cec5SDimitry Andric if (Right.is(Keywords.kw_as)) 59980b57cec5SDimitry Andric return false; // must not break before as in 'x as type' casts 59990b57cec5SDimitry Andric if (Right.isOneOf(Keywords.kw_extends, Keywords.kw_infer)) { 60000b57cec5SDimitry Andric // extends and infer can appear as keywords in conditional types: 60010b57cec5SDimitry Andric // https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#conditional-types 60020b57cec5SDimitry Andric // do not break before them, as the expressions are subject to ASI. 60030b57cec5SDimitry Andric return false; 60040b57cec5SDimitry Andric } 60050b57cec5SDimitry Andric if (Left.is(Keywords.kw_as)) 60060b57cec5SDimitry Andric return true; 6007fe6060f1SDimitry Andric if (Left.is(TT_NonNullAssertion)) 60080b57cec5SDimitry Andric return true; 60090b57cec5SDimitry Andric if (Left.is(Keywords.kw_declare) && 60100b57cec5SDimitry Andric Right.isOneOf(Keywords.kw_module, tok::kw_namespace, 60110b57cec5SDimitry Andric Keywords.kw_function, tok::kw_class, tok::kw_enum, 60120b57cec5SDimitry Andric Keywords.kw_interface, Keywords.kw_type, Keywords.kw_var, 601381ad6265SDimitry Andric Keywords.kw_let, tok::kw_const)) { 60140b57cec5SDimitry Andric // See grammar for 'declare' statements at: 6015349cc55cSDimitry Andric // https://github.com/Microsoft/TypeScript/blob/main/doc/spec-ARCHIVED.md#A.10 60160b57cec5SDimitry Andric return false; 601781ad6265SDimitry Andric } 60180b57cec5SDimitry Andric if (Left.isOneOf(Keywords.kw_module, tok::kw_namespace) && 601981ad6265SDimitry Andric Right.isOneOf(tok::identifier, tok::string_literal)) { 60200b57cec5SDimitry Andric return false; // must not break in "module foo { ...}" 602181ad6265SDimitry Andric } 60220b57cec5SDimitry Andric if (Right.is(TT_TemplateString) && Right.closesScope()) 60230b57cec5SDimitry Andric return false; 60240b57cec5SDimitry Andric // Don't split tagged template literal so there is a break between the tag 60250b57cec5SDimitry Andric // identifier and template string. 602681ad6265SDimitry Andric if (Left.is(tok::identifier) && Right.is(TT_TemplateString)) 60270b57cec5SDimitry Andric return false; 60280b57cec5SDimitry Andric if (Left.is(TT_TemplateString) && Left.opensScope()) 60290b57cec5SDimitry Andric return true; 60300fca6ea1SDimitry Andric } else if (Style.isTableGen()) { 60310fca6ea1SDimitry Andric // Avoid to break after "def", "class", "let" and so on. 60320fca6ea1SDimitry Andric if (Keywords.isTableGenDefinition(Left)) 60330fca6ea1SDimitry Andric return false; 60340fca6ea1SDimitry Andric // Avoid to break after '(' in the cases that is in bang operators. 60350fca6ea1SDimitry Andric if (Right.is(tok::l_paren)) { 60360fca6ea1SDimitry Andric return !Left.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator, 60370fca6ea1SDimitry Andric TT_TemplateCloser); 60380fca6ea1SDimitry Andric } 60390fca6ea1SDimitry Andric // Avoid to break between the value and its suffix part. 60400fca6ea1SDimitry Andric if (Left.is(TT_TableGenValueSuffix)) 60410fca6ea1SDimitry Andric return false; 60420fca6ea1SDimitry Andric // Avoid to break around paste operator. 60430fca6ea1SDimitry Andric if (Left.is(tok::hash) || Right.is(tok::hash)) 60440fca6ea1SDimitry Andric return false; 60450fca6ea1SDimitry Andric if (Left.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator)) 60460fca6ea1SDimitry Andric return false; 60470b57cec5SDimitry Andric } 60480b57cec5SDimitry Andric 60490b57cec5SDimitry Andric if (Left.is(tok::at)) 60500b57cec5SDimitry Andric return false; 60510b57cec5SDimitry Andric if (Left.Tok.getObjCKeywordID() == tok::objc_interface) 60520b57cec5SDimitry Andric return false; 60530b57cec5SDimitry Andric if (Left.isOneOf(TT_JavaAnnotation, TT_LeadingJavaAnnotation)) 60545f757f3fSDimitry Andric return Right.isNot(tok::l_paren); 605581ad6265SDimitry Andric if (Right.is(TT_PointerOrReference)) { 60560b57cec5SDimitry Andric return Line.IsMultiVariableDeclStmt || 6057fe6060f1SDimitry Andric (getTokenPointerOrReferenceAlignment(Right) == 6058fe6060f1SDimitry Andric FormatStyle::PAS_Right && 60590b57cec5SDimitry Andric (!Right.Next || Right.Next->isNot(TT_FunctionDeclarationName))); 606081ad6265SDimitry Andric } 60610b57cec5SDimitry Andric if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName) || 606281ad6265SDimitry Andric Right.is(tok::kw_operator)) { 60630b57cec5SDimitry Andric return true; 606481ad6265SDimitry Andric } 60650b57cec5SDimitry Andric if (Left.is(TT_PointerOrReference)) 60660b57cec5SDimitry Andric return false; 606781ad6265SDimitry Andric if (Right.isTrailingComment()) { 60680b57cec5SDimitry Andric // We rely on MustBreakBefore being set correctly here as we should not 60690b57cec5SDimitry Andric // change the "binding" behavior of a comment. 60700b57cec5SDimitry Andric // The first comment in a braced lists is always interpreted as belonging to 60710b57cec5SDimitry Andric // the first list element. Otherwise, it should be placed outside of the 60720b57cec5SDimitry Andric // list. 6073e8d8bef9SDimitry Andric return Left.is(BK_BracedInit) || 6074753f127fSDimitry Andric (Left.is(TT_CtorInitializerColon) && Right.NewlinesBefore > 0 && 60750b57cec5SDimitry Andric Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon); 607681ad6265SDimitry Andric } 60770b57cec5SDimitry Andric if (Left.is(tok::question) && Right.is(tok::colon)) 60780b57cec5SDimitry Andric return false; 60790b57cec5SDimitry Andric if (Right.is(TT_ConditionalExpr) || Right.is(tok::question)) 60800b57cec5SDimitry Andric return Style.BreakBeforeTernaryOperators; 60810b57cec5SDimitry Andric if (Left.is(TT_ConditionalExpr) || Left.is(tok::question)) 60820b57cec5SDimitry Andric return !Style.BreakBeforeTernaryOperators; 60830b57cec5SDimitry Andric if (Left.is(TT_InheritanceColon)) 60840b57cec5SDimitry Andric return Style.BreakInheritanceList == FormatStyle::BILS_AfterColon; 60850b57cec5SDimitry Andric if (Right.is(TT_InheritanceColon)) 60860b57cec5SDimitry Andric return Style.BreakInheritanceList != FormatStyle::BILS_AfterColon; 60875f757f3fSDimitry Andric if (Right.is(TT_ObjCMethodExpr) && Right.isNot(tok::r_square) && 608881ad6265SDimitry Andric Left.isNot(TT_SelectorName)) { 60890b57cec5SDimitry Andric return true; 609081ad6265SDimitry Andric } 60910b57cec5SDimitry Andric 60920b57cec5SDimitry Andric if (Right.is(tok::colon) && 609381ad6265SDimitry Andric !Right.isOneOf(TT_CtorInitializerColon, TT_InlineASMColon)) { 60940b57cec5SDimitry Andric return false; 609581ad6265SDimitry Andric } 60960b57cec5SDimitry Andric if (Left.is(tok::colon) && Left.isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)) { 60975f757f3fSDimitry Andric if (Style.isProto()) { 60980b57cec5SDimitry Andric if (!Style.AlwaysBreakBeforeMultilineStrings && Right.isStringLiteral()) 60990b57cec5SDimitry Andric return false; 61000b57cec5SDimitry Andric // Prevent cases like: 61010b57cec5SDimitry Andric // 61020b57cec5SDimitry Andric // submessage: 61030b57cec5SDimitry Andric // { key: valueeeeeeeeeeee } 61040b57cec5SDimitry Andric // 61050b57cec5SDimitry Andric // when the snippet does not fit into one line. 61060b57cec5SDimitry Andric // Prefer: 61070b57cec5SDimitry Andric // 61080b57cec5SDimitry Andric // submessage: { 61090b57cec5SDimitry Andric // key: valueeeeeeeeeeee 61100b57cec5SDimitry Andric // } 61110b57cec5SDimitry Andric // 61120b57cec5SDimitry Andric // instead, even if it is longer by one line. 61130b57cec5SDimitry Andric // 6114bdd1243dSDimitry Andric // Note that this allows the "{" to go over the column limit 61150b57cec5SDimitry Andric // when the column limit is just between ":" and "{", but that does 61160b57cec5SDimitry Andric // not happen too often and alternative formattings in this case are 61170b57cec5SDimitry Andric // not much better. 61180b57cec5SDimitry Andric // 61190b57cec5SDimitry Andric // The code covers the cases: 61200b57cec5SDimitry Andric // 61210b57cec5SDimitry Andric // submessage: { ... } 61220b57cec5SDimitry Andric // submessage: < ... > 61230b57cec5SDimitry Andric // repeated: [ ... ] 61240b57cec5SDimitry Andric if (((Right.is(tok::l_brace) || Right.is(tok::less)) && 61250b57cec5SDimitry Andric Right.is(TT_DictLiteral)) || 612681ad6265SDimitry Andric Right.is(TT_ArrayInitializerLSquare)) { 61270b57cec5SDimitry Andric return false; 61280b57cec5SDimitry Andric } 612981ad6265SDimitry Andric } 61300b57cec5SDimitry Andric return true; 61310b57cec5SDimitry Andric } 61320b57cec5SDimitry Andric if (Right.is(tok::r_square) && Right.MatchingParen && 613381ad6265SDimitry Andric Right.MatchingParen->is(TT_ProtoExtensionLSquare)) { 61340b57cec5SDimitry Andric return false; 613581ad6265SDimitry Andric } 61360b57cec5SDimitry Andric if (Right.is(TT_SelectorName) || (Right.is(tok::identifier) && Right.Next && 613781ad6265SDimitry Andric Right.Next->is(TT_ObjCMethodExpr))) { 61380b57cec5SDimitry Andric return Left.isNot(tok::period); // FIXME: Properly parse ObjC calls. 613981ad6265SDimitry Andric } 61400b57cec5SDimitry Andric if (Left.is(tok::r_paren) && Line.Type == LT_ObjCProperty) 61410b57cec5SDimitry Andric return true; 614281ad6265SDimitry Andric if (Right.is(tok::kw_concept)) 614381ad6265SDimitry Andric return Style.BreakBeforeConceptDeclarations != FormatStyle::BBCDS_Never; 614481ad6265SDimitry Andric if (Right.is(TT_RequiresClause)) 614581ad6265SDimitry Andric return true; 61460fca6ea1SDimitry Andric if (Left.ClosesTemplateDeclaration) { 61470fca6ea1SDimitry Andric return Style.BreakTemplateDeclarations != FormatStyle::BTDS_Leave || 61480fca6ea1SDimitry Andric Right.NewlinesBefore > 0; 61490fca6ea1SDimitry Andric } 61500fca6ea1SDimitry Andric if (Left.is(TT_FunctionAnnotationRParen)) 61510b57cec5SDimitry Andric return true; 615281ad6265SDimitry Andric if (Left.ClosesRequiresClause) 615381ad6265SDimitry Andric return true; 61540b57cec5SDimitry Andric if (Right.isOneOf(TT_RangeBasedForLoopColon, TT_OverloadedOperatorLParen, 615581ad6265SDimitry Andric TT_OverloadedOperator)) { 61560b57cec5SDimitry Andric return false; 615781ad6265SDimitry Andric } 61580b57cec5SDimitry Andric if (Left.is(TT_RangeBasedForLoopColon)) 61590b57cec5SDimitry Andric return true; 61600b57cec5SDimitry Andric if (Right.is(TT_RangeBasedForLoopColon)) 61610b57cec5SDimitry Andric return false; 61620b57cec5SDimitry Andric if (Left.is(TT_TemplateCloser) && Right.is(TT_TemplateOpener)) 61630b57cec5SDimitry Andric return true; 616481ad6265SDimitry Andric if ((Left.is(tok::greater) && Right.is(tok::greater)) || 616581ad6265SDimitry Andric (Left.is(tok::less) && Right.is(tok::less))) { 616681ad6265SDimitry Andric return false; 616781ad6265SDimitry Andric } 616881ad6265SDimitry Andric if (Right.is(TT_BinaryOperator) && 616981ad6265SDimitry Andric Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None && 617081ad6265SDimitry Andric (Style.BreakBeforeBinaryOperators == FormatStyle::BOS_All || 617181ad6265SDimitry Andric Right.getPrecedence() != prec::Assignment)) { 617281ad6265SDimitry Andric return true; 617381ad6265SDimitry Andric } 61740b57cec5SDimitry Andric if (Left.isOneOf(TT_TemplateCloser, TT_UnaryOperator) || 617581ad6265SDimitry Andric Left.is(tok::kw_operator)) { 61760b57cec5SDimitry Andric return false; 617781ad6265SDimitry Andric } 61780b57cec5SDimitry Andric if (Left.is(tok::equal) && !Right.isOneOf(tok::kw_default, tok::kw_delete) && 617981ad6265SDimitry Andric Line.Type == LT_VirtualFunctionDecl && Left.NestingLevel == 0) { 61800b57cec5SDimitry Andric return false; 618181ad6265SDimitry Andric } 61820b57cec5SDimitry Andric if (Left.is(tok::equal) && Right.is(tok::l_brace) && 618381ad6265SDimitry Andric !Style.Cpp11BracedListStyle) { 61840b57cec5SDimitry Andric return false; 618581ad6265SDimitry Andric } 61865f757f3fSDimitry Andric if (Left.is(TT_AttributeLParen) || 61875f757f3fSDimitry Andric (Left.is(tok::l_paren) && Left.is(TT_TypeDeclarationParen))) { 61880b57cec5SDimitry Andric return false; 618981ad6265SDimitry Andric } 61900b57cec5SDimitry Andric if (Left.is(tok::l_paren) && Left.Previous && 619181ad6265SDimitry Andric (Left.Previous->isOneOf(TT_BinaryOperator, TT_CastRParen))) { 61920b57cec5SDimitry Andric return false; 619381ad6265SDimitry Andric } 61940b57cec5SDimitry Andric if (Right.is(TT_ImplicitStringLiteral)) 61950b57cec5SDimitry Andric return false; 61960b57cec5SDimitry Andric 619704eeddc0SDimitry Andric if (Right.is(TT_TemplateCloser)) 61980b57cec5SDimitry Andric return false; 61990b57cec5SDimitry Andric if (Right.is(tok::r_square) && Right.MatchingParen && 620081ad6265SDimitry Andric Right.MatchingParen->is(TT_LambdaLSquare)) { 62010b57cec5SDimitry Andric return false; 620281ad6265SDimitry Andric } 62030b57cec5SDimitry Andric 62040b57cec5SDimitry Andric // We only break before r_brace if there was a corresponding break before 62050b57cec5SDimitry Andric // the l_brace, which is tracked by BreakBeforeClosingBrace. 620606c3fb27SDimitry Andric if (Right.is(tok::r_brace)) { 620706c3fb27SDimitry Andric return Right.MatchingParen && (Right.MatchingParen->is(BK_Block) || 620806c3fb27SDimitry Andric (Right.isBlockIndentedInitRBrace(Style))); 620906c3fb27SDimitry Andric } 62100b57cec5SDimitry Andric 621104eeddc0SDimitry Andric // We only break before r_paren if we're in a block indented context. 621204eeddc0SDimitry Andric if (Right.is(tok::r_paren)) { 621381ad6265SDimitry Andric if (Style.AlignAfterOpenBracket != FormatStyle::BAS_BlockIndent || 621481ad6265SDimitry Andric !Right.MatchingParen) { 621504eeddc0SDimitry Andric return false; 621604eeddc0SDimitry Andric } 6217bdd1243dSDimitry Andric auto Next = Right.Next; 6218bdd1243dSDimitry Andric if (Next && Next->is(tok::r_paren)) 6219bdd1243dSDimitry Andric Next = Next->Next; 6220bdd1243dSDimitry Andric if (Next && Next->is(tok::l_paren)) 6221bdd1243dSDimitry Andric return false; 622281ad6265SDimitry Andric const FormatToken *Previous = Right.MatchingParen->Previous; 622381ad6265SDimitry Andric return !(Previous && (Previous->is(tok::kw_for) || Previous->isIf())); 622481ad6265SDimitry Andric } 622504eeddc0SDimitry Andric 62260b57cec5SDimitry Andric // Allow breaking after a trailing annotation, e.g. after a method 62270b57cec5SDimitry Andric // declaration. 622881ad6265SDimitry Andric if (Left.is(TT_TrailingAnnotation)) { 62290b57cec5SDimitry Andric return !Right.isOneOf(tok::l_brace, tok::semi, tok::equal, tok::l_paren, 62300b57cec5SDimitry Andric tok::less, tok::coloncolon); 623181ad6265SDimitry Andric } 62320b57cec5SDimitry Andric 62335f757f3fSDimitry Andric if (Right.isAttribute()) 62345f757f3fSDimitry Andric return true; 62355f757f3fSDimitry Andric 62365f757f3fSDimitry Andric if (Right.is(tok::l_square) && Right.is(TT_AttributeSquare)) 62375f757f3fSDimitry Andric return Left.isNot(TT_AttributeSquare); 62380b57cec5SDimitry Andric 62390b57cec5SDimitry Andric if (Left.is(tok::identifier) && Right.is(tok::string_literal)) 62400b57cec5SDimitry Andric return true; 62410b57cec5SDimitry Andric 62420b57cec5SDimitry Andric if (Right.is(tok::identifier) && Right.Next && Right.Next->is(TT_DictLiteral)) 62430b57cec5SDimitry Andric return true; 62440b57cec5SDimitry Andric 6245753f127fSDimitry Andric if (Left.is(TT_CtorInitializerColon)) { 6246753f127fSDimitry Andric return Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon && 6247753f127fSDimitry Andric (!Right.isTrailingComment() || Right.NewlinesBefore > 0); 6248753f127fSDimitry Andric } 62490b57cec5SDimitry Andric if (Right.is(TT_CtorInitializerColon)) 62500b57cec5SDimitry Andric return Style.BreakConstructorInitializers != FormatStyle::BCIS_AfterColon; 62510b57cec5SDimitry Andric if (Left.is(TT_CtorInitializerComma) && 625281ad6265SDimitry Andric Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma) { 62530b57cec5SDimitry Andric return false; 625481ad6265SDimitry Andric } 62550b57cec5SDimitry Andric if (Right.is(TT_CtorInitializerComma) && 625681ad6265SDimitry Andric Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma) { 62570b57cec5SDimitry Andric return true; 625881ad6265SDimitry Andric } 62590b57cec5SDimitry Andric if (Left.is(TT_InheritanceComma) && 626081ad6265SDimitry Andric Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma) { 62610b57cec5SDimitry Andric return false; 626281ad6265SDimitry Andric } 62630b57cec5SDimitry Andric if (Right.is(TT_InheritanceComma) && 626481ad6265SDimitry Andric Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma) { 62650b57cec5SDimitry Andric return true; 626681ad6265SDimitry Andric } 62670b57cec5SDimitry Andric if (Left.is(TT_ArrayInitializerLSquare)) 62680b57cec5SDimitry Andric return true; 62690b57cec5SDimitry Andric if (Right.is(tok::kw_typename) && Left.isNot(tok::kw_const)) 62700b57cec5SDimitry Andric return true; 62710b57cec5SDimitry Andric if ((Left.isBinaryOperator() || Left.is(TT_BinaryOperator)) && 62720b57cec5SDimitry Andric !Left.isOneOf(tok::arrowstar, tok::lessless) && 62730b57cec5SDimitry Andric Style.BreakBeforeBinaryOperators != FormatStyle::BOS_All && 62740b57cec5SDimitry Andric (Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None || 627581ad6265SDimitry Andric Left.getPrecedence() == prec::Assignment)) { 62760b57cec5SDimitry Andric return true; 627781ad6265SDimitry Andric } 62780b57cec5SDimitry Andric if ((Left.is(TT_AttributeSquare) && Right.is(tok::l_square)) || 627981ad6265SDimitry Andric (Left.is(tok::r_square) && Right.is(TT_AttributeSquare))) { 62800b57cec5SDimitry Andric return false; 628181ad6265SDimitry Andric } 62825ffd83dbSDimitry Andric 62835ffd83dbSDimitry Andric auto ShortLambdaOption = Style.AllowShortLambdasOnASingleLine; 6284fe6060f1SDimitry Andric if (Style.BraceWrapping.BeforeLambdaBody && Right.is(TT_LambdaLBrace)) { 62855ffd83dbSDimitry Andric if (isAllmanLambdaBrace(Left)) 62865ffd83dbSDimitry Andric return !isItAnEmptyLambdaAllowed(Left, ShortLambdaOption); 62875ffd83dbSDimitry Andric if (isAllmanLambdaBrace(Right)) 62885ffd83dbSDimitry Andric return !isItAnEmptyLambdaAllowed(Right, ShortLambdaOption); 62895ffd83dbSDimitry Andric } 62905ffd83dbSDimitry Andric 62915f757f3fSDimitry Andric if (Right.is(tok::kw_noexcept) && Right.is(TT_TrailingAnnotation)) { 62925f757f3fSDimitry Andric switch (Style.AllowBreakBeforeNoexceptSpecifier) { 62935f757f3fSDimitry Andric case FormatStyle::BBNSS_Never: 62945f757f3fSDimitry Andric return false; 62955f757f3fSDimitry Andric case FormatStyle::BBNSS_Always: 62965f757f3fSDimitry Andric return true; 62975f757f3fSDimitry Andric case FormatStyle::BBNSS_OnlyWithParen: 62985f757f3fSDimitry Andric return Right.Next && Right.Next->is(tok::l_paren); 62995f757f3fSDimitry Andric } 63005f757f3fSDimitry Andric } 63015f757f3fSDimitry Andric 63020b57cec5SDimitry Andric return Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace, 63030b57cec5SDimitry Andric tok::kw_class, tok::kw_struct, tok::comment) || 63040b57cec5SDimitry Andric Right.isMemberAccess() || 63056c4b055cSDimitry Andric Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow, tok::lessless, 63066c4b055cSDimitry Andric tok::colon, tok::l_square, tok::at) || 63070b57cec5SDimitry Andric (Left.is(tok::r_paren) && 63080b57cec5SDimitry Andric Right.isOneOf(tok::identifier, tok::kw_const)) || 63095f757f3fSDimitry Andric (Left.is(tok::l_paren) && Right.isNot(tok::r_paren)) || 63105f757f3fSDimitry Andric (Left.is(TT_TemplateOpener) && Right.isNot(TT_TemplateCloser)); 63110b57cec5SDimitry Andric } 63120b57cec5SDimitry Andric 631381ad6265SDimitry Andric void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) const { 6314bdd1243dSDimitry Andric llvm::errs() << "AnnotatedTokens(L=" << Line.Level << ", P=" << Line.PPLevel 6315bdd1243dSDimitry Andric << ", T=" << Line.Type << ", C=" << Line.IsContinuation 6316bdd1243dSDimitry Andric << "):\n"; 63170b57cec5SDimitry Andric const FormatToken *Tok = Line.First; 63180b57cec5SDimitry Andric while (Tok) { 63190b57cec5SDimitry Andric llvm::errs() << " M=" << Tok->MustBreakBefore 63200b57cec5SDimitry Andric << " C=" << Tok->CanBreakBefore 63215ffd83dbSDimitry Andric << " T=" << getTokenTypeName(Tok->getType()) 63220b57cec5SDimitry Andric << " S=" << Tok->SpacesRequiredBefore 63235ffd83dbSDimitry Andric << " F=" << Tok->Finalized << " B=" << Tok->BlockParameterCount 6324e8d8bef9SDimitry Andric << " BK=" << Tok->getBlockKind() << " P=" << Tok->SplitPenalty 63250b57cec5SDimitry Andric << " Name=" << Tok->Tok.getName() << " L=" << Tok->TotalLength 6326e8d8bef9SDimitry Andric << " PPK=" << Tok->getPackingKind() << " FakeLParens="; 632781ad6265SDimitry Andric for (prec::Level LParen : Tok->FakeLParens) 632881ad6265SDimitry Andric llvm::errs() << LParen << "/"; 63290b57cec5SDimitry Andric llvm::errs() << " FakeRParens=" << Tok->FakeRParens; 63300b57cec5SDimitry Andric llvm::errs() << " II=" << Tok->Tok.getIdentifierInfo(); 63310b57cec5SDimitry Andric llvm::errs() << " Text='" << Tok->TokenText << "'\n"; 63320b57cec5SDimitry Andric if (!Tok->Next) 63330b57cec5SDimitry Andric assert(Tok == Line.Last); 63340b57cec5SDimitry Andric Tok = Tok->Next; 63350b57cec5SDimitry Andric } 63360b57cec5SDimitry Andric llvm::errs() << "----\n"; 63370b57cec5SDimitry Andric } 63380b57cec5SDimitry Andric 6339fe6060f1SDimitry Andric FormatStyle::PointerAlignmentStyle 634081ad6265SDimitry Andric TokenAnnotator::getTokenReferenceAlignment(const FormatToken &Reference) const { 6341fe6060f1SDimitry Andric assert(Reference.isOneOf(tok::amp, tok::ampamp)); 6342fe6060f1SDimitry Andric switch (Style.ReferenceAlignment) { 6343fe6060f1SDimitry Andric case FormatStyle::RAS_Pointer: 6344fe6060f1SDimitry Andric return Style.PointerAlignment; 6345fe6060f1SDimitry Andric case FormatStyle::RAS_Left: 6346fe6060f1SDimitry Andric return FormatStyle::PAS_Left; 6347fe6060f1SDimitry Andric case FormatStyle::RAS_Right: 6348fe6060f1SDimitry Andric return FormatStyle::PAS_Right; 6349fe6060f1SDimitry Andric case FormatStyle::RAS_Middle: 6350fe6060f1SDimitry Andric return FormatStyle::PAS_Middle; 6351fe6060f1SDimitry Andric } 6352fe6060f1SDimitry Andric assert(0); //"Unhandled value of ReferenceAlignment" 6353fe6060f1SDimitry Andric return Style.PointerAlignment; 6354fe6060f1SDimitry Andric } 6355fe6060f1SDimitry Andric 6356fe6060f1SDimitry Andric FormatStyle::PointerAlignmentStyle 6357fe6060f1SDimitry Andric TokenAnnotator::getTokenPointerOrReferenceAlignment( 635881ad6265SDimitry Andric const FormatToken &PointerOrReference) const { 6359fe6060f1SDimitry Andric if (PointerOrReference.isOneOf(tok::amp, tok::ampamp)) { 6360fe6060f1SDimitry Andric switch (Style.ReferenceAlignment) { 6361fe6060f1SDimitry Andric case FormatStyle::RAS_Pointer: 6362fe6060f1SDimitry Andric return Style.PointerAlignment; 6363fe6060f1SDimitry Andric case FormatStyle::RAS_Left: 6364fe6060f1SDimitry Andric return FormatStyle::PAS_Left; 6365fe6060f1SDimitry Andric case FormatStyle::RAS_Right: 6366fe6060f1SDimitry Andric return FormatStyle::PAS_Right; 6367fe6060f1SDimitry Andric case FormatStyle::RAS_Middle: 6368fe6060f1SDimitry Andric return FormatStyle::PAS_Middle; 6369fe6060f1SDimitry Andric } 6370fe6060f1SDimitry Andric } 6371fe6060f1SDimitry Andric assert(PointerOrReference.is(tok::star)); 6372fe6060f1SDimitry Andric return Style.PointerAlignment; 6373fe6060f1SDimitry Andric } 6374fe6060f1SDimitry Andric 63750b57cec5SDimitry Andric } // namespace format 63760b57cec5SDimitry Andric } // namespace clang 6377