Update Clang for rebase to r212749.
This also fixes a small issue with arm_neon.h not being generated always.
Includes a cherry-pick of:
r213450 - fixes mac-specific header issue
r213126 - removes a default -Bsymbolic on Android
Change-Id: I2a790a0f5d3b2aab11de596fc3a74e7cbc99081d
diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp
index 7485e0d..2af16fc 100644
--- a/lib/Format/ContinuationIndenter.cpp
+++ b/lib/Format/ContinuationIndenter.cpp
@@ -112,6 +112,15 @@
return false;
if (Current.isMemberAccess() && State.Stack.back().ContainsUnwrappedBuilder)
return false;
+
+ // Don't create a 'hanging' indent if there are multiple blocks in a single
+ // statement.
+ if (Style.Language == FormatStyle::LK_JavaScript &&
+ Previous.is(tok::l_brace) && State.Stack.size() > 1 &&
+ State.Stack[State.Stack.size() - 2].JSFunctionInlined &&
+ State.Stack[State.Stack.size() - 2].HasMultipleNestedBlocks)
+ return false;
+
return !State.Stack.back().NoLineBreak;
}
@@ -137,7 +146,8 @@
if (Style.AlwaysBreakBeforeMultilineStrings &&
State.Column > State.Stack.back().Indent && // Breaking saves columns.
!Previous.isOneOf(tok::kw_return, tok::lessless, tok::at) &&
- Previous.Type != TT_InlineASMColon && nextIsMultilineString(State))
+ Previous.Type != TT_InlineASMColon &&
+ Previous.Type != TT_ConditionalExpr && nextIsMultilineString(State))
return true;
if (((Previous.Type == TT_DictLiteral && Previous.is(tok::l_brace)) ||
Previous.Type == TT_ArrayInitializerLSquare) &&
@@ -185,7 +195,7 @@
State.Stack.back().FirstLessLess == 0)
return true;
- if (Current.Type == TT_ObjCSelectorName &&
+ if (Current.Type == TT_SelectorName &&
State.Stack.back().ObjCSelectorNameFound &&
State.Stack.back().BreakBeforeParameter)
return true;
@@ -193,10 +203,12 @@
!Current.isTrailingComment())
return true;
- if ((Current.Type == TT_StartOfName || Current.is(tok::kw_operator)) &&
- State.Line->MightBeFunctionDecl &&
- State.Stack.back().BreakBeforeParameter && Current.NestingLevel == 0)
+ // If the return type spans multiple lines, wrap before the function name.
+ if ((Current.Type == TT_FunctionDeclarationName ||
+ Current.is(tok::kw_operator)) &&
+ State.Stack.back().BreakBeforeParameter)
return true;
+
if (startsSegmentOfBuilderTypeCall(Current) &&
(State.Stack.back().CallContinuation != 0 ||
(State.Stack.back().BreakBeforeParameter &&
@@ -268,7 +280,7 @@
Whitespaces.replaceWhitespace(Current, /*Newlines=*/0, /*IndentLevel=*/0,
Spaces, State.Column + Spaces);
- if (Current.Type == TT_ObjCSelectorName &&
+ if (Current.Type == TT_SelectorName &&
!State.Stack.back().ObjCSelectorNameFound) {
if (Current.LongestObjCSelectorName == 0)
State.Stack.back().AlignColons = false;
@@ -294,7 +306,7 @@
// Treat the condition inside an if as if it was a second function
// parameter, i.e. let nested calls have a continuation indent.
State.Stack.back().LastSpace = State.Column;
- else if (Current.isNot(tok::comment) &&
+ else if (!Current.isOneOf(tok::comment, tok::caret) &&
(Previous.is(tok::comma) ||
(Previous.is(tok::colon) && Previous.Type == TT_ObjCMethodExpr)))
State.Stack.back().LastSpace = State.Column;
@@ -363,7 +375,7 @@
if (NextNonComment->isMemberAccess()) {
if (State.Stack.back().CallContinuation == 0)
State.Stack.back().CallContinuation = State.Column;
- } else if (NextNonComment->Type == TT_ObjCSelectorName) {
+ } else if (NextNonComment->Type == TT_SelectorName) {
if (!State.Stack.back().ObjCSelectorNameFound) {
if (NextNonComment->LongestObjCSelectorName == 0) {
State.Stack.back().AlignColons = false;
@@ -404,10 +416,8 @@
State.Stack.back().BreakBeforeParameter = true;
if (!DryRun) {
- unsigned Newlines = 1;
- if (Current.is(tok::comment))
- Newlines = std::max(Newlines, std::min(Current.NewlinesBefore,
- Style.MaxEmptyLinesToKeep + 1));
+ unsigned Newlines = std::max(
+ 1u, std::min(Current.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1));
Whitespaces.replaceWhitespace(Current, Newlines,
State.Stack.back().IndentLevel, State.Column,
State.Column, State.Line->InPPDirective);
@@ -439,7 +449,9 @@
// If we break after { or the [ of an array initializer, we should also break
// before the corresponding } or ].
- if (Previous.is(tok::l_brace) || Previous.Type == TT_ArrayInitializerLSquare)
+ if (PreviousNonComment &&
+ (PreviousNonComment->is(tok::l_brace) ||
+ PreviousNonComment->Type == TT_ArrayInitializerLSquare))
State.Stack.back().BreakBeforeClosingBrace = true;
if (State.Stack.back().AvoidBinPacking) {
@@ -508,13 +520,11 @@
return State.Stack.back().VariablePos;
if ((PreviousNonComment && (PreviousNonComment->ClosesTemplateDeclaration ||
PreviousNonComment->Type == TT_AttributeParen)) ||
- ((NextNonComment->Type == TT_StartOfName ||
- NextNonComment->is(tok::kw_operator)) &&
- Current.NestingLevel == 0 &&
- (!Style.IndentFunctionDeclarationAfterType ||
- State.Line->StartsDefinition)))
+ (!Style.IndentWrappedFunctionNames &&
+ (NextNonComment->is(tok::kw_operator) ||
+ NextNonComment->Type == TT_FunctionDeclarationName)))
return std::max(State.Stack.back().LastSpace, State.Stack.back().Indent);
- if (NextNonComment->Type == TT_ObjCSelectorName) {
+ if (NextNonComment->Type == TT_SelectorName) {
if (!State.Stack.back().ObjCSelectorNameFound) {
if (NextNonComment->LongestObjCSelectorName == 0) {
return State.Stack.back().Indent;
@@ -587,10 +597,8 @@
if (Current.isMemberAccess())
State.Stack.back().StartOfFunctionCall =
Current.LastOperator ? 0 : State.Column + Current.ColumnWidth;
- if (Current.Type == TT_ObjCSelectorName)
+ if (Current.Type == TT_SelectorName)
State.Stack.back().ObjCSelectorNameFound = true;
- if (Current.Type == TT_LambdaLSquare)
- ++State.Stack.back().LambdasFound;
if (Current.Type == TT_CtorInitializerColon) {
// Indent 2 from the column, so:
// SomeClass::SomeClass()
@@ -736,27 +744,60 @@
}
}
-void ContinuationIndenter::moveStatePastFakeRParens(LineState &State) {
- const FormatToken &Current = *State.NextToken;
-
- // Remove scopes created by fake parenthesis.
- if (Current.isNot(tok::r_brace) ||
- (Current.MatchingParen && Current.MatchingParen->BlockKind != BK_Block)) {
- // Don't remove FakeRParens attached to r_braces that surround nested blocks
- // as they will have been removed early (see above).
- for (unsigned i = 0, e = Current.FakeRParens; i != e; ++i) {
- unsigned VariablePos = State.Stack.back().VariablePos;
- assert(State.Stack.size() > 1);
- if (State.Stack.size() == 1) {
- // Do not pop the last element.
- break;
- }
- State.Stack.pop_back();
- State.Stack.back().VariablePos = VariablePos;
+// Remove the fake r_parens after 'Tok'.
+static void consumeRParens(LineState& State, const FormatToken &Tok) {
+ for (unsigned i = 0, e = Tok.FakeRParens; i != e; ++i) {
+ unsigned VariablePos = State.Stack.back().VariablePos;
+ assert(State.Stack.size() > 1);
+ if (State.Stack.size() == 1) {
+ // Do not pop the last element.
+ break;
}
+ State.Stack.pop_back();
+ State.Stack.back().VariablePos = VariablePos;
}
}
+// Returns whether 'Tok' opens or closes a scope requiring special handling
+// of the subsequent fake r_parens.
+//
+// For example, if this is an l_brace starting a nested block, we pretend (wrt.
+// to indentation) that we already consumed the corresponding r_brace. Thus, we
+// remove all ParenStates caused by fake parentheses that end at the r_brace.
+// The net effect of this is that we don't indent relative to the l_brace, if
+// the nested block is the last parameter of a function. This formats:
+//
+// SomeFunction(a, [] {
+// f(); // break
+// });
+//
+// instead of:
+// SomeFunction(a, [] {
+// f(); // break
+// });
+static bool fakeRParenSpecialCase(const LineState &State) {
+ const FormatToken &Tok = *State.NextToken;
+ if (!Tok.MatchingParen)
+ return false;
+ const FormatToken *Left = &Tok;
+ if (Tok.isOneOf(tok::r_brace, tok::r_square))
+ Left = Tok.MatchingParen;
+ return !State.Stack.back().HasMultipleNestedBlocks &&
+ Left->isOneOf(tok::l_brace, tok::l_square) &&
+ (Left->BlockKind == BK_Block ||
+ Left->Type == TT_ArrayInitializerLSquare ||
+ Left->Type == TT_DictLiteral);
+}
+
+void ContinuationIndenter::moveStatePastFakeRParens(LineState &State) {
+ // Don't remove FakeRParens attached to r_braces that surround nested blocks
+ // as they will have been removed early (see above).
+ if (fakeRParenSpecialCase(State))
+ return;
+
+ consumeRParens(State, *State.NextToken);
+}
+
void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
bool Newline) {
const FormatToken &Current = *State.NextToken;
@@ -773,6 +814,9 @@
bool AvoidBinPacking;
bool BreakBeforeParameter = false;
if (Current.is(tok::l_brace) || Current.Type == TT_ArrayInitializerLSquare) {
+ if (fakeRParenSpecialCase(State))
+ consumeRParens(State, *Current.MatchingParen);
+
NewIndent = State.Stack.back().LastSpace;
if (Current.opensBlockTypeList(Style)) {
NewIndent += Style.IndentWidth;
@@ -812,6 +856,7 @@
State.Stack.back().LastSpace,
AvoidBinPacking, NoLineBreak));
State.Stack.back().BreakBeforeParameter = BreakBeforeParameter;
+ State.Stack.back().HasMultipleNestedBlocks = Current.BlockParameterCount > 1;
}
void ContinuationIndenter::moveStatePastScopeCloser(LineState &State) {
@@ -824,9 +869,9 @@
if (State.Stack.size() > 1 &&
(Current.isOneOf(tok::r_paren, tok::r_square) ||
(Current.is(tok::r_brace) && State.NextToken != State.Line->First) ||
- State.NextToken->Type == TT_TemplateCloser)) {
+ State.NextToken->Type == TT_TemplateCloser))
State.Stack.pop_back();
- }
+
if (Current.is(tok::r_square)) {
// If this ends the array subscript expr, reset the corresponding value.
const FormatToken *NextNonComment = Current.getNextNonComment();
@@ -836,35 +881,10 @@
}
void ContinuationIndenter::moveStateToNewBlock(LineState &State) {
- // If this is an l_brace starting a nested block, we pretend (wrt. to
- // indentation) that we already consumed the corresponding r_brace. Thus, we
- // remove all ParenStates caused by fake parentheses that end at the r_brace.
- // The net effect of this is that we don't indent relative to the l_brace, if
- // the nested block is the last parameter of a function. For example, this
- // formats:
- //
- // SomeFunction(a, [] {
- // f(); // break
- // });
- //
- // instead of:
- // SomeFunction(a, [] {
- // f(); // break
- // });
- //
// If we have already found more than one lambda introducers on this level, we
// opt out of this because similarity between the lambdas is more important.
- if (State.Stack.back().LambdasFound <= 1) {
- for (unsigned i = 0; i != State.NextToken->MatchingParen->FakeRParens;
- ++i) {
- assert(State.Stack.size() > 1);
- if (State.Stack.size() == 1) {
- // Do not pop the last element.
- break;
- }
- State.Stack.pop_back();
- }
- }
+ if (fakeRParenSpecialCase(State))
+ consumeRParens(State, *State.NextToken->MatchingParen);
// For some reason, ObjC blocks are indented like continuations.
unsigned NewIndent = State.Stack.back().LastSpace +
diff --git a/lib/Format/ContinuationIndenter.h b/lib/Format/ContinuationIndenter.h
index 4733bda..0969a8c 100644
--- a/lib/Format/ContinuationIndenter.h
+++ b/lib/Format/ContinuationIndenter.h
@@ -151,8 +151,8 @@
StartOfFunctionCall(0), StartOfArraySubscripts(0),
NestedNameSpecifierContinuation(0), CallContinuation(0), VariablePos(0),
ContainsLineBreak(false), ContainsUnwrappedBuilder(0),
- AlignColons(true), ObjCSelectorNameFound(false), LambdasFound(0),
- JSFunctionInlined(false) {}
+ AlignColons(true), ObjCSelectorNameFound(false),
+ HasMultipleNestedBlocks(false), JSFunctionInlined(false) {}
/// \brief The position to which a specific parenthesis level needs to be
/// indented.
@@ -247,11 +247,11 @@
/// the same token.
bool ObjCSelectorNameFound;
- /// \brief Counts the number of lambda introducers found on this level.
+ /// \brief \c true if there are multiple nested blocks inside these parens.
///
/// Not considered for memoization as it will always have the same value at
/// the same token.
- unsigned LambdasFound;
+ bool HasMultipleNestedBlocks;
// \brief The previous JavaScript 'function' keyword is not wrapped to a new
// line.
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index 7d0e102..be9bbed 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -97,6 +97,20 @@
};
template <>
+struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
+ static void enumeration(IO &IO,
+ FormatStyle::PointerAlignmentStyle &Value) {
+ IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle);
+ IO.enumCase(Value, "Left", FormatStyle::PAS_Left);
+ IO.enumCase(Value, "Right", FormatStyle::PAS_Right);
+
+ // For backward compability.
+ IO.enumCase(Value, "true", FormatStyle::PAS_Left);
+ IO.enumCase(Value, "false", FormatStyle::PAS_Right);
+ }
+};
+
+template <>
struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> {
static void enumeration(IO &IO,
FormatStyle::SpaceBeforeParensOptions &Value) {
@@ -173,10 +187,14 @@
IO.mapOptional("ColumnLimit", Style.ColumnLimit);
IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",
Style.ConstructorInitializerAllOnOneLineOrOnePerLine);
- IO.mapOptional("DerivePointerBinding", Style.DerivePointerBinding);
+ IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment);
IO.mapOptional("ExperimentalAutoDetectBinPacking",
Style.ExperimentalAutoDetectBinPacking);
IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
+ IO.mapOptional("IndentWrappedFunctionNames",
+ Style.IndentWrappedFunctionNames);
+ IO.mapOptional("IndentFunctionDeclarationAfterType",
+ Style.IndentWrappedFunctionNames);
IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
Style.KeepEmptyLinesAtTheStartOfBlocks);
@@ -193,7 +211,7 @@
IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);
IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
Style.PenaltyReturnTypeOnItsOwnLine);
- IO.mapOptional("PointerBindsToType", Style.PointerBindsToType);
+ IO.mapOptional("PointerAlignment", Style.PointerAlignment);
IO.mapOptional("SpacesBeforeTrailingComments",
Style.SpacesBeforeTrailingComments);
IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle);
@@ -202,8 +220,6 @@
IO.mapOptional("TabWidth", Style.TabWidth);
IO.mapOptional("UseTab", Style.UseTab);
IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
- IO.mapOptional("IndentFunctionDeclarationAfterType",
- Style.IndentFunctionDeclarationAfterType);
IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses);
IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);
IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses);
@@ -221,6 +237,8 @@
if (!IO.outputting()) {
IO.mapOptional("SpaceAfterControlStatementKeyword",
Style.SpaceBeforeParens);
+ IO.mapOptional("PointerBindsToType", Style.PointerAlignment);
+ IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment);
}
IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
IO.mapOptional("DisableFormat", Style.DisableFormat);
@@ -258,6 +276,30 @@
namespace clang {
namespace format {
+const std::error_category &getParseCategory() {
+ static ParseErrorCategory C;
+ return C;
+}
+std::error_code make_error_code(ParseError e) {
+ return std::error_code(static_cast<int>(e), getParseCategory());
+}
+
+const char *ParseErrorCategory::name() const LLVM_NOEXCEPT {
+ return "clang-format.parse_error";
+}
+
+std::string ParseErrorCategory::message(int EV) const {
+ switch (static_cast<ParseError>(EV)) {
+ case ParseError::Success:
+ return "Success";
+ case ParseError::Error:
+ return "Invalid argument";
+ case ParseError::Unsuitable:
+ return "Unsuitable";
+ }
+ llvm_unreachable("unexpected parse error");
+}
+
FormatStyle getLLVMStyle() {
FormatStyle LLVMStyle;
LLVMStyle.Language = FormatStyle::LK_Cpp;
@@ -282,13 +324,13 @@
LLVMStyle.ConstructorInitializerIndentWidth = 4;
LLVMStyle.ContinuationIndentWidth = 4;
LLVMStyle.Cpp11BracedListStyle = true;
- LLVMStyle.DerivePointerBinding = false;
+ LLVMStyle.DerivePointerAlignment = false;
LLVMStyle.ExperimentalAutoDetectBinPacking = false;
LLVMStyle.ForEachMacros.push_back("foreach");
LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
LLVMStyle.IndentCaseLabels = false;
- LLVMStyle.IndentFunctionDeclarationAfterType = false;
+ LLVMStyle.IndentWrappedFunctionNames = false;
LLVMStyle.IndentWidth = 2;
LLVMStyle.TabWidth = 8;
LLVMStyle.MaxEmptyLinesToKeep = 1;
@@ -296,7 +338,7 @@
LLVMStyle.NamespaceIndentation = FormatStyle::NI_None;
LLVMStyle.ObjCSpaceAfterProperty = false;
LLVMStyle.ObjCSpaceBeforeProtocolList = true;
- LLVMStyle.PointerBindsToType = false;
+ LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
LLVMStyle.SpacesBeforeTrailingComments = 1;
LLVMStyle.Standard = FormatStyle::LS_Cpp11;
LLVMStyle.UseTab = FormatStyle::UT_Never;
@@ -331,13 +373,12 @@
GoogleStyle.AlwaysBreakBeforeMultilineStrings = true;
GoogleStyle.AlwaysBreakTemplateDeclarations = true;
GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
- GoogleStyle.DerivePointerBinding = true;
+ GoogleStyle.DerivePointerAlignment = true;
GoogleStyle.IndentCaseLabels = true;
- GoogleStyle.IndentFunctionDeclarationAfterType = true;
GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false;
GoogleStyle.ObjCSpaceAfterProperty = false;
GoogleStyle.ObjCSpaceBeforeProtocolList = false;
- GoogleStyle.PointerBindsToType = true;
+ GoogleStyle.PointerAlignment = FormatStyle::PAS_Left;
GoogleStyle.SpacesBeforeTrailingComments = 2;
GoogleStyle.Standard = FormatStyle::LS_Auto;
@@ -363,7 +404,7 @@
ChromiumStyle.AllowShortIfStatementsOnASingleLine = false;
ChromiumStyle.AllowShortLoopsOnASingleLine = false;
ChromiumStyle.BinPackParameters = false;
- ChromiumStyle.DerivePointerBinding = false;
+ ChromiumStyle.DerivePointerAlignment = false;
ChromiumStyle.Standard = FormatStyle::LS_Cpp03;
return ChromiumStyle;
}
@@ -373,12 +414,12 @@
MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
MozillaStyle.Cpp11BracedListStyle = false;
MozillaStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
- MozillaStyle.DerivePointerBinding = true;
+ MozillaStyle.DerivePointerAlignment = true;
MozillaStyle.IndentCaseLabels = true;
MozillaStyle.ObjCSpaceAfterProperty = true;
MozillaStyle.ObjCSpaceBeforeProtocolList = false;
MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;
- MozillaStyle.PointerBindsToType = true;
+ MozillaStyle.PointerAlignment = FormatStyle::PAS_Left;
MozillaStyle.Standard = FormatStyle::LS_Cpp03;
return MozillaStyle;
}
@@ -395,7 +436,7 @@
Style.IndentWidth = 4;
Style.NamespaceIndentation = FormatStyle::NI_Inner;
Style.ObjCSpaceAfterProperty = true;
- Style.PointerBindsToType = true;
+ Style.PointerAlignment = FormatStyle::PAS_Left;
Style.Standard = FormatStyle::LS_Cpp03;
return Style;
}
@@ -442,12 +483,12 @@
return true;
}
-llvm::error_code parseConfiguration(StringRef Text, FormatStyle *Style) {
+std::error_code parseConfiguration(StringRef Text, FormatStyle *Style) {
assert(Style);
FormatStyle::LanguageKind Language = Style->Language;
assert(Language != FormatStyle::LK_None);
if (Text.trim().empty())
- return llvm::make_error_code(llvm::errc::invalid_argument);
+ return make_error_code(ParseError::Error);
std::vector<FormatStyle> Styles;
llvm::yaml::Input Input(Text);
@@ -463,14 +504,14 @@
for (unsigned i = 0; i < Styles.size(); ++i) {
// Ensures that only the first configuration can skip the Language option.
if (Styles[i].Language == FormatStyle::LK_None && i != 0)
- return llvm::make_error_code(llvm::errc::invalid_argument);
+ return make_error_code(ParseError::Error);
// Ensure that each language is configured at most once.
for (unsigned j = 0; j < i; ++j) {
if (Styles[i].Language == Styles[j].Language) {
DEBUG(llvm::dbgs()
<< "Duplicate languages in the config file on positions " << j
<< " and " << i << "\n");
- return llvm::make_error_code(llvm::errc::invalid_argument);
+ return make_error_code(ParseError::Error);
}
}
}
@@ -482,10 +523,10 @@
Styles[i].Language == FormatStyle::LK_None) {
*Style = Styles[i];
Style->Language = Language;
- return llvm::error_code::success();
+ return make_error_code(ParseError::Success);
}
}
- return llvm::make_error_code(llvm::errc::not_supported);
+ return make_error_code(ParseError::Unsuitable);
}
std::string configurationAsText(const FormatStyle &Style) {
@@ -1164,7 +1205,8 @@
return true;
if (NewLine) {
- int AdditionalIndent = 0;
+ int AdditionalIndent =
+ State.FirstIndent - State.Line->Level * Style.IndentWidth;
if (State.Stack.size() < 2 ||
!State.Stack[State.Stack.size() - 2].JSFunctionInlined) {
AdditionalIndent = State.Stack.back().Indent -
@@ -1881,11 +1923,11 @@
Tok = Tok->Next;
}
}
- if (Style.DerivePointerBinding) {
+ if (Style.DerivePointerAlignment) {
if (CountBoundToType > CountBoundToVariable)
- Style.PointerBindsToType = true;
+ Style.PointerAlignment = FormatStyle::PAS_Left;
else if (CountBoundToType < CountBoundToVariable)
- Style.PointerBindsToType = false;
+ Style.PointerAlignment = FormatStyle::PAS_Right;
}
if (Style.Standard == FormatStyle::LS_Auto) {
Style.Standard = HasCpp03IncompatibleFormat ? FormatStyle::LS_Cpp11
@@ -2001,7 +2043,7 @@
if (StyleName.startswith("{")) {
// Parse YAML/JSON style from the command line.
- if (llvm::error_code ec = parseConfiguration(StyleName, &Style)) {
+ if (std::error_code ec = parseConfiguration(StyleName, &Style)) {
llvm::errs() << "Error parsing -style: " << ec.message() << ", using "
<< FallbackStyle << " style\n";
}
@@ -2041,14 +2083,15 @@
}
if (IsFile) {
- std::unique_ptr<llvm::MemoryBuffer> Text;
- if (llvm::error_code ec =
- llvm::MemoryBuffer::getFile(ConfigFile.c_str(), Text)) {
- llvm::errs() << ec.message() << "\n";
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
+ llvm::MemoryBuffer::getFile(ConfigFile.c_str());
+ if (std::error_code EC = Text.getError()) {
+ llvm::errs() << EC.message() << "\n";
break;
}
- if (llvm::error_code ec = parseConfiguration(Text->getBuffer(), &Style)) {
- if (ec == llvm::errc::not_supported) {
+ if (std::error_code ec =
+ parseConfiguration(Text.get()->getBuffer(), &Style)) {
+ if (ec == ParseError::Unsuitable) {
if (!UnsuitableConfigFiles.empty())
UnsuitableConfigFiles.append(", ");
UnsuitableConfigFiles.append(ConfigFile);
diff --git a/lib/Format/FormatToken.h b/lib/Format/FormatToken.h
index f2bba32..c376c50 100644
--- a/lib/Format/FormatToken.h
+++ b/lib/Format/FormatToken.h
@@ -40,6 +40,7 @@
TT_CtorInitializerComma,
TT_DesignatedInitializerPeriod,
TT_DictLiteral,
+ TT_FunctionDeclarationName,
TT_FunctionLBrace,
TT_FunctionTypeLParen,
TT_ImplicitStringLiteral,
@@ -54,13 +55,13 @@
TT_ObjCMethodExpr,
TT_ObjCMethodSpecifier,
TT_ObjCProperty,
- TT_ObjCSelectorName,
TT_OverloadedOperator,
TT_OverloadedOperatorLParen,
TT_PointerOrReference,
TT_PureVirtualSpecifier,
TT_RangeBasedForLoopColon,
TT_RegexLiteral,
+ TT_SelectorName,
TT_StartOfName,
TT_TemplateCloser,
TT_TemplateOpener,
@@ -103,9 +104,10 @@
IsFirst(false), MustBreakBefore(false), IsUnterminatedLiteral(false),
BlockKind(BK_Unknown), Type(TT_Unknown), SpacesRequiredBefore(0),
CanBreakBefore(false), ClosesTemplateDeclaration(false),
- ParameterCount(0), PackingKind(PPK_Inconclusive), TotalLength(0),
- UnbreakableTailLength(0), BindingStrength(0), NestingLevel(0),
- SplitPenalty(0), LongestObjCSelectorName(0), FakeRParens(0),
+ ParameterCount(0), BlockParameterCount(0),
+ PackingKind(PPK_Inconclusive), TotalLength(0), UnbreakableTailLength(0),
+ BindingStrength(0), NestingLevel(0), SplitPenalty(0),
+ LongestObjCSelectorName(0), FakeRParens(0),
StartsBinaryExpression(false), EndsBinaryExpression(false),
OperatorIndex(0), LastOperator(false),
PartOfMultiVariableDeclStmt(false), IsForEachMacro(false),
@@ -191,6 +193,10 @@
/// the number of commas.
unsigned ParameterCount;
+ /// \brief Number of parameters that are nested blocks,
+ /// if this is "(", "[" or "<".
+ unsigned BlockParameterCount;
+
/// \brief A token can have a special role that can carry extra information
/// about the token's formatting.
std::unique_ptr<TokenRole> Role;
@@ -318,7 +324,7 @@
/// \brief Returns \c true if this is a "." or "->" accessing a member.
bool isMemberAccess() const {
- return isOneOf(tok::arrow, tok::period) &&
+ return isOneOf(tok::arrow, tok::period, tok::arrowstar) &&
Type != TT_DesignatedInitializerPeriod;
}
diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp
index 3fea52b..afa9840 100644
--- a/lib/Format/TokenAnnotator.cpp
+++ b/lib/Format/TokenAnnotator.cpp
@@ -164,6 +164,8 @@
CurrentToken->Previous->Previous->isOneOf(tok::l_paren,
tok::coloncolon))
MightBeFunctionType = true;
+ if (CurrentToken->Previous->Type == TT_BinaryOperator)
+ Contexts.back().IsExpression = true;
if (CurrentToken->is(tok::r_paren)) {
if (MightBeFunctionType && CurrentToken->Next &&
(CurrentToken->Next->is(tok::l_paren) ||
@@ -198,7 +200,6 @@
return false;
else if (CurrentToken->is(tok::l_brace))
Left->Type = TT_Unknown; // Not TT_ObjCBlockLParen
- updateParameterCount(Left, CurrentToken);
if (CurrentToken->is(tok::comma) && CurrentToken->Next &&
!CurrentToken->Next->HasUnescapedNewline &&
!CurrentToken->Next->isTrailingComment())
@@ -206,8 +207,10 @@
if (CurrentToken->isOneOf(tok::kw_const, tok::kw_auto) ||
CurrentToken->isSimpleTypeSpecifier())
Contexts.back().IsExpression = false;
+ FormatToken *Tok = CurrentToken;
if (!consumeToken())
return false;
+ updateParameterCount(Left, Tok);
if (CurrentToken && CurrentToken->HasUnescapedNewline)
HasMultipleLines = true;
}
@@ -266,7 +269,7 @@
if (Contexts.back().FirstObjCSelectorName) {
Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
Contexts.back().LongestObjCSelectorName;
- if (Contexts.back().NumBlockParameters > 1)
+ if (Left->BlockParameterCount > 1)
Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = 0;
}
next();
@@ -281,9 +284,10 @@
(Left->Type == TT_ArraySubscriptLSquare ||
(Left->Type == TT_ObjCMethodExpr && !ColonFound)))
Left->Type = TT_ArrayInitializerLSquare;
- updateParameterCount(Left, CurrentToken);
+ FormatToken* Tok = CurrentToken;
if (!consumeToken())
return false;
+ updateParameterCount(Left, Tok);
}
return false;
}
@@ -312,18 +316,25 @@
return false;
updateParameterCount(Left, CurrentToken);
if (CurrentToken->is(tok::colon) &&
- Style.Language != FormatStyle::LK_Proto)
+ Style.Language != FormatStyle::LK_Proto) {
+ if (CurrentToken->getPreviousNonComment()->is(tok::identifier))
+ CurrentToken->getPreviousNonComment()->Type = TT_SelectorName;
Left->Type = TT_DictLiteral;
+ }
if (!consumeToken())
return false;
}
}
- // No closing "}" found, this probably starts a definition.
- Line.StartsDefinition = true;
return true;
}
void updateParameterCount(FormatToken *Left, FormatToken *Current) {
+ if (Current->Type == TT_LambdaLSquare ||
+ (Current->is(tok::caret) && Current->Type == TT_UnaryOperator) ||
+ (Style.Language == FormatStyle::LK_JavaScript &&
+ Current->TokenText == "function")) {
+ ++Left->BlockParameterCount;
+ }
if (Current->is(tok::comma)) {
++Left->ParameterCount;
if (!Left->Role)
@@ -381,7 +392,7 @@
} else if (Contexts.back().ColonIsObjCMethodExpr ||
Line.First->Type == TT_ObjCMethodSpecifier) {
Tok->Type = TT_ObjCMethodExpr;
- Tok->Previous->Type = TT_ObjCSelectorName;
+ Tok->Previous->Type = TT_SelectorName;
if (Tok->Previous->ColumnWidth >
Contexts.back().LongestObjCSelectorName) {
Contexts.back().LongestObjCSelectorName = Tok->Previous->ColumnWidth;
@@ -392,7 +403,8 @@
Tok->Type = TT_RangeBasedForLoopColon;
} else if (CurrentToken && CurrentToken->is(tok::numeric_constant)) {
Tok->Type = TT_BitFieldColon;
- } else if (Contexts.size() == 1 && Line.First->isNot(tok::kw_enum)) {
+ } else if (Contexts.size() == 1 &&
+ !Line.First->isOneOf(tok::kw_enum, tok::kw_case)) {
Tok->Type = TT_InheritanceColon;
} else if (Contexts.back().ContextKind == tok::l_paren) {
Tok->Type = TT_InlineASMColon;
@@ -638,17 +650,16 @@
Context(tok::TokenKind ContextKind, unsigned BindingStrength,
bool IsExpression)
: ContextKind(ContextKind), BindingStrength(BindingStrength),
- LongestObjCSelectorName(0), NumBlockParameters(0),
- ColonIsForRangeExpr(false), ColonIsDictLiteral(false),
- ColonIsObjCMethodExpr(false), FirstObjCSelectorName(nullptr),
- FirstStartOfName(nullptr), IsExpression(IsExpression),
- CanBeExpression(true), InTemplateArgument(false),
- InCtorInitializer(false), CaretFound(false), IsForEachMacro(false) {}
+ LongestObjCSelectorName(0), ColonIsForRangeExpr(false),
+ ColonIsDictLiteral(false), ColonIsObjCMethodExpr(false),
+ FirstObjCSelectorName(nullptr), FirstStartOfName(nullptr),
+ IsExpression(IsExpression), CanBeExpression(true),
+ InTemplateArgument(false), InCtorInitializer(false),
+ CaretFound(false), IsForEachMacro(false) {}
tok::TokenKind ContextKind;
unsigned BindingStrength;
unsigned LongestObjCSelectorName;
- unsigned NumBlockParameters;
bool ColonIsForRangeExpr;
bool ColonIsDictLiteral;
bool ColonIsObjCMethodExpr;
@@ -741,10 +752,8 @@
Contexts.back().InTemplateArgument);
} else if (Current.isOneOf(tok::minus, tok::plus, tok::caret)) {
Current.Type = determinePlusMinusCaretUsage(Current);
- if (Current.Type == TT_UnaryOperator && Current.is(tok::caret)) {
- ++Contexts.back().NumBlockParameters;
+ if (Current.Type == TT_UnaryOperator && Current.is(tok::caret))
Contexts.back().CaretFound = true;
- }
} else if (Current.isOneOf(tok::minusminus, tok::plusplus)) {
Current.Type = determineIncrementUsage(Current);
} else if (Current.is(tok::exclaim)) {
@@ -829,7 +838,7 @@
/// \brief Determine whether ')' is ending a cast.
bool rParenEndsCast(const FormatToken &Tok) {
- FormatToken *LeftOfParens = NULL;
+ FormatToken *LeftOfParens = nullptr;
if (Tok.MatchingParen)
LeftOfParens = Tok.MatchingParen->getPreviousNonComment();
bool IsCast = false;
@@ -852,8 +861,9 @@
IsCast = true;
// If there is an identifier after the (), it is likely a cast, unless
// there is also an identifier before the ().
- else if (LeftOfParens && (LeftOfParens->Tok.getIdentifierInfo() == NULL ||
- LeftOfParens->is(tok::kw_return)) &&
+ else if (LeftOfParens &&
+ (LeftOfParens->Tok.getIdentifierInfo() == nullptr ||
+ LeftOfParens->is(tok::kw_return)) &&
LeftOfParens->Type != TT_OverloadedOperator &&
LeftOfParens->isNot(tok::at) &&
LeftOfParens->Type != TT_TemplateCloser && Tok.Next) {
@@ -891,7 +901,7 @@
return TT_UnaryOperator;
const FormatToken *NextToken = Tok.getNextNonComment();
- if (!NextToken)
+ if (!NextToken || NextToken->is(tok::l_brace))
return TT_Unknown;
if (PrevToken->is(tok::coloncolon) ||
@@ -908,10 +918,13 @@
if (NextToken->is(tok::l_square) && NextToken->Type != TT_LambdaLSquare)
return TT_PointerOrReference;
+ if (NextToken->is(tok::kw_operator))
+ return TT_PointerOrReference;
if (PrevToken->is(tok::r_paren) && PrevToken->MatchingParen &&
PrevToken->MatchingParen->Previous &&
- PrevToken->MatchingParen->Previous->is(tok::kw_typeof))
+ PrevToken->MatchingParen->Previous->isOneOf(tok::kw_typeof,
+ tok::kw_decltype))
return TT_PointerOrReference;
if (PrevToken->Tok.isLiteral() ||
@@ -926,6 +939,12 @@
(InTemplateArgument && NextToken->Tok.isAnyIdentifier()))
return TT_BinaryOperator;
+ // This catches some cases where evaluation order is used as control flow:
+ // aaa && aaa->f();
+ const FormatToken *NextNextToken = NextToken->getNextNonComment();
+ if (NextNextToken && NextNextToken->is(tok::arrow))
+ return TT_BinaryOperator;
+
// It is very unlikely that we are going to find a pointer or reference type
// definition on the RHS of an assignment.
if (IsExpression)
@@ -993,7 +1012,8 @@
// expression.
while (Current &&
(Current->is(tok::kw_return) ||
- (Current->is(tok::colon) && Current->Type == TT_ObjCMethodExpr)))
+ (Current->is(tok::colon) && (Current->Type == TT_ObjCMethodExpr ||
+ Current->Type == TT_DictLiteral))))
next();
if (!Current || Precedence > PrecedenceArrowAndPeriod)
@@ -1022,7 +1042,7 @@
int CurrentPrecedence = getCurrentPrecedence();
- if (Current && Current->Type == TT_ObjCSelectorName &&
+ if (Current && Current->Type == TT_SelectorName &&
Precedence == CurrentPrecedence) {
if (LatestOperator)
addFakeParenthesis(Start, prec::Level(Precedence));
@@ -1073,7 +1093,7 @@
if (Current->Type == TT_ConditionalExpr)
return prec::Conditional;
else if (Current->is(tok::semi) || Current->Type == TT_InlineASMColon ||
- Current->Type == TT_ObjCSelectorName)
+ Current->Type == TT_SelectorName)
return 0;
else if (Current->Type == TT_RangeBasedForLoopColon)
return prec::Comma;
@@ -1179,6 +1199,43 @@
Line.First->CanBreakBefore = Line.First->MustBreakBefore;
}
+// This function heuristically determines whether 'Current' starts the name of a
+// function declaration.
+static bool isFunctionDeclarationName(const FormatToken &Current) {
+ if (Current.Type != TT_StartOfName ||
+ Current.NestingLevel != 0 ||
+ Current.Previous->Type == TT_StartOfName)
+ return false;
+ const FormatToken *Next = Current.Next;
+ for (; Next; Next = Next->Next) {
+ if (Next->Type == TT_TemplateOpener) {
+ Next = Next->MatchingParen;
+ } else if (Next->is(tok::coloncolon)) {
+ Next = Next->Next;
+ if (!Next || !Next->is(tok::identifier))
+ return false;
+ } else if (Next->is(tok::l_paren)) {
+ break;
+ } else {
+ return false;
+ }
+ }
+ if (!Next)
+ return false;
+ assert(Next->is(tok::l_paren));
+ if (Next->Next == Next->MatchingParen)
+ return true;
+ for (const FormatToken *Tok = Next->Next; Tok != Next->MatchingParen;
+ Tok = Tok->Next) {
+ if (Tok->is(tok::kw_const) || Tok->isSimpleTypeSpecifier() ||
+ Tok->Type == TT_PointerOrReference || Tok->Type == TT_StartOfName)
+ return true;
+ if (Tok->isOneOf(tok::l_brace, tok::string_literal) || Tok->Tok.isLiteral())
+ return false;
+ }
+ return false;
+}
+
void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
for (SmallVectorImpl<AnnotatedLine *>::iterator I = Line.Children.begin(),
E = Line.Children.end();
@@ -1193,6 +1250,8 @@
FormatToken *Current = Line.First->Next;
bool InFunctionDecl = Line.MightBeFunctionDecl;
while (Current) {
+ if (isFunctionDeclarationName(*Current))
+ Current->Type = TT_FunctionDeclarationName;
if (Current->Type == TT_LineComment) {
if (Current->Previous->BlockKind == BK_BracedInit &&
Current->Previous->opensScope())
@@ -1295,10 +1354,11 @@
if (Right.is(tok::l_square)) {
if (Style.Language == FormatStyle::LK_Proto)
return 1;
- if (Right.Type != TT_ObjCMethodExpr)
- return 250;
+ if (Right.Type != TT_ObjCMethodExpr && Right.Type != TT_LambdaLSquare)
+ return 500;
}
- if (Right.Type == TT_StartOfName || Right.is(tok::kw_operator)) {
+ if (Right.Type == TT_StartOfName ||
+ Right.Type == TT_FunctionDeclarationName || Right.is(tok::kw_operator)) {
if (Line.First->is(tok::kw_for) && Right.PartOfMultiVariableDeclStmt)
return 3;
if (Left.Type == TT_StartOfName)
@@ -1328,8 +1388,8 @@
return 150;
}
- if (Right.Type == TT_TrailingAnnotation && Right.Next &&
- Right.Next->isNot(tok::l_paren)) {
+ if (Right.Type == TT_TrailingAnnotation &&
+ (!Right.Next || Right.Next->isNot(tok::l_paren))) {
// Generally, breaking before a trailing annotation is bad unless it is
// function-like. It seems to be especially preferable to keep standard
// annotations (i.e. "const", "final" and "override") on the same line.
@@ -1345,7 +1405,7 @@
// In Objective-C method expressions, prefer breaking before "param:" over
// breaking after it.
- if (Right.Type == TT_ObjCSelectorName)
+ if (Right.Type == TT_SelectorName)
return 0;
if (Left.is(tok::colon) && Left.Type == TT_ObjCMethodExpr)
return Line.MightBeFunctionDecl ? 50 : 500;
@@ -1386,6 +1446,10 @@
const FormatToken &Left,
const FormatToken &Right) {
if (Style.Language == FormatStyle::LK_Proto) {
+ if (Right.is(tok::period) &&
+ (Left.TokenText == "optional" || Left.TokenText == "required" ||
+ Left.TokenText == "repeated"))
+ return true;
if (Right.is(tok::l_paren) &&
(Left.TokenText == "returns" || Left.TokenText == "option"))
return true;
@@ -1442,14 +1506,14 @@
if (Right.Type == TT_PointerOrReference)
return Left.Tok.isLiteral() ||
((Left.Type != TT_PointerOrReference) && Left.isNot(tok::l_paren) &&
- !Style.PointerBindsToType);
+ Style.PointerAlignment != FormatStyle::PAS_Left);
if (Right.Type == TT_FunctionTypeLParen && Left.isNot(tok::l_paren) &&
- (Left.Type != TT_PointerOrReference || Style.PointerBindsToType))
+ (Left.Type != TT_PointerOrReference || Style.PointerAlignment != FormatStyle::PAS_Right))
return true;
if (Left.Type == TT_PointerOrReference)
return Right.Tok.isLiteral() || Right.Type == TT_BlockComment ||
((Right.Type != TT_PointerOrReference) &&
- Right.isNot(tok::l_paren) && Style.PointerBindsToType &&
+ Right.isNot(tok::l_paren) && Style.PointerAlignment != FormatStyle::PAS_Right &&
Left.Previous &&
!Left.Previous->isOneOf(tok::l_paren, tok::coloncolon));
if (Right.is(tok::star) && Left.is(tok::l_paren))
@@ -1492,7 +1556,8 @@
if (Right.Type == TT_UnaryOperator)
return !Left.isOneOf(tok::l_paren, tok::l_square, tok::at) &&
(Left.isNot(tok::colon) || Left.Type != TT_ObjCMethodExpr);
- if ((Left.isOneOf(tok::identifier, tok::greater, tok::r_square) ||
+ if ((Left.isOneOf(tok::identifier, tok::greater, tok::r_square,
+ tok::r_paren) ||
Left.isSimpleTypeSpecifier()) &&
Right.is(tok::l_brace) && Right.getNextNonComment() &&
Right.BlockKind != BK_Block)
@@ -1569,9 +1634,17 @@
return spaceRequiredBetween(Line, *Tok.Previous, Tok);
}
+// Returns 'true' if 'Tok' is a brace we'd want to break before in Allman style.
+static bool isAllmanBrace(const FormatToken &Tok) {
+ return Tok.is(tok::l_brace) && Tok.BlockKind == BK_Block &&
+ Tok.Type != TT_ObjCBlockLBrace && Tok.Type != TT_DictLiteral;
+}
+
bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
const FormatToken &Right) {
const FormatToken &Left = *Right.Previous;
+ if (Right.NewlinesBefore > 1)
+ return true;
if (Right.is(tok::comment)) {
return Right.Previous->BlockKind != BK_BracedInit &&
Right.Previous->Type != TT_CtorInitializerColon &&
@@ -1595,10 +1668,6 @@
Style.BreakConstructorInitializersBeforeComma &&
!Style.ConstructorInitializerAllOnOneLineOrOnePerLine) {
return true;
- } else if (Right.is(tok::l_brace) && Right.BlockKind == BK_Block &&
- Right.Type != TT_ObjCBlockLBrace && Right.Type != TT_DictLiteral) {
- return Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
- Style.BreakBeforeBraces == FormatStyle::BS_GNU;
} else if (Right.is(tok::string_literal) &&
Right.TokenText.startswith("R\"")) {
// Raw string literals are special wrt. line breaks. The author has made a
@@ -1609,6 +1678,9 @@
Style.Language == FormatStyle::LK_Proto) {
// Don't enums onto single lines in protocol buffers.
return true;
+ } else if (isAllmanBrace(Left) || isAllmanBrace(Right)) {
+ return Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
+ Style.BreakBeforeBraces == FormatStyle::BS_GNU;
}
// If the last token before a '}' is a comma or a comment, the intention is to
@@ -1640,7 +1712,8 @@
return false;
if (Left.Tok.getObjCKeywordID() == tok::objc_interface)
return false;
- if (Right.Type == TT_StartOfName || Right.is(tok::kw_operator))
+ if (Right.Type == TT_StartOfName ||
+ Right.Type == TT_FunctionDeclarationName || Right.is(tok::kw_operator))
return true;
if (Right.isTrailingComment())
// We rely on MustBreakBefore being set correctly here as we should not
@@ -1655,15 +1728,15 @@
return Style.BreakBeforeTernaryOperators;
if (Left.Type == TT_ConditionalExpr || Left.is(tok::question))
return !Style.BreakBeforeTernaryOperators;
- if (Right.is(tok::colon) &&
- (Right.Type == TT_DictLiteral || Right.Type == TT_ObjCMethodExpr))
- return false;
if (Right.Type == TT_InheritanceColon)
return true;
+ if (Right.is(tok::colon) && (Right.Type != TT_CtorInitializerColon &&
+ Right.Type != TT_InlineASMColon))
+ return false;
if (Left.is(tok::colon) &&
(Left.Type == TT_DictLiteral || Left.Type == TT_ObjCMethodExpr))
return true;
- if (Right.Type == TT_ObjCSelectorName)
+ if (Right.Type == TT_SelectorName)
return true;
if (Left.is(tok::r_paren) && Line.Type == LT_ObjCProperty)
return true;
@@ -1728,12 +1801,13 @@
return true;
if (Left.Type == TT_ArrayInitializerLSquare)
return true;
- return (Left.isBinaryOperator() && Left.isNot(tok::lessless) &&
+ return (Left.isBinaryOperator() &&
+ !Left.isOneOf(tok::arrowstar, tok::lessless) &&
!Style.BreakBeforeBinaryOperators) ||
Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace,
tok::kw_class, tok::kw_struct) ||
- Right.isOneOf(tok::lessless, tok::arrow, tok::period, tok::colon,
- tok::l_square, tok::at) ||
+ Right.isMemberAccess() ||
+ Right.isOneOf(tok::lessless, tok::colon, tok::l_square, tok::at) ||
(Left.is(tok::r_paren) &&
Right.isOneOf(tok::identifier, tok::kw_const)) ||
(Left.is(tok::l_paren) && !Right.is(tok::r_paren));
@@ -1746,6 +1820,7 @@
llvm::errs() << " M=" << Tok->MustBreakBefore
<< " C=" << Tok->CanBreakBefore << " T=" << Tok->Type
<< " S=" << Tok->SpacesRequiredBefore
+ << " B=" << Tok->BlockParameterCount
<< " P=" << Tok->SplitPenalty << " Name=" << Tok->Tok.getName()
<< " L=" << Tok->TotalLength << " PPK=" << Tok->PackingKind
<< " FakeLParens=";
diff --git a/lib/Format/TokenAnnotator.h b/lib/Format/TokenAnnotator.h
index 0df70a0..36de010 100644
--- a/lib/Format/TokenAnnotator.h
+++ b/lib/Format/TokenAnnotator.h
@@ -41,8 +41,8 @@
: First(Line.Tokens.front().Tok), Level(Line.Level),
InPPDirective(Line.InPPDirective),
MustBeDeclaration(Line.MustBeDeclaration), MightBeFunctionDecl(false),
- StartsDefinition(false), Affected(false),
- LeadingEmptyLinesAffected(false), ChildrenAffected(false) {
+ Affected(false), LeadingEmptyLinesAffected(false),
+ ChildrenAffected(false) {
assert(!Line.Tokens.empty());
// Calculate Next and Previous for all tokens. Note that we must overwrite
@@ -86,7 +86,6 @@
bool InPPDirective;
bool MustBeDeclaration;
bool MightBeFunctionDecl;
- bool StartsDefinition;
/// \c True if this line should be formatted, i.e. intersects directly or
/// indirectly with one of the input ranges.
diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp
index d0750af..20dd573 100644
--- a/lib/Format/UnwrappedLineParser.cpp
+++ b/lib/Format/UnwrappedLineParser.cpp
@@ -770,7 +770,10 @@
return;
case tok::identifier: {
StringRef Text = FormatTok->TokenText;
- if (Style.Language == FormatStyle::LK_JavaScript && Text == "function") {
+ // 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;
}
@@ -891,6 +894,8 @@
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)) {
@@ -905,6 +910,11 @@
void UnwrappedLineParser::tryToParseJSFunction() {
nextToken();
+
+ // Consume function name.
+ if (FormatTok->is(tok::identifier))
+ nextToken();
+
if (FormatTok->isNot(tok::l_paren))
return;
nextToken();