aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Format
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Format')
-rw-r--r--contrib/llvm-project/clang/lib/Format/BreakableToken.cpp92
-rw-r--r--contrib/llvm-project/clang/lib/Format/BreakableToken.h1
-rw-r--r--contrib/llvm-project/clang/lib/Format/ContinuationIndenter.cpp59
-rw-r--r--contrib/llvm-project/clang/lib/Format/Format.cpp167
-rw-r--r--contrib/llvm-project/clang/lib/Format/FormatInternal.h1
-rw-r--r--contrib/llvm-project/clang/lib/Format/FormatToken.cpp5
-rw-r--r--contrib/llvm-project/clang/lib/Format/FormatToken.h279
-rw-r--r--contrib/llvm-project/clang/lib/Format/FormatTokenLexer.cpp23
-rw-r--r--contrib/llvm-project/clang/lib/Format/MacroExpander.cpp224
-rw-r--r--contrib/llvm-project/clang/lib/Format/Macros.h141
-rwxr-xr-x[-rw-r--r--]contrib/llvm-project/clang/lib/Format/TokenAnnotator.cpp243
-rw-r--r--contrib/llvm-project/clang/lib/Format/UnwrappedLineFormatter.cpp78
-rw-r--r--contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp307
-rw-r--r--contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.h17
-rw-r--r--contrib/llvm-project/clang/lib/Format/WhitespaceManager.cpp86
15 files changed, 1398 insertions, 325 deletions
diff --git a/contrib/llvm-project/clang/lib/Format/BreakableToken.cpp b/contrib/llvm-project/clang/lib/Format/BreakableToken.cpp
index 15fbe3b6515d..f179ac64de17 100644
--- a/contrib/llvm-project/clang/lib/Format/BreakableToken.cpp
+++ b/contrib/llvm-project/clang/lib/Format/BreakableToken.cpp
@@ -25,7 +25,7 @@
namespace clang {
namespace format {
-static const char *const Blanks = " \t\v\f\r";
+static constexpr StringRef Blanks = " \t\v\f\r";
static bool IsBlank(char C) {
switch (C) {
case ' ':
@@ -41,25 +41,27 @@ static bool IsBlank(char C) {
static StringRef getLineCommentIndentPrefix(StringRef Comment,
const FormatStyle &Style) {
- static const char *const KnownCStylePrefixes[] = {"///<", "//!<", "///", "//",
- "//!"};
- static const char *const KnownTextProtoPrefixes[] = {"//", "#", "##", "###",
- "####"};
- ArrayRef<const char *> KnownPrefixes(KnownCStylePrefixes);
+ static constexpr StringRef KnownCStylePrefixes[] = {"///<", "//!<", "///",
+ "//!", "//:", "//"};
+ static constexpr StringRef KnownTextProtoPrefixes[] = {"####", "###", "##",
+ "//", "#"};
+ ArrayRef<StringRef> KnownPrefixes(KnownCStylePrefixes);
if (Style.Language == FormatStyle::LK_TextProto)
KnownPrefixes = KnownTextProtoPrefixes;
- StringRef LongestPrefix;
+ assert(std::is_sorted(KnownPrefixes.begin(), KnownPrefixes.end(),
+ [](StringRef Lhs, StringRef Rhs) noexcept {
+ return Lhs.size() > Rhs.size();
+ }));
+
for (StringRef KnownPrefix : KnownPrefixes) {
if (Comment.startswith(KnownPrefix)) {
- size_t PrefixLength = KnownPrefix.size();
- while (PrefixLength < Comment.size() && Comment[PrefixLength] == ' ')
- ++PrefixLength;
- if (PrefixLength > LongestPrefix.size())
- LongestPrefix = Comment.substr(0, PrefixLength);
+ const auto PrefixLength =
+ Comment.find_first_not_of(' ', KnownPrefix.size());
+ return Comment.substr(0, PrefixLength);
}
}
- return LongestPrefix;
+ return {};
}
static BreakableToken::Split
@@ -86,22 +88,53 @@ getCommentSplit(StringRef Text, unsigned ContentStartColumn,
MaxSplitBytes += BytesInChar;
}
+ // In JavaScript, some @tags can be followed by {, and machinery that parses
+ // these comments will fail to understand the comment if followed by a line
+ // break. So avoid ever breaking before a {.
+ if (Style.Language == FormatStyle::LK_JavaScript) {
+ StringRef::size_type SpaceOffset =
+ Text.find_first_of(Blanks, MaxSplitBytes);
+ if (SpaceOffset != StringRef::npos && SpaceOffset + 1 < Text.size() &&
+ Text[SpaceOffset + 1] == '{') {
+ MaxSplitBytes = SpaceOffset + 1;
+ }
+ }
+
StringRef::size_type SpaceOffset = Text.find_last_of(Blanks, MaxSplitBytes);
static const auto kNumberedListRegexp = llvm::Regex("^[1-9][0-9]?\\.");
+ // Some spaces are unacceptable to break on, rewind past them.
while (SpaceOffset != StringRef::npos) {
+ // If a line-comment ends with `\`, the next line continues the comment,
+ // whether or not it starts with `//`. This is confusing and triggers
+ // -Wcomment.
+ // Avoid introducing multiline comments by not allowing a break right
+ // after '\'.
+ if (Style.isCpp()) {
+ StringRef::size_type LastNonBlank =
+ Text.find_last_not_of(Blanks, SpaceOffset);
+ if (LastNonBlank != StringRef::npos && Text[LastNonBlank] == '\\') {
+ SpaceOffset = Text.find_last_of(Blanks, LastNonBlank);
+ continue;
+ }
+ }
+
// Do not split before a number followed by a dot: this would be interpreted
// as a numbered list, which would prevent re-flowing in subsequent passes.
- if (kNumberedListRegexp.match(Text.substr(SpaceOffset).ltrim(Blanks)))
+ if (kNumberedListRegexp.match(Text.substr(SpaceOffset).ltrim(Blanks))) {
SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);
- // In JavaScript, some @tags can be followed by {, and machinery that parses
- // these comments will fail to understand the comment if followed by a line
- // break. So avoid ever breaking before a {.
- else if (Style.Language == FormatStyle::LK_JavaScript &&
- SpaceOffset + 1 < Text.size() && Text[SpaceOffset + 1] == '{')
+ continue;
+ }
+
+ // Avoid ever breaking before a @tag or a { in JavaScript.
+ if (Style.Language == FormatStyle::LK_JavaScript &&
+ SpaceOffset + 1 < Text.size() &&
+ (Text[SpaceOffset + 1] == '{' || Text[SpaceOffset + 1] == '@')) {
SpaceOffset = Text.find_last_of(Blanks, SpaceOffset);
- else
- break;
+ continue;
+ }
+
+ break;
}
if (SpaceOffset == StringRef::npos ||
@@ -718,8 +751,7 @@ bool BreakableBlockComment::mayReflow(
}
BreakableLineCommentSection::BreakableLineCommentSection(
- const FormatToken &Token, unsigned StartColumn,
- unsigned OriginalStartColumn, bool FirstInLine, bool InPPDirective,
+ const FormatToken &Token, unsigned StartColumn, bool InPPDirective,
encoding::Encoding Encoding, const FormatStyle &Style)
: BreakableComment(Token, StartColumn, InPPDirective, Encoding, Style) {
assert(Tok.is(TT_LineComment) &&
@@ -742,10 +774,7 @@ BreakableLineCommentSection::BreakableLineCommentSection(
OriginalPrefix.resize(Lines.size());
for (size_t i = FirstLineIndex, e = Lines.size(); i < e; ++i) {
Lines[i] = Lines[i].ltrim(Blanks);
- // We need to trim the blanks in case this is not the first line in a
- // multiline comment. Then the indent is included in Lines[i].
- StringRef IndentPrefix =
- getLineCommentIndentPrefix(Lines[i].ltrim(Blanks), Style);
+ StringRef IndentPrefix = getLineCommentIndentPrefix(Lines[i], Style);
assert((TokenText.startswith("//") || TokenText.startswith("#")) &&
"unsupported line comment prefix, '//' and '#' are supported");
OriginalPrefix[i] = Prefix[i] = IndentPrefix;
@@ -761,9 +790,14 @@ BreakableLineCommentSection::BreakableLineCommentSection(
Prefix[i] = "///< ";
else if (Prefix[i] == "//!<")
Prefix[i] = "//!< ";
- else if (Prefix[i] == "#" &&
- Style.Language == FormatStyle::LK_TextProto)
+ else if (Prefix[i] == "#")
Prefix[i] = "# ";
+ else if (Prefix[i] == "##")
+ Prefix[i] = "## ";
+ else if (Prefix[i] == "###")
+ Prefix[i] = "### ";
+ else if (Prefix[i] == "####")
+ Prefix[i] = "#### ";
}
Tokens[i] = LineTok;
diff --git a/contrib/llvm-project/clang/lib/Format/BreakableToken.h b/contrib/llvm-project/clang/lib/Format/BreakableToken.h
index a6691300de3b..41b19f82e9df 100644
--- a/contrib/llvm-project/clang/lib/Format/BreakableToken.h
+++ b/contrib/llvm-project/clang/lib/Format/BreakableToken.h
@@ -436,7 +436,6 @@ private:
class BreakableLineCommentSection : public BreakableComment {
public:
BreakableLineCommentSection(const FormatToken &Token, unsigned StartColumn,
- unsigned OriginalStartColumn, bool FirstInLine,
bool InPPDirective, encoding::Encoding Encoding,
const FormatStyle &Style);
diff --git a/contrib/llvm-project/clang/lib/Format/ContinuationIndenter.cpp b/contrib/llvm-project/clang/lib/Format/ContinuationIndenter.cpp
index b1497651a8fe..7198671901f3 100644
--- a/contrib/llvm-project/clang/lib/Format/ContinuationIndenter.cpp
+++ b/contrib/llvm-project/clang/lib/Format/ContinuationIndenter.cpp
@@ -284,7 +284,7 @@ bool ContinuationIndenter::canBreak(const LineState &State) {
// The opening "{" of a braced list has to be on the same line as the first
// element if it is nested in another braced init list or function call.
if (!Current.MustBreakBefore && Previous.is(tok::l_brace) &&
- Previous.isNot(TT_DictLiteral) && Previous.BlockKind == BK_BracedInit &&
+ Previous.isNot(TT_DictLiteral) && Previous.is(BK_BracedInit) &&
Previous.Previous &&
Previous.Previous->isOneOf(tok::l_brace, tok::l_paren, tok::comma))
return false;
@@ -400,7 +400,9 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
return true;
if (Current.is(TT_SelectorName) && !Previous.is(tok::at) &&
State.Stack.back().ObjCSelectorNameFound &&
- State.Stack.back().BreakBeforeParameter)
+ State.Stack.back().BreakBeforeParameter &&
+ (Style.ObjCBreakBeforeNestedBlockParam ||
+ !Current.startsSequence(TT_SelectorName, tok::colon, tok::caret)))
return true;
unsigned NewLineColumn = getNewLineColumn(State);
@@ -501,7 +503,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
// The following could be precomputed as they do not depend on the state.
// However, as they should take effect only if the UnwrappedLine does not fit
// into the ColumnLimit, they are checked here in the ContinuationIndenter.
- if (Style.ColumnLimit != 0 && Previous.BlockKind == BK_Block &&
+ if (Style.ColumnLimit != 0 && Previous.is(BK_Block) &&
Previous.is(tok::l_brace) && !Current.isOneOf(tok::r_brace, tok::comment))
return true;
@@ -627,7 +629,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
// opening parenthesis. Don't break if it doesn't conserve columns.
if (Style.AlignAfterOpenBracket == FormatStyle::BAS_AlwaysBreak &&
(Previous.isOneOf(tok::l_paren, TT_TemplateOpener, tok::l_square) ||
- (Previous.is(tok::l_brace) && Previous.BlockKind != BK_Block &&
+ (Previous.is(tok::l_brace) && Previous.isNot(BK_Block) &&
Style.Cpp11BracedListStyle)) &&
State.Column > getNewLineColumn(State) &&
(!Previous.Previous || !Previous.Previous->isOneOf(
@@ -648,7 +650,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
if (Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign &&
!State.Stack.back().IsCSharpGenericTypeConstraint &&
Previous.opensScope() && Previous.isNot(TT_ObjCMethodExpr) &&
- (Current.isNot(TT_LineComment) || Previous.BlockKind == BK_BracedInit)) {
+ (Current.isNot(TT_LineComment) || Previous.is(BK_BracedInit))) {
State.Stack.back().Indent = State.Column + Spaces;
State.Stack.back().IsAligned = true;
}
@@ -783,6 +785,22 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
State.Column = getNewLineColumn(State);
+ // Add Penalty proportional to amount of whitespace away from FirstColumn
+ // This tends to penalize several lines that are far-right indented,
+ // and prefers a line-break prior to such a block, e.g:
+ //
+ // Constructor() :
+ // member(value), looooooooooooooooong_member(
+ // looooooooooong_call(param_1, param_2, param_3))
+ // would then become
+ // Constructor() :
+ // member(value),
+ // looooooooooooooooong_member(
+ // looooooooooong_call(param_1, param_2, param_3))
+ if (State.Column > State.FirstIndent)
+ Penalty +=
+ Style.PenaltyIndentedWhitespace * (State.Column - State.FirstIndent);
+
// Indent nested blocks relative to this column, unless in a very specific
// JavaScript special case where:
//
@@ -972,7 +990,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
return (Style.IndentWidth * State.Line->First->IndentLevel) +
Style.IndentWidth;
- if (NextNonComment->is(tok::l_brace) && NextNonComment->BlockKind == BK_Block)
+ if (NextNonComment->is(tok::l_brace) && NextNonComment->is(BK_Block))
return Current.NestingLevel == 0 ? State.FirstIndent
: State.Stack.back().Indent;
if ((Current.isOneOf(tok::r_brace, tok::r_square) ||
@@ -982,8 +1000,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
State.Stack.size() > 1) {
if (Current.closesBlockOrBlockTypeList(Style))
return State.Stack[State.Stack.size() - 2].NestedBlockIndent;
- if (Current.MatchingParen &&
- Current.MatchingParen->BlockKind == BK_BracedInit)
+ if (Current.MatchingParen && Current.MatchingParen->is(BK_BracedInit))
return State.Stack[State.Stack.size() - 2].LastSpace;
return State.FirstIndent;
}
@@ -1349,16 +1366,20 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
State.Stack.back().LastSpace);
}
- // If BreakBeforeBinaryOperators is set, un-indent a bit to account for
- // the operator and keep the operands aligned
- if (Style.AlignOperands == FormatStyle::OAS_AlignAfterOperator &&
- Previous &&
+ if (Previous &&
(Previous->getPrecedence() == prec::Assignment ||
Previous->is(tok::kw_return) ||
(*I == prec::Conditional && Previous->is(tok::question) &&
Previous->is(TT_ConditionalExpr))) &&
- !Newline)
- NewParenState.UnindentOperator = true;
+ !Newline) {
+ // If BreakBeforeBinaryOperators is set, un-indent a bit to account for
+ // the operator and keep the operands aligned
+ if (Style.AlignOperands == FormatStyle::OAS_AlignAfterOperator)
+ NewParenState.UnindentOperator = true;
+ // Mark indentation as alignment if the expression is aligned.
+ if (Style.AlignOperands != FormatStyle::OAS_DontAlign)
+ NewParenState.IsAligned = true;
+ }
// Do not indent relative to the fake parentheses inserted for "." or "->".
// This is a special case to make the following to statements consistent:
@@ -1417,7 +1438,7 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
State.Stack.back().IsCSharpGenericTypeConstraint)
return;
- if (Current.MatchingParen && Current.BlockKind == BK_Block) {
+ if (Current.MatchingParen && Current.is(BK_Block)) {
moveStateToNewBlock(State);
return;
}
@@ -1486,9 +1507,8 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
(State.Line->MustBeDeclaration && !BinPackDeclaration) ||
(!State.Line->MustBeDeclaration && !Style.BinPackArguments) ||
(Style.ExperimentalAutoDetectBinPacking &&
- (Current.PackingKind == PPK_OnePerLine ||
- (!BinPackInconclusiveFunctions &&
- Current.PackingKind == PPK_Inconclusive)));
+ (Current.is(PPK_OnePerLine) ||
+ (!BinPackInconclusiveFunctions && Current.is(PPK_Inconclusive))));
if (Current.is(TT_ObjCMethodExpr) && Current.MatchingParen &&
Style.ObjCBreakBeforeNestedBlockParam) {
@@ -1954,8 +1974,7 @@ ContinuationIndenter::createBreakableToken(const FormatToken &Current,
switchesFormatting(Current))
return nullptr;
return std::make_unique<BreakableLineCommentSection>(
- Current, StartColumn, Current.OriginalColumn, !Current.Previous,
- /*InPPDirective=*/false, Encoding, Style);
+ Current, StartColumn, /*InPPDirective=*/false, Encoding, Style);
}
return nullptr;
}
diff --git a/contrib/llvm-project/clang/lib/Format/Format.cpp b/contrib/llvm-project/clang/lib/Format/Format.cpp
index 0d277a6464af..5f5bb8585ac1 100644
--- a/contrib/llvm-project/clang/lib/Format/Format.cpp
+++ b/contrib/llvm-project/clang/lib/Format/Format.cpp
@@ -128,6 +128,21 @@ template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
}
};
+template <> struct ScalarEnumerationTraits<FormatStyle::AlignConsecutiveStyle> {
+ static void enumeration(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
+ IO.enumCase(Value, "None", FormatStyle::ACS_None);
+ IO.enumCase(Value, "Consecutive", FormatStyle::ACS_Consecutive);
+ IO.enumCase(Value, "AcrossEmptyLines", FormatStyle::ACS_AcrossEmptyLines);
+ IO.enumCase(Value, "AcrossComments", FormatStyle::ACS_AcrossComments);
+ IO.enumCase(Value, "AcrossEmptyLinesAndComments",
+ FormatStyle::ACS_AcrossEmptyLinesAndComments);
+
+ // For backward compability.
+ IO.enumCase(Value, "true", FormatStyle::ACS_Consecutive);
+ IO.enumCase(Value, "false", FormatStyle::ACS_None);
+ }
+};
+
template <> struct ScalarEnumerationTraits<FormatStyle::ShortIfStyle> {
static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value) {
IO.enumCase(Value, "Never", FormatStyle::SIS_Never);
@@ -227,6 +242,18 @@ struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> {
};
template <>
+struct ScalarEnumerationTraits<
+ FormatStyle::EmptyLineBeforeAccessModifierStyle> {
+ static void
+ enumeration(IO &IO, FormatStyle::EmptyLineBeforeAccessModifierStyle &Value) {
+ IO.enumCase(Value, "Never", FormatStyle::ELBAMS_Never);
+ IO.enumCase(Value, "Leave", FormatStyle::ELBAMS_Leave);
+ IO.enumCase(Value, "LogicalBlock", FormatStyle::ELBAMS_LogicalBlock);
+ IO.enumCase(Value, "Always", FormatStyle::ELBAMS_Always);
+ }
+};
+
+template <>
struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> {
static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) {
IO.enumCase(Value, "None", FormatStyle::PPDIS_None);
@@ -348,6 +375,17 @@ template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
};
template <>
+struct ScalarEnumerationTraits<FormatStyle::SpaceAroundPointerQualifiersStyle> {
+ static void
+ enumeration(IO &IO, FormatStyle::SpaceAroundPointerQualifiersStyle &Value) {
+ IO.enumCase(Value, "Default", FormatStyle::SAPQ_Default);
+ IO.enumCase(Value, "Before", FormatStyle::SAPQ_Before);
+ IO.enumCase(Value, "After", FormatStyle::SAPQ_After);
+ IO.enumCase(Value, "Both", FormatStyle::SAPQ_Both);
+ }
+};
+
+template <>
struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> {
static void enumeration(IO &IO,
FormatStyle::SpaceBeforeParensOptions &Value) {
@@ -366,6 +404,26 @@ struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> {
}
};
+template <>
+struct ScalarEnumerationTraits<FormatStyle::BitFieldColonSpacingStyle> {
+ static void enumeration(IO &IO,
+ FormatStyle::BitFieldColonSpacingStyle &Value) {
+ IO.enumCase(Value, "Both", FormatStyle::BFCS_Both);
+ IO.enumCase(Value, "None", FormatStyle::BFCS_None);
+ IO.enumCase(Value, "Before", FormatStyle::BFCS_Before);
+ IO.enumCase(Value, "After", FormatStyle::BFCS_After);
+ }
+};
+
+template <>
+struct ScalarEnumerationTraits<FormatStyle::SortJavaStaticImportOptions> {
+ static void enumeration(IO &IO,
+ FormatStyle::SortJavaStaticImportOptions &Value) {
+ IO.enumCase(Value, "Before", FormatStyle::SJSIO_Before);
+ IO.enumCase(Value, "After", FormatStyle::SJSIO_After);
+ }
+};
+
template <> struct MappingTraits<FormatStyle> {
static void mapping(IO &IO, FormatStyle &Style) {
// When reading, read the language first, we need it for getPredefinedStyle.
@@ -464,11 +522,14 @@ template <> struct MappingTraits<FormatStyle> {
Style.AlwaysBreakBeforeMultilineStrings);
IO.mapOptional("AlwaysBreakTemplateDeclarations",
Style.AlwaysBreakTemplateDeclarations);
+ IO.mapOptional("AttributeMacros", Style.AttributeMacros);
IO.mapOptional("BinPackArguments", Style.BinPackArguments);
IO.mapOptional("BinPackParameters", Style.BinPackParameters);
IO.mapOptional("BraceWrapping", Style.BraceWrapping);
IO.mapOptional("BreakBeforeBinaryOperators",
Style.BreakBeforeBinaryOperators);
+ IO.mapOptional("BreakBeforeConceptDeclarations",
+ Style.BreakBeforeConceptDeclarations);
IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
bool BreakBeforeInheritanceComma = false;
@@ -511,10 +572,14 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("DeriveLineEnding", Style.DeriveLineEnding);
IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment);
IO.mapOptional("DisableFormat", Style.DisableFormat);
+ IO.mapOptional("EmptyLineBeforeAccessModifier",
+ Style.EmptyLineBeforeAccessModifier);
IO.mapOptional("ExperimentalAutoDetectBinPacking",
Style.ExperimentalAutoDetectBinPacking);
IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments);
IO.mapOptional("ForEachMacros", Style.ForEachMacros);
+ IO.mapOptional("StatementAttributeLikeMacros",
+ Style.StatementAttributeLikeMacros);
IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);
IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);
IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);
@@ -525,6 +590,7 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("IndentGotoLabels", Style.IndentGotoLabels);
IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives);
IO.mapOptional("IndentExternBlock", Style.IndentExternBlock);
+ IO.mapOptional("IndentRequires", Style.IndentRequires);
IO.mapOptional("IndentWidth", Style.IndentWidth);
IO.mapOptional("IndentWrappedFunctionNames",
Style.IndentWrappedFunctionNames);
@@ -558,10 +624,13 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);
IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
Style.PenaltyReturnTypeOnItsOwnLine);
+ IO.mapOptional("PenaltyIndentedWhitespace",
+ Style.PenaltyIndentedWhitespace);
IO.mapOptional("PointerAlignment", Style.PointerAlignment);
IO.mapOptional("RawStringFormats", Style.RawStringFormats);
IO.mapOptional("ReflowComments", Style.ReflowComments);
IO.mapOptional("SortIncludes", Style.SortIncludes);
+ IO.mapOptional("SortJavaStaticImport", Style.SortJavaStaticImport);
IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations);
IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);
IO.mapOptional("SpaceAfterLogicalNot", Style.SpaceAfterLogicalNot);
@@ -569,6 +638,7 @@ template <> struct MappingTraits<FormatStyle> {
Style.SpaceAfterTemplateKeyword);
IO.mapOptional("SpaceBeforeAssignmentOperators",
Style.SpaceBeforeAssignmentOperators);
+ IO.mapOptional("SpaceBeforeCaseColon", Style.SpaceBeforeCaseColon);
IO.mapOptional("SpaceBeforeCpp11BracedList",
Style.SpaceBeforeCpp11BracedList);
IO.mapOptional("SpaceBeforeCtorInitializerColon",
@@ -576,6 +646,8 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("SpaceBeforeInheritanceColon",
Style.SpaceBeforeInheritanceColon);
IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
+ IO.mapOptional("SpaceAroundPointerQualifiers",
+ Style.SpaceAroundPointerQualifiers);
IO.mapOptional("SpaceBeforeRangeBasedForLoopColon",
Style.SpaceBeforeRangeBasedForLoopColon);
IO.mapOptional("SpaceInEmptyBlock", Style.SpaceInEmptyBlock);
@@ -593,6 +665,7 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
IO.mapOptional("SpaceBeforeSquareBrackets",
Style.SpaceBeforeSquareBrackets);
+ IO.mapOptional("BitFieldColonSpacing", Style.BitFieldColonSpacing);
IO.mapOptional("Standard", Style.Standard);
IO.mapOptional("StatementMacros", Style.StatementMacros);
IO.mapOptional("TabWidth", Style.TabWidth);
@@ -757,6 +830,7 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
Expanded.BraceWrapping.BeforeCatch = true;
Expanded.BraceWrapping.BeforeElse = true;
+ Expanded.BraceWrapping.BeforeLambdaBody = true;
break;
case FormatStyle::BS_Whitesmiths:
Expanded.BraceWrapping.AfterCaseLabel = true;
@@ -812,10 +886,10 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align;
LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
LLVMStyle.AlignTrailingComments = true;
- LLVMStyle.AlignConsecutiveAssignments = false;
- LLVMStyle.AlignConsecutiveBitFields = false;
- LLVMStyle.AlignConsecutiveDeclarations = false;
- LLVMStyle.AlignConsecutiveMacros = false;
+ LLVMStyle.AlignConsecutiveAssignments = FormatStyle::ACS_None;
+ LLVMStyle.AlignConsecutiveBitFields = FormatStyle::ACS_None;
+ LLVMStyle.AlignConsecutiveDeclarations = FormatStyle::ACS_None;
+ LLVMStyle.AlignConsecutiveMacros = FormatStyle::ACS_None;
LLVMStyle.AllowAllArgumentsOnNextLine = true;
LLVMStyle.AllowAllConstructorInitializersOnNextLine = true;
LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
@@ -830,9 +904,11 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
LLVMStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;
+ LLVMStyle.AttributeMacros.push_back("__capability");
LLVMStyle.BinPackArguments = true;
LLVMStyle.BinPackParameters = true;
LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
+ LLVMStyle.BreakBeforeConceptDeclarations = true;
LLVMStyle.BreakBeforeTernaryOperators = true;
LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false,
@@ -867,21 +943,23 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.Cpp11BracedListStyle = true;
LLVMStyle.DeriveLineEnding = true;
LLVMStyle.DerivePointerAlignment = false;
+ LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock;
LLVMStyle.ExperimentalAutoDetectBinPacking = false;
LLVMStyle.FixNamespaceComments = true;
LLVMStyle.ForEachMacros.push_back("foreach");
LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
LLVMStyle.IncludeStyle.IncludeCategories = {
- {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0},
- {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0},
- {".*", 1, 0}};
+ {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false},
+ {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false},
+ {".*", 1, 0, false}};
LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;
LLVMStyle.IndentCaseLabels = false;
LLVMStyle.IndentCaseBlocks = false;
LLVMStyle.IndentGotoLabels = true;
LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;
+ LLVMStyle.IndentRequires = false;
LLVMStyle.IndentWrappedFunctionNames = false;
LLVMStyle.IndentWidth = 2;
LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None;
@@ -911,6 +989,8 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.SpaceAfterCStyleCast = false;
LLVMStyle.SpaceAfterLogicalNot = false;
LLVMStyle.SpaceAfterTemplateKeyword = true;
+ LLVMStyle.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default;
+ LLVMStyle.SpaceBeforeCaseColon = false;
LLVMStyle.SpaceBeforeCtorInitializerColon = true;
LLVMStyle.SpaceBeforeInheritanceColon = true;
LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
@@ -918,6 +998,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.SpaceBeforeAssignmentOperators = true;
LLVMStyle.SpaceBeforeCpp11BracedList = false;
LLVMStyle.SpaceBeforeSquareBrackets = false;
+ LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both;
LLVMStyle.SpacesInAngles = false;
LLVMStyle.SpacesInConditionalStatement = false;
@@ -929,15 +1010,20 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;
LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;
LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational;
+ LLVMStyle.PenaltyIndentedWhitespace = 0;
LLVMStyle.DisableFormat = false;
LLVMStyle.SortIncludes = true;
+ LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;
LLVMStyle.SortUsingDeclarations = true;
+ LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT");
LLVMStyle.StatementMacros.push_back("Q_UNUSED");
LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION");
LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE");
LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE");
LLVMStyle.WhitespaceSensitiveMacros.push_back("BOOST_PP_STRINGIZE");
+ LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME");
+ LLVMStyle.WhitespaceSensitiveMacros.push_back("CF_SWIFT_NAME");
// Defaults that differ when not C++.
if (Language == FormatStyle::LK_TableGen) {
@@ -966,10 +1052,10 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
GoogleStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
GoogleStyle.DerivePointerAlignment = true;
- GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0},
- {"^<.*\\.h>", 1, 0},
- {"^<.*", 2, 0},
- {".*", 3, 0}};
+ GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false},
+ {"^<.*\\.h>", 1, 0, false},
+ {"^<.*", 2, 0, false},
+ {".*", 3, 0, false}};
GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
GoogleStyle.IndentCaseLabels = true;
@@ -1275,20 +1361,23 @@ bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language,
return true;
}
-std::error_code parseConfiguration(StringRef Text, FormatStyle *Style) {
+std::error_code parseConfiguration(llvm::MemoryBufferRef Config,
+ FormatStyle *Style,
+ bool AllowUnknownOptions) {
assert(Style);
FormatStyle::LanguageKind Language = Style->Language;
assert(Language != FormatStyle::LK_None);
- if (Text.trim().empty())
+ if (Config.getBuffer().trim().empty())
return make_error_code(ParseError::Error);
Style->StyleSet.Clear();
std::vector<FormatStyle> Styles;
- llvm::yaml::Input Input(Text);
+ llvm::yaml::Input Input(Config);
// DocumentListTraits<vector<FormatStyle>> uses the context to get default
// values for the fields, keys for which are missing from the configuration.
// Mapping also uses the context to get the language to find the correct
// base style.
Input.setContext(Style);
+ Input.setAllowUnknownKeys(AllowUnknownOptions);
Input >> Styles;
if (Input.error())
return Input.error();
@@ -1562,9 +1651,9 @@ private:
continue;
FormatToken *Tok = AnnotatedLines[i]->First->Next;
while (Tok->Next) {
- if (Tok->PackingKind == PPK_BinPacked)
+ if (Tok->is(PPK_BinPacked))
HasBinPackedFunction = true;
- if (Tok->PackingKind == PPK_OnePerLine)
+ if (Tok->is(PPK_OnePerLine))
HasOnePerLineFunction = true;
Tok = Tok->Next;
@@ -1980,6 +2069,10 @@ private:
};
for (auto Line : AnnotatedLines) {
+ if (Line->First && (Line->First->TokenText.startswith("#") ||
+ Line->First->TokenText == "__pragma" ||
+ Line->First->TokenText == "_Pragma"))
+ continue;
for (const FormatToken *FormatTok = Line->First; FormatTok;
FormatTok = FormatTok->Next) {
if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&
@@ -2132,7 +2225,8 @@ static void sortCppIncludes(const FormatStyle &Style,
// Deduplicate #includes.
Indices.erase(std::unique(Indices.begin(), Indices.end(),
[&](unsigned LHSI, unsigned RHSI) {
- return Includes[LHSI].Text == Includes[RHSI].Text;
+ return Includes[LHSI].Text.trim() ==
+ Includes[RHSI].Text.trim();
}),
Indices.end());
@@ -2191,7 +2285,9 @@ tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
StringRef FileName,
tooling::Replacements &Replaces,
unsigned *Cursor) {
- unsigned Prev = 0;
+ unsigned Prev = llvm::StringSwitch<size_t>(Code)
+ .StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM
+ .Default(0);
unsigned SearchFrom = 0;
llvm::Regex IncludeRegex(CppIncludeRegexPattern);
SmallVector<StringRef, 4> Matches;
@@ -2227,7 +2323,8 @@ tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
Style.IncludeStyle.IncludeBlocks ==
tooling::IncludeStyle::IBS_Regroup);
- if (!FormattingOff && !Line.endswith("\\")) {
+ bool MergeWithNextLine = Trimmed.endswith("\\");
+ if (!FormattingOff && !MergeWithNextLine) {
if (IncludeRegex.match(Line, &Matches)) {
StringRef IncludeName = Matches[2];
int Category = Categories.getIncludePriority(
@@ -2243,12 +2340,17 @@ tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code,
Replaces, Cursor);
IncludesInBlock.clear();
- FirstIncludeBlock = false;
+ if (Trimmed.startswith("#pragma hdrstop")) // Precompiled headers.
+ FirstIncludeBlock = true;
+ else
+ FirstIncludeBlock = false;
}
- Prev = Pos + 1;
}
if (Pos == StringRef::npos || Pos + 1 == Code.size())
break;
+
+ if (!MergeWithNextLine)
+ Prev = Pos + 1;
SearchFrom = Pos + 1;
}
if (!IncludesInBlock.empty()) {
@@ -2297,12 +2399,16 @@ static void sortJavaImports(const FormatStyle &Style,
JavaImportGroups.push_back(
findJavaImportGroup(Style, Imports[i].Identifier));
}
+ bool StaticImportAfterNormalImport =
+ Style.SortJavaStaticImport == FormatStyle::SJSIO_After;
llvm::sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
// Negating IsStatic to push static imports above non-static imports.
- return std::make_tuple(!Imports[LHSI].IsStatic, JavaImportGroups[LHSI],
- Imports[LHSI].Identifier) <
- std::make_tuple(!Imports[RHSI].IsStatic, JavaImportGroups[RHSI],
- Imports[RHSI].Identifier);
+ return std::make_tuple(!Imports[LHSI].IsStatic ^
+ StaticImportAfterNormalImport,
+ JavaImportGroups[LHSI], Imports[LHSI].Identifier) <
+ std::make_tuple(!Imports[RHSI].IsStatic ^
+ StaticImportAfterNormalImport,
+ JavaImportGroups[RHSI], Imports[RHSI].Identifier);
});
// Deduplicate imports.
@@ -2726,6 +2832,7 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style) {
LangOpts.ObjC = 1;
LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally.
LangOpts.DeclSpecKeyword = 1; // To get __declspec.
+ LangOpts.C99 = 1; // To get kw_restrict for non-underscore-prefixed restrict.
return LangOpts;
}
@@ -2787,8 +2894,8 @@ const char *DefaultFallbackStyle = "LLVM";
llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
StringRef FallbackStyleName,
- StringRef Code,
- llvm::vfs::FileSystem *FS) {
+ StringRef Code, llvm::vfs::FileSystem *FS,
+ bool AllowUnknownOptions) {
if (!FS) {
FS = llvm::vfs::getRealFileSystem().get();
}
@@ -2800,7 +2907,9 @@ llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
if (StyleName.startswith("{")) {
// Parse YAML/JSON style from the command line.
- if (std::error_code ec = parseConfiguration(StyleName, &Style))
+ if (std::error_code ec = parseConfiguration(
+ llvm::MemoryBufferRef(StyleName, "<command-line>"), &Style,
+ AllowUnknownOptions))
return make_string_error("Error parsing -style: " + ec.message());
return Style;
}
@@ -2845,7 +2954,7 @@ llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
if (std::error_code EC = Text.getError())
return make_string_error(EC.message());
if (std::error_code ec =
- parseConfiguration(Text.get()->getBuffer(), &Style)) {
+ parseConfiguration(*Text.get(), &Style, AllowUnknownOptions)) {
if (ec == ParseError::Unsuitable) {
if (!UnsuitableConfigFiles.empty())
UnsuitableConfigFiles.append(", ");
diff --git a/contrib/llvm-project/clang/lib/Format/FormatInternal.h b/contrib/llvm-project/clang/lib/Format/FormatInternal.h
index 3aa616da23d8..9043ce32e9e3 100644
--- a/contrib/llvm-project/clang/lib/Format/FormatInternal.h
+++ b/contrib/llvm-project/clang/lib/Format/FormatInternal.h
@@ -16,7 +16,6 @@
#define LLVM_CLANG_LIB_FORMAT_FORMATINTERNAL_H
#include "BreakableToken.h"
-#include "clang/Tooling/Core/Lookup.h"
#include <utility>
namespace clang {
diff --git a/contrib/llvm-project/clang/lib/Format/FormatToken.cpp b/contrib/llvm-project/clang/lib/Format/FormatToken.cpp
index 7d792974cd57..8e4994f4c0d5 100644
--- a/contrib/llvm-project/clang/lib/Format/FormatToken.cpp
+++ b/contrib/llvm-project/clang/lib/Format/FormatToken.cpp
@@ -62,6 +62,7 @@ bool FormatToken::isSimpleTypeSpecifier() const {
case tok::kw_char32_t:
case tok::kw_typeof:
case tok::kw_decltype:
+ case tok::kw__Atomic:
return true;
default:
return false;
@@ -85,8 +86,8 @@ unsigned CommaSeparatedList::formatAfterToken(LineState &State,
const FormatToken *LBrace =
State.NextToken->Previous->getPreviousNonComment();
if (!LBrace || !LBrace->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
- LBrace->BlockKind == BK_Block || LBrace->getType() == TT_DictLiteral ||
- LBrace->Next->getType() == TT_DesignatedInitializerPeriod)
+ LBrace->is(BK_Block) || LBrace->is(TT_DictLiteral) ||
+ LBrace->Next->is(TT_DesignatedInitializerPeriod))
return 0;
// Calculate the number of code points we have to format this list. As the
diff --git a/contrib/llvm-project/clang/lib/Format/FormatToken.h b/contrib/llvm-project/clang/lib/Format/FormatToken.h
index b132a3e84da5..2f53b338379d 100644
--- a/contrib/llvm-project/clang/lib/Format/FormatToken.h
+++ b/contrib/llvm-project/clang/lib/Format/FormatToken.h
@@ -29,6 +29,7 @@ namespace format {
TYPE(ArrayInitializerLSquare) \
TYPE(ArraySubscriptLSquare) \
TYPE(AttributeColon) \
+ TYPE(AttributeMacro) \
TYPE(AttributeParen) \
TYPE(AttributeSquare) \
TYPE(BinaryOperator) \
@@ -39,6 +40,7 @@ namespace format {
TYPE(ConflictAlternative) \
TYPE(ConflictEnd) \
TYPE(ConflictStart) \
+ TYPE(ConstraintJunctions) \
TYPE(CtorInitializerColon) \
TYPE(CtorInitializerComma) \
TYPE(DesignatedInitializerLSquare) \
@@ -67,6 +69,9 @@ namespace format {
TYPE(JsTypeColon) \
TYPE(JsTypeOperator) \
TYPE(JsTypeOptionalQuestion) \
+ TYPE(JsAndAndEqual) \
+ TYPE(JsPipePipeEqual) \
+ TYPE(JsNullishCoalescingEqual) \
TYPE(LambdaArrow) \
TYPE(LambdaLBrace) \
TYPE(LambdaLSquare) \
@@ -91,6 +96,7 @@ namespace format {
TYPE(RegexLiteral) \
TYPE(SelectorName) \
TYPE(StartOfName) \
+ TYPE(StatementAttributeLikeMacro) \
TYPE(StatementMacro) \
TYPE(StructuredBindingLSquare) \
TYPE(TemplateCloser) \
@@ -100,6 +106,7 @@ namespace format {
TYPE(TrailingAnnotation) \
TYPE(TrailingReturnArrow) \
TYPE(TrailingUnaryOperator) \
+ TYPE(TypeDeclarationParen) \
TYPE(TypenameMacro) \
TYPE(UnaryOperator) \
TYPE(UntouchableMacroFunc) \
@@ -116,7 +123,7 @@ namespace format {
/// Determines the semantic type of a syntactic token, e.g. whether "<" is a
/// template opener or binary operator.
-enum TokenType {
+enum TokenType : uint8_t {
#define TYPE(X) TT_##X,
LIST_TOKEN_TYPES
#undef TYPE
@@ -134,80 +141,216 @@ enum ParameterPackingKind { PPK_BinPacked, PPK_OnePerLine, PPK_Inconclusive };
enum FormatDecision { FD_Unformatted, FD_Continue, FD_Break };
+/// Roles a token can take in a configured macro expansion.
+enum MacroRole {
+ /// The token was expanded from a macro argument when formatting the expanded
+ /// token sequence.
+ MR_ExpandedArg,
+ /// The token is part of a macro argument that was previously formatted as
+ /// expansion when formatting the unexpanded macro call.
+ MR_UnexpandedArg,
+ /// The token was expanded from a macro definition, and is not visible as part
+ /// of the macro call.
+ MR_Hidden,
+};
+
+struct FormatToken;
+
+/// Contains information on the token's role in a macro expansion.
+///
+/// Given the following definitions:
+/// A(X) = [ X ]
+/// B(X) = < X >
+/// C(X) = X
+///
+/// Consider the macro call:
+/// A({B(C(C(x)))}) -> [{<x>}]
+///
+/// In this case, the tokens of the unexpanded macro call will have the
+/// following relevant entries in their macro context (note that formatting
+/// the unexpanded macro call happens *after* formatting the expanded macro
+/// call):
+/// A( { B( C( C(x) ) ) } )
+/// Role: NN U NN NN NNUN N N U N (N=None, U=UnexpandedArg)
+///
+/// [ { < x > } ]
+/// Role: H E H E H E H (H=Hidden, E=ExpandedArg)
+/// ExpandedFrom[0]: A A A A A A A
+/// ExpandedFrom[1]: B B B
+/// ExpandedFrom[2]: C
+/// ExpandedFrom[3]: C
+/// StartOfExpansion: 1 0 1 2 0 0 0
+/// EndOfExpansion: 0 0 0 2 1 0 1
+struct MacroExpansion {
+ MacroExpansion(MacroRole Role) : Role(Role) {}
+
+ /// The token's role in the macro expansion.
+ /// When formatting an expanded macro, all tokens that are part of macro
+ /// arguments will be MR_ExpandedArg, while all tokens that are not visible in
+ /// the macro call will be MR_Hidden.
+ /// When formatting an unexpanded macro call, all tokens that are part of
+ /// macro arguments will be MR_UnexpandedArg.
+ MacroRole Role;
+
+ /// The stack of macro call identifier tokens this token was expanded from.
+ llvm::SmallVector<FormatToken *, 1> ExpandedFrom;
+
+ /// The number of expansions of which this macro is the first entry.
+ unsigned StartOfExpansion = 0;
+
+ /// The number of currently open expansions in \c ExpandedFrom this macro is
+ /// the last token in.
+ unsigned EndOfExpansion = 0;
+};
+
class TokenRole;
class AnnotatedLine;
/// A wrapper around a \c Token storing information about the
/// whitespace characters preceding it.
struct FormatToken {
- FormatToken() {}
+ FormatToken()
+ : HasUnescapedNewline(false), IsMultiline(false), IsFirst(false),
+ MustBreakBefore(false), IsUnterminatedLiteral(false),
+ CanBreakBefore(false), ClosesTemplateDeclaration(false),
+ StartsBinaryExpression(false), EndsBinaryExpression(false),
+ PartOfMultiVariableDeclStmt(false), ContinuesLineCommentSection(false),
+ Finalized(false), BlockKind(BK_Unknown), Decision(FD_Unformatted),
+ PackingKind(PPK_Inconclusive), Type(TT_Unknown) {}
/// The \c Token.
Token Tok;
- /// The number of newlines immediately before the \c Token.
+ /// The raw text of the token.
///
- /// This can be used to determine what the user wrote in the original code
- /// and thereby e.g. leave an empty line between two function definitions.
- unsigned NewlinesBefore = 0;
+ /// Contains the raw token text without leading whitespace and without leading
+ /// escaped newlines.
+ StringRef TokenText;
- /// Whether there is at least one unescaped newline before the \c
- /// Token.
- bool HasUnescapedNewline = false;
+ /// A token can have a special role that can carry extra information
+ /// about the token's formatting.
+ /// FIXME: Make FormatToken for parsing and AnnotatedToken two different
+ /// classes and make this a unique_ptr in the AnnotatedToken class.
+ std::shared_ptr<TokenRole> Role;
/// The range of the whitespace immediately preceding the \c Token.
SourceRange WhitespaceRange;
- /// The offset just past the last '\n' in this token's leading
- /// whitespace (relative to \c WhiteSpaceStart). 0 if there is no '\n'.
- unsigned LastNewlineOffset = 0;
-
- /// The width of the non-whitespace parts of the token (or its first
- /// line for multi-line tokens) in columns.
- /// We need this to correctly measure number of columns a token spans.
- unsigned ColumnWidth = 0;
-
- /// Contains the width in columns of the last line of a multi-line
- /// token.
- unsigned LastLineColumnWidth = 0;
+ /// Whether there is at least one unescaped newline before the \c
+ /// Token.
+ unsigned HasUnescapedNewline : 1;
/// Whether the token text contains newlines (escaped or not).
- bool IsMultiline = false;
+ unsigned IsMultiline : 1;
/// Indicates that this is the first token of the file.
- bool IsFirst = false;
+ unsigned IsFirst : 1;
/// Whether there must be a line break before this token.
///
/// This happens for example when a preprocessor directive ended directly
/// before the token.
- bool MustBreakBefore = false;
+ unsigned MustBreakBefore : 1;
- /// The raw text of the token.
+ /// Set to \c true if this token is an unterminated literal.
+ unsigned IsUnterminatedLiteral : 1;
+
+ /// \c true if it is allowed to break before this token.
+ unsigned CanBreakBefore : 1;
+
+ /// \c true if this is the ">" of "template<..>".
+ unsigned ClosesTemplateDeclaration : 1;
+
+ /// \c true if this token starts a binary expression, i.e. has at least
+ /// one fake l_paren with a precedence greater than prec::Unknown.
+ unsigned StartsBinaryExpression : 1;
+ /// \c true if this token ends a binary expression.
+ unsigned EndsBinaryExpression : 1;
+
+ /// Is this token part of a \c DeclStmt defining multiple variables?
///
- /// Contains the raw token text without leading whitespace and without leading
- /// escaped newlines.
- StringRef TokenText;
+ /// Only set if \c Type == \c TT_StartOfName.
+ unsigned PartOfMultiVariableDeclStmt : 1;
- /// Set to \c true if this token is an unterminated literal.
- bool IsUnterminatedLiteral = 0;
+ /// Does this line comment continue a line comment section?
+ ///
+ /// Only set to true if \c Type == \c TT_LineComment.
+ unsigned ContinuesLineCommentSection : 1;
+
+ /// If \c true, this token has been fully formatted (indented and
+ /// potentially re-formatted inside), and we do not allow further formatting
+ /// changes.
+ unsigned Finalized : 1;
+private:
/// Contains the kind of block if this token is a brace.
- BraceBlockKind BlockKind = BK_Unknown;
+ unsigned BlockKind : 2;
+
+public:
+ BraceBlockKind getBlockKind() const {
+ return static_cast<BraceBlockKind>(BlockKind);
+ }
+ void setBlockKind(BraceBlockKind BBK) {
+ BlockKind = BBK;
+ assert(getBlockKind() == BBK && "BraceBlockKind overflow!");
+ }
+private:
+ /// Stores the formatting decision for the token once it was made.
+ unsigned Decision : 2;
+
+public:
+ FormatDecision getDecision() const {
+ return static_cast<FormatDecision>(Decision);
+ }
+ void setDecision(FormatDecision D) {
+ Decision = D;
+ assert(getDecision() == D && "FormatDecision overflow!");
+ }
+
+private:
+ /// If this is an opening parenthesis, how are the parameters packed?
+ unsigned PackingKind : 2;
+
+public:
+ ParameterPackingKind getPackingKind() const {
+ return static_cast<ParameterPackingKind>(PackingKind);
+ }
+ void setPackingKind(ParameterPackingKind K) {
+ PackingKind = K;
+ assert(getPackingKind() == K && "ParameterPackingKind overflow!");
+ }
+
+private:
+ TokenType Type;
+
+public:
/// Returns the token's type, e.g. whether "<" is a template opener or
/// binary operator.
TokenType getType() const { return Type; }
void setType(TokenType T) { Type = T; }
- /// The number of spaces that should be inserted before this token.
- unsigned SpacesRequiredBefore = 0;
+ /// The number of newlines immediately before the \c Token.
+ ///
+ /// This can be used to determine what the user wrote in the original code
+ /// and thereby e.g. leave an empty line between two function definitions.
+ unsigned NewlinesBefore = 0;
- /// \c true if it is allowed to break before this token.
- bool CanBreakBefore = false;
+ /// The offset just past the last '\n' in this token's leading
+ /// whitespace (relative to \c WhiteSpaceStart). 0 if there is no '\n'.
+ unsigned LastNewlineOffset = 0;
- /// \c true if this is the ">" of "template<..>".
- bool ClosesTemplateDeclaration = false;
+ /// The width of the non-whitespace parts of the token (or its first
+ /// line for multi-line tokens) in columns.
+ /// We need this to correctly measure number of columns a token spans.
+ unsigned ColumnWidth = 0;
+
+ /// Contains the width in columns of the last line of a multi-line
+ /// token.
+ unsigned LastLineColumnWidth = 0;
+
+ /// The number of spaces that should be inserted before this token.
+ unsigned SpacesRequiredBefore = 0;
/// Number of parameters, if this is "(", "[" or "<".
unsigned ParameterCount = 0;
@@ -220,13 +363,6 @@ struct FormatToken {
/// the surrounding bracket.
tok::TokenKind ParentBracket = tok::unknown;
- /// A token can have a special role that can carry extra information
- /// about the token's formatting.
- std::unique_ptr<TokenRole> Role;
-
- /// If this is an opening parenthesis, how are the parameters packed?
- ParameterPackingKind PackingKind = PPK_Inconclusive;
-
/// The total length of the unwrapped line up to and including this
/// token.
unsigned TotalLength = 0;
@@ -280,12 +416,6 @@ struct FormatToken {
/// Insert this many fake ) after this token for correct indentation.
unsigned FakeRParens = 0;
- /// \c true if this token starts a binary expression, i.e. has at least
- /// one fake l_paren with a precedence greater than prec::Unknown.
- bool StartsBinaryExpression = false;
- /// \c true if this token ends a binary expression.
- bool EndsBinaryExpression = false;
-
/// If this is an operator (or "."/"->") in a sequence of operators
/// with the same precedence, contains the 0-based operator index.
unsigned OperatorIndex = 0;
@@ -294,16 +424,6 @@ struct FormatToken {
/// with the same precedence, points to the next operator.
FormatToken *NextOperator = nullptr;
- /// Is this token part of a \c DeclStmt defining multiple variables?
- ///
- /// Only set if \c Type == \c TT_StartOfName.
- bool PartOfMultiVariableDeclStmt = false;
-
- /// Does this line comment continue a line comment section?
- ///
- /// Only set to true if \c Type == \c TT_LineComment.
- bool ContinuesLineCommentSection = false;
-
/// If this is a bracket, this points to the matching one.
FormatToken *MatchingParen = nullptr;
@@ -317,16 +437,12 @@ struct FormatToken {
/// in it.
SmallVector<AnnotatedLine *, 1> Children;
- /// Stores the formatting decision for the token once it was made.
- FormatDecision Decision = FD_Unformatted;
-
- /// If \c true, this token has been fully formatted (indented and
- /// potentially re-formatted inside), and we do not allow further formatting
- /// changes.
- bool Finalized = false;
+ // Contains all attributes related to how this token takes part
+ // in a configured macro expansion.
+ llvm::Optional<MacroExpansion> MacroCtx;
bool is(tok::TokenKind Kind) const { return Tok.is(Kind); }
- bool is(TokenType TT) const { return Type == TT; }
+ bool is(TokenType TT) const { return getType() == TT; }
bool is(const IdentifierInfo *II) const {
return II && II == Tok.getIdentifierInfo();
}
@@ -334,6 +450,9 @@ struct FormatToken {
return Tok.getIdentifierInfo() &&
Tok.getIdentifierInfo()->getPPKeywordID() == Kind;
}
+ bool is(BraceBlockKind BBK) const { return getBlockKind() == BBK; }
+ bool is(ParameterPackingKind PPK) const { return getPackingKind() == PPK; }
+
template <typename A, typename B> bool isOneOf(A K1, B K2) const {
return is(K1) || is(K2);
}
@@ -349,7 +468,7 @@ struct FormatToken {
}
bool closesScopeAfterBlock() const {
- if (BlockKind == BK_Block)
+ if (getBlockKind() == BK_Block)
return true;
if (closesScope())
return Previous->closesScopeAfterBlock();
@@ -385,6 +504,13 @@ struct FormatToken {
(!ColonRequired || (Next && Next->is(tok::colon)));
}
+ bool canBePointerOrReferenceQualifier() const {
+ return isOneOf(tok::kw_const, tok::kw_restrict, tok::kw_volatile,
+ tok::kw___attribute, tok::kw__Nonnull, tok::kw__Nullable,
+ tok::kw__Null_unspecified, tok::kw___ptr32, tok::kw___ptr64,
+ TT_AttributeMacro);
+ }
+
/// Determine whether the token is a simple-type-specifier.
bool isSimpleTypeSpecifier() const;
@@ -463,7 +589,10 @@ struct FormatToken {
case tok::kw_decltype:
case tok::kw_noexcept:
case tok::kw_static_assert:
+ case tok::kw__Atomic:
case tok::kw___attribute:
+ case tok::kw___underlying_type:
+ case tok::kw_requires:
return true;
default:
return false;
@@ -519,13 +648,13 @@ struct FormatToken {
/// list that should be indented with a block indent.
bool opensBlockOrBlockTypeList(const FormatStyle &Style) const {
// C# Does not indent object initialisers as continuations.
- if (is(tok::l_brace) && BlockKind == BK_BracedInit && Style.isCSharp())
+ if (is(tok::l_brace) && getBlockKind() == BK_BracedInit && Style.isCSharp())
return true;
if (is(TT_TemplateString) && opensScope())
return true;
return is(TT_ArrayInitializerLSquare) || is(TT_ProtoExtensionLSquare) ||
(is(tok::l_brace) &&
- (BlockKind == BK_Block || is(TT_DictLiteral) ||
+ (getBlockKind() == BK_Block || is(TT_DictLiteral) ||
(!Style.Cpp11BracedListStyle && NestingLevel == 0))) ||
(is(tok::less) && (Style.Language == FormatStyle::LK_Proto ||
Style.Language == FormatStyle::LK_TextProto));
@@ -566,10 +695,12 @@ struct FormatToken {
: nullptr;
}
+ void copyFrom(const FormatToken &Tok) { *this = Tok; }
+
private:
- // Disallow copying.
+ // Only allow copying via the explicit copyFrom method.
FormatToken(const FormatToken &) = delete;
- void operator=(const FormatToken &) = delete;
+ FormatToken &operator=(const FormatToken &) = default;
template <typename A, typename... Ts>
bool startsSequenceInternal(A K1, Ts... Tokens) const {
@@ -596,8 +727,6 @@ private:
return Previous->endsSequenceInternal(K1, Tokens...);
return is(K1) && Previous && Previous->endsSequenceInternal(Tokens...);
}
-
- TokenType Type = TT_Unknown;
};
class ContinuationIndenter;
diff --git a/contrib/llvm-project/clang/lib/Format/FormatTokenLexer.cpp b/contrib/llvm-project/clang/lib/Format/FormatTokenLexer.cpp
index 1fd153d1112e..e9b096370dbb 100644
--- a/contrib/llvm-project/clang/lib/Format/FormatTokenLexer.cpp
+++ b/contrib/llvm-project/clang/lib/Format/FormatTokenLexer.cpp
@@ -33,12 +33,14 @@ FormatTokenLexer::FormatTokenLexer(
Encoding(Encoding), Allocator(Allocator), FirstInLineIndex(0),
FormattingDisabled(false), MacroBlockBeginRegex(Style.MacroBlockBegin),
MacroBlockEndRegex(Style.MacroBlockEnd) {
- Lex.reset(new Lexer(ID, SourceMgr.getBuffer(ID), SourceMgr,
+ Lex.reset(new Lexer(ID, SourceMgr.getBufferOrFake(ID), SourceMgr,
getFormattingLangOpts(Style)));
Lex->SetKeepWhitespaceMode(true);
for (const std::string &ForEachMacro : Style.ForEachMacros)
Macros.insert({&IdentTable.get(ForEachMacro), TT_ForEachMacro});
+ for (const std::string &AttributeMacro : Style.AttributeMacros)
+ Macros.insert({&IdentTable.get(AttributeMacro), TT_AttributeMacro});
for (const std::string &StatementMacro : Style.StatementMacros)
Macros.insert({&IdentTable.get(StatementMacro), TT_StatementMacro});
for (const std::string &TypenameMacro : Style.TypenameMacros)
@@ -50,6 +52,10 @@ FormatTokenLexer::FormatTokenLexer(
Macros.insert(
{&IdentTable.get(WhitespaceSensitiveMacro), TT_UntouchableMacroFunc});
}
+ for (const std::string &StatementAttributeLikeMacro :
+ Style.StatementAttributeLikeMacros)
+ Macros.insert({&IdentTable.get(StatementAttributeLikeMacro),
+ TT_StatementAttributeLikeMacro});
}
ArrayRef<FormatToken *> FormatTokenLexer::lex() {
@@ -119,6 +125,10 @@ void FormatTokenLexer::tryMergePreviousTokens() {
tok::period};
static const tok::TokenKind JSNullishOperator[] = {tok::question,
tok::question};
+ static const tok::TokenKind JSNullishEqual[] = {tok::question,
+ tok::question, tok::equal};
+ static const tok::TokenKind JSPipePipeEqual[] = {tok::pipepipe, tok::equal};
+ static const tok::TokenKind JSAndAndEqual[] = {tok::ampamp, tok::equal};
// FIXME: Investigate what token type gives the correct operator priority.
if (tryMergeTokens(JSIdentity, TT_BinaryOperator))
@@ -146,6 +156,13 @@ void FormatTokenLexer::tryMergePreviousTokens() {
Tokens.back()->Tok.setKind(tok::period);
return;
}
+ if (tryMergeTokens(JSAndAndEqual, TT_JsAndAndEqual) ||
+ tryMergeTokens(JSPipePipeEqual, TT_JsPipePipeEqual) ||
+ tryMergeTokens(JSNullishEqual, TT_JsNullishCoalescingEqual)) {
+ // Treat like the "=" assignment operator.
+ Tokens.back()->Tok.setKind(tok::equal);
+ return;
+ }
if (tryMergeJSPrivateIdentifier())
return;
}
@@ -399,7 +416,7 @@ bool FormatTokenLexer::tryTransformTryUsageForC() {
if (!Try->is(tok::kw_try))
return false;
auto &Next = *(Tokens.end() - 1);
- if (Next->isOneOf(tok::l_brace, tok::colon))
+ if (Next->isOneOf(tok::l_brace, tok::colon, tok::hash, tok::comment))
return false;
if (Tokens.size() > 2) {
@@ -761,7 +778,7 @@ bool FormatTokenLexer::tryMergeConflictMarkers() {
unsigned FirstInLineOffset;
std::tie(ID, FirstInLineOffset) = SourceMgr.getDecomposedLoc(
Tokens[FirstInLineIndex]->getStartOfNonWhitespace());
- StringRef Buffer = SourceMgr.getBuffer(ID)->getBuffer();
+ StringRef Buffer = SourceMgr.getBufferOrFake(ID).getBuffer();
// Calculate the offset of the start of the current line.
auto LineOffset = Buffer.rfind('\n', FirstInLineOffset);
if (LineOffset == StringRef::npos) {
diff --git a/contrib/llvm-project/clang/lib/Format/MacroExpander.cpp b/contrib/llvm-project/clang/lib/Format/MacroExpander.cpp
new file mode 100644
index 000000000000..e50c80446963
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Format/MacroExpander.cpp
@@ -0,0 +1,224 @@
+//===--- MacroExpander.cpp - Format C++ code --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the implementation of MacroExpander, which handles macro
+/// configuration and expansion while formatting.
+///
+//===----------------------------------------------------------------------===//
+
+#include "Macros.h"
+
+#include "Encoding.h"
+#include "FormatToken.h"
+#include "FormatTokenLexer.h"
+#include "clang/Basic/TokenKinds.h"
+#include "clang/Format/Format.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderSearchOptions.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace clang {
+namespace format {
+
+struct MacroExpander::Definition {
+ StringRef Name;
+ SmallVector<FormatToken *, 8> Params;
+ SmallVector<FormatToken *, 8> Body;
+
+ // Map from each argument's name to its position in the argument list.
+ // With "M(x, y) x + y":
+ // x -> 0
+ // y -> 1
+ llvm::StringMap<size_t> ArgMap;
+
+ bool ObjectLike = true;
+};
+
+class MacroExpander::DefinitionParser {
+public:
+ DefinitionParser(ArrayRef<FormatToken *> Tokens) : Tokens(Tokens) {
+ assert(!Tokens.empty());
+ Current = Tokens[0];
+ }
+
+ // Parse the token stream and return the corresonding Definition object.
+ // Returns an empty definition object with a null-Name on error.
+ MacroExpander::Definition parse() {
+ if (!Current->is(tok::identifier))
+ return {};
+ Def.Name = Current->TokenText;
+ nextToken();
+ if (Current->is(tok::l_paren)) {
+ Def.ObjectLike = false;
+ if (!parseParams())
+ return {};
+ }
+ if (!parseExpansion())
+ return {};
+
+ return Def;
+ }
+
+private:
+ bool parseParams() {
+ assert(Current->is(tok::l_paren));
+ nextToken();
+ while (Current->is(tok::identifier)) {
+ Def.Params.push_back(Current);
+ Def.ArgMap[Def.Params.back()->TokenText] = Def.Params.size() - 1;
+ nextToken();
+ if (Current->isNot(tok::comma))
+ break;
+ nextToken();
+ }
+ if (Current->isNot(tok::r_paren))
+ return false;
+ nextToken();
+ return true;
+ }
+
+ bool parseExpansion() {
+ if (!Current->isOneOf(tok::equal, tok::eof))
+ return false;
+ if (Current->is(tok::equal))
+ nextToken();
+ parseTail();
+ return true;
+ }
+
+ void parseTail() {
+ while (Current->isNot(tok::eof)) {
+ Def.Body.push_back(Current);
+ nextToken();
+ }
+ Def.Body.push_back(Current);
+ }
+
+ void nextToken() {
+ if (Pos + 1 < Tokens.size())
+ ++Pos;
+ Current = Tokens[Pos];
+ Current->Finalized = true;
+ }
+
+ size_t Pos = 0;
+ FormatToken *Current = nullptr;
+ Definition Def;
+ ArrayRef<FormatToken *> Tokens;
+};
+
+MacroExpander::MacroExpander(
+ const std::vector<std::string> &Macros, clang::SourceManager &SourceMgr,
+ const FormatStyle &Style,
+ llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator,
+ IdentifierTable &IdentTable)
+ : SourceMgr(SourceMgr), Style(Style), Allocator(Allocator),
+ IdentTable(IdentTable) {
+ for (const std::string &Macro : Macros) {
+ parseDefinition(Macro);
+ }
+}
+
+MacroExpander::~MacroExpander() = default;
+
+void MacroExpander::parseDefinition(const std::string &Macro) {
+ Buffers.push_back(
+ llvm::MemoryBuffer::getMemBufferCopy(Macro, "<scratch space>"));
+ clang::FileID FID = SourceMgr.createFileID(Buffers.back()->getMemBufferRef());
+ FormatTokenLexer Lex(SourceMgr, FID, 0, Style, encoding::Encoding_UTF8,
+ Allocator, IdentTable);
+ const auto Tokens = Lex.lex();
+ if (!Tokens.empty()) {
+ DefinitionParser Parser(Tokens);
+ auto Definition = Parser.parse();
+ Definitions[Definition.Name] = std::move(Definition);
+ }
+}
+
+bool MacroExpander::defined(llvm::StringRef Name) const {
+ return Definitions.find(Name) != Definitions.end();
+}
+
+bool MacroExpander::objectLike(llvm::StringRef Name) const {
+ return Definitions.find(Name)->second.ObjectLike;
+}
+
+llvm::SmallVector<FormatToken *, 8> MacroExpander::expand(FormatToken *ID,
+ ArgsList Args) const {
+ assert(defined(ID->TokenText));
+ SmallVector<FormatToken *, 8> Result;
+ const Definition &Def = Definitions.find(ID->TokenText)->second;
+
+ // Expand each argument at most once.
+ llvm::StringSet<> ExpandedArgs;
+
+ // Adds the given token to Result.
+ auto pushToken = [&](FormatToken *Tok) {
+ Tok->MacroCtx->ExpandedFrom.push_back(ID);
+ Result.push_back(Tok);
+ };
+
+ // If Tok references a parameter, adds the corresponding argument to Result.
+ // Returns false if Tok does not reference a parameter.
+ auto expandArgument = [&](FormatToken *Tok) -> bool {
+ // If the current token references a parameter, expand the corresponding
+ // argument.
+ if (!Tok->is(tok::identifier) || ExpandedArgs.contains(Tok->TokenText))
+ return false;
+ ExpandedArgs.insert(Tok->TokenText);
+ auto I = Def.ArgMap.find(Tok->TokenText);
+ if (I == Def.ArgMap.end())
+ return false;
+ // If there are fewer arguments than referenced parameters, treat the
+ // parameter as empty.
+ // FIXME: Potentially fully abort the expansion instead.
+ if (I->getValue() >= Args.size())
+ return true;
+ for (FormatToken *Arg : Args[I->getValue()]) {
+ // A token can be part of a macro argument at multiple levels.
+ // For example, with "ID(x) x":
+ // in ID(ID(x)), 'x' is expanded first as argument to the inner
+ // ID, then again as argument to the outer ID. We keep the macro
+ // role the token had from the inner expansion.
+ if (!Arg->MacroCtx)
+ Arg->MacroCtx = MacroExpansion(MR_ExpandedArg);
+ pushToken(Arg);
+ }
+ return true;
+ };
+
+ // Expand the definition into Result.
+ for (FormatToken *Tok : Def.Body) {
+ if (expandArgument(Tok))
+ continue;
+ // Create a copy of the tokens from the macro body, i.e. were not provided
+ // by user code.
+ FormatToken *New = new (Allocator.Allocate()) FormatToken;
+ New->copyFrom(*Tok);
+ assert(!New->MacroCtx);
+ // Tokens that are not part of the user code are not formatted.
+ New->MacroCtx = MacroExpansion(MR_Hidden);
+ pushToken(New);
+ }
+ assert(Result.size() >= 1 && Result.back()->is(tok::eof));
+ if (Result.size() > 1) {
+ ++Result[0]->MacroCtx->StartOfExpansion;
+ ++Result[Result.size() - 2]->MacroCtx->EndOfExpansion;
+ }
+ return Result;
+}
+
+} // namespace format
+} // namespace clang
diff --git a/contrib/llvm-project/clang/lib/Format/Macros.h b/contrib/llvm-project/clang/lib/Format/Macros.h
new file mode 100644
index 000000000000..591ef8b5be3c
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Format/Macros.h
@@ -0,0 +1,141 @@
+//===--- MacroExpander.h - Format C++ code ----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the main building blocks of macro support in
+/// clang-format.
+///
+/// In order to not violate the requirement that clang-format can format files
+/// in isolation, clang-format's macro support uses expansions users provide
+/// as part of clang-format's style configuration.
+///
+/// Macro definitions are of the form "MACRO(p1, p2)=p1 + p2", but only support
+/// one level of expansion (\see MacroExpander for a full description of what
+/// is supported).
+///
+/// As part of parsing, clang-format uses the MacroExpander to expand the
+/// spelled token streams into expanded token streams when it encounters a
+/// macro call. The UnwrappedLineParser continues to parse UnwrappedLines
+/// from the expanded token stream.
+/// After the expanded unwrapped lines are parsed, the MacroUnexpander matches
+/// the spelled token stream into unwrapped lines that best resemble the
+/// structure of the expanded unwrapped lines.
+///
+/// When formatting, clang-format formats the expanded unwrapped lines first,
+/// determining the token types. Next, it formats the spelled unwrapped lines,
+/// keeping the token types fixed, while allowing other formatting decisions
+/// to change.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_LIB_FORMAT_MACROS_H
+#define CLANG_LIB_FORMAT_MACROS_H
+
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "Encoding.h"
+#include "FormatToken.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+class MemoryBuffer;
+} // namespace llvm
+
+namespace clang {
+class IdentifierTable;
+class SourceManager;
+
+namespace format {
+struct FormatStyle;
+
+/// Takes a set of macro definitions as strings and allows expanding calls to
+/// those macros.
+///
+/// For example:
+/// Definition: A(x, y)=x + y
+/// Call : A(int a = 1, 2)
+/// Expansion : int a = 1 + 2
+///
+/// Expansion does not check arity of the definition.
+/// If fewer arguments than expected are provided, the remaining parameters
+/// are considered empty:
+/// Call : A(a)
+/// Expansion: a +
+/// If more arguments than expected are provided, they will be discarded.
+///
+/// The expander does not support:
+/// - recursive expansion
+/// - stringification
+/// - concatenation
+/// - variadic macros
+///
+/// Furthermore, only a single expansion of each macro argument is supported,
+/// so that we cannot get conflicting formatting decisions from different
+/// expansions.
+/// Definition: A(x)=x+x
+/// Call : A(id)
+/// Expansion : id+x
+///
+class MacroExpander {
+public:
+ using ArgsList = llvm::ArrayRef<llvm::SmallVector<FormatToken *, 8>>;
+
+ /// Construct a macro expander from a set of macro definitions.
+ /// Macro definitions must be encoded as UTF-8.
+ ///
+ /// Each entry in \p Macros must conform to the following simple
+ /// macro-definition language:
+ /// <definition> ::= <id> <expansion> | <id> "(" <params> ")" <expansion>
+ /// <params> ::= <id-list> | ""
+ /// <id-list> ::= <id> | <id> "," <params>
+ /// <expansion> ::= "=" <tail> | <eof>
+ /// <tail> ::= <tok> <tail> | <eof>
+ ///
+ /// Macros that cannot be parsed will be silently discarded.
+ ///
+ MacroExpander(const std::vector<std::string> &Macros,
+ clang::SourceManager &SourceMgr, const FormatStyle &Style,
+ llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator,
+ IdentifierTable &IdentTable);
+ ~MacroExpander();
+
+ /// Returns whether a macro \p Name is defined.
+ bool defined(llvm::StringRef Name) const;
+
+ /// Returns whether the macro has no arguments and should not consume
+ /// subsequent parentheses.
+ bool objectLike(llvm::StringRef Name) const;
+
+ /// Returns the expanded stream of format tokens for \p ID, where
+ /// each element in \p Args is a positional argument to the macro call.
+ llvm::SmallVector<FormatToken *, 8> expand(FormatToken *ID,
+ ArgsList Args) const;
+
+private:
+ struct Definition;
+ class DefinitionParser;
+
+ void parseDefinition(const std::string &Macro);
+
+ clang::SourceManager &SourceMgr;
+ const FormatStyle &Style;
+ llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator;
+ IdentifierTable &IdentTable;
+ std::vector<std::unique_ptr<llvm::MemoryBuffer>> Buffers;
+ llvm::StringMap<Definition> Definitions;
+};
+
+} // namespace format
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm-project/clang/lib/Format/TokenAnnotator.cpp b/contrib/llvm-project/clang/lib/Format/TokenAnnotator.cpp
index 914c05f72aec..82d6cfed308d 100644..100755
--- a/contrib/llvm-project/clang/lib/Format/TokenAnnotator.cpp
+++ b/contrib/llvm-project/clang/lib/Format/TokenAnnotator.cpp
@@ -27,7 +27,7 @@ namespace format {
namespace {
/// Returns \c true if the token can be used as an identifier in
-/// an Objective-C \c @selector, \c false otherwise.
+/// an Objective-C \c \@selector, \c false otherwise.
///
/// Because getFormattingLangOpts() always lexes source code as
/// Objective-C++, C++ keywords like \c new and \c delete are
@@ -198,6 +198,8 @@ private:
if (!CurrentToken)
return false;
FormatToken *Left = CurrentToken->Previous;
+ assert(Left && "Unknown previous token");
+ FormatToken *PrevNonComment = Left->getPreviousNonComment();
Left->ParentBracket = Contexts.back().ContextKind;
ScopedContextCreator ContextCreator(*this, tok::l_paren, 1);
@@ -229,9 +231,8 @@ private:
// export type X = (...);
Contexts.back().IsExpression = false;
} else if (Left->Previous &&
- (Left->Previous->isOneOf(tok::kw_static_assert, tok::kw_decltype,
- tok::kw_while, tok::l_paren,
- tok::comma) ||
+ (Left->Previous->isOneOf(tok::kw_static_assert, tok::kw_while,
+ tok::l_paren, tok::comma) ||
Left->Previous->isIf() ||
Left->Previous->is(TT_BinaryOperator))) {
// static_assert, if and while usually contain expressions.
@@ -255,8 +256,6 @@ private:
} else if (Contexts[Contexts.size() - 2].CaretFound) {
// This is the parameter list of an ObjC block.
Contexts.back().IsExpression = false;
- } else if (Left->Previous && Left->Previous->is(tok::kw___attribute)) {
- Left->setType(TT_AttributeParen);
} else if (Left->Previous && Left->Previous->is(TT_ForEachMacro)) {
// The first argument to a foreach macro is a declaration.
Contexts.back().IsForEachMacro = true;
@@ -270,6 +269,21 @@ private:
Contexts.back().IsExpression = !IsForOrCatch;
}
+ // Infer the role of the l_paren based on the previous token if we haven't
+ // detected one one yet.
+ if (PrevNonComment && Left->is(TT_Unknown)) {
+ if (PrevNonComment->is(tok::kw___attribute)) {
+ Left->setType(TT_AttributeParen);
+ } else if (PrevNonComment->isOneOf(TT_TypenameMacro, tok::kw_decltype,
+ tok::kw_typeof, tok::kw__Atomic,
+ tok::kw___underlying_type)) {
+ Left->setType(TT_TypeDeclarationParen);
+ // decltype() and typeof() usually contain expressions.
+ if (PrevNonComment->isOneOf(tok::kw_decltype, tok::kw_typeof))
+ Contexts.back().IsExpression = true;
+ }
+ }
+
if (StartsObjCMethodExpr) {
Contexts.back().ColonIsObjCMethodExpr = true;
Left->setType(TT_ObjCMethodExpr);
@@ -348,6 +362,8 @@ private:
if (Left->is(TT_AttributeParen))
CurrentToken->setType(TT_AttributeParen);
+ if (Left->is(TT_TypeDeclarationParen))
+ CurrentToken->setType(TT_TypeDeclarationParen);
if (Left->Previous && Left->Previous->is(TT_JavaAnnotation))
CurrentToken->setType(TT_JavaAnnotation);
if (Left->Previous && Left->Previous->is(TT_LeadingJavaAnnotation))
@@ -356,11 +372,11 @@ private:
CurrentToken->setType(TT_AttributeSquare);
if (!HasMultipleLines)
- Left->PackingKind = PPK_Inconclusive;
+ Left->setPackingKind(PPK_Inconclusive);
else if (HasMultipleParametersOnALine)
- Left->PackingKind = PPK_BinPacked;
+ Left->setPackingKind(PPK_BinPacked);
else
- Left->PackingKind = PPK_OnePerLine;
+ Left->setPackingKind(PPK_OnePerLine);
next();
return true;
@@ -717,7 +733,7 @@ private:
ScopedContextCreator ContextCreator(*this, tok::l_brace, 1);
Contexts.back().ColonIsDictLiteral = true;
- if (Left->BlockKind == BK_BracedInit)
+ if (Left->is(BK_BracedInit))
Contexts.back().IsExpression = true;
if (Style.Language == FormatStyle::LK_JavaScript && Left->Previous &&
Left->Previous->is(TT_JsTypeColon))
@@ -764,7 +780,7 @@ private:
// For ObjC methods, the number of parameters is calculated differently as
// method declarations have a different structure (the parameters are not
// inside a bracket scope).
- if (Current->is(tok::l_brace) && Current->BlockKind == BK_Block)
+ if (Current->is(tok::l_brace) && Current->is(BK_Block))
++Left->BlockParameterCount;
if (Current->is(tok::comma)) {
++Left->ParameterCount;
@@ -880,7 +896,8 @@ private:
} else if (CurrentToken && CurrentToken->is(tok::numeric_constant)) {
Tok->setType(TT_BitFieldColon);
} else if (Contexts.size() == 1 &&
- !Line.First->isOneOf(tok::kw_enum, tok::kw_case)) {
+ !Line.First->isOneOf(tok::kw_enum, tok::kw_case,
+ tok::kw_default)) {
FormatToken *Prev = Tok->getPreviousNonComment();
if (Prev->isOneOf(tok::r_paren, tok::kw_noexcept))
Tok->setType(TT_CtorInitializerColon);
@@ -953,9 +970,9 @@ private:
return false;
if (Line.MustBeDeclaration && Contexts.size() == 1 &&
!Contexts.back().IsExpression && !Line.startsWith(TT_ObjCProperty) &&
- (!Tok->Previous ||
- !Tok->Previous->isOneOf(tok::kw_decltype, tok::kw___attribute,
- TT_LeadingJavaAnnotation)))
+ !Tok->is(TT_TypeDeclarationParen) &&
+ (!Tok->Previous || !Tok->Previous->isOneOf(tok::kw___attribute,
+ TT_LeadingJavaAnnotation)))
Line.MightBeFunctionDecl = true;
break;
case tok::l_square:
@@ -1346,11 +1363,13 @@ private:
// Reset token type in case we have already looked at it and then
// recovered from an error (e.g. failure to find the matching >).
if (!CurrentToken->isOneOf(
- TT_LambdaLSquare, TT_LambdaLBrace, TT_ForEachMacro,
- TT_TypenameMacro, TT_FunctionLBrace, TT_ImplicitStringLiteral,
- TT_InlineASMBrace, TT_JsFatArrow, TT_LambdaArrow, TT_NamespaceMacro,
- TT_OverloadedOperator, TT_RegexLiteral, TT_TemplateString,
- TT_ObjCStringLiteral, TT_UntouchableMacroFunc))
+ TT_LambdaLSquare, TT_LambdaLBrace, TT_AttributeMacro,
+ TT_ForEachMacro, TT_TypenameMacro, TT_FunctionLBrace,
+ TT_ImplicitStringLiteral, TT_InlineASMBrace, TT_JsFatArrow,
+ TT_LambdaArrow, TT_NamespaceMacro, TT_OverloadedOperator,
+ TT_RegexLiteral, TT_TemplateString, TT_ObjCStringLiteral,
+ TT_UntouchableMacroFunc, TT_ConstraintJunctions,
+ TT_StatementAttributeLikeMacro))
CurrentToken->setType(TT_Unknown);
CurrentToken->Role.reset();
CurrentToken->MatchingParen = nullptr;
@@ -1604,7 +1623,11 @@ private:
!Current.Previous->is(tok::kw_operator)) {
// not auto operator->() -> xxx;
Current.setType(TT_TrailingReturnArrow);
-
+ } else if (Current.is(tok::arrow) && Current.Previous &&
+ Current.Previous->is(tok::r_brace)) {
+ // Concept implicit conversion contraint needs to be treated like
+ // a trailing return type ... } -> <type>.
+ Current.setType(TT_TrailingReturnArrow);
} else if (isDeductionGuide(Current)) {
// Deduction guides trailing arrow " A(...) -> A<T>;".
Current.setType(TT_TrailingReturnArrow);
@@ -1705,8 +1728,8 @@ private:
// colon after this, this is the only place which annotates the identifier
// as a selector.)
Current.setType(TT_SelectorName);
- } else if (Current.isOneOf(tok::identifier, tok::kw_const,
- tok::kw_noexcept) &&
+ } else if (Current.isOneOf(tok::identifier, tok::kw_const, tok::kw_noexcept,
+ tok::kw_requires) &&
Current.Previous &&
!Current.Previous->isOneOf(tok::equal, tok::at) &&
Line.MightBeFunctionDecl && Contexts.size() == 1) {
@@ -1766,9 +1789,8 @@ private:
PreviousNotConst->MatchingParen->Previous->isNot(tok::period) &&
PreviousNotConst->MatchingParen->Previous->isNot(tok::kw_template);
- if (PreviousNotConst->is(tok::r_paren) && PreviousNotConst->MatchingParen &&
- PreviousNotConst->MatchingParen->Previous &&
- PreviousNotConst->MatchingParen->Previous->is(tok::kw_decltype))
+ if (PreviousNotConst->is(tok::r_paren) &&
+ PreviousNotConst->is(TT_TypeDeclarationParen))
return true;
return (!IsPPKeyword &&
@@ -1823,8 +1845,8 @@ private:
// Functions which end with decorations like volatile, noexcept are unlikely
// to be casts.
if (Tok.Next->isOneOf(tok::kw_noexcept, tok::kw_volatile, tok::kw_const,
- tok::kw_throw, tok::arrow, Keywords.kw_override,
- Keywords.kw_final) ||
+ tok::kw_requires, tok::kw_throw, tok::arrow,
+ Keywords.kw_override, Keywords.kw_final) ||
isCpp11AttributeSpecifier(*Tok.Next))
return false;
@@ -1840,10 +1862,38 @@ private:
return true;
// Heuristically try to determine whether the parentheses contain a type.
+ auto IsQualifiedPointerOrReference = [](FormatToken *T) {
+ // This is used to handle cases such as x = (foo *const)&y;
+ assert(!T->isSimpleTypeSpecifier() && "Should have already been checked");
+ // Strip trailing qualifiers such as const or volatile when checking
+ // whether the parens could be a cast to a pointer/reference type.
+ while (T) {
+ if (T->is(TT_AttributeParen)) {
+ // Handle `x = (foo *__attribute__((foo)))&v;`:
+ if (T->MatchingParen && T->MatchingParen->Previous &&
+ T->MatchingParen->Previous->is(tok::kw___attribute)) {
+ T = T->MatchingParen->Previous->Previous;
+ continue;
+ }
+ } else if (T->is(TT_AttributeSquare)) {
+ // Handle `x = (foo *[[clang::foo]])&v;`:
+ if (T->MatchingParen && T->MatchingParen->Previous) {
+ T = T->MatchingParen->Previous;
+ continue;
+ }
+ } else if (T->canBePointerOrReferenceQualifier()) {
+ T = T->Previous;
+ continue;
+ }
+ break;
+ }
+ return T && T->is(TT_PointerOrReference);
+ };
bool ParensAreType =
!Tok.Previous ||
- Tok.Previous->isOneOf(TT_PointerOrReference, TT_TemplateCloser) ||
- Tok.Previous->isSimpleTypeSpecifier();
+ Tok.Previous->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) ||
+ Tok.Previous->isSimpleTypeSpecifier() ||
+ IsQualifiedPointerOrReference(Tok.Previous);
bool ParensCouldEndDecl =
Tok.Next->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater);
if (ParensAreType && !ParensCouldEndDecl)
@@ -1867,6 +1917,13 @@ private:
if (Tok.Next->isOneOf(tok::identifier, tok::kw_this))
return true;
+ // Look for a cast `( x ) (`.
+ if (Tok.Next->is(tok::l_paren) && Tok.Previous && Tok.Previous->Previous) {
+ if (Tok.Previous->is(tok::identifier) &&
+ Tok.Previous->Previous->is(tok::l_paren))
+ return true;
+ }
+
if (!Tok.Next->Next)
return false;
@@ -1903,18 +1960,22 @@ private:
const FormatToken *NextToken = Tok.getNextNonComment();
if (!NextToken ||
- NextToken->isOneOf(tok::arrow, tok::equal, tok::kw_const,
- tok::kw_noexcept) ||
+ NextToken->isOneOf(tok::arrow, tok::equal, tok::kw_noexcept) ||
+ NextToken->canBePointerOrReferenceQualifier() ||
(NextToken->is(tok::l_brace) && !NextToken->getNextNonComment()))
return TT_PointerOrReference;
if (PrevToken->is(tok::coloncolon))
return TT_PointerOrReference;
+ if (PrevToken->is(tok::r_paren) && PrevToken->is(TT_TypeDeclarationParen))
+ return TT_PointerOrReference;
+
if (PrevToken->isOneOf(tok::l_paren, tok::l_square, tok::l_brace,
tok::comma, tok::semi, tok::kw_return, tok::colon,
- tok::equal, tok::kw_delete, tok::kw_sizeof,
- tok::kw_throw) ||
+ tok::kw_co_return, tok::kw_co_await,
+ tok::kw_co_yield, tok::equal, tok::kw_delete,
+ tok::kw_sizeof, tok::kw_throw) ||
PrevToken->isOneOf(TT_BinaryOperator, TT_ConditionalExpr,
TT_UnaryOperator, TT_CastRParen))
return TT_UnaryOperator;
@@ -1926,15 +1987,6 @@ private:
if (NextToken->isOneOf(tok::comma, tok::semi))
return TT_PointerOrReference;
- if (PrevToken->is(tok::r_paren) && PrevToken->MatchingParen) {
- FormatToken *TokenBeforeMatchingParen =
- PrevToken->MatchingParen->getPreviousNonComment();
- if (TokenBeforeMatchingParen &&
- TokenBeforeMatchingParen->isOneOf(tok::kw_typeof, tok::kw_decltype,
- TT_TypenameMacro))
- return TT_PointerOrReference;
- }
-
if (PrevToken->Tok.isLiteral() ||
PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::kw_true,
tok::kw_false, tok::r_brace) ||
@@ -2380,6 +2432,8 @@ static bool isFunctionDeclarationName(const FormatToken &Current,
return true;
for (const FormatToken *Tok = Next->Next; Tok && Tok != Next->MatchingParen;
Tok = Tok->Next) {
+ if (Tok->is(TT_TypeDeclarationParen))
+ return true;
if (Tok->isOneOf(tok::l_paren, TT_TemplateOpener) && Tok->MatchingParen) {
Tok = Tok->MatchingParen;
continue;
@@ -2433,7 +2487,7 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
if (isFunctionDeclarationName(*Current, Line))
Current->setType(TT_FunctionDeclarationName);
if (Current->is(TT_LineComment)) {
- if (Current->Previous->BlockKind == BK_BracedInit &&
+ if (Current->Previous->is(BK_BracedInit) &&
Current->Previous->opensScope())
Current->SpacesRequiredBefore =
(Style.Cpp11BracedListStyle && !Style.SpacesInParentheses) ? 0 : 1;
@@ -2694,7 +2748,11 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Left.is(TT_TemplateOpener))
return 100;
if (Left.opensScope()) {
- if (Style.AlignAfterOpenBracket == FormatStyle::BAS_DontAlign)
+ // If we aren't aligning after opening parens/braces we can always break
+ // here unless the style does not want us to place all arguments on the
+ // next line.
+ if (Style.AlignAfterOpenBracket == FormatStyle::BAS_DontAlign &&
+ (Left.ParameterCount <= 1 || Style.AllowAllArgumentsOnNextLine))
return 0;
if (Left.is(tok::l_brace) && !Style.Cpp11BracedListStyle)
return 19;
@@ -2761,8 +2819,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (Left.isOneOf(tok::hashhash, tok::hash))
return Right.is(tok::hash);
if ((Left.is(tok::l_paren) && Right.is(tok::r_paren)) ||
- (Left.is(tok::l_brace) && Left.BlockKind != BK_Block &&
- Right.is(tok::r_brace) && Right.BlockKind != BK_Block))
+ (Left.is(tok::l_brace) && Left.isNot(BK_Block) &&
+ Right.is(tok::r_brace) && Right.isNot(BK_Block)))
return Style.SpaceInEmptyParentheses;
if (Style.SpacesInConditionalStatement) {
if (Left.is(tok::l_paren) && Left.Previous &&
@@ -2773,6 +2831,14 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
isKeywordWithCondition(*Right.MatchingParen->Previous))
return true;
}
+
+ // requires ( or requires(
+ if (Right.is(tok::l_paren) && Left.is(tok::kw_requires))
+ return spaceRequiredBeforeParens(Right);
+ // requires clause Concept1<T> && Concept2<T>
+ if (Left.is(TT_ConstraintJunctions) && Right.is(tok::identifier))
+ return true;
+
if (Left.is(tok::l_paren) || Right.is(tok::r_paren))
return (Right.is(TT_CastRParen) ||
(Left.MatchingParen && Left.MatchingParen->is(TT_CastRParen)))
@@ -2821,11 +2887,16 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return true;
FormatToken *TokenBeforeMatchingParen =
Left.MatchingParen->getPreviousNonComment();
- if (!TokenBeforeMatchingParen ||
- !TokenBeforeMatchingParen->isOneOf(tok::kw_typeof, tok::kw_decltype,
- TT_TypenameMacro))
+ if (!TokenBeforeMatchingParen || !Left.is(TT_TypeDeclarationParen))
return true;
}
+ // Add a space if the previous token is a pointer qualifer or the closing
+ // parenthesis of __attribute__(()) expression and the style requires spaces
+ // after pointer qualifiers.
+ if ((Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_After ||
+ Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both) &&
+ (Left.is(TT_AttributeParen) || Left.canBePointerOrReferenceQualifier()))
+ return true;
return (Left.Tok.isLiteral() ||
(!Left.isOneOf(TT_PointerOrReference, tok::l_paren) &&
(Style.PointerAlignment != FormatStyle::PAS_Left ||
@@ -2838,11 +2909,17 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
(Style.PointerAlignment != FormatStyle::PAS_Right &&
!Line.IsMultiVariableDeclStmt)))
return true;
- if (Left.is(TT_PointerOrReference))
+ if (Left.is(TT_PointerOrReference)) {
+ // Add a space if the next token is a pointer qualifer and the style
+ // requires spaces before pointer qualifiers.
+ if ((Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Before ||
+ Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both) &&
+ Right.canBePointerOrReferenceQualifier())
+ return true;
return Right.Tok.isLiteral() || Right.is(TT_BlockComment) ||
(Right.isOneOf(Keywords.kw_override, Keywords.kw_final) &&
!Right.is(TT_StartOfName)) ||
- (Right.is(tok::l_brace) && Right.BlockKind == BK_Block) ||
+ (Right.is(tok::l_brace) && Right.is(BK_Block)) ||
(!Right.isOneOf(TT_PointerOrReference, TT_ArraySubscriptLSquare,
tok::l_paren) &&
(Style.PointerAlignment != FormatStyle::PAS_Right &&
@@ -2850,6 +2927,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
Left.Previous &&
!Left.Previous->isOneOf(tok::l_paren, tok::coloncolon,
tok::l_square));
+ }
// Ensure right pointer alignement with ellipsis e.g. int *...P
if (Left.is(tok::ellipsis) && Left.Previous &&
Left.Previous->isOneOf(tok::star, tok::amp, tok::ampamp))
@@ -2927,9 +3005,9 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return false;
if (Left.is(tok::l_brace) && Right.is(tok::r_brace))
return !Left.Children.empty(); // No spaces in "{}".
- if ((Left.is(tok::l_brace) && Left.BlockKind != BK_Block) ||
+ if ((Left.is(tok::l_brace) && Left.isNot(BK_Block)) ||
(Right.is(tok::r_brace) && Right.MatchingParen &&
- Right.MatchingParen->BlockKind != BK_Block))
+ Right.MatchingParen->isNot(BK_Block)))
return Style.Cpp11BracedListStyle ? Style.SpacesInParentheses : true;
if (Left.is(TT_BlockComment))
// No whitespace in x(/*foo=*/1), except for JavaScript.
@@ -2973,7 +3051,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
tok::r_paren) ||
Left.isSimpleTypeSpecifier()) &&
Right.is(tok::l_brace) && Right.getNextNonComment() &&
- Right.BlockKind != BK_Block)
+ Right.isNot(BK_Block))
return false;
if (Left.is(tok::period) || Right.is(tok::period))
return false;
@@ -3015,7 +3093,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
if (Style.isCpp()) {
if (Left.is(tok::kw_operator))
return Right.is(tok::coloncolon);
- if (Right.is(tok::l_brace) && Right.BlockKind == BK_BracedInit &&
+ if (Right.is(tok::l_brace) && Right.is(BK_BracedInit) &&
!Left.opensScope() && Style.SpaceBeforeCpp11BracedList)
return true;
} else if (Style.Language == FormatStyle::LK_Proto ||
@@ -3121,6 +3199,16 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
Keywords.kw_lock))
return Style.SpaceBeforeParens == FormatStyle::SBPO_ControlStatements ||
spaceRequiredBeforeParens(Right);
+
+ // space between method modifier and opening parenthesis of a tuple return
+ // type
+ if (Left.isOneOf(tok::kw_public, tok::kw_private, tok::kw_protected,
+ tok::kw_virtual, tok::kw_extern, tok::kw_static,
+ Keywords.kw_internal, Keywords.kw_abstract,
+ Keywords.kw_sealed, Keywords.kw_override,
+ Keywords.kw_async, Keywords.kw_unsafe) &&
+ Right.is(tok::l_paren))
+ return true;
} else if (Style.Language == FormatStyle::LK_JavaScript) {
if (Left.is(TT_JsFatArrow))
return true;
@@ -3257,9 +3345,13 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
if (Right.is(TT_RangeBasedForLoopColon) &&
!Style.SpaceBeforeRangeBasedForLoopColon)
return false;
+ if (Left.is(TT_BitFieldColon))
+ return Style.BitFieldColonSpacing == FormatStyle::BFCS_Both ||
+ Style.BitFieldColonSpacing == FormatStyle::BFCS_After;
if (Right.is(tok::colon)) {
- if (Line.First->isOneOf(tok::kw_case, tok::kw_default) ||
- !Right.getNextNonComment() || Right.getNextNonComment()->is(tok::semi))
+ if (Line.First->isOneOf(tok::kw_default, tok::kw_case))
+ return Style.SpaceBeforeCaseColon;
+ if (!Right.getNextNonComment() || Right.getNextNonComment()->is(tok::semi))
return false;
if (Right.is(TT_ObjCMethodExpr))
return false;
@@ -3273,6 +3365,9 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return false;
if (Right.is(TT_CSharpNamedArgumentColon))
return false;
+ if (Right.is(TT_BitFieldColon))
+ return Style.BitFieldColonSpacing == FormatStyle::BFCS_Both ||
+ Style.BitFieldColonSpacing == FormatStyle::BFCS_Before;
return true;
}
if (Left.is(TT_UnaryOperator)) {
@@ -3362,7 +3457,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
// 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 &&
+ return Tok.is(tok::l_brace) && Tok.is(BK_Block) &&
!Tok.isOneOf(TT_ObjCBlockLBrace, TT_LambdaLBrace, TT_DictLiteral);
}
@@ -3398,7 +3493,7 @@ static bool isOneChildWithoutMustBreakBefore(const FormatToken &Tok) {
return true;
}
static bool isAllmanLambdaBrace(const FormatToken &Tok) {
- return (Tok.is(tok::l_brace) && Tok.BlockKind == BK_Block &&
+ return (Tok.is(tok::l_brace) && Tok.is(BK_Block) &&
!Tok.isOneOf(TT_ObjCBlockLBrace, TT_DictLiteral));
}
@@ -3498,7 +3593,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
if ((Left.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
(Style.Language == FormatStyle::LK_JavaScript &&
Left.is(tok::l_paren))) &&
- Left.BlockKind != BK_Block && Left.MatchingParen)
+ Left.isNot(BK_Block) && Left.MatchingParen)
BeforeClosingBrace = Left.MatchingParen->Previous;
else if (Right.MatchingParen &&
(Right.MatchingParen->isOneOf(tok::l_brace,
@@ -3512,8 +3607,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
}
if (Right.is(tok::comment))
- return Left.BlockKind != BK_BracedInit &&
- Left.isNot(TT_CtorInitializerColon) &&
+ return Left.isNot(BK_BracedInit) && Left.isNot(TT_CtorInitializerColon) &&
(Right.NewlinesBefore > 0 && Right.HasUnescapedNewline);
if (Left.isTrailingComment())
return true;
@@ -3523,11 +3617,17 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
Right.Previous->is(tok::string_literal) &&
Right.Next->is(tok::string_literal))
return true;
+ // Can break after template<> declaration
if (Right.Previous->ClosesTemplateDeclaration &&
Right.Previous->MatchingParen &&
- Right.Previous->MatchingParen->NestingLevel == 0 &&
- Style.AlwaysBreakTemplateDeclarations == FormatStyle::BTDS_Yes)
- return true;
+ Right.Previous->MatchingParen->NestingLevel == 0) {
+ // Put concepts on the next line e.g.
+ // template<typename T>
+ // concept ...
+ if (Right.is(tok::kw_concept))
+ return Style.BreakBeforeConceptDeclarations;
+ return (Style.AlwaysBreakTemplateDeclarations == FormatStyle::BTDS_Yes);
+ }
if (Right.is(TT_CtorInitializerComma) &&
Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma &&
!Style.ConstructorInitializerAllOnOneLineOrOnePerLine)
@@ -3822,7 +3922,7 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
// The first comment in a braced lists is always interpreted as belonging to
// the first list element. Otherwise, it should be placed outside of the
// list.
- return Left.BlockKind == BK_BracedInit ||
+ return Left.is(BK_BracedInit) ||
(Left.is(TT_CtorInitializerColon) &&
Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon);
if (Left.is(tok::question) && Right.is(tok::colon))
@@ -3906,7 +4006,8 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
if (Left.is(tok::equal) && Right.is(tok::l_brace) &&
!Style.Cpp11BracedListStyle)
return false;
- if (Left.is(tok::l_paren) && Left.is(TT_AttributeParen))
+ if (Left.is(tok::l_paren) &&
+ Left.isOneOf(TT_AttributeParen, TT_TypeDeclarationParen))
return false;
if (Left.is(tok::l_paren) && Left.Previous &&
(Left.Previous->isOneOf(TT_BinaryOperator, TT_CastRParen)))
@@ -3923,7 +4024,7 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
// We only break before r_brace if there was a corresponding break before
// the l_brace, which is tracked by BreakBeforeClosingBrace.
if (Right.is(tok::r_brace))
- return Right.MatchingParen && Right.MatchingParen->BlockKind == BK_Block;
+ return Right.MatchingParen && Right.MatchingParen->is(BK_Block);
// Allow breaking after a trailing annotation, e.g. after a method
// declaration.
@@ -4008,9 +4109,9 @@ void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) {
<< " T=" << getTokenTypeName(Tok->getType())
<< " S=" << Tok->SpacesRequiredBefore
<< " F=" << Tok->Finalized << " B=" << Tok->BlockParameterCount
- << " BK=" << Tok->BlockKind << " P=" << Tok->SplitPenalty
+ << " BK=" << Tok->getBlockKind() << " P=" << Tok->SplitPenalty
<< " Name=" << Tok->Tok.getName() << " L=" << Tok->TotalLength
- << " PPK=" << Tok->PackingKind << " FakeLParens=";
+ << " PPK=" << Tok->getPackingKind() << " FakeLParens=";
for (unsigned i = 0, e = Tok->FakeLParens.size(); i != e; ++i)
llvm::errs() << Tok->FakeLParens[i] << "/";
llvm::errs() << " FakeRParens=" << Tok->FakeRParens;
diff --git a/contrib/llvm-project/clang/lib/Format/UnwrappedLineFormatter.cpp b/contrib/llvm-project/clang/lib/Format/UnwrappedLineFormatter.cpp
index 22f27a668dcc..7d197310e65b 100644
--- a/contrib/llvm-project/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/contrib/llvm-project/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -248,6 +248,11 @@ private:
return !Style.BraceWrapping.SplitEmptyRecord && EmptyBlock
? tryMergeSimpleBlock(I, E, Limit)
: 0;
+
+ if (Tok && Tok->is(tok::kw_template) &&
+ Style.BraceWrapping.SplitEmptyRecord && EmptyBlock) {
+ return 0;
+ }
}
// FIXME: TheLine->Level != 0 might or might not be the right check to do.
@@ -309,7 +314,8 @@ private:
// Try to merge a control statement block with left brace wrapped
if (I[1]->First->is(tok::l_brace) &&
(TheLine->First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for,
- tok::kw_switch, tok::kw_try, tok::kw_do) ||
+ tok::kw_switch, tok::kw_try, tok::kw_do,
+ TT_ForEachMacro) ||
(TheLine->First->is(tok::r_brace) && TheLine->First->Next &&
TheLine->First->Next->isOneOf(tok::kw_else, tok::kw_catch))) &&
Style.BraceWrapping.AfterControlStatement ==
@@ -354,6 +360,30 @@ private:
if (TheLine->First->is(tok::l_brace) && I != AnnotatedLines.begin() &&
I[-1]->First->isOneOf(tok::kw_case, tok::kw_default))
return 0;
+
+ // Don't merge an empty template class or struct if SplitEmptyRecords
+ // is defined.
+ if (Style.BraceWrapping.SplitEmptyRecord &&
+ TheLine->Last->is(tok::l_brace) && I != AnnotatedLines.begin() &&
+ I[-1]->Last) {
+ const FormatToken *Previous = I[-1]->Last;
+ if (Previous) {
+ if (Previous->is(tok::comment))
+ Previous = Previous->getPreviousNonComment();
+ if (Previous) {
+ if (Previous->is(tok::greater) && !I[-1]->InPPDirective)
+ return 0;
+ if (Previous->is(tok::identifier)) {
+ const FormatToken *PreviousPrevious =
+ Previous->getPreviousNonComment();
+ if (PreviousPrevious &&
+ PreviousPrevious->isOneOf(tok::kw_class, tok::kw_struct))
+ return 0;
+ }
+ }
+ }
+ }
+
// Try to merge a block with left brace wrapped that wasn't yet covered
if (TheLine->Last->is(tok::l_brace)) {
return !Style.BraceWrapping.AfterFunction ||
@@ -606,7 +636,7 @@ private:
if (I[1]->Last->is(TT_LineComment))
return 0;
do {
- if (Tok->is(tok::l_brace) && Tok->BlockKind != BK_BracedInit)
+ if (Tok->is(tok::l_brace) && Tok->isNot(BK_BracedInit))
return 0;
Tok = Tok->Next;
} while (Tok);
@@ -767,8 +797,8 @@ protected:
unsigned &Penalty) {
const FormatToken *LBrace = State.NextToken->getPreviousNonComment();
FormatToken &Previous = *State.NextToken->Previous;
- if (!LBrace || LBrace->isNot(tok::l_brace) ||
- LBrace->BlockKind != BK_Block || Previous.Children.size() == 0)
+ if (!LBrace || LBrace->isNot(tok::l_brace) || LBrace->isNot(BK_Block) ||
+ Previous.Children.size() == 0)
// The previous token does not open a block. Nothing to do. We don't
// assert so that we can simply call this function for all tokens.
return true;
@@ -979,7 +1009,7 @@ private:
// State already examined with lower penalty.
continue;
- FormatDecision LastFormat = Node->State.NextToken->Decision;
+ FormatDecision LastFormat = Node->State.NextToken->getDecision();
if (LastFormat == FD_Unformatted || LastFormat == FD_Continue)
addNextStateToQueue(Penalty, Node, /*NewLine=*/false, &Count, &Queue);
if (LastFormat == FD_Unformatted || LastFormat == FD_Break)
@@ -1215,10 +1245,33 @@ void UnwrappedLineFormatter::formatFirstToken(
!startsExternCBlock(*PreviousLine))
Newlines = 1;
- // Insert extra new line before access specifiers.
- if (PreviousLine && PreviousLine->Last->isOneOf(tok::semi, tok::r_brace) &&
- RootToken.isAccessSpecifier() && RootToken.NewlinesBefore == 1)
- ++Newlines;
+ // Insert or remove empty line before access specifiers.
+ if (PreviousLine && RootToken.isAccessSpecifier()) {
+ switch (Style.EmptyLineBeforeAccessModifier) {
+ case FormatStyle::ELBAMS_Never:
+ if (RootToken.NewlinesBefore > 1)
+ Newlines = 1;
+ break;
+ case FormatStyle::ELBAMS_Leave:
+ Newlines = std::max(RootToken.NewlinesBefore, 1u);
+ break;
+ case FormatStyle::ELBAMS_LogicalBlock:
+ if (PreviousLine->Last->isOneOf(tok::semi, tok::r_brace) &&
+ RootToken.NewlinesBefore <= 1)
+ Newlines = 2;
+ break;
+ case FormatStyle::ELBAMS_Always: {
+ const FormatToken *previousToken;
+ if (PreviousLine->Last->is(tok::comment))
+ previousToken = PreviousLine->Last->getPreviousNonComment();
+ else
+ previousToken = PreviousLine->Last;
+ if ((!previousToken || !previousToken->is(tok::l_brace)) &&
+ RootToken.NewlinesBefore <= 1)
+ Newlines = 2;
+ } break;
+ }
+ }
// Remove empty lines after access specifiers.
if (PreviousLine && PreviousLine->First->isAccessSpecifier() &&
@@ -1228,13 +1281,6 @@ void UnwrappedLineFormatter::formatFirstToken(
if (Newlines)
Indent = NewlineIndent;
- // If in Whitemsmiths mode, indent start and end of blocks
- if (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) {
- if (RootToken.isOneOf(tok::l_brace, tok::r_brace, tok::kw_case,
- tok::kw_default))
- Indent += Style.IndentWidth;
- }
-
// Preprocessor directives get indented before the hash only if specified
if (Style.IndentPPDirectives != FormatStyle::PPDIS_BeforeHash &&
(Line.Type == LT_PreprocessorDirective ||
diff --git a/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp b/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp
index ea8a41cfba82..bec18bd5d8df 100644
--- a/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp
@@ -472,19 +472,19 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
// individual members in a type member list, which would normally
// trigger BK_Block. In both cases, this must be parsed as an inline
// braced init.
- Tok->BlockKind = BK_BracedInit;
+ Tok->setBlockKind(BK_BracedInit);
else if (PrevTok->is(tok::r_paren))
// `) { }` can only occur in function or method declarations in JS.
- Tok->BlockKind = BK_Block;
+ Tok->setBlockKind(BK_Block);
} else {
- Tok->BlockKind = BK_Unknown;
+ Tok->setBlockKind(BK_Unknown);
}
LBraceStack.push_back(Tok);
break;
case tok::r_brace:
if (LBraceStack.empty())
break;
- if (LBraceStack.back()->BlockKind == BK_Unknown) {
+ if (LBraceStack.back()->is(BK_Unknown)) {
bool ProbablyBracedList = false;
if (Style.Language == FormatStyle::LK_Proto) {
ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square);
@@ -524,11 +524,11 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
}
}
if (ProbablyBracedList) {
- Tok->BlockKind = BK_BracedInit;
- LBraceStack.back()->BlockKind = BK_BracedInit;
+ Tok->setBlockKind(BK_BracedInit);
+ LBraceStack.back()->setBlockKind(BK_BracedInit);
} else {
- Tok->BlockKind = BK_Block;
- LBraceStack.back()->BlockKind = BK_Block;
+ Tok->setBlockKind(BK_Block);
+ LBraceStack.back()->setBlockKind(BK_Block);
}
}
LBraceStack.pop_back();
@@ -545,8 +545,8 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
case tok::kw_switch:
case tok::kw_try:
case tok::kw___try:
- if (!LBraceStack.empty() && LBraceStack.back()->BlockKind == BK_Unknown)
- LBraceStack.back()->BlockKind = BK_Block;
+ if (!LBraceStack.empty() && LBraceStack.back()->is(BK_Unknown))
+ LBraceStack.back()->setBlockKind(BK_Block);
break;
default:
break;
@@ -557,8 +557,8 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
// Assume other blocks for all unclosed opening braces.
for (unsigned i = 0, e = LBraceStack.size(); i != e; ++i) {
- if (LBraceStack[i]->BlockKind == BK_Unknown)
- LBraceStack[i]->BlockKind = BK_Block;
+ if (LBraceStack[i]->is(BK_Unknown))
+ LBraceStack[i]->setBlockKind(BK_Block);
}
FormatTok = Tokens->setPosition(StoredPosition);
@@ -579,17 +579,23 @@ size_t UnwrappedLineParser::computePPHash() const {
return h;
}
-void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel,
- bool MunchSemi) {
+void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, unsigned AddLevels,
+ bool MunchSemi,
+ bool UnindentWhitesmithsBraces) {
assert(FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) &&
"'{' or macro block token expected");
const bool MacroBlock = FormatTok->is(TT_MacroBlockBegin);
- FormatTok->BlockKind = BK_Block;
+ FormatTok->setBlockKind(BK_Block);
+
+ // For Whitesmiths mode, jump to the next level prior to skipping over the
+ // braces.
+ if (AddLevels > 0 && Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths)
+ ++Line->Level;
size_t PPStartHash = computePPHash();
unsigned InitialLevel = Line->Level;
- nextToken(/*LevelDifference=*/AddLevel ? 1 : 0);
+ nextToken(/*LevelDifference=*/AddLevels);
if (MacroBlock && FormatTok->is(tok::l_paren))
parseParens();
@@ -602,10 +608,16 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel,
? (UnwrappedLine::kInvalidIndex)
: (CurrentLines->size() - 1 - NbPreprocessorDirectives);
+ // Whitesmiths is weird here. The brace needs to be indented for the namespace
+ // block, but the block itself may not be indented depending on the style
+ // settings. This allows the format to back up one level in those cases.
+ if (UnindentWhitesmithsBraces)
+ --Line->Level;
+
ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
MustBeDeclaration);
- if (AddLevel)
- ++Line->Level;
+ if (AddLevels > 0u && Style.BreakBeforeBraces != FormatStyle::BS_Whitesmiths)
+ Line->Level += AddLevels;
parseLevel(/*HasOpeningBrace=*/true);
if (eof())
@@ -614,21 +626,30 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel,
if (MacroBlock ? !FormatTok->is(TT_MacroBlockEnd)
: !FormatTok->is(tok::r_brace)) {
Line->Level = InitialLevel;
- FormatTok->BlockKind = BK_Block;
+ FormatTok->setBlockKind(BK_Block);
return;
}
size_t PPEndHash = computePPHash();
// Munch the closing brace.
- nextToken(/*LevelDifference=*/AddLevel ? -1 : 0);
+ nextToken(/*LevelDifference=*/-AddLevels);
if (MacroBlock && FormatTok->is(tok::l_paren))
parseParens();
+ if (FormatTok->is(tok::arrow)) {
+ // Following the } we can find a trailing return type arrow
+ // as part of an implicit conversion constraint.
+ nextToken();
+ parseStructuralElement();
+ }
+
if (MunchSemi && FormatTok->Tok.is(tok::semi))
nextToken();
+
Line->Level = InitialLevel;
+ FormatTok->setBlockKind(BK_Block);
if (PPStartHash == PPEndHash) {
Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
@@ -690,7 +711,7 @@ static bool ShouldBreakBeforeBrace(const FormatStyle &Style,
}
void UnwrappedLineParser::parseChildBlock() {
- FormatTok->BlockKind = BK_Block;
+ FormatTok->setBlockKind(BK_Block);
nextToken();
{
bool SkipIndent = (Style.Language == FormatStyle::LK_JavaScript &&
@@ -1262,6 +1283,12 @@ void UnwrappedLineParser::parseStructuralElement() {
break;
}
break;
+ case tok::kw_concept:
+ parseConcept();
+ break;
+ case tok::kw_requires:
+ parseRequires();
+ break;
case tok::kw_enum:
// Ignore if this is part of "template <enum ...".
if (Previous && Previous->is(tok::less)) {
@@ -1476,7 +1503,7 @@ void UnwrappedLineParser::parseStructuralElement() {
// C# needs this change to ensure that array initialisers and object
// initialisers are indented the same way.
if (Style.isCSharp())
- FormatTok->BlockKind = BK_BracedInit;
+ FormatTok->setBlockKind(BK_BracedInit);
nextToken();
parseBracedList();
} else if (Style.Language == FormatStyle::LK_Proto &&
@@ -1747,10 +1774,10 @@ void UnwrappedLineParser::tryToParseJSFunction() {
}
bool UnwrappedLineParser::tryToParseBracedList() {
- if (FormatTok->BlockKind == BK_Unknown)
+ if (FormatTok->is(BK_Unknown))
calculateBraceTypes();
- assert(FormatTok->BlockKind != BK_Unknown);
- if (FormatTok->BlockKind == BK_Block)
+ assert(FormatTok->isNot(BK_Unknown));
+ if (FormatTok->is(BK_Block))
return false;
nextToken();
parseBracedList();
@@ -1830,7 +1857,7 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons,
case tok::l_brace:
// Assume there are no blocks inside a braced init list apart
// from the ones we explicitly parse out (like lambdas).
- FormatTok->BlockKind = BK_BracedInit;
+ FormatTok->setBlockKind(BK_BracedInit);
nextToken();
parseBracedList();
break;
@@ -2025,6 +2052,13 @@ void UnwrappedLineParser::parseTryCatch() {
nextToken();
if (FormatTok->is(tok::l_paren))
parseParens();
+ if (FormatTok->Previous && FormatTok->Previous->is(tok::identifier) &&
+ FormatTok->is(tok::l_brace)) {
+ do {
+ nextToken();
+ } while (!FormatTok->is(tok::r_brace));
+ nextToken();
+ }
// In case identifiers were removed by clang-tidy, what might follow is
// multiple commas in sequence - after the first identifier.
@@ -2107,15 +2141,34 @@ void UnwrappedLineParser::parseNamespace() {
if (ShouldBreakBeforeBrace(Style, InitialToken))
addUnwrappedLine();
- bool AddLevel = Style.NamespaceIndentation == FormatStyle::NI_All ||
- (Style.NamespaceIndentation == FormatStyle::NI_Inner &&
- DeclarationScopeStack.size() > 1);
- parseBlock(/*MustBeDeclaration=*/true, AddLevel);
+ unsigned AddLevels =
+ Style.NamespaceIndentation == FormatStyle::NI_All ||
+ (Style.NamespaceIndentation == FormatStyle::NI_Inner &&
+ DeclarationScopeStack.size() > 1)
+ ? 1u
+ : 0u;
+ bool ManageWhitesmithsBraces =
+ AddLevels == 0u &&
+ Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths;
+
+ // If we're in Whitesmiths mode, indent the brace if we're not indenting
+ // the whole block.
+ if (ManageWhitesmithsBraces)
+ ++Line->Level;
+
+ parseBlock(/*MustBeDeclaration=*/true, AddLevels,
+ /*MunchSemi=*/true,
+ /*UnindentWhitesmithsBraces=*/ManageWhitesmithsBraces);
+
// Munch the semicolon after a namespace. This is more common than one would
// think. Putting the semicolon into its own line is very ugly.
if (FormatTok->Tok.is(tok::semi))
nextToken();
- addUnwrappedLine();
+
+ addUnwrappedLine(AddLevels > 0 ? LineLevel::Remove : LineLevel::Keep);
+
+ if (ManageWhitesmithsBraces)
+ --Line->Level;
}
// FIXME: Add error handling.
}
@@ -2201,6 +2254,11 @@ void UnwrappedLineParser::parseDoWhile() {
return;
}
+ // If in Whitesmiths mode, the line with the while() needs to be indented
+ // to the same level as the block.
+ if (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths)
+ ++Line->Level;
+
nextToken();
parseStructuralElement();
}
@@ -2212,8 +2270,10 @@ void UnwrappedLineParser::parseLabel(bool LeftAlignLabel) {
--Line->Level;
if (LeftAlignLabel)
Line->Level = 0;
+
if (!Style.IndentCaseBlocks && CommentsBeforeNextToken.empty() &&
FormatTok->Tok.is(tok::l_brace)) {
+
CompoundStatementIndenter Indenter(this, Line->Level,
Style.BraceWrapping.AfterCaseLabel,
Style.BraceWrapping.IndentBraces);
@@ -2244,6 +2304,7 @@ void UnwrappedLineParser::parseLabel(bool LeftAlignLabel) {
void UnwrappedLineParser::parseCaseLabel() {
assert(FormatTok->Tok.is(tok::kw_case) && "'case' expected");
+
// FIXME: fix handling of complex expressions here.
do {
nextToken();
@@ -2279,6 +2340,117 @@ void UnwrappedLineParser::parseAccessSpecifier() {
addUnwrappedLine();
}
+void UnwrappedLineParser::parseConcept() {
+ assert(FormatTok->Tok.is(tok::kw_concept) && "'concept' expected");
+ nextToken();
+ if (!FormatTok->Tok.is(tok::identifier))
+ return;
+ nextToken();
+ if (!FormatTok->Tok.is(tok::equal))
+ return;
+ nextToken();
+ if (FormatTok->Tok.is(tok::kw_requires)) {
+ nextToken();
+ parseRequiresExpression(Line->Level);
+ } else {
+ parseConstraintExpression(Line->Level);
+ }
+}
+
+void UnwrappedLineParser::parseRequiresExpression(unsigned int OriginalLevel) {
+ // requires (R range)
+ if (FormatTok->Tok.is(tok::l_paren)) {
+ parseParens();
+ if (Style.IndentRequires && OriginalLevel != Line->Level) {
+ addUnwrappedLine();
+ --Line->Level;
+ }
+ }
+
+ if (FormatTok->Tok.is(tok::l_brace)) {
+ if (Style.BraceWrapping.AfterFunction)
+ addUnwrappedLine();
+ FormatTok->setType(TT_FunctionLBrace);
+ parseBlock(/*MustBeDeclaration=*/false);
+ addUnwrappedLine();
+ } else {
+ parseConstraintExpression(OriginalLevel);
+ }
+}
+
+void UnwrappedLineParser::parseConstraintExpression(
+ unsigned int OriginalLevel) {
+ // requires Id<T> && Id<T> || Id<T>
+ while (
+ FormatTok->isOneOf(tok::identifier, tok::kw_requires, tok::coloncolon)) {
+ nextToken();
+ while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::less,
+ tok::greater, tok::comma, tok::ellipsis)) {
+ if (FormatTok->Tok.is(tok::less)) {
+ parseBracedList(/*ContinueOnSemicolons=*/false, /*IsEnum=*/false,
+ /*ClosingBraceKind=*/tok::greater);
+ continue;
+ }
+ nextToken();
+ }
+ if (FormatTok->Tok.is(tok::kw_requires)) {
+ parseRequiresExpression(OriginalLevel);
+ }
+ if (FormatTok->Tok.is(tok::less)) {
+ parseBracedList(/*ContinueOnSemicolons=*/false, /*IsEnum=*/false,
+ /*ClosingBraceKind=*/tok::greater);
+ }
+
+ if (FormatTok->Tok.is(tok::l_paren)) {
+ parseParens();
+ }
+ if (FormatTok->Tok.is(tok::l_brace)) {
+ if (Style.BraceWrapping.AfterFunction)
+ addUnwrappedLine();
+ FormatTok->setType(TT_FunctionLBrace);
+ parseBlock(/*MustBeDeclaration=*/false);
+ }
+ if (FormatTok->Tok.is(tok::semi)) {
+ // Eat any trailing semi.
+ nextToken();
+ addUnwrappedLine();
+ }
+ if (FormatTok->Tok.is(tok::colon)) {
+ return;
+ }
+ if (!FormatTok->Tok.isOneOf(tok::ampamp, tok::pipepipe)) {
+ if (FormatTok->Previous &&
+ !FormatTok->Previous->isOneOf(tok::identifier, tok::kw_requires,
+ tok::coloncolon)) {
+ addUnwrappedLine();
+ }
+ if (Style.IndentRequires && OriginalLevel != Line->Level) {
+ --Line->Level;
+ }
+ break;
+ } else {
+ FormatTok->setType(TT_ConstraintJunctions);
+ }
+
+ nextToken();
+ }
+}
+
+void UnwrappedLineParser::parseRequires() {
+ assert(FormatTok->Tok.is(tok::kw_requires) && "'requires' expected");
+
+ unsigned OriginalLevel = Line->Level;
+ if (FormatTok->Previous && FormatTok->Previous->is(tok::greater)) {
+ addUnwrappedLine();
+ if (Style.IndentRequires) {
+ Line->Level++;
+ }
+ }
+ nextToken();
+
+ parseRequiresExpression(OriginalLevel);
+}
+
bool UnwrappedLineParser::parseEnum() {
// Won't be 'enum' for NS_ENUMs.
if (FormatTok->Tok.is(tok::kw_enum))
@@ -2318,7 +2490,7 @@ bool UnwrappedLineParser::parseEnum() {
// Just a declaration or something is wrong.
if (FormatTok->isNot(tok::l_brace))
return true;
- FormatTok->BlockKind = BK_Block;
+ FormatTok->setBlockKind(BK_Block);
if (Style.Language == FormatStyle::LK_Java) {
// Java enums are different.
@@ -2612,32 +2784,15 @@ void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
// @interface can be followed by a lightweight generic
// specialization list, then either a base class or a category.
if (FormatTok->Tok.is(tok::less)) {
- // Unlike protocol lists, generic parameterizations support
- // nested angles:
- //
- // @interface Foo<ValueType : id <NSCopying, NSSecureCoding>> :
- // NSObject <NSCopying, NSSecureCoding>
- //
- // so we need to count how many open angles we have left.
- unsigned NumOpenAngles = 1;
- do {
- nextToken();
- // Early exit in case someone forgot a close angle.
- if (FormatTok->isOneOf(tok::semi, tok::l_brace) ||
- FormatTok->Tok.isObjCAtKeyword(tok::objc_end))
- break;
- if (FormatTok->Tok.is(tok::less))
- ++NumOpenAngles;
- else if (FormatTok->Tok.is(tok::greater)) {
- assert(NumOpenAngles > 0 && "'>' makes NumOpenAngles negative");
- --NumOpenAngles;
- }
- } while (!eof() && NumOpenAngles != 0);
- nextToken(); // Skip '>'.
+ parseObjCLightweightGenerics();
}
if (FormatTok->Tok.is(tok::colon)) {
nextToken();
nextToken(); // base class name
+ // The base class can also have lightweight generics applied to it.
+ if (FormatTok->Tok.is(tok::less)) {
+ parseObjCLightweightGenerics();
+ }
} else if (FormatTok->Tok.is(tok::l_paren))
// Skip category, if present.
parseParens();
@@ -2658,6 +2813,32 @@ void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
parseObjCUntilAtEnd();
}
+void UnwrappedLineParser::parseObjCLightweightGenerics() {
+ assert(FormatTok->Tok.is(tok::less));
+ // Unlike protocol lists, generic parameterizations support
+ // nested angles:
+ //
+ // @interface Foo<ValueType : id <NSCopying, NSSecureCoding>> :
+ // NSObject <NSCopying, NSSecureCoding>
+ //
+ // so we need to count how many open angles we have left.
+ unsigned NumOpenAngles = 1;
+ do {
+ nextToken();
+ // Early exit in case someone forgot a close angle.
+ if (FormatTok->isOneOf(tok::semi, tok::l_brace) ||
+ FormatTok->Tok.isObjCAtKeyword(tok::objc_end))
+ break;
+ if (FormatTok->Tok.is(tok::less))
+ ++NumOpenAngles;
+ else if (FormatTok->Tok.is(tok::greater)) {
+ assert(NumOpenAngles > 0 && "'>' makes NumOpenAngles negative");
+ --NumOpenAngles;
+ }
+ } while (!eof() && NumOpenAngles != 0);
+ nextToken(); // Skip '>'.
+}
+
// Returns true for the declaration/definition form of @protocol,
// false for the expression form.
bool UnwrappedLineParser::parseObjCProtocol() {
@@ -2726,7 +2907,7 @@ void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {
return;
}
if (FormatTok->is(tok::l_brace)) {
- FormatTok->BlockKind = BK_Block;
+ FormatTok->setBlockKind(BK_Block);
nextToken();
parseBracedList();
} else {
@@ -2753,7 +2934,7 @@ LLVM_ATTRIBUTE_UNUSED static void printDebugInfo(const UnwrappedLine &Line,
E = Line.Tokens.end();
I != E; ++I) {
llvm::dbgs() << I->Tok->Tok.getName() << "["
- << "T=" << I->Tok->getType()
+ << "T=" << (unsigned)I->Tok->getType()
<< ", OC=" << I->Tok->OriginalColumn << "] ";
}
for (std::list<UnwrappedLineNode>::const_iterator I = Line.Tokens.begin(),
@@ -2770,17 +2951,29 @@ LLVM_ATTRIBUTE_UNUSED static void printDebugInfo(const UnwrappedLine &Line,
llvm::dbgs() << "\n";
}
-void UnwrappedLineParser::addUnwrappedLine() {
+void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) {
if (Line->Tokens.empty())
return;
LLVM_DEBUG({
if (CurrentLines == &Lines)
printDebugInfo(*Line);
});
+
+ // If this line closes a block when in Whitesmiths mode, remember that
+ // information so that the level can be decreased after the line is added.
+ // This has to happen after the addition of the line since the line itself
+ // needs to be indented.
+ bool ClosesWhitesmithsBlock =
+ Line->MatchingOpeningBlockLineIndex != UnwrappedLine::kInvalidIndex &&
+ Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths;
+
CurrentLines->push_back(std::move(*Line));
Line->Tokens.clear();
Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex;
Line->FirstStartColumn = 0;
+
+ if (ClosesWhitesmithsBlock && AdjustLevel == LineLevel::Remove)
+ --Line->Level;
if (CurrentLines == &Lines && !PreprocessorDirectives.empty()) {
CurrentLines->append(
std::make_move_iterator(PreprocessorDirectives.begin()),
diff --git a/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.h b/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.h
index 8b3aa4c84edb..ce135fac5e57 100644
--- a/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.h
+++ b/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.h
@@ -85,8 +85,9 @@ private:
void reset();
void parseFile();
void parseLevel(bool HasOpeningBrace);
- void parseBlock(bool MustBeDeclaration, bool AddLevel = true,
- bool MunchSemi = true);
+ void parseBlock(bool MustBeDeclaration, unsigned AddLevels = 1u,
+ bool MunchSemi = true,
+ bool UnindentWhitesmithsBraces = false);
void parseChildBlock();
void parsePPDirective();
void parsePPDefine();
@@ -113,11 +114,16 @@ private:
void parseNew();
void parseAccessSpecifier();
bool parseEnum();
+ void parseConcept();
+ void parseRequires();
+ void parseRequiresExpression(unsigned int OriginalLevel);
+ void parseConstraintExpression(unsigned int OriginalLevel);
void parseJavaEnumBody();
// Parses a record (aka class) as a top level element. If ParseAsExpr is true,
// parses the record as a child block, i.e. if the class declaration is an
// expression.
void parseRecord(bool ParseAsExpr = false);
+ void parseObjCLightweightGenerics();
void parseObjCMethod();
void parseObjCProtocolList();
void parseObjCUntilAtEnd();
@@ -135,7 +141,12 @@ private:
bool tryToParsePropertyAccessor();
void tryToParseJSFunction();
bool tryToParseSimpleAttribute();
- void addUnwrappedLine();
+
+ // Used by addUnwrappedLine to denote whether to keep or remove a level
+ // when resetting the line state.
+ enum class LineLevel { Remove, Keep };
+
+ void addUnwrappedLine(LineLevel AdjustLevel = LineLevel::Remove);
bool eof() const;
// LevelDifference is the difference of levels after and before the current
// token. For example:
diff --git a/contrib/llvm-project/clang/lib/Format/WhitespaceManager.cpp b/contrib/llvm-project/clang/lib/Format/WhitespaceManager.cpp
index 3a265bd09168..7d6964b7c72f 100644
--- a/contrib/llvm-project/clang/lib/Format/WhitespaceManager.cpp
+++ b/contrib/llvm-project/clang/lib/Format/WhitespaceManager.cpp
@@ -49,7 +49,7 @@ void WhitespaceManager::replaceWhitespace(FormatToken &Tok, unsigned Newlines,
bool IsAligned, bool InPPDirective) {
if (Tok.Finalized)
return;
- Tok.Decision = (Newlines > 0) ? FD_Break : FD_Continue;
+ Tok.setDecision((Newlines > 0) ? FD_Break : FD_Continue);
Changes.push_back(Change(Tok, /*CreateReplacement=*/true, Tok.WhitespaceRange,
Spaces, StartOfTokenColumn, Newlines, "", "",
IsAligned, InPPDirective && !Tok.IsFirst,
@@ -361,9 +361,10 @@ AlignTokenSequence(unsigned Start, unsigned End, unsigned Column, F &&Matches,
// that are split across multiple lines. See the test case in FormatTest.cpp
// that mentions "split function parameter alignment" for an example of this.
template <typename F>
-static unsigned AlignTokens(const FormatStyle &Style, F &&Matches,
- SmallVector<WhitespaceManager::Change, 16> &Changes,
- unsigned StartAt) {
+static unsigned AlignTokens(
+ const FormatStyle &Style, F &&Matches,
+ SmallVector<WhitespaceManager::Change, 16> &Changes, unsigned StartAt,
+ const FormatStyle::AlignConsecutiveStyle &ACS = FormatStyle::ACS_None) {
unsigned MinColumn = 0;
unsigned MaxColumn = UINT_MAX;
@@ -386,6 +387,9 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches,
// Whether a matching token has been found on the current line.
bool FoundMatchOnLine = false;
+ // Whether the current line consists purely of comments.
+ bool LineIsComment = true;
+
// Aligns a sequence of matching tokens, on the MinColumn column.
//
// Sequences start from the first matching token to align, and end at the
@@ -411,19 +415,38 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches,
if (Changes[i].NewlinesBefore != 0) {
CommasBeforeMatch = 0;
EndOfSequence = i;
- // If there is a blank line, or if the last line didn't contain any
- // matching token, the sequence ends here.
- if (Changes[i].NewlinesBefore > 1 || !FoundMatchOnLine)
+
+ // Whether to break the alignment sequence because of an empty line.
+ bool EmptyLineBreak =
+ (Changes[i].NewlinesBefore > 1) &&
+ (ACS != FormatStyle::ACS_AcrossEmptyLines) &&
+ (ACS != FormatStyle::ACS_AcrossEmptyLinesAndComments);
+
+ // Whether to break the alignment sequence because of a line without a
+ // match.
+ bool NoMatchBreak =
+ !FoundMatchOnLine &&
+ !(LineIsComment &&
+ ((ACS == FormatStyle::ACS_AcrossComments) ||
+ (ACS == FormatStyle::ACS_AcrossEmptyLinesAndComments)));
+
+ if (EmptyLineBreak || NoMatchBreak)
AlignCurrentSequence();
+ // A new line starts, re-initialize line status tracking bools.
FoundMatchOnLine = false;
+ LineIsComment = true;
+ }
+
+ if (!Changes[i].Tok->is(tok::comment)) {
+ LineIsComment = false;
}
if (Changes[i].Tok->is(tok::comma)) {
++CommasBeforeMatch;
} else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
// Call AlignTokens recursively, skipping over this scope block.
- unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i);
+ unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
i = StoppedAt - 1;
continue;
}
@@ -518,7 +541,7 @@ static void AlignMacroSequence(
}
void WhitespaceManager::alignConsecutiveMacros() {
- if (!Style.AlignConsecutiveMacros)
+ if (Style.AlignConsecutiveMacros == FormatStyle::ACS_None)
return;
auto AlignMacrosMatches = [](const Change &C) {
@@ -560,17 +583,41 @@ void WhitespaceManager::alignConsecutiveMacros() {
// Whether a matching token has been found on the current line.
bool FoundMatchOnLine = false;
+ // Whether the current line consists only of comments
+ bool LineIsComment = true;
+
unsigned I = 0;
for (unsigned E = Changes.size(); I != E; ++I) {
if (Changes[I].NewlinesBefore != 0) {
EndOfSequence = I;
- // If there is a blank line, or if the last line didn't contain any
- // matching token, the sequence ends here.
- if (Changes[I].NewlinesBefore > 1 || !FoundMatchOnLine)
+
+ // Whether to break the alignment sequence because of an empty line.
+ bool EmptyLineBreak =
+ (Changes[I].NewlinesBefore > 1) &&
+ (Style.AlignConsecutiveMacros != FormatStyle::ACS_AcrossEmptyLines) &&
+ (Style.AlignConsecutiveMacros !=
+ FormatStyle::ACS_AcrossEmptyLinesAndComments);
+
+ // Whether to break the alignment sequence because of a line without a
+ // match.
+ bool NoMatchBreak =
+ !FoundMatchOnLine &&
+ !(LineIsComment && ((Style.AlignConsecutiveMacros ==
+ FormatStyle::ACS_AcrossComments) ||
+ (Style.AlignConsecutiveMacros ==
+ FormatStyle::ACS_AcrossEmptyLinesAndComments)));
+
+ if (EmptyLineBreak || NoMatchBreak)
AlignMacroSequence(StartOfSequence, EndOfSequence, MinColumn, MaxColumn,
FoundMatchOnLine, AlignMacrosMatches, Changes);
+ // A new line starts, re-initialize line status tracking bools.
FoundMatchOnLine = false;
+ LineIsComment = true;
+ }
+
+ if (!Changes[I].Tok->is(tok::comment)) {
+ LineIsComment = false;
}
if (!AlignMacrosMatches(Changes[I]))
@@ -597,7 +644,7 @@ void WhitespaceManager::alignConsecutiveMacros() {
}
void WhitespaceManager::alignConsecutiveAssignments() {
- if (!Style.AlignConsecutiveAssignments)
+ if (Style.AlignConsecutiveAssignments == FormatStyle::ACS_None)
return;
AlignTokens(
@@ -613,11 +660,11 @@ void WhitespaceManager::alignConsecutiveAssignments() {
return C.Tok->is(tok::equal);
},
- Changes, /*StartAt=*/0);
+ Changes, /*StartAt=*/0, Style.AlignConsecutiveAssignments);
}
void WhitespaceManager::alignConsecutiveBitFields() {
- if (!Style.AlignConsecutiveBitFields)
+ if (Style.AlignConsecutiveBitFields == FormatStyle::ACS_None)
return;
AlignTokens(
@@ -633,11 +680,11 @@ void WhitespaceManager::alignConsecutiveBitFields() {
return C.Tok->is(TT_BitFieldColon);
},
- Changes, /*StartAt=*/0);
+ Changes, /*StartAt=*/0, Style.AlignConsecutiveBitFields);
}
void WhitespaceManager::alignConsecutiveDeclarations() {
- if (!Style.AlignConsecutiveDeclarations)
+ if (Style.AlignConsecutiveDeclarations == FormatStyle::ACS_None)
return;
// FIXME: Currently we don't handle properly the PointerAlignment: Right
@@ -655,6 +702,9 @@ void WhitespaceManager::alignConsecutiveDeclarations() {
return true;
if (C.Tok->isNot(TT_StartOfName))
return false;
+ if (C.Tok->Previous &&
+ C.Tok->Previous->is(TT_StatementAttributeLikeMacro))
+ return false;
// Check if there is a subsequent name that starts the same declaration.
for (FormatToken *Next = C.Tok->Next; Next; Next = Next->Next) {
if (Next->is(tok::comment))
@@ -667,7 +717,7 @@ void WhitespaceManager::alignConsecutiveDeclarations() {
}
return true;
},
- Changes, /*StartAt=*/0);
+ Changes, /*StartAt=*/0, Style.AlignConsecutiveDeclarations);
}
void WhitespaceManager::alignChainedConditionals() {