aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Format
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Format')
-rw-r--r--clang/lib/Format/ContinuationIndenter.cpp121
-rw-r--r--clang/lib/Format/ContinuationIndenter.h51
-rw-r--r--clang/lib/Format/Format.cpp33
-rw-r--r--clang/lib/Format/FormatToken.h182
-rw-r--r--clang/lib/Format/FormatTokenLexer.cpp15
-rw-r--r--clang/lib/Format/IntegerLiteralSeparatorFixer.cpp35
-rw-r--r--clang/lib/Format/QualifierAlignmentFixer.cpp17
-rw-r--r--clang/lib/Format/TokenAnnotator.cpp38
-rw-r--r--clang/lib/Format/UnwrappedLineFormatter.cpp14
-rw-r--r--clang/lib/Format/UnwrappedLineParser.cpp145
-rw-r--r--clang/lib/Format/UnwrappedLineParser.h6
-rw-r--r--clang/lib/Format/WhitespaceManager.cpp81
-rw-r--r--clang/lib/Format/WhitespaceManager.h25
13 files changed, 531 insertions, 232 deletions
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp
index 9ab024a..1272bb7 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -240,6 +240,45 @@ RawStringFormatStyleManager::getEnclosingFunctionStyle(
return It->second;
}
+IndentationAndAlignment
+IndentationAndAlignment::addPadding(unsigned Spaces) const {
+ return IndentationAndAlignment(Total + Spaces, IndentedFrom);
+}
+
+IndentationAndAlignment
+IndentationAndAlignment::operator+(unsigned Spaces) const {
+ return IndentationAndAlignment(Total + Spaces, Total);
+}
+
+IndentationAndAlignment
+IndentationAndAlignment::operator-(unsigned Spaces) const {
+ return IndentationAndAlignment(Total - Spaces, Total);
+}
+
+IndentationAndAlignment &IndentationAndAlignment::operator+=(unsigned Spaces) {
+ *this = *this + Spaces;
+ return *this;
+}
+
+IndentationAndAlignment::IndentationAndAlignment(unsigned Total,
+ unsigned IndentedFrom)
+ : Total(Total), IndentedFrom(IndentedFrom) {}
+
+IndentationAndAlignment::IndentationAndAlignment(unsigned Spaces)
+ : Total(Spaces), IndentedFrom(Spaces) {}
+
+bool IndentationAndAlignment::operator<(
+ const IndentationAndAlignment &Other) const {
+ if (Total != Other.Total)
+ return Total < Other.Total;
+ // The sign to use here was decided arbitrarily. This operator is mostly used
+ // when a line's indentation should be the max of 2 things. Using this sign
+ // here makes the program prefer alignment over continuation indentation. That
+ // is, it makes the alignment step that follows prefer to move the line when
+ // aligning the previous line.
+ return IndentedFrom > Other.IndentedFrom;
+}
+
ContinuationIndenter::ContinuationIndenter(const FormatStyle &Style,
const AdditionalKeywords &Keywords,
const SourceManager &SourceMgr,
@@ -491,7 +530,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
return true;
}
- unsigned NewLineColumn = getNewLineColumn(State);
+ unsigned NewLineColumn = getNewLineColumn(State).Total;
if (Current.isMemberAccess() && Style.ColumnLimit != 0 &&
State.Column + getLengthToNextOperator(Current) > Style.ColumnLimit &&
(State.Column > NewLineColumn ||
@@ -819,8 +858,9 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
}
if (Current.is(TT_SelectorName) && !CurrentState.ObjCSelectorNameFound) {
- unsigned MinIndent = std::max(
- State.FirstIndent + Style.ContinuationIndentWidth, CurrentState.Indent);
+ unsigned MinIndent =
+ std::max(State.FirstIndent + Style.ContinuationIndentWidth,
+ CurrentState.Indent.Total);
unsigned FirstColonPos = State.Column + Spaces + Current.ColumnWidth;
if (Current.LongestObjCSelectorName == 0)
CurrentState.AlignColons = false;
@@ -910,7 +950,8 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
return !Next || Next->isMemberAccess() ||
Next->is(TT_FunctionDeclarationLParen) || IsFunctionCallParen(*Next);
};
- if (IsOpeningBracket(Previous) && State.Column > getNewLineColumn(State) &&
+ if (IsOpeningBracket(Previous) &&
+ State.Column > getNewLineColumn(State).Total &&
// Don't do this for simple (no expressions) one-argument function calls
// as that feels like needlessly wasting whitespace, e.g.:
//
@@ -955,7 +996,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
CurrentState.NoLineBreak = true;
if (startsSegmentOfBuilderTypeCall(Current) &&
- State.Column > getNewLineColumn(State)) {
+ State.Column > getNewLineColumn(State).Total) {
CurrentState.ContainsUnwrappedBuilder = true;
}
@@ -1086,7 +1127,8 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
Penalty += Style.PenaltyBreakFirstLessLess;
}
- State.Column = getNewLineColumn(State);
+ const auto [TotalColumn, IndentedFromColumn] = getNewLineColumn(State);
+ State.Column = TotalColumn;
// Add Penalty proportional to amount of whitespace away from FirstColumn
// This tends to penalize several lines that are far-right indented,
@@ -1132,9 +1174,9 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
} else {
CurrentState.ColonPos =
(shouldIndentWrappedSelectorName(Style, State.Line->Type)
- ? std::max(CurrentState.Indent,
+ ? std::max(CurrentState.Indent.Total,
State.FirstIndent + Style.ContinuationIndentWidth)
- : CurrentState.Indent) +
+ : CurrentState.Indent.Total) +
std::max(NextNonComment->LongestObjCSelectorName,
NextNonComment->ColumnWidth);
}
@@ -1155,7 +1197,7 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
// when we consume all of the "}"'s FakeRParens at the "{".
if (State.Stack.size() > 1) {
State.Stack[State.Stack.size() - 2].LastSpace =
- std::max(CurrentState.LastSpace, CurrentState.Indent) +
+ std::max(CurrentState.LastSpace, CurrentState.Indent.Total) +
Style.ContinuationIndentWidth;
}
}
@@ -1196,7 +1238,8 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
State.Line->Type != LT_ImportStatement &&
Current.isNot(TT_LineComment);
Whitespaces.replaceWhitespace(Current, Newlines, State.Column, State.Column,
- CurrentState.IsAligned, ContinuePPDirective);
+ CurrentState.IsAligned, ContinuePPDirective,
+ IndentedFromColumn);
}
if (!Current.isTrailingComment())
@@ -1340,7 +1383,8 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
return Penalty;
}
-unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
+IndentationAndAlignment
+ContinuationIndenter::getNewLineColumn(const LineState &State) {
if (!State.NextToken || !State.NextToken->Previous)
return 0;
@@ -1354,8 +1398,9 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
const FormatToken &Previous = *Current.Previous;
// If we are continuing an expression, we want to use the continuation indent.
- unsigned ContinuationIndent =
- std::max(CurrentState.LastSpace, CurrentState.Indent) +
+ const auto ContinuationIndent =
+ std::max(IndentationAndAlignment(CurrentState.LastSpace),
+ CurrentState.Indent) +
Style.ContinuationIndentWidth;
const FormatToken *PreviousNonComment = Current.getPreviousNonComment();
const FormatToken *NextNonComment = Previous.getNextNonComment();
@@ -1365,7 +1410,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
// Java specific bits.
if (Style.isJava() &&
Current.isOneOf(Keywords.kw_implements, Keywords.kw_extends)) {
- return std::max(CurrentState.LastSpace,
+ return std::max(IndentationAndAlignment(CurrentState.LastSpace),
CurrentState.Indent + Style.ContinuationIndentWidth);
}
@@ -1378,7 +1423,8 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
if (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths &&
State.Line->First->is(tok::kw_enum)) {
- return (Style.IndentWidth * State.Line->First->IndentLevel) +
+ return IndentationAndAlignment(Style.IndentWidth *
+ State.Line->First->IndentLevel) +
Style.IndentWidth;
}
@@ -1497,7 +1543,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
// * not remove the 'lead' ContinuationIndentWidth
// * always un-indent by the operator when
// BreakBeforeTernaryOperators=true
- unsigned Indent = CurrentState.Indent;
+ unsigned Indent = CurrentState.Indent.Total;
if (Style.AlignOperands != FormatStyle::OAS_DontAlign)
Indent -= Style.ContinuationIndentWidth;
if (Style.BreakBeforeTernaryOperators && CurrentState.UnindentOperator)
@@ -1537,14 +1583,16 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
TT_LeadingJavaAnnotation))) ||
(!Style.IndentWrappedFunctionNames &&
NextNonComment->isOneOf(tok::kw_operator, TT_FunctionDeclarationName))) {
- return std::max(CurrentState.LastSpace, CurrentState.Indent);
+ return std::max(IndentationAndAlignment(CurrentState.LastSpace),
+ CurrentState.Indent);
}
if (NextNonComment->is(TT_SelectorName)) {
if (!CurrentState.ObjCSelectorNameFound) {
- unsigned MinIndent = CurrentState.Indent;
+ auto MinIndent = CurrentState.Indent;
if (shouldIndentWrappedSelectorName(Style, State.Line->Type)) {
- MinIndent = std::max(MinIndent,
- State.FirstIndent + Style.ContinuationIndentWidth);
+ MinIndent =
+ std::max(MinIndent, IndentationAndAlignment(State.FirstIndent) +
+ Style.ContinuationIndentWidth);
}
// If LongestObjCSelectorName is 0, we are indenting the first
// part of an ObjC selector (or a selector component which is
@@ -1555,10 +1603,10 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
// component of the ObjC selector.
//
// In either case, we want to respect Style.IndentWrappedFunctionNames.
- return MinIndent +
- std::max(NextNonComment->LongestObjCSelectorName,
- NextNonComment->ColumnWidth) -
- NextNonComment->ColumnWidth;
+ return MinIndent.addPadding(
+ std::max(NextNonComment->LongestObjCSelectorName,
+ NextNonComment->ColumnWidth) -
+ NextNonComment->ColumnWidth);
}
if (!CurrentState.AlignColons)
return CurrentState.Indent;
@@ -1628,7 +1676,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
return CurrentState.Indent - NextNonComment->Tok.getLength() -
NextNonComment->SpacesRequiredBefore;
}
- if (CurrentState.Indent == State.FirstIndent && PreviousNonComment &&
+ if (CurrentState.Indent.Total == State.FirstIndent && PreviousNonComment &&
PreviousNonComment->isNoneOf(tok::r_brace, TT_CtorInitializerComma)) {
// Ensure that we fall back to the continuation indent width instead of
// just flushing continuations left.
@@ -1718,7 +1766,7 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
FormatStyle::BCIS_BeforeComma
? 0
: 2);
- CurrentState.NestedBlockIndent = CurrentState.Indent;
+ CurrentState.NestedBlockIndent = CurrentState.Indent.Total;
if (Style.PackConstructorInitializers > FormatStyle::PCIS_BinPack) {
CurrentState.AvoidBinPacking = true;
CurrentState.BreakBeforeParameter =
@@ -1733,7 +1781,7 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon) {
CurrentState.Indent =
State.FirstIndent + Style.ConstructorInitializerIndentWidth;
- CurrentState.NestedBlockIndent = CurrentState.Indent;
+ CurrentState.NestedBlockIndent = CurrentState.Indent.Total;
if (Style.PackConstructorInitializers > FormatStyle::PCIS_BinPack)
CurrentState.AvoidBinPacking = true;
else
@@ -1877,8 +1925,9 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
(!Style.isTableGen() ||
(Previous && Previous->isOneOf(TT_TableGenDAGArgListComma,
TT_TableGenDAGArgListCommaToBreak)))) {
- NewParenState.Indent = std::max(
- std::max(State.Column, NewParenState.Indent), CurrentState.LastSpace);
+ NewParenState.Indent =
+ std::max({IndentationAndAlignment(State.Column), NewParenState.Indent,
+ IndentationAndAlignment(CurrentState.LastSpace)});
}
// Special case for generic selection expressions, its comma-separated
@@ -1986,7 +2035,7 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
return Prev->is(tok::comma);
}(Current.MatchingParen);
- unsigned NewIndent;
+ IndentationAndAlignment NewIndent = 0;
unsigned LastSpace = CurrentState.LastSpace;
bool AvoidBinPacking;
bool BreakBeforeParameter = false;
@@ -1999,7 +2048,7 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
std::min(State.Column, CurrentState.NestedBlockIndent);
} else if (Current.is(tok::l_brace)) {
const auto Width = Style.BracedInitializerIndentWidth;
- NewIndent = CurrentState.LastSpace +
+ NewIndent = IndentationAndAlignment(CurrentState.LastSpace) +
(Width < 0 ? Style.ContinuationIndentWidth : Width);
} else {
NewIndent = CurrentState.LastSpace + Style.ContinuationIndentWidth;
@@ -2014,9 +2063,9 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
if (Current.ParameterCount > 1)
NestedBlockIndent = std::max(NestedBlockIndent, State.Column + 1);
} else {
- NewIndent =
- Style.ContinuationIndentWidth +
- std::max(CurrentState.LastSpace, CurrentState.StartOfFunctionCall);
+ NewIndent = IndentationAndAlignment(std::max(
+ CurrentState.LastSpace, CurrentState.StartOfFunctionCall)) +
+ Style.ContinuationIndentWidth;
if (Style.isTableGen() && Current.is(TT_TableGenDAGArgOpenerToBreak) &&
Style.TableGenBreakInsideDAGArg == FormatStyle::DAS_BreakElements) {
@@ -2035,7 +2084,7 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
// FIXME: We likely want to do this for more combinations of brackets.
if (Current.is(tok::less) && Current.ParentBracket == tok::l_paren) {
NewIndent = std::max(NewIndent, CurrentState.Indent);
- LastSpace = std::max(LastSpace, CurrentState.Indent);
+ LastSpace = std::max(LastSpace, CurrentState.Indent.Total);
}
// If ObjCBinPackProtocolList is unspecified, fall back to BinPackParameters
@@ -2281,7 +2330,7 @@ unsigned ContinuationIndenter::reformatRawStringLiteral(
unsigned CurrentIndent =
(!Newline && Current.Next && Current.Next->is(tok::r_paren))
? State.Stack.back().NestedBlockIndent
- : State.Stack.back().Indent;
+ : State.Stack.back().Indent.Total;
unsigned NextStartColumn = ContentStartsOnNewline
? CurrentIndent + Style.IndentWidth
: FirstStartColumn;
diff --git a/clang/lib/Format/ContinuationIndenter.h b/clang/lib/Format/ContinuationIndenter.h
index fe957cf..1554fb4 100644
--- a/clang/lib/Format/ContinuationIndenter.h
+++ b/clang/lib/Format/ContinuationIndenter.h
@@ -43,6 +43,41 @@ struct RawStringFormatStyleManager {
getEnclosingFunctionStyle(StringRef EnclosingFunction) const;
};
+/// Represents the spaces at the start of a line, keeping track of what the
+/// spaces are for.
+struct IndentationAndAlignment {
+ unsigned Total;
+
+ /// The column that the position of the start of the line is calculated
+ /// from. It can be more than Total.
+ unsigned IndentedFrom;
+
+ /// Add spaces for right-justifying the token. The IndentedFrom field does not
+ /// change.
+ ///
+ /// This example in Objective-C shows why the field should not change. The
+ /// token `xx` is right-justified with this method to align the `:`
+ /// symbols. The `:` symbols should remain aligned through the step that
+ /// aligns assignments. That step uses the IndentedFrom field to tell what
+ /// lines to move. Not changing the field in this method ensures that the 2
+ /// lines move together.
+ ///
+ /// [x //
+ /// xxxx:0
+ /// xx:0];
+ IndentationAndAlignment addPadding(unsigned Spaces) const;
+ /// Adding indentation is more common than padding. So the operator does that.
+ IndentationAndAlignment operator+(unsigned Spaces) const;
+ IndentationAndAlignment operator-(unsigned Spaces) const;
+ IndentationAndAlignment &operator+=(unsigned Spaces);
+
+ IndentationAndAlignment(unsigned Total, unsigned IndentedFrom);
+
+ IndentationAndAlignment(unsigned Spaces);
+
+ bool operator<(const IndentationAndAlignment &Other) const;
+};
+
class ContinuationIndenter {
public:
/// Constructs a \c ContinuationIndenter to format \p Line starting in
@@ -168,7 +203,7 @@ private:
unsigned addTokenOnNewLine(LineState &State, bool DryRun);
/// Calculate the new column for a line wrap before the next token.
- unsigned getNewLineColumn(const LineState &State);
+ IndentationAndAlignment getNewLineColumn(const LineState &State);
/// Adds a multiline token to the \p State.
///
@@ -195,10 +230,10 @@ private:
};
struct ParenState {
- ParenState(const FormatToken *Tok, unsigned Indent, unsigned LastSpace,
- bool AvoidBinPacking, bool NoLineBreak)
+ ParenState(const FormatToken *Tok, IndentationAndAlignment Indent,
+ unsigned LastSpace, bool AvoidBinPacking, bool NoLineBreak)
: Tok(Tok), Indent(Indent), LastSpace(LastSpace),
- NestedBlockIndent(Indent), IsAligned(false),
+ NestedBlockIndent(Indent.Total), IsAligned(false),
BreakBeforeClosingBrace(false), BreakBeforeClosingParen(false),
BreakBeforeClosingAngle(false), AvoidBinPacking(AvoidBinPacking),
BreakBeforeParameter(false), NoLineBreak(NoLineBreak),
@@ -219,7 +254,7 @@ struct ParenState {
/// The position to which a specific parenthesis level needs to be
/// indented.
- unsigned Indent;
+ IndentationAndAlignment Indent;
/// The position of the last space on each level.
///
@@ -356,8 +391,8 @@ struct ParenState {
bool UnindentOperator : 1;
bool operator<(const ParenState &Other) const {
- if (Indent != Other.Indent)
- return Indent < Other.Indent;
+ if (Indent.Total != Other.Indent.Total)
+ return Indent.Total < Other.Indent.Total;
if (LastSpace != Other.LastSpace)
return LastSpace < Other.LastSpace;
if (NestedBlockIndent != Other.NestedBlockIndent)
@@ -406,7 +441,7 @@ struct ParenState {
return IsWrappedConditional;
if (UnindentOperator != Other.UnindentOperator)
return UnindentOperator;
- return false;
+ return Indent < Other.Indent;
}
};
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index dd14fcd..f0e9aff 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -405,11 +405,19 @@ struct ScalarEnumerationTraits<FormatStyle::IndentExternBlockStyle> {
template <> struct MappingTraits<FormatStyle::IntegerLiteralSeparatorStyle> {
static void mapping(IO &IO, FormatStyle::IntegerLiteralSeparatorStyle &Base) {
IO.mapOptional("Binary", Base.Binary);
- IO.mapOptional("BinaryMinDigits", Base.BinaryMinDigits);
+ IO.mapOptional("BinaryMinDigitsInsert", Base.BinaryMinDigitsInsert);
+ IO.mapOptional("BinaryMaxDigitsRemove", Base.BinaryMaxDigitsRemove);
IO.mapOptional("Decimal", Base.Decimal);
- IO.mapOptional("DecimalMinDigits", Base.DecimalMinDigits);
+ IO.mapOptional("DecimalMinDigitsInsert", Base.DecimalMinDigitsInsert);
+ IO.mapOptional("DecimalMaxDigitsRemove", Base.DecimalMaxDigitsRemove);
IO.mapOptional("Hex", Base.Hex);
- IO.mapOptional("HexMinDigits", Base.HexMinDigits);
+ IO.mapOptional("HexMinDigitsInsert", Base.HexMinDigitsInsert);
+ IO.mapOptional("HexMaxDigitsRemove", Base.HexMaxDigitsRemove);
+
+ // For backward compatibility.
+ IO.mapOptional("BinaryMinDigits", Base.BinaryMinDigitsInsert);
+ IO.mapOptional("DecimalMinDigits", Base.DecimalMinDigitsInsert);
+ IO.mapOptional("HexMinDigits", Base.HexMinDigitsInsert);
}
};
@@ -876,27 +884,28 @@ template <> struct MappingTraits<FormatStyle::TrailingCommentsAlignmentStyle> {
FormatStyle::TrailingCommentsAlignmentStyle &Value) {
IO.enumCase(Value, "Leave",
FormatStyle::TrailingCommentsAlignmentStyle(
- {FormatStyle::TCAS_Leave, 0}));
+ {FormatStyle::TCAS_Leave, 0, true}));
IO.enumCase(Value, "Always",
FormatStyle::TrailingCommentsAlignmentStyle(
- {FormatStyle::TCAS_Always, 0}));
+ {FormatStyle::TCAS_Always, 0, true}));
IO.enumCase(Value, "Never",
FormatStyle::TrailingCommentsAlignmentStyle(
- {FormatStyle::TCAS_Never, 0}));
+ {FormatStyle::TCAS_Never, 0, true}));
// For backwards compatibility
IO.enumCase(Value, "true",
FormatStyle::TrailingCommentsAlignmentStyle(
- {FormatStyle::TCAS_Always, 0}));
+ {FormatStyle::TCAS_Always, 0, true}));
IO.enumCase(Value, "false",
FormatStyle::TrailingCommentsAlignmentStyle(
- {FormatStyle::TCAS_Never, 0}));
+ {FormatStyle::TCAS_Never, 0, true}));
}
static void mapping(IO &IO,
FormatStyle::TrailingCommentsAlignmentStyle &Value) {
+ IO.mapOptional("AlignPPAndNotPP", Value.AlignPPAndNotPP);
IO.mapOptional("Kind", Value.Kind);
IO.mapOptional("OverEmptyLines", Value.OverEmptyLines);
}
@@ -1651,6 +1660,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.AlignTrailingComments = {};
LLVMStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Always;
LLVMStyle.AlignTrailingComments.OverEmptyLines = 0;
+ LLVMStyle.AlignTrailingComments.AlignPPAndNotPP = true;
LLVMStyle.AllowAllArgumentsOnNextLine = true;
LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never;
@@ -1756,10 +1766,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.InsertBraces = false;
LLVMStyle.InsertNewlineAtEOF = false;
LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None;
- LLVMStyle.IntegerLiteralSeparator = {
- /*Binary=*/0, /*BinaryMinDigits=*/0,
- /*Decimal=*/0, /*DecimalMinDigits=*/0,
- /*Hex=*/0, /*HexMinDigits=*/0};
+ LLVMStyle.IntegerLiteralSeparator = {};
LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
LLVMStyle.JavaScriptWrapImports = true;
LLVMStyle.KeepEmptyLines = {
@@ -2181,7 +2188,7 @@ FormatStyle getClangFormatStyle() {
Style.InsertBraces = true;
Style.InsertNewlineAtEOF = true;
Style.IntegerLiteralSeparator.Decimal = 3;
- Style.IntegerLiteralSeparator.DecimalMinDigits = 5;
+ Style.IntegerLiteralSeparator.DecimalMinDigitsInsert = 5;
Style.LineEnding = FormatStyle::LE_LF;
Style.RemoveBracesLLVM = true;
Style.RemoveEmptyLinesInUnwrappedLines = true;
diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index d833130..56abd70 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -1170,6 +1170,7 @@ struct AdditionalKeywords {
kw_checker = &IdentTable.get("checker");
kw_clocking = &IdentTable.get("clocking");
kw_constraint = &IdentTable.get("constraint");
+ kw_context = &IdentTable.get("context");
kw_cover = &IdentTable.get("cover");
kw_covergroup = &IdentTable.get("covergroup");
kw_coverpoint = &IdentTable.get("coverpoint");
@@ -1325,50 +1326,138 @@ struct AdditionalKeywords {
// Some keywords are not included here because they don't need special
// treatment like `showcancelled` or they should be treated as identifiers
// like `int` and `logic`.
- VerilogExtraKeywords = std::unordered_set<IdentifierInfo *>(
- {kw_always, kw_always_comb, kw_always_ff,
- kw_always_latch, kw_assert, kw_assign,
- kw_assume, kw_automatic, kw_before,
- kw_begin, kw_bins, kw_binsof,
- kw_casex, kw_casez, kw_celldefine,
- kw_checker, kw_clocking, kw_constraint,
- kw_cover, kw_covergroup, kw_coverpoint,
- kw_disable, kw_dist, kw_edge,
- kw_end, kw_endcase, kw_endchecker,
- kw_endclass, kw_endclocking, kw_endfunction,
- kw_endgenerate, kw_endgroup, kw_endinterface,
- kw_endmodule, kw_endpackage, kw_endprimitive,
- kw_endprogram, kw_endproperty, kw_endsequence,
- kw_endspecify, kw_endtable, kw_endtask,
- kw_extends, kw_final, kw_foreach,
- kw_forever, kw_fork, kw_function,
- kw_generate, kw_highz0, kw_highz1,
- kw_iff, kw_ifnone, kw_ignore_bins,
- kw_illegal_bins, kw_implements, kw_import,
- kw_initial, kw_inout, kw_input,
- kw_inside, kw_interconnect, kw_interface,
- kw_intersect, kw_join, kw_join_any,
- kw_join_none, kw_large, kw_let,
- kw_local, kw_localparam, kw_macromodule,
- kw_matches, kw_medium, kw_negedge,
- kw_output, kw_package, kw_packed,
- kw_parameter, kw_posedge, kw_primitive,
- kw_priority, kw_program, kw_property,
- kw_pull0, kw_pull1, kw_pure,
- kw_rand, kw_randc, kw_randcase,
- kw_randsequence, kw_ref, kw_repeat,
- kw_sample, kw_scalared, kw_sequence,
- kw_small, kw_soft, kw_solve,
- kw_specify, kw_specparam, kw_strong0,
- kw_strong1, kw_supply0, kw_supply1,
- kw_table, kw_tagged, kw_task,
- kw_tri, kw_tri0, kw_tri1,
- kw_triand, kw_trior, kw_trireg,
- kw_unique, kw_unique0, kw_uwire,
- kw_var, kw_vectored, kw_wait,
- kw_wand, kw_weak0, kw_weak1,
- kw_wildcard, kw_wire, kw_with,
- kw_wor, kw_verilogHash, kw_verilogHashHash});
+ VerilogExtraKeywords =
+ std::unordered_set<IdentifierInfo *>({kw_always,
+ kw_always_comb,
+ kw_always_ff,
+ kw_always_latch,
+ kw_assert,
+ kw_assign,
+ kw_assume,
+ kw_automatic,
+ kw_before,
+ kw_begin,
+ kw_bins,
+ kw_binsof,
+ kw_casex,
+ kw_casez,
+ kw_celldefine,
+ kw_checker,
+ kw_clocking,
+ kw_constraint,
+ kw_context,
+ kw_cover,
+ kw_covergroup,
+ kw_coverpoint,
+ kw_disable,
+ kw_dist,
+ kw_edge,
+ kw_end,
+ kw_endcase,
+ kw_endchecker,
+ kw_endclass,
+ kw_endclocking,
+ kw_endfunction,
+ kw_endgenerate,
+ kw_endgroup,
+ kw_endinterface,
+ kw_endmodule,
+ kw_endpackage,
+ kw_endprimitive,
+ kw_endprogram,
+ kw_endproperty,
+ kw_endsequence,
+ kw_endspecify,
+ kw_endtable,
+ kw_endtask,
+ kw_extends,
+ kw_final,
+ kw_foreach,
+ kw_forever,
+ kw_fork,
+ kw_function,
+ kw_generate,
+ kw_highz0,
+ kw_highz1,
+ kw_iff,
+ kw_ifnone,
+ kw_ignore_bins,
+ kw_illegal_bins,
+ kw_implements,
+ kw_import,
+ kw_initial,
+ kw_inout,
+ kw_input,
+ kw_inside,
+ kw_interconnect,
+ kw_interface,
+ kw_intersect,
+ kw_join,
+ kw_join_any,
+ kw_join_none,
+ kw_large,
+ kw_let,
+ kw_local,
+ kw_localparam,
+ kw_macromodule,
+ kw_matches,
+ kw_medium,
+ kw_module,
+ kw_negedge,
+ kw_output,
+ kw_package,
+ kw_packed,
+ kw_parameter,
+ kw_posedge,
+ kw_primitive,
+ kw_priority,
+ kw_program,
+ kw_property,
+ kw_pull0,
+ kw_pull1,
+ kw_pure,
+ kw_rand,
+ kw_randc,
+ kw_randcase,
+ kw_randsequence,
+ kw_ref,
+ kw_repeat,
+ kw_sample,
+ kw_scalared,
+ kw_sequence,
+ kw_small,
+ kw_soft,
+ kw_solve,
+ kw_specify,
+ kw_specparam,
+ kw_strong0,
+ kw_strong1,
+ kw_supply0,
+ kw_supply1,
+ kw_table,
+ kw_tagged,
+ kw_task,
+ kw_tri,
+ kw_tri0,
+ kw_tri1,
+ kw_triand,
+ kw_trior,
+ kw_trireg,
+ kw_unique,
+ kw_unique0,
+ kw_uwire,
+ kw_var,
+ kw_vectored,
+ kw_wait,
+ kw_wand,
+ kw_weak0,
+ kw_weak1,
+ kw_wildcard,
+ kw_wire,
+ kw_with,
+ kw_wor,
+ kw_verilogHash,
+ kw_verilogHashHash});
TableGenExtraKeywords = std::unordered_set<IdentifierInfo *>({
kw_assert,
@@ -1516,6 +1605,7 @@ struct AdditionalKeywords {
IdentifierInfo *kw_checker;
IdentifierInfo *kw_clocking;
IdentifierInfo *kw_constraint;
+ IdentifierInfo *kw_context;
IdentifierInfo *kw_cover;
IdentifierInfo *kw_covergroup;
IdentifierInfo *kw_coverpoint;
@@ -1800,11 +1890,13 @@ struct AdditionalKeywords {
case tok::kw_continue:
case tok::kw_default:
case tok::kw_do:
- case tok::kw_extern:
case tok::kw_else:
case tok::kw_enum:
+ case tok::kw_export:
+ case tok::kw_extern:
case tok::kw_for:
case tok::kw_if:
+ case tok::kw_import:
case tok::kw_restrict:
case tok::kw_signed:
case tok::kw_static:
diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp
index ab32938..eb86583 100644
--- a/clang/lib/Format/FormatTokenLexer.cpp
+++ b/clang/lib/Format/FormatTokenLexer.cpp
@@ -318,14 +318,21 @@ void FormatTokenLexer::tryMergePreviousTokens() {
{tok::equal, tok::greater},
{tok::star, tok::greater},
{tok::pipeequal, tok::greater},
- {tok::pipe, tok::arrow},
- {tok::hash, tok::minus, tok::hash},
- {tok::hash, tok::equal, tok::hash}},
+ {tok::pipe, tok::arrow}},
TT_BinaryOperator) ||
Tokens.back()->is(tok::arrow)) {
Tokens.back()->ForcedPrecedence = prec::Comma;
return;
}
+ if (Tokens.size() >= 3 &&
+ Tokens[Tokens.size() - 3]->is(Keywords.kw_verilogHash) &&
+ Tokens[Tokens.size() - 2]->isOneOf(tok::minus, tok::equal) &&
+ Tokens[Tokens.size() - 1]->is(Keywords.kw_verilogHash) &&
+ tryMergeTokens(3, TT_BinaryOperator)) {
+ Tokens.back()->setFinalizedType(TT_BinaryOperator);
+ Tokens.back()->ForcedPrecedence = prec::Comma;
+ return;
+ }
} else if (Style.isTableGen()) {
// TableGen's Multi line string starts with [{
if (tryMergeTokens({tok::l_square, tok::l_brace},
@@ -1401,6 +1408,8 @@ FormatToken *FormatTokenLexer::getNextToken() {
FormatTok->Tok.setKind(tok::identifier);
} else if (Style.isTableGen() && !Keywords.isTableGenKeyword(*FormatTok)) {
FormatTok->Tok.setKind(tok::identifier);
+ } else if (Style.isVerilog() && Keywords.isVerilogIdentifier(*FormatTok)) {
+ FormatTok->Tok.setKind(tok::identifier);
}
} else if (const bool Greater = FormatTok->is(tok::greatergreater);
Greater || FormatTok->is(tok::lessless)) {
diff --git a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp
index b51991bf..a283884 100644
--- a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp
+++ b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp
@@ -72,11 +72,22 @@ IntegerLiteralSeparatorFixer::process(const Environment &Env,
if (SkipBinary && SkipDecimal && SkipHex)
return {};
- const auto BinaryMinDigits =
- std::max((int)Option.BinaryMinDigits, Binary + 1);
- const auto DecimalMinDigits =
- std::max((int)Option.DecimalMinDigits, Decimal + 1);
- const auto HexMinDigits = std::max((int)Option.HexMinDigits, Hex + 1);
+ auto CalcMinAndMax = [](int DigitsPerGroup, int MinDigitsInsert,
+ int MaxDigitsRemove) {
+ MinDigitsInsert = std::max(MinDigitsInsert, DigitsPerGroup + 1);
+ if (MinDigitsInsert < 1)
+ MaxDigitsRemove = 0;
+ else if (MaxDigitsRemove < 1 || MaxDigitsRemove >= MinDigitsInsert)
+ MaxDigitsRemove = MinDigitsInsert - 1;
+ return std::pair(MinDigitsInsert, MaxDigitsRemove);
+ };
+
+ const auto [BinaryMinDigitsInsert, BinaryMaxDigitsRemove] = CalcMinAndMax(
+ Binary, Option.BinaryMinDigitsInsert, Option.BinaryMaxDigitsRemove);
+ const auto [DecimalMinDigitsInsert, DecimalMaxDigitsRemove] = CalcMinAndMax(
+ Decimal, Option.DecimalMinDigitsInsert, Option.DecimalMaxDigitsRemove);
+ const auto [HexMinDigitsInsert, HexMaxDigitsRemove] =
+ CalcMinAndMax(Hex, Option.HexMinDigitsInsert, Option.HexMaxDigitsRemove);
const auto &SourceMgr = Env.getSourceManager();
AffectedRangeManager AffectedRangeMgr(SourceMgr, Env.getCharRanges());
@@ -138,17 +149,23 @@ IntegerLiteralSeparatorFixer::process(const Environment &Env,
Text = Text.substr(Start, Length);
}
auto DigitsPerGroup = Decimal;
- auto MinDigits = DecimalMinDigits;
+ auto MinDigitsInsert = DecimalMinDigitsInsert;
+ auto MaxDigitsRemove = DecimalMaxDigitsRemove;
if (IsBase2) {
DigitsPerGroup = Binary;
- MinDigits = BinaryMinDigits;
+ MinDigitsInsert = BinaryMinDigitsInsert;
+ MaxDigitsRemove = BinaryMaxDigitsRemove;
} else if (IsBase16) {
DigitsPerGroup = Hex;
- MinDigits = HexMinDigits;
+ MinDigitsInsert = HexMinDigitsInsert;
+ MaxDigitsRemove = HexMaxDigitsRemove;
}
const auto SeparatorCount = Text.count(Separator);
const int DigitCount = Length - SeparatorCount;
- const bool RemoveSeparator = DigitsPerGroup < 0 || DigitCount < MinDigits;
+ if (DigitCount > MaxDigitsRemove && DigitCount < MinDigitsInsert)
+ continue;
+ const bool RemoveSeparator =
+ DigitsPerGroup < 0 || DigitCount <= MaxDigitsRemove;
if (RemoveSeparator && SeparatorCount == 0)
continue;
if (!RemoveSeparator && SeparatorCount > 0 &&
diff --git a/clang/lib/Format/QualifierAlignmentFixer.cpp b/clang/lib/Format/QualifierAlignmentFixer.cpp
index e3e30ca..eb0f886 100644
--- a/clang/lib/Format/QualifierAlignmentFixer.cpp
+++ b/clang/lib/Format/QualifierAlignmentFixer.cpp
@@ -182,8 +182,11 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight(
// We only need to think about streams that begin with a qualifier.
if (Tok->isNot(QualifierType))
return Tok;
+
+ const auto *Next = Tok->getNextNonComment();
+
// Don't concern yourself if nothing follows the qualifier.
- if (!Tok->Next)
+ if (!Next)
return Tok;
// Skip qualifiers to the left to find what preceeds the qualifiers.
@@ -247,9 +250,15 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight(
}();
// Find the last qualifier to the right.
- const FormatToken *LastQual = Tok;
- while (isQualifier(LastQual->getNextNonComment()))
- LastQual = LastQual->getNextNonComment();
+ const auto *LastQual = Tok;
+ for (; isQualifier(Next); Next = Next->getNextNonComment())
+ LastQual = Next;
+
+ if (!LastQual || !Next ||
+ (LastQual->isOneOf(tok::kw_const, tok::kw_volatile) &&
+ Next->isOneOf(Keywords.kw_override, Keywords.kw_final))) {
+ return Tok;
+ }
// If this qualifier is to the right of a type or pointer do a partial sort
// and return.
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 8e227da..79cfa73 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -358,11 +358,11 @@ private:
Contexts.back().IsExpression = false;
} else if (OpeningParen.Previous &&
(OpeningParen.Previous->isOneOf(
- tok::kw_static_assert, tok::kw_noexcept, tok::kw_explicit,
- tok::kw_while, tok::l_paren, tok::comma, TT_CastRParen,
+ tok::kw_noexcept, tok::kw_explicit, tok::kw_while,
+ tok::l_paren, tok::comma, TT_CastRParen,
TT_BinaryOperator) ||
OpeningParen.Previous->isIf())) {
- // static_assert, if and while usually contain expressions.
+ // if and while usually contain expressions.
Contexts.back().IsExpression = true;
} else if (Style.isJavaScript() && OpeningParen.Previous &&
(OpeningParen.Previous->is(Keywords.kw_function) ||
@@ -454,6 +454,11 @@ private:
if (StartsObjCSelector)
OpeningParen.setType(TT_ObjCSelector);
+ const bool IsStaticAssert =
+ PrevNonComment && PrevNonComment->is(tok::kw_static_assert);
+ if (IsStaticAssert)
+ Contexts.back().InStaticAssertFirstArgument = true;
+
// MightBeFunctionType and ProbablyFunctionType are used for
// function pointer and reference types as well as Objective-C
// block types:
@@ -583,8 +588,12 @@ private:
}
// When we discover a 'new', we set CanBeExpression to 'false' in order to
// parse the type correctly. Reset that after a comma.
- if (CurrentToken->is(tok::comma))
- Contexts.back().CanBeExpression = true;
+ if (CurrentToken->is(tok::comma)) {
+ if (IsStaticAssert)
+ Contexts.back().InStaticAssertFirstArgument = false;
+ else
+ Contexts.back().CanBeExpression = true;
+ }
if (Style.isTableGen()) {
if (CurrentToken->is(tok::comma)) {
@@ -699,6 +708,11 @@ private:
IsCpp && !IsCpp11AttributeSpecifier && !IsCSharpAttributeSpecifier &&
Contexts.back().CanBeExpression && Left->isNot(TT_LambdaLSquare) &&
CurrentToken->isNoneOf(tok::l_brace, tok::r_square) &&
+ // Do not consider '[' after a comma inside a braced initializer the
+ // start of an ObjC method expression. In braced initializer lists,
+ // commas are list separators and should not trigger ObjC parsing.
+ (!Parent || !Parent->is(tok::comma) ||
+ Contexts.back().ContextKind != tok::l_brace) &&
(!Parent ||
Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren,
tok::kw_return, tok::kw_throw) ||
@@ -2144,6 +2158,7 @@ private:
bool CaretFound = false;
bool InCpp11AttributeSpecifier = false;
bool InCSharpAttributeSpecifier = false;
+ bool InStaticAssertFirstArgument = false;
bool VerilogAssignmentFound = false;
// Whether the braces may mean concatenation instead of structure or array
// literal.
@@ -2440,7 +2455,8 @@ private:
} else if (Current.isPointerOrReference()) {
Current.setType(determineStarAmpUsage(
Current,
- Contexts.back().CanBeExpression && Contexts.back().IsExpression,
+ (Contexts.back().CanBeExpression && Contexts.back().IsExpression) ||
+ Contexts.back().InStaticAssertFirstArgument,
Contexts.back().ContextType == Context::TemplateArgument));
} else if (Current.isOneOf(tok::minus, tok::plus, tok::caret) ||
(Style.isVerilog() && Current.is(tok::pipe))) {
@@ -3118,8 +3134,11 @@ private:
// It is very unlikely that we are going to find a pointer or reference type
// definition on the RHS of an assignment.
- if (IsExpression && !Contexts.back().CaretFound)
+ if (IsExpression && !Contexts.back().CaretFound &&
+ Line.getFirstNonComment()->isNot(
+ TT_RequiresClauseInARequiresExpression)) {
return TT_BinaryOperator;
+ }
// Opeartors at class scope are likely pointer or reference members.
if (!Scopes.empty() && Scopes.back() == ST_Class)
@@ -5019,8 +5038,11 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return true;
// Space between import <iostream>.
// or import .....;
- if (Left.is(Keywords.kw_import) && Right.isOneOf(tok::less, tok::ellipsis))
+ if (Left.is(Keywords.kw_import) &&
+ Right.isOneOf(tok::less, tok::ellipsis) &&
+ (!BeforeLeft || BeforeLeft->is(tok::kw_export))) {
return true;
+ }
// Space between `module :` and `import :`.
if (Left.isOneOf(Keywords.kw_module, Keywords.kw_import) &&
Right.is(TT_ModulePartitionColon)) {
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp
index ac9c81d..913789a 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -285,7 +285,8 @@ private:
if (Tok && Tok->is(tok::kw_typedef))
Tok = Tok->getNextNonComment();
if (Tok && Tok->isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union,
- tok::kw_extern, Keywords.kw_interface)) {
+ tok::kw_extern, Keywords.kw_interface,
+ Keywords.kw_record)) {
return !Style.BraceWrapping.SplitEmptyRecord && EmptyBlock
? tryMergeSimpleBlock(I, E, Limit)
: 0;
@@ -498,7 +499,8 @@ private:
ShouldMerge = Style.AllowShortEnumsOnASingleLine;
} else if (TheLine->Last->is(TT_CompoundRequirementLBrace)) {
ShouldMerge = Style.AllowShortCompoundRequirementOnASingleLine;
- } else if (TheLine->Last->isOneOf(TT_ClassLBrace, TT_StructLBrace)) {
+ } else if (TheLine->Last->isOneOf(TT_ClassLBrace, TT_StructLBrace,
+ TT_RecordLBrace)) {
// NOTE: We use AfterClass (whereas AfterStruct exists) for both classes
// and structs, but it seems that wrapping is still handled correctly
// elsewhere.
@@ -507,7 +509,7 @@ private:
!Style.BraceWrapping.SplitEmptyRecord);
} else if (TheLine->InPPDirective ||
TheLine->First->isNoneOf(tok::kw_class, tok::kw_enum,
- tok::kw_struct)) {
+ tok::kw_struct, Keywords.kw_record)) {
// Try to merge a block with left brace unwrapped that wasn't yet
// covered.
ShouldMerge = !Style.BraceWrapping.AfterFunction ||
@@ -1050,8 +1052,8 @@ static void markFinalized(FormatToken *Tok) {
static void printLineState(const LineState &State) {
llvm::dbgs() << "State: ";
for (const ParenState &P : State.Stack) {
- llvm::dbgs() << (P.Tok ? P.Tok->TokenText : "F") << "|" << P.Indent << "|"
- << P.LastSpace << "|" << P.NestedBlockIndent << " ";
+ llvm::dbgs() << (P.Tok ? P.Tok->TokenText : "F") << "|" << P.Indent.Total
+ << "|" << P.LastSpace << "|" << P.NestedBlockIndent << " ";
}
llvm::dbgs() << State.NextToken->TokenText << "\n";
}
@@ -1109,7 +1111,7 @@ protected:
const ParenState &P = State.Stack.back();
int AdditionalIndent =
- P.Indent - Previous.Children[0]->Level * Style.IndentWidth;
+ P.Indent.Total - Previous.Children[0]->Level * Style.IndentWidth;
Penalty +=
BlockFormatter->format(Previous.Children, DryRun, AdditionalIndent,
/*FixBadIndentation=*/true);
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 5e2584e..c1a9161 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -948,7 +948,11 @@ static bool isIIFE(const UnwrappedLine &Line,
}
static bool ShouldBreakBeforeBrace(const FormatStyle &Style,
- const FormatToken &InitialToken) {
+ const FormatToken &InitialToken,
+ const bool IsJavaRecord) {
+ if (IsJavaRecord)
+ return Style.BraceWrapping.AfterClass;
+
tok::TokenKind Kind = InitialToken.Tok.getKind();
if (InitialToken.is(TT_NamespaceMacro))
Kind = tok::kw_namespace;
@@ -1588,15 +1592,14 @@ void UnwrappedLineParser::parseStructuralElement(
parseTryCatch();
return;
case tok::kw_extern:
- nextToken();
if (Style.isVerilog()) {
- // In Verilog and extern module declaration looks like a start of module.
+ // In Verilog an extern module declaration looks like a start of module.
// But there is no body and endmodule. So we handle it separately.
- if (Keywords.isVerilogHierarchy(*FormatTok)) {
- parseVerilogHierarchyHeader();
- return;
- }
- } else if (FormatTok->is(tok::string_literal)) {
+ parseVerilogExtern();
+ return;
+ }
+ nextToken();
+ if (FormatTok->is(tok::string_literal)) {
nextToken();
if (FormatTok->is(tok::l_brace)) {
if (Style.BraceWrapping.AfterExternBlock)
@@ -1621,6 +1624,10 @@ void UnwrappedLineParser::parseStructuralElement(
parseJavaScriptEs6ImportExport();
return;
}
+ if (Style.isVerilog()) {
+ parseVerilogExtern();
+ return;
+ }
if (IsCpp) {
nextToken();
if (FormatTok->is(tok::kw_namespace)) {
@@ -1669,6 +1676,10 @@ void UnwrappedLineParser::parseStructuralElement(
addUnwrappedLine();
return;
}
+ if (Style.isVerilog()) {
+ parseVerilogExtern();
+ return;
+ }
if (IsCpp && parseModuleImport())
return;
}
@@ -2352,12 +2363,9 @@ bool UnwrappedLineParser::tryToParseLambda() {
Arrow = FormatTok;
nextToken();
break;
- case tok::kw_requires: {
- auto *RequiresToken = FormatTok;
- nextToken();
- parseRequiresClause(RequiresToken);
+ case tok::kw_requires:
+ parseRequiresClause();
break;
- }
case tok::equal:
if (!InTemplateParameterList)
return true;
@@ -2387,17 +2395,17 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
const FormatToken *LeftSquare = FormatTok;
nextToken();
if (Previous) {
+ const auto *PrevPrev = Previous->getPreviousNonComment();
+ if (Previous->is(tok::star) && PrevPrev && PrevPrev->isTypeName(LangOpts))
+ return false;
if (Previous->closesScope()) {
// Not a potential C-style cast.
if (Previous->isNot(tok::r_paren))
return false;
- const auto *BeforeRParen = Previous->getPreviousNonComment();
// Lambdas can be cast to function types only, e.g. `std::function<int()>`
// and `int (*)()`.
- if (!BeforeRParen || BeforeRParen->isNoneOf(tok::greater, tok::r_paren))
+ if (!PrevPrev || PrevPrev->isNoneOf(tok::greater, tok::r_paren))
return false;
- } else if (Previous->is(tok::star)) {
- Previous = Previous->getPreviousNonComment();
}
if (Previous && Previous->Tok.getIdentifierInfo() &&
Previous->isNoneOf(tok::kw_return, tok::kw_co_await, tok::kw_co_yield,
@@ -2569,12 +2577,9 @@ bool UnwrappedLineParser::parseBracedList(bool IsAngleBracket, bool IsEnum) {
if (IsEnum && !Style.AllowShortEnumsOnASingleLine)
addUnwrappedLine();
break;
- case tok::kw_requires: {
- auto *RequiresToken = FormatTok;
- nextToken();
- parseRequiresExpression(RequiresToken);
+ case tok::kw_requires:
+ parseRequiresExpression();
break;
- }
default:
nextToken();
break;
@@ -2716,12 +2721,9 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType,
else
nextToken();
break;
- case tok::kw_requires: {
- auto RequiresToken = FormatTok;
- nextToken();
- parseRequiresExpression(RequiresToken);
+ case tok::kw_requires:
+ parseRequiresExpression();
break;
- }
case tok::ampamp:
if (AmpAmpTokenType != TT_Unknown)
FormatTok->setFinalizedType(AmpAmpTokenType);
@@ -3200,7 +3202,7 @@ void UnwrappedLineParser::parseNamespace() {
if (FormatTok->is(tok::l_brace)) {
FormatTok->setFinalizedType(TT_NamespaceLBrace);
- if (ShouldBreakBeforeBrace(Style, InitialToken))
+ if (ShouldBreakBeforeBrace(Style, InitialToken, /*IsJavaRecord=*/false))
addUnwrappedLine();
unsigned AddLevels =
@@ -3456,23 +3458,20 @@ void UnwrappedLineParser::parseAccessSpecifier() {
/// \returns true if it parsed a clause.
bool UnwrappedLineParser::parseRequires(bool SeenEqual) {
assert(FormatTok->is(tok::kw_requires) && "'requires' expected");
- auto RequiresToken = FormatTok;
// We try to guess if it is a requires clause, or a requires expression. For
- // that we first consume the keyword and check the next token.
- nextToken();
-
- switch (FormatTok->Tok.getKind()) {
+ // that we first check the next token.
+ switch (Tokens->peekNextToken(/*SkipComment=*/true)->Tok.getKind()) {
case tok::l_brace:
// This can only be an expression, never a clause.
- parseRequiresExpression(RequiresToken);
+ parseRequiresExpression();
return false;
case tok::l_paren:
// Clauses and expression can start with a paren, it's unclear what we have.
break;
default:
// All other tokens can only be a clause.
- parseRequiresClause(RequiresToken);
+ parseRequiresClause();
return true;
}
@@ -3483,13 +3482,13 @@ bool UnwrappedLineParser::parseRequires(bool SeenEqual) {
// requires (C<T> && ...
// But first let's look behind.
- auto *PreviousNonComment = RequiresToken->getPreviousNonComment();
+ auto *PreviousNonComment = FormatTok->getPreviousNonComment();
if (!PreviousNonComment ||
PreviousNonComment->is(TT_RequiresExpressionLBrace)) {
// If there is no token, or an expression left brace, we are a requires
// clause within a requires expression.
- parseRequiresClause(RequiresToken);
+ parseRequiresClause();
return true;
}
@@ -3501,7 +3500,7 @@ bool UnwrappedLineParser::parseRequires(bool SeenEqual) {
case tok::star:
case tok::amp:
// This is a requires clause.
- parseRequiresClause(RequiresToken);
+ parseRequiresClause();
return true;
case tok::ampamp: {
// This can be either:
@@ -3512,7 +3511,7 @@ bool UnwrappedLineParser::parseRequires(bool SeenEqual) {
// void member(...) const && requires (C<T> ...
auto PrevPrev = PreviousNonComment->getPreviousNonComment();
if ((PrevPrev && PrevPrev->is(tok::kw_const)) || !SeenEqual) {
- parseRequiresClause(RequiresToken);
+ parseRequiresClause();
return true;
}
break;
@@ -3520,11 +3519,11 @@ bool UnwrappedLineParser::parseRequires(bool SeenEqual) {
default:
if (PreviousNonComment->isTypeOrIdentifier(LangOpts)) {
// This is a requires clause.
- parseRequiresClause(RequiresToken);
+ parseRequiresClause();
return true;
}
// It's an expression.
- parseRequiresExpression(RequiresToken);
+ parseRequiresExpression();
return false;
}
@@ -3553,7 +3552,7 @@ bool UnwrappedLineParser::parseRequires(bool SeenEqual) {
case tok::comma:
if (OpenAngles == 0) {
FormatTok = Tokens->setPosition(StoredPosition);
- parseRequiresExpression(RequiresToken);
+ parseRequiresExpression();
return false;
}
break;
@@ -3568,7 +3567,7 @@ bool UnwrappedLineParser::parseRequires(bool SeenEqual) {
case tok::identifier:
if (FoundType && !LastWasColonColon && OpenAngles == 0) {
FormatTok = Tokens->setPosition(StoredPosition);
- parseRequiresExpression(RequiresToken);
+ parseRequiresExpression();
return false;
}
FoundType = true;
@@ -3583,7 +3582,7 @@ bool UnwrappedLineParser::parseRequires(bool SeenEqual) {
default:
if (NextToken->isTypeName(LangOpts)) {
FormatTok = Tokens->setPosition(StoredPosition);
- parseRequiresExpression(RequiresToken);
+ parseRequiresExpression();
return false;
}
break;
@@ -3591,31 +3590,29 @@ bool UnwrappedLineParser::parseRequires(bool SeenEqual) {
}
// This seems to be a complicated expression, just assume it's a clause.
FormatTok = Tokens->setPosition(StoredPosition);
- parseRequiresClause(RequiresToken);
+ parseRequiresClause();
return true;
}
/// Parses a requires clause.
-/// \param RequiresToken The requires keyword token, which starts this clause.
-/// \pre We need to be on the next token after the requires keyword.
/// \sa parseRequiresExpression
///
/// Returns if it either has finished parsing the clause, or it detects, that
/// the clause is incorrect.
-void UnwrappedLineParser::parseRequiresClause(FormatToken *RequiresToken) {
- assert(FormatTok->getPreviousNonComment() == RequiresToken);
- assert(RequiresToken->is(tok::kw_requires) && "'requires' expected");
+void UnwrappedLineParser::parseRequiresClause() {
+ assert(FormatTok->is(tok::kw_requires) && "'requires' expected");
// If there is no previous token, we are within a requires expression,
// otherwise we will always have the template or function declaration in front
// of it.
bool InRequiresExpression =
- !RequiresToken->Previous ||
- RequiresToken->Previous->is(TT_RequiresExpressionLBrace);
+ !FormatTok->Previous ||
+ FormatTok->Previous->is(TT_RequiresExpressionLBrace);
- RequiresToken->setFinalizedType(InRequiresExpression
- ? TT_RequiresClauseInARequiresExpression
- : TT_RequiresClause);
+ FormatTok->setFinalizedType(InRequiresExpression
+ ? TT_RequiresClauseInARequiresExpression
+ : TT_RequiresClause);
+ nextToken();
// NOTE: parseConstraintExpression is only ever called from this function.
// It could be inlined into here.
@@ -3626,17 +3623,15 @@ void UnwrappedLineParser::parseRequiresClause(FormatToken *RequiresToken) {
}
/// Parses a requires expression.
-/// \param RequiresToken The requires keyword token, which starts this clause.
-/// \pre We need to be on the next token after the requires keyword.
/// \sa parseRequiresClause
///
/// Returns if it either has finished parsing the expression, or it detects,
/// that the expression is incorrect.
-void UnwrappedLineParser::parseRequiresExpression(FormatToken *RequiresToken) {
- assert(FormatTok->getPreviousNonComment() == RequiresToken);
- assert(RequiresToken->is(tok::kw_requires) && "'requires' expected");
+void UnwrappedLineParser::parseRequiresExpression() {
+ assert(FormatTok->is(tok::kw_requires) && "'requires' expected");
- RequiresToken->setFinalizedType(TT_RequiresExpression);
+ FormatTok->setFinalizedType(TT_RequiresExpression);
+ nextToken();
if (FormatTok->is(tok::l_paren)) {
FormatTok->setFinalizedType(TT_RequiresExpressionLParen);
@@ -3676,12 +3671,9 @@ void UnwrappedLineParser::parseConstraintExpression() {
bool LambdaThisTimeAllowed = std::exchange(LambdaNextTimeAllowed, false);
switch (FormatTok->Tok.getKind()) {
- case tok::kw_requires: {
- auto RequiresToken = FormatTok;
- nextToken();
- parseRequiresExpression(RequiresToken);
+ case tok::kw_requires:
+ parseRequiresExpression();
break;
- }
case tok::l_paren:
if (!TopLevelParensAllowed)
@@ -3865,7 +3857,7 @@ bool UnwrappedLineParser::parseEnum() {
}
if (!Style.AllowShortEnumsOnASingleLine &&
- ShouldBreakBeforeBrace(Style, InitialToken)) {
+ ShouldBreakBeforeBrace(Style, InitialToken, /*IsJavaRecord=*/false)) {
addUnwrappedLine();
}
// Parse enum body.
@@ -4160,7 +4152,7 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr, bool IsJavaRecord) {
if (ParseAsExpr) {
parseChildBlock();
} else {
- if (ShouldBreakBeforeBrace(Style, InitialToken))
+ if (ShouldBreakBeforeBrace(Style, InitialToken, IsJavaRecord))
addUnwrappedLine();
unsigned AddLevels = Style.IndentAccessModifiers ? 2u : 1u;
@@ -4555,6 +4547,23 @@ void UnwrappedLineParser::parseVerilogCaseLabel() {
Line->Level = OrigLevel;
}
+void UnwrappedLineParser::parseVerilogExtern() {
+ assert(
+ FormatTok->isOneOf(tok::kw_extern, tok::kw_export, Keywords.kw_import));
+ nextToken();
+ // "DPI-C"
+ if (FormatTok->is(tok::string_literal))
+ nextToken();
+ if (FormatTok->isOneOf(Keywords.kw_context, Keywords.kw_pure))
+ nextToken();
+ if (Keywords.isVerilogIdentifier(*FormatTok))
+ nextToken();
+ if (FormatTok->is(tok::equal))
+ nextToken();
+ if (Keywords.isVerilogHierarchy(*FormatTok))
+ parseVerilogHierarchyHeader();
+}
+
bool UnwrappedLineParser::containsExpansion(const UnwrappedLine &Line) const {
for (const auto &N : Line.Tokens) {
if (N.Tok->MacroCtx)
diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h
index 8b8ad84..86022d9 100644
--- a/clang/lib/Format/UnwrappedLineParser.h
+++ b/clang/lib/Format/UnwrappedLineParser.h
@@ -169,8 +169,8 @@ private:
bool parseEnum();
bool parseStructLike();
bool parseRequires(bool SeenEqual);
- void parseRequiresClause(FormatToken *RequiresToken);
- void parseRequiresExpression(FormatToken *RequiresToken);
+ void parseRequiresClause();
+ void parseRequiresExpression();
void parseConstraintExpression();
void parseCppExportBlock();
void parseNamespaceOrExportBlock(unsigned AddLevels);
@@ -205,6 +205,8 @@ private:
unsigned parseVerilogHierarchyHeader();
void parseVerilogTable();
void parseVerilogCaseLabel();
+ // For import, export, and extern.
+ void parseVerilogExtern();
std::optional<llvm::SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>>
parseMacroCall();
diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp
index f24b8ab..805bb78 100644
--- a/clang/lib/Format/WhitespaceManager.cpp
+++ b/clang/lib/Format/WhitespaceManager.cpp
@@ -35,13 +35,15 @@ WhitespaceManager::Change::Change(const FormatToken &Tok,
bool CreateReplacement,
SourceRange OriginalWhitespaceRange,
int Spaces, unsigned StartOfTokenColumn,
+ unsigned IndentedFromColumn,
unsigned NewlinesBefore,
StringRef PreviousLinePostfix,
StringRef CurrentLinePrefix, bool IsAligned,
bool ContinuesPPDirective, bool IsInsideToken)
: Tok(&Tok), CreateReplacement(CreateReplacement),
OriginalWhitespaceRange(OriginalWhitespaceRange),
- StartOfTokenColumn(StartOfTokenColumn), NewlinesBefore(NewlinesBefore),
+ StartOfTokenColumn(StartOfTokenColumn),
+ IndentedFromColumn(IndentedFromColumn), NewlinesBefore(NewlinesBefore),
PreviousLinePostfix(PreviousLinePostfix),
CurrentLinePrefix(CurrentLinePrefix), IsAligned(IsAligned),
ContinuesPPDirective(ContinuesPPDirective), Spaces(Spaces),
@@ -53,13 +55,15 @@ WhitespaceManager::Change::Change(const FormatToken &Tok,
void WhitespaceManager::replaceWhitespace(FormatToken &Tok, unsigned Newlines,
unsigned Spaces,
unsigned StartOfTokenColumn,
- bool IsAligned, bool InPPDirective) {
+ bool IsAligned, bool InPPDirective,
+ unsigned IndentedFromColumn) {
if (Tok.Finalized || (Tok.MacroCtx && Tok.MacroCtx->Role == MR_ExpandedArg))
return;
Tok.setDecision((Newlines > 0) ? FD_Break : FD_Continue);
Changes.push_back(Change(Tok, /*CreateReplacement=*/true, Tok.WhitespaceRange,
- Spaces, StartOfTokenColumn, Newlines, "", "",
- IsAligned, InPPDirective && !Tok.IsFirst,
+ Spaces, StartOfTokenColumn, IndentedFromColumn,
+ Newlines, "", "", IsAligned,
+ InPPDirective && !Tok.IsFirst,
/*IsInsideToken=*/false));
}
@@ -67,11 +71,11 @@ void WhitespaceManager::addUntouchableToken(const FormatToken &Tok,
bool InPPDirective) {
if (Tok.Finalized || (Tok.MacroCtx && Tok.MacroCtx->Role == MR_ExpandedArg))
return;
- Changes.push_back(Change(Tok, /*CreateReplacement=*/false,
- Tok.WhitespaceRange, /*Spaces=*/0,
- Tok.OriginalColumn, Tok.NewlinesBefore, "", "",
- /*IsAligned=*/false, InPPDirective && !Tok.IsFirst,
- /*IsInsideToken=*/false));
+ Changes.push_back(Change(
+ Tok, /*CreateReplacement=*/false, Tok.WhitespaceRange, /*Spaces=*/0,
+ Tok.OriginalColumn, /*IndentedFromColumn=*/0, Tok.NewlinesBefore, "", "",
+ /*IsAligned=*/false, InPPDirective && !Tok.IsFirst,
+ /*IsInsideToken=*/false));
}
llvm::Error
@@ -95,7 +99,8 @@ void WhitespaceManager::replaceWhitespaceInToken(
Changes.push_back(
Change(Tok, /*CreateReplacement=*/true,
SourceRange(Start, Start.getLocWithOffset(ReplaceChars)), Spaces,
- std::max(0, Spaces), Newlines, PreviousPostfix, CurrentPrefix,
+ std::max(0, Spaces), /*IndentedFromColumn=*/0, Newlines,
+ PreviousPostfix, CurrentPrefix,
/*IsAligned=*/true, InPPDirective && !Tok.IsFirst,
/*IsInsideToken=*/true));
}
@@ -287,6 +292,7 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
unsigned Column, bool RightJustify,
ArrayRef<unsigned> Matches,
SmallVector<WhitespaceManager::Change, 16> &Changes) {
+ unsigned OriginalMatchColumn = 0;
int Shift = 0;
// Set when the shift is applied anywhere in the line. Cleared when the line
// ends.
@@ -330,21 +336,19 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
// Keep track of the level that should not move with the aligned token.
if (ScopeStack.size() == 1u && CurrentChange.NewlinesBefore != 0u &&
CurrentChange.indentAndNestingLevel() > ScopeStack[0] &&
- !CurrentChange.IsAligned) {
+ CurrentChange.IndentedFromColumn < OriginalMatchColumn) {
ScopeStack.push_back(CurrentChange.indentAndNestingLevel());
}
bool InsideNestedScope =
!ScopeStack.empty() &&
- CurrentChange.indentAndNestingLevel() > ScopeStack[0];
- bool ContinuedStringLiteral = i > Start &&
- CurrentChange.Tok->is(tok::string_literal) &&
- Changes[i - 1].Tok->is(tok::string_literal);
- bool SkipMatchCheck = InsideNestedScope || ContinuedStringLiteral;
+ (CurrentChange.indentAndNestingLevel() > ScopeStack[0] ||
+ (CurrentChange.indentAndNestingLevel() == ScopeStack[0] &&
+ CurrentChange.IndentedFromColumn >= OriginalMatchColumn));
if (CurrentChange.NewlinesBefore > 0) {
LineShifted = false;
- if (!SkipMatchCheck)
+ if (!InsideNestedScope)
Shift = 0;
}
@@ -352,6 +356,7 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
// spaces it has to be shifted, so the rest of the changes on the line are
// shifted by the same amount
if (!Matches.empty() && Matches[0] == i) {
+ OriginalMatchColumn = CurrentChange.StartOfTokenColumn;
Shift = Column - (RightJustify ? CurrentChange.TokenLength : 0) -
CurrentChange.StartOfTokenColumn;
ScopeStack = {CurrentChange.indentAndNestingLevel()};
@@ -365,7 +370,7 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
// not in a scope that should not move.
if ((!Matches.empty() && Matches[0] == i) ||
(ScopeStack.size() == 1u && CurrentChange.NewlinesBefore > 0 &&
- (ContinuedStringLiteral || InsideNestedScope))) {
+ InsideNestedScope)) {
LineShifted = true;
CurrentChange.Spaces += Shift;
}
@@ -516,7 +521,8 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches,
};
unsigned I = StartAt;
- for (unsigned E = Changes.size(); I != E; ++I) {
+ const auto E = Changes.size();
+ for (; I != E; ++I) {
auto &CurrentChange = Changes[I];
if (CurrentChange.indentAndNestingLevel() < IndentAndNestingLevel)
break;
@@ -591,7 +597,8 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches,
CurrentChangeWidthRight = CurrentChange.TokenLength;
const FormatToken *MatchingParenToEncounter = nullptr;
for (unsigned J = I + 1;
- J != E && (Changes[J].NewlinesBefore == 0 || MatchingParenToEncounter);
+ J != E && (Changes[J].NewlinesBefore == 0 ||
+ MatchingParenToEncounter || Changes[J].IsAligned);
++J) {
const auto &Change = Changes[J];
const auto *Tok = Change.Tok;
@@ -621,7 +628,7 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches,
// int k = bar( | We still want to align the = | int k = bar(
// argument1, | here, even if we can't move | argument1,
// argument2); | the following lines. | argument2);
- if (static_cast<unsigned>(Change.Spaces) < ChangeWidthStart)
+ if (Change.IndentedFromColumn < ChangeWidthStart)
break;
CurrentChangeWidthRight = Change.Spaces - ChangeWidthStart;
} else {
@@ -659,8 +666,15 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches,
MatchedIndices.push_back(I);
}
- EndOfSequence = I;
+ // Pass entire lines to the function so that it can update the state of all
+ // tokens that move.
+ for (EndOfSequence = I;
+ EndOfSequence < E && Changes[EndOfSequence].NewlinesBefore == 0;
+ ++EndOfSequence) {
+ }
AlignCurrentSequence();
+ // The return value should still be where the level ends. The rest of the line
+ // may contain stuff to be aligned within an outer level.
return I;
}
@@ -1006,9 +1020,13 @@ void WhitespaceManager::alignTrailingComments() {
return;
const int Size = Changes.size();
+ if (Size == 0)
+ return;
+
int MinColumn = 0;
int StartOfSequence = 0;
bool BreakBeforeNext = false;
+ bool IsInPP = Changes.front().Tok->Tok.is(tok::hash);
int NewLineThreshold = 1;
if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Always)
NewLineThreshold = Style.AlignTrailingComments.OverEmptyLines + 1;
@@ -1017,7 +1035,19 @@ void WhitespaceManager::alignTrailingComments() {
auto &C = Changes[I];
if (C.StartOfBlockComment)
continue;
- Newlines += C.NewlinesBefore;
+ if (C.NewlinesBefore != 0) {
+ Newlines += C.NewlinesBefore;
+ const bool WasInPP = std::exchange(
+ IsInPP, C.Tok->Tok.is(tok::hash) || (IsInPP && C.IsTrailingComment) ||
+ C.ContinuesPPDirective);
+ if (IsInPP != WasInPP && !Style.AlignTrailingComments.AlignPPAndNotPP) {
+ alignTrailingComments(StartOfSequence, I, MinColumn);
+ MinColumn = 0;
+ MaxColumn = INT_MAX;
+ StartOfSequence = I;
+ Newlines = 0;
+ }
+ }
if (!C.IsTrailingComment)
continue;
@@ -1215,7 +1245,10 @@ void WhitespaceManager::alignArrayInitializers() {
bool FoundComplete = false;
for (unsigned InsideIndex = ChangeIndex + 1; InsideIndex < ChangeEnd;
++InsideIndex) {
- if (Changes[InsideIndex].Tok == C.Tok->MatchingParen) {
+ const auto *Tok = Changes[InsideIndex].Tok;
+ if (Tok->is(tok::pp_define))
+ break;
+ if (Tok == C.Tok->MatchingParen) {
alignArrayInitializers(ChangeIndex, InsideIndex + 1);
ChangeIndex = InsideIndex + 1;
FoundComplete = true;
diff --git a/clang/lib/Format/WhitespaceManager.h b/clang/lib/Format/WhitespaceManager.h
index 6d18db7..3e6fa9d 100644
--- a/clang/lib/Format/WhitespaceManager.h
+++ b/clang/lib/Format/WhitespaceManager.h
@@ -49,9 +49,15 @@ public:
/// \p StartOfTokenColumn is the column at which the token will start after
/// this replacement. It is needed for determining how \p Spaces is turned
/// into tabs and spaces for some format styles.
+ ///
+ /// \p IndentedFromColumn is only used when the replacement starts a new
+ /// line. It should be the column that the position of the line is derived
+ /// from. It is used for determining what lines the alignment process should
+ /// move.
void replaceWhitespace(FormatToken &Tok, unsigned Newlines, unsigned Spaces,
unsigned StartOfTokenColumn, bool IsAligned = false,
- bool InPPDirective = false);
+ bool InPPDirective = false,
+ unsigned IndentedFromColumn = 0);
/// Adds information about an unchangeable token's whitespace.
///
@@ -104,13 +110,15 @@ public:
/// \p PreviousLinePostfix, \p NewlinesBefore line breaks, \p Spaces spaces
/// and \p CurrentLinePrefix.
///
- /// \p StartOfTokenColumn and \p InPPDirective will be used to lay out
- /// trailing comments and escaped newlines.
+ /// \p StartOfTokenColumn and \p ContinuesPPDirective will be used to lay
+ /// out trailing comments and escaped newlines. \p IndentedFromColumn will
+ /// be used to continue aligned lines.
Change(const FormatToken &Tok, bool CreateReplacement,
SourceRange OriginalWhitespaceRange, int Spaces,
- unsigned StartOfTokenColumn, unsigned NewlinesBefore,
- StringRef PreviousLinePostfix, StringRef CurrentLinePrefix,
- bool IsAligned, bool ContinuesPPDirective, bool IsInsideToken);
+ unsigned StartOfTokenColumn, unsigned IndentedFromColumn,
+ unsigned NewlinesBefore, StringRef PreviousLinePostfix,
+ StringRef CurrentLinePrefix, bool IsAligned,
+ bool ContinuesPPDirective, bool IsInsideToken);
// The kind of the token whose whitespace this change replaces, or in which
// this change inserts whitespace.
@@ -123,6 +131,11 @@ public:
// FormatToken around to query its information.
SourceRange OriginalWhitespaceRange;
unsigned StartOfTokenColumn;
+ // Only used when the token is at the start of a line. The column that the
+ // position of the line is derived from. The alignment procedure moves the
+ // line when it moves a token in the same unwrapped line that is to the left
+ // of said column.
+ unsigned IndentedFromColumn;
unsigned NewlinesBefore;
std::string PreviousLinePostfix;
std::string CurrentLinePrefix;