aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Format
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Format')
-rw-r--r--clang/lib/Format/BreakableToken.cpp8
-rw-r--r--clang/lib/Format/ContinuationIndenter.cpp95
-rw-r--r--clang/lib/Format/ContinuationIndenter.h9
-rw-r--r--clang/lib/Format/DefinitionBlockSeparator.cpp6
-rw-r--r--clang/lib/Format/Format.cpp1250
-rw-r--r--clang/lib/Format/FormatToken.cpp3
-rw-r--r--clang/lib/Format/FormatToken.h92
-rw-r--r--clang/lib/Format/FormatTokenLexer.cpp184
-rw-r--r--clang/lib/Format/FormatTokenLexer.h7
-rw-r--r--clang/lib/Format/IntegerLiteralSeparatorFixer.cpp199
-rw-r--r--clang/lib/Format/IntegerLiteralSeparatorFixer.h38
-rw-r--r--clang/lib/Format/MacroCallReconstructor.cpp23
-rw-r--r--clang/lib/Format/QualifierAlignmentFixer.cpp4
-rw-r--r--clang/lib/Format/TokenAnalyzer.cpp6
-rw-r--r--clang/lib/Format/TokenAnalyzer.h3
-rw-r--r--clang/lib/Format/TokenAnnotator.cpp445
-rw-r--r--clang/lib/Format/TokenAnnotator.h15
-rw-r--r--clang/lib/Format/UnwrappedLineFormatter.cpp50
-rw-r--r--clang/lib/Format/UnwrappedLineFormatter.h2
-rw-r--r--clang/lib/Format/UnwrappedLineParser.cpp598
-rw-r--r--clang/lib/Format/UnwrappedLineParser.h30
-rw-r--r--clang/lib/Format/UsingDeclarationsSorter.cpp57
-rw-r--r--clang/lib/Format/WhitespaceManager.cpp57
-rw-r--r--clang/lib/Format/WhitespaceManager.h2
24 files changed, 2242 insertions, 941 deletions
diff --git a/clang/lib/Format/BreakableToken.cpp b/clang/lib/Format/BreakableToken.cpp
index db82018a4c83..b3ef2a895d7f 100644
--- a/clang/lib/Format/BreakableToken.cpp
+++ b/clang/lib/Format/BreakableToken.cpp
@@ -49,10 +49,10 @@ static StringRef getLineCommentIndentPrefix(StringRef Comment,
if (Style.Language == FormatStyle::LK_TextProto)
KnownPrefixes = KnownTextProtoPrefixes;
- assert(std::is_sorted(KnownPrefixes.begin(), KnownPrefixes.end(),
- [](StringRef Lhs, StringRef Rhs) noexcept {
- return Lhs.size() > Rhs.size();
- }));
+ assert(
+ llvm::is_sorted(KnownPrefixes, [](StringRef Lhs, StringRef Rhs) noexcept {
+ return Lhs.size() > Rhs.size();
+ }));
for (StringRef KnownPrefix : KnownPrefixes) {
if (Comment.startswith(KnownPrefix)) {
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp
index 651ec80d6196..412c57b850b5 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -21,6 +21,7 @@
#include "clang/Format/Format.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Debug.h"
+#include <optional>
#define DEBUG_TYPE "format-indenter"
@@ -146,13 +147,13 @@ static bool opensProtoMessageField(const FormatToken &LessTok,
(LessTok.Previous && LessTok.Previous->is(tok::equal))));
}
-// Returns the delimiter of a raw string literal, or None if TokenText is not
-// the text of a raw string literal. The delimiter could be the empty string.
-// For example, the delimiter of R"deli(cont)deli" is deli.
-static llvm::Optional<StringRef> getRawStringDelimiter(StringRef TokenText) {
+// Returns the delimiter of a raw string literal, or std::nullopt if TokenText
+// is not the text of a raw string literal. The delimiter could be the empty
+// string. For example, the delimiter of R"deli(cont)deli" is deli.
+static std::optional<StringRef> getRawStringDelimiter(StringRef TokenText) {
if (TokenText.size() < 5 // The smallest raw string possible is 'R"()"'.
|| !TokenText.startswith("R\"") || !TokenText.endswith("\"")) {
- return None;
+ return std::nullopt;
}
// A raw string starts with 'R"<delimiter>(' and delimiter is ascii and has
@@ -160,15 +161,15 @@ static llvm::Optional<StringRef> getRawStringDelimiter(StringRef TokenText) {
// 19 bytes.
size_t LParenPos = TokenText.substr(0, 19).find_first_of('(');
if (LParenPos == StringRef::npos)
- return None;
+ return std::nullopt;
StringRef Delimiter = TokenText.substr(2, LParenPos - 2);
// Check that the string ends in ')Delimiter"'.
size_t RParenPos = TokenText.size() - Delimiter.size() - 2;
if (TokenText[RParenPos] != ')')
- return None;
+ return std::nullopt;
if (!TokenText.substr(RParenPos + 1).startswith(Delimiter))
- return None;
+ return std::nullopt;
return Delimiter;
}
@@ -186,7 +187,7 @@ getCanonicalRawStringDelimiter(const FormatStyle &Style,
RawStringFormatStyleManager::RawStringFormatStyleManager(
const FormatStyle &CodeStyle) {
for (const auto &RawStringFormat : CodeStyle.RawStringFormats) {
- llvm::Optional<FormatStyle> LanguageStyle =
+ std::optional<FormatStyle> LanguageStyle =
CodeStyle.GetLanguageStyle(RawStringFormat.Language);
if (!LanguageStyle) {
FormatStyle PredefinedStyle;
@@ -205,20 +206,20 @@ RawStringFormatStyleManager::RawStringFormatStyleManager(
}
}
-llvm::Optional<FormatStyle>
+std::optional<FormatStyle>
RawStringFormatStyleManager::getDelimiterStyle(StringRef Delimiter) const {
auto It = DelimiterStyle.find(Delimiter);
if (It == DelimiterStyle.end())
- return None;
+ return std::nullopt;
return It->second;
}
-llvm::Optional<FormatStyle>
+std::optional<FormatStyle>
RawStringFormatStyleManager::getEnclosingFunctionStyle(
StringRef EnclosingFunction) const {
auto It = EnclosingFunctionStyle.find(EnclosingFunction);
if (It == EnclosingFunctionStyle.end())
- return None;
+ return std::nullopt;
return It->second;
}
@@ -331,6 +332,15 @@ bool ContinuationIndenter::canBreak(const LineState &State) {
if (Previous.is(tok::l_square) && Previous.is(TT_ObjCMethodExpr))
return false;
+ if (Current.is(TT_ConditionalExpr) && Previous.is(tok::r_paren) &&
+ Previous.MatchingParen && Previous.MatchingParen->Previous &&
+ Previous.MatchingParen->Previous->MatchingParen &&
+ Previous.MatchingParen->Previous->MatchingParen->is(TT_LambdaLBrace)) {
+ // We have a lambda within a conditional expression, allow breaking here.
+ assert(Previous.MatchingParen->Previous->is(tok::r_brace));
+ return true;
+ }
+
return !CurrentState.NoLineBreak;
}
@@ -343,8 +353,12 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
auto LambdaBodyLength = getLengthToMatchingParen(Current, State.Stack);
return LambdaBodyLength > getColumnLimit(State);
}
- if (Current.MustBreakBefore || Current.is(TT_InlineASMColon))
+ if (Current.MustBreakBefore ||
+ (Current.is(TT_InlineASMColon) &&
+ (Style.BreakBeforeInlineASMColon == FormatStyle::BBIAS_Always ||
+ Style.BreakBeforeInlineASMColon == FormatStyle::BBIAS_OnlyMultiline))) {
return true;
+ }
if (CurrentState.BreakBeforeClosingBrace &&
Current.closesBlockOrBlockTypeList(Style)) {
return true;
@@ -444,7 +458,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
}
// If the template declaration spans multiple lines, force wrap before the
- // function/class declaration
+ // function/class declaration.
if (Previous.ClosesTemplateDeclaration && CurrentState.BreakBeforeParameter &&
Current.CanBreakBefore) {
return true;
@@ -552,7 +566,8 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
// If the return type spans multiple lines, wrap before the function name.
if (((Current.is(TT_FunctionDeclarationName) &&
- // Don't break before a C# function when no break after return type
+ !State.Line->ReturnTypeWrapped &&
+ // Don't break before a C# function when no break after return type.
(!Style.isCSharp() ||
Style.AlwaysBreakAfterReturnType != FormatStyle::RTBS_None) &&
// Don't always break between a JavaScript `function` and the function
@@ -707,8 +722,9 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
(Previous.is(tok::l_brace) && Previous.isNot(BK_Block) &&
Style.Cpp11BracedListStyle)) &&
State.Column > getNewLineColumn(State) &&
- (!Previous.Previous || !Previous.Previous->isOneOf(
- tok::kw_for, tok::kw_while, tok::kw_switch)) &&
+ (!Previous.Previous ||
+ !Previous.Previous->isOneOf(TT_CastRParen, tok::kw_for, tok::kw_while,
+ tok::kw_switch)) &&
// Don't do this for simple (no expressions) one-argument function calls
// as that feels like needlessly wasting whitespace, e.g.:
//
@@ -1090,8 +1106,12 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
CurrentState.Indent + Style.ContinuationIndentWidth);
}
- if (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths &&
- State.Line->First->is(tok::kw_enum)) {
+ // After a goto label. Usually labels are on separate lines. However
+ // for Verilog the labels may be only recognized by the annotator and
+ // thus are on the same line as the current token.
+ if ((Style.isVerilog() && Keywords.isVerilogEndOfLabel(Previous)) ||
+ (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths &&
+ State.Line->First->is(tok::kw_enum))) {
return (Style.IndentWidth * State.Line->First->IndentLevel) +
Style.IndentWidth;
}
@@ -1244,6 +1264,9 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
return ContinuationIndent;
}
+ if (State.Line->InPragmaDirective)
+ return CurrentState.Indent + Style.ContinuationIndentWidth;
+
// This ensure that we correctly format ObjC methods calls without inputs,
// i.e. where the last element isn't selector like: [callee method];
if (NextNonComment->is(tok::identifier) && NextNonComment->FakeRParens == 0 &&
@@ -1301,7 +1324,7 @@ static bool hasNestedBlockInlined(const FormatToken *Previous,
if (Previous->ParameterCount > 1)
return true;
- // Also a nested block if contains a lambda inside function with 1 parameter
+ // Also a nested block if contains a lambda inside function with 1 parameter.
return Style.BraceWrapping.BeforeLambdaBody && Current.is(TT_LambdaLSquare);
}
@@ -1399,8 +1422,10 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
CurrentState.NestedBlockIndent = State.Column + Current.ColumnWidth + 1;
if (Current.isOneOf(TT_LambdaLSquare, TT_LambdaArrow))
CurrentState.LastSpace = State.Column;
- if (Current.is(TT_RequiresExpression))
+ if (Current.is(TT_RequiresExpression) &&
+ Style.RequiresExpressionIndentation == FormatStyle::REI_Keyword) {
CurrentState.NestedBlockIndent = State.Column;
+ }
// Insert scopes created by fake parenthesis.
const FormatToken *Previous = Current.getPreviousNonComment();
@@ -1514,6 +1539,12 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
std::max(State.Column, NewParenState.Indent), CurrentState.LastSpace);
}
+ // Special case for generic selection expressions, its comma-separated
+ // expressions are not aligned to the opening paren like regular calls, but
+ // rather continuation-indented relative to the _Generic keyword.
+ if (Previous && Previous->endsSequence(tok::l_paren, tok::kw__Generic))
+ NewParenState.Indent = CurrentState.LastSpace;
+
if (Previous &&
(Previous->getPrecedence() == prec::Assignment ||
Previous->isOneOf(tok::kw_return, TT_RequiresClause) ||
@@ -1521,7 +1552,7 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
Previous->is(TT_ConditionalExpr))) &&
!Newline) {
// If BreakBeforeBinaryOperators is set, un-indent a bit to account for
- // the operator and keep the operands aligned
+ // 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.
@@ -1660,8 +1691,12 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
(State.Line->Type != LT_ObjCDecl && Style.BinPackParameters) ||
(State.Line->Type == LT_ObjCDecl && ObjCBinPackProtocolList);
+ bool GenericSelection =
+ Current.getPreviousNonComment() &&
+ Current.getPreviousNonComment()->is(tok::kw__Generic);
+
AvoidBinPacking =
- (CurrentState.IsCSharpGenericTypeConstraint) ||
+ (CurrentState.IsCSharpGenericTypeConstraint) || GenericSelection ||
(Style.isJavaScript() && EndsInComma) ||
(State.Line->MustBeDeclaration && !BinPackDeclaration) ||
(!State.Line->MustBeDeclaration && !Style.BinPackArguments) ||
@@ -1713,7 +1748,7 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
if (Style.BraceWrapping.BeforeLambdaBody && Current.Next != nullptr &&
Current.is(tok::l_paren)) {
- // Search for any parameter that is a lambda
+ // Search for any parameter that is a lambda.
FormatToken const *next = Current.Next;
while (next != nullptr) {
if (next->is(TT_LambdaLSquare)) {
@@ -2045,21 +2080,21 @@ static StringRef getEnclosingFunctionName(const FormatToken &Current) {
return Tok->TokenText;
}
-llvm::Optional<FormatStyle>
+std::optional<FormatStyle>
ContinuationIndenter::getRawStringStyle(const FormatToken &Current,
const LineState &State) {
if (!Current.isStringLiteral())
- return None;
+ return std::nullopt;
auto Delimiter = getRawStringDelimiter(Current.TokenText);
if (!Delimiter)
- return None;
+ return std::nullopt;
auto RawStringStyle = RawStringFormats.getDelimiterStyle(*Delimiter);
if (!RawStringStyle && Delimiter->empty()) {
RawStringStyle = RawStringFormats.getEnclosingFunctionStyle(
getEnclosingFunctionName(Current));
}
if (!RawStringStyle)
- return None;
+ return std::nullopt;
RawStringStyle->ColumnLimit = getColumnLimit(State);
return RawStringStyle;
}
@@ -2533,7 +2568,7 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
}
unsigned ContinuationIndenter::getColumnLimit(const LineState &State) const {
- // In preprocessor directives reserve two chars for trailing " \"
+ // In preprocessor directives reserve two chars for trailing " \".
return Style.ColumnLimit - (State.Line->InPPDirective ? 2 : 0);
}
diff --git a/clang/lib/Format/ContinuationIndenter.h b/clang/lib/Format/ContinuationIndenter.h
index 620060e68861..2a1b96834a79 100644
--- a/clang/lib/Format/ContinuationIndenter.h
+++ b/clang/lib/Format/ContinuationIndenter.h
@@ -20,6 +20,7 @@
#include "clang/Format/Format.h"
#include "llvm/Support/Regex.h"
#include <map>
+#include <optional>
#include <tuple>
namespace clang {
@@ -41,9 +42,9 @@ struct RawStringFormatStyleManager {
RawStringFormatStyleManager(const FormatStyle &CodeStyle);
- llvm::Optional<FormatStyle> getDelimiterStyle(StringRef Delimiter) const;
+ std::optional<FormatStyle> getDelimiterStyle(StringRef Delimiter) const;
- llvm::Optional<FormatStyle>
+ std::optional<FormatStyle>
getEnclosingFunctionStyle(StringRef EnclosingFunction) const;
};
@@ -120,8 +121,8 @@ private:
/// If \p Current is a raw string that is configured to be reformatted,
/// return the style to be used.
- llvm::Optional<FormatStyle> getRawStringStyle(const FormatToken &Current,
- const LineState &State);
+ std::optional<FormatStyle> getRawStringStyle(const FormatToken &Current,
+ const LineState &State);
/// If the current token sticks out over the end of the line, break
/// it if possible.
diff --git a/clang/lib/Format/DefinitionBlockSeparator.cpp b/clang/lib/Format/DefinitionBlockSeparator.cpp
index f6edcd13ecd6..5c006e2d037b 100644
--- a/clang/lib/Format/DefinitionBlockSeparator.cpp
+++ b/clang/lib/Format/DefinitionBlockSeparator.cpp
@@ -69,11 +69,11 @@ void DefinitionBlockSeparator::separateBlocks(
(Style.SeparateDefinitionBlocks == FormatStyle::SDS_Always ? 1 : 0) + 1;
WhitespaceManager Whitespaces(
Env.getSourceManager(), Style,
- Style.DeriveLineEnding
+ Style.LineEnding > FormatStyle::LE_CRLF
? WhitespaceManager::inputUsesCRLF(
Env.getSourceManager().getBufferData(Env.getFileID()),
- Style.UseCRLF)
- : Style.UseCRLF);
+ Style.LineEnding == FormatStyle::LE_DeriveCRLF)
+ : Style.LineEnding == FormatStyle::LE_CRLF);
for (unsigned I = 0; I < Lines.size(); ++I) {
const auto &CurrentLine = Lines[I];
if (CurrentLine->InPPDirective)
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 2659fa2af1a7..f37c3f983635 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -20,6 +20,7 @@
#include "FormatInternal.h"
#include "FormatToken.h"
#include "FormatTokenLexer.h"
+#include "IntegerLiteralSeparatorFixer.h"
#include "NamespaceEndCommentsFixer.h"
#include "QualifierAlignmentFixer.h"
#include "SortJavaScriptImports.h"
@@ -46,6 +47,7 @@
#include <algorithm>
#include <memory>
#include <mutex>
+#include <optional>
#include <string>
#include <unordered_map>
@@ -57,101 +59,6 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::RawStringFormat)
namespace llvm {
namespace yaml {
-template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
- static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) {
- IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp);
- IO.enumCase(Value, "Java", FormatStyle::LK_Java);
- IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript);
- IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC);
- IO.enumCase(Value, "Proto", FormatStyle::LK_Proto);
- IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen);
- IO.enumCase(Value, "TextProto", FormatStyle::LK_TextProto);
- IO.enumCase(Value, "CSharp", FormatStyle::LK_CSharp);
- IO.enumCase(Value, "Json", FormatStyle::LK_Json);
- }
-};
-
-template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> {
- static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) {
- IO.enumCase(Value, "c++03", FormatStyle::LS_Cpp03);
- IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03); // Legacy alias
- IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03); // Legacy alias
-
- IO.enumCase(Value, "c++11", FormatStyle::LS_Cpp11);
- IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11); // Legacy alias
-
- IO.enumCase(Value, "c++14", FormatStyle::LS_Cpp14);
- IO.enumCase(Value, "c++17", FormatStyle::LS_Cpp17);
- IO.enumCase(Value, "c++20", FormatStyle::LS_Cpp20);
-
- IO.enumCase(Value, "Latest", FormatStyle::LS_Latest);
- IO.enumCase(Value, "Cpp11", FormatStyle::LS_Latest); // Legacy alias
- IO.enumCase(Value, "Auto", FormatStyle::LS_Auto);
- }
-};
-
-template <>
-struct ScalarEnumerationTraits<FormatStyle::LambdaBodyIndentationKind> {
- static void enumeration(IO &IO,
- FormatStyle::LambdaBodyIndentationKind &Value) {
- IO.enumCase(Value, "Signature", FormatStyle::LBI_Signature);
- IO.enumCase(Value, "OuterScope", FormatStyle::LBI_OuterScope);
- }
-};
-
-template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> {
- static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) {
- IO.enumCase(Value, "Never", FormatStyle::UT_Never);
- IO.enumCase(Value, "false", FormatStyle::UT_Never);
- IO.enumCase(Value, "Always", FormatStyle::UT_Always);
- IO.enumCase(Value, "true", FormatStyle::UT_Always);
- IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation);
- IO.enumCase(Value, "ForContinuationAndIndentation",
- FormatStyle::UT_ForContinuationAndIndentation);
- IO.enumCase(Value, "AlignWithSpaces", FormatStyle::UT_AlignWithSpaces);
- }
-};
-
-template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> {
- static void enumeration(IO &IO, FormatStyle::JavaScriptQuoteStyle &Value) {
- IO.enumCase(Value, "Leave", FormatStyle::JSQS_Leave);
- IO.enumCase(Value, "Single", FormatStyle::JSQS_Single);
- IO.enumCase(Value, "Double", FormatStyle::JSQS_Double);
- }
-};
-
-template <> struct ScalarEnumerationTraits<FormatStyle::ShortBlockStyle> {
- static void enumeration(IO &IO, FormatStyle::ShortBlockStyle &Value) {
- IO.enumCase(Value, "Never", FormatStyle::SBS_Never);
- IO.enumCase(Value, "false", FormatStyle::SBS_Never);
- IO.enumCase(Value, "Always", FormatStyle::SBS_Always);
- IO.enumCase(Value, "true", FormatStyle::SBS_Always);
- IO.enumCase(Value, "Empty", FormatStyle::SBS_Empty);
- }
-};
-
-template <>
-struct ScalarEnumerationTraits<FormatStyle::QualifierAlignmentStyle> {
- static void enumeration(IO &IO, FormatStyle::QualifierAlignmentStyle &Value) {
- IO.enumCase(Value, "Leave", FormatStyle::QAS_Leave);
- IO.enumCase(Value, "Left", FormatStyle::QAS_Left);
- IO.enumCase(Value, "Right", FormatStyle::QAS_Right);
- IO.enumCase(Value, "Custom", FormatStyle::QAS_Custom);
- }
-};
-
-template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
- static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) {
- IO.enumCase(Value, "None", FormatStyle::SFS_None);
- IO.enumCase(Value, "false", FormatStyle::SFS_None);
- IO.enumCase(Value, "All", FormatStyle::SFS_All);
- IO.enumCase(Value, "true", FormatStyle::SFS_All);
- IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline);
- IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly);
- IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty);
- }
-};
-
template <> struct MappingTraits<FormatStyle::AlignConsecutiveStyle> {
static void enumInput(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
IO.enumCase(Value, "None",
@@ -205,6 +112,15 @@ template <> struct MappingTraits<FormatStyle::AlignConsecutiveStyle> {
};
template <>
+struct ScalarEnumerationTraits<FormatStyle::AttributeBreakingStyle> {
+ static void enumeration(IO &IO, FormatStyle::AttributeBreakingStyle &Value) {
+ IO.enumCase(Value, "Always", FormatStyle::ABS_Always);
+ IO.enumCase(Value, "Leave", FormatStyle::ABS_Leave);
+ IO.enumCase(Value, "Never", FormatStyle::ABS_Never);
+ }
+};
+
+template <>
struct ScalarEnumerationTraits<FormatStyle::ArrayInitializerAlignmentStyle> {
static void enumeration(IO &IO,
FormatStyle::ArrayInitializerAlignmentStyle &Value) {
@@ -214,28 +130,13 @@ struct ScalarEnumerationTraits<FormatStyle::ArrayInitializerAlignmentStyle> {
}
};
-template <> struct ScalarEnumerationTraits<FormatStyle::ShortIfStyle> {
- static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value) {
- IO.enumCase(Value, "Never", FormatStyle::SIS_Never);
- IO.enumCase(Value, "WithoutElse", FormatStyle::SIS_WithoutElse);
- IO.enumCase(Value, "OnlyFirstIf", FormatStyle::SIS_OnlyFirstIf);
- IO.enumCase(Value, "AllIfsAndElse", FormatStyle::SIS_AllIfsAndElse);
-
- // For backward compatibility.
- IO.enumCase(Value, "Always", FormatStyle::SIS_OnlyFirstIf);
- IO.enumCase(Value, "false", FormatStyle::SIS_Never);
- IO.enumCase(Value, "true", FormatStyle::SIS_WithoutElse);
- }
-};
-
-template <> struct ScalarEnumerationTraits<FormatStyle::ShortLambdaStyle> {
- static void enumeration(IO &IO, FormatStyle::ShortLambdaStyle &Value) {
- IO.enumCase(Value, "None", FormatStyle::SLS_None);
- IO.enumCase(Value, "false", FormatStyle::SLS_None);
- IO.enumCase(Value, "Empty", FormatStyle::SLS_Empty);
- IO.enumCase(Value, "Inline", FormatStyle::SLS_Inline);
- IO.enumCase(Value, "All", FormatStyle::SLS_All);
- IO.enumCase(Value, "true", FormatStyle::SLS_All);
+template <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> {
+ static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) {
+ IO.enumCase(Value, "All", FormatStyle::BOS_All);
+ IO.enumCase(Value, "true", FormatStyle::BOS_All);
+ IO.enumCase(Value, "None", FormatStyle::BOS_None);
+ IO.enumCase(Value, "false", FormatStyle::BOS_None);
+ IO.enumCase(Value, "NonAssignment", FormatStyle::BOS_NonAssignment);
}
};
@@ -247,20 +148,14 @@ template <> struct ScalarEnumerationTraits<FormatStyle::BinPackStyle> {
}
};
-template <> struct ScalarEnumerationTraits<FormatStyle::TrailingCommaStyle> {
- static void enumeration(IO &IO, FormatStyle::TrailingCommaStyle &Value) {
- IO.enumCase(Value, "None", FormatStyle::TCS_None);
- IO.enumCase(Value, "Wrapped", FormatStyle::TCS_Wrapped);
- }
-};
-
-template <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> {
- static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) {
- IO.enumCase(Value, "All", FormatStyle::BOS_All);
- IO.enumCase(Value, "true", FormatStyle::BOS_All);
- IO.enumCase(Value, "None", FormatStyle::BOS_None);
- IO.enumCase(Value, "false", FormatStyle::BOS_None);
- IO.enumCase(Value, "NonAssignment", FormatStyle::BOS_NonAssignment);
+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);
}
};
@@ -278,6 +173,42 @@ template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
}
};
+template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
+ static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) {
+ IO.mapOptional("AfterCaseLabel", Wrapping.AfterCaseLabel);
+ IO.mapOptional("AfterClass", Wrapping.AfterClass);
+ IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement);
+ IO.mapOptional("AfterEnum", Wrapping.AfterEnum);
+ IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock);
+ IO.mapOptional("AfterFunction", Wrapping.AfterFunction);
+ IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace);
+ IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);
+ IO.mapOptional("AfterStruct", Wrapping.AfterStruct);
+ IO.mapOptional("AfterUnion", Wrapping.AfterUnion);
+ IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);
+ IO.mapOptional("BeforeElse", Wrapping.BeforeElse);
+ IO.mapOptional("BeforeLambdaBody", Wrapping.BeforeLambdaBody);
+ IO.mapOptional("BeforeWhile", Wrapping.BeforeWhile);
+ IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
+ IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction);
+ IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord);
+ IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace);
+ }
+};
+
+template <> struct ScalarEnumerationTraits<FormatStyle::BracketAlignmentStyle> {
+ static void enumeration(IO &IO, FormatStyle::BracketAlignmentStyle &Value) {
+ IO.enumCase(Value, "Align", FormatStyle::BAS_Align);
+ IO.enumCase(Value, "DontAlign", FormatStyle::BAS_DontAlign);
+ IO.enumCase(Value, "AlwaysBreak", FormatStyle::BAS_AlwaysBreak);
+ IO.enumCase(Value, "BlockIndent", FormatStyle::BAS_BlockIndent);
+
+ // For backward compatibility.
+ IO.enumCase(Value, "true", FormatStyle::BAS_Align);
+ IO.enumCase(Value, "false", FormatStyle::BAS_DontAlign);
+ }
+};
+
template <>
struct ScalarEnumerationTraits<
FormatStyle::BraceWrappingAfterControlStatementStyle> {
@@ -310,6 +241,15 @@ struct ScalarEnumerationTraits<
};
template <>
+struct ScalarEnumerationTraits<FormatStyle::BreakBeforeInlineASMColonStyle> {
+ static void enumeration(IO &IO,
+ FormatStyle::BreakBeforeInlineASMColonStyle &Value) {
+ IO.enumCase(Value, "Never", FormatStyle::BBIAS_Never);
+ IO.enumCase(Value, "OnlyMultiline", FormatStyle::BBIAS_OnlyMultiline);
+ IO.enumCase(Value, "Always", FormatStyle::BBIAS_Always);
+ }
+};
+template <>
struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
static void
enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) {
@@ -331,13 +271,44 @@ struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> {
};
template <>
-struct ScalarEnumerationTraits<FormatStyle::PackConstructorInitializersStyle> {
+struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> {
+ static void enumeration(IO &IO,
+ FormatStyle::BreakTemplateDeclarationsStyle &Value) {
+ IO.enumCase(Value, "No", FormatStyle::BTDS_No);
+ IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine);
+ IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes);
+
+ // For backward compatibility.
+ IO.enumCase(Value, "false", FormatStyle::BTDS_MultiLine);
+ IO.enumCase(Value, "true", FormatStyle::BTDS_Yes);
+ }
+};
+
+template <>
+struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {
static void
- enumeration(IO &IO, FormatStyle::PackConstructorInitializersStyle &Value) {
- IO.enumCase(Value, "Never", FormatStyle::PCIS_Never);
- IO.enumCase(Value, "BinPack", FormatStyle::PCIS_BinPack);
- IO.enumCase(Value, "CurrentLine", FormatStyle::PCIS_CurrentLine);
- IO.enumCase(Value, "NextLine", FormatStyle::PCIS_NextLine);
+ enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) {
+ IO.enumCase(Value, "None", FormatStyle::DRTBS_None);
+ IO.enumCase(Value, "All", FormatStyle::DRTBS_All);
+ IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel);
+
+ // For backward compatibility.
+ IO.enumCase(Value, "false", FormatStyle::DRTBS_None);
+ IO.enumCase(Value, "true", FormatStyle::DRTBS_All);
+ }
+};
+
+template <>
+struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> {
+ static void enumeration(IO &IO,
+ FormatStyle::EscapedNewlineAlignmentStyle &Value) {
+ IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign);
+ IO.enumCase(Value, "Left", FormatStyle::ENAS_Left);
+ IO.enumCase(Value, "Right", FormatStyle::ENAS_Right);
+
+ // For backward compatibility.
+ IO.enumCase(Value, "true", FormatStyle::ENAS_Left);
+ IO.enumCase(Value, "false", FormatStyle::ENAS_Right);
}
};
@@ -364,15 +335,6 @@ struct ScalarEnumerationTraits<
};
template <>
-struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> {
- static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) {
- IO.enumCase(Value, "None", FormatStyle::PPDIS_None);
- IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash);
- IO.enumCase(Value, "BeforeHash", FormatStyle::PPDIS_BeforeHash);
- }
-};
-
-template <>
struct ScalarEnumerationTraits<FormatStyle::IndentExternBlockStyle> {
static void enumeration(IO &IO, FormatStyle::IndentExternBlockStyle &Value) {
IO.enumCase(Value, "AfterExternBlock", FormatStyle::IEBS_AfterExternBlock);
@@ -383,80 +345,80 @@ struct ScalarEnumerationTraits<FormatStyle::IndentExternBlockStyle> {
}
};
-template <>
-struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {
- static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) {
- IO.enumCase(Value, "None", FormatStyle::RTBS_None);
- IO.enumCase(Value, "All", FormatStyle::RTBS_All);
- IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel);
- IO.enumCase(Value, "TopLevelDefinitions",
- FormatStyle::RTBS_TopLevelDefinitions);
- IO.enumCase(Value, "AllDefinitions", FormatStyle::RTBS_AllDefinitions);
+template <> struct MappingTraits<FormatStyle::IntegerLiteralSeparatorStyle> {
+ static void mapping(IO &IO, FormatStyle::IntegerLiteralSeparatorStyle &Base) {
+ IO.mapOptional("Binary", Base.Binary);
+ IO.mapOptional("Decimal", Base.Decimal);
+ IO.mapOptional("Hex", Base.Hex);
}
};
-template <>
-struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> {
- static void enumeration(IO &IO,
- FormatStyle::BreakTemplateDeclarationsStyle &Value) {
- IO.enumCase(Value, "No", FormatStyle::BTDS_No);
- IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine);
- IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes);
+template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> {
+ static void enumeration(IO &IO, FormatStyle::JavaScriptQuoteStyle &Value) {
+ IO.enumCase(Value, "Leave", FormatStyle::JSQS_Leave);
+ IO.enumCase(Value, "Single", FormatStyle::JSQS_Single);
+ IO.enumCase(Value, "Double", FormatStyle::JSQS_Double);
+ }
+};
- // For backward compatibility.
- IO.enumCase(Value, "false", FormatStyle::BTDS_MultiLine);
- IO.enumCase(Value, "true", FormatStyle::BTDS_Yes);
+template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
+ static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) {
+ IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp);
+ IO.enumCase(Value, "Java", FormatStyle::LK_Java);
+ IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript);
+ IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC);
+ IO.enumCase(Value, "Proto", FormatStyle::LK_Proto);
+ IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen);
+ IO.enumCase(Value, "TextProto", FormatStyle::LK_TextProto);
+ IO.enumCase(Value, "CSharp", FormatStyle::LK_CSharp);
+ IO.enumCase(Value, "Json", FormatStyle::LK_Json);
}
};
-template <>
-struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {
- static void
- enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) {
- IO.enumCase(Value, "None", FormatStyle::DRTBS_None);
- IO.enumCase(Value, "All", FormatStyle::DRTBS_All);
- IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel);
+template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> {
+ static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) {
+ IO.enumCase(Value, "c++03", FormatStyle::LS_Cpp03);
+ IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03); // Legacy alias
+ IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03); // Legacy alias
- // For backward compatibility.
- IO.enumCase(Value, "false", FormatStyle::DRTBS_None);
- IO.enumCase(Value, "true", FormatStyle::DRTBS_All);
+ IO.enumCase(Value, "c++11", FormatStyle::LS_Cpp11);
+ IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11); // Legacy alias
+
+ IO.enumCase(Value, "c++14", FormatStyle::LS_Cpp14);
+ IO.enumCase(Value, "c++17", FormatStyle::LS_Cpp17);
+ IO.enumCase(Value, "c++20", FormatStyle::LS_Cpp20);
+
+ IO.enumCase(Value, "Latest", FormatStyle::LS_Latest);
+ IO.enumCase(Value, "Cpp11", FormatStyle::LS_Latest); // Legacy alias
+ IO.enumCase(Value, "Auto", FormatStyle::LS_Auto);
}
};
template <>
-struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> {
+struct ScalarEnumerationTraits<FormatStyle::LambdaBodyIndentationKind> {
static void enumeration(IO &IO,
- FormatStyle::NamespaceIndentationKind &Value) {
- IO.enumCase(Value, "None", FormatStyle::NI_None);
- IO.enumCase(Value, "Inner", FormatStyle::NI_Inner);
- IO.enumCase(Value, "All", FormatStyle::NI_All);
+ FormatStyle::LambdaBodyIndentationKind &Value) {
+ IO.enumCase(Value, "Signature", FormatStyle::LBI_Signature);
+ IO.enumCase(Value, "OuterScope", FormatStyle::LBI_OuterScope);
}
};
-template <> struct ScalarEnumerationTraits<FormatStyle::BracketAlignmentStyle> {
- static void enumeration(IO &IO, FormatStyle::BracketAlignmentStyle &Value) {
- IO.enumCase(Value, "Align", FormatStyle::BAS_Align);
- IO.enumCase(Value, "DontAlign", FormatStyle::BAS_DontAlign);
- IO.enumCase(Value, "AlwaysBreak", FormatStyle::BAS_AlwaysBreak);
- IO.enumCase(Value, "BlockIndent", FormatStyle::BAS_BlockIndent);
-
- // For backward compatibility.
- IO.enumCase(Value, "true", FormatStyle::BAS_Align);
- IO.enumCase(Value, "false", FormatStyle::BAS_DontAlign);
+template <> struct ScalarEnumerationTraits<FormatStyle::LineEndingStyle> {
+ static void enumeration(IO &IO, FormatStyle::LineEndingStyle &Value) {
+ IO.enumCase(Value, "LF", FormatStyle::LE_LF);
+ IO.enumCase(Value, "CRLF", FormatStyle::LE_CRLF);
+ IO.enumCase(Value, "DeriveLF", FormatStyle::LE_DeriveLF);
+ IO.enumCase(Value, "DeriveCRLF", FormatStyle::LE_DeriveCRLF);
}
};
template <>
-struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> {
+struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> {
static void enumeration(IO &IO,
- FormatStyle::EscapedNewlineAlignmentStyle &Value) {
- IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign);
- IO.enumCase(Value, "Left", FormatStyle::ENAS_Left);
- IO.enumCase(Value, "Right", FormatStyle::ENAS_Right);
-
- // For backward compatibility.
- IO.enumCase(Value, "true", FormatStyle::ENAS_Left);
- IO.enumCase(Value, "false", FormatStyle::ENAS_Right);
+ FormatStyle::NamespaceIndentationKind &Value) {
+ IO.enumCase(Value, "None", FormatStyle::NI_None);
+ IO.enumCase(Value, "Inner", FormatStyle::NI_Inner);
+ IO.enumCase(Value, "All", FormatStyle::NI_All);
}
};
@@ -473,6 +435,17 @@ template <> struct ScalarEnumerationTraits<FormatStyle::OperandAlignmentStyle> {
}
};
+template <>
+struct ScalarEnumerationTraits<FormatStyle::PackConstructorInitializersStyle> {
+ static void
+ enumeration(IO &IO, FormatStyle::PackConstructorInitializersStyle &Value) {
+ IO.enumCase(Value, "Never", FormatStyle::PCIS_Never);
+ IO.enumCase(Value, "BinPack", FormatStyle::PCIS_BinPack);
+ IO.enumCase(Value, "CurrentLine", FormatStyle::PCIS_CurrentLine);
+ IO.enumCase(Value, "NextLine", FormatStyle::PCIS_NextLine);
+ }
+};
+
template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) {
IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle);
@@ -486,22 +459,31 @@ template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
};
template <>
-struct ScalarEnumerationTraits<FormatStyle::SeparateDefinitionStyle> {
- static void enumeration(IO &IO, FormatStyle::SeparateDefinitionStyle &Value) {
- IO.enumCase(Value, "Leave", FormatStyle::SDS_Leave);
- IO.enumCase(Value, "Always", FormatStyle::SDS_Always);
- IO.enumCase(Value, "Never", FormatStyle::SDS_Never);
+struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> {
+ static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) {
+ IO.enumCase(Value, "None", FormatStyle::PPDIS_None);
+ IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash);
+ IO.enumCase(Value, "BeforeHash", FormatStyle::PPDIS_BeforeHash);
}
};
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);
+struct ScalarEnumerationTraits<FormatStyle::QualifierAlignmentStyle> {
+ static void enumeration(IO &IO, FormatStyle::QualifierAlignmentStyle &Value) {
+ IO.enumCase(Value, "Leave", FormatStyle::QAS_Leave);
+ IO.enumCase(Value, "Left", FormatStyle::QAS_Left);
+ IO.enumCase(Value, "Right", FormatStyle::QAS_Right);
+ IO.enumCase(Value, "Custom", FormatStyle::QAS_Custom);
+ }
+};
+
+template <> struct MappingTraits<FormatStyle::RawStringFormat> {
+ static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
+ IO.mapOptional("Language", Format.Language);
+ IO.mapOptional("Delimiters", Format.Delimiters);
+ IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions);
+ IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter);
+ IO.mapOptional("BasedOnStyle", Format.BasedOnStyle);
}
};
@@ -527,34 +509,79 @@ struct ScalarEnumerationTraits<FormatStyle::RequiresClausePositionStyle> {
};
template <>
-struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensStyle> {
- static void enumeration(IO &IO, FormatStyle::SpaceBeforeParensStyle &Value) {
- IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
- IO.enumCase(Value, "ControlStatements",
- FormatStyle::SBPO_ControlStatements);
- IO.enumCase(Value, "ControlStatementsExceptControlMacros",
- FormatStyle::SBPO_ControlStatementsExceptControlMacros);
- IO.enumCase(Value, "NonEmptyParentheses",
- FormatStyle::SBPO_NonEmptyParentheses);
- IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);
- IO.enumCase(Value, "Custom", FormatStyle::SBPO_Custom);
+struct ScalarEnumerationTraits<FormatStyle::RequiresExpressionIndentationKind> {
+ static void
+ enumeration(IO &IO, FormatStyle::RequiresExpressionIndentationKind &Value) {
+ IO.enumCase(Value, "Keyword", FormatStyle::REI_Keyword);
+ IO.enumCase(Value, "OuterScope", FormatStyle::REI_OuterScope);
+ }
+};
- // For backward compatibility.
- IO.enumCase(Value, "false", FormatStyle::SBPO_Never);
- IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements);
- IO.enumCase(Value, "ControlStatementsExceptForEachMacros",
- FormatStyle::SBPO_ControlStatementsExceptControlMacros);
+template <>
+struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {
+ static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) {
+ IO.enumCase(Value, "None", FormatStyle::RTBS_None);
+ IO.enumCase(Value, "All", FormatStyle::RTBS_All);
+ IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel);
+ IO.enumCase(Value, "TopLevelDefinitions",
+ FormatStyle::RTBS_TopLevelDefinitions);
+ IO.enumCase(Value, "AllDefinitions", FormatStyle::RTBS_AllDefinitions);
}
};
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);
+struct ScalarEnumerationTraits<FormatStyle::SeparateDefinitionStyle> {
+ static void enumeration(IO &IO, FormatStyle::SeparateDefinitionStyle &Value) {
+ IO.enumCase(Value, "Leave", FormatStyle::SDS_Leave);
+ IO.enumCase(Value, "Always", FormatStyle::SDS_Always);
+ IO.enumCase(Value, "Never", FormatStyle::SDS_Never);
+ }
+};
+
+template <> struct ScalarEnumerationTraits<FormatStyle::ShortBlockStyle> {
+ static void enumeration(IO &IO, FormatStyle::ShortBlockStyle &Value) {
+ IO.enumCase(Value, "Never", FormatStyle::SBS_Never);
+ IO.enumCase(Value, "false", FormatStyle::SBS_Never);
+ IO.enumCase(Value, "Always", FormatStyle::SBS_Always);
+ IO.enumCase(Value, "true", FormatStyle::SBS_Always);
+ IO.enumCase(Value, "Empty", FormatStyle::SBS_Empty);
+ }
+};
+
+template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
+ static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) {
+ IO.enumCase(Value, "None", FormatStyle::SFS_None);
+ IO.enumCase(Value, "false", FormatStyle::SFS_None);
+ IO.enumCase(Value, "All", FormatStyle::SFS_All);
+ IO.enumCase(Value, "true", FormatStyle::SFS_All);
+ IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline);
+ IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly);
+ IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty);
+ }
+};
+
+template <> struct ScalarEnumerationTraits<FormatStyle::ShortIfStyle> {
+ static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value) {
+ IO.enumCase(Value, "Never", FormatStyle::SIS_Never);
+ IO.enumCase(Value, "WithoutElse", FormatStyle::SIS_WithoutElse);
+ IO.enumCase(Value, "OnlyFirstIf", FormatStyle::SIS_OnlyFirstIf);
+ IO.enumCase(Value, "AllIfsAndElse", FormatStyle::SIS_AllIfsAndElse);
+
+ // For backward compatibility.
+ IO.enumCase(Value, "Always", FormatStyle::SIS_OnlyFirstIf);
+ IO.enumCase(Value, "false", FormatStyle::SIS_Never);
+ IO.enumCase(Value, "true", FormatStyle::SIS_WithoutElse);
+ }
+};
+
+template <> struct ScalarEnumerationTraits<FormatStyle::ShortLambdaStyle> {
+ static void enumeration(IO &IO, FormatStyle::ShortLambdaStyle &Value) {
+ IO.enumCase(Value, "None", FormatStyle::SLS_None);
+ IO.enumCase(Value, "false", FormatStyle::SLS_None);
+ IO.enumCase(Value, "Empty", FormatStyle::SLS_Empty);
+ IO.enumCase(Value, "Inline", FormatStyle::SLS_Inline);
+ IO.enumCase(Value, "All", FormatStyle::SLS_All);
+ IO.enumCase(Value, "true", FormatStyle::SLS_All);
}
};
@@ -579,6 +606,71 @@ struct ScalarEnumerationTraits<FormatStyle::SortJavaStaticImportOptions> {
}
};
+template <>
+struct ScalarEnumerationTraits<FormatStyle::SortUsingDeclarationsOptions> {
+ static void enumeration(IO &IO,
+ FormatStyle::SortUsingDeclarationsOptions &Value) {
+ IO.enumCase(Value, "Never", FormatStyle::SUD_Never);
+ IO.enumCase(Value, "Lexicographic", FormatStyle::SUD_Lexicographic);
+ IO.enumCase(Value, "LexicographicNumeric",
+ FormatStyle::SUD_LexicographicNumeric);
+
+ // For backward compatibility.
+ IO.enumCase(Value, "false", FormatStyle::SUD_Never);
+ IO.enumCase(Value, "true", FormatStyle::SUD_LexicographicNumeric);
+ }
+};
+
+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 MappingTraits<FormatStyle::SpaceBeforeParensCustom> {
+ static void mapping(IO &IO, FormatStyle::SpaceBeforeParensCustom &Spacing) {
+ IO.mapOptional("AfterControlStatements", Spacing.AfterControlStatements);
+ IO.mapOptional("AfterForeachMacros", Spacing.AfterForeachMacros);
+ IO.mapOptional("AfterFunctionDefinitionName",
+ Spacing.AfterFunctionDefinitionName);
+ IO.mapOptional("AfterFunctionDeclarationName",
+ Spacing.AfterFunctionDeclarationName);
+ IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros);
+ IO.mapOptional("AfterOverloadedOperator", Spacing.AfterOverloadedOperator);
+ IO.mapOptional("AfterRequiresInClause", Spacing.AfterRequiresInClause);
+ IO.mapOptional("AfterRequiresInExpression",
+ Spacing.AfterRequiresInExpression);
+ IO.mapOptional("BeforeNonEmptyParentheses",
+ Spacing.BeforeNonEmptyParentheses);
+ }
+};
+
+template <>
+struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensStyle> {
+ static void enumeration(IO &IO, FormatStyle::SpaceBeforeParensStyle &Value) {
+ IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
+ IO.enumCase(Value, "ControlStatements",
+ FormatStyle::SBPO_ControlStatements);
+ IO.enumCase(Value, "ControlStatementsExceptControlMacros",
+ FormatStyle::SBPO_ControlStatementsExceptControlMacros);
+ IO.enumCase(Value, "NonEmptyParentheses",
+ FormatStyle::SBPO_NonEmptyParentheses);
+ IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);
+ IO.enumCase(Value, "Custom", FormatStyle::SBPO_Custom);
+
+ // For backward compatibility.
+ IO.enumCase(Value, "false", FormatStyle::SBPO_Never);
+ IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements);
+ IO.enumCase(Value, "ControlStatementsExceptForEachMacros",
+ FormatStyle::SBPO_ControlStatementsExceptControlMacros);
+ }
+};
+
template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInAnglesStyle> {
static void enumeration(IO &IO, FormatStyle::SpacesInAnglesStyle &Value) {
IO.enumCase(Value, "Never", FormatStyle::SIAS_Never);
@@ -591,11 +683,86 @@ template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInAnglesStyle> {
}
};
+template <> struct MappingTraits<FormatStyle::SpacesInLineComment> {
+ static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) {
+ // Transform the maximum to signed, to parse "-1" correctly
+ int signedMaximum = static_cast<int>(Space.Maximum);
+ IO.mapOptional("Minimum", Space.Minimum);
+ IO.mapOptional("Maximum", signedMaximum);
+ Space.Maximum = static_cast<unsigned>(signedMaximum);
+
+ if (Space.Maximum != -1u)
+ Space.Minimum = std::min(Space.Minimum, Space.Maximum);
+ }
+};
+
+template <> struct ScalarEnumerationTraits<FormatStyle::TrailingCommaStyle> {
+ static void enumeration(IO &IO, FormatStyle::TrailingCommaStyle &Value) {
+ IO.enumCase(Value, "None", FormatStyle::TCS_None);
+ IO.enumCase(Value, "Wrapped", FormatStyle::TCS_Wrapped);
+ }
+};
+
+template <>
+struct ScalarEnumerationTraits<FormatStyle::TrailingCommentsAlignmentKinds> {
+ static void enumeration(IO &IO,
+ FormatStyle::TrailingCommentsAlignmentKinds &Value) {
+ IO.enumCase(Value, "Leave", FormatStyle::TCAS_Leave);
+ IO.enumCase(Value, "Always", FormatStyle::TCAS_Always);
+ IO.enumCase(Value, "Never", FormatStyle::TCAS_Never);
+ }
+};
+
+template <> struct MappingTraits<FormatStyle::TrailingCommentsAlignmentStyle> {
+ static void enumInput(IO &IO,
+ FormatStyle::TrailingCommentsAlignmentStyle &Value) {
+ IO.enumCase(Value, "Leave",
+ FormatStyle::TrailingCommentsAlignmentStyle(
+ {FormatStyle::TCAS_Leave, 1}));
+
+ IO.enumCase(Value, "Always",
+ FormatStyle::TrailingCommentsAlignmentStyle(
+ {FormatStyle::TCAS_Always, 1}));
+
+ IO.enumCase(Value, "Never",
+ FormatStyle::TrailingCommentsAlignmentStyle(
+ {FormatStyle::TCAS_Never, 1}));
+
+ // For backwards compatibility
+ IO.enumCase(Value, "true",
+ FormatStyle::TrailingCommentsAlignmentStyle(
+ {FormatStyle::TCAS_Always, 1}));
+ IO.enumCase(Value, "false",
+ FormatStyle::TrailingCommentsAlignmentStyle(
+ {FormatStyle::TCAS_Never, 1}));
+ }
+
+ static void mapping(IO &IO,
+ FormatStyle::TrailingCommentsAlignmentStyle &Value) {
+ IO.mapOptional("Kind", Value.Kind);
+ IO.mapOptional("OverEmptyLines", Value.OverEmptyLines);
+ }
+};
+
+template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> {
+ static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) {
+ IO.enumCase(Value, "Never", FormatStyle::UT_Never);
+ IO.enumCase(Value, "false", FormatStyle::UT_Never);
+ IO.enumCase(Value, "Always", FormatStyle::UT_Always);
+ IO.enumCase(Value, "true", FormatStyle::UT_Always);
+ IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation);
+ IO.enumCase(Value, "ForContinuationAndIndentation",
+ FormatStyle::UT_ForContinuationAndIndentation);
+ IO.enumCase(Value, "AlignWithSpaces", FormatStyle::UT_AlignWithSpaces);
+ }
+};
+
template <> struct MappingTraits<FormatStyle> {
static void mapping(IO &IO, FormatStyle &Style) {
// When reading, read the language first, we need it for getPredefinedStyle.
IO.mapOptional("Language", Style.Language);
+ StringRef BasedOnStyle;
if (IO.outputting()) {
StringRef Styles[] = {"LLVM", "Google", "Chromium", "Mozilla",
"WebKit", "GNU", "Microsoft"};
@@ -604,11 +771,11 @@ template <> struct MappingTraits<FormatStyle> {
if (getPredefinedStyle(StyleName, Style.Language, &PredefinedStyle) &&
Style == PredefinedStyle) {
IO.mapOptional("# BasedOnStyle", StyleName);
+ BasedOnStyle = StyleName;
break;
}
}
} else {
- StringRef BasedOnStyle;
IO.mapOptional("BasedOnStyle", BasedOnStyle);
if (!BasedOnStyle.empty()) {
FormatStyle::LanguageKind OldLanguage = Style.Language;
@@ -622,9 +789,39 @@ template <> struct MappingTraits<FormatStyle> {
}
}
+ // Initialize some variables used in the parsing. The using logic is at the
+ // end.
+
+ // For backward compatibility:
+ // The default value of ConstructorInitializerAllOnOneLineOrOnePerLine was
+ // false unless BasedOnStyle was Google or Chromium whereas that of
+ // AllowAllConstructorInitializersOnNextLine was always true, so the
+ // equivalent default value of PackConstructorInitializers is PCIS_NextLine
+ // for Google/Chromium or PCIS_BinPack otherwise. If the deprecated options
+ // had a non-default value while PackConstructorInitializers has a default
+ // value, set the latter to an equivalent non-default value if needed.
+ const bool IsGoogleOrChromium = BasedOnStyle.equals_insensitive("google") ||
+ BasedOnStyle.equals_insensitive("chromium");
+ bool OnCurrentLine = IsGoogleOrChromium;
+ bool OnNextLine = true;
+
+ bool BreakBeforeInheritanceComma = false;
+ bool BreakConstructorInitializersBeforeComma = false;
+
+ bool DeriveLineEnding = true;
+ bool UseCRLF = false;
+
// For backward compatibility.
if (!IO.outputting()) {
IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlines);
+ IO.mapOptional("AllowAllConstructorInitializersOnNextLine", OnNextLine);
+ IO.mapOptional("BreakBeforeInheritanceComma",
+ BreakBeforeInheritanceComma);
+ IO.mapOptional("BreakConstructorInitializersBeforeComma",
+ BreakConstructorInitializersBeforeComma);
+ IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",
+ OnCurrentLine);
+ IO.mapOptional("DeriveLineEnding", DeriveLineEnding);
IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment);
IO.mapOptional("IndentFunctionDeclarationAfterType",
Style.IndentWrappedFunctionNames);
@@ -632,6 +829,7 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("PointerBindsToType", Style.PointerAlignment);
IO.mapOptional("SpaceAfterControlStatementKeyword",
Style.SpaceBeforeParens);
+ IO.mapOptional("UseCRLF", UseCRLF);
}
IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);
@@ -651,40 +849,24 @@ template <> struct MappingTraits<FormatStyle> {
Style.AllowAllArgumentsOnNextLine);
IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",
Style.AllowAllParametersOfDeclarationOnNextLine);
- IO.mapOptional("AllowShortEnumsOnASingleLine",
- Style.AllowShortEnumsOnASingleLine);
IO.mapOptional("AllowShortBlocksOnASingleLine",
Style.AllowShortBlocksOnASingleLine);
IO.mapOptional("AllowShortCaseLabelsOnASingleLine",
Style.AllowShortCaseLabelsOnASingleLine);
+ IO.mapOptional("AllowShortEnumsOnASingleLine",
+ Style.AllowShortEnumsOnASingleLine);
IO.mapOptional("AllowShortFunctionsOnASingleLine",
Style.AllowShortFunctionsOnASingleLine);
- IO.mapOptional("AllowShortLambdasOnASingleLine",
- Style.AllowShortLambdasOnASingleLine);
IO.mapOptional("AllowShortIfStatementsOnASingleLine",
Style.AllowShortIfStatementsOnASingleLine);
+ IO.mapOptional("AllowShortLambdasOnASingleLine",
+ Style.AllowShortLambdasOnASingleLine);
IO.mapOptional("AllowShortLoopsOnASingleLine",
Style.AllowShortLoopsOnASingleLine);
IO.mapOptional("AlwaysBreakAfterDefinitionReturnType",
Style.AlwaysBreakAfterDefinitionReturnType);
IO.mapOptional("AlwaysBreakAfterReturnType",
Style.AlwaysBreakAfterReturnType);
-
- // If AlwaysBreakAfterDefinitionReturnType was specified but
- // AlwaysBreakAfterReturnType was not, initialize the latter from the
- // former for backwards compatibility.
- if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None &&
- Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None) {
- if (Style.AlwaysBreakAfterDefinitionReturnType ==
- FormatStyle::DRTBS_All) {
- Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
- } else if (Style.AlwaysBreakAfterDefinitionReturnType ==
- FormatStyle::DRTBS_TopLevel) {
- Style.AlwaysBreakAfterReturnType =
- FormatStyle::RTBS_TopLevelDefinitions;
- }
- }
-
IO.mapOptional("AlwaysBreakBeforeMultilineStrings",
Style.AlwaysBreakBeforeMultilineStrings);
IO.mapOptional("AlwaysBreakTemplateDeclarations",
@@ -692,61 +874,32 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("AttributeMacros", Style.AttributeMacros);
IO.mapOptional("BinPackArguments", Style.BinPackArguments);
IO.mapOptional("BinPackParameters", Style.BinPackParameters);
+ IO.mapOptional("BitFieldColonSpacing", Style.BitFieldColonSpacing);
IO.mapOptional("BraceWrapping", Style.BraceWrapping);
+ IO.mapOptional("BreakAfterAttributes", Style.BreakAfterAttributes);
+ IO.mapOptional("BreakAfterJavaFieldAnnotations",
+ Style.BreakAfterJavaFieldAnnotations);
+ IO.mapOptional("BreakArrays", Style.BreakArrays);
IO.mapOptional("BreakBeforeBinaryOperators",
Style.BreakBeforeBinaryOperators);
IO.mapOptional("BreakBeforeConceptDeclarations",
Style.BreakBeforeConceptDeclarations);
IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
-
- bool BreakBeforeInheritanceComma = false;
- IO.mapOptional("BreakBeforeInheritanceComma", BreakBeforeInheritanceComma);
- IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList);
- // If BreakBeforeInheritanceComma was specified but
- // BreakInheritance was not, initialize the latter from the
- // former for backwards compatibility.
- if (BreakBeforeInheritanceComma &&
- Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon) {
- Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
- }
-
+ IO.mapOptional("BreakBeforeInlineASMColon",
+ Style.BreakBeforeInlineASMColon);
IO.mapOptional("BreakBeforeTernaryOperators",
Style.BreakBeforeTernaryOperators);
-
- bool BreakConstructorInitializersBeforeComma = false;
- IO.mapOptional("BreakConstructorInitializersBeforeComma",
- BreakConstructorInitializersBeforeComma);
IO.mapOptional("BreakConstructorInitializers",
Style.BreakConstructorInitializers);
- // If BreakConstructorInitializersBeforeComma was specified but
- // BreakConstructorInitializers was not, initialize the latter from the
- // former for backwards compatibility.
- if (BreakConstructorInitializersBeforeComma &&
- Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon) {
- Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
- }
-
- IO.mapOptional("BreakAfterJavaFieldAnnotations",
- Style.BreakAfterJavaFieldAnnotations);
+ IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList);
IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals);
IO.mapOptional("ColumnLimit", Style.ColumnLimit);
IO.mapOptional("CommentPragmas", Style.CommentPragmas);
- IO.mapOptional("QualifierAlignment", Style.QualifierAlignment);
-
- // Default Order for Left/Right based Qualifier alignment.
- if (Style.QualifierAlignment == FormatStyle::QAS_Right)
- Style.QualifierOrder = {"type", "const", "volatile"};
- else if (Style.QualifierAlignment == FormatStyle::QAS_Left)
- Style.QualifierOrder = {"const", "volatile", "type"};
- else if (Style.QualifierAlignment == FormatStyle::QAS_Custom)
- IO.mapOptional("QualifierOrder", Style.QualifierOrder);
-
IO.mapOptional("CompactNamespaces", Style.CompactNamespaces);
IO.mapOptional("ConstructorInitializerIndentWidth",
Style.ConstructorInitializerIndentWidth);
IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);
IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle);
- IO.mapOptional("DeriveLineEnding", Style.DeriveLineEnding);
IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment);
IO.mapOptional("DisableFormat", Style.DisableFormat);
IO.mapOptional("EmptyLineAfterAccessModifier",
@@ -755,68 +908,35 @@ template <> struct MappingTraits<FormatStyle> {
Style.EmptyLineBeforeAccessModifier);
IO.mapOptional("ExperimentalAutoDetectBinPacking",
Style.ExperimentalAutoDetectBinPacking);
-
- IO.mapOptional("PackConstructorInitializers",
- Style.PackConstructorInitializers);
- // For backward compatibility:
- // The default value of ConstructorInitializerAllOnOneLineOrOnePerLine was
- // false unless BasedOnStyle was Google or Chromium whereas that of
- // AllowAllConstructorInitializersOnNextLine was always true, so the
- // equivalent default value of PackConstructorInitializers is PCIS_NextLine
- // for Google/Chromium or PCIS_BinPack otherwise. If the deprecated options
- // had a non-default value while PackConstructorInitializers has a default
- // value, set the latter to an equivalent non-default value if needed.
- StringRef BasedOn;
- IO.mapOptional("BasedOnStyle", BasedOn);
- const bool IsGoogleOrChromium = BasedOn.equals_insensitive("google") ||
- BasedOn.equals_insensitive("chromium");
- bool OnCurrentLine = IsGoogleOrChromium;
- bool OnNextLine = true;
- IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",
- OnCurrentLine);
- IO.mapOptional("AllowAllConstructorInitializersOnNextLine", OnNextLine);
- if (!IsGoogleOrChromium) {
- if (Style.PackConstructorInitializers == FormatStyle::PCIS_BinPack &&
- OnCurrentLine) {
- Style.PackConstructorInitializers = OnNextLine
- ? FormatStyle::PCIS_NextLine
- : FormatStyle::PCIS_CurrentLine;
- }
- } else if (Style.PackConstructorInitializers ==
- FormatStyle::PCIS_NextLine) {
- if (!OnCurrentLine)
- Style.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
- else if (!OnNextLine)
- Style.PackConstructorInitializers = FormatStyle::PCIS_CurrentLine;
- }
-
IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments);
IO.mapOptional("ForEachMacros", Style.ForEachMacros);
IO.mapOptional("IfMacros", Style.IfMacros);
-
IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);
IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);
IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);
IO.mapOptional("IncludeIsMainSourceRegex",
Style.IncludeStyle.IncludeIsMainSourceRegex);
IO.mapOptional("IndentAccessModifiers", Style.IndentAccessModifiers);
- IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
IO.mapOptional("IndentCaseBlocks", Style.IndentCaseBlocks);
+ IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
+ IO.mapOptional("IndentExternBlock", Style.IndentExternBlock);
IO.mapOptional("IndentGotoLabels", Style.IndentGotoLabels);
IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives);
- IO.mapOptional("IndentExternBlock", Style.IndentExternBlock);
IO.mapOptional("IndentRequiresClause", Style.IndentRequiresClause);
IO.mapOptional("IndentWidth", Style.IndentWidth);
IO.mapOptional("IndentWrappedFunctionNames",
Style.IndentWrappedFunctionNames);
IO.mapOptional("InsertBraces", Style.InsertBraces);
+ IO.mapOptional("InsertNewlineAtEOF", Style.InsertNewlineAtEOF);
IO.mapOptional("InsertTrailingCommas", Style.InsertTrailingCommas);
+ IO.mapOptional("IntegerLiteralSeparator", Style.IntegerLiteralSeparator);
IO.mapOptional("JavaImportGroups", Style.JavaImportGroups);
IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes);
IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);
IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
Style.KeepEmptyLinesAtTheStartOfBlocks);
IO.mapOptional("LambdaBodyIndentation", Style.LambdaBodyIndentation);
+ IO.mapOptional("LineEnding", Style.LineEnding);
IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin);
IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd);
IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
@@ -829,6 +949,8 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty);
IO.mapOptional("ObjCSpaceBeforeProtocolList",
Style.ObjCSpaceBeforeProtocolList);
+ IO.mapOptional("PackConstructorInitializers",
+ Style.PackConstructorInitializers);
IO.mapOptional("PenaltyBreakAssignment", Style.PenaltyBreakAssignment);
IO.mapOptional("PenaltyBreakBeforeFirstCallParameter",
Style.PenaltyBreakBeforeFirstCallParameter);
@@ -841,17 +963,28 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("PenaltyBreakTemplateDeclaration",
Style.PenaltyBreakTemplateDeclaration);
IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);
- IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
- Style.PenaltyReturnTypeOnItsOwnLine);
IO.mapOptional("PenaltyIndentedWhitespace",
Style.PenaltyIndentedWhitespace);
+ IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
+ Style.PenaltyReturnTypeOnItsOwnLine);
IO.mapOptional("PointerAlignment", Style.PointerAlignment);
IO.mapOptional("PPIndentWidth", Style.PPIndentWidth);
+ IO.mapOptional("QualifierAlignment", Style.QualifierAlignment);
+ // Default Order for Left/Right based Qualifier alignment.
+ if (Style.QualifierAlignment == FormatStyle::QAS_Right)
+ Style.QualifierOrder = {"type", "const", "volatile"};
+ else if (Style.QualifierAlignment == FormatStyle::QAS_Left)
+ Style.QualifierOrder = {"const", "volatile", "type"};
+ else if (Style.QualifierAlignment == FormatStyle::QAS_Custom)
+ IO.mapOptional("QualifierOrder", Style.QualifierOrder);
IO.mapOptional("RawStringFormats", Style.RawStringFormats);
IO.mapOptional("ReferenceAlignment", Style.ReferenceAlignment);
IO.mapOptional("ReflowComments", Style.ReflowComments);
IO.mapOptional("RemoveBracesLLVM", Style.RemoveBracesLLVM);
+ IO.mapOptional("RemoveSemicolon", Style.RemoveSemicolon);
IO.mapOptional("RequiresClausePosition", Style.RequiresClausePosition);
+ IO.mapOptional("RequiresExpressionIndentation",
+ Style.RequiresExpressionIndentation);
IO.mapOptional("SeparateDefinitionBlocks", Style.SeparateDefinitionBlocks);
IO.mapOptional("ShortNamespaceLines", Style.ShortNamespaceLines);
IO.mapOptional("SortIncludes", Style.SortIncludes);
@@ -861,6 +994,8 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("SpaceAfterLogicalNot", Style.SpaceAfterLogicalNot);
IO.mapOptional("SpaceAfterTemplateKeyword",
Style.SpaceAfterTemplateKeyword);
+ IO.mapOptional("SpaceAroundPointerQualifiers",
+ Style.SpaceAroundPointerQualifiers);
IO.mapOptional("SpaceBeforeAssignmentOperators",
Style.SpaceBeforeAssignmentOperators);
IO.mapOptional("SpaceBeforeCaseColon", Style.SpaceBeforeCaseColon);
@@ -872,10 +1007,10 @@ template <> struct MappingTraits<FormatStyle> {
Style.SpaceBeforeInheritanceColon);
IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
IO.mapOptional("SpaceBeforeParensOptions", Style.SpaceBeforeParensOptions);
- IO.mapOptional("SpaceAroundPointerQualifiers",
- Style.SpaceAroundPointerQualifiers);
IO.mapOptional("SpaceBeforeRangeBasedForLoopColon",
Style.SpaceBeforeRangeBasedForLoopColon);
+ IO.mapOptional("SpaceBeforeSquareBrackets",
+ Style.SpaceBeforeSquareBrackets);
IO.mapOptional("SpaceInEmptyBlock", Style.SpaceInEmptyBlock);
IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses);
IO.mapOptional("SpacesBeforeTrailingComments",
@@ -891,83 +1026,67 @@ template <> struct MappingTraits<FormatStyle> {
Style.SpacesInLineCommentPrefix);
IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses);
IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
- IO.mapOptional("SpaceBeforeSquareBrackets",
- Style.SpaceBeforeSquareBrackets);
- IO.mapOptional("BitFieldColonSpacing", Style.BitFieldColonSpacing);
IO.mapOptional("Standard", Style.Standard);
IO.mapOptional("StatementAttributeLikeMacros",
Style.StatementAttributeLikeMacros);
IO.mapOptional("StatementMacros", Style.StatementMacros);
IO.mapOptional("TabWidth", Style.TabWidth);
IO.mapOptional("TypenameMacros", Style.TypenameMacros);
- IO.mapOptional("UseCRLF", Style.UseCRLF);
IO.mapOptional("UseTab", Style.UseTab);
IO.mapOptional("WhitespaceSensitiveMacros",
Style.WhitespaceSensitiveMacros);
- }
-};
-template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
- static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) {
- IO.mapOptional("AfterCaseLabel", Wrapping.AfterCaseLabel);
- IO.mapOptional("AfterClass", Wrapping.AfterClass);
- IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement);
- IO.mapOptional("AfterEnum", Wrapping.AfterEnum);
- IO.mapOptional("AfterFunction", Wrapping.AfterFunction);
- IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace);
- IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);
- IO.mapOptional("AfterStruct", Wrapping.AfterStruct);
- IO.mapOptional("AfterUnion", Wrapping.AfterUnion);
- IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock);
- IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);
- IO.mapOptional("BeforeElse", Wrapping.BeforeElse);
- IO.mapOptional("BeforeLambdaBody", Wrapping.BeforeLambdaBody);
- IO.mapOptional("BeforeWhile", Wrapping.BeforeWhile);
- IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
- IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction);
- IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord);
- IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace);
- }
-};
+ // If AlwaysBreakAfterDefinitionReturnType was specified but
+ // AlwaysBreakAfterReturnType was not, initialize the latter from the
+ // former for backwards compatibility.
+ if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None &&
+ Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None) {
+ if (Style.AlwaysBreakAfterDefinitionReturnType ==
+ FormatStyle::DRTBS_All) {
+ Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
+ } else if (Style.AlwaysBreakAfterDefinitionReturnType ==
+ FormatStyle::DRTBS_TopLevel) {
+ Style.AlwaysBreakAfterReturnType =
+ FormatStyle::RTBS_TopLevelDefinitions;
+ }
+ }
-template <> struct MappingTraits<FormatStyle::SpaceBeforeParensCustom> {
- static void mapping(IO &IO, FormatStyle::SpaceBeforeParensCustom &Spacing) {
- IO.mapOptional("AfterControlStatements", Spacing.AfterControlStatements);
- IO.mapOptional("AfterForeachMacros", Spacing.AfterForeachMacros);
- IO.mapOptional("AfterFunctionDefinitionName",
- Spacing.AfterFunctionDefinitionName);
- IO.mapOptional("AfterFunctionDeclarationName",
- Spacing.AfterFunctionDeclarationName);
- IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros);
- IO.mapOptional("AfterOverloadedOperator", Spacing.AfterOverloadedOperator);
- IO.mapOptional("AfterRequiresInClause", Spacing.AfterRequiresInClause);
- IO.mapOptional("AfterRequiresInExpression",
- Spacing.AfterRequiresInExpression);
- IO.mapOptional("BeforeNonEmptyParentheses",
- Spacing.BeforeNonEmptyParentheses);
- }
-};
+ // If BreakBeforeInheritanceComma was specified but BreakInheritance was
+ // not, initialize the latter from the former for backwards compatibility.
+ if (BreakBeforeInheritanceComma &&
+ Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon) {
+ Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
+ }
-template <> struct MappingTraits<FormatStyle::RawStringFormat> {
- static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
- IO.mapOptional("Language", Format.Language);
- IO.mapOptional("Delimiters", Format.Delimiters);
- IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions);
- IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter);
- IO.mapOptional("BasedOnStyle", Format.BasedOnStyle);
- }
-};
+ // If BreakConstructorInitializersBeforeComma was specified but
+ // BreakConstructorInitializers was not, initialize the latter from the
+ // former for backwards compatibility.
+ if (BreakConstructorInitializersBeforeComma &&
+ Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon) {
+ Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
+ }
-template <> struct MappingTraits<FormatStyle::SpacesInLineComment> {
- static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) {
- // Transform the maximum to signed, to parse "-1" correctly
- int signedMaximum = static_cast<int>(Space.Maximum);
- IO.mapOptional("Minimum", Space.Minimum);
- IO.mapOptional("Maximum", signedMaximum);
- Space.Maximum = static_cast<unsigned>(signedMaximum);
+ if (!IsGoogleOrChromium) {
+ if (Style.PackConstructorInitializers == FormatStyle::PCIS_BinPack &&
+ OnCurrentLine) {
+ Style.PackConstructorInitializers = OnNextLine
+ ? FormatStyle::PCIS_NextLine
+ : FormatStyle::PCIS_CurrentLine;
+ }
+ } else if (Style.PackConstructorInitializers ==
+ FormatStyle::PCIS_NextLine) {
+ if (!OnCurrentLine)
+ Style.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
+ else if (!OnNextLine)
+ Style.PackConstructorInitializers = FormatStyle::PCIS_CurrentLine;
+ }
- if (Space.Maximum != -1u)
- Space.Minimum = std::min(Space.Minimum, Space.Maximum);
+ if (Style.LineEnding == FormatStyle::LE_DeriveLF) {
+ if (!DeriveLineEnding)
+ Style.LineEnding = UseCRLF ? FormatStyle::LE_CRLF : FormatStyle::LE_LF;
+ else if (UseCRLF)
+ Style.LineEnding = FormatStyle::LE_DeriveCRLF;
+ }
}
};
@@ -1181,7 +1300,6 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align;
LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None;
LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
- LLVMStyle.AlignTrailingComments = true;
LLVMStyle.AlignConsecutiveAssignments = {};
LLVMStyle.AlignConsecutiveAssignments.Enabled = false;
LLVMStyle.AlignConsecutiveAssignments.AcrossEmptyLines = false;
@@ -1191,12 +1309,15 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.AlignConsecutiveBitFields = {};
LLVMStyle.AlignConsecutiveDeclarations = {};
LLVMStyle.AlignConsecutiveMacros = {};
+ LLVMStyle.AlignTrailingComments = {};
+ LLVMStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Always;
+ LLVMStyle.AlignTrailingComments.OverEmptyLines = 0;
LLVMStyle.AllowAllArgumentsOnNextLine = true;
LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
- LLVMStyle.AllowShortEnumsOnASingleLine = true;
- LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;
LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;
+ LLVMStyle.AllowShortEnumsOnASingleLine = true;
+ LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
LLVMStyle.AllowShortLoopsOnASingleLine = false;
@@ -1205,12 +1326,9 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
LLVMStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;
LLVMStyle.AttributeMacros.push_back("__capability");
+ LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both;
LLVMStyle.BinPackArguments = true;
LLVMStyle.BinPackParameters = true;
- LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
- LLVMStyle.BreakBeforeConceptDeclarations = FormatStyle::BBCDS_Always;
- LLVMStyle.BreakBeforeTernaryOperators = true;
- LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false,
/*AfterClass=*/false,
/*AfterControlStatement=*/FormatStyle::BWACS_Never,
@@ -1229,8 +1347,14 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
/*SplitEmptyFunction=*/true,
/*SplitEmptyRecord=*/true,
/*SplitEmptyNamespace=*/true};
- LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
+ LLVMStyle.BreakAfterAttributes = FormatStyle::ABS_Never;
LLVMStyle.BreakAfterJavaFieldAnnotations = false;
+ LLVMStyle.BreakArrays = true;
+ LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
+ LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
+ LLVMStyle.BreakBeforeConceptDeclarations = FormatStyle::BBCDS_Always;
+ LLVMStyle.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline;
+ LLVMStyle.BreakBeforeTernaryOperators = true;
LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
LLVMStyle.BreakStringLiterals = true;
@@ -1240,16 +1364,11 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.ConstructorInitializerIndentWidth = 4;
LLVMStyle.ContinuationIndentWidth = 4;
LLVMStyle.Cpp11BracedListStyle = true;
-
- // Off by default Qualifier ordering
- LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave;
-
- LLVMStyle.DeriveLineEnding = true;
LLVMStyle.DerivePointerAlignment = false;
+ LLVMStyle.DisableFormat = false;
LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never;
LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock;
LLVMStyle.ExperimentalAutoDetectBinPacking = false;
- LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
LLVMStyle.FixNamespaceComments = true;
LLVMStyle.ForEachMacros.push_back("foreach");
LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
@@ -1264,44 +1383,43 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.IndentAccessModifiers = false;
LLVMStyle.IndentCaseLabels = false;
LLVMStyle.IndentCaseBlocks = false;
+ LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
LLVMStyle.IndentGotoLabels = true;
LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;
LLVMStyle.IndentRequiresClause = true;
- LLVMStyle.IndentWrappedFunctionNames = false;
LLVMStyle.IndentWidth = 2;
- LLVMStyle.PPIndentWidth = -1;
+ LLVMStyle.IndentWrappedFunctionNames = false;
LLVMStyle.InsertBraces = false;
+ LLVMStyle.InsertNewlineAtEOF = false;
LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None;
+ LLVMStyle.IntegerLiteralSeparator = {/*Binary=*/0, /*Decimal=*/0, /*Hex=*/0};
LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
LLVMStyle.JavaScriptWrapImports = true;
- LLVMStyle.TabWidth = 8;
+ LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true;
LLVMStyle.LambdaBodyIndentation = FormatStyle::LBI_Signature;
+ LLVMStyle.LineEnding = FormatStyle::LE_DeriveLF;
LLVMStyle.MaxEmptyLinesToKeep = 1;
- LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true;
LLVMStyle.NamespaceIndentation = FormatStyle::NI_None;
LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto;
LLVMStyle.ObjCBlockIndentWidth = 2;
LLVMStyle.ObjCBreakBeforeNestedBlockParam = true;
LLVMStyle.ObjCSpaceAfterProperty = false;
LLVMStyle.ObjCSpaceBeforeProtocolList = true;
+ LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
+ LLVMStyle.PPIndentWidth = -1;
+ LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave;
LLVMStyle.ReferenceAlignment = FormatStyle::RAS_Pointer;
+ LLVMStyle.ReflowComments = true;
+ LLVMStyle.RemoveBracesLLVM = false;
+ LLVMStyle.RemoveSemicolon = false;
LLVMStyle.RequiresClausePosition = FormatStyle::RCPS_OwnLine;
+ LLVMStyle.RequiresExpressionIndentation = FormatStyle::REI_OuterScope;
LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave;
LLVMStyle.ShortNamespaceLines = 1;
- LLVMStyle.SpacesBeforeTrailingComments = 1;
- LLVMStyle.Standard = FormatStyle::LS_Latest;
- LLVMStyle.UseCRLF = false;
- LLVMStyle.UseTab = FormatStyle::UT_Never;
- LLVMStyle.ReflowComments = true;
- LLVMStyle.RemoveBracesLLVM = false;
- LLVMStyle.SpacesInParentheses = false;
- LLVMStyle.SpacesInSquareBrackets = false;
- LLVMStyle.SpaceInEmptyBlock = false;
- LLVMStyle.SpaceInEmptyParentheses = false;
- LLVMStyle.SpacesInContainerLiterals = true;
- LLVMStyle.SpacesInCStyleCastParentheses = false;
- LLVMStyle.SpacesInLineCommentPrefix = {/*Minimum=*/1, /*Maximum=*/-1u};
+ LLVMStyle.SortIncludes = FormatStyle::SI_CaseSensitive;
+ LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;
+ LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric;
LLVMStyle.SpaceAfterCStyleCast = false;
LLVMStyle.SpaceAfterLogicalNot = false;
LLVMStyle.SpaceAfterTemplateKeyword = true;
@@ -1318,9 +1436,27 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.SpaceBeforeAssignmentOperators = true;
LLVMStyle.SpaceBeforeCpp11BracedList = false;
LLVMStyle.SpaceBeforeSquareBrackets = false;
- LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both;
+ LLVMStyle.SpaceInEmptyBlock = false;
+ LLVMStyle.SpaceInEmptyParentheses = false;
+ LLVMStyle.SpacesBeforeTrailingComments = 1;
LLVMStyle.SpacesInAngles = FormatStyle::SIAS_Never;
+ LLVMStyle.SpacesInContainerLiterals = true;
+ LLVMStyle.SpacesInCStyleCastParentheses = false;
+ LLVMStyle.SpacesInLineCommentPrefix = {/*Minimum=*/1, /*Maximum=*/-1u};
+ LLVMStyle.SpacesInParentheses = false;
+ LLVMStyle.SpacesInSquareBrackets = false;
LLVMStyle.SpacesInConditionalStatement = false;
+ LLVMStyle.Standard = FormatStyle::LS_Latest;
+ LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT");
+ LLVMStyle.StatementMacros.push_back("Q_UNUSED");
+ LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION");
+ LLVMStyle.TabWidth = 8;
+ LLVMStyle.UseTab = FormatStyle::UT_Never;
+ LLVMStyle.WhitespaceSensitiveMacros.push_back("BOOST_PP_STRINGIZE");
+ LLVMStyle.WhitespaceSensitiveMacros.push_back("CF_SWIFT_NAME");
+ LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME");
+ LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE");
+ LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE");
LLVMStyle.PenaltyBreakAssignment = prec::Assignment;
LLVMStyle.PenaltyBreakComment = 300;
@@ -1333,24 +1469,20 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational;
LLVMStyle.PenaltyIndentedWhitespace = 0;
- LLVMStyle.DisableFormat = false;
- LLVMStyle.SortIncludes = FormatStyle::SI_CaseSensitive;
- 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)
+ switch (Language) {
+ case FormatStyle::LK_TableGen:
LLVMStyle.SpacesInContainerLiterals = false;
- if (LLVMStyle.isJson())
+ break;
+ case FormatStyle::LK_Json:
LLVMStyle.ColumnLimit = 0;
+ break;
+ case FormatStyle::LK_Verilog:
+ LLVMStyle.IndentCaseLabels = true;
+ break;
+ default:
+ break;
+ }
return LLVMStyle;
}
@@ -1438,7 +1570,8 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
if (Language == FormatStyle::LK_Java) {
GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
- GoogleStyle.AlignTrailingComments = false;
+ GoogleStyle.AlignTrailingComments = {};
+ GoogleStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Never;
GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
@@ -1586,7 +1719,8 @@ FormatStyle getWebKitStyle() {
Style.AccessModifierOffset = -4;
Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
Style.AlignOperands = FormatStyle::OAS_DontAlign;
- Style.AlignTrailingComments = false;
+ Style.AlignTrailingComments = {};
+ Style.AlignTrailingComments.Kind = FormatStyle::TCAS_Never;
Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty;
Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
Style.BreakBeforeBraces = FormatStyle::BS_WebKit;
@@ -1653,7 +1787,7 @@ FormatStyle getNoStyle() {
FormatStyle NoStyle = getLLVMStyle();
NoStyle.DisableFormat = true;
NoStyle.SortIncludes = FormatStyle::SI_Never;
- NoStyle.SortUsingDeclarations = false;
+ NoStyle.SortUsingDeclarations = FormatStyle::SUD_Never;
return NoStyle;
}
@@ -1710,9 +1844,7 @@ ParseError validateQualifierOrder(FormatStyle *Style) {
}
// Ensure the list has 'type' in it.
- auto type = std::find(Style->QualifierOrder.begin(),
- Style->QualifierOrder.end(), "type");
- if (type == Style->QualifierOrder.end())
+ if (!llvm::is_contained(Style->QualifierOrder, "type"))
return ParseError::MissingQualifierType;
return ParseError::Success;
@@ -1798,13 +1930,13 @@ std::string configurationAsText(const FormatStyle &Style) {
return Stream.str();
}
-llvm::Optional<FormatStyle>
+std::optional<FormatStyle>
FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const {
if (!Styles)
- return None;
+ return std::nullopt;
auto It = Styles->find(Language);
if (It == Styles->end())
- return None;
+ return std::nullopt;
FormatStyle Style = It->second;
Style.StyleSet = *this;
return Style;
@@ -1823,7 +1955,7 @@ void FormatStyle::FormatStyleSet::Add(FormatStyle Style) {
void FormatStyle::FormatStyleSet::Clear() { Styles.reset(); }
-llvm::Optional<FormatStyle>
+std::optional<FormatStyle>
FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const {
return StyleSet.Get(Language);
}
@@ -1833,9 +1965,7 @@ namespace {
class BracesInserter : public TokenAnalyzer {
public:
BracesInserter(const Environment &Env, const FormatStyle &Style)
- : TokenAnalyzer(Env, Style) {
- this->Style.RemoveBracesLLVM = false;
- }
+ : TokenAnalyzer(Env, Style) {}
std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator &Annotator,
@@ -1851,35 +1981,44 @@ private:
void insertBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
tooling::Replacements &Result) {
const auto &SourceMgr = Env.getSourceManager();
+ int OpeningBraceSurplus = 0;
for (AnnotatedLine *Line : Lines) {
insertBraces(Line->Children, Result);
- if (!Line->Affected)
+ if (!Line->Affected && OpeningBraceSurplus == 0)
continue;
for (FormatToken *Token = Line->First; Token && !Token->Finalized;
Token = Token->Next) {
- if (Token->BraceCount == 0)
+ int BraceCount = Token->BraceCount;
+ if (BraceCount == 0)
continue;
std::string Brace;
- if (Token->BraceCount < 0) {
- assert(Token->BraceCount == -1);
- Brace = '{';
+ if (BraceCount < 0) {
+ assert(BraceCount == -1);
+ if (!Line->Affected)
+ break;
+ Brace = Token->is(tok::comment) ? "\n{" : "{";
+ ++OpeningBraceSurplus;
} else {
- Brace = '\n' + std::string(Token->BraceCount, '}');
+ if (OpeningBraceSurplus == 0)
+ break;
+ if (OpeningBraceSurplus < BraceCount)
+ BraceCount = OpeningBraceSurplus;
+ Brace = '\n' + std::string(BraceCount, '}');
+ OpeningBraceSurplus -= BraceCount;
}
Token->BraceCount = 0;
const auto Start = Token->Tok.getEndLoc();
cantFail(Result.add(tooling::Replacement(SourceMgr, Start, 0, Brace)));
}
}
+ assert(OpeningBraceSurplus == 0);
}
};
class BracesRemover : public TokenAnalyzer {
public:
BracesRemover(const Environment &Env, const FormatStyle &Style)
- : TokenAnalyzer(Env, Style) {
- this->Style.InsertBraces = false;
- }
+ : TokenAnalyzer(Env, Style) {}
std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator &Annotator,
@@ -1895,31 +2034,85 @@ private:
void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
tooling::Replacements &Result) {
const auto &SourceMgr = Env.getSourceManager();
- bool EndsWithComment = false;
- for (AnnotatedLine *Line : Lines) {
+ const auto End = Lines.end();
+ for (auto I = Lines.begin(); I != End; ++I) {
+ const auto Line = *I;
removeBraces(Line->Children, Result);
- if (Line->Affected) {
- for (FormatToken *Token = Line->First; Token && !Token->Finalized;
- Token = Token->Next) {
- if (!Token->Optional)
- continue;
- assert(Token->isOneOf(tok::l_brace, tok::r_brace));
- assert(Token->Previous || Token == Line->First);
- const FormatToken *Next = Token->Next;
- assert(Next || Token == Line->Last);
- const auto Start =
- (!Token->Previous && EndsWithComment) ||
- (Next && !(Next->isOneOf(tok::kw_else, tok::comment) &&
- Next->NewlinesBefore > 0))
- ? Token->Tok.getLocation()
- : Token->WhitespaceRange.getBegin();
- const auto Range =
- CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
- cantFail(Result.add(tooling::Replacement(SourceMgr, Range, "")));
+ if (!Line->Affected)
+ continue;
+ const auto NextLine = I + 1 == End ? nullptr : I[1];
+ for (auto Token = Line->First; Token && !Token->Finalized;
+ Token = Token->Next) {
+ if (!Token->Optional)
+ continue;
+ if (!Token->isOneOf(tok::l_brace, tok::r_brace))
+ continue;
+ auto Next = Token->Next;
+ assert(Next || Token == Line->Last);
+ if (!Next && NextLine)
+ Next = NextLine->First;
+ SourceLocation Start;
+ if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {
+ Start = Token->Tok.getLocation();
+ Next->WhitespaceRange = Token->WhitespaceRange;
+ } else {
+ Start = Token->WhitespaceRange.getBegin();
}
+ const auto Range =
+ CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
+ cantFail(Result.add(tooling::Replacement(SourceMgr, Range, "")));
+ }
+ }
+ }
+};
+
+class SemiRemover : public TokenAnalyzer {
+public:
+ SemiRemover(const Environment &Env, const FormatStyle &Style)
+ : TokenAnalyzer(Env, Style) {}
+
+ std::pair<tooling::Replacements, unsigned>
+ analyze(TokenAnnotator &Annotator,
+ SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
+ FormatTokenLexer &Tokens) override {
+ AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
+ tooling::Replacements Result;
+ removeSemi(AnnotatedLines, Result);
+ return {Result, 0};
+ }
+
+private:
+ void removeSemi(SmallVectorImpl<AnnotatedLine *> &Lines,
+ tooling::Replacements &Result) {
+ const auto &SourceMgr = Env.getSourceManager();
+ const auto End = Lines.end();
+ for (auto I = Lines.begin(); I != End; ++I) {
+ const auto Line = *I;
+ removeSemi(Line->Children, Result);
+ if (!Line->Affected)
+ continue;
+ const auto NextLine = I + 1 == End ? nullptr : I[1];
+ for (auto Token = Line->First; Token && !Token->Finalized;
+ Token = Token->Next) {
+ if (!Token->Optional)
+ continue;
+ if (Token->isNot(tok::semi))
+ continue;
+ auto Next = Token->Next;
+ assert(Next || Token == Line->Last);
+ if (!Next && NextLine)
+ Next = NextLine->First;
+ SourceLocation Start;
+ if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {
+ Start = Token->Tok.getLocation();
+ Next->WhitespaceRange = Token->WhitespaceRange;
+ } else {
+ Start = Token->WhitespaceRange.getBegin();
+ }
+ const auto Range =
+ CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
+ cantFail(Result.add(tooling::Replacement(SourceMgr, Range, "")));
}
- assert(Line->Last);
- EndsWithComment = Line->Last->is(tok::comment);
}
}
};
@@ -2031,11 +2224,11 @@ public:
WhitespaceManager Whitespaces(
Env.getSourceManager(), Style,
- Style.DeriveLineEnding
+ Style.LineEnding > FormatStyle::LE_CRLF
? WhitespaceManager::inputUsesCRLF(
Env.getSourceManager().getBufferData(Env.getFileID()),
- Style.UseCRLF)
- : Style.UseCRLF);
+ Style.LineEnding == FormatStyle::LE_DeriveCRLF)
+ : Style.LineEnding == FormatStyle::LE_CRLF);
ContinuationIndenter Indenter(Style, Tokens.getKeywords(),
Env.getSourceManager(), Whitespaces, Encoding,
BinPackInconclusiveFunctions);
@@ -2123,9 +2316,11 @@ private:
}
}
if (Style.DerivePointerAlignment) {
- Style.PointerAlignment = countVariableAlignments(AnnotatedLines) <= 0
- ? FormatStyle::PAS_Left
- : FormatStyle::PAS_Right;
+ const auto NetRightCount = countVariableAlignments(AnnotatedLines);
+ if (NetRightCount > 0)
+ Style.PointerAlignment = FormatStyle::PAS_Right;
+ else if (NetRightCount < 0)
+ Style.PointerAlignment = FormatStyle::PAS_Left;
Style.ReferenceAlignment = FormatStyle::RAS_Pointer;
}
if (Style.Standard == FormatStyle::LS_Auto) {
@@ -2533,7 +2728,7 @@ private:
"UIView",
};
- for (auto Line : AnnotatedLines) {
+ for (auto *Line : AnnotatedLines) {
if (Line->First && (Line->First->TokenText.startswith("#") ||
Line->First->TokenText == "__pragma" ||
Line->First->TokenText == "_Pragma")) {
@@ -2758,13 +2953,6 @@ static void sortCppIncludes(const FormatStyle &Style,
}
}
-namespace {
-
-const char CppIncludeRegexPattern[] =
- R"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))";
-
-} // anonymous namespace
-
tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
ArrayRef<tooling::Range> Ranges,
StringRef FileName,
@@ -2774,7 +2962,6 @@ tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
.StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM
.Default(0);
unsigned SearchFrom = 0;
- llvm::Regex IncludeRegex(CppIncludeRegexPattern);
SmallVector<StringRef, 4> Matches;
SmallVector<IncludeDirective, 16> IncludesInBlock;
@@ -2831,7 +3018,7 @@ tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
bool MergeWithNextLine = Trimmed.endswith("\\");
if (!FormattingOff && !MergeWithNextLine) {
- if (IncludeRegex.match(Line, &Matches)) {
+ if (tooling::HeaderIncludes::IncludeRegex.match(Line, &Matches)) {
StringRef IncludeName = Matches[2];
if (Line.contains("/*") && !Line.contains("*/")) {
// #include with a start of a block comment, but without the end.
@@ -3109,8 +3296,8 @@ namespace {
inline bool isHeaderInsertion(const tooling::Replacement &Replace) {
return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 &&
- llvm::Regex(CppIncludeRegexPattern)
- .match(Replace.getReplacementText());
+ tooling::HeaderIncludes::IncludeRegex.match(
+ Replace.getReplacementText());
}
inline bool isHeaderDeletion(const tooling::Replacement &Replace) {
@@ -3162,17 +3349,18 @@ fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
}
}
- llvm::Regex IncludeRegex = llvm::Regex(CppIncludeRegexPattern);
llvm::SmallVector<StringRef, 4> Matches;
for (const auto &R : HeaderInsertions) {
auto IncludeDirective = R.getReplacementText();
- bool Matched = IncludeRegex.match(IncludeDirective, &Matches);
+ bool Matched =
+ tooling::HeaderIncludes::IncludeRegex.match(IncludeDirective, &Matches);
assert(Matched && "Header insertion replacement must have replacement text "
"'#include ...'");
(void)Matched;
auto IncludeName = Matches[2];
auto Replace =
- Includes.insert(IncludeName.trim("\"<>"), IncludeName.startswith("<"));
+ Includes.insert(IncludeName.trim("\"<>"), IncludeName.startswith("<"),
+ tooling::IncludeDirective::Include);
if (Replace) {
auto Err = Result.add(*Replace);
if (Err) {
@@ -3203,7 +3391,7 @@ cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
// Make header insertion replacements insert new headers into correct blocks.
tooling::Replacements NewReplaces =
fixCppIncludeInsertions(Code, Replaces, Style);
- return processReplacements(Cleanup, Code, NewReplaces, Style);
+ return cantFail(processReplacements(Cleanup, Code, NewReplaces, Style));
}
namespace internal {
@@ -3215,6 +3403,9 @@ reformat(const FormatStyle &Style, StringRef Code,
FormatStyle Expanded = Style;
expandPresetsBraceWrapping(Expanded);
expandPresetsSpaceBeforeParens(Expanded);
+ Expanded.InsertBraces = false;
+ Expanded.RemoveBracesLLVM = false;
+ Expanded.RemoveSemicolon = false;
switch (Expanded.RequiresClausePosition) {
case FormatStyle::RCPS_SingleLine:
case FormatStyle::RCPS_WithPreceding:
@@ -3250,11 +3441,20 @@ reformat(const FormatStyle &Style, StringRef Code,
return {tooling::Replacements(), 0};
}
+ auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,
+ NextStartColumn, LastStartColumn);
+ if (!Env)
+ return {};
+
typedef std::function<std::pair<tooling::Replacements, unsigned>(
const Environment &)>
AnalyzerPass;
SmallVector<AnalyzerPass, 8> Passes;
+ Passes.emplace_back([&](const Environment &Env) {
+ return IntegerLiteralSeparatorFixer().process(Env, Expanded);
+ });
+
if (Style.isCpp()) {
if (Style.QualifierAlignment != FormatStyle::QAS_Leave) {
Passes.emplace_back([&](const Environment &Env) {
@@ -3266,14 +3466,26 @@ reformat(const FormatStyle &Style, StringRef Code,
}
if (Style.InsertBraces) {
- Passes.emplace_back([&](const Environment &Env) {
- return BracesInserter(Env, Expanded).process();
+ FormatStyle S = Expanded;
+ S.InsertBraces = true;
+ Passes.emplace_back([&, S](const Environment &Env) {
+ return BracesInserter(Env, S).process(/*SkipAnnotation=*/true);
});
}
if (Style.RemoveBracesLLVM) {
- Passes.emplace_back([&](const Environment &Env) {
- return BracesRemover(Env, Expanded).process();
+ FormatStyle S = Expanded;
+ S.RemoveBracesLLVM = true;
+ Passes.emplace_back([&, S](const Environment &Env) {
+ return BracesRemover(Env, S).process(/*SkipAnnotation=*/true);
+ });
+ }
+
+ if (Style.RemoveSemicolon) {
+ FormatStyle S = Expanded;
+ S.RemoveSemicolon = true;
+ Passes.emplace_back([&, S](const Environment &Env) {
+ return SemiRemover(Env, S).process(/*SkipAnnotation=*/true);
});
}
@@ -3283,7 +3495,7 @@ reformat(const FormatStyle &Style, StringRef Code,
});
}
- if (Style.SortUsingDeclarations) {
+ if (Style.SortUsingDeclarations != FormatStyle::SUD_Never) {
Passes.emplace_back([&](const Environment &Env) {
return UsingDeclarationsSorter(Env, Expanded).process();
});
@@ -3299,7 +3511,7 @@ reformat(const FormatStyle &Style, StringRef Code,
if (Style.isJavaScript() &&
Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) {
Passes.emplace_back([&](const Environment &Env) {
- return JavaScriptRequoter(Env, Expanded).process();
+ return JavaScriptRequoter(Env, Expanded).process(/*SkipAnnotation=*/true);
});
}
@@ -3314,11 +3526,7 @@ reformat(const FormatStyle &Style, StringRef Code,
});
}
- auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,
- NextStartColumn, LastStartColumn);
- if (!Env)
- return {};
- llvm::Optional<std::string> CurrentCode = None;
+ std::optional<std::string> CurrentCode;
tooling::Replacements Fixes;
unsigned Penalty = 0;
for (size_t I = 0, E = Passes.size(); I < E; ++I) {
diff --git a/clang/lib/Format/FormatToken.cpp b/clang/lib/Format/FormatToken.cpp
index 832af463206c..f9f0d712bc16 100644
--- a/clang/lib/Format/FormatToken.cpp
+++ b/clang/lib/Format/FormatToken.cpp
@@ -56,7 +56,8 @@ bool FormatToken::isSimpleTypeSpecifier() const {
case tok::kw___ibm128:
case tok::kw_wchar_t:
case tok::kw_bool:
- case tok::kw___underlying_type:
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
+#include "clang/Basic/TransformTypeTraits.def"
case tok::annot_typename:
case tok::kw_char8_t:
case tok::kw_char16_t:
diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index 73e32979853f..9d055efd8007 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -20,6 +20,7 @@
#include "clang/Format/Format.h"
#include "clang/Lex/Lexer.h"
#include <memory>
+#include <optional>
#include <unordered_set>
namespace clang {
@@ -39,7 +40,10 @@ namespace format {
TYPE(CastRParen) \
TYPE(ClassLBrace) \
TYPE(CompoundRequirementLBrace) \
+ /* ternary ?: expression */ \
TYPE(ConditionalExpr) \
+ /* the condition in an if statement */ \
+ TYPE(ConditionLParen) \
TYPE(ConflictAlternative) \
TYPE(ConflictEnd) \
TYPE(ConflictStart) \
@@ -67,6 +71,11 @@ namespace format {
TYPE(FunctionLBrace) \
TYPE(FunctionLikeOrFreestandingMacro) \
TYPE(FunctionTypeLParen) \
+ /* The colons as part of a C11 _Generic selection */ \
+ TYPE(GenericSelectionColon) \
+ /* The colon at the end of a goto label or a case label. Currently only used \
+ * for Verilog. */ \
+ TYPE(GotoLabelColon) \
TYPE(IfMacro) \
TYPE(ImplicitStringLiteral) \
TYPE(InheritanceColon) \
@@ -135,6 +144,16 @@ namespace format {
TYPE(UnaryOperator) \
TYPE(UnionLBrace) \
TYPE(UntouchableMacroFunc) \
+ /* like in begin : block */ \
+ TYPE(VerilogBlockLabelColon) \
+ /* The square bracket for the dimension part of the type name. \
+ * In 'logic [1:0] x[1:0]', only the first '['. This way we can have space \
+ * before the first bracket but not the second. */ \
+ TYPE(VerilogDimensionedTypeName) \
+ /* for the base in a number literal, not including the quote */ \
+ TYPE(VerilogNumberBase) \
+ /* Things inside the table in user-defined primitives. */ \
+ TYPE(VerilogTableItem) \
TYPE(Unknown)
/// Determines the semantic type of a syntactic token, e.g. whether "<" is a
@@ -231,7 +250,8 @@ struct FormatToken {
CanBreakBefore(false), ClosesTemplateDeclaration(false),
StartsBinaryExpression(false), EndsBinaryExpression(false),
PartOfMultiVariableDeclStmt(false), ContinuesLineCommentSection(false),
- Finalized(false), ClosesRequiresClause(false), BlockKind(BK_Unknown),
+ Finalized(false), ClosesRequiresClause(false),
+ EndsCppAttributeGroup(false), BlockKind(BK_Unknown),
Decision(FD_Unformatted), PackingKind(PPK_Inconclusive),
TypeIsFinalized(false), Type(TT_Unknown) {}
@@ -302,6 +322,9 @@ struct FormatToken {
/// \c true if this is the last token within requires clause.
unsigned ClosesRequiresClause : 1;
+ /// \c true if this token ends a group of C++ attributes.
+ unsigned EndsCppAttributeGroup : 1;
+
private:
/// Contains the kind of block if this token is a brace.
unsigned BlockKind : 2;
@@ -368,6 +391,9 @@ public:
}
bool isTypeFinalized() const { return TypeIsFinalized; }
+ /// Used to set an operator precedence explicitly.
+ prec::Level ForcedPrecedence = prec::Unknown;
+
/// The number of newlines immediately before the \c Token.
///
/// This can be used to determine what the user wrote in the original code
@@ -495,7 +521,7 @@ public:
// Contains all attributes related to how this token takes part
// in a configured macro expansion.
- llvm::Optional<MacroExpansion> MacroCtx;
+ std::optional<MacroExpansion> MacroCtx;
/// When macro expansion introduces nodes with children, those are marked as
/// \c MacroParent.
@@ -565,8 +591,12 @@ public:
}
bool isAccessSpecifier(bool ColonRequired = true) const {
- return isOneOf(tok::kw_public, tok::kw_protected, tok::kw_private) &&
- (!ColonRequired || (Next && Next->is(tok::colon)));
+ if (!isOneOf(tok::kw_public, tok::kw_protected, tok::kw_private))
+ return false;
+ if (!ColonRequired)
+ return true;
+ const auto NextNonComment = getNextNonComment();
+ return NextNonComment && NextNonComment->is(tok::colon);
}
bool canBePointerOrReferenceQualifier() const {
@@ -577,9 +607,9 @@ public:
}
/// Determine whether the token is a simple-type-specifier.
- LLVM_NODISCARD bool isSimpleTypeSpecifier() const;
+ [[nodiscard]] bool isSimpleTypeSpecifier() const;
- LLVM_NODISCARD bool isTypeOrIdentifier() const;
+ [[nodiscard]] bool isTypeOrIdentifier() const;
bool isObjCAccessSpecifier() const {
return is(tok::at) && Next &&
@@ -658,7 +688,8 @@ public:
case tok::kw_static_assert:
case tok::kw__Atomic:
case tok::kw___attribute:
- case tok::kw___underlying_type:
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
+#include "clang/Basic/TransformTypeTraits.def"
case tok::kw_requires:
return true;
default:
@@ -697,12 +728,14 @@ public:
}
prec::Level getPrecedence() const {
+ if (ForcedPrecedence != prec::Unknown)
+ return ForcedPrecedence;
return getBinOpPrecedence(Tok.getKind(), /*GreaterThanIsOperator=*/true,
/*CPlusPlus11=*/true);
}
/// Returns the previous token ignoring comments.
- LLVM_NODISCARD FormatToken *getPreviousNonComment() const {
+ [[nodiscard]] FormatToken *getPreviousNonComment() const {
FormatToken *Tok = Previous;
while (Tok && Tok->is(tok::comment))
Tok = Tok->Previous;
@@ -710,7 +743,7 @@ public:
}
/// Returns the next token ignoring comments.
- LLVM_NODISCARD const FormatToken *getNextNonComment() const {
+ [[nodiscard]] const FormatToken *getNextNonComment() const {
const FormatToken *Tok = Next;
while (Tok && Tok->is(tok::comment))
Tok = Tok->Next;
@@ -719,7 +752,7 @@ public:
/// Returns \c true if this tokens starts a block-type list, i.e. a
/// list that should be indented with a block indent.
- LLVM_NODISCARD bool opensBlockOrBlockTypeList(const FormatStyle &Style) const;
+ [[nodiscard]] bool opensBlockOrBlockTypeList(const FormatStyle &Style) const;
/// Returns whether the token is the left square bracket of a C++
/// structured binding declaration.
@@ -988,6 +1021,7 @@ struct AdditionalKeywords {
kw_when = &IdentTable.get("when");
kw_where = &IdentTable.get("where");
+ // Verilog keywords
kw_always = &IdentTable.get("always");
kw_always_comb = &IdentTable.get("always_comb");
kw_always_ff = &IdentTable.get("always_ff");
@@ -1119,6 +1153,7 @@ struct AdditionalKeywords {
// Symbols that are treated as keywords.
kw_verilogHash = &IdentTable.get("#");
kw_verilogHashHash = &IdentTable.get("##");
+ kw_apostrophe = &IdentTable.get("\'");
// Keep this at the end of the constructor to make sure everything here
// is
@@ -1511,11 +1546,14 @@ struct AdditionalKeywords {
IdentifierInfo *kw_verilogHash;
IdentifierInfo *kw_verilogHashHash;
+ // Symbols in Verilog that don't exist in C++.
+ IdentifierInfo *kw_apostrophe;
+
/// Returns \c true if \p Tok is a keyword or an identifier.
bool isWordLike(const FormatToken &Tok) const {
// getIdentifierinfo returns non-null for keywords as well as identifiers.
return Tok.Tok.getIdentifierInfo() != nullptr &&
- !Tok.isOneOf(kw_verilogHash, kw_verilogHashHash);
+ !Tok.isOneOf(kw_verilogHash, kw_verilogHashHash, kw_apostrophe);
}
/// Returns \c true if \p Tok is a true JavaScript identifier, returns
@@ -1644,6 +1682,11 @@ struct AdditionalKeywords {
}
}
+ bool isVerilogWordOperator(const FormatToken &Tok) const {
+ return Tok.isOneOf(kw_before, kw_intersect, kw_dist, kw_iff, kw_inside,
+ kw_with);
+ }
+
bool isVerilogIdentifier(const FormatToken &Tok) const {
switch (Tok.Tok.getKind()) {
case tok::kw_case:
@@ -1724,10 +1767,29 @@ struct AdditionalKeywords {
kw_join_any, kw_join_none);
}
- /// Whether the token begins a block.
- bool isBlockBegin(const FormatToken &Tok, const FormatStyle &Style) const {
- return Tok.is(TT_MacroBlockBegin) ||
- (Style.isVerilog() ? isVerilogBegin(Tok) : Tok.is(tok::l_brace));
+ /// Returns whether \p Tok is a Verilog keyword that opens a module, etc.
+ bool isVerilogHierarchy(const FormatToken &Tok) const {
+ if (Tok.endsSequence(kw_function, kw_with))
+ return false;
+ if (Tok.is(kw_property)) {
+ const FormatToken *Prev = Tok.getPreviousNonComment();
+ return !(Prev &&
+ Prev->isOneOf(tok::kw_restrict, kw_assert, kw_assume, kw_cover));
+ }
+ return Tok.isOneOf(tok::kw_case, tok::kw_class, kw_function, kw_module,
+ kw_interface, kw_package, kw_casex, kw_casez, kw_checker,
+ kw_clocking, kw_covergroup, kw_macromodule, kw_primitive,
+ kw_program, kw_property, kw_randcase, kw_randsequence,
+ kw_task);
+ }
+
+ bool isVerilogEndOfLabel(const FormatToken &Tok) const {
+ const FormatToken *Next = Tok.getNextNonComment();
+ // In Verilog the colon in a default label is optional.
+ return Tok.is(TT_GotoLabelColon) ||
+ (Tok.is(tok::kw_default) &&
+ !(Next && Next->isOneOf(tok::colon, tok::semi, kw_clocking, kw_iff,
+ kw_input, kw_output, kw_sequence)));
}
private:
diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp
index 3f9b68ccbb39..f8f5f7112188 100644
--- a/clang/lib/Format/FormatTokenLexer.cpp
+++ b/clang/lib/Format/FormatTokenLexer.cpp
@@ -193,6 +193,78 @@ void FormatTokenLexer::tryMergePreviousTokens() {
if (tryMergeTokens(JavaRightLogicalShiftAssign, TT_BinaryOperator))
return;
}
+
+ if (Style.isVerilog()) {
+ // Merge the number following a base like `'h?a0`.
+ if (Tokens.size() >= 3 && Tokens.end()[-3]->is(TT_VerilogNumberBase) &&
+ Tokens.end()[-2]->is(tok::numeric_constant) &&
+ Tokens.back()->isOneOf(tok::numeric_constant, tok::identifier,
+ tok::question) &&
+ tryMergeTokens(2, TT_Unknown)) {
+ return;
+ }
+ // Part select.
+ if (tryMergeTokensAny({{tok::minus, tok::colon}, {tok::plus, tok::colon}},
+ TT_BitFieldColon)) {
+ return;
+ }
+ // Xnor. The combined token is treated as a caret which can also be either a
+ // unary or binary operator. The actual type is determined in
+ // TokenAnnotator. We also check the token length so we know it is not
+ // already a merged token.
+ if (Tokens.back()->TokenText.size() == 1 &&
+ tryMergeTokensAny({{tok::caret, tok::tilde}, {tok::tilde, tok::caret}},
+ TT_BinaryOperator)) {
+ Tokens.back()->Tok.setKind(tok::caret);
+ return;
+ }
+ // Signed shift and distribution weight.
+ if (tryMergeTokens({tok::less, tok::less}, TT_BinaryOperator)) {
+ Tokens.back()->Tok.setKind(tok::lessless);
+ return;
+ }
+ if (tryMergeTokens({tok::greater, tok::greater}, TT_BinaryOperator)) {
+ Tokens.back()->Tok.setKind(tok::greatergreater);
+ return;
+ }
+ if (tryMergeTokensAny({{tok::lessless, tok::equal},
+ {tok::lessless, tok::lessequal},
+ {tok::greatergreater, tok::equal},
+ {tok::greatergreater, tok::greaterequal},
+ {tok::colon, tok::equal},
+ {tok::colon, tok::slash}},
+ TT_BinaryOperator)) {
+ Tokens.back()->ForcedPrecedence = prec::Assignment;
+ return;
+ }
+ // Exponentiation, signed shift, case equality, and wildcard equality.
+ if (tryMergeTokensAny({{tok::star, tok::star},
+ {tok::lessless, tok::less},
+ {tok::greatergreater, tok::greater},
+ {tok::exclaimequal, tok::equal},
+ {tok::exclaimequal, tok::question},
+ {tok::equalequal, tok::equal},
+ {tok::equalequal, tok::question}},
+ TT_BinaryOperator)) {
+ return;
+ }
+ // Module paths in specify blocks and implications in properties.
+ if (tryMergeTokensAny({{tok::plusequal, tok::greater},
+ {tok::plus, tok::star, tok::greater},
+ {tok::minusequal, tok::greater},
+ {tok::minus, tok::star, tok::greater},
+ {tok::less, tok::arrow},
+ {tok::equal, tok::greater},
+ {tok::star, tok::greater},
+ {tok::pipeequal, tok::greater},
+ {tok::pipe, tok::arrow},
+ {tok::hash, tok::minus, tok::hash},
+ {tok::hash, tok::equal, tok::hash}},
+ TT_BinaryOperator)) {
+ Tokens.back()->ForcedPrecedence = prec::Comma;
+ return;
+ }
+ }
}
bool FormatTokenLexer::tryMergeNSStringLiteral() {
@@ -240,36 +312,32 @@ bool FormatTokenLexer::tryMergeCSharpStringLiteral() {
return false;
// Look for @"aaaaaa" or $"aaaaaa".
- auto &String = *(Tokens.end() - 1);
- if (!String->is(tok::string_literal))
+ const auto String = *(Tokens.end() - 1);
+ if (String->isNot(tok::string_literal))
return false;
- auto &At = *(Tokens.end() - 2);
- if (!(At->is(tok::at) || At->TokenText == "$"))
+ auto Prefix = *(Tokens.end() - 2);
+ if (Prefix->isNot(tok::at) && Prefix->TokenText != "$")
return false;
- if (Tokens.size() > 2 && At->is(tok::at)) {
- auto &Dollar = *(Tokens.end() - 3);
- if (Dollar->TokenText == "$") {
- // This looks like $@"aaaaa" so we need to combine all 3 tokens.
- Dollar->Tok.setKind(tok::string_literal);
- Dollar->TokenText =
- StringRef(Dollar->TokenText.begin(),
- String->TokenText.end() - Dollar->TokenText.begin());
- Dollar->ColumnWidth += (At->ColumnWidth + String->ColumnWidth);
- Dollar->setType(TT_CSharpStringLiteral);
+ if (Tokens.size() > 2) {
+ const auto Tok = *(Tokens.end() - 3);
+ if ((Tok->TokenText == "$" && Prefix->is(tok::at)) ||
+ (Tok->is(tok::at) && Prefix->TokenText == "$")) {
+ // This looks like $@"aaa" or @$"aaa" so we need to combine all 3 tokens.
+ Tok->ColumnWidth += Prefix->ColumnWidth;
Tokens.erase(Tokens.end() - 2);
- Tokens.erase(Tokens.end() - 1);
- return true;
+ Prefix = Tok;
}
}
// Convert back into just a string_literal.
- At->Tok.setKind(tok::string_literal);
- At->TokenText = StringRef(At->TokenText.begin(),
- String->TokenText.end() - At->TokenText.begin());
- At->ColumnWidth += String->ColumnWidth;
- At->setType(TT_CSharpStringLiteral);
+ Prefix->Tok.setKind(tok::string_literal);
+ Prefix->TokenText =
+ StringRef(Prefix->TokenText.begin(),
+ String->TokenText.end() - Prefix->TokenText.begin());
+ Prefix->ColumnWidth += String->ColumnWidth;
+ Prefix->setType(TT_CSharpStringLiteral);
Tokens.erase(Tokens.end() - 1);
return true;
}
@@ -303,9 +371,11 @@ bool FormatTokenLexer::tryMergeNullishCoalescingEqual() {
bool FormatTokenLexer::tryMergeCSharpKeywordVariables() {
if (Tokens.size() < 2)
return false;
- auto &At = *(Tokens.end() - 2);
- auto &Keyword = *(Tokens.end() - 1);
- if (!At->is(tok::at))
+ const auto At = *(Tokens.end() - 2);
+ if (At->isNot(tok::at))
+ return false;
+ const auto Keyword = *(Tokens.end() - 1);
+ if (Keyword->TokenText == "$")
return false;
if (!Keywords.isCSharpKeyword(*Keyword))
return false;
@@ -412,15 +482,28 @@ bool FormatTokenLexer::tryMergeTokens(ArrayRef<tok::TokenKind> Kinds,
SmallVectorImpl<FormatToken *>::const_iterator First =
Tokens.end() - Kinds.size();
- if (!First[0]->is(Kinds[0]))
+ for (unsigned i = 0; i < Kinds.size(); ++i)
+ if (!First[i]->is(Kinds[i]))
+ return false;
+
+ return tryMergeTokens(Kinds.size(), NewType);
+}
+
+bool FormatTokenLexer::tryMergeTokens(size_t Count, TokenType NewType) {
+ if (Tokens.size() < Count)
return false;
+
+ SmallVectorImpl<FormatToken *>::const_iterator First = Tokens.end() - Count;
unsigned AddLength = 0;
- for (unsigned i = 1; i < Kinds.size(); ++i) {
- if (!First[i]->is(Kinds[i]) || First[i]->hasWhitespaceBefore())
+ for (size_t i = 1; i < Count; ++i) {
+ // If there is whitespace separating the token and the previous one,
+ // they should not be merged.
+ if (First[i]->hasWhitespaceBefore())
return false;
AddLength += First[i]->TokenText.size();
}
- Tokens.resize(Tokens.size() - Kinds.size() + 1);
+
+ Tokens.resize(Tokens.size() - Count + 1);
First[0]->TokenText = StringRef(First[0]->TokenText.data(),
First[0]->TokenText.size() + AddLength);
First[0]->ColumnWidth += AddLength;
@@ -428,6 +511,13 @@ bool FormatTokenLexer::tryMergeTokens(ArrayRef<tok::TokenKind> Kinds,
return true;
}
+bool FormatTokenLexer::tryMergeTokensAny(
+ ArrayRef<ArrayRef<tok::TokenKind>> Kinds, TokenType NewType) {
+ return llvm::any_of(Kinds, [this, NewType](ArrayRef<tok::TokenKind> Kinds) {
+ return tryMergeTokens(Kinds, NewType);
+ });
+}
+
// Returns \c true if \p Tok can only be followed by an operand in JavaScript.
bool FormatTokenLexer::precedesOperand(FormatToken *Tok) {
// NB: This is not entirely correct, as an r_paren can introduce an operand
@@ -591,7 +681,7 @@ void FormatTokenLexer::handleCSharpVerbatimAndInterpolatedStrings() {
bool Verbatim = false;
bool Interpolated = false;
- if (TokenText.startswith(R"($@")")) {
+ if (TokenText.startswith(R"($@")") || TokenText.startswith(R"(@$")")) {
Verbatim = true;
Interpolated = true;
} else if (TokenText.startswith(R"(@")")) {
@@ -670,6 +760,7 @@ void FormatTokenLexer::handleTemplateStrings() {
for (; Offset != Lex->getBuffer().end(); ++Offset) {
if (Offset[0] == '`') {
StateStack.pop();
+ ++Offset;
break;
}
if (Offset[0] == '\\') {
@@ -678,12 +769,12 @@ void FormatTokenLexer::handleTemplateStrings() {
Offset[1] == '{') {
// '${' introduces an expression interpolation in the template string.
StateStack.push(LexerState::NORMAL);
- ++Offset;
+ Offset += 2;
break;
}
}
- StringRef LiteralText(TmplBegin, Offset - TmplBegin + 1);
+ StringRef LiteralText(TmplBegin, Offset - TmplBegin);
BacktickToken->setType(TT_TemplateString);
BacktickToken->Tok.setKind(tok::string_literal);
BacktickToken->TokenText = LiteralText;
@@ -704,9 +795,7 @@ void FormatTokenLexer::handleTemplateStrings() {
StartColumn, Style.TabWidth, Encoding);
}
- SourceLocation loc = Offset < Lex->getBuffer().end()
- ? Lex->getSourceLocation(Offset + 1)
- : SourceMgr.getLocForEndOfFile(ID);
+ SourceLocation loc = Lex->getSourceLocation(Offset);
resetLexer(SourceMgr.getFileOffset(loc));
}
@@ -935,7 +1024,7 @@ FormatToken *FormatTokenLexer::getNextToken() {
// the same as a single LF.
if (i + 1 < e && Text[i + 1] == '\n')
break;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case '\n':
++FormatTok->NewlinesBefore;
if (!InEscape)
@@ -1004,12 +1093,19 @@ FormatToken *FormatTokenLexer::getNextToken() {
}
if (Style.isVerilog()) {
+ static const llvm::Regex NumberBase("^s?[bdho]", llvm::Regex::IgnoreCase);
+ SmallVector<StringRef, 1> Matches;
// Verilog uses the backtick instead of the hash for preprocessor stuff.
// And it uses the hash for delays and parameter lists. In order to continue
// using `tok::hash` in other places, the backtick gets marked as the hash
// here. And in order to tell the backtick and hash apart for
// Verilog-specific stuff, the hash becomes an identifier.
- if (FormatTok->isOneOf(tok::hash, tok::hashhash)) {
+ if (FormatTok->is(tok::numeric_constant)) {
+ // In Verilog the quote is not part of a number.
+ auto Quote = FormatTok->TokenText.find('\'');
+ if (Quote != StringRef::npos)
+ truncateToken(Quote);
+ } else if (FormatTok->isOneOf(tok::hash, tok::hashhash)) {
FormatTok->Tok.setKind(tok::raw_identifier);
} else if (FormatTok->is(tok::raw_identifier)) {
if (FormatTok->TokenText == "`") {
@@ -1018,6 +1114,15 @@ FormatToken *FormatTokenLexer::getNextToken() {
} else if (FormatTok->TokenText == "``") {
FormatTok->Tok.setIdentifierInfo(nullptr);
FormatTok->Tok.setKind(tok::hashhash);
+ } else if (Tokens.size() > 0 &&
+ Tokens.back()->is(Keywords.kw_apostrophe) &&
+ NumberBase.match(FormatTok->TokenText, &Matches)) {
+ // In Verilog in a based number literal like `'b10`, there may be
+ // whitespace between `'b` and `10`. Therefore we handle the base and
+ // the rest of the number literal as two tokens. But if there is no
+ // space in the input code, we need to manually separate the two parts.
+ truncateToken(Matches[0].size());
+ FormatTok->setFinalizedType(TT_VerilogNumberBase);
}
}
}
@@ -1060,6 +1165,13 @@ FormatToken *FormatTokenLexer::getNextToken() {
StateStack.push(LexerState::TOKEN_STASHED);
}
+ if (Style.isVerilog() && Tokens.size() > 0 &&
+ Tokens.back()->is(TT_VerilogNumberBase) &&
+ FormatTok->Tok.isOneOf(tok::identifier, tok::question)) {
+ // Mark the number following a base like `'h?a0` as a number.
+ FormatTok->Tok.setKind(tok::numeric_constant);
+ }
+
// Now FormatTok is the next non-whitespace token.
StringRef Text = FormatTok->TokenText;
diff --git a/clang/lib/Format/FormatTokenLexer.h b/clang/lib/Format/FormatTokenLexer.h
index bff2c181d81e..950305a37d68 100644
--- a/clang/lib/Format/FormatTokenLexer.h
+++ b/clang/lib/Format/FormatTokenLexer.h
@@ -60,7 +60,14 @@ private:
bool tryMergeForEach();
bool tryTransformTryUsageForC();
+ // Merge the most recently lexed tokens into a single token if their kinds are
+ // correct.
bool tryMergeTokens(ArrayRef<tok::TokenKind> Kinds, TokenType NewType);
+ // Merge without checking their kinds.
+ bool tryMergeTokens(size_t Count, TokenType NewType);
+ // Merge if their kinds match any one of Kinds.
+ bool tryMergeTokensAny(ArrayRef<ArrayRef<tok::TokenKind>> Kinds,
+ TokenType NewType);
// Returns \c true if \p Tok can only be followed by an operand in JavaScript.
bool precedesOperand(FormatToken *Tok);
diff --git a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp
new file mode 100644
index 000000000000..ef07ab06760b
--- /dev/null
+++ b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp
@@ -0,0 +1,199 @@
+//===--- IntegerLiteralSeparatorFixer.cpp -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file implements IntegerLiteralSeparatorFixer that fixes C++ integer
+/// literal separators.
+///
+//===----------------------------------------------------------------------===//
+
+#include "IntegerLiteralSeparatorFixer.h"
+
+namespace clang {
+namespace format {
+
+enum class Base { Binary, Decimal, Hex, Other };
+
+static Base getBase(const StringRef IntegerLiteral) {
+ assert(IntegerLiteral.size() > 1);
+
+ if (IntegerLiteral[0] > '0') {
+ assert(IntegerLiteral[0] <= '9');
+ return Base::Decimal;
+ }
+
+ assert(IntegerLiteral[0] == '0');
+
+ switch (IntegerLiteral[1]) {
+ case 'b':
+ case 'B':
+ return Base::Binary;
+ case 'x':
+ case 'X':
+ return Base::Hex;
+ default:
+ return Base::Other;
+ }
+}
+
+std::pair<tooling::Replacements, unsigned>
+IntegerLiteralSeparatorFixer::process(const Environment &Env,
+ const FormatStyle &Style) {
+ switch (Style.Language) {
+ case FormatStyle::LK_Cpp:
+ case FormatStyle::LK_ObjC:
+ Separator = '\'';
+ break;
+ case FormatStyle::LK_CSharp:
+ case FormatStyle::LK_Java:
+ case FormatStyle::LK_JavaScript:
+ Separator = '_';
+ break;
+ default:
+ return {};
+ }
+
+ const auto &Option = Style.IntegerLiteralSeparator;
+ const auto Binary = Option.Binary;
+ const auto Decimal = Option.Decimal;
+ const auto Hex = Option.Hex;
+ const bool SkipBinary = Binary == 0;
+ const bool SkipDecimal = Decimal == 0;
+ const bool SkipHex = Hex == 0;
+
+ if (SkipBinary && SkipDecimal && SkipHex)
+ return {};
+
+ const auto &SourceMgr = Env.getSourceManager();
+ AffectedRangeManager AffectedRangeMgr(SourceMgr, Env.getCharRanges());
+
+ const auto ID = Env.getFileID();
+ const auto LangOpts = getFormattingLangOpts(Style);
+ Lexer Lex(ID, SourceMgr.getBufferOrFake(ID), SourceMgr, LangOpts);
+ Lex.SetCommentRetentionState(true);
+
+ Token Tok;
+ tooling::Replacements Result;
+
+ for (bool Skip = false; !Lex.LexFromRawLexer(Tok);) {
+ auto Length = Tok.getLength();
+ if (Length < 2)
+ continue;
+ auto Location = Tok.getLocation();
+ auto Text = StringRef(SourceMgr.getCharacterData(Location), Length);
+ if (Tok.is(tok::comment)) {
+ if (Text == "// clang-format off" || Text == "/* clang-format off */")
+ Skip = true;
+ else if (Text == "// clang-format on" || Text == "/* clang-format on */")
+ Skip = false;
+ continue;
+ }
+ if (Skip || Tok.isNot(tok::numeric_constant) || Text[0] == '.' ||
+ !AffectedRangeMgr.affectsCharSourceRange(
+ CharSourceRange::getCharRange(Location, Tok.getEndLoc()))) {
+ continue;
+ }
+ const auto B = getBase(Text);
+ const bool IsBase2 = B == Base::Binary;
+ const bool IsBase10 = B == Base::Decimal;
+ const bool IsBase16 = B == Base::Hex;
+ if ((IsBase2 && SkipBinary) || (IsBase10 && SkipDecimal) ||
+ (IsBase16 && SkipHex) || B == Base::Other) {
+ continue;
+ }
+ if ((IsBase10 && Text.find_last_of(".eEfFdDmM") != StringRef::npos) ||
+ (IsBase16 && Text.find_last_of(".pP") != StringRef::npos)) {
+ continue;
+ }
+ if (((IsBase2 && Binary < 0) || (IsBase10 && Decimal < 0) ||
+ (IsBase16 && Hex < 0)) &&
+ Text.find(Separator) == StringRef::npos) {
+ continue;
+ }
+ const auto Start = Text[0] == '0' ? 2 : 0;
+ auto End = Text.find_first_of("uUlLzZn");
+ if (End == StringRef::npos)
+ End = Length;
+ if (Start > 0 || End < Length) {
+ Length = End - Start;
+ Text = Text.substr(Start, Length);
+ }
+ auto DigitsPerGroup = Decimal;
+ if (IsBase2)
+ DigitsPerGroup = Binary;
+ else if (IsBase16)
+ DigitsPerGroup = Hex;
+ if (DigitsPerGroup > 0 && checkSeparator(Text, DigitsPerGroup))
+ continue;
+ if (Start > 0)
+ Location = Location.getLocWithOffset(Start);
+ cantFail(Result.add(tooling::Replacement(SourceMgr, Location, Length,
+ format(Text, DigitsPerGroup))));
+ }
+
+ return {Result, 0};
+}
+
+bool IntegerLiteralSeparatorFixer::checkSeparator(
+ const StringRef IntegerLiteral, int DigitsPerGroup) const {
+ assert(DigitsPerGroup > 0);
+
+ int I = 0;
+ for (auto C : llvm::reverse(IntegerLiteral)) {
+ if (C == Separator) {
+ if (I < DigitsPerGroup)
+ return false;
+ I = 0;
+ } else {
+ ++I;
+ if (I == DigitsPerGroup)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+std::string IntegerLiteralSeparatorFixer::format(const StringRef IntegerLiteral,
+ int DigitsPerGroup) const {
+ assert(DigitsPerGroup != 0);
+
+ std::string Formatted;
+
+ if (DigitsPerGroup < 0) {
+ for (auto C : IntegerLiteral)
+ if (C != Separator)
+ Formatted.push_back(C);
+ return Formatted;
+ }
+
+ int DigitCount = 0;
+ for (auto C : IntegerLiteral)
+ if (C != Separator)
+ ++DigitCount;
+
+ int Remainder = DigitCount % DigitsPerGroup;
+
+ int I = 0;
+ for (auto C : IntegerLiteral) {
+ if (C == Separator)
+ continue;
+ if (I == (Remainder > 0 ? Remainder : DigitsPerGroup)) {
+ Formatted.push_back(Separator);
+ I = 0;
+ Remainder = 0;
+ }
+ Formatted.push_back(C);
+ ++I;
+ }
+
+ return Formatted;
+}
+
+} // namespace format
+} // namespace clang
diff --git a/clang/lib/Format/IntegerLiteralSeparatorFixer.h b/clang/lib/Format/IntegerLiteralSeparatorFixer.h
new file mode 100644
index 000000000000..156bf5c14fca
--- /dev/null
+++ b/clang/lib/Format/IntegerLiteralSeparatorFixer.h
@@ -0,0 +1,38 @@
+//===--- IntegerLiteralSeparatorFixer.h -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file declares IntegerLiteralSeparatorFixer that fixes C++ integer
+/// literal separators.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_FORMAT_INTEGERLITERALSEPARATORFIXER_H
+#define LLVM_CLANG_LIB_FORMAT_INTEGERLITERALSEPARATORFIXER_H
+
+#include "TokenAnalyzer.h"
+
+namespace clang {
+namespace format {
+
+class IntegerLiteralSeparatorFixer {
+public:
+ std::pair<tooling::Replacements, unsigned> process(const Environment &Env,
+ const FormatStyle &Style);
+
+private:
+ bool checkSeparator(const StringRef IntegerLiteral, int DigitsPerGroup) const;
+ std::string format(const StringRef IntegerLiteral, int DigitsPerGroup) const;
+
+ char Separator;
+};
+
+} // end namespace format
+} // end namespace clang
+
+#endif
diff --git a/clang/lib/Format/MacroCallReconstructor.cpp b/clang/lib/Format/MacroCallReconstructor.cpp
index ccff183cf0da..1c295477a922 100644
--- a/clang/lib/Format/MacroCallReconstructor.cpp
+++ b/clang/lib/Format/MacroCallReconstructor.cpp
@@ -35,9 +35,8 @@ void forEachToken(const UnwrappedLine &Line, const T &Call,
for (const auto &N : Line.Tokens) {
Call(N.Tok, Parent, First);
First = false;
- for (const auto &Child : N.Children) {
+ for (const auto &Child : N.Children)
forEachToken(Child, Call, N.Tok);
- }
}
}
@@ -61,7 +60,8 @@ void MacroCallReconstructor::addLine(const UnwrappedLine &Line) {
UnwrappedLine MacroCallReconstructor::takeResult() && {
finalize();
- assert(Result.Tokens.size() == 1 && Result.Tokens.front()->Children.size() == 1);
+ assert(Result.Tokens.size() == 1 &&
+ Result.Tokens.front()->Children.size() == 1);
UnwrappedLine Final =
createUnwrappedLine(*Result.Tokens.front()->Children.front(), Level);
assert(!Final.Tokens.empty());
@@ -194,9 +194,8 @@ FormatToken *MacroCallReconstructor::getParentInResult(FormatToken *Parent) {
FormatToken *Mapped = SpelledParentToReconstructedParent.lookup(Parent);
if (!Mapped)
return Parent;
- for (; Mapped; Mapped = SpelledParentToReconstructedParent.lookup(Parent)) {
+ for (; Mapped; Mapped = SpelledParentToReconstructedParent.lookup(Parent))
Parent = Mapped;
- }
// If we use a different token than the parent in the expanded token stream
// as parent, mark it as a special parent, so the formatting code knows it
// needs to have its children formatted.
@@ -216,9 +215,8 @@ void MacroCallReconstructor::reconstruct(FormatToken *Token) {
// If the order of tokens in the expanded token stream is not the
// same as the order of tokens in the reconstructed stream, we need
// to reconstruct tokens that arrive later in the stream.
- if (Token->MacroCtx->Role != MR_Hidden) {
+ if (Token->MacroCtx->Role != MR_Hidden)
reconstructActiveCallUntil(Token);
- }
}
assert(!ActiveExpansions.empty());
if (ActiveExpansions.back().SpelledI != ActiveExpansions.back().SpelledE) {
@@ -275,7 +273,7 @@ void MacroCallReconstructor::startReconstruction(FormatToken *Token) {
// Note that the token's expanded from stack is inside-to-outside, and the
// expansions for which this token is not the first are the outermost ones.
ArrayRef<FormatToken *> StartedMacros =
- makeArrayRef(Token->MacroCtx->ExpandedFrom)
+ ArrayRef(Token->MacroCtx->ExpandedFrom)
.drop_back(ActiveExpansions.size());
assert(StartedMacros.size() == Token->MacroCtx->StartOfExpansion);
// We reconstruct macro calls outside-to-inside.
@@ -334,9 +332,8 @@ void MacroCallReconstructor::endReconstruction(FormatToken *Token) {
bool PreviousLevel =
Token->MacroCtx &&
(ActiveExpansions.size() < Token->MacroCtx->ExpandedFrom.size());
- if (!ClosingParen && !TrailingComment && !PreviousLevel) {
+ if (!ClosingParen && !TrailingComment && !PreviousLevel)
llvm::dbgs() << "At token: " << Token->TokenText << "\n";
- }
// In addition to the following cases, we can also run into this
// when a macro call had more arguments than expected; in that case,
// the comma and the remaining tokens in the macro call will potentially
@@ -392,9 +389,8 @@ bool MacroCallReconstructor::processNextReconstructed() {
++ActiveExpansions.back().SpelledI;
if (Token->MacroCtx) {
// Skip tokens that are not part of the macro call.
- if (Token->MacroCtx->Role == MR_Hidden) {
+ if (Token->MacroCtx->Role == MR_Hidden)
return false;
- }
// Skip tokens we already expanded during an inner reconstruction.
// For example, given: #define ID(x) {x}
// And the call: ID(ID(f))
@@ -403,9 +399,8 @@ bool MacroCallReconstructor::processNextReconstructed() {
// ID({f}) -> {{f}}
// We reconstruct f during the first reconstruction, and skip it during the
// second reconstruction.
- if (ActiveExpansions.size() < Token->MacroCtx->ExpandedFrom.size()) {
+ if (ActiveExpansions.size() < Token->MacroCtx->ExpandedFrom.size())
return false;
- }
}
// Tokens that do not have a macro context are tokens in that are part of the
// macro call that have not taken part in expansion.
diff --git a/clang/lib/Format/QualifierAlignmentFixer.cpp b/clang/lib/Format/QualifierAlignmentFixer.cpp
index 61f17cae383e..cef8b36ff758 100644
--- a/clang/lib/Format/QualifierAlignmentFixer.cpp
+++ b/clang/lib/Format/QualifierAlignmentFixer.cpp
@@ -18,6 +18,7 @@
#include "llvm/Support/Regex.h"
#include <algorithm>
+#include <optional>
#define DEBUG_TYPE "format-qualifier-alignment-fixer"
@@ -66,7 +67,7 @@ std::pair<tooling::Replacements, unsigned> QualifierAlignmentFixer::analyze(
NextStartColumn, LastStartColumn);
if (!Env)
return {};
- llvm::Optional<std::string> CurrentCode = None;
+ std::optional<std::string> CurrentCode;
tooling::Replacements Fixes;
for (size_t I = 0, E = Passes.size(); I < E; ++I) {
std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
@@ -413,6 +414,7 @@ tok::TokenKind LeftRightQualifierAlignmentFixer::getTokenFromQualifier(
.Case("inline", tok::kw_inline)
.Case("constexpr", tok::kw_constexpr)
.Case("restrict", tok::kw_restrict)
+ .Case("friend", tok::kw_friend)
.Default(tok::identifier);
}
diff --git a/clang/lib/Format/TokenAnalyzer.cpp b/clang/lib/Format/TokenAnalyzer.cpp
index 0a775c0a87ed..77e403581a0d 100644
--- a/clang/lib/Format/TokenAnalyzer.cpp
+++ b/clang/lib/Format/TokenAnalyzer.cpp
@@ -97,7 +97,8 @@ TokenAnalyzer::TokenAnalyzer(const Environment &Env, const FormatStyle &Style)
<< "\n");
}
-std::pair<tooling::Replacements, unsigned> TokenAnalyzer::process() {
+std::pair<tooling::Replacements, unsigned>
+TokenAnalyzer::process(bool SkipAnnotation) {
tooling::Replacements Result;
llvm::SpecificBumpPtrAllocator<FormatToken> Allocator;
IdentifierTable IdentTable(getFormattingLangOpts(Style));
@@ -121,7 +122,8 @@ std::pair<tooling::Replacements, unsigned> TokenAnalyzer::process() {
TokenAnnotator Annotator(Style, Lex.getKeywords());
for (const UnwrappedLine &Line : Lines) {
AnnotatedLines.push_back(new AnnotatedLine(Line));
- Annotator.annotate(*AnnotatedLines.back());
+ if (!SkipAnnotation)
+ Annotator.annotate(*AnnotatedLines.back());
}
std::pair<tooling::Replacements, unsigned> RunResult =
diff --git a/clang/lib/Format/TokenAnalyzer.h b/clang/lib/Format/TokenAnalyzer.h
index aaca518df41f..e5cc1287c616 100644
--- a/clang/lib/Format/TokenAnalyzer.h
+++ b/clang/lib/Format/TokenAnalyzer.h
@@ -89,7 +89,8 @@ class TokenAnalyzer : public UnwrappedLineConsumer {
public:
TokenAnalyzer(const Environment &Env, const FormatStyle &Style);
- std::pair<tooling::Replacements, unsigned> process();
+ std::pair<tooling::Replacements, unsigned>
+ process(bool SkipAnnotation = false);
protected:
virtual std::pair<tooling::Replacements, unsigned>
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 5991cf23d5dc..49c30ca78deb 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -71,6 +71,38 @@ static bool isKeywordWithCondition(const FormatToken &Tok) {
tok::kw_constexpr, tok::kw_catch);
}
+/// Returns \c true if the token starts a C++ attribute, \c false otherwise.
+static bool isCppAttribute(bool IsCpp, const FormatToken &Tok) {
+ if (!IsCpp || !Tok.startsSequence(tok::l_square, tok::l_square))
+ return false;
+ // The first square bracket is part of an ObjC array literal
+ if (Tok.Previous && Tok.Previous->is(tok::at))
+ return false;
+ const FormatToken *AttrTok = Tok.Next->Next;
+ if (!AttrTok)
+ return false;
+ // C++17 '[[using ns: foo, bar(baz, blech)]]'
+ // We assume nobody will name an ObjC variable 'using'.
+ if (AttrTok->startsSequence(tok::kw_using, tok::identifier, tok::colon))
+ return true;
+ if (AttrTok->isNot(tok::identifier))
+ return false;
+ while (AttrTok && !AttrTok->startsSequence(tok::r_square, tok::r_square)) {
+ // ObjC message send. We assume nobody will use : in a C++11 attribute
+ // specifier parameter, although this is technically valid:
+ // [[foo(:)]].
+ if (AttrTok->is(tok::colon) ||
+ AttrTok->startsSequence(tok::identifier, tok::identifier) ||
+ AttrTok->startsSequence(tok::r_paren, tok::identifier)) {
+ return false;
+ }
+ if (AttrTok->is(tok::ellipsis))
+ return true;
+ AttrTok = AttrTok->Next;
+ }
+ return AttrTok && AttrTok->startsSequence(tok::r_square, tok::r_square);
+}
+
/// A parser that gathers additional information about tokens.
///
/// The \c TokenAnnotator tries to match parenthesis and square brakets and
@@ -134,10 +166,9 @@ private:
// parameter cases, but should not alter program semantics.
if (CurrentToken->Next && CurrentToken->Next->is(tok::greater) &&
Left->ParentBracket != tok::less &&
- (isKeywordWithCondition(*Line.First) ||
- CurrentToken->getStartOfNonWhitespace() ==
- CurrentToken->Next->getStartOfNonWhitespace().getLocWithOffset(
- -1))) {
+ CurrentToken->getStartOfNonWhitespace() ==
+ CurrentToken->Next->getStartOfNonWhitespace().getLocWithOffset(
+ -1)) {
return false;
}
Left->MatchingParen = CurrentToken;
@@ -238,11 +269,13 @@ private:
}
bool StartsObjCMethodExpr = false;
- if (FormatToken *MaybeSel = OpeningParen.Previous) {
- // @selector( starts a selector.
- if (MaybeSel->isObjCAtKeyword(tok::objc_selector) && MaybeSel->Previous &&
- MaybeSel->Previous->is(tok::at)) {
- StartsObjCMethodExpr = true;
+ if (!Style.isVerilog()) {
+ if (FormatToken *MaybeSel = OpeningParen.Previous) {
+ // @selector( starts a selector.
+ if (MaybeSel->isObjCAtKeyword(tok::objc_selector) &&
+ MaybeSel->Previous && MaybeSel->Previous->is(tok::at)) {
+ StartsObjCMethodExpr = true;
+ }
}
}
@@ -287,6 +320,12 @@ private:
} else if (isLambdaParameterList(&OpeningParen)) {
// This is a parameter list of a lambda expression.
Contexts.back().IsExpression = false;
+ } else if (OpeningParen.is(TT_RequiresExpressionLParen)) {
+ Contexts.back().IsExpression = false;
+ } else if (OpeningParen.Previous &&
+ OpeningParen.Previous->is(tok::kw__Generic)) {
+ Contexts.back().ContextType = Context::C11GenericSelection;
+ Contexts.back().IsExpression = true;
} else if (Line.InPPDirective &&
(!OpeningParen.Previous ||
!OpeningParen.Previous->is(tok::identifier))) {
@@ -300,7 +339,8 @@ private:
Contexts.back().ContextType = Context::ForEachMacro;
Contexts.back().IsExpression = false;
} else if (OpeningParen.Previous && OpeningParen.Previous->MatchingParen &&
- OpeningParen.Previous->MatchingParen->is(TT_ObjCBlockLParen)) {
+ OpeningParen.Previous->MatchingParen->isOneOf(
+ TT_ObjCBlockLParen, TT_FunctionTypeLParen)) {
Contexts.back().IsExpression = false;
} else if (!Line.MustBeDeclaration && !Line.InPPDirective) {
bool IsForOrCatch =
@@ -310,13 +350,15 @@ private:
}
// Infer the role of the l_paren based on the previous token if we haven't
- // detected one one yet.
+ // detected one yet.
if (PrevNonComment && OpeningParen.is(TT_Unknown)) {
if (PrevNonComment->is(tok::kw___attribute)) {
OpeningParen.setType(TT_AttributeParen);
} else if (PrevNonComment->isOneOf(TT_TypenameMacro, tok::kw_decltype,
- tok::kw_typeof, tok::kw__Atomic,
- tok::kw___underlying_type)) {
+ tok::kw_typeof,
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait,
+#include "clang/Basic/TransformTypeTraits.def"
+ tok::kw__Atomic)) {
OpeningParen.setType(TT_TypeDeclarationParen);
// decltype() and typeof() usually contain expressions.
if (PrevNonComment->isOneOf(tok::kw_decltype, tok::kw_typeof))
@@ -357,7 +399,8 @@ private:
FormatToken *Next = CurrentToken->Next;
if (PrevPrev && PrevPrev->is(tok::identifier) &&
Prev->isOneOf(tok::star, tok::amp, tok::ampamp) &&
- CurrentToken->is(tok::identifier) && Next->isNot(tok::equal)) {
+ CurrentToken->is(tok::identifier) &&
+ !Next->isOneOf(tok::equal, tok::l_brace)) {
Prev->setType(TT_BinaryOperator);
LookForDecls = false;
}
@@ -532,34 +575,7 @@ private:
}
bool isCpp11AttributeSpecifier(const FormatToken &Tok) {
- if (!Style.isCpp() || !Tok.startsSequence(tok::l_square, tok::l_square))
- return false;
- // The first square bracket is part of an ObjC array literal
- if (Tok.Previous && Tok.Previous->is(tok::at))
- return false;
- const FormatToken *AttrTok = Tok.Next->Next;
- if (!AttrTok)
- return false;
- // C++17 '[[using ns: foo, bar(baz, blech)]]'
- // We assume nobody will name an ObjC variable 'using'.
- if (AttrTok->startsSequence(tok::kw_using, tok::identifier, tok::colon))
- return true;
- if (AttrTok->isNot(tok::identifier))
- return false;
- while (AttrTok && !AttrTok->startsSequence(tok::r_square, tok::r_square)) {
- // ObjC message send. We assume nobody will use : in a C++11 attribute
- // specifier parameter, although this is technically valid:
- // [[foo(:)]].
- if (AttrTok->is(tok::colon) ||
- AttrTok->startsSequence(tok::identifier, tok::identifier) ||
- AttrTok->startsSequence(tok::r_paren, tok::identifier)) {
- return false;
- }
- if (AttrTok->is(tok::ellipsis))
- return true;
- AttrTok = AttrTok->Next;
- }
- return AttrTok && AttrTok->startsSequence(tok::r_square, tok::r_square);
+ return isCppAttribute(Style.isCpp(), Tok);
}
bool parseSquare() {
@@ -582,8 +598,9 @@ private:
(Contexts.back().CanBeExpression || Contexts.back().IsExpression ||
Contexts.back().ContextType == Context::TemplateArgument);
- bool IsCpp11AttributeSpecifier = isCpp11AttributeSpecifier(*Left) ||
- Contexts.back().InCpp11AttributeSpecifier;
+ const bool IsInnerSquare = Contexts.back().InCpp11AttributeSpecifier;
+ const bool IsCpp11AttributeSpecifier =
+ isCpp11AttributeSpecifier(*Left) || IsInnerSquare;
// Treat C# Attributes [STAThread] much like C++ attributes [[...]].
bool IsCSharpAttributeSpecifier =
@@ -618,6 +635,8 @@ private:
Left->setType(TT_InlineASMSymbolicNameLSquare);
} else if (IsCpp11AttributeSpecifier) {
Left->setType(TT_AttributeSquare);
+ if (!IsInnerSquare && Left->Previous)
+ Left->Previous->EndsCppAttributeGroup = false;
} else if (Style.isJavaScript() && Parent &&
Contexts.back().ContextKind == tok::l_brace &&
Parent->isOneOf(tok::l_brace, tok::comma)) {
@@ -691,8 +710,11 @@ private:
while (CurrentToken) {
if (CurrentToken->is(tok::r_square)) {
- if (IsCpp11AttributeSpecifier)
+ if (IsCpp11AttributeSpecifier) {
CurrentToken->setType(TT_AttributeSquare);
+ if (!IsInnerSquare)
+ CurrentToken->EndsCppAttributeGroup = true;
+ }
if (IsCSharpAttributeSpecifier) {
CurrentToken->setType(TT_AttributeSquare);
} else if (((CurrentToken->Next &&
@@ -761,7 +783,8 @@ private:
// Remember that this is a [[using ns: foo]] C++ attribute, so we
// don't add a space before the colon (unlike other colons).
CurrentToken->setType(TT_AttributeColon);
- } else if (Left->isOneOf(TT_ArraySubscriptLSquare,
+ } else if (!Style.isVerilog() && !Line.InPragmaDirective &&
+ Left->isOneOf(TT_ArraySubscriptLSquare,
TT_DesignatedInitializerLSquare)) {
Left->setType(TT_ObjCMethodExpr);
StartsObjCMethodExpr = true;
@@ -914,6 +937,10 @@ private:
bool consumeToken() {
FormatToken *Tok = CurrentToken;
next();
+ // In Verilog primitives' state tables, `:`, `?`, and `-` aren't normal
+ // operators.
+ if (Tok->is(TT_VerilogTableItem))
+ return true;
switch (Tok->Tok.getKind()) {
case tok::plus:
case tok::minus:
@@ -947,6 +974,25 @@ private:
Tok->setType(TT_CSharpNamedArgumentColon);
break;
}
+ } else if (Style.isVerilog() && Tok->isNot(TT_BinaryOperator)) {
+ // The distribution weight operators are labeled
+ // TT_BinaryOperator by the lexer.
+ if (Keywords.isVerilogEnd(*Tok->Previous) ||
+ Keywords.isVerilogBegin(*Tok->Previous)) {
+ Tok->setType(TT_VerilogBlockLabelColon);
+ } else if (Contexts.back().ContextKind == tok::l_square) {
+ Tok->setType(TT_BitFieldColon);
+ } else if (Contexts.back().ColonIsDictLiteral) {
+ Tok->setType(TT_DictLiteral);
+ } else if (Contexts.size() == 1) {
+ // In Verilog a case label doesn't have the case keyword. We
+ // assume a colon following an expression is a case label.
+ // Colons from ?: are annotated in parseConditional().
+ Tok->setType(TT_GotoLabelColon);
+ if (Line.Level > 1 || (!Line.InPPDirective && Line.Level > 0))
+ --Line.Level;
+ }
+ break;
}
if (Line.First->isOneOf(Keywords.kw_module, Keywords.kw_import) ||
Line.First->startsSequence(tok::kw_export, Keywords.kw_module) ||
@@ -991,6 +1037,8 @@ private:
}
} else if (Contexts.back().ColonIsForRangeExpr) {
Tok->setType(TT_RangeBasedForLoopColon);
+ } else if (Contexts.back().ContextType == Context::C11GenericSelection) {
+ Tok->setType(TT_GenericSelectionColon);
} else if (CurrentToken && CurrentToken->is(tok::numeric_constant)) {
Tok->setType(TT_BitFieldColon);
} else if (Contexts.size() == 1 &&
@@ -1019,7 +1067,8 @@ private:
// This handles a special macro in ObjC code where selectors including
// the colon are passed as macro arguments.
Tok->setType(TT_ObjCMethodExpr);
- } else if (Contexts.back().ContextKind == tok::l_paren) {
+ } else if (Contexts.back().ContextKind == tok::l_paren &&
+ !Line.InPragmaDirective) {
Tok->setType(TT_InlineASMColon);
}
break;
@@ -1035,7 +1084,7 @@ private:
CurrentToken->isOneOf(tok::kw_constexpr, tok::identifier)) {
next();
}
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case tok::kw_while:
if (CurrentToken && CurrentToken->is(tok::l_paren)) {
next();
@@ -1082,7 +1131,7 @@ private:
!Contexts.back().IsExpression && !Line.startsWith(TT_ObjCProperty) &&
!Tok->isOneOf(TT_TypeDeclarationParen, TT_RequiresExpressionLParen) &&
(!Tok->Previous ||
- !Tok->Previous->isOneOf(tok::kw___attribute,
+ !Tok->Previous->isOneOf(tok::kw___attribute, TT_RequiresClause,
TT_LeadingJavaAnnotation))) {
Line.MightBeFunctionDecl = true;
}
@@ -1147,13 +1196,17 @@ private:
if (CurrentToken->isOneOf(tok::star, tok::amp))
CurrentToken->setType(TT_PointerOrReference);
consumeToken();
- if (CurrentToken && CurrentToken->is(tok::comma) &&
+ if (!CurrentToken)
+ continue;
+ if (CurrentToken->is(tok::comma) &&
CurrentToken->Previous->isNot(tok::kw_operator)) {
break;
}
- if (CurrentToken && CurrentToken->Previous->isOneOf(
- TT_BinaryOperator, TT_UnaryOperator, tok::comma,
- tok::star, tok::arrow, tok::amp, tok::ampamp)) {
+ if (CurrentToken->Previous->isOneOf(TT_BinaryOperator, TT_UnaryOperator,
+ tok::comma, tok::star, tok::arrow,
+ tok::amp, tok::ampamp) ||
+ // User defined literal.
+ CurrentToken->Previous->TokenText.startswith("\"\"")) {
CurrentToken->Previous->setType(TT_OverloadedOperator);
}
}
@@ -1215,6 +1268,13 @@ private:
if (Contexts.back().ContextType == Context::ForEachMacro)
Contexts.back().IsExpression = true;
break;
+ case tok::kw_default:
+ // Unindent case labels.
+ if (Style.isVerilog() && Keywords.isVerilogEndOfLabel(*Tok) &&
+ (Line.Level > 1 || (!Line.InPPDirective && Line.Level > 0))) {
+ --Line.Level;
+ }
+ break;
case tok::identifier:
if (Tok->isOneOf(Keywords.kw___has_include,
Keywords.kw___has_include_next)) {
@@ -1224,6 +1284,8 @@ private:
Tok->Next->isNot(tok::l_paren)) {
Tok->setType(TT_CSharpGenericTypeConstraint);
parseCSharpGenericTypeConstraint();
+ if (Tok->getPreviousNonComment() == nullptr)
+ Line.IsContinuation = true;
}
break;
case tok::arrow:
@@ -1232,6 +1294,10 @@ private:
Tok->setType(TT_TrailingReturnArrow);
}
break;
+ case tok::eof:
+ if (Style.InsertNewlineAtEOF && Tok->NewlinesBefore == 0)
+ Tok->NewlinesBefore = 1;
+ break;
default:
break;
}
@@ -1298,11 +1364,12 @@ private:
if (CurrentToken &&
CurrentToken->isOneOf(Keywords.kw_mark, Keywords.kw_option,
Keywords.kw_region)) {
- bool IsMark = CurrentToken->is(Keywords.kw_mark);
+ bool IsMarkOrRegion =
+ CurrentToken->isOneOf(Keywords.kw_mark, Keywords.kw_region);
next();
next(); // Consume first token (so we fix leading whitespace).
while (CurrentToken) {
- if (IsMark || CurrentToken->Previous->is(TT_BinaryOperator))
+ if (IsMarkOrRegion || CurrentToken->Previous->is(TT_BinaryOperator))
CurrentToken->setType(TT_ImplicitStringLiteral);
next();
}
@@ -1390,7 +1457,7 @@ public:
if (!CurrentToken)
return LT_Invalid;
NonTemplateLess.clear();
- if (CurrentToken->is(tok::hash)) {
+ if (!Line.InMacroBody && CurrentToken->is(tok::hash)) {
// We were not yet allowed to use C++17 optional when this was being
// written. So we used LT_Invalid to mark that the line is not a
// preprocessor directive.
@@ -1405,8 +1472,8 @@ public:
IdentifierInfo *Info = CurrentToken->Tok.getIdentifierInfo();
if ((Style.Language == FormatStyle::LK_Java &&
CurrentToken->is(Keywords.kw_package)) ||
- (Info && Info->getPPKeywordID() == tok::pp_import &&
- CurrentToken->Next &&
+ (!Style.isVerilog() && Info &&
+ Info->getPPKeywordID() == tok::pp_import && CurrentToken->Next &&
CurrentToken->Next->isOneOf(tok::string_literal, tok::identifier,
tok::kw_static))) {
next();
@@ -1571,6 +1638,8 @@ private:
StructArrayInitializer,
// Like in `static_cast<int>`.
TemplateArgument,
+ // C11 _Generic selection.
+ C11GenericSelection,
} ContextType = Unknown;
};
@@ -1628,8 +1697,8 @@ private:
if (!Tok)
return false;
- if (Tok->isOneOf(tok::kw_class, tok::kw_enum, tok::kw_concept,
- tok::kw_struct, tok::kw_using)) {
+ if (Tok->isOneOf(tok::kw_class, tok::kw_enum, tok::kw_struct,
+ tok::kw_using)) {
return false;
}
@@ -1754,21 +1823,8 @@ private:
FormatToken *LeadingIdentifier =
Current.Previous->MatchingParen->Previous;
- // Differentiate a deduction guide by seeing the
- // > of the template prior to the leading identifier.
- if (LeadingIdentifier) {
- FormatToken *PriorLeadingIdentifier = LeadingIdentifier->Previous;
- // Skip back past explicit decoration
- if (PriorLeadingIdentifier &&
- PriorLeadingIdentifier->is(tok::kw_explicit)) {
- PriorLeadingIdentifier = PriorLeadingIdentifier->Previous;
- }
-
- return PriorLeadingIdentifier &&
- (PriorLeadingIdentifier->is(TT_TemplateCloser) ||
- PriorLeadingIdentifier->ClosesRequiresClause) &&
- LeadingIdentifier->TokenText == Current.Next->TokenText;
- }
+ return LeadingIdentifier &&
+ LeadingIdentifier->TokenText == Current.Next->TokenText;
}
}
return false;
@@ -1842,7 +1898,8 @@ private:
Current,
Contexts.back().CanBeExpression && Contexts.back().IsExpression,
Contexts.back().ContextType == Context::TemplateArgument));
- } else if (Current.isOneOf(tok::minus, tok::plus, tok::caret)) {
+ } else if (Current.isOneOf(tok::minus, tok::plus, tok::caret) ||
+ (Style.isVerilog() && Current.is(tok::pipe))) {
Current.setType(determinePlusMinusCaretUsage(Current));
if (Current.is(TT_UnaryOperator) && Current.is(tok::caret))
Contexts.back().CaretFound = true;
@@ -1886,7 +1943,7 @@ private:
!Current.Next->isBinaryOperator() &&
!Current.Next->isOneOf(tok::semi, tok::colon, tok::l_brace,
tok::comma, tok::period, tok::arrow,
- tok::coloncolon)) {
+ tok::coloncolon, tok::kw_noexcept)) {
if (FormatToken *AfterParen = Current.MatchingParen->Next) {
// Make sure this isn't the return type of an Obj-C block declaration
if (AfterParen->isNot(tok::caret)) {
@@ -1943,7 +2000,9 @@ private:
} else if (Current.isOneOf(tok::identifier, tok::kw_const, tok::kw_noexcept,
tok::kw_requires) &&
Current.Previous &&
- !Current.Previous->isOneOf(tok::equal, tok::at) &&
+ !Current.Previous->isOneOf(tok::equal, tok::at,
+ TT_CtorInitializerComma,
+ TT_CtorInitializerColon) &&
Line.MightBeFunctionDecl && Contexts.size() == 1) {
// Line.MightBeFunctionDecl can only be true after the parentheses of a
// function declaration have been found.
@@ -2029,6 +2088,12 @@ private:
if (PreviousNotConst->isSimpleTypeSpecifier())
return true;
+ // type[] a in Java
+ if (Style.Language == FormatStyle::LK_Java &&
+ PreviousNotConst->is(tok::r_square)) {
+ return true;
+ }
+
// const a = in JavaScript.
return Style.isJavaScript() && PreviousNotConst->is(tok::kw_const);
}
@@ -2066,6 +2131,9 @@ private:
if (Tok.Previous == Tok.MatchingParen || !Tok.Next || !Tok.MatchingParen)
return false;
+ if (Tok.MatchingParen->is(TT_OverloadedOperatorLParen))
+ return false;
+
FormatToken *LeftOfParens = Tok.MatchingParen->getPreviousNonComment();
if (LeftOfParens) {
// If there is a closing parenthesis left of the current
@@ -2110,7 +2178,7 @@ private:
// before the parentheses, this is unlikely to be a cast.
if (LeftOfParens->Tok.getIdentifierInfo() &&
!LeftOfParens->isOneOf(Keywords.kw_in, tok::kw_return, tok::kw_case,
- tok::kw_delete)) {
+ tok::kw_delete, tok::kw_throw)) {
return false;
}
@@ -2293,7 +2361,8 @@ private:
return TT_BinaryOperator;
if (!NextToken ||
- NextToken->isOneOf(tok::arrow, tok::equal, tok::kw_noexcept) ||
+ NextToken->isOneOf(tok::arrow, tok::equal, tok::kw_noexcept, tok::comma,
+ tok::r_paren) ||
NextToken->canBePointerOrReferenceQualifier() ||
(NextToken->is(tok::l_brace) && !NextToken->getNextNonComment())) {
return TT_PointerOrReference;
@@ -2326,28 +2395,19 @@ private:
// case, the matching `{` is on the same unwrapped line, so check for the
// presence of the matching brace to distinguish between those.
if (PrevToken->is(tok::r_brace) && Tok.is(tok::star) &&
- !PrevToken->MatchingParen)
+ !PrevToken->MatchingParen) {
return TT_PointerOrReference;
+ }
- // For "} &&"
- if (PrevToken->is(tok::r_brace) && Tok.is(tok::ampamp)) {
- const FormatToken *MatchingLBrace = PrevToken->MatchingParen;
-
- // We check whether there is a TemplateCloser(">") to indicate it's a
- // template or not. If it's not a template, "&&" is likely a reference
- // operator.
- // struct {} &&ref = {};
- if (!MatchingLBrace)
- return TT_PointerOrReference;
- FormatToken *BeforeLBrace = MatchingLBrace->getPreviousNonComment();
- if (!BeforeLBrace || BeforeLBrace->isNot(TT_TemplateCloser))
- return TT_PointerOrReference;
-
- // If it is a template, "&&" is a binary operator.
- // enable_if<>{} && ...
- return TT_BinaryOperator;
+ // if (Class* obj { function() })
+ if (PrevToken->Tok.isAnyIdentifier() && NextToken->Tok.isAnyIdentifier() &&
+ NextToken->Next && NextToken->Next->is(tok::l_brace)) {
+ return TT_PointerOrReference;
}
+ if (PrevToken->endsSequence(tok::r_square, tok::l_square, tok::kw_delete))
+ return TT_UnaryOperator;
+
if (PrevToken->Tok.isLiteral() ||
PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::kw_true,
tok::kw_false, tok::r_brace)) {
@@ -2529,7 +2589,7 @@ public:
(Start->Previous &&
Start->Previous->isOneOf(TT_RequiresClause,
TT_RequiresClauseInARequiresExpression))
- ? [this](){
+ ? [this]() {
auto Ret = Current ? Current : Line.Last;
while (!Ret->ClosesRequiresClause && Ret->Previous)
Ret = Ret->Previous;
@@ -2584,13 +2644,19 @@ private:
}
if (Current->is(TT_BinaryOperator) || Current->is(tok::comma))
return Current->getPrecedence();
- if (Current->isOneOf(tok::period, tok::arrow))
+ if (Current->isOneOf(tok::period, tok::arrow) &&
+ Current->isNot(TT_TrailingReturnArrow)) {
return PrecedenceArrowAndPeriod;
+ }
if ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) &&
Current->isOneOf(Keywords.kw_extends, Keywords.kw_implements,
Keywords.kw_throws)) {
return 0;
}
+ // In Verilog case labels are not on separate lines straight out of
+ // UnwrappedLineParser. The colon is not part of an expression.
+ if (Style.isVerilog() && Current->is(tok::colon))
+ return 0;
}
return -1;
}
@@ -2670,15 +2736,18 @@ void TokenAnnotator::setCommentLineLevels(
NextNonCommentLine->First->NewlinesBefore <= 1 &&
NextNonCommentLine->First->OriginalColumn ==
Line->First->OriginalColumn) {
+ const bool PPDirectiveOrImportStmt =
+ NextNonCommentLine->Type == LT_PreprocessorDirective ||
+ NextNonCommentLine->Type == LT_ImportStatement;
+ if (PPDirectiveOrImportStmt)
+ Line->Type = LT_CommentAbovePPDirective;
// Align comments for preprocessor lines with the # in column 0 if
// preprocessor lines are not indented. Otherwise, align with the next
// line.
- Line->Level =
- (Style.IndentPPDirectives != FormatStyle::PPDIS_BeforeHash &&
- (NextNonCommentLine->Type == LT_PreprocessorDirective ||
- NextNonCommentLine->Type == LT_ImportStatement))
- ? 0
- : NextNonCommentLine->Level;
+ Line->Level = Style.IndentPPDirectives != FormatStyle::PPDIS_BeforeHash &&
+ PPDirectiveOrImportStmt
+ ? 0
+ : NextNonCommentLine->Level;
} else {
NextNonCommentLine = Line->First->isNot(tok::r_brace) ? Line : nullptr;
}
@@ -2774,7 +2843,7 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
if (!Current.is(TT_StartOfName) || Current.NestingLevel != 0)
return false;
for (; Next; Next = Next->Next) {
- if (Next->is(TT_TemplateOpener)) {
+ if (Next->is(TT_TemplateOpener) && Next->MatchingParen) {
Next = Next->MatchingParen;
} else if (Next->is(tok::coloncolon)) {
Next = Next->Next;
@@ -2786,6 +2855,10 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
}
if (!Next->is(tok::identifier))
return false;
+ } else if (isCppAttribute(IsCpp, *Next)) {
+ Next = Next->MatchingParen;
+ if (!Next)
+ return false;
} else if (Next->is(tok::l_paren)) {
break;
} else {
@@ -2867,6 +2940,18 @@ bool TokenAnnotator::mustBreakForReturnType(const AnnotatedLine &Line) const {
return false;
}
+static bool mustBreakAfterAttributes(const FormatToken &Tok,
+ const FormatStyle &Style) {
+ switch (Style.BreakAfterAttributes) {
+ case FormatStyle::ABS_Always:
+ return true;
+ case FormatStyle::ABS_Leave:
+ return Tok.NewlinesBefore > 0;
+ default:
+ return false;
+ }
+}
+
void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
for (AnnotatedLine *ChildLine : Line.Children)
calculateFormattingInformation(*ChildLine);
@@ -2882,9 +2967,22 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
if (AlignArrayOfStructures)
calculateArrayInitializerColumnList(Line);
+ for (FormatToken *Tok = Current, *AfterLastAttribute = nullptr; Tok;
+ Tok = Tok->Next) {
+ if (isFunctionDeclarationName(Style.isCpp(), *Tok, Line)) {
+ Tok->setType(TT_FunctionDeclarationName);
+ if (AfterLastAttribute &&
+ mustBreakAfterAttributes(*AfterLastAttribute, Style)) {
+ AfterLastAttribute->MustBreakBefore = true;
+ Line.ReturnTypeWrapped = true;
+ }
+ break;
+ }
+ if (Tok->Previous->EndsCppAttributeGroup)
+ AfterLastAttribute = Tok;
+ }
+
while (Current) {
- if (isFunctionDeclarationName(Style.isCpp(), *Current, Line))
- Current->setType(TT_FunctionDeclarationName);
const FormatToken *Prev = Current->Previous;
if (Current->is(TT_LineComment)) {
if (Prev->is(BK_BracedInit) && Prev->opensScope()) {
@@ -3057,6 +3155,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Left.is(tok::semi))
return 0;
+ // Language specific handling.
if (Style.Language == FormatStyle::LK_Java) {
if (Right.isOneOf(Keywords.kw_extends, Keywords.kw_throws))
return 1;
@@ -3076,13 +3175,16 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
// Prefer breaking call chains (".foo") over empty "{}", "[]" or "()".
if (Left.opensScope() && Right.closesScope())
return 200;
+ } else if (Style.isProto()) {
+ if (Right.is(tok::l_square))
+ return 1;
+ if (Right.is(tok::period))
+ return 500;
}
if (Right.is(tok::identifier) && Right.Next && Right.Next->is(TT_DictLiteral))
return 1;
if (Right.is(tok::l_square)) {
- if (Style.Language == FormatStyle::LK_Proto)
- return 1;
if (Left.is(tok::r_square))
return 200;
// Slightly prefer formatting local lambda definitions like functions.
@@ -3095,10 +3197,8 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
}
}
- if (Left.is(tok::coloncolon) ||
- (Right.is(tok::period) && Style.Language == FormatStyle::LK_Proto)) {
+ if (Left.is(tok::coloncolon))
return 500;
- }
if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName) ||
Right.is(tok::kw_operator)) {
if (Line.startsWith(tok::kw_for) && Right.PartOfMultiVariableDeclStmt)
@@ -3117,7 +3217,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
return 160;
if (Left.is(TT_CastRParen))
return 100;
- if (Left.isOneOf(tok::kw_class, tok::kw_struct))
+ if (Left.isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union))
return 5000;
if (Left.is(tok::comment))
return 1000;
@@ -3193,7 +3293,8 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
return 100;
}
if (Left.is(tok::l_paren) && Left.Previous &&
- (Left.Previous->is(tok::kw_for) || Left.Previous->isIf())) {
+ (Left.Previous->isOneOf(tok::kw_for, tok::kw__Generic) ||
+ Left.Previous->isIf())) {
return 1000;
}
if (Left.is(tok::equal) && InFunctionDecl)
@@ -3281,6 +3382,10 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
!Right.isOneOf(tok::semi, tok::r_paren, tok::hashhash)) {
return true;
}
+ if (Left.is(tok::kw_throw) && Right.is(tok::l_paren) && Right.MatchingParen &&
+ Right.MatchingParen->is(TT_CastRParen)) {
+ return true;
+ }
if (Style.isJson() && Left.is(tok::string_literal) && Right.is(tok::colon))
return false;
if (Left.is(Keywords.kw_assert) && Style.Language == FormatStyle::LK_Java)
@@ -3310,6 +3415,13 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
}
}
+ // trailing return type 'auto': []() -> auto {}, auto foo() -> auto {}
+ if (Left.is(tok::kw_auto) && Right.isOneOf(TT_LambdaLBrace, TT_FunctionLBrace,
+ // function return type 'auto'
+ TT_FunctionTypeLParen)) {
+ return true;
+ }
+
// auto{x} auto(x)
if (Left.is(tok::kw_auto) && Right.isOneOf(tok::l_paren, tok::l_brace))
return false;
@@ -3362,7 +3474,9 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return false;
return !Style.Cpp11BracedListStyle;
}
- return false;
+ // Don't attempt to format operator<(), as it is handled later.
+ if (Right.isNot(TT_OverloadedOperatorLParen))
+ return false;
}
if (Right.is(tok::ellipsis)) {
return Left.Tok.isLiteral() || (Left.is(tok::identifier) && Left.Previous &&
@@ -3424,7 +3538,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (Right.is(TT_BlockComment))
return true;
// foo() -> const Bar * override/final
- if (Right.isOneOf(Keywords.kw_override, Keywords.kw_final) &&
+ if (Right.isOneOf(Keywords.kw_override, Keywords.kw_final,
+ tok::kw_noexcept) &&
!Right.is(TT_StartOfName)) {
return true;
}
@@ -3591,7 +3706,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return true;
if (Left.isOneOf(tok::pp_elif, tok::kw_for, tok::kw_while, tok::kw_switch,
tok::kw_case, TT_ForEachMacro, TT_ObjCForIn) ||
- Left.isIf(Line.Type != LT_PreprocessorDirective)) {
+ Left.isIf(Line.Type != LT_PreprocessorDirective) ||
+ Right.is(TT_ConditionLParen)) {
return Style.SpaceBeforeParensOptions.AfterControlStatements ||
spaceRequiredBeforeParens(Right);
}
@@ -3977,8 +4093,16 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return true;
}
} else if (Style.isVerilog()) {
+ // Add space between things in a primitive's state table unless in a
+ // transition like `(0?)`.
+ if ((Left.is(TT_VerilogTableItem) &&
+ !Right.isOneOf(tok::r_paren, tok::semi)) ||
+ (Right.is(TT_VerilogTableItem) && Left.isNot(tok::l_paren))) {
+ const FormatToken *Next = Right.getNextNonComment();
+ return !(Next && Next->is(tok::r_paren));
+ }
// Don't add space within a delay like `#0`.
- if (!Left.is(TT_BinaryOperator) &&
+ if (Left.isNot(TT_BinaryOperator) &&
Left.isOneOf(Keywords.kw_verilogHash, Keywords.kw_verilogHashHash)) {
return false;
}
@@ -3991,6 +4115,31 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
Left.MatchingParen->endsSequence(tok::l_paren, tok::at)))) {
return true;
}
+ // Don't add embedded spaces in a number literal like `16'h1?ax` or an array
+ // literal like `'{}`.
+ if (Left.is(Keywords.kw_apostrophe) ||
+ (Left.is(TT_VerilogNumberBase) && Right.is(tok::numeric_constant))) {
+ return false;
+ }
+ // Add space between the type name and dimension like `logic [1:0]`.
+ if (Right.is(tok::l_square) &&
+ Left.isOneOf(TT_VerilogDimensionedTypeName, Keywords.kw_function)) {
+ return true;
+ }
+ // Don't add spaces between a casting type and the quote or repetition count
+ // and the brace.
+ if ((Right.is(Keywords.kw_apostrophe) ||
+ (Right.is(BK_BracedInit) && Right.is(tok::l_brace))) &&
+ !(Left.isOneOf(Keywords.kw_assign, Keywords.kw_unique) ||
+ Keywords.isVerilogWordOperator(Left)) &&
+ (Left.isOneOf(tok::r_square, tok::r_paren, tok::r_brace,
+ tok::numeric_constant) ||
+ Keywords.isWordLike(Left))) {
+ return false;
+ }
+ // Add space in attribute like `(* ASYNC_REG = "TRUE" *)`.
+ if (Left.endsSequence(tok::star, tok::l_paren) && Right.is(tok::identifier))
+ return true;
}
if (Left.is(TT_ImplicitStringLiteral))
return Right.hasWhitespaceBefore();
@@ -4032,6 +4181,11 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
Style.BitFieldColonSpacing == FormatStyle::BFCS_After;
}
if (Right.is(tok::colon)) {
+ if (Right.is(TT_GotoLabelColon) ||
+ (!Style.isVerilog() &&
+ Line.First->isOneOf(tok::kw_default, tok::kw_case))) {
+ return Style.SpaceBeforeCaseColon;
+ }
if (Line.First->isOneOf(tok::kw_default, tok::kw_case))
return Style.SpaceBeforeCaseColon;
const FormatToken *Next = Right.getNextNonComment();
@@ -4049,6 +4203,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return false;
if (Right.is(TT_CSharpNamedArgumentColon))
return false;
+ if (Right.is(TT_GenericSelectionColon))
+ return false;
if (Right.is(TT_BitFieldColon)) {
return Style.BitFieldColonSpacing == FormatStyle::BFCS_Both ||
Style.BitFieldColonSpacing == FormatStyle::BFCS_Before;
@@ -4157,7 +4313,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return false;
}
if (Right.is(tok::less) && Left.isNot(tok::l_paren) &&
- Line.startsWith(tok::hash)) {
+ Line.Type == LT_ImportStatement) {
return true;
}
if (Right.is(TT_TrailingUnaryOperator))
@@ -4294,6 +4450,11 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
Right.Next->is(tok::string_literal)) {
return true;
}
+ } else if (Style.isVerilog()) {
+ // Break after labels. In Verilog labels don't have the 'case' keyword, so
+ // it is hard to identify them in UnwrappedLineParser.
+ if (!Keywords.isVerilogBegin(Right) && Keywords.isVerilogEndOfLabel(Left))
+ return true;
} else if (Style.Language == FormatStyle::LK_Cpp ||
Style.Language == FormatStyle::LK_ObjC ||
Style.Language == FormatStyle::LK_Proto ||
@@ -4310,18 +4471,27 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
// }
if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace))
return true;
- // Always break after a JSON array opener.
- // [
- // ]
- if (Left.is(TT_ArrayInitializerLSquare) && Left.is(tok::l_square) &&
- !Right.is(tok::r_square)) {
- return true;
+ // Always break after a JSON array opener based on BreakArrays.
+ if ((Left.is(TT_ArrayInitializerLSquare) && Left.is(tok::l_square) &&
+ Right.isNot(tok::r_square)) ||
+ Left.is(tok::comma)) {
+ if (Right.is(tok::l_brace))
+ return true;
+ // scan to the right if an we see an object or an array inside
+ // then break.
+ for (const auto *Tok = &Right; Tok; Tok = Tok->Next) {
+ if (Tok->isOneOf(tok::l_brace, tok::l_square))
+ return true;
+ if (Tok->isOneOf(tok::r_brace, tok::r_square))
+ break;
+ }
+ return Style.BreakArrays;
}
- // Always break after successive entries.
- // 1,
- // 2
- if (Left.is(tok::comma))
- return true;
+ }
+
+ if (Line.startsWith(tok::kw_asm) && Right.is(TT_InlineASMColon) &&
+ Style.BreakBeforeInlineASMColon == FormatStyle::BBIAS_Always) {
+ return true;
}
// If the last token before a '}', ']', or ')' is a comma or a trailing
@@ -4784,7 +4954,7 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
//
// instead, even if it is longer by one line.
//
- // Note that this allows allows the "{" to go over the column limit
+ // Note that this allows the "{" to go over the column limit
// when the column limit is just between ":" and "{", but that does
// not happen too often and alternative formattings in this case are
// not much better.
@@ -4881,6 +5051,11 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
!Right.MatchingParen) {
return false;
}
+ auto Next = Right.Next;
+ if (Next && Next->is(tok::r_paren))
+ Next = Next->Next;
+ if (Next && Next->is(tok::l_paren))
+ return false;
const FormatToken *Previous = Right.MatchingParen->Previous;
return !(Previous && (Previous->is(tok::kw_for) || Previous->isIf()));
}
@@ -4961,7 +5136,9 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
}
void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) const {
- llvm::errs() << "AnnotatedTokens(L=" << Line.Level << "):\n";
+ llvm::errs() << "AnnotatedTokens(L=" << Line.Level << ", P=" << Line.PPLevel
+ << ", T=" << Line.Type << ", C=" << Line.IsContinuation
+ << "):\n";
const FormatToken *Tok = Line.First;
while (Tok) {
llvm::errs() << " M=" << Tok->MustBreakBefore
diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h
index 1be64ed6d3b5..354511b6323a 100644
--- a/clang/lib/Format/TokenAnnotator.h
+++ b/clang/lib/Format/TokenAnnotator.h
@@ -31,18 +31,23 @@ enum LineType {
LT_PreprocessorDirective,
LT_VirtualFunctionDecl,
LT_ArrayOfStructInitializer,
+ LT_CommentAbovePPDirective,
};
class AnnotatedLine {
public:
AnnotatedLine(const UnwrappedLine &Line)
: First(Line.Tokens.front().Tok), Level(Line.Level),
+ PPLevel(Line.PPLevel),
MatchingOpeningBlockLineIndex(Line.MatchingOpeningBlockLineIndex),
MatchingClosingBlockLineIndex(Line.MatchingClosingBlockLineIndex),
InPPDirective(Line.InPPDirective),
+ InPragmaDirective(Line.InPragmaDirective),
+ InMacroBody(Line.InMacroBody),
MustBeDeclaration(Line.MustBeDeclaration), MightBeFunctionDecl(false),
IsMultiVariableDeclStmt(false), Affected(false),
LeadingEmptyLinesAffected(false), ChildrenAffected(false),
+ ReturnTypeWrapped(false), IsContinuation(Line.IsContinuation),
FirstStartColumn(Line.FirstStartColumn) {
assert(!Line.Tokens.empty());
@@ -125,9 +130,12 @@ public:
LineType Type;
unsigned Level;
+ unsigned PPLevel;
size_t MatchingOpeningBlockLineIndex;
size_t MatchingClosingBlockLineIndex;
bool InPPDirective;
+ bool InPragmaDirective;
+ bool InMacroBody;
bool MustBeDeclaration;
bool MightBeFunctionDecl;
bool IsMultiVariableDeclStmt;
@@ -143,6 +151,13 @@ public:
/// \c True if one of this line's children intersects with an input range.
bool ChildrenAffected;
+ /// \c True if breaking after last attribute group in function return type.
+ bool ReturnTypeWrapped;
+
+ /// \c True if this line should be indented by ContinuationIndent in addition
+ /// to the normal indention level.
+ bool IsContinuation;
+
unsigned FirstStartColumn;
private:
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp
index abeb93d23776..8e1d907208c0 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -60,16 +60,23 @@ public:
// Update the indent level cache size so that we can rely on it
// having the right size in adjustToUnmodifiedline.
skipLine(Line, /*UnknownIndent=*/true);
- if (Line.InPPDirective) {
- unsigned IndentWidth =
+ if (Style.IndentPPDirectives != FormatStyle::PPDIS_None &&
+ (Line.InPPDirective ||
+ (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
+ Line.Type == LT_CommentAbovePPDirective))) {
+ unsigned PPIndentWidth =
(Style.PPIndentWidth >= 0) ? Style.PPIndentWidth : Style.IndentWidth;
- Indent = Line.Level * IndentWidth + AdditionalIndent;
+ Indent = Line.InMacroBody
+ ? Line.PPLevel * PPIndentWidth +
+ (Line.Level - Line.PPLevel) * Style.IndentWidth
+ : Line.Level * PPIndentWidth;
+ Indent += AdditionalIndent;
} else {
Indent = getIndent(Line.Level);
}
if (static_cast<int>(Indent) + Offset >= 0)
Indent += Offset;
- if (Line.First->is(TT_CSharpGenericTypeConstraint))
+ if (Line.IsContinuation)
Indent = Line.Level * Style.IndentWidth + Style.ContinuationIndentWidth;
}
@@ -641,6 +648,7 @@ private:
unsigned Length = 0;
bool EndsWithComment = false;
bool InPPDirective = I[0]->InPPDirective;
+ bool InMacroBody = I[0]->InMacroBody;
const unsigned Level = I[0]->Level;
for (; NumStmts < 3; ++NumStmts) {
if (I + 1 + NumStmts == E)
@@ -648,6 +656,8 @@ private:
const AnnotatedLine *Line = I[1 + NumStmts];
if (Line->InPPDirective != InPPDirective)
break;
+ if (Line->InMacroBody != InMacroBody)
+ break;
if (Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace))
break;
if (Line->First->isOneOf(tok::kw_if, tok::kw_for, tok::kw_switch,
@@ -709,16 +719,23 @@ private:
if (Tok && Tok->is(tok::colon))
return 0;
}
- if (Line.First->isOneOf(tok::kw_if, tok::kw_else, tok::kw_while, tok::kw_do,
- tok::kw_try, tok::kw___try, tok::kw_catch,
- tok::kw___finally, tok::kw_for, TT_ForEachMacro,
- tok::r_brace, Keywords.kw___except)) {
- if (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never)
- return 0;
- if (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Empty &&
- !I[1]->First->is(tok::r_brace)) {
+
+ auto IsCtrlStmt = [](const auto &Line) {
+ return Line.First->isOneOf(tok::kw_if, tok::kw_else, tok::kw_while,
+ tok::kw_do, tok::kw_for, TT_ForEachMacro);
+ };
+
+ const bool IsSplitBlock =
+ Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never ||
+ (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Empty &&
+ I[1]->First->isNot(tok::r_brace));
+
+ if (IsCtrlStmt(Line) ||
+ Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch,
+ tok::kw___finally, tok::r_brace,
+ Keywords.kw___except)) {
+ if (IsSplitBlock)
return 0;
- }
// Don't merge when we can't except the case when
// the control statement block is empty
if (!Style.AllowShortIfStatementsOnASingleLine &&
@@ -761,6 +778,11 @@ private:
}
if (Line.Last->is(tok::l_brace)) {
+ if (IsSplitBlock && Line.First == Line.Last &&
+ I > AnnotatedLines.begin() &&
+ (I[-1]->endsWith(tok::kw_else) || IsCtrlStmt(*I[-1]))) {
+ return 0;
+ }
FormatToken *Tok = I[1]->First;
auto ShouldMerge = [Tok]() {
if (Tok->isNot(tok::r_brace) || Tok->MustBreakBefore)
@@ -1297,7 +1319,7 @@ unsigned UnwrappedLineFormatter::format(
// We continue formatting unchanged lines to adjust their indent, e.g. if a
// scope was added. However, we need to carefully stop doing this when we
- // exit the scope of affected lines to prevent indenting a the entire
+ // exit the scope of affected lines to prevent indenting the entire
// remaining file if it currently missing a closing brace.
bool PreviousRBrace =
PreviousLine && PreviousLine->startsWith(tok::r_brace);
diff --git a/clang/lib/Format/UnwrappedLineFormatter.h b/clang/lib/Format/UnwrappedLineFormatter.h
index 3e33de07fa12..ee6d31de8c42 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.h
+++ b/clang/lib/Format/UnwrappedLineFormatter.h
@@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// Implements a combinartorial exploration of all the different
+/// Implements a combinatorial exploration of all the different
/// linebreaks unwrapped lines can be formatted in.
///
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 83b4f1e7991f..3e58b6f90559 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -41,13 +41,7 @@ public:
// Returns the token that would be returned by the next call to
// getNextToken().
- virtual FormatToken *peekNextToken() = 0;
-
- // Returns the token that would be returned after the next N calls to
- // getNextToken(). N needs to be greater than zero, and small enough that
- // there are still tokens. Check for tok::eof with N-1 before calling it with
- // N.
- virtual FormatToken *peekNextToken(int N) = 0;
+ virtual FormatToken *peekNextToken(bool SkipComment = false) = 0;
// Returns whether we are at the end of the file.
// This can be different from whether getNextToken() returned an eof token
@@ -64,6 +58,39 @@ public:
namespace {
+void printLine(llvm::raw_ostream &OS, const UnwrappedLine &Line,
+ StringRef Prefix = "", bool PrintText = false) {
+ OS << Prefix << "Line(" << Line.Level << ", FSC=" << Line.FirstStartColumn
+ << ")" << (Line.InPPDirective ? " MACRO" : "") << ": ";
+ bool NewLine = false;
+ for (std::list<UnwrappedLineNode>::const_iterator I = Line.Tokens.begin(),
+ E = Line.Tokens.end();
+ I != E; ++I) {
+ if (NewLine) {
+ OS << Prefix;
+ NewLine = false;
+ }
+ OS << I->Tok->Tok.getName() << "["
+ << "T=" << (unsigned)I->Tok->getType()
+ << ", OC=" << I->Tok->OriginalColumn << ", \"" << I->Tok->TokenText
+ << "\"] ";
+ for (SmallVectorImpl<UnwrappedLine>::const_iterator
+ CI = I->Children.begin(),
+ CE = I->Children.end();
+ CI != CE; ++CI) {
+ OS << "\n";
+ printLine(OS, *CI, (Prefix + " ").str());
+ NewLine = true;
+ }
+ }
+ if (!NewLine)
+ OS << "\n";
+}
+
+LLVM_ATTRIBUTE_UNUSED static void printDebugInfo(const UnwrappedLine &Line) {
+ printLine(llvm::dbgs(), Line);
+}
+
class ScopedDeclarationState {
public:
ScopedDeclarationState(UnwrappedLine &Line, llvm::BitVector &Stack,
@@ -116,12 +143,14 @@ public:
TokenSource = this;
Line.Level = 0;
Line.InPPDirective = true;
+ // InMacroBody gets set after the `#define x` part.
}
~ScopedMacroState() override {
TokenSource = PreviousTokenSource;
ResetToken = Token;
Line.InPPDirective = false;
+ Line.InMacroBody = false;
Line.Level = PreviousLineLevel;
}
@@ -140,17 +169,10 @@ public:
return PreviousTokenSource->getPreviousToken();
}
- FormatToken *peekNextToken() override {
+ FormatToken *peekNextToken(bool SkipComment) override {
if (eof())
return &FakeEOF;
- return PreviousTokenSource->peekNextToken();
- }
-
- FormatToken *peekNextToken(int N) override {
- assert(N > 0);
- if (eof())
- return &FakeEOF;
- return PreviousTokenSource->peekNextToken(N);
+ return PreviousTokenSource->peekNextToken(SkipComment);
}
bool isEOF() override { return PreviousTokenSource->isEOF(); }
@@ -195,7 +217,9 @@ public:
PreBlockLine = std::move(Parser.Line);
Parser.Line = std::make_unique<UnwrappedLine>();
Parser.Line->Level = PreBlockLine->Level;
+ Parser.Line->PPLevel = PreBlockLine->PPLevel;
Parser.Line->InPPDirective = PreBlockLine->InPPDirective;
+ Parser.Line->InMacroBody = PreBlockLine->InMacroBody;
}
~ScopedLineState() {
@@ -245,7 +269,7 @@ public:
: Tokens(Tokens), Position(-1) {}
FormatToken *getNextToken() override {
- if (Position >= 0 && Tokens[Position]->is(tok::eof)) {
+ if (Position >= 0 && isEOF()) {
LLVM_DEBUG({
llvm::dbgs() << "Next ";
dbgToken(Position);
@@ -264,8 +288,11 @@ public:
return Position > 0 ? Tokens[Position - 1] : nullptr;
}
- FormatToken *peekNextToken() override {
+ FormatToken *peekNextToken(bool SkipComment) override {
int Next = Position + 1;
+ if (SkipComment)
+ while (Tokens[Next]->is(tok::comment))
+ ++Next;
LLVM_DEBUG({
llvm::dbgs() << "Peeking ";
dbgToken(Next);
@@ -273,16 +300,6 @@ public:
return Tokens[Next];
}
- FormatToken *peekNextToken(int N) override {
- assert(N > 0);
- int Next = Position + N;
- LLVM_DEBUG({
- llvm::dbgs() << "Peeking (+" << (N - 1) << ") ";
- dbgToken(Next);
- });
- return Tokens[Next];
- }
-
bool isEOF() override { return Tokens[Position]->is(tok::eof); }
unsigned getPosition() override {
@@ -573,12 +590,16 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace,
break;
}
// Else, if it is 'default:', fall through to the case handling.
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
}
case tok::kw_case:
- if (Style.isJavaScript() && Line->MustBeDeclaration) {
- // A 'case: string' style field declaration.
- parseStructuralElement();
+ if (Style.isProto() || Style.isVerilog() ||
+ (Style.isJavaScript() && Line->MustBeDeclaration)) {
+ // Proto: there are no switch/case statements
+ // Verilog: Case labels don't have this word. We handle case
+ // labels including default in TokenAnnotator.
+ // JavaScript: A 'case: string' style field declaration.
+ ParseDefault();
break;
}
if (!SwitchLabelEncountered &&
@@ -597,7 +618,7 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace,
}
if (handleCppAttributes())
break;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
default:
ParseDefault();
break;
@@ -733,7 +754,7 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
case tok::identifier:
if (!Tok->is(TT_StatementMacro))
break;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case tok::at:
case tok::semi:
case tok::kw_if:
@@ -812,9 +833,18 @@ bool UnwrappedLineParser::mightFitOnOneLine(
auto Length = LastToken->TotalLength;
if (OpeningBrace) {
assert(OpeningBrace != Tokens.front().Tok);
+ if (auto Prev = OpeningBrace->Previous;
+ Prev && Prev->TotalLength + ColumnLimit == OpeningBrace->TotalLength) {
+ Length -= ColumnLimit;
+ }
Length -= OpeningBrace->TokenText.size() + 1;
}
+ if (const auto *FirstToken = Line.First; FirstToken->is(tok::r_brace)) {
+ assert(!OpeningBrace || OpeningBrace->is(TT_ControlStatementLBrace));
+ Length -= FirstToken->TokenText.size() + 1;
+ }
+
Index = 0;
for (auto &Token : Tokens) {
const auto &SavedToken = SavedTokens[Index++];
@@ -823,6 +853,9 @@ bool UnwrappedLineParser::mightFitOnOneLine(
delete SavedToken.Tok;
}
+ // If these change PPLevel needs to be used for get correct indentation.
+ assert(!Line.InMacroBody);
+ assert(!Line.InPPDirective);
return Line.Level * Style.IndentWidth + Length <= ColumnLimit;
}
@@ -839,8 +872,13 @@ FormatToken *UnwrappedLineParser::parseBlock(
}
};
+ // Whether this is a Verilog-specific block that has a special header like a
+ // module.
+ const bool VerilogHierarchy =
+ Style.isVerilog() && Keywords.isVerilogHierarchy(*FormatTok);
assert((FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) ||
- (Style.isVerilog() && Keywords.isVerilogBegin(*FormatTok))) &&
+ (Style.isVerilog() &&
+ (Keywords.isVerilogBegin(*FormatTok) || VerilogHierarchy))) &&
"'{' or macro block token expected");
FormatToken *Tok = FormatTok;
const bool FollowedByComment = Tokens->peekNextToken()->is(tok::comment);
@@ -850,14 +888,20 @@ FormatToken *UnwrappedLineParser::parseBlock(
// For Whitesmiths mode, jump to the next level prior to skipping over the
// braces.
- if (AddLevels > 0 && Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths)
+ if (!VerilogHierarchy && AddLevels > 0 &&
+ Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) {
++Line->Level;
+ }
size_t PPStartHash = computePPHash();
const unsigned InitialLevel = Line->Level;
- nextToken(/*LevelDifference=*/AddLevels);
- HandleVerilogBlockLabel();
+ if (VerilogHierarchy) {
+ AddLevels += parseVerilogHierarchyHeader();
+ } else {
+ nextToken(/*LevelDifference=*/AddLevels);
+ HandleVerilogBlockLabel();
+ }
// Bail out if there are too many levels. Otherwise, the stack might overflow.
if (Line->Level > 300)
@@ -899,6 +943,9 @@ FormatToken *UnwrappedLineParser::parseBlock(
return IfLBrace;
}
+ const bool IsFunctionRBrace =
+ FormatTok->is(tok::r_brace) && Tok->is(TT_FunctionLBrace);
+
auto RemoveBraces = [=]() mutable {
if (!SimpleBlock)
return false;
@@ -938,11 +985,24 @@ FormatToken *UnwrappedLineParser::parseBlock(
// Munch the closing brace.
nextToken(/*LevelDifference=*/-AddLevels);
+
+ // When this is a function block and there is an unnecessary semicolon
+ // afterwards then mark it as optional (so the RemoveSemi pass can get rid of
+ // it later).
+ if (Style.RemoveSemicolon && IsFunctionRBrace) {
+ while (FormatTok->is(tok::semi)) {
+ FormatTok->Optional = true;
+ nextToken();
+ }
+ }
+
HandleVerilogBlockLabel();
if (MacroBlock && FormatTok->is(tok::l_paren))
parseParens();
+ Line->Level = InitialLevel;
+
if (FormatTok->is(tok::kw_noexcept)) {
// A noexcept in a requires expression.
nextToken();
@@ -958,8 +1018,6 @@ FormatToken *UnwrappedLineParser::parseBlock(
if (MunchSemi && FormatTok->is(tok::semi))
nextToken();
- Line->Level = InitialLevel;
-
if (PPStartHash == PPEndHash) {
Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
if (OpeningLineIndex != UnwrappedLine::kInvalidIndex) {
@@ -1073,16 +1131,17 @@ void UnwrappedLineParser::parsePPDirective() {
parsePPIf(/*IfDef=*/true);
break;
case tok::pp_else:
- parsePPElse();
- break;
case tok::pp_elifdef:
case tok::pp_elifndef:
case tok::pp_elif:
- parsePPElIf();
+ parsePPElse();
break;
case tok::pp_endif:
parsePPEndIf();
break;
+ case tok::pp_pragma:
+ parsePPPragma();
+ break;
default:
parsePPUnknown();
break;
@@ -1109,7 +1168,7 @@ void UnwrappedLineParser::conditionalCompilationStart(bool Unreachable) {
PPLevelBranchIndex.push_back(0);
PPLevelBranchCount.push_back(0);
}
- PPChainBranchIndex.push(0);
+ PPChainBranchIndex.push(Unreachable ? -1 : 0);
bool Skip = PPLevelBranchIndex[PPBranchLevel] > 0;
conditionalCompilationCondition(Unreachable || Skip);
}
@@ -1175,15 +1234,16 @@ void UnwrappedLineParser::parsePPElse() {
// If a potential include guard has an #else, it's not an include guard.
if (IncludeGuard == IG_Defined && PPBranchLevel == 0)
IncludeGuard = IG_Rejected;
+ // Don't crash when there is an #else without an #if.
+ assert(PPBranchLevel >= -1);
+ if (PPBranchLevel == -1)
+ conditionalCompilationStart(/*Unreachable=*/true);
conditionalCompilationAlternative();
- if (PPBranchLevel > -1)
- --PPBranchLevel;
+ --PPBranchLevel;
parsePPUnknown();
++PPBranchLevel;
}
-void UnwrappedLineParser::parsePPElIf() { parsePPElse(); }
-
void UnwrappedLineParser::parsePPEndIf() {
conditionalCompilationEnd();
parsePPUnknown();
@@ -1234,6 +1294,10 @@ void UnwrappedLineParser::parsePPDefine() {
addUnwrappedLine();
++Line->Level;
+ Line->PPLevel = PPBranchLevel + (IncludeGuard == IG_Defined ? 0 : 1);
+ assert((int)Line->PPLevel >= 0);
+ Line->InMacroBody = true;
+
// Errors during a preprocessor directive can only affect the layout of the
// preprocessor directive, and thus we ignore them. An alternative approach
// would be to use the same approach we use on the file level (no
@@ -1242,6 +1306,11 @@ void UnwrappedLineParser::parsePPDefine() {
parseFile();
}
+void UnwrappedLineParser::parsePPPragma() {
+ Line->InPragmaDirective = true;
+ parsePPUnknown();
+}
+
void UnwrappedLineParser::parsePPUnknown() {
do {
nextToken();
@@ -1369,7 +1438,15 @@ static bool isC78ParameterDecl(const FormatToken *Tok, const FormatToken *Next,
return Tok->Previous && Tok->Previous->isOneOf(tok::l_paren, tok::comma);
}
-void UnwrappedLineParser::parseModuleImport() {
+bool UnwrappedLineParser::parseModuleImport() {
+ assert(FormatTok->is(Keywords.kw_import) && "'import' expected");
+
+ if (auto Token = Tokens->peekNextToken(/*SkipComment=*/true);
+ !Token->Tok.getIdentifierInfo() &&
+ !Token->isOneOf(tok::colon, tok::less, tok::string_literal)) {
+ return false;
+ }
+
nextToken();
while (!eof()) {
if (FormatTok->is(tok::colon)) {
@@ -1396,6 +1473,7 @@ void UnwrappedLineParser::parseModuleImport() {
}
addUnwrappedLine();
+ return true;
}
// readTokenWithJavaScriptASI reads the next token and terminates the current
@@ -1457,13 +1535,30 @@ void UnwrappedLineParser::parseStructuralElement(
addUnwrappedLine();
return;
}
+
+ if (Style.isVerilog()) {
+ // Skip things that can exist before keywords like 'if' and 'case'.
+ while (true) {
+ if (FormatTok->isOneOf(Keywords.kw_priority, Keywords.kw_unique,
+ Keywords.kw_unique0)) {
+ nextToken();
+ } else if (FormatTok->is(tok::l_paren) &&
+ Tokens->peekNextToken()->is(tok::star)) {
+ parseParens();
+ } else {
+ break;
+ }
+ }
+ }
+
+ // Tokens that only make sense at the beginning of a line.
switch (FormatTok->Tok.getKind()) {
case tok::kw_asm:
nextToken();
if (FormatTok->is(tok::l_brace)) {
FormatTok->setFinalizedType(TT_InlineASMBrace);
nextToken();
- while (FormatTok && FormatTok->isNot(tok::eof)) {
+ while (FormatTok && !eof()) {
if (FormatTok->is(tok::r_brace)) {
FormatTok->setFinalizedType(TT_InlineASMBrace);
nextToken();
@@ -1523,6 +1618,9 @@ void UnwrappedLineParser::parseStructuralElement(
parseSwitch();
return;
case tok::kw_default:
+ // In Verilog default along with other labels are handled in the next loop.
+ if (Style.isVerilog())
+ break;
if (Style.isJavaScript() && Line->MustBeDeclaration) {
// 'default: string' field declaration.
break;
@@ -1535,6 +1633,16 @@ void UnwrappedLineParser::parseStructuralElement(
// e.g. "default void f() {}" in a Java interface.
break;
case tok::kw_case:
+ // Proto: there are no switch/case statements.
+ if (Style.isProto()) {
+ nextToken();
+ return;
+ }
+ if (Style.isVerilog()) {
+ parseBlock();
+ addUnwrappedLine();
+ return;
+ }
if (Style.isJavaScript() && Line->MustBeDeclaration) {
// 'case: string' field declaration.
nextToken();
@@ -1552,7 +1660,14 @@ void UnwrappedLineParser::parseStructuralElement(
return;
case tok::kw_extern:
nextToken();
- if (FormatTok->is(tok::string_literal)) {
+ if (Style.isVerilog()) {
+ // In Verilog and extern module declaration looks like a start of module.
+ // But there is no body and endmodule. So we handle it separately.
+ if (Keywords.isVerilogHierarchy(*FormatTok)) {
+ parseVerilogHierarchyHeader();
+ return;
+ }
+ } else if (FormatTok->is(tok::string_literal)) {
nextToken();
if (FormatTok->is(tok::l_brace)) {
if (Style.BraceWrapping.AfterExternBlock)
@@ -1577,10 +1692,16 @@ void UnwrappedLineParser::parseStructuralElement(
parseJavaScriptEs6ImportExport();
return;
}
- if (!Style.isCpp())
- break;
- // Handle C++ "(inline|export) namespace".
- LLVM_FALLTHROUGH;
+ if (Style.isCpp()) {
+ nextToken();
+ if (FormatTok->is(tok::kw_namespace)) {
+ parseNamespace();
+ return;
+ }
+ if (FormatTok->is(Keywords.kw_import) && parseModuleImport())
+ return;
+ }
+ break;
case tok::kw_inline:
nextToken();
if (FormatTok->is(tok::kw_namespace)) {
@@ -1615,10 +1736,8 @@ void UnwrappedLineParser::parseStructuralElement(
addUnwrappedLine();
return;
}
- if (Style.isCpp()) {
- parseModuleImport();
+ if (Style.isCpp() && parseModuleImport())
return;
- }
}
if (Style.isCpp() &&
FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,
@@ -1712,9 +1831,6 @@ void UnwrappedLineParser::parseStructuralElement(
break;
}
break;
- case tok::kw_concept:
- parseConcept();
- return;
case tok::kw_requires: {
if (Style.isCpp()) {
bool ParsedClause = parseRequires();
@@ -1751,9 +1867,15 @@ void UnwrappedLineParser::parseStructuralElement(
parseEnum();
}
break;
+ case tok::kw_class:
+ if (Style.isVerilog()) {
+ parseBlock();
+ addUnwrappedLine();
+ return;
+ }
+ [[fallthrough]];
case tok::kw_struct:
case tok::kw_union:
- case tok::kw_class:
if (parseStructLike())
return;
break;
@@ -1782,9 +1904,11 @@ void UnwrappedLineParser::parseStructuralElement(
parseParens();
// Break the unwrapped line if a K&R C function definition has a parameter
// declaration.
- if (!IsTopLevel || !Style.isCpp() || !Previous || FormatTok->is(tok::eof))
+ if (!IsTopLevel || !Style.isCpp() || !Previous || eof())
break;
- if (isC78ParameterDecl(FormatTok, Tokens->peekNextToken(), Previous)) {
+ if (isC78ParameterDecl(FormatTok,
+ Tokens->peekNextToken(/*SkipComment=*/true),
+ Previous)) {
addUnwrappedLine();
return;
}
@@ -1825,8 +1949,7 @@ void UnwrappedLineParser::parseStructuralElement(
} else if (Style.BraceWrapping.AfterFunction) {
addUnwrappedLine();
}
- if (!Line->InPPDirective)
- FormatTok->setFinalizedType(TT_FunctionLBrace);
+ FormatTok->setFinalizedType(TT_FunctionLBrace);
parseBlock();
addUnwrappedLine();
return;
@@ -1888,6 +2011,19 @@ void UnwrappedLineParser::parseStructuralElement(
return;
}
+ if (Style.isVerilog()) {
+ if (FormatTok->is(Keywords.kw_table)) {
+ parseVerilogTable();
+ return;
+ }
+ if (Keywords.isVerilogBegin(*FormatTok) ||
+ Keywords.isVerilogHierarchy(*FormatTok)) {
+ parseBlock();
+ addUnwrappedLine();
+ return;
+ }
+ }
+
if (FormatTok->is(Keywords.kw_interface)) {
if (parseStructLike())
return;
@@ -1919,7 +2055,9 @@ void UnwrappedLineParser::parseStructuralElement(
return I != E && (++I == E);
};
if (OneTokenSoFar()) {
- if (FormatTok->is(tok::colon) && !Line->MustBeDeclaration) {
+ // In Verilog labels can be any expression, so we don't do them here.
+ if (!Style.isVerilog() && FormatTok->is(tok::colon) &&
+ !Line->MustBeDeclaration) {
Line->Tokens.begin()->Tok->MustBreakBefore = true;
parseLabel(!Style.IndentGotoLabels);
if (HasLabel)
@@ -1939,7 +2077,8 @@ void UnwrappedLineParser::parseStructuralElement(
if (FollowedByNewline && (Text.size() >= 5 || FunctionLike) &&
tokenCanStartNewLine(*FormatTok) && Text == Text.upper()) {
- PreviousToken->setFinalizedType(TT_FunctionLikeOrFreestandingMacro);
+ if (PreviousToken->isNot(TT_UntouchableMacroFunc))
+ PreviousToken->setFinalizedType(TT_FunctionLikeOrFreestandingMacro);
addUnwrappedLine();
return;
}
@@ -1976,6 +2115,17 @@ void UnwrappedLineParser::parseStructuralElement(
parseNew();
break;
case tok::kw_case:
+ // Proto: there are no switch/case statements.
+ if (Style.isProto()) {
+ nextToken();
+ return;
+ }
+ // In Verilog switch is called case.
+ if (Style.isVerilog()) {
+ parseBlock();
+ addUnwrappedLine();
+ return;
+ }
if (Style.isJavaScript() && Line->MustBeDeclaration) {
// 'case: string' field declaration.
nextToken();
@@ -1983,6 +2133,30 @@ void UnwrappedLineParser::parseStructuralElement(
}
parseCaseLabel();
break;
+ case tok::kw_default:
+ nextToken();
+ if (Style.isVerilog()) {
+ if (FormatTok->is(tok::colon)) {
+ // The label will be handled in the next iteration.
+ break;
+ }
+ if (FormatTok->is(Keywords.kw_clocking)) {
+ // A default clocking block.
+ parseBlock();
+ addUnwrappedLine();
+ return;
+ }
+ parseVerilogCaseLabel();
+ return;
+ }
+ break;
+ case tok::colon:
+ nextToken();
+ if (Style.isVerilog()) {
+ parseVerilogCaseLabel();
+ return;
+ }
+ break;
default:
nextToken();
break;
@@ -2108,26 +2282,29 @@ bool UnwrappedLineParser::tryToParseLambda() {
case tok::l_square:
parseSquare();
break;
- case tok::kw_class:
- case tok::kw_template:
- case tok::kw_typename:
+ case tok::less:
assert(FormatTok->Previous);
- if (FormatTok->Previous->is(tok::less))
+ if (FormatTok->Previous->is(tok::r_square))
InTemplateParameterList = true;
nextToken();
break;
+ case tok::kw_auto:
+ case tok::kw_class:
+ case tok::kw_template:
+ case tok::kw_typename:
case tok::amp:
case tok::star:
case tok::kw_const:
case tok::kw_constexpr:
+ case tok::kw_consteval:
case tok::comma:
- case tok::less:
case tok::greater:
case tok::identifier:
case tok::numeric_constant:
case tok::coloncolon:
case tok::kw_mutable:
case tok::kw_noexcept:
+ case tok::kw_static:
nextToken();
break;
// Specialization of a template with an integer parameter can contain
@@ -2201,7 +2378,7 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
if (FormatTok->is(tok::l_square))
return false;
if (FormatTok->is(tok::r_square)) {
- const FormatToken *Next = Tokens->peekNextToken();
+ const FormatToken *Next = Tokens->peekNextToken(/*SkipComment=*/true);
if (Next->is(tok::greater))
return false;
}
@@ -2432,7 +2609,7 @@ void UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) {
case tok::ampamp:
if (AmpAmpTokenType != TT_Unknown)
FormatTok->setFinalizedType(AmpAmpTokenType);
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
default:
nextToken();
break;
@@ -2502,8 +2679,10 @@ void UnwrappedLineParser::parseUnbracedBody(bool CheckEOF) {
FormatToken *Tok = nullptr;
if (Style.InsertBraces && !Line->InPPDirective && !Line->Tokens.empty() &&
- PreprocessorDirectives.empty()) {
- Tok = getLastNonComment(*Line);
+ PreprocessorDirectives.empty() && FormatTok->isNot(tok::semi)) {
+ Tok = Style.BraceWrapping.AfterControlStatement == FormatStyle::BWACS_Never
+ ? getLastNonComment(*Line)
+ : Line->Tokens.back().Tok;
assert(Tok);
if (Tok->BraceCount < 0) {
assert(Tok->BraceCount == -1);
@@ -2530,7 +2709,7 @@ void UnwrappedLineParser::parseUnbracedBody(bool CheckEOF) {
++Tok->BraceCount;
}
- if (CheckEOF && FormatTok->is(tok::eof))
+ if (CheckEOF && eof())
addUnwrappedLine();
--Line->Level;
@@ -2572,6 +2751,14 @@ bool UnwrappedLineParser::handleCppAttributes() {
return false;
}
+/// Returns whether \c Tok begins a block.
+bool UnwrappedLineParser::isBlockBegin(const FormatToken &Tok) const {
+ // FIXME: rename the function or make
+ // Tok.isOneOf(tok::l_brace, TT_MacroBlockBegin) work.
+ return Style.isVerilog() ? Keywords.isVerilogBegin(Tok)
+ : Tok.is(tok::l_brace);
+}
+
FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
bool KeepBraces) {
assert(FormatTok->is(tok::kw_if) && "'if' expected");
@@ -2597,7 +2784,7 @@ FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
FormatToken *IfLeftBrace = nullptr;
IfStmtKind IfBlockKind = IfStmtKind::NotIf;
- if (Keywords.isBlockBegin(*FormatTok, Style)) {
+ if (isBlockBegin(*FormatTok)) {
FormatTok->setFinalizedType(TT_ControlStatementLBrace);
IfLeftBrace = FormatTok;
CompoundStatementIndenter Indenter(this, Style, Line->Level);
@@ -2630,7 +2817,7 @@ FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
}
nextToken();
handleAttributes();
- if (Keywords.isBlockBegin(*FormatTok, Style)) {
+ if (isBlockBegin(*FormatTok)) {
const bool FollowedByIf = Tokens->peekNextToken()->is(tok::kw_if);
FormatTok->setFinalizedType(TT_ElseLBrace);
ElseLeftBrace = FormatTok;
@@ -2862,6 +3049,11 @@ void UnwrappedLineParser::parseNew() {
if (Style.isCSharp()) {
do {
+ // Handle constructor invocation, e.g. `new(field: value)`.
+ if (FormatTok->is(tok::l_paren))
+ parseParens();
+
+ // Handle array initialization syntax, e.g. `new[] {10, 20, 30}`.
if (FormatTok->is(tok::l_brace))
parseBracedList();
@@ -2897,7 +3089,7 @@ void UnwrappedLineParser::parseNew() {
void UnwrappedLineParser::parseLoopBody(bool KeepBraces, bool WrapRightBrace) {
keepAncestorBraces();
- if (Keywords.isBlockBegin(*FormatTok, Style)) {
+ if (isBlockBegin(*FormatTok)) {
if (!KeepBraces)
FormatTok->setFinalizedType(TT_ControlStatementLBrace);
FormatToken *LeftBrace = FormatTok;
@@ -3102,26 +3294,6 @@ void UnwrappedLineParser::parseAccessSpecifier() {
}
}
-/// \brief Parses a concept definition.
-/// \pre The current token has to be the concept keyword.
-///
-/// Returns if either the concept has been completely parsed, or if it detects
-/// that the concept definition is incorrect.
-void UnwrappedLineParser::parseConcept() {
- assert(FormatTok->is(tok::kw_concept) && "'concept' expected");
- nextToken();
- if (!FormatTok->is(tok::identifier))
- return;
- nextToken();
- if (!FormatTok->is(tok::equal))
- return;
- nextToken();
- parseConstraintExpression();
- if (FormatTok->is(tok::semi))
- nextToken();
- addUnwrappedLine();
-}
-
/// \brief Parses a requires, decides if it is a clause or an expression.
/// \pre The current token has to be the requires keyword.
/// \returns true if it parsed a clause.
@@ -3204,37 +3376,41 @@ bool clang::format::UnwrappedLineParser::parseRequires() {
// So we want basically to check for TYPE NAME, but TYPE can contain all kinds
// of stuff: typename, const, *, &, &&, ::, identifiers.
- int NextTokenOffset = 1;
- auto NextToken = Tokens->peekNextToken(NextTokenOffset);
- auto PeekNext = [&NextTokenOffset, &NextToken, this] {
- ++NextTokenOffset;
- NextToken = Tokens->peekNextToken(NextTokenOffset);
+ unsigned StoredPosition = Tokens->getPosition();
+ FormatToken *NextToken = Tokens->getNextToken();
+ int Lookahead = 0;
+ auto PeekNext = [&Lookahead, &NextToken, this] {
+ ++Lookahead;
+ NextToken = Tokens->getNextToken();
};
bool FoundType = false;
bool LastWasColonColon = false;
int OpenAngles = 0;
- for (; NextTokenOffset < 50; PeekNext()) {
+ for (; Lookahead < 50; PeekNext()) {
switch (NextToken->Tok.getKind()) {
case tok::kw_volatile:
case tok::kw_const:
case tok::comma:
+ FormatTok = Tokens->setPosition(StoredPosition);
parseRequiresExpression(RequiresToken);
return false;
case tok::r_paren:
case tok::pipepipe:
+ FormatTok = Tokens->setPosition(StoredPosition);
parseRequiresClause(RequiresToken);
return true;
case tok::eof:
// Break out of the loop.
- NextTokenOffset = 50;
+ Lookahead = 50;
break;
case tok::coloncolon:
LastWasColonColon = true;
break;
case tok::identifier:
if (FoundType && !LastWasColonColon && OpenAngles == 0) {
+ FormatTok = Tokens->setPosition(StoredPosition);
parseRequiresExpression(RequiresToken);
return false;
}
@@ -3249,14 +3425,15 @@ bool clang::format::UnwrappedLineParser::parseRequires() {
break;
default:
if (NextToken->isSimpleTypeSpecifier()) {
+ FormatTok = Tokens->setPosition(StoredPosition);
parseRequiresExpression(RequiresToken);
return false;
}
break;
}
}
-
// This seems to be a complicated expression, just assume it's a clause.
+ FormatTok = Tokens->setPosition(StoredPosition);
parseRequiresClause(RequiresToken);
return true;
}
@@ -3283,6 +3460,8 @@ void UnwrappedLineParser::parseRequiresClause(FormatToken *RequiresToken) {
? TT_RequiresClauseInARequiresExpression
: TT_RequiresClause);
+ // NOTE: parseConstraintExpression is only ever called from this function.
+ // It could be inlined into here.
parseConstraintExpression();
if (!InRequiresExpression)
@@ -3316,9 +3495,8 @@ void UnwrappedLineParser::parseRequiresExpression(FormatToken *RequiresToken) {
/// \brief Parses a constraint expression.
///
-/// This is either the definition of a concept, or the body of a requires
-/// clause. It returns, when the parsing is complete, or the expression is
-/// incorrect.
+/// This is the body of a requires clause. It returns, when the parsing is
+/// complete, or the expression is incorrect.
void UnwrappedLineParser::parseConstraintExpression() {
// The special handling for lambdas is needed since tryToParseLambda() eats a
// token and if a requires expression is the last part of a requires clause
@@ -3385,7 +3563,6 @@ void UnwrappedLineParser::parseConstraintExpression() {
case tok::minus:
case tok::star:
case tok::slash:
- case tok::kw_decltype:
LambdaNextTimeAllowed = true;
// Just eat them.
nextToken();
@@ -3417,9 +3594,9 @@ void UnwrappedLineParser::parseConstraintExpression() {
// concept C = bool(...);
// and bool is the only type, all other types as cast must be inside a
// cast to bool an thus are handled by the other cases.
- nextToken();
- if (FormatTok->isNot(tok::l_paren))
+ if (Tokens->peekNextToken()->isNot(tok::l_paren))
return;
+ nextToken();
parseParens();
break;
@@ -3438,7 +3615,8 @@ void UnwrappedLineParser::parseConstraintExpression() {
switch (FormatTok->Previous->Tok.getKind()) {
case tok::coloncolon: // Nested identifier.
case tok::ampamp: // Start of a function or variable for the
- case tok::pipepipe: // constraint expression.
+ case tok::pipepipe: // constraint expression. (binary)
+ case tok::exclaim: // The same as above, but unary.
case tok::kw_requires: // Initial identifier of a requires clause.
case tok::equal: // Initial identifier of a concept declaration.
break;
@@ -3639,7 +3817,7 @@ void UnwrappedLineParser::parseJavaEnumBody() {
++Line->Level;
// Parse the enum constants.
- while (FormatTok->isNot(tok::eof)) {
+ while (!eof()) {
if (FormatTok->is(tok::l_brace)) {
// Parse the constant's class body.
parseBlock(/*MustBeDeclaration=*/true, /*AddLevels=*/1u,
@@ -3989,21 +4167,176 @@ void UnwrappedLineParser::parseStatementMacro() {
addUnwrappedLine();
}
-LLVM_ATTRIBUTE_UNUSED static void printDebugInfo(const UnwrappedLine &Line,
- StringRef Prefix = "") {
- llvm::dbgs() << Prefix << "Line(" << Line.Level
- << ", FSC=" << Line.FirstStartColumn << ")"
- << (Line.InPPDirective ? " MACRO" : "") << ": ";
- for (const auto &Node : Line.Tokens) {
- llvm::dbgs() << Node.Tok->Tok.getName() << "["
- << "T=" << static_cast<unsigned>(Node.Tok->getType())
- << ", OC=" << Node.Tok->OriginalColumn << "] ";
- }
- for (const auto &Node : Line.Tokens)
- for (const auto &ChildNode : Node.Children)
- printDebugInfo(ChildNode, "\nChild: ");
-
- llvm::dbgs() << "\n";
+void UnwrappedLineParser::parseVerilogHierarchyIdentifier() {
+ // consume things like a::`b.c[d:e] or a::*
+ while (true) {
+ if (FormatTok->isOneOf(tok::star, tok::period, tok::periodstar,
+ tok::coloncolon, tok::hash) ||
+ Keywords.isVerilogIdentifier(*FormatTok)) {
+ nextToken();
+ } else if (FormatTok->is(tok::l_square)) {
+ parseSquare();
+ } else {
+ break;
+ }
+ }
+}
+
+void UnwrappedLineParser::parseVerilogSensitivityList() {
+ if (!FormatTok->is(tok::at))
+ return;
+ nextToken();
+ // A block event expression has 2 at signs.
+ if (FormatTok->is(tok::at))
+ nextToken();
+ switch (FormatTok->Tok.getKind()) {
+ case tok::star:
+ nextToken();
+ break;
+ case tok::l_paren:
+ parseParens();
+ break;
+ default:
+ parseVerilogHierarchyIdentifier();
+ break;
+ }
+}
+
+unsigned UnwrappedLineParser::parseVerilogHierarchyHeader() {
+ unsigned AddLevels = 0;
+
+ if (FormatTok->is(Keywords.kw_clocking)) {
+ nextToken();
+ if (Keywords.isVerilogIdentifier(*FormatTok))
+ nextToken();
+ parseVerilogSensitivityList();
+ if (FormatTok->is(tok::semi))
+ nextToken();
+ } else if (FormatTok->isOneOf(tok::kw_case, Keywords.kw_casex,
+ Keywords.kw_casez, Keywords.kw_randcase,
+ Keywords.kw_randsequence)) {
+ if (Style.IndentCaseLabels)
+ AddLevels++;
+ nextToken();
+ if (FormatTok->is(tok::l_paren)) {
+ FormatTok->setFinalizedType(TT_ConditionLParen);
+ parseParens();
+ }
+ if (FormatTok->isOneOf(Keywords.kw_inside, Keywords.kw_matches))
+ nextToken();
+ // The case header has no semicolon.
+ } else {
+ // "module" etc.
+ nextToken();
+ // all the words like the name of the module and specifiers like
+ // "automatic" and the width of function return type
+ while (true) {
+ if (FormatTok->is(tok::l_square)) {
+ auto Prev = FormatTok->getPreviousNonComment();
+ if (Prev && Keywords.isVerilogIdentifier(*Prev))
+ Prev->setFinalizedType(TT_VerilogDimensionedTypeName);
+ parseSquare();
+ } else if (Keywords.isVerilogIdentifier(*FormatTok) ||
+ FormatTok->isOneOf(Keywords.kw_automatic, tok::kw_static)) {
+ nextToken();
+ } else {
+ break;
+ }
+ }
+
+ auto NewLine = [this]() {
+ addUnwrappedLine();
+ Line->IsContinuation = true;
+ };
+
+ // package imports
+ while (FormatTok->is(Keywords.kw_import)) {
+ NewLine();
+ nextToken();
+ parseVerilogHierarchyIdentifier();
+ if (FormatTok->is(tok::semi))
+ nextToken();
+ }
+
+ // parameters and ports
+ if (FormatTok->is(Keywords.kw_verilogHash)) {
+ NewLine();
+ nextToken();
+ if (FormatTok->is(tok::l_paren))
+ parseParens();
+ }
+ if (FormatTok->is(tok::l_paren)) {
+ NewLine();
+ parseParens();
+ }
+
+ // extends and implements
+ if (FormatTok->is(Keywords.kw_extends)) {
+ NewLine();
+ nextToken();
+ parseVerilogHierarchyIdentifier();
+ if (FormatTok->is(tok::l_paren))
+ parseParens();
+ }
+ if (FormatTok->is(Keywords.kw_implements)) {
+ NewLine();
+ do {
+ nextToken();
+ parseVerilogHierarchyIdentifier();
+ } while (FormatTok->is(tok::comma));
+ }
+
+ // Coverage event for cover groups.
+ if (FormatTok->is(tok::at)) {
+ NewLine();
+ parseVerilogSensitivityList();
+ }
+
+ if (FormatTok->is(tok::semi))
+ nextToken(/*LevelDifference=*/1);
+ addUnwrappedLine();
+ }
+
+ return AddLevels;
+}
+
+void UnwrappedLineParser::parseVerilogTable() {
+ assert(FormatTok->is(Keywords.kw_table));
+ nextToken(/*LevelDifference=*/1);
+ addUnwrappedLine();
+
+ auto InitialLevel = Line->Level++;
+ while (!eof() && !Keywords.isVerilogEnd(*FormatTok)) {
+ FormatToken *Tok = FormatTok;
+ nextToken();
+ if (Tok->is(tok::semi))
+ addUnwrappedLine();
+ else if (Tok->isOneOf(tok::star, tok::colon, tok::question, tok::minus))
+ Tok->setFinalizedType(TT_VerilogTableItem);
+ }
+ Line->Level = InitialLevel;
+ nextToken(/*LevelDifference=*/-1);
+ addUnwrappedLine();
+}
+
+void UnwrappedLineParser::parseVerilogCaseLabel() {
+ // The label will get unindented in AnnotatingParser. If there are no leading
+ // spaces, indent the rest here so that things inside the block will be
+ // indented relative to things outside. We don't use parseLabel because we
+ // don't know whether this colon is a label or a ternary expression at this
+ // point.
+ auto OrigLevel = Line->Level;
+ auto FirstLine = CurrentLines->size();
+ if (Line->Level == 0 || (Line->InPPDirective && Line->Level <= 1))
+ ++Line->Level;
+ else if (!Style.IndentCaseBlocks && Keywords.isVerilogBegin(*FormatTok))
+ --Line->Level;
+ parseStructuralElement();
+ // Restore the indentation in both the new line and the line that has the
+ // label.
+ if (CurrentLines->size() > FirstLine)
+ (*CurrentLines)[FirstLine].Level = OrigLevel;
+ Line->Level = OrigLevel;
}
void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) {
@@ -4026,6 +4359,7 @@ void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) {
Line->Tokens.clear();
Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex;
Line->FirstStartColumn = 0;
+ Line->IsContinuation = false;
if (ClosesWhitesmithsBlock && AdjustLevel == LineLevel::Remove)
--Line->Level;
diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h
index 3394bfab8b8e..f043e567eb73 100644
--- a/clang/lib/Format/UnwrappedLineParser.h
+++ b/clang/lib/Format/UnwrappedLineParser.h
@@ -44,11 +44,23 @@ struct UnwrappedLine {
/// The indent level of the \c UnwrappedLine.
unsigned Level;
+ /// The \c PPBranchLevel (adjusted for header guards) if this line is a
+ /// \c InMacroBody line, and 0 otherwise.
+ unsigned PPLevel;
+
/// Whether this \c UnwrappedLine is part of a preprocessor directive.
bool InPPDirective;
+ /// Whether this \c UnwrappedLine is part of a pramga directive.
+ bool InPragmaDirective;
+ /// Whether it is part of a macro body.
+ bool InMacroBody;
bool MustBeDeclaration;
+ /// \c True if this line should be indented by ContinuationIndent in
+ /// addition to the normal indention level.
+ bool IsContinuation = false;
+
/// If this \c UnwrappedLine closes a block in a sequence of lines,
/// \c MatchingOpeningBlockLineIndex stores the index of the corresponding
/// opening line. Otherwise, \c MatchingOpeningBlockLineIndex must be
@@ -111,9 +123,9 @@ private:
void parsePPDirective();
void parsePPDefine();
void parsePPIf(bool IfDef);
- void parsePPElIf();
void parsePPElse();
void parsePPEndIf();
+ void parsePPPragma();
void parsePPUnknown();
void readTokenWithJavaScriptASI();
void parseStructuralElement(bool IsTopLevel = false,
@@ -131,6 +143,7 @@ private:
void parseUnbracedBody(bool CheckEOF = false);
void handleAttributes();
bool handleCppAttributes();
+ bool isBlockBegin(const FormatToken &Tok) const;
FormatToken *parseIfThenElse(IfStmtKind *IfKind, bool KeepBraces = false);
void parseTryCatch();
void parseLoopBody(bool KeepBraces, bool WrapRightBrace);
@@ -140,12 +153,11 @@ private:
void parseCaseLabel();
void parseSwitch();
void parseNamespace();
- void parseModuleImport();
+ bool parseModuleImport();
void parseNew();
void parseAccessSpecifier();
bool parseEnum();
bool parseStructLike();
- void parseConcept();
bool parseRequires();
void parseRequiresClause(FormatToken *RequiresToken);
void parseRequiresExpression(FormatToken *RequiresToken);
@@ -174,6 +186,13 @@ private:
bool tryToParsePropertyAccessor();
void tryToParseJSFunction();
bool tryToParseSimpleAttribute();
+ void parseVerilogHierarchyIdentifier();
+ void parseVerilogSensitivityList();
+ // Returns the number of levels of indentation in addition to the normal 1
+ // level for a block, used for indenting case labels.
+ unsigned parseVerilogHierarchyHeader();
+ void parseVerilogTable();
+ void parseVerilogCaseLabel();
// Used by addUnwrappedLine to denote whether to keep or remove a level
// when resetting the line state.
@@ -197,7 +216,7 @@ private:
//
// NextTok specifies the next token. A null pointer NextTok is supported, and
// signifies either the absence of a next token, or that the next token
- // shouldn't be taken into accunt for the analysis.
+ // shouldn't be taken into account for the analysis.
void distributeComments(const SmallVectorImpl<FormatToken *> &Comments,
const FormatToken *NextTok);
@@ -342,7 +361,8 @@ struct UnwrappedLineNode {
};
inline UnwrappedLine::UnwrappedLine()
- : Level(0), InPPDirective(false), MustBeDeclaration(false),
+ : Level(0), PPLevel(0), InPPDirective(false), InPragmaDirective(false),
+ InMacroBody(false), MustBeDeclaration(false),
MatchingOpeningBlockLineIndex(kInvalidIndex) {}
} // end namespace format
diff --git a/clang/lib/Format/UsingDeclarationsSorter.cpp b/clang/lib/Format/UsingDeclarationsSorter.cpp
index bf5307260c0b..2f4b1e0e4627 100644
--- a/clang/lib/Format/UsingDeclarationsSorter.cpp
+++ b/clang/lib/Format/UsingDeclarationsSorter.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "UsingDeclarationsSorter.h"
+#include "clang/Format/Format.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Regex.h"
@@ -32,7 +33,7 @@ namespace {
// individual names is that all non-namespace names come before all namespace
// names, and within those groups, names are in case-insensitive lexicographic
// order.
-int compareLabels(StringRef A, StringRef B) {
+int compareLabelsLexicographicNumeric(StringRef A, StringRef B) {
SmallVector<StringRef, 2> NamesA;
A.split(NamesA, "::", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
SmallVector<StringRef, 2> NamesB;
@@ -64,16 +65,38 @@ int compareLabels(StringRef A, StringRef B) {
return 0;
}
+int compareLabelsLexicographic(StringRef A, StringRef B) {
+ SmallVector<StringRef, 2> NamesA;
+ A.split(NamesA, "::", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+ SmallVector<StringRef, 2> NamesB;
+ B.split(NamesB, "::", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+ size_t SizeA = NamesA.size();
+ size_t SizeB = NamesB.size();
+ for (size_t I = 0, E = std::min(SizeA, SizeB); I < E; ++I) {
+ // Two namespaces names within a group compare case-insensitively.
+ int C = NamesA[I].compare_insensitive(NamesB[I]);
+ if (C != 0)
+ return C;
+ }
+ if (SizeA < SizeB)
+ return -1;
+ return SizeA == SizeB ? 0 : 1;
+}
+
+int compareLabels(
+ StringRef A, StringRef B,
+ FormatStyle::SortUsingDeclarationsOptions SortUsingDeclarations) {
+ if (SortUsingDeclarations == FormatStyle::SUD_LexicographicNumeric)
+ return compareLabelsLexicographicNumeric(A, B);
+ return compareLabelsLexicographic(A, B);
+}
+
struct UsingDeclaration {
const AnnotatedLine *Line;
std::string Label;
UsingDeclaration(const AnnotatedLine *Line, const std::string &Label)
: Line(Line), Label(Label) {}
-
- bool operator<(const UsingDeclaration &Other) const {
- return compareLabels(Label, Other.Label) < 0;
- }
};
/// Computes the label of a using declaration starting at tthe using token
@@ -113,7 +136,8 @@ std::string computeUsingDeclarationLabel(const FormatToken *UsingTok) {
void endUsingDeclarationBlock(
SmallVectorImpl<UsingDeclaration> *UsingDeclarations,
- const SourceManager &SourceMgr, tooling::Replacements *Fixes) {
+ const SourceManager &SourceMgr, tooling::Replacements *Fixes,
+ FormatStyle::SortUsingDeclarationsOptions SortUsingDeclarations) {
bool BlockAffected = false;
for (const UsingDeclaration &Declaration : *UsingDeclarations) {
if (Declaration.Line->Affected) {
@@ -127,7 +151,11 @@ void endUsingDeclarationBlock(
}
SmallVector<UsingDeclaration, 4> SortedUsingDeclarations(
UsingDeclarations->begin(), UsingDeclarations->end());
- llvm::stable_sort(SortedUsingDeclarations);
+ auto Comp = [SortUsingDeclarations](const UsingDeclaration &Lhs,
+ const UsingDeclaration &Rhs) -> bool {
+ return compareLabels(Lhs.Label, Rhs.Label, SortUsingDeclarations) < 0;
+ };
+ llvm::stable_sort(SortedUsingDeclarations, Comp);
SortedUsingDeclarations.erase(
std::unique(SortedUsingDeclarations.begin(),
SortedUsingDeclarations.end(),
@@ -192,21 +220,26 @@ std::pair<tooling::Replacements, unsigned> UsingDeclarationsSorter::analyze(
const auto *FirstTok = Line->First;
if (Line->InPPDirective || !Line->startsWith(tok::kw_using) ||
FirstTok->Finalized) {
- endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes);
+ endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes,
+ Style.SortUsingDeclarations);
continue;
}
- if (FirstTok->NewlinesBefore > 1)
- endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes);
+ if (FirstTok->NewlinesBefore > 1) {
+ endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes,
+ Style.SortUsingDeclarations);
+ }
const auto *UsingTok =
FirstTok->is(tok::comment) ? FirstTok->getNextNonComment() : FirstTok;
std::string Label = computeUsingDeclarationLabel(UsingTok);
if (Label.empty()) {
- endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes);
+ endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes,
+ Style.SortUsingDeclarations);
continue;
}
UsingDeclarations.push_back(UsingDeclaration(Line, Label));
}
- endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes);
+ endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes,
+ Style.SortUsingDeclarations);
return {Fixes, 0};
}
diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp
index 6ec788ad23c6..9951906b6af0 100644
--- a/clang/lib/Format/WhitespaceManager.cpp
+++ b/clang/lib/Format/WhitespaceManager.cpp
@@ -522,6 +522,13 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches,
? Changes[StartAt].indentAndNestingLevel()
: std::tuple<unsigned, unsigned, unsigned>();
+ // Keep track if the first token has a non-zero indent and nesting level.
+ // This can happen when aligning the contents of "#else" preprocessor blocks,
+ // which is done separately.
+ bool HasInitialIndentAndNesting =
+ StartAt == 0 &&
+ IndentAndNestingLevel > std::tuple<unsigned, unsigned, unsigned>();
+
// Keep track of the number of commas before the matching tokens, we will only
// align a sequence of matching tokens if they are preceded by the same number
// of commas.
@@ -556,8 +563,19 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches,
unsigned i = StartAt;
for (unsigned e = Changes.size(); i != e; ++i) {
- if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
- break;
+ if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel) {
+ if (!HasInitialIndentAndNesting)
+ break;
+ // The contents of preprocessor blocks are aligned separately.
+ // If the initial preprocessor block is indented or nested (e.g. it's in
+ // a function), do not align and exit after finishing this scope block.
+ // Instead, align, and then lower the baseline indent and nesting level
+ // in order to continue aligning subsequent blocks.
+ EndOfSequence = i;
+ AlignCurrentSequence();
+ IndentAndNestingLevel =
+ Changes[i].indentAndNestingLevel(); // new baseline
+ }
if (Changes[i].NewlinesBefore != 0) {
CommasBeforeMatch = 0;
@@ -591,7 +609,8 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches,
++CommasBeforeMatch;
} else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
// Call AlignTokens recursively, skipping over this scope block.
- unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
+ unsigned StoppedAt =
+ AlignTokens(Style, Matches, Changes, i, ACS, RightJustify);
i = StoppedAt - 1;
continue;
}
@@ -852,9 +871,7 @@ void WhitespaceManager::alignConsecutiveDeclarations() {
AlignTokens(
Style,
[](Change const &C) {
- // tok::kw_operator is necessary for aligning operator overload
- // definitions.
- if (C.Tok->isOneOf(TT_FunctionDeclarationName, tok::kw_operator))
+ if (C.Tok->is(TT_FunctionDeclarationName))
return true;
if (C.Tok->isNot(TT_StartOfName))
return false;
@@ -927,6 +944,10 @@ void WhitespaceManager::alignTrailingComments() {
unsigned StartOfSequence = 0;
bool BreakBeforeNext = false;
unsigned Newlines = 0;
+ unsigned int NewLineThreshold = 1;
+ if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Always)
+ NewLineThreshold = Style.AlignTrailingComments.OverEmptyLines + 1;
+
for (unsigned i = 0, e = Changes.size(); i != e; ++i) {
if (Changes[i].StartOfBlockComment)
continue;
@@ -934,6 +955,21 @@ void WhitespaceManager::alignTrailingComments() {
if (!Changes[i].IsTrailingComment)
continue;
+ if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Leave) {
+ auto OriginalSpaces =
+ Changes[i].OriginalWhitespaceRange.getEnd().getRawEncoding() -
+ Changes[i].OriginalWhitespaceRange.getBegin().getRawEncoding() -
+ Changes[i].Tok->NewlinesBefore;
+ unsigned RestoredLineLength = Changes[i].StartOfTokenColumn +
+ Changes[i].TokenLength + OriginalSpaces;
+ // If leaving comments makes the line exceed the column limit, give up to
+ // leave the comments.
+ if (RestoredLineLength >= Style.ColumnLimit && Style.ColumnLimit != 0)
+ break;
+ Changes[i].Spaces = OriginalSpaces;
+ continue;
+ }
+
unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
unsigned ChangeMaxColumn;
@@ -957,7 +993,7 @@ void WhitespaceManager::alignTrailingComments() {
Changes[i - 1].Tok->is(tok::r_brace) &&
Changes[i - 1].StartOfTokenColumn == 0;
bool WasAlignedWithStartOfNextLine = false;
- if (Changes[i].NewlinesBefore == 1) { // A comment on its own line.
+ if (Changes[i].NewlinesBefore >= 1) { // A comment on its own line.
unsigned CommentColumn = SourceMgr.getSpellingColumnNumber(
Changes[i].OriginalWhitespaceRange.getEnd());
for (unsigned j = i + 1; j != e; ++j) {
@@ -974,12 +1010,13 @@ void WhitespaceManager::alignTrailingComments() {
break;
}
}
- if (!Style.AlignTrailingComments || FollowsRBraceInColumn0) {
+ if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Never ||
+ FollowsRBraceInColumn0) {
alignTrailingComments(StartOfSequence, i, MinColumn);
MinColumn = ChangeMinColumn;
MaxColumn = ChangeMinColumn;
StartOfSequence = i;
- } else if (BreakBeforeNext || Newlines > 1 ||
+ } else if (BreakBeforeNext || Newlines > NewLineThreshold ||
(ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn) ||
// Break the comment sequence if the previous line did not end
// in a trailing comment.
@@ -1014,7 +1051,7 @@ void WhitespaceManager::alignTrailingComments(unsigned Start, unsigned End,
Changes[i].StartOfBlockComment->StartOfTokenColumn -
Changes[i].StartOfTokenColumn;
}
- if (Shift < 0)
+ if (Shift <= 0)
continue;
Changes[i].Spaces += Shift;
if (i + 1 != Changes.size())
diff --git a/clang/lib/Format/WhitespaceManager.h b/clang/lib/Format/WhitespaceManager.h
index 2be62338bc9a..2ccf8c08302a 100644
--- a/clang/lib/Format/WhitespaceManager.h
+++ b/clang/lib/Format/WhitespaceManager.h
@@ -199,7 +199,7 @@ private:
SmallVector<unsigned> CellCounts;
unsigned InitialSpaces = 0;
- // Determine if every row in the the array
+ // Determine if every row in the array
// has the same number of columns.
bool isRectangular() const {
if (CellCounts.empty())