Update Clang for 3.5 rebase (r209713).
Change-Id: I8c9133b0f8f776dc915f270b60f94962e771bc83
diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp
index 96d8155..d0750af 100644
--- a/lib/Format/UnwrappedLineParser.cpp
+++ b/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 @@
: 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;
@@ -164,9 +164,7 @@
++LineLevel;
}
}
- ~CompoundStatementIndenter() {
- LineLevel = OldLineLevel;
- }
+ ~CompoundStatementIndenter() { LineLevel = OldLineLevel; }
private:
unsigned &LineLevel;
@@ -208,14 +206,15 @@
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;
@@ -335,18 +334,30 @@
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::period,
- 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 {
@@ -408,16 +419,34 @@
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();
}
@@ -427,7 +456,7 @@
ScopedMacroState MacroState(*Line, Tokens, FormatTok, StructuralError);
nextToken();
- if (FormatTok->Tok.getIdentifierInfo() == NULL) {
+ if (!FormatTok->Tok.getIdentifierInfo()) {
parsePPUnknown();
return;
}
@@ -458,14 +487,14 @@
}
}
-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()) {
@@ -473,37 +502,22 @@
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]) {
@@ -517,6 +531,27 @@
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();
}
@@ -575,7 +610,9 @@
// 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() {
@@ -644,6 +681,9 @@
case tok::kw_case:
parseCaseLabel();
return;
+ case tok::kw_try:
+ parseTryCatch();
+ return;
case tok::kw_extern:
nextToken();
if (FormatTok->Tok.is(tok::string_literal)) {
@@ -724,8 +764,16 @@
// 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;
+ if (Style.Language == FormatStyle::LK_JavaScript && Text == "function") {
+ tryToParseJSFunction();
+ break;
+ }
nextToken();
if (Line->Tokens.size() == 1) {
if (FormatTok->Tok.is(tok::colon)) {
@@ -855,6 +903,22 @@
return false;
}
+void UnwrappedLineParser::tryToParseJSFunction() {
+ 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();
@@ -872,9 +936,11 @@
// 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();
@@ -1022,6 +1088,72 @@
}
}
+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();
@@ -1157,9 +1289,8 @@
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();
@@ -1278,9 +1409,12 @@
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.
@@ -1351,13 +1485,18 @@
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);
@@ -1371,7 +1510,7 @@
void UnwrappedLineParser::nextToken() {
if (eof())
return;
- flushComments(FormatTok->NewlinesBefore > 0);
+ flushComments(isOnNewLine(*FormatTok));
pushToken(FormatTok);
readToken();
}
@@ -1391,9 +1530,22 @@
// 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) {
@@ -1402,7 +1554,7 @@
if (!FormatTok->Tok.is(tok::comment))
return;
- if (FormatTok->NewlinesBefore > 0 || FormatTok->IsFirst) {
+ if (isOnNewLine(*FormatTok) || FormatTok->IsFirst) {
CommentsInCurrentLine = false;
}
if (CommentsInCurrentLine) {