diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp | 483 |
1 files changed, 357 insertions, 126 deletions
diff --git a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp index e0b090f..20dd573 100644 --- a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp +++ b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp @@ -13,11 +13,11 @@ /// //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "format-parser" - #include "UnwrappedLineParser.h" #include "llvm/Support/Debug.h" +#define DEBUG_TYPE "format-parser" + namespace clang { namespace format { @@ -60,7 +60,7 @@ public: : Line(Line), TokenSource(TokenSource), ResetToken(ResetToken), PreviousLineLevel(Line.Level), PreviousTokenSource(TokenSource), StructuralError(StructuralError), - PreviousStructuralError(StructuralError), Token(NULL) { + PreviousStructuralError(StructuralError), Token(nullptr) { TokenSource = this; Line.Level = 0; Line.InPPDirective = true; @@ -74,7 +74,7 @@ public: StructuralError = PreviousStructuralError; } - virtual FormatToken *getNextToken() { + FormatToken *getNextToken() override { // The \c UnwrappedLineParser guards against this by never calling // \c getNextToken() after it has encountered the first eof token. assert(!eof()); @@ -84,9 +84,9 @@ public: return Token; } - virtual unsigned getPosition() { return PreviousTokenSource->getPosition(); } + unsigned getPosition() override { return PreviousTokenSource->getPosition(); } - virtual FormatToken *setPosition(unsigned Position) { + FormatToken *setPosition(unsigned Position) override { Token = PreviousTokenSource->setPosition(Position); return Token; } @@ -128,7 +128,7 @@ public: Parser.CurrentLines = &Parser.PreprocessorDirectives; else if (!Parser.Line->Tokens.empty()) Parser.CurrentLines = &Parser.Line->Tokens.back().Children; - PreBlockLine = Parser.Line.take(); + PreBlockLine = Parser.Line.release(); Parser.Line.reset(new UnwrappedLine()); Parser.Line->Level = PreBlockLine->Level; Parser.Line->InPPDirective = PreBlockLine->InPPDirective; @@ -152,6 +152,25 @@ private: SmallVectorImpl<UnwrappedLine> *OriginalLines; }; +class CompoundStatementIndenter { +public: + CompoundStatementIndenter(UnwrappedLineParser *Parser, + const FormatStyle &Style, unsigned &LineLevel) + : LineLevel(LineLevel), OldLineLevel(LineLevel) { + if (Style.BreakBeforeBraces == FormatStyle::BS_Allman) { + Parser->addUnwrappedLine(); + } else if (Style.BreakBeforeBraces == FormatStyle::BS_GNU) { + Parser->addUnwrappedLine(); + ++LineLevel; + } + } + ~CompoundStatementIndenter() { LineLevel = OldLineLevel; } + +private: + unsigned &LineLevel; + unsigned OldLineLevel; +}; + namespace { class IndexedTokenSource : public FormatTokenSource { @@ -159,17 +178,17 @@ public: IndexedTokenSource(ArrayRef<FormatToken *> Tokens) : Tokens(Tokens), Position(-1) {} - virtual FormatToken *getNextToken() { + FormatToken *getNextToken() override { ++Position; return Tokens[Position]; } - virtual unsigned getPosition() { + unsigned getPosition() override { assert(Position >= 0); return Position; } - virtual FormatToken *setPosition(unsigned P) { + FormatToken *setPosition(unsigned P) override { Position = P; return Tokens[Position]; } @@ -187,14 +206,15 @@ UnwrappedLineParser::UnwrappedLineParser(const FormatStyle &Style, ArrayRef<FormatToken *> Tokens, UnwrappedLineConsumer &Callback) : Line(new UnwrappedLine), MustBreakBeforeNextToken(false), - CurrentLines(&Lines), StructuralError(false), Style(Style), Tokens(NULL), - Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1) {} + CurrentLines(&Lines), StructuralError(false), Style(Style), + Tokens(nullptr), Callback(Callback), AllTokens(Tokens), + PPBranchLevel(-1) {} void UnwrappedLineParser::reset() { PPBranchLevel = -1; Line.reset(new UnwrappedLine); CommentsBeforeNextToken.clear(); - FormatTok = NULL; + FormatTok = nullptr; MustBreakBeforeNextToken = false; PreprocessorDirectives.clear(); CurrentLines = &Lines; @@ -314,18 +334,30 @@ void UnwrappedLineParser::calculateBraceTypes() { case tok::r_brace: if (!LBraceStack.empty()) { if (LBraceStack.back()->BlockKind == BK_Unknown) { - // If there is a comma, semicolon or right paren after the closing - // brace, we assume this is a braced initializer list. Note that - // regardless how we mark inner braces here, we will overwrite the - // BlockKind later if we parse a braced list (where all blocks inside - // are by default braced lists), or when we explicitly detect blocks - // (for example while parsing lambdas). - // - // We exclude + and - as they can be ObjC visibility modifiers. - if (NextTok->isOneOf(tok::comma, tok::semi, tok::r_paren, - tok::r_square, tok::l_brace, tok::colon) || - (NextTok->isBinaryOperator() && - !NextTok->isOneOf(tok::plus, tok::minus))) { + bool ProbablyBracedList = false; + if (Style.Language == FormatStyle::LK_Proto) { + ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square); + } else { + // Using OriginalColumn to distinguish between ObjC methods and + // binary operators is a bit hacky. + bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) && + NextTok->OriginalColumn == 0; + + // If there is a comma, semicolon or right paren after the closing + // brace, we assume this is a braced initializer list. Note that + // regardless how we mark inner braces here, we will overwrite the + // BlockKind later if we parse a braced list (where all blocks + // inside are by default braced lists), or when we explicitly detect + // blocks (for example while parsing lambdas). + // + // We exclude + and - as they can be ObjC visibility modifiers. + ProbablyBracedList = + NextTok->isOneOf(tok::comma, tok::semi, tok::period, tok::colon, + tok::r_paren, tok::r_square, tok::l_brace, + tok::l_paren) || + (NextTok->isBinaryOperator() && !NextIsObjCMethod); + } + if (ProbablyBracedList) { Tok->BlockKind = BK_BracedInit; LBraceStack.back()->BlockKind = BK_BracedInit; } else { @@ -336,6 +368,7 @@ void UnwrappedLineParser::calculateBraceTypes() { LBraceStack.pop_back(); } break; + case tok::at: case tok::semi: case tok::kw_if: case tok::kw_while: @@ -386,16 +419,34 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel, Line->Level = InitialLevel; } +static bool IsGoogScope(const UnwrappedLine &Line) { + if (Line.Tokens.size() < 4) + return false; + auto I = Line.Tokens.begin(); + if (I->Tok->TokenText != "goog") + return false; + ++I; + if (I->Tok->isNot(tok::period)) + return false; + ++I; + if (I->Tok->TokenText != "scope") + return false; + ++I; + return I->Tok->is(tok::l_paren); +} + void UnwrappedLineParser::parseChildBlock() { FormatTok->BlockKind = BK_Block; nextToken(); { + bool GoogScope = + Style.Language == FormatStyle::LK_JavaScript && IsGoogScope(*Line); ScopedLineState LineState(*this); ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack, /*MustBeDeclaration=*/false); - Line->Level += 1; + Line->Level += GoogScope ? 0 : 1; parseLevel(/*HasOpeningBrace=*/true); - Line->Level -= 1; + Line->Level -= GoogScope ? 0 : 1; } nextToken(); } @@ -405,7 +456,7 @@ void UnwrappedLineParser::parsePPDirective() { ScopedMacroState MacroState(*Line, Tokens, FormatTok, StructuralError); nextToken(); - if (FormatTok->Tok.getIdentifierInfo() == NULL) { + if (!FormatTok->Tok.getIdentifierInfo()) { parsePPUnknown(); return; } @@ -436,14 +487,14 @@ void UnwrappedLineParser::parsePPDirective() { } } -void UnwrappedLineParser::pushPPConditional() { - if (!PPStack.empty() && PPStack.back() == PP_Unreachable) +void UnwrappedLineParser::conditionalCompilationCondition(bool Unreachable) { + if (Unreachable || (!PPStack.empty() && PPStack.back() == PP_Unreachable)) PPStack.push_back(PP_Unreachable); else PPStack.push_back(PP_Conditional); } -void UnwrappedLineParser::parsePPIf(bool IfDef) { +void UnwrappedLineParser::conditionalCompilationStart(bool Unreachable) { ++PPBranchLevel; assert(PPBranchLevel >= 0 && PPBranchLevel <= (int)PPLevelBranchIndex.size()); if (PPBranchLevel == (int)PPLevelBranchIndex.size()) { @@ -451,48 +502,56 @@ void UnwrappedLineParser::parsePPIf(bool IfDef) { PPLevelBranchCount.push_back(0); } PPChainBranchIndex.push(0); - nextToken(); - bool IsLiteralFalse = (FormatTok->Tok.isLiteral() && - StringRef(FormatTok->Tok.getLiteralData(), - FormatTok->Tok.getLength()) == "0") || - FormatTok->Tok.is(tok::kw_false); - if ((!IfDef && IsLiteralFalse) || PPLevelBranchIndex[PPBranchLevel] > 0) { - PPStack.push_back(PP_Unreachable); - } else { - pushPPConditional(); - } - parsePPUnknown(); + bool Skip = PPLevelBranchIndex[PPBranchLevel] > 0; + conditionalCompilationCondition(Unreachable || Skip); } -void UnwrappedLineParser::parsePPElse() { +void UnwrappedLineParser::conditionalCompilationAlternative() { if (!PPStack.empty()) PPStack.pop_back(); assert(PPBranchLevel < (int)PPLevelBranchIndex.size()); if (!PPChainBranchIndex.empty()) ++PPChainBranchIndex.top(); - if (PPBranchLevel >= 0 && !PPChainBranchIndex.empty() && - PPLevelBranchIndex[PPBranchLevel] != PPChainBranchIndex.top()) { - PPStack.push_back(PP_Unreachable); - } else { - pushPPConditional(); - } - parsePPUnknown(); + conditionalCompilationCondition( + PPBranchLevel >= 0 && !PPChainBranchIndex.empty() && + PPLevelBranchIndex[PPBranchLevel] != PPChainBranchIndex.top()); } -void UnwrappedLineParser::parsePPElIf() { parsePPElse(); } - -void UnwrappedLineParser::parsePPEndIf() { +void UnwrappedLineParser::conditionalCompilationEnd() { assert(PPBranchLevel < (int)PPLevelBranchIndex.size()); if (PPBranchLevel >= 0 && !PPChainBranchIndex.empty()) { if (PPChainBranchIndex.top() + 1 > PPLevelBranchCount[PPBranchLevel]) { PPLevelBranchCount[PPBranchLevel] = PPChainBranchIndex.top() + 1; } } - --PPBranchLevel; + // Guard against #endif's without #if. + if (PPBranchLevel > 0) + --PPBranchLevel; if (!PPChainBranchIndex.empty()) PPChainBranchIndex.pop(); if (!PPStack.empty()) PPStack.pop_back(); +} + +void UnwrappedLineParser::parsePPIf(bool IfDef) { + nextToken(); + bool IsLiteralFalse = (FormatTok->Tok.isLiteral() && + StringRef(FormatTok->Tok.getLiteralData(), + FormatTok->Tok.getLength()) == "0") || + FormatTok->Tok.is(tok::kw_false); + conditionalCompilationStart(!IfDef && IsLiteralFalse); + parsePPUnknown(); +} + +void UnwrappedLineParser::parsePPElse() { + conditionalCompilationAlternative(); + parsePPUnknown(); +} + +void UnwrappedLineParser::parsePPElIf() { parsePPElse(); } + +void UnwrappedLineParser::parsePPEndIf() { + conditionalCompilationEnd(); parsePPUnknown(); } @@ -551,7 +610,9 @@ bool tokenCanStartNewLine(clang::Token Tok) { // Colon is used in labels, base class lists, initializer lists, // range-based for loops, ternary operator, but should never be the // first token in an unwrapped line. - Tok.isNot(tok::colon); + Tok.isNot(tok::colon) && + // 'noexcept' is a trailing annotation. + Tok.isNot(tok::kw_noexcept); } void UnwrappedLineParser::parseStructuralElement() { @@ -620,8 +681,8 @@ void UnwrappedLineParser::parseStructuralElement() { case tok::kw_case: parseCaseLabel(); return; - case tok::kw_return: - parseReturn(); + case tok::kw_try: + parseTryCatch(); return; case tok::kw_extern: nextToken(); @@ -633,6 +694,12 @@ void UnwrappedLineParser::parseStructuralElement() { return; } } + break; + case tok::identifier: + if (FormatTok->IsForEachMacro) { + parseForOrWhileLoop(); + return; + } // In all other cases, parse the declaration. break; default: @@ -648,6 +715,12 @@ void UnwrappedLineParser::parseStructuralElement() { case tok::kw_enum: parseEnum(); break; + case tok::kw_typedef: + nextToken(); + // FIXME: Use the IdentifierTable instead. + if (FormatTok->TokenText == "NS_ENUM") + parseEnum(); + break; case tok::kw_struct: case tok::kw_union: case tok::kw_class: @@ -667,9 +740,13 @@ void UnwrappedLineParser::parseStructuralElement() { break; case tok::caret: nextToken(); - if (FormatTok->is(tok::l_brace)) { + if (FormatTok->Tok.isAnyIdentifier() || + FormatTok->isSimpleTypeSpecifier()) + nextToken(); + if (FormatTok->is(tok::l_paren)) + parseParens(); + if (FormatTok->is(tok::l_brace)) parseChildBlock(); - } break; case tok::l_brace: if (!tryToParseBracedList()) { @@ -677,10 +754,9 @@ void UnwrappedLineParser::parseStructuralElement() { // structural element. // FIXME: Figure out cases where this is not true, and add projections // for them (the one we know is missing are lambdas). - if (Style.BreakBeforeBraces == FormatStyle::BS_Linux || - Style.BreakBeforeBraces == FormatStyle::BS_Stroustrup || - Style.BreakBeforeBraces == FormatStyle::BS_Allman) + if (Style.BreakBeforeBraces != FormatStyle::BS_Attach) addUnwrappedLine(); + FormatTok->Type = TT_FunctionLBrace; parseBlock(/*MustBeDeclaration=*/false); addUnwrappedLine(); return; @@ -688,8 +764,19 @@ void UnwrappedLineParser::parseStructuralElement() { // Otherwise this was a braced init list, and the structural // element continues. break; + case tok::kw_try: + // We arrive here when parsing function-try blocks. + parseTryCatch(); + return; case tok::identifier: { StringRef Text = FormatTok->TokenText; + // Parse function literal unless 'function' is the first token in a line + // in which case this should be treated as a free-standing function. + if (Style.Language == FormatStyle::LK_JavaScript && Text == "function" && + Line->Tokens.size() > 0) { + tryToParseJSFunction(); + break; + } nextToken(); if (Line->Tokens.size() == 1) { if (FormatTok->Tok.is(tok::colon)) { @@ -699,8 +786,8 @@ void UnwrappedLineParser::parseStructuralElement() { // Recognize function-like macro usages without trailing semicolon. if (FormatTok->Tok.is(tok::l_paren)) { parseParens(); - if (FormatTok->HasUnescapedNewline && - tokenCanStartNewLine(FormatTok->Tok)) { + if (FormatTok->NewlinesBefore > 0 && + tokenCanStartNewLine(FormatTok->Tok) && Text == Text.upper()) { addUnwrappedLine(); return; } @@ -720,7 +807,7 @@ void UnwrappedLineParser::parseStructuralElement() { } break; case tok::l_square: - tryToParseLambda(); + parseSquare(); break; default: nextToken(); @@ -729,36 +816,50 @@ void UnwrappedLineParser::parseStructuralElement() { } while (!eof()); } -void UnwrappedLineParser::tryToParseLambda() { +bool UnwrappedLineParser::tryToParseLambda() { // FIXME: This is a dirty way to access the previous token. Find a better // solution. if (!Line->Tokens.empty() && - Line->Tokens.back().Tok->isOneOf(tok::identifier, tok::kw_operator)) { + (Line->Tokens.back().Tok->isOneOf(tok::identifier, tok::kw_operator) || + Line->Tokens.back().Tok->closesScope() || + Line->Tokens.back().Tok->isSimpleTypeSpecifier())) { nextToken(); - return; + return false; } assert(FormatTok->is(tok::l_square)); FormatToken &LSquare = *FormatTok; if (!tryToParseLambdaIntroducer()) - return; + return false; while (FormatTok->isNot(tok::l_brace)) { + if (FormatTok->isSimpleTypeSpecifier()) { + nextToken(); + continue; + } switch (FormatTok->Tok.getKind()) { case tok::l_brace: break; case tok::l_paren: parseParens(); break; + case tok::less: + case tok::greater: case tok::identifier: + case tok::coloncolon: case tok::kw_mutable: nextToken(); break; + case tok::arrow: + FormatTok->Type = TT_TrailingReturnArrow; + nextToken(); + break; default: - return; + return true; } } LSquare.Type = TT_LambdaLSquare; parseChildBlock(); + return true; } bool UnwrappedLineParser::tryToParseLambdaIntroducer() { @@ -793,6 +894,8 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() { if (!FormatTok->isOneOf(tok::identifier, tok::kw_this)) return false; nextToken(); + if (FormatTok->is(tok::ellipsis)) + nextToken(); if (FormatTok->is(tok::comma)) { nextToken(); } else if (FormatTok->is(tok::r_square)) { @@ -805,6 +908,27 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() { return false; } +void UnwrappedLineParser::tryToParseJSFunction() { + nextToken(); + + // Consume function name. + if (FormatTok->is(tok::identifier)) + nextToken(); + + if (FormatTok->isNot(tok::l_paren)) + return; + nextToken(); + while (FormatTok->isNot(tok::l_brace)) { + // Err on the side of caution in order to avoid consuming the full file in + // case of incomplete code. + if (!FormatTok->isOneOf(tok::identifier, tok::comma, tok::r_paren, + tok::comment)) + return; + nextToken(); + } + parseChildBlock(); +} + bool UnwrappedLineParser::tryToParseBracedList() { if (FormatTok->BlockKind == BK_Unknown) calculateBraceTypes(); @@ -822,9 +946,11 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) { // FIXME: Once we have an expression parser in the UnwrappedLineParser, // replace this by using parseAssigmentExpression() inside. do { - // FIXME: When we start to support lambdas, we'll want to parse them away - // here, otherwise our bail-out scenarios below break. The better solution - // might be to just implement a more or less complete expression parser. + if (Style.Language == FormatStyle::LK_JavaScript && + FormatTok->TokenText == "function") { + tryToParseJSFunction(); + continue; + } switch (FormatTok->Tok.getKind()) { case tok::caret: nextToken(); @@ -861,33 +987,34 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) { return false; } -void UnwrappedLineParser::parseReturn() { +void UnwrappedLineParser::parseParens() { + assert(FormatTok->Tok.is(tok::l_paren) && "'(' expected."); nextToken(); - do { switch (FormatTok->Tok.getKind()) { - case tok::l_brace: - parseBracedList(); - if (FormatTok->Tok.isNot(tok::semi)) { - // Assume missing ';'. - addUnwrappedLine(); - return; - } - break; case tok::l_paren: parseParens(); break; - case tok::r_brace: - // Assume missing ';'. - addUnwrappedLine(); - return; - case tok::semi: + case tok::r_paren: nextToken(); - addUnwrappedLine(); + return; + case tok::r_brace: + // A "}" inside parenthesis is an error if there wasn't a matching "{". return; case tok::l_square: tryToParseLambda(); break; + case tok::l_brace: { + if (!tryToParseBracedList()) { + parseChildBlock(); + } + break; + } + case tok::at: + nextToken(); + if (FormatTok->Tok.is(tok::l_brace)) + parseBracedList(); + break; default: nextToken(); break; @@ -895,22 +1022,23 @@ void UnwrappedLineParser::parseReturn() { } while (!eof()); } -void UnwrappedLineParser::parseParens() { - assert(FormatTok->Tok.is(tok::l_paren) && "'(' expected."); - nextToken(); +void UnwrappedLineParser::parseSquare() { + assert(FormatTok->Tok.is(tok::l_square) && "'[' expected."); + if (tryToParseLambda()) + return; do { switch (FormatTok->Tok.getKind()) { case tok::l_paren: parseParens(); break; - case tok::r_paren: + case tok::r_square: nextToken(); return; case tok::r_brace: // A "}" inside parenthesis is an error if there wasn't a matching "{". return; case tok::l_square: - tryToParseLambda(); + parseSquare(); break; case tok::l_brace: { if (!tryToParseBracedList()) { @@ -937,13 +1065,14 @@ void UnwrappedLineParser::parseIfThenElse() { parseParens(); bool NeedsUnwrappedLine = false; if (FormatTok->Tok.is(tok::l_brace)) { - if (Style.BreakBeforeBraces == FormatStyle::BS_Allman) - addUnwrappedLine(); + CompoundStatementIndenter Indenter(this, Style, Line->Level); parseBlock(/*MustBeDeclaration=*/false); - if (Style.BreakBeforeBraces == FormatStyle::BS_Allman) + if (Style.BreakBeforeBraces == FormatStyle::BS_Allman || + Style.BreakBeforeBraces == FormatStyle::BS_GNU) { addUnwrappedLine(); - else + } else { NeedsUnwrappedLine = true; + } } else { addUnwrappedLine(); ++Line->Level; @@ -953,8 +1082,7 @@ void UnwrappedLineParser::parseIfThenElse() { if (FormatTok->Tok.is(tok::kw_else)) { nextToken(); if (FormatTok->Tok.is(tok::l_brace)) { - if (Style.BreakBeforeBraces == FormatStyle::BS_Allman) - addUnwrappedLine(); + CompoundStatementIndenter Indenter(this, Style, Line->Level); parseBlock(/*MustBeDeclaration=*/false); addUnwrappedLine(); } else if (FormatTok->Tok.is(tok::kw_if)) { @@ -970,6 +1098,72 @@ void UnwrappedLineParser::parseIfThenElse() { } } +void UnwrappedLineParser::parseTryCatch() { + assert(FormatTok->is(tok::kw_try) && "'try' expected"); + nextToken(); + bool NeedsUnwrappedLine = false; + if (FormatTok->is(tok::colon)) { + // We are in a function try block, what comes is an initializer list. + nextToken(); + while (FormatTok->is(tok::identifier)) { + nextToken(); + if (FormatTok->is(tok::l_paren)) + parseParens(); + else + StructuralError = true; + if (FormatTok->is(tok::comma)) + nextToken(); + } + } + if (FormatTok->is(tok::l_brace)) { + CompoundStatementIndenter Indenter(this, Style, Line->Level); + parseBlock(/*MustBeDeclaration=*/false); + if (Style.BreakBeforeBraces == FormatStyle::BS_Allman || + Style.BreakBeforeBraces == FormatStyle::BS_GNU || + Style.BreakBeforeBraces == FormatStyle::BS_Stroustrup) { + addUnwrappedLine(); + } else { + NeedsUnwrappedLine = true; + } + } else if (!FormatTok->is(tok::kw_catch)) { + // The C++ standard requires a compound-statement after a try. + // If there's none, we try to assume there's a structuralElement + // and try to continue. + StructuralError = true; + addUnwrappedLine(); + ++Line->Level; + parseStructuralElement(); + --Line->Level; + } + while (FormatTok->is(tok::kw_catch) || + (Style.Language == FormatStyle::LK_JavaScript && + FormatTok->TokenText == "finally")) { + nextToken(); + while (FormatTok->isNot(tok::l_brace)) { + if (FormatTok->is(tok::l_paren)) { + parseParens(); + continue; + } + if (FormatTok->isOneOf(tok::semi, tok::r_brace)) + return; + nextToken(); + } + NeedsUnwrappedLine = false; + CompoundStatementIndenter Indenter(this, Style, Line->Level); + parseBlock(/*MustBeDeclaration=*/false); + if (Style.BreakBeforeBraces == FormatStyle::BS_Allman || + Style.BreakBeforeBraces == FormatStyle::BS_GNU || + Style.BreakBeforeBraces == FormatStyle::BS_Stroustrup) { + addUnwrappedLine(); + } else { + NeedsUnwrappedLine = true; + } + } + if (NeedsUnwrappedLine) { + addUnwrappedLine(); + } +} + void UnwrappedLineParser::parseNamespace() { assert(FormatTok->Tok.is(tok::kw_namespace) && "'namespace' expected"); nextToken(); @@ -977,7 +1171,8 @@ void UnwrappedLineParser::parseNamespace() { nextToken(); if (FormatTok->Tok.is(tok::l_brace)) { if (Style.BreakBeforeBraces == FormatStyle::BS_Linux || - Style.BreakBeforeBraces == FormatStyle::BS_Allman) + Style.BreakBeforeBraces == FormatStyle::BS_Allman || + Style.BreakBeforeBraces == FormatStyle::BS_GNU) addUnwrappedLine(); bool AddLevel = Style.NamespaceIndentation == FormatStyle::NI_All || @@ -994,14 +1189,14 @@ void UnwrappedLineParser::parseNamespace() { } void UnwrappedLineParser::parseForOrWhileLoop() { - assert((FormatTok->Tok.is(tok::kw_for) || FormatTok->Tok.is(tok::kw_while)) && - "'for' or 'while' expected"); + assert((FormatTok->Tok.is(tok::kw_for) || FormatTok->Tok.is(tok::kw_while) || + FormatTok->IsForEachMacro) && + "'for', 'while' or foreach macro expected"); nextToken(); if (FormatTok->Tok.is(tok::l_paren)) parseParens(); if (FormatTok->Tok.is(tok::l_brace)) { - if (Style.BreakBeforeBraces == FormatStyle::BS_Allman) - addUnwrappedLine(); + CompoundStatementIndenter Indenter(this, Style, Line->Level); parseBlock(/*MustBeDeclaration=*/false); addUnwrappedLine(); } else { @@ -1016,9 +1211,10 @@ void UnwrappedLineParser::parseDoWhile() { assert(FormatTok->Tok.is(tok::kw_do) && "'do' expected"); nextToken(); if (FormatTok->Tok.is(tok::l_brace)) { - if (Style.BreakBeforeBraces == FormatStyle::BS_Allman) - addUnwrappedLine(); + CompoundStatementIndenter Indenter(this, Style, Line->Level); parseBlock(/*MustBeDeclaration=*/false); + if (Style.BreakBeforeBraces == FormatStyle::BS_GNU) + addUnwrappedLine(); } else { addUnwrappedLine(); ++Line->Level; @@ -1042,17 +1238,20 @@ void UnwrappedLineParser::parseLabel() { if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0)) --Line->Level; if (CommentsBeforeNextToken.empty() && FormatTok->Tok.is(tok::l_brace)) { - if (Style.BreakBeforeBraces == FormatStyle::BS_Allman) - addUnwrappedLine(); + CompoundStatementIndenter Indenter(this, Style, Line->Level); parseBlock(/*MustBeDeclaration=*/false); if (FormatTok->Tok.is(tok::kw_break)) { - // "break;" after "}" on its own line only for BS_Allman - if (Style.BreakBeforeBraces == FormatStyle::BS_Allman) + // "break;" after "}" on its own line only for BS_Allman and BS_GNU + if (Style.BreakBeforeBraces == FormatStyle::BS_Allman || + Style.BreakBeforeBraces == FormatStyle::BS_GNU) { addUnwrappedLine(); + } parseStructuralElement(); } + addUnwrappedLine(); + } else { + addUnwrappedLine(); } - addUnwrappedLine(); Line->Level = OldLineLevel; } @@ -1071,8 +1270,7 @@ void UnwrappedLineParser::parseSwitch() { if (FormatTok->Tok.is(tok::l_paren)) parseParens(); if (FormatTok->Tok.is(tok::l_brace)) { - if (Style.BreakBeforeBraces == FormatStyle::BS_Allman) - addUnwrappedLine(); + CompoundStatementIndenter Indenter(this, Style, Line->Level); parseBlock(/*MustBeDeclaration=*/false); addUnwrappedLine(); } else { @@ -1085,6 +1283,10 @@ void UnwrappedLineParser::parseSwitch() { void UnwrappedLineParser::parseAccessSpecifier() { nextToken(); + // Understand Qt's slots. + if (FormatTok->is(tok::identifier) && + (FormatTok->TokenText == "slots" || FormatTok->TokenText == "Q_SLOTS")) + nextToken(); // Otherwise, we don't know what it is, and we'd better keep the next token. if (FormatTok->Tok.is(tok::colon)) nextToken(); @@ -1092,11 +1294,13 @@ void UnwrappedLineParser::parseAccessSpecifier() { } void UnwrappedLineParser::parseEnum() { - nextToken(); + if (FormatTok->Tok.is(tok::kw_enum)) { + // Won't be 'enum' for NS_ENUMs. + nextToken(); + } // Eat up enum class ... - if (FormatTok->Tok.is(tok::kw_class) || - FormatTok->Tok.is(tok::kw_struct)) - nextToken(); + if (FormatTok->Tok.is(tok::kw_class) || FormatTok->Tok.is(tok::kw_struct)) + nextToken(); while (FormatTok->Tok.getIdentifierInfo() || FormatTok->isOneOf(tok::colon, tok::coloncolon)) { nextToken(); @@ -1159,10 +1363,11 @@ void UnwrappedLineParser::parseRecord() { } if (FormatTok->Tok.is(tok::l_brace)) { if (Style.BreakBeforeBraces == FormatStyle::BS_Linux || - Style.BreakBeforeBraces == FormatStyle::BS_Allman) + Style.BreakBeforeBraces == FormatStyle::BS_Allman || + Style.BreakBeforeBraces == FormatStyle::BS_GNU) addUnwrappedLine(); - parseBlock(/*MustBeDeclaration=*/true, /*Addlevel=*/true, + parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/true, /*MunchSemi=*/false); } // We fall through to parsing a structural element afterwards, so @@ -1189,6 +1394,10 @@ void UnwrappedLineParser::parseObjCUntilAtEnd() { parseBlock(/*MustBeDeclaration=*/false); // In ObjC interfaces, nothing should be following the "}". addUnwrappedLine(); + } else if (FormatTok->is(tok::r_brace)) { + // Ignore stray "}". parseStructuralElement doesn't consume them. + nextToken(); + addUnwrappedLine(); } else { parseStructuralElement(); } @@ -1210,9 +1419,12 @@ void UnwrappedLineParser::parseObjCInterfaceOrImplementation() { if (FormatTok->Tok.is(tok::less)) parseObjCProtocolList(); - // If instance variables are present, keep the '{' on the first line too. - if (FormatTok->Tok.is(tok::l_brace)) + if (FormatTok->Tok.is(tok::l_brace)) { + if (Style.BreakBeforeBraces == FormatStyle::BS_Allman || + Style.BreakBeforeBraces == FormatStyle::BS_GNU) + addUnwrappedLine(); parseBlock(/*MustBeDeclaration=*/true); + } // With instance variables, this puts '}' on its own line. Without instance // variables, this ends the @interface line. @@ -1283,13 +1495,18 @@ void UnwrappedLineParser::addUnwrappedLine() { bool UnwrappedLineParser::eof() const { return FormatTok->Tok.is(tok::eof); } +bool UnwrappedLineParser::isOnNewLine(const FormatToken &FormatTok) { + return (Line->InPPDirective || FormatTok.HasUnescapedNewline) && + FormatTok.NewlinesBefore > 0; +} + void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) { bool JustComments = Line->Tokens.empty(); for (SmallVectorImpl<FormatToken *>::const_iterator I = CommentsBeforeNextToken.begin(), E = CommentsBeforeNextToken.end(); I != E; ++I) { - if ((*I)->NewlinesBefore && JustComments) { + if (isOnNewLine(**I) && JustComments) { addUnwrappedLine(); } pushToken(*I); @@ -1303,7 +1520,7 @@ void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) { void UnwrappedLineParser::nextToken() { if (eof()) return; - flushComments(FormatTok->NewlinesBefore > 0); + flushComments(isOnNewLine(*FormatTok)); pushToken(FormatTok); readToken(); } @@ -1312,6 +1529,7 @@ void UnwrappedLineParser::readToken() { bool CommentsInCurrentLine = true; do { FormatTok = Tokens->getNextToken(); + assert(FormatTok); while (!Line->InPPDirective && FormatTok->Tok.is(tok::hash) && (FormatTok->HasUnescapedNewline || FormatTok->IsFirst)) { // If there is an unfinished unwrapped line, we flush the preprocessor @@ -1322,9 +1540,22 @@ void UnwrappedLineParser::readToken() { // Comments stored before the preprocessor directive need to be output // before the preprocessor directive, at the same level as the // preprocessor directive, as we consider them to apply to the directive. - flushComments(FormatTok->NewlinesBefore > 0); + flushComments(isOnNewLine(*FormatTok)); parsePPDirective(); } + while (FormatTok->Type == TT_ConflictStart || + FormatTok->Type == TT_ConflictEnd || + FormatTok->Type == TT_ConflictAlternative) { + if (FormatTok->Type == TT_ConflictStart) { + conditionalCompilationStart(/*Unreachable=*/false); + } else if (FormatTok->Type == TT_ConflictAlternative) { + conditionalCompilationAlternative(); + } else if (FormatTok->Type == TT_ConflictEnd) { + conditionalCompilationEnd(); + } + FormatTok = Tokens->getNextToken(); + FormatTok->MustBreakBefore = true; + } if (!PPStack.empty() && (PPStack.back() == PP_Unreachable) && !Line->InPPDirective) { @@ -1333,7 +1564,7 @@ void UnwrappedLineParser::readToken() { if (!FormatTok->Tok.is(tok::comment)) return; - if (FormatTok->NewlinesBefore > 0 || FormatTok->IsFirst) { + if (isOnNewLine(*FormatTok) || FormatTok->IsFirst) { CommentsInCurrentLine = false; } if (CommentsInCurrentLine) { |