aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Format
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2024-07-27 23:34:35 +0000
committerDimitry Andric <dim@FreeBSD.org>2024-10-23 18:26:01 +0000
commit0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583 (patch)
tree6cf5ab1f05330c6773b1f3f64799d56a9c7a1faa /contrib/llvm-project/clang/lib/Format
parent6b9f7133aba44189d9625c352bc2c2a59baf18ef (diff)
parentac9a064cb179f3425b310fa2847f8764ac970a4d (diff)
Diffstat (limited to 'contrib/llvm-project/clang/lib/Format')
-rw-r--r--contrib/llvm-project/clang/lib/Format/BreakableToken.cpp4
-rw-r--r--contrib/llvm-project/clang/lib/Format/BreakableToken.h3
-rw-r--r--contrib/llvm-project/clang/lib/Format/ContinuationIndenter.cpp79
-rw-r--r--contrib/llvm-project/clang/lib/Format/ContinuationIndenter.h7
-rw-r--r--contrib/llvm-project/clang/lib/Format/Encoding.h1
-rw-r--r--contrib/llvm-project/clang/lib/Format/Format.cpp317
-rw-r--r--contrib/llvm-project/clang/lib/Format/FormatInternal.h4
-rw-r--r--contrib/llvm-project/clang/lib/Format/FormatToken.cpp54
-rw-r--r--contrib/llvm-project/clang/lib/Format/FormatToken.h89
-rw-r--r--contrib/llvm-project/clang/lib/Format/FormatTokenLexer.cpp52
-rw-r--r--contrib/llvm-project/clang/lib/Format/FormatTokenLexer.h5
-rw-r--r--contrib/llvm-project/clang/lib/Format/FormatTokenSource.h14
-rw-r--r--contrib/llvm-project/clang/lib/Format/MacroCallReconstructor.cpp68
-rw-r--r--contrib/llvm-project/clang/lib/Format/MacroExpander.cpp12
-rw-r--r--contrib/llvm-project/clang/lib/Format/Macros.h40
-rw-r--r--contrib/llvm-project/clang/lib/Format/QualifierAlignmentFixer.cpp29
-rw-r--r--contrib/llvm-project/clang/lib/Format/QualifierAlignmentFixer.h18
-rw-r--r--contrib/llvm-project/clang/lib/Format/SortJavaScriptImports.cpp18
-rw-r--r--contrib/llvm-project/clang/lib/Format/SortJavaScriptImports.h3
-rw-r--r--contrib/llvm-project/clang/lib/Format/TokenAnalyzer.cpp4
-rw-r--r--contrib/llvm-project/clang/lib/Format/TokenAnalyzer.h12
-rw-r--r--contrib/llvm-project/clang/lib/Format/TokenAnnotator.cpp934
-rw-r--r--contrib/llvm-project/clang/lib/Format/TokenAnnotator.h13
-rw-r--r--contrib/llvm-project/clang/lib/Format/UnwrappedLineFormatter.cpp65
-rw-r--r--contrib/llvm-project/clang/lib/Format/UnwrappedLineFormatter.h2
-rw-r--r--contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp365
-rw-r--r--contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.h18
-rw-r--r--contrib/llvm-project/clang/lib/Format/WhitespaceManager.cpp136
-rw-r--r--contrib/llvm-project/clang/lib/Format/WhitespaceManager.h21
29 files changed, 1606 insertions, 781 deletions
diff --git a/contrib/llvm-project/clang/lib/Format/BreakableToken.cpp b/contrib/llvm-project/clang/lib/Format/BreakableToken.cpp
index 473908e8fee3..75304908dc65 100644
--- a/contrib/llvm-project/clang/lib/Format/BreakableToken.cpp
+++ b/contrib/llvm-project/clang/lib/Format/BreakableToken.cpp
@@ -449,11 +449,11 @@ const FormatToken &BreakableComment::tokenAt(unsigned LineIndex) const {
static bool mayReflowContent(StringRef Content) {
Content = Content.trim(Blanks);
- // Lines starting with '@' commonly have special meaning.
+ // Lines starting with '@' or '\' commonly have special meaning.
// Lines starting with '-', '-#', '+' or '*' are bulleted/numbered lists.
bool hasSpecialMeaningPrefix = false;
for (StringRef Prefix :
- {"@", "TODO", "FIXME", "XXX", "-# ", "- ", "+ ", "* "}) {
+ {"@", "\\", "TODO", "FIXME", "XXX", "-# ", "- ", "+ ", "* "}) {
if (Content.starts_with(Prefix)) {
hasSpecialMeaningPrefix = true;
break;
diff --git a/contrib/llvm-project/clang/lib/Format/BreakableToken.h b/contrib/llvm-project/clang/lib/Format/BreakableToken.h
index e7c0680641e2..8b9360a3335e 100644
--- a/contrib/llvm-project/clang/lib/Format/BreakableToken.h
+++ b/contrib/llvm-project/clang/lib/Format/BreakableToken.h
@@ -18,11 +18,8 @@
#define LLVM_CLANG_LIB_FORMAT_BREAKABLETOKEN_H
#include "Encoding.h"
-#include "TokenAnnotator.h"
#include "WhitespaceManager.h"
#include "llvm/ADT/StringSet.h"
-#include "llvm/Support/Regex.h"
-#include <utility>
namespace clang {
namespace format {
diff --git a/contrib/llvm-project/clang/lib/Format/ContinuationIndenter.cpp b/contrib/llvm-project/clang/lib/Format/ContinuationIndenter.cpp
index 53cd169b0590..b07360425ca6 100644
--- a/contrib/llvm-project/clang/lib/Format/ContinuationIndenter.cpp
+++ b/contrib/llvm-project/clang/lib/Format/ContinuationIndenter.cpp
@@ -328,9 +328,17 @@ bool ContinuationIndenter::canBreak(const LineState &State) {
// Don't break after very short return types (e.g. "void") as that is often
// unexpected.
- if (Current.is(TT_FunctionDeclarationName) && State.Column < 6) {
- if (Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None)
+ if (Current.is(TT_FunctionDeclarationName)) {
+ if (Style.BreakAfterReturnType == FormatStyle::RTBS_None &&
+ State.Column < 6) {
return false;
+ }
+
+ if (Style.BreakAfterReturnType == FormatStyle::RTBS_ExceptShortType) {
+ assert(State.Column >= State.FirstIndent);
+ if (State.Column - State.FirstIndent < 6)
+ return false;
+ }
}
// If binary operators are moved to the next line (including commas for some
@@ -561,7 +569,9 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
return true;
}
}
- return Style.AlwaysBreakTemplateDeclarations != FormatStyle::BTDS_No;
+ return Style.BreakTemplateDeclarations != FormatStyle::BTDS_No &&
+ (Style.BreakTemplateDeclarations != FormatStyle::BTDS_Leave ||
+ Current.NewlinesBefore > 0);
}
if (Previous.is(TT_FunctionAnnotationRParen) &&
State.Line->Type != LT_PreprocessorDirective) {
@@ -587,7 +597,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
!State.Line->ReturnTypeWrapped &&
// Don't break before a C# function when no break after return type.
(!Style.isCSharp() ||
- Style.AlwaysBreakAfterReturnType != FormatStyle::RTBS_None) &&
+ Style.BreakAfterReturnType > FormatStyle::RTBS_ExceptShortType) &&
// Don't always break between a JavaScript `function` and the function
// name.
!Style.isJavaScript() && Previous.isNot(tok::kw_template) &&
@@ -817,6 +827,8 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
if (Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign &&
!CurrentState.IsCSharpGenericTypeConstraint && Previous.opensScope() &&
Previous.isNot(TT_ObjCMethodExpr) && Previous.isNot(TT_RequiresClause) &&
+ Previous.isNot(TT_TableGenDAGArgOpener) &&
+ Previous.isNot(TT_TableGenDAGArgOpenerToBreak) &&
!(Current.MacroParent && Previous.MacroParent) &&
(Current.isNot(TT_LineComment) ||
Previous.isOneOf(BK_BracedInit, TT_VerilogMultiLineListLParen))) {
@@ -1245,8 +1257,13 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
}
return CurrentState.Indent;
}
+ if (Current.is(TT_TrailingReturnArrow) &&
+ Previous.isOneOf(tok::kw_noexcept, tok::kw_mutable, tok::kw_constexpr,
+ tok::kw_consteval, tok::kw_static, TT_AttributeSquare)) {
+ return ContinuationIndent;
+ }
if ((Current.isOneOf(tok::r_brace, tok::r_square) ||
- (Current.is(tok::greater) && Style.isProto())) &&
+ (Current.is(tok::greater) && (Style.isProto() || Style.isTableGen()))) &&
State.Stack.size() > 1) {
if (Current.closesBlockOrBlockTypeList(Style))
return State.Stack[State.Stack.size() - 2].NestedBlockIndent;
@@ -1274,6 +1291,12 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
Current.Next->isOneOf(tok::semi, tok::kw_const, tok::l_brace))) {
return State.Stack[State.Stack.size() - 2].LastSpace;
}
+ // When DAGArg closer exists top of line, it should be aligned in the similar
+ // way as function call above.
+ if (Style.isTableGen() && Current.is(TT_TableGenDAGArgCloser) &&
+ State.Stack.size() > 1) {
+ return State.Stack[State.Stack.size() - 2].LastSpace;
+ }
if (Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent &&
(Current.is(tok::r_paren) ||
(Current.is(tok::r_brace) && Current.MatchingParen &&
@@ -1404,7 +1427,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
// the next line.
if (State.Line->InPragmaDirective) {
FormatToken *PragmaType = State.Line->First->Next->Next;
- if (PragmaType && PragmaType->TokenText.equals("omp"))
+ if (PragmaType && PragmaType->TokenText == "omp")
return CurrentState.Indent + Style.ContinuationIndentWidth;
}
@@ -1433,7 +1456,9 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
Style.BreakInheritanceList == FormatStyle::BILS_AfterColon) {
return CurrentState.Indent;
}
- if (Previous.is(tok::r_paren) && !Current.isBinaryOperator() &&
+ if (Previous.is(tok::r_paren) &&
+ Previous.isNot(TT_TableGenDAGArgOperatorToBreak) &&
+ !Current.isBinaryOperator() &&
!Current.isOneOf(tok::colon, tok::comment)) {
return ContinuationIndent;
}
@@ -1692,7 +1717,10 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
(!Previous || Previous->isNot(tok::kw_return) ||
(Style.Language != FormatStyle::LK_Java && PrecedenceLevel > 0)) &&
(Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign ||
- PrecedenceLevel != prec::Comma || Current.NestingLevel == 0)) {
+ PrecedenceLevel > prec::Comma || Current.NestingLevel == 0) &&
+ (!Style.isTableGen() ||
+ (Previous && Previous->isOneOf(TT_TableGenDAGArgListComma,
+ TT_TableGenDAGArgListCommaToBreak)))) {
NewParenState.Indent = std::max(
std::max(State.Column, NewParenState.Indent), CurrentState.LastSpace);
}
@@ -1700,8 +1728,11 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
// 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->endsSequence(tok::l_paren, tok::kw__Generic) &&
+ State.Stack.size() > 1) {
+ NewParenState.Indent = State.Stack[State.Stack.size() - 2].Indent +
+ Style.ContinuationIndentWidth;
+ }
if ((shouldUnindentNextOperator(Current) ||
(Previous &&
@@ -1787,7 +1818,7 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
}
if (Current.MatchingParen && Current.is(BK_Block)) {
- moveStateToNewBlock(State);
+ moveStateToNewBlock(State, Newline);
return;
}
@@ -1826,6 +1857,17 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
Style.ContinuationIndentWidth +
std::max(CurrentState.LastSpace, CurrentState.StartOfFunctionCall);
+ if (Style.isTableGen() && Current.is(TT_TableGenDAGArgOpenerToBreak) &&
+ Style.TableGenBreakInsideDAGArg == FormatStyle::DAS_BreakElements) {
+ // For the case the next token is a TableGen DAGArg operator identifier
+ // that is not marked to have a line break after it.
+ // In this case the option DAS_BreakElements requires to align the
+ // DAGArg elements to the operator.
+ const FormatToken *Next = Current.Next;
+ if (Next && Next->is(TT_TableGenDAGArgOperatorID))
+ NewIndent = State.Column + Next->TokenText.size() + 2;
+ }
+
// Ensure that different different brackets force relative alignment, e.g.:
// void SomeFunction(vector< // break
// int> v);
@@ -1935,6 +1977,7 @@ void ContinuationIndenter::moveStatePastScopeCloser(LineState &State) {
(Current.isOneOf(tok::r_paren, tok::r_square, TT_TemplateString) ||
(Current.is(tok::r_brace) && State.NextToken != State.Line->First) ||
State.NextToken->is(TT_TemplateCloser) ||
+ State.NextToken->is(TT_TableGenListCloser) ||
(Current.is(tok::greater) && Current.is(TT_DictLiteral)))) {
State.Stack.pop_back();
}
@@ -1974,7 +2017,7 @@ void ContinuationIndenter::moveStatePastScopeCloser(LineState &State) {
}
}
-void ContinuationIndenter::moveStateToNewBlock(LineState &State) {
+void ContinuationIndenter::moveStateToNewBlock(LineState &State, bool NewLine) {
if (Style.LambdaBodyIndentation == FormatStyle::LBI_OuterScope &&
State.NextToken->is(TT_LambdaLBrace) &&
!State.Line->MightBeFunctionDecl) {
@@ -1986,10 +2029,18 @@ void ContinuationIndenter::moveStateToNewBlock(LineState &State) {
NestedBlockIndent + (State.NextToken->is(TT_ObjCBlockLBrace)
? Style.ObjCBlockIndentWidth
: Style.IndentWidth);
+
+ // Even when wrapping before lambda body, the left brace can still be added to
+ // the same line. This occurs when checking whether the whole lambda body can
+ // go on a single line. In this case we have to make sure there are no line
+ // breaks in the body, otherwise we could just end up with a regular lambda
+ // body without the brace wrapped.
+ bool NoLineBreak = Style.BraceWrapping.BeforeLambdaBody && !NewLine &&
+ State.NextToken->is(TT_LambdaLBrace);
+
State.Stack.push_back(ParenState(State.NextToken, NewIndent,
State.Stack.back().LastSpace,
- /*AvoidBinPacking=*/true,
- /*NoLineBreak=*/false));
+ /*AvoidBinPacking=*/true, NoLineBreak));
State.Stack.back().NestedBlockIndent = NestedBlockIndent;
State.Stack.back().BreakBeforeParameter = true;
}
diff --git a/contrib/llvm-project/clang/lib/Format/ContinuationIndenter.h b/contrib/llvm-project/clang/lib/Format/ContinuationIndenter.h
index 057b85bd32d5..18441e10a124 100644
--- a/contrib/llvm-project/clang/lib/Format/ContinuationIndenter.h
+++ b/contrib/llvm-project/clang/lib/Format/ContinuationIndenter.h
@@ -17,11 +17,6 @@
#include "Encoding.h"
#include "FormatToken.h"
-#include "clang/Format/Format.h"
-#include "llvm/Support/Regex.h"
-#include <map>
-#include <optional>
-#include <tuple>
namespace clang {
class SourceManager;
@@ -104,7 +99,7 @@ private:
/// Update 'State' according to the next token being one of ")>}]".
void moveStatePastScopeCloser(LineState &State);
/// Update 'State' with the next token opening a nested block.
- void moveStateToNewBlock(LineState &State);
+ void moveStateToNewBlock(LineState &State, bool NewLine);
/// Reformats a raw string literal.
///
diff --git a/contrib/llvm-project/clang/lib/Format/Encoding.h b/contrib/llvm-project/clang/lib/Format/Encoding.h
index a0d664121b2b..12f9043bb95a 100644
--- a/contrib/llvm-project/clang/lib/Format/Encoding.h
+++ b/contrib/llvm-project/clang/lib/Format/Encoding.h
@@ -16,7 +16,6 @@
#define LLVM_CLANG_LIB_FORMAT_ENCODING_H
#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Unicode.h"
diff --git a/contrib/llvm-project/clang/lib/Format/Format.cpp b/contrib/llvm-project/clang/lib/Format/Format.cpp
index 10fe35c79a4f..7fd42e46e0cc 100644
--- a/contrib/llvm-project/clang/lib/Format/Format.cpp
+++ b/contrib/llvm-project/clang/lib/Format/Format.cpp
@@ -13,50 +13,22 @@
//===----------------------------------------------------------------------===//
#include "clang/Format/Format.h"
-#include "AffectedRangeManager.h"
-#include "BreakableToken.h"
-#include "ContinuationIndenter.h"
#include "DefinitionBlockSeparator.h"
-#include "FormatInternal.h"
-#include "FormatToken.h"
-#include "FormatTokenLexer.h"
#include "IntegerLiteralSeparatorFixer.h"
#include "NamespaceEndCommentsFixer.h"
#include "ObjCPropertyAttributeOrderFixer.h"
#include "QualifierAlignmentFixer.h"
#include "SortJavaScriptImports.h"
-#include "TokenAnalyzer.h"
-#include "TokenAnnotator.h"
#include "UnwrappedLineFormatter.h"
-#include "UnwrappedLineParser.h"
#include "UsingDeclarationsSorter.h"
-#include "WhitespaceManager.h"
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/DiagnosticOptions.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Lex/Lexer.h"
#include "clang/Tooling/Inclusions/HeaderIncludes.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Sequence.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/Regex.h"
-#include "llvm/Support/VirtualFileSystem.h"
-#include "llvm/Support/YAMLTraits.h"
-#include <algorithm>
-#include <memory>
-#include <mutex>
-#include <optional>
-#include <string>
-#include <unordered_map>
#define DEBUG_TYPE "format-formatter"
using clang::format::FormatStyle;
-LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::RawStringFormat)
+LLVM_YAML_IS_SEQUENCE_VECTOR(FormatStyle::RawStringFormat)
namespace llvm {
namespace yaml {
@@ -128,6 +100,7 @@ struct MappingTraits<FormatStyle::ShortCaseStatementsAlignmentStyle> {
IO.mapOptional("Enabled", Value.Enabled);
IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines);
IO.mapOptional("AcrossComments", Value.AcrossComments);
+ IO.mapOptional("AlignCaseArrows", Value.AlignCaseArrows);
IO.mapOptional("AlignCaseColons", Value.AlignCaseColons);
}
};
@@ -296,6 +269,7 @@ template <>
struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> {
static void enumeration(IO &IO,
FormatStyle::BreakTemplateDeclarationsStyle &Value) {
+ IO.enumCase(Value, "Leave", FormatStyle::BTDS_Leave);
IO.enumCase(Value, "No", FormatStyle::BTDS_No);
IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine);
IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes);
@@ -306,6 +280,14 @@ struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> {
}
};
+template <> struct ScalarEnumerationTraits<FormatStyle::DAGArgStyle> {
+ static void enumeration(IO &IO, FormatStyle::DAGArgStyle &Value) {
+ IO.enumCase(Value, "DontBreak", FormatStyle::DAS_DontBreak);
+ IO.enumCase(Value, "BreakElements", FormatStyle::DAS_BreakElements);
+ IO.enumCase(Value, "BreakAll", FormatStyle::DAS_BreakAll);
+ }
+};
+
template <>
struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {
static void
@@ -326,6 +308,7 @@ struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> {
FormatStyle::EscapedNewlineAlignmentStyle &Value) {
IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign);
IO.enumCase(Value, "Left", FormatStyle::ENAS_Left);
+ IO.enumCase(Value, "LeftWithLastLine", FormatStyle::ENAS_LeftWithLastLine);
IO.enumCase(Value, "Right", FormatStyle::ENAS_Right);
// For backward compatibility.
@@ -386,6 +369,14 @@ template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> {
}
};
+template <> struct MappingTraits<FormatStyle::KeepEmptyLinesStyle> {
+ static void mapping(IO &IO, FormatStyle::KeepEmptyLinesStyle &Value) {
+ IO.mapOptional("AtEndOfFile", Value.AtEndOfFile);
+ IO.mapOptional("AtStartOfBlock", Value.AtStartOfBlock);
+ IO.mapOptional("AtStartOfFile", Value.AtStartOfFile);
+ }
+};
+
template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) {
IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp);
@@ -558,6 +549,8 @@ template <>
struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {
static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) {
IO.enumCase(Value, "None", FormatStyle::RTBS_None);
+ IO.enumCase(Value, "Automatic", FormatStyle::RTBS_Automatic);
+ IO.enumCase(Value, "ExceptShortType", FormatStyle::RTBS_ExceptShortType);
IO.enumCase(Value, "All", FormatStyle::RTBS_All);
IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel);
IO.enumCase(Value, "TopLevelDefinitions",
@@ -736,6 +729,7 @@ template <> struct MappingTraits<FormatStyle::SpacesInLineComment> {
template <> struct MappingTraits<FormatStyle::SpacesInParensCustom> {
static void mapping(IO &IO, FormatStyle::SpacesInParensCustom &Spaces) {
+ IO.mapOptional("ExceptDoubleParentheses", Spaces.ExceptDoubleParentheses);
IO.mapOptional("InCStyleCasts", Spaces.InCStyleCasts);
IO.mapOptional("InConditionalStatements", Spaces.InConditionalStatements);
IO.mapOptional("InEmptyParentheses", Spaces.InEmptyParentheses);
@@ -824,7 +818,6 @@ template <> struct MappingTraits<FormatStyle> {
FormatStyle PredefinedStyle;
if (getPredefinedStyle(StyleName, Style.Language, &PredefinedStyle) &&
Style == PredefinedStyle) {
- IO.mapOptional("# BasedOnStyle", StyleName);
BasedOnStyle = StyleName;
break;
}
@@ -874,6 +867,9 @@ template <> struct MappingTraits<FormatStyle> {
if (!IO.outputting()) {
IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlines);
IO.mapOptional("AllowAllConstructorInitializersOnNextLine", OnNextLine);
+ IO.mapOptional("AlwaysBreakAfterReturnType", Style.BreakAfterReturnType);
+ IO.mapOptional("AlwaysBreakTemplateDeclarations",
+ Style.BreakTemplateDeclarations);
IO.mapOptional("BreakBeforeInheritanceComma",
BreakBeforeInheritanceComma);
IO.mapOptional("BreakConstructorInitializersBeforeComma",
@@ -882,6 +878,9 @@ template <> struct MappingTraits<FormatStyle> {
OnCurrentLine);
IO.mapOptional("DeriveLineEnding", DeriveLineEnding);
IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment);
+ IO.mapOptional("KeepEmptyLinesAtEOF", Style.KeepEmptyLines.AtEndOfFile);
+ IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
+ Style.KeepEmptyLines.AtStartOfBlock);
IO.mapOptional("IndentFunctionDeclarationAfterType",
Style.IndentWrappedFunctionNames);
IO.mapOptional("IndentRequires", Style.IndentRequiresClause);
@@ -909,6 +908,12 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros);
IO.mapOptional("AlignConsecutiveShortCaseStatements",
Style.AlignConsecutiveShortCaseStatements);
+ IO.mapOptional("AlignConsecutiveTableGenBreakingDAGArgColons",
+ Style.AlignConsecutiveTableGenBreakingDAGArgColons);
+ IO.mapOptional("AlignConsecutiveTableGenCondOperatorColons",
+ Style.AlignConsecutiveTableGenCondOperatorColons);
+ IO.mapOptional("AlignConsecutiveTableGenDefinitionColons",
+ Style.AlignConsecutiveTableGenDefinitionColons);
IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines);
IO.mapOptional("AlignOperands", Style.AlignOperands);
IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
@@ -920,6 +925,8 @@ template <> struct MappingTraits<FormatStyle> {
Style.AllowBreakBeforeNoexceptSpecifier);
IO.mapOptional("AllowShortBlocksOnASingleLine",
Style.AllowShortBlocksOnASingleLine);
+ IO.mapOptional("AllowShortCaseExpressionOnASingleLine",
+ Style.AllowShortCaseExpressionOnASingleLine);
IO.mapOptional("AllowShortCaseLabelsOnASingleLine",
Style.AllowShortCaseLabelsOnASingleLine);
IO.mapOptional("AllowShortCompoundRequirementOnASingleLine",
@@ -936,12 +943,8 @@ template <> struct MappingTraits<FormatStyle> {
Style.AllowShortLoopsOnASingleLine);
IO.mapOptional("AlwaysBreakAfterDefinitionReturnType",
Style.AlwaysBreakAfterDefinitionReturnType);
- IO.mapOptional("AlwaysBreakAfterReturnType",
- Style.AlwaysBreakAfterReturnType);
IO.mapOptional("AlwaysBreakBeforeMultilineStrings",
Style.AlwaysBreakBeforeMultilineStrings);
- IO.mapOptional("AlwaysBreakTemplateDeclarations",
- Style.AlwaysBreakTemplateDeclarations);
IO.mapOptional("AttributeMacros", Style.AttributeMacros);
IO.mapOptional("BinPackArguments", Style.BinPackArguments);
IO.mapOptional("BinPackParameters", Style.BinPackParameters);
@@ -954,6 +957,7 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("BreakAfterAttributes", Style.BreakAfterAttributes);
IO.mapOptional("BreakAfterJavaFieldAnnotations",
Style.BreakAfterJavaFieldAnnotations);
+ IO.mapOptional("BreakAfterReturnType", Style.BreakAfterReturnType);
IO.mapOptional("BreakArrays", Style.BreakArrays);
IO.mapOptional("BreakBeforeBinaryOperators",
Style.BreakBeforeBinaryOperators);
@@ -966,8 +970,12 @@ template <> struct MappingTraits<FormatStyle> {
Style.BreakBeforeTernaryOperators);
IO.mapOptional("BreakConstructorInitializers",
Style.BreakConstructorInitializers);
+ IO.mapOptional("BreakFunctionDefinitionParameters",
+ Style.BreakFunctionDefinitionParameters);
IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList);
IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals);
+ IO.mapOptional("BreakTemplateDeclarations",
+ Style.BreakTemplateDeclarations);
IO.mapOptional("ColumnLimit", Style.ColumnLimit);
IO.mapOptional("CommentPragmas", Style.CommentPragmas);
IO.mapOptional("CompactNamespaces", Style.CompactNamespaces);
@@ -1008,14 +1016,13 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("JavaImportGroups", Style.JavaImportGroups);
IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes);
IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);
- IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
- Style.KeepEmptyLinesAtTheStartOfBlocks);
- IO.mapOptional("KeepEmptyLinesAtEOF", Style.KeepEmptyLinesAtEOF);
+ IO.mapOptional("KeepEmptyLines", Style.KeepEmptyLines);
IO.mapOptional("LambdaBodyIndentation", Style.LambdaBodyIndentation);
IO.mapOptional("LineEnding", Style.LineEnding);
IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin);
IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd);
IO.mapOptional("Macros", Style.Macros);
+ IO.mapOptional("MainIncludeChar", Style.IncludeStyle.MainIncludeChar);
IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation);
IO.mapOptional("NamespaceMacros", Style.NamespaceMacros);
@@ -1110,6 +1117,10 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("StatementAttributeLikeMacros",
Style.StatementAttributeLikeMacros);
IO.mapOptional("StatementMacros", Style.StatementMacros);
+ IO.mapOptional("TableGenBreakingDAGArgOperators",
+ Style.TableGenBreakingDAGArgOperators);
+ IO.mapOptional("TableGenBreakInsideDAGArg",
+ Style.TableGenBreakInsideDAGArg);
IO.mapOptional("TabWidth", Style.TabWidth);
IO.mapOptional("TypeNames", Style.TypeNames);
IO.mapOptional("TypenameMacros", Style.TypenameMacros);
@@ -1120,17 +1131,16 @@ template <> struct MappingTraits<FormatStyle> {
Style.WhitespaceSensitiveMacros);
// If AlwaysBreakAfterDefinitionReturnType was specified but
- // AlwaysBreakAfterReturnType was not, initialize the latter from the
- // former for backwards compatibility.
+ // BreakAfterReturnType was not, initialize the latter from the former for
+ // backwards compatibility.
if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None &&
- Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None) {
+ Style.BreakAfterReturnType == FormatStyle::RTBS_None) {
if (Style.AlwaysBreakAfterDefinitionReturnType ==
FormatStyle::DRTBS_All) {
- Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
+ Style.BreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
} else if (Style.AlwaysBreakAfterDefinitionReturnType ==
FormatStyle::DRTBS_TopLevel) {
- Style.AlwaysBreakAfterReturnType =
- FormatStyle::RTBS_TopLevelDefinitions;
+ Style.BreakAfterReturnType = FormatStyle::RTBS_TopLevelDefinitions;
}
}
@@ -1175,8 +1185,8 @@ template <> struct MappingTraits<FormatStyle> {
(SpacesInParentheses || SpaceInEmptyParentheses ||
SpacesInConditionalStatement || SpacesInCStyleCastParentheses)) {
if (SpacesInParentheses) {
- // set all options except InCStyleCasts and InEmptyParentheses
- // to true for backward compatibility.
+ // For backward compatibility.
+ Style.SpacesInParensOptions.ExceptDoubleParentheses = false;
Style.SpacesInParensOptions.InConditionalStatements = true;
Style.SpacesInParensOptions.InCStyleCasts =
SpacesInCStyleCastParentheses;
@@ -1236,7 +1246,7 @@ std::error_code make_error_code(ParseError e) {
return std::error_code(static_cast<int>(e), getParseCategory());
}
-inline llvm::Error make_string_error(const llvm::Twine &Message) {
+inline llvm::Error make_string_error(const Twine &Message) {
return llvm::make_error<llvm::StringError>(Message,
llvm::inconvertibleErrorCode());
}
@@ -1401,30 +1411,33 @@ static void expandPresetsSpacesInParens(FormatStyle &Expanded) {
FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
FormatStyle LLVMStyle;
- LLVMStyle.InheritsParentConfig = false;
- LLVMStyle.Language = Language;
LLVMStyle.AccessModifierOffset = -2;
- LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right;
LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align;
LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None;
- LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
LLVMStyle.AlignConsecutiveAssignments = {};
- LLVMStyle.AlignConsecutiveAssignments.Enabled = false;
- LLVMStyle.AlignConsecutiveAssignments.AcrossEmptyLines = false;
LLVMStyle.AlignConsecutiveAssignments.AcrossComments = false;
+ LLVMStyle.AlignConsecutiveAssignments.AcrossEmptyLines = false;
LLVMStyle.AlignConsecutiveAssignments.AlignCompound = false;
LLVMStyle.AlignConsecutiveAssignments.AlignFunctionPointers = false;
+ LLVMStyle.AlignConsecutiveAssignments.Enabled = false;
LLVMStyle.AlignConsecutiveAssignments.PadOperators = true;
LLVMStyle.AlignConsecutiveBitFields = {};
LLVMStyle.AlignConsecutiveDeclarations = {};
LLVMStyle.AlignConsecutiveMacros = {};
LLVMStyle.AlignConsecutiveShortCaseStatements = {};
+ LLVMStyle.AlignConsecutiveTableGenBreakingDAGArgColons = {};
+ LLVMStyle.AlignConsecutiveTableGenCondOperatorColons = {};
+ LLVMStyle.AlignConsecutiveTableGenDefinitionColons = {};
+ LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right;
+ LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
LLVMStyle.AlignTrailingComments = {};
LLVMStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Always;
LLVMStyle.AlignTrailingComments.OverEmptyLines = 0;
LLVMStyle.AllowAllArgumentsOnNextLine = true;
LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
+ LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never;
LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;
+ LLVMStyle.AllowShortCaseExpressionOnASingleLine = true;
LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;
LLVMStyle.AllowShortCompoundRequirementOnASingleLine = true;
LLVMStyle.AllowShortEnumsOnASingleLine = true;
@@ -1432,14 +1445,12 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
LLVMStyle.AllowShortLoopsOnASingleLine = false;
- LLVMStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None;
LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
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.BitFieldColonSpacing = FormatStyle::BFCS_Both;
LLVMStyle.BracedInitializerIndentWidth = std::nullopt;
LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false,
/*AfterClass=*/false,
@@ -1462,16 +1473,18 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.BreakAdjacentStringLiterals = true;
LLVMStyle.BreakAfterAttributes = FormatStyle::ABS_Leave;
LLVMStyle.BreakAfterJavaFieldAnnotations = false;
+ LLVMStyle.BreakAfterReturnType = FormatStyle::RTBS_None;
LLVMStyle.BreakArrays = true;
LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
LLVMStyle.BreakBeforeConceptDeclarations = FormatStyle::BBCDS_Always;
LLVMStyle.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline;
- LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never;
LLVMStyle.BreakBeforeTernaryOperators = true;
LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
+ LLVMStyle.BreakFunctionDefinitionParameters = false;
LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
LLVMStyle.BreakStringLiterals = true;
+ LLVMStyle.BreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;
LLVMStyle.ColumnLimit = 80;
LLVMStyle.CommentPragmas = "^ IWYU pragma:";
LLVMStyle.CompactNamespaces = false;
@@ -1488,21 +1501,23 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
LLVMStyle.IfMacros.push_back("KJ_IF_MAYBE");
+ LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;
LLVMStyle.IncludeStyle.IncludeCategories = {
{"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false},
{"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false},
{".*", 1, 0, false}};
LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
- LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;
+ LLVMStyle.IncludeStyle.MainIncludeChar = tooling::IncludeStyle::MICD_Quote;
LLVMStyle.IndentAccessModifiers = false;
- LLVMStyle.IndentCaseLabels = false;
LLVMStyle.IndentCaseBlocks = false;
+ LLVMStyle.IndentCaseLabels = false;
LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
LLVMStyle.IndentGotoLabels = true;
LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;
LLVMStyle.IndentRequiresClause = true;
LLVMStyle.IndentWidth = 2;
LLVMStyle.IndentWrappedFunctionNames = false;
+ LLVMStyle.InheritsParentConfig = false;
LLVMStyle.InsertBraces = false;
LLVMStyle.InsertNewlineAtEOF = false;
LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None;
@@ -1512,9 +1527,13 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
/*Hex=*/0, /*HexMinDigits=*/0};
LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
LLVMStyle.JavaScriptWrapImports = true;
- LLVMStyle.KeepEmptyLinesAtEOF = false;
- LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true;
+ LLVMStyle.KeepEmptyLines = {
+ /*AtEndOfFile=*/false,
+ /*AtStartOfBlock=*/true,
+ /*AtStartOfFile=*/true,
+ };
LLVMStyle.LambdaBodyIndentation = FormatStyle::LBI_Signature;
+ LLVMStyle.Language = Language;
LLVMStyle.LineEnding = FormatStyle::LE_DeriveLF;
LLVMStyle.MaxEmptyLinesToKeep = 1;
LLVMStyle.NamespaceIndentation = FormatStyle::NI_None;
@@ -1544,7 +1563,9 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.SpaceAfterLogicalNot = false;
LLVMStyle.SpaceAfterTemplateKeyword = true;
LLVMStyle.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default;
+ LLVMStyle.SpaceBeforeAssignmentOperators = true;
LLVMStyle.SpaceBeforeCaseColon = false;
+ LLVMStyle.SpaceBeforeCpp11BracedList = false;
LLVMStyle.SpaceBeforeCtorInitializerColon = true;
LLVMStyle.SpaceBeforeInheritanceColon = true;
LLVMStyle.SpaceBeforeJsonColon = false;
@@ -1554,8 +1575,6 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.SpaceBeforeParensOptions.AfterForeachMacros = true;
LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true;
LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;
- LLVMStyle.SpaceBeforeAssignmentOperators = true;
- LLVMStyle.SpaceBeforeCpp11BracedList = false;
LLVMStyle.SpaceBeforeSquareBrackets = false;
LLVMStyle.SpaceInEmptyBlock = false;
LLVMStyle.SpacesBeforeTrailingComments = 1;
@@ -1568,6 +1587,8 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT");
LLVMStyle.StatementMacros.push_back("Q_UNUSED");
LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION");
+ LLVMStyle.TableGenBreakingDAGArgOperators = {};
+ LLVMStyle.TableGenBreakInsideDAGArg = FormatStyle::DAS_DontBreak;
LLVMStyle.TabWidth = 8;
LLVMStyle.UseTab = FormatStyle::UT_Never;
LLVMStyle.VerilogBreakBetweenInstancePorts = true;
@@ -1578,16 +1599,16 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE");
LLVMStyle.PenaltyBreakAssignment = prec::Assignment;
+ LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;
LLVMStyle.PenaltyBreakComment = 300;
LLVMStyle.PenaltyBreakFirstLessLess = 120;
- LLVMStyle.PenaltyBreakString = 1000;
- LLVMStyle.PenaltyExcessCharacter = 1000000;
- LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;
- LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;
LLVMStyle.PenaltyBreakOpenParenthesis = 0;
LLVMStyle.PenaltyBreakScopeResolution = 500;
+ LLVMStyle.PenaltyBreakString = 1000;
LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational;
+ LLVMStyle.PenaltyExcessCharacter = 1'000'000;
LLVMStyle.PenaltyIndentedWhitespace = 0;
+ LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;
// Defaults that differ when not C++.
switch (Language) {
@@ -1624,16 +1645,16 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
FormatStyle::SIS_WithoutElse;
GoogleStyle.AllowShortLoopsOnASingleLine = true;
GoogleStyle.AlwaysBreakBeforeMultilineStrings = true;
- GoogleStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
+ GoogleStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;
GoogleStyle.DerivePointerAlignment = true;
+ GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false},
{"^<.*\\.h>", 1, 0, false},
{"^<.*", 2, 0, false},
{".*", 3, 0, false}};
GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
- GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
GoogleStyle.IndentCaseLabels = true;
- GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false;
+ GoogleStyle.KeepEmptyLines.AtStartOfBlock = false;
GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never;
GoogleStyle.ObjCSpaceAfterProperty = false;
GoogleStyle.ObjCSpaceBeforeProtocolList = true;
@@ -1686,8 +1707,8 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
GoogleStyle.SpacesBeforeTrailingComments = 2;
GoogleStyle.Standard = FormatStyle::LS_Auto;
- GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200;
GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1;
+ GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200;
if (Language == FormatStyle::LK_Java) {
GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
@@ -1715,22 +1736,22 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
// TODO: enable once decided, in particular re disabling bin packing.
// https://google.github.io/styleguide/jsguide.html#features-arrays-trailing-comma
// GoogleStyle.InsertTrailingCommas = FormatStyle::TCS_Wrapped;
+ GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single;
+ GoogleStyle.JavaScriptWrapImports = false;
GoogleStyle.MaxEmptyLinesToKeep = 3;
GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
GoogleStyle.SpacesInContainerLiterals = false;
- GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single;
- GoogleStyle.JavaScriptWrapImports = false;
} else if (Language == FormatStyle::LK_Proto) {
GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
- GoogleStyle.SpacesInContainerLiterals = false;
- GoogleStyle.Cpp11BracedListStyle = false;
// This affects protocol buffer options specifications and text protos.
// Text protos are currently mostly formatted inside C++ raw string literals
// and often the current breaking behavior of string literals is not
// beneficial there. Investigate turning this on once proper string reflow
// has been implemented.
GoogleStyle.BreakStringLiterals = false;
+ GoogleStyle.Cpp11BracedListStyle = false;
+ GoogleStyle.SpacesInContainerLiterals = false;
} else if (Language == FormatStyle::LK_ObjC) {
GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
GoogleStyle.ColumnLimit = 100;
@@ -1814,15 +1835,15 @@ FormatStyle getMozillaStyle() {
FormatStyle MozillaStyle = getLLVMStyle();
MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
- MozillaStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevel;
MozillaStyle.AlwaysBreakAfterDefinitionReturnType =
FormatStyle::DRTBS_TopLevel;
- MozillaStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
- MozillaStyle.BinPackParameters = false;
MozillaStyle.BinPackArguments = false;
+ MozillaStyle.BinPackParameters = false;
+ MozillaStyle.BreakAfterReturnType = FormatStyle::RTBS_TopLevel;
MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;
MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
+ MozillaStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;
MozillaStyle.ConstructorInitializerIndentWidth = 2;
MozillaStyle.ContinuationIndentWidth = 2;
MozillaStyle.Cpp11BracedListStyle = false;
@@ -1847,8 +1868,8 @@ FormatStyle getWebKitStyle() {
Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
Style.BreakBeforeBraces = FormatStyle::BS_WebKit;
Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
- Style.Cpp11BracedListStyle = false;
Style.ColumnLimit = 0;
+ Style.Cpp11BracedListStyle = false;
Style.FixNamespaceComments = false;
Style.IndentWidth = 4;
Style.NamespaceIndentation = FormatStyle::NI_Inner;
@@ -1863,12 +1884,12 @@ FormatStyle getWebKitStyle() {
FormatStyle getGNUStyle() {
FormatStyle Style = getLLVMStyle();
Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All;
- Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
+ Style.BreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
Style.BreakBeforeBraces = FormatStyle::BS_GNU;
Style.BreakBeforeTernaryOperators = true;
- Style.Cpp11BracedListStyle = false;
Style.ColumnLimit = 79;
+ Style.Cpp11BracedListStyle = false;
Style.FixNamespaceComments = false;
Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
Style.Standard = FormatStyle::LS_Cpp03;
@@ -1900,7 +1921,7 @@ FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) {
Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
Style.AllowShortLoopsOnASingleLine = false;
Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
- Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None;
+ Style.BreakAfterReturnType = FormatStyle::RTBS_None;
return Style;
}
@@ -1908,9 +1929,12 @@ FormatStyle getClangFormatStyle() {
FormatStyle Style = getLLVMStyle();
Style.InsertBraces = true;
Style.InsertNewlineAtEOF = true;
+ Style.IntegerLiteralSeparator.Decimal = 3;
+ Style.IntegerLiteralSeparator.DecimalMinDigits = 5;
Style.LineEnding = FormatStyle::LE_LF;
Style.RemoveBracesLLVM = true;
Style.RemoveParentheses = FormatStyle::RPS_ReturnStatement;
+ Style.RemoveSemicolon = true;
return Style;
}
@@ -2255,27 +2279,36 @@ public:
FormatTokenLexer &Tokens) override {
AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
tooling::Replacements Result;
- removeSemi(AnnotatedLines, Result);
+ removeSemi(Annotator, AnnotatedLines, Result);
return {Result, 0};
}
private:
- void removeSemi(SmallVectorImpl<AnnotatedLine *> &Lines,
+ void removeSemi(TokenAnnotator &Annotator,
+ SmallVectorImpl<AnnotatedLine *> &Lines,
tooling::Replacements &Result) {
+ auto PrecededByFunctionRBrace = [](const FormatToken &Tok) {
+ const auto *Prev = Tok.Previous;
+ if (!Prev || Prev->isNot(tok::r_brace))
+ return false;
+ const auto *LBrace = Prev->MatchingParen;
+ return LBrace && LBrace->is(TT_FunctionLBrace);
+ };
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);
+ removeSemi(Annotator, Line->Children, Result);
if (!Line->Affected)
continue;
+ Annotator.calculateFormattingInformation(*Line);
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))
+ if (Token->isNot(tok::semi) ||
+ (!Token->Optional && !PrecededByFunctionRBrace(*Token))) {
continue;
+ }
auto Next = Token->Next;
assert(Next || Token == Line->Last);
if (!Next && NextLine)
@@ -2342,7 +2375,7 @@ private:
// FIXME: handle error. For now, print error message and skip the
// replacement for release version.
if (Err) {
- llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+ llvm::errs() << toString(std::move(Err)) << "\n";
assert(false);
}
};
@@ -2783,7 +2816,7 @@ private:
// FIXME: better error handling. for now just print error message and skip
// for the release version.
if (Err) {
- llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+ llvm::errs() << toString(std::move(Err)) << "\n";
assert(false && "Fixes must not conflict!");
}
Idx = End + 1;
@@ -2942,9 +2975,9 @@ private:
<< getTokenTypeName(FormatTok->getType()) << "\n");
return true;
}
- if (guessIsObjC(SourceManager, Line->Children, Keywords))
- return true;
}
+ if (guessIsObjC(SourceManager, Line->Children, Keywords))
+ return true;
}
return false;
}
@@ -3055,7 +3088,7 @@ static void sortCppIncludes(const FormatStyle &Style,
llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size()));
if (Style.SortIncludes == FormatStyle::SI_CaseInsensitive) {
- llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
+ stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
return std::tie(Includes[LHSI].Priority, LHSFilenameLower,
@@ -3064,7 +3097,7 @@ static void sortCppIncludes(const FormatStyle &Style,
Includes[RHSI].Filename);
});
} else {
- llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
+ stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename);
});
@@ -3096,11 +3129,12 @@ static void sortCppIncludes(const FormatStyle &Style,
// enough as additional newlines might be added or removed across #include
// blocks. This we handle below by generating the updated #include blocks and
// comparing it to the original.
- if (Indices.size() == Includes.size() && llvm::is_sorted(Indices) &&
+ if (Indices.size() == Includes.size() && is_sorted(Indices) &&
Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve) {
return;
}
+ const auto OldCursor = Cursor ? *Cursor : 0;
std::string result;
for (unsigned Index : Indices) {
if (!result.empty()) {
@@ -3124,6 +3158,8 @@ static void sortCppIncludes(const FormatStyle &Style,
// the entire range of blocks. Otherwise, no replacement is generated.
if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(
IncludesBeginOffset, IncludesBlockSize)))) {
+ if (Cursor)
+ *Cursor = OldCursor;
return;
}
@@ -3132,7 +3168,7 @@ static void sortCppIncludes(const FormatStyle &Style,
// FIXME: better error handling. For now, just skip the replacement for the
// release version.
if (Err) {
- llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+ llvm::errs() << toString(std::move(Err)) << "\n";
assert(false);
}
}
@@ -3186,10 +3222,16 @@ tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
if (Trimmed.contains(RawStringTermination))
FormattingOff = false;
- if (isClangFormatOff(Trimmed))
+ bool IsBlockComment = false;
+
+ if (isClangFormatOff(Trimmed)) {
FormattingOff = true;
- else if (isClangFormatOn(Trimmed))
+ } else if (isClangFormatOn(Trimmed)) {
FormattingOff = false;
+ } else if (Trimmed.starts_with("/*")) {
+ IsBlockComment = true;
+ Pos = Code.find("*/", SearchFrom + 2);
+ }
const bool EmptyLineSkipped =
Trimmed.empty() &&
@@ -3199,9 +3241,10 @@ tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
bool MergeWithNextLine = Trimmed.ends_with("\\");
if (!FormattingOff && !MergeWithNextLine) {
- if (tooling::HeaderIncludes::IncludeRegex.match(Line, &Matches)) {
+ if (!IsBlockComment &&
+ tooling::HeaderIncludes::IncludeRegex.match(Trimmed, &Matches)) {
StringRef IncludeName = Matches[2];
- if (Line.contains("/*") && !Line.contains("*/")) {
+ if (Trimmed.contains("/*") && !Trimmed.contains("*/")) {
// #include with a start of a block comment, but without the end.
// Need to keep all the lines until the end of the comment together.
// FIXME: This is somehow simplified check that probably does not work
@@ -3285,7 +3328,7 @@ static void sortJavaImports(const FormatStyle &Style,
bool StaticImportAfterNormalImport =
Style.SortJavaStaticImport == FormatStyle::SJSIO_After;
- llvm::sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
+ sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
// Negating IsStatic to push static imports above non-static imports.
return std::make_tuple(!Imports[LHSI].IsStatic ^
StaticImportAfterNormalImport,
@@ -3335,7 +3378,7 @@ static void sortJavaImports(const FormatStyle &Style,
// FIXME: better error handling. For now, just skip the replacement for the
// release version.
if (Err) {
- llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+ llvm::errs() << toString(std::move(Err)) << "\n";
assert(false);
}
}
@@ -3429,7 +3472,7 @@ tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
}
template <typename T>
-static llvm::Expected<tooling::Replacements>
+static Expected<tooling::Replacements>
processReplacements(T ProcessFunc, StringRef Code,
const tooling::Replacements &Replaces,
const FormatStyle &Style) {
@@ -3448,7 +3491,7 @@ processReplacements(T ProcessFunc, StringRef Code,
return Replaces.merge(FormatReplaces);
}
-llvm::Expected<tooling::Replacements>
+Expected<tooling::Replacements>
formatReplacements(StringRef Code, const tooling::Replacements &Replaces,
const FormatStyle &Style) {
// We need to use lambda function here since there are two versions of
@@ -3493,13 +3536,13 @@ fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
return Replaces;
tooling::Replacements HeaderInsertions;
- std::set<llvm::StringRef> HeadersToDelete;
+ std::set<StringRef> HeadersToDelete;
tooling::Replacements Result;
for (const auto &R : Replaces) {
if (isHeaderInsertion(R)) {
// Replacements from \p Replaces must be conflict-free already, so we can
// simply consume the error.
- llvm::consumeError(HeaderInsertions.add(R));
+ consumeError(HeaderInsertions.add(R));
} else if (isHeaderDeletion(R)) {
HeadersToDelete.insert(R.getReplacementText());
} else if (R.getOffset() == UINT_MAX) {
@@ -3507,7 +3550,7 @@ fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
"not supported! "
<< R.getReplacementText() << "\n";
} else {
- llvm::consumeError(Result.add(R));
+ consumeError(Result.add(R));
}
}
if (HeaderInsertions.empty() && HeadersToDelete.empty())
@@ -3524,13 +3567,12 @@ fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
if (Err) {
// Ignore the deletion on conflict.
llvm::errs() << "Failed to add header deletion replacement for "
- << Header << ": " << llvm::toString(std::move(Err))
- << "\n";
+ << Header << ": " << toString(std::move(Err)) << "\n";
}
}
}
- llvm::SmallVector<StringRef, 4> Matches;
+ SmallVector<StringRef, 4> Matches;
for (const auto &R : HeaderInsertions) {
auto IncludeDirective = R.getReplacementText();
bool Matched =
@@ -3545,7 +3587,7 @@ fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
if (Replace) {
auto Err = Result.add(*Replace);
if (Err) {
- llvm::consumeError(std::move(Err));
+ consumeError(std::move(Err));
unsigned NewOffset =
Result.getShiftedCodePosition(Replace->getOffset());
auto Shifted = tooling::Replacement(FileName, NewOffset, 0,
@@ -3559,13 +3601,13 @@ fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
} // anonymous namespace
-llvm::Expected<tooling::Replacements>
+Expected<tooling::Replacements>
cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
const FormatStyle &Style) {
// We need to use lambda function here since there are two versions of
// `cleanup`.
auto Cleanup = [](const FormatStyle &Style, StringRef Code,
- std::vector<tooling::Range> Ranges,
+ ArrayRef<tooling::Range> Ranges,
StringRef FileName) -> tooling::Replacements {
return cleanup(Style, Code, Ranges, FileName);
};
@@ -3671,7 +3713,7 @@ reformat(const FormatStyle &Style, StringRef Code,
FormatStyle S = Expanded;
S.RemoveSemicolon = true;
Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {
- return SemiRemover(Env, S).process(/*SkipAnnotation=*/true);
+ return SemiRemover(Env, S).process();
});
}
@@ -3748,11 +3790,11 @@ reformat(const FormatStyle &Style, StringRef Code,
tooling::Replacements NonNoOpFixes;
for (const tooling::Replacement &Fix : Fixes) {
StringRef OriginalCode = Code.substr(Fix.getOffset(), Fix.getLength());
- if (!OriginalCode.equals(Fix.getReplacementText())) {
+ if (OriginalCode != Fix.getReplacementText()) {
auto Err = NonNoOpFixes.add(Fix);
if (Err) {
llvm::errs() << "Error adding replacements : "
- << llvm::toString(std::move(Err)) << "\n";
+ << toString(std::move(Err)) << "\n";
}
}
}
@@ -3836,8 +3878,7 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style) {
LangOpts.Digraphs = LexingStd >= FormatStyle::LS_Cpp11;
LangOpts.LineComment = 1;
- bool AlternativeOperators = Style.isCpp();
- LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0;
+ LangOpts.CXXOperatorNames = Style.isCpp();
LangOpts.Bool = 1;
LangOpts.ObjC = 1;
LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally.
@@ -3875,7 +3916,11 @@ static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
FileName.ends_with_insensitive(".protodevel")) {
return FormatStyle::LK_Proto;
}
- if (FileName.ends_with_insensitive(".textpb") ||
+ // txtpb is the canonical extension, and textproto is the legacy canonical
+ // extension
+ // https://protobuf.dev/reference/protobuf/textformat-spec/#text-format-files
+ if (FileName.ends_with_insensitive(".txtpb") ||
+ FileName.ends_with_insensitive(".textpb") ||
FileName.ends_with_insensitive(".pb.txt") ||
FileName.ends_with_insensitive(".textproto") ||
FileName.ends_with_insensitive(".asciipb")) {
@@ -3902,7 +3947,7 @@ FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) {
auto Extension = llvm::sys::path::extension(FileName);
// If there's no file extension (or it's .h), we need to check the contents
// of the code to see if it contains Objective-C.
- if (Extension.empty() || Extension == ".h") {
+ if (!Code.empty() && (Extension.empty() || Extension == ".h")) {
auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName;
Environment Env(Code, NonEmptyFileName, /*Ranges=*/{});
ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle());
@@ -3921,34 +3966,37 @@ const char *DefaultFallbackStyle = "LLVM";
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS,
- FormatStyle *Style, bool AllowUnknownOptions) {
+ FormatStyle *Style, bool AllowUnknownOptions,
+ llvm::SourceMgr::DiagHandlerTy DiagHandler) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
FS->getBufferForFile(ConfigFile.str());
if (auto EC = Text.getError())
return EC;
- if (auto EC = parseConfiguration(*Text.get(), Style, AllowUnknownOptions))
+ if (auto EC = parseConfiguration(*Text.get(), Style, AllowUnknownOptions,
+ DiagHandler)) {
return EC;
+ }
return Text;
}
-llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
- StringRef FallbackStyleName,
- StringRef Code, llvm::vfs::FileSystem *FS,
- bool AllowUnknownOptions) {
+Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
+ StringRef FallbackStyleName, StringRef Code,
+ llvm::vfs::FileSystem *FS,
+ bool AllowUnknownOptions,
+ llvm::SourceMgr::DiagHandlerTy DiagHandler) {
FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code));
FormatStyle FallbackStyle = getNoStyle();
if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle))
return make_string_error("Invalid fallback style: " + FallbackStyleName);
- llvm::SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1>
- ChildFormatTextToApply;
+ SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1> ChildFormatTextToApply;
if (StyleName.starts_with("{")) {
// Parse YAML/JSON style from the command line.
StringRef Source = "<command-line>";
if (std::error_code ec =
parseConfiguration(llvm::MemoryBufferRef(StyleName, Source), &Style,
- AllowUnknownOptions)) {
+ AllowUnknownOptions, DiagHandler)) {
return make_string_error("Error parsing -style: " + ec.message());
}
@@ -3968,7 +4016,8 @@ llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
StyleName.starts_with_insensitive("file:")) {
auto ConfigFile = StyleName.substr(5);
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
- loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions);
+ loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions,
+ DiagHandler);
if (auto EC = Text.getError()) {
return make_string_error("Error reading " + ConfigFile + ": " +
EC.message());
@@ -4007,8 +4056,9 @@ llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
auto applyChildFormatTexts = [&](FormatStyle *Style) {
for (const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) {
- auto EC = parseConfiguration(*MemBuf, Style, AllowUnknownOptions,
- dropDiagnosticHandler);
+ auto EC =
+ parseConfiguration(*MemBuf, Style, AllowUnknownOptions,
+ DiagHandler ? DiagHandler : dropDiagnosticHandler);
// It was already correctly parsed.
assert(!EC);
static_cast<void>(EC);
@@ -4016,7 +4066,7 @@ llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
};
// Look for .clang-format/_clang-format file in the file's parent directories.
- llvm::SmallVector<std::string, 2> FilesToLookFor;
+ SmallVector<std::string, 2> FilesToLookFor;
FilesToLookFor.push_back(".clang-format");
FilesToLookFor.push_back("_clang-format");
@@ -4042,7 +4092,8 @@ llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
}
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
- loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions);
+ loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions,
+ DiagHandler);
if (auto EC = Text.getError()) {
if (EC != ParseError::Unsuitable) {
return make_string_error("Error reading " + ConfigFile + ": " +
diff --git a/contrib/llvm-project/clang/lib/Format/FormatInternal.h b/contrib/llvm-project/clang/lib/Format/FormatInternal.h
index 9043ce32e9e3..60c5bf6b786b 100644
--- a/contrib/llvm-project/clang/lib/Format/FormatInternal.h
+++ b/contrib/llvm-project/clang/lib/Format/FormatInternal.h
@@ -15,7 +15,9 @@
#ifndef LLVM_CLANG_LIB_FORMAT_FORMATINTERNAL_H
#define LLVM_CLANG_LIB_FORMAT_FORMATINTERNAL_H
-#include "BreakableToken.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Format/Format.h"
+#include "clang/Tooling/Core/Replacement.h"
#include <utility>
namespace clang {
diff --git a/contrib/llvm-project/clang/lib/Format/FormatToken.cpp b/contrib/llvm-project/clang/lib/Format/FormatToken.cpp
index b791c5a26bbe..85bec71ffbbc 100644
--- a/contrib/llvm-project/clang/lib/Format/FormatToken.cpp
+++ b/contrib/llvm-project/clang/lib/Format/FormatToken.cpp
@@ -34,45 +34,23 @@ const char *getTokenTypeName(TokenType Type) {
return nullptr;
}
-// FIXME: This is copy&pasted from Sema. Put it in a common place and remove
-// duplication.
-bool FormatToken::isSimpleTypeSpecifier() const {
- switch (Tok.getKind()) {
- case tok::kw_short:
- case tok::kw_long:
- case tok::kw___int64:
- case tok::kw___int128:
- case tok::kw_signed:
- case tok::kw_unsigned:
- case tok::kw_void:
- case tok::kw_char:
- case tok::kw_int:
- case tok::kw_half:
- case tok::kw_float:
- case tok::kw_double:
- case tok::kw___bf16:
- case tok::kw__Float16:
- case tok::kw___float128:
- case tok::kw___ibm128:
- case tok::kw_wchar_t:
- case tok::kw_bool:
-#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:
- case tok::kw_char32_t:
- case tok::kw_typeof:
- case tok::kw_decltype:
- case tok::kw__Atomic:
- return true;
- default:
- return false;
- }
+// Sorted common C++ non-keyword types.
+static SmallVector<StringRef> CppNonKeywordTypes = {
+ "clock_t", "int16_t", "int32_t", "int64_t", "int8_t",
+ "intptr_t", "ptrdiff_t", "size_t", "time_t", "uint16_t",
+ "uint32_t", "uint64_t", "uint8_t", "uintptr_t",
+};
+
+bool FormatToken::isTypeName(const LangOptions &LangOpts) const {
+ const bool IsCpp = LangOpts.CXXOperatorNames;
+ return is(TT_TypeName) || Tok.isSimpleTypeSpecifier(LangOpts) ||
+ (IsCpp && is(tok::identifier) &&
+ std::binary_search(CppNonKeywordTypes.begin(),
+ CppNonKeywordTypes.end(), TokenText));
}
-bool FormatToken::isTypeOrIdentifier() const {
- return isSimpleTypeSpecifier() || Tok.isOneOf(tok::kw_auto, tok::identifier);
+bool FormatToken::isTypeOrIdentifier(const LangOptions &LangOpts) const {
+ return isTypeName(LangOpts) || isOneOf(tok::kw_auto, tok::identifier);
}
bool FormatToken::isBlockIndentedInitRBrace(const FormatStyle &Style) const {
@@ -137,7 +115,7 @@ unsigned CommaSeparatedList::formatAfterToken(LineState &State,
// bin-packed. Add a severe penalty to this so that column layouts are
// preferred if possible.
if (!Format)
- return 10000;
+ return 10'000;
// Format the entire list.
unsigned Penalty = 0;
diff --git a/contrib/llvm-project/clang/lib/Format/FormatToken.h b/contrib/llvm-project/clang/lib/Format/FormatToken.h
index dede89f26001..cc45d5a8c5c1 100644
--- a/contrib/llvm-project/clang/lib/Format/FormatToken.h
+++ b/contrib/llvm-project/clang/lib/Format/FormatToken.h
@@ -19,8 +19,6 @@
#include "clang/Basic/OperatorPrecedence.h"
#include "clang/Format/Format.h"
#include "clang/Lex/Lexer.h"
-#include <memory>
-#include <optional>
#include <unordered_set>
namespace clang {
@@ -37,7 +35,10 @@ namespace format {
TYPE(BinaryOperator) \
TYPE(BitFieldColon) \
TYPE(BlockComment) \
+ /* l_brace of a block that is not the body of a (e.g. loop) statement. */ \
+ TYPE(BlockLBrace) \
TYPE(BracedListLBrace) \
+ TYPE(CaseLabelArrow) \
/* The colon at the end of a case label. */ \
TYPE(CaseLabelColon) \
TYPE(CastRParen) \
@@ -76,6 +77,7 @@ namespace format {
TYPE(ForEachMacro) \
TYPE(FunctionAnnotationRParen) \
TYPE(FunctionDeclarationName) \
+ TYPE(FunctionDeclarationLParen) \
TYPE(FunctionLBrace) \
TYPE(FunctionLikeOrFreestandingMacro) \
TYPE(FunctionTypeLParen) \
@@ -148,7 +150,26 @@ namespace format {
TYPE(StructLBrace) \
TYPE(StructRBrace) \
TYPE(StructuredBindingLSquare) \
+ TYPE(SwitchExpressionLabel) \
+ TYPE(SwitchExpressionLBrace) \
+ TYPE(TableGenBangOperator) \
+ TYPE(TableGenCondOperator) \
+ TYPE(TableGenCondOperatorColon) \
+ TYPE(TableGenCondOperatorComma) \
+ TYPE(TableGenDAGArgCloser) \
+ TYPE(TableGenDAGArgListColon) \
+ TYPE(TableGenDAGArgListColonToAlign) \
+ TYPE(TableGenDAGArgListComma) \
+ TYPE(TableGenDAGArgListCommaToBreak) \
+ TYPE(TableGenDAGArgOpener) \
+ TYPE(TableGenDAGArgOpenerToBreak) \
+ TYPE(TableGenDAGArgOperatorID) \
+ TYPE(TableGenDAGArgOperatorToBreak) \
+ TYPE(TableGenListCloser) \
+ TYPE(TableGenListOpener) \
TYPE(TableGenMultiLineString) \
+ TYPE(TableGenTrailingPasteOperator) \
+ TYPE(TableGenValueSuffix) \
TYPE(TemplateCloser) \
TYPE(TemplateOpener) \
TYPE(TemplateString) \
@@ -559,6 +580,9 @@ public:
/// Is optional and can be removed.
bool Optional = false;
+ /// Might be function declaration open/closing paren.
+ bool MightBeFunctionDeclParen = false;
+
/// Number of optional braces to be inserted after this token:
/// -1: a single left brace
/// 0: no braces
@@ -644,12 +668,16 @@ public:
return Tok.isObjCAtKeyword(Kind);
}
+ bool isAccessSpecifierKeyword() const {
+ return isOneOf(tok::kw_public, tok::kw_protected, tok::kw_private);
+ }
+
bool isAccessSpecifier(bool ColonRequired = true) const {
- if (!isOneOf(tok::kw_public, tok::kw_protected, tok::kw_private))
+ if (!isAccessSpecifierKeyword())
return false;
if (!ColonRequired)
return true;
- const auto NextNonComment = getNextNonComment();
+ const auto *NextNonComment = getNextNonComment();
return NextNonComment && NextNonComment->is(tok::colon);
}
@@ -661,10 +689,8 @@ public:
isAttribute();
}
- /// Determine whether the token is a simple-type-specifier.
- [[nodiscard]] bool isSimpleTypeSpecifier() const;
-
- [[nodiscard]] bool isTypeOrIdentifier() const;
+ [[nodiscard]] bool isTypeName(const LangOptions &LangOpts) const;
+ [[nodiscard]] bool isTypeOrIdentifier(const LangOptions &LangOpts) const;
bool isObjCAccessSpecifier() const {
return is(tok::at) && Next &&
@@ -706,6 +732,29 @@ public:
return isOneOf(tok::star, tok::amp, tok::ampamp);
}
+ bool isCppAlternativeOperatorKeyword() const {
+ assert(!TokenText.empty());
+ if (!isalpha(TokenText[0]))
+ return false;
+
+ switch (Tok.getKind()) {
+ case tok::ampamp:
+ case tok::ampequal:
+ case tok::amp:
+ case tok::pipe:
+ case tok::tilde:
+ case tok::exclaim:
+ case tok::exclaimequal:
+ case tok::pipepipe:
+ case tok::pipeequal:
+ case tok::caret:
+ case tok::caretequal:
+ return true;
+ default:
+ return false;
+ }
+ }
+
bool isUnaryOperator() const {
switch (Tok.getKind()) {
case tok::plus:
@@ -809,8 +858,8 @@ public:
/// Returns whether the token is the left square bracket of a C++
/// structured binding declaration.
- bool isCppStructuredBinding(const FormatStyle &Style) const {
- if (!Style.isCpp() || isNot(tok::l_square))
+ bool isCppStructuredBinding(bool IsCpp) const {
+ if (!IsCpp || isNot(tok::l_square))
return false;
const FormatToken *T = this;
do {
@@ -1601,10 +1650,10 @@ struct AdditionalKeywords {
IdentifierInfo *kw_then;
/// Returns \c true if \p Tok is a keyword or an identifier.
- bool isWordLike(const FormatToken &Tok) const {
+ bool isWordLike(const FormatToken &Tok, bool IsVerilog = true) const {
// getIdentifierinfo returns non-null for keywords as well as identifiers.
return Tok.Tok.getIdentifierInfo() &&
- !Tok.isOneOf(kw_verilogHash, kw_verilogHashHash, kw_apostrophe);
+ (!IsVerilog || !isVerilogKeywordSymbol(Tok));
}
/// Returns \c true if \p Tok is a true JavaScript identifier, returns
@@ -1612,10 +1661,12 @@ struct AdditionalKeywords {
/// If \c AcceptIdentifierName is true, returns true not only for keywords,
// but also for IdentifierName tokens (aka pseudo-keywords), such as
// ``yield``.
- bool IsJavaScriptIdentifier(const FormatToken &Tok,
+ bool isJavaScriptIdentifier(const FormatToken &Tok,
bool AcceptIdentifierName = true) const {
// Based on the list of JavaScript & TypeScript keywords here:
// https://github.com/microsoft/TypeScript/blob/main/src/compiler/scanner.ts#L74
+ if (Tok.isAccessSpecifierKeyword())
+ return false;
switch (Tok.Tok.getKind()) {
case tok::kw_break:
case tok::kw_case:
@@ -1635,9 +1686,6 @@ struct AdditionalKeywords {
case tok::kw_import:
case tok::kw_module:
case tok::kw_new:
- case tok::kw_private:
- case tok::kw_protected:
- case tok::kw_public:
case tok::kw_return:
case tok::kw_static:
case tok::kw_switch:
@@ -1680,6 +1728,8 @@ struct AdditionalKeywords {
/// Returns \c true if \p Tok is a C# keyword, returns
/// \c false if it is a anything else.
bool isCSharpKeyword(const FormatToken &Tok) const {
+ if (Tok.isAccessSpecifierKeyword())
+ return true;
switch (Tok.Tok.getKind()) {
case tok::kw_bool:
case tok::kw_break:
@@ -1706,9 +1756,6 @@ struct AdditionalKeywords {
case tok::kw_namespace:
case tok::kw_new:
case tok::kw_operator:
- case tok::kw_private:
- case tok::kw_protected:
- case tok::kw_public:
case tok::kw_return:
case tok::kw_short:
case tok::kw_sizeof:
@@ -1733,6 +1780,10 @@ struct AdditionalKeywords {
}
}
+ bool isVerilogKeywordSymbol(const FormatToken &Tok) const {
+ return Tok.isOneOf(kw_verilogHash, kw_verilogHashHash, kw_apostrophe);
+ }
+
bool isVerilogWordOperator(const FormatToken &Tok) const {
return Tok.isOneOf(kw_before, kw_intersect, kw_dist, kw_iff, kw_inside,
kw_with);
diff --git a/contrib/llvm-project/clang/lib/Format/FormatTokenLexer.cpp b/contrib/llvm-project/clang/lib/Format/FormatTokenLexer.cpp
index 52a55ea23b5f..e21b5a882b77 100644
--- a/contrib/llvm-project/clang/lib/Format/FormatTokenLexer.cpp
+++ b/contrib/llvm-project/clang/lib/Format/FormatTokenLexer.cpp
@@ -276,13 +276,44 @@ void FormatTokenLexer::tryMergePreviousTokens() {
return;
}
}
- // TableGen's Multi line string starts with [{
- if (Style.isTableGen() && tryMergeTokens({tok::l_square, tok::l_brace},
- TT_TableGenMultiLineString)) {
- // Set again with finalizing. This must never be annotated as other types.
- Tokens.back()->setFinalizedType(TT_TableGenMultiLineString);
- Tokens.back()->Tok.setKind(tok::string_literal);
- return;
+ if (Style.isTableGen()) {
+ // TableGen's Multi line string starts with [{
+ if (tryMergeTokens({tok::l_square, tok::l_brace},
+ TT_TableGenMultiLineString)) {
+ // Set again with finalizing. This must never be annotated as other types.
+ Tokens.back()->setFinalizedType(TT_TableGenMultiLineString);
+ Tokens.back()->Tok.setKind(tok::string_literal);
+ return;
+ }
+ // TableGen's bang operator is the form !<name>.
+ // !cond is a special case with specific syntax.
+ if (tryMergeTokens({tok::exclaim, tok::identifier},
+ TT_TableGenBangOperator)) {
+ Tokens.back()->Tok.setKind(tok::identifier);
+ Tokens.back()->Tok.setIdentifierInfo(nullptr);
+ if (Tokens.back()->TokenText == "!cond")
+ Tokens.back()->setFinalizedType(TT_TableGenCondOperator);
+ else
+ Tokens.back()->setFinalizedType(TT_TableGenBangOperator);
+ return;
+ }
+ if (tryMergeTokens({tok::exclaim, tok::kw_if}, TT_TableGenBangOperator)) {
+ // Here, "! if" becomes "!if". That is, ! captures if even when the space
+ // exists. That is only one possibility in TableGen's syntax.
+ Tokens.back()->Tok.setKind(tok::identifier);
+ Tokens.back()->Tok.setIdentifierInfo(nullptr);
+ Tokens.back()->setFinalizedType(TT_TableGenBangOperator);
+ return;
+ }
+ // +, - with numbers are literals. Not unary operators.
+ if (tryMergeTokens({tok::plus, tok::numeric_constant}, TT_Unknown)) {
+ Tokens.back()->Tok.setKind(tok::numeric_constant);
+ return;
+ }
+ if (tryMergeTokens({tok::minus, tok::numeric_constant}, TT_Unknown)) {
+ Tokens.back()->Tok.setKind(tok::numeric_constant);
+ return;
+ }
}
}
@@ -373,7 +404,7 @@ bool FormatTokenLexer::tryMergeNullishCoalescingEqual() {
return false;
auto &NullishCoalescing = *(Tokens.end() - 2);
auto &Equal = *(Tokens.end() - 1);
- if (NullishCoalescing->getType() != TT_NullCoalescingOperator ||
+ if (NullishCoalescing->isNot(TT_NullCoalescingOperator) ||
Equal->isNot(tok::equal)) {
return false;
}
@@ -785,7 +816,7 @@ void FormatTokenLexer::handleTableGenMultilineString() {
auto CloseOffset = Lex->getBuffer().find("}]", OpenOffset);
if (CloseOffset == StringRef::npos)
return;
- auto Text = Lex->getBuffer().substr(OpenOffset, CloseOffset + 2);
+ auto Text = Lex->getBuffer().substr(OpenOffset, CloseOffset - OpenOffset + 2);
MultiLineString->TokenText = Text;
resetLexer(SourceMgr.getFileOffset(
Lex->getSourceLocation(Lex->getBufferLocation() - 2 + Text.size())));
@@ -1389,7 +1420,7 @@ void FormatTokenLexer::readRawToken(FormatToken &Tok) {
// For formatting, treat unterminated string literals like normal string
// literals.
if (Tok.is(tok::unknown)) {
- if (!Tok.TokenText.empty() && Tok.TokenText[0] == '"') {
+ if (Tok.TokenText.starts_with("\"")) {
Tok.Tok.setKind(tok::string_literal);
Tok.IsUnterminatedLiteral = true;
} else if (Style.isJavaScript() && Tok.TokenText == "''") {
@@ -1411,7 +1442,6 @@ void FormatTokenLexer::readRawToken(FormatToken &Tok) {
void FormatTokenLexer::resetLexer(unsigned Offset) {
StringRef Buffer = SourceMgr.getBufferData(ID);
- LangOpts = getFormattingLangOpts(Style);
Lex.reset(new Lexer(SourceMgr.getLocForStartOfFile(ID), LangOpts,
Buffer.begin(), Buffer.begin() + Offset, Buffer.end()));
Lex->SetKeepWhitespaceMode(true);
diff --git a/contrib/llvm-project/clang/lib/Format/FormatTokenLexer.h b/contrib/llvm-project/clang/lib/Format/FormatTokenLexer.h
index 65dd733bd533..277cc0a2dfde 100644
--- a/contrib/llvm-project/clang/lib/Format/FormatTokenLexer.h
+++ b/contrib/llvm-project/clang/lib/Format/FormatTokenLexer.h
@@ -17,14 +17,9 @@
#include "Encoding.h"
#include "FormatToken.h"
-#include "clang/Basic/LangOptions.h"
-#include "clang/Basic/SourceLocation.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Format/Format.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringSet.h"
-#include "llvm/Support/Regex.h"
#include <stack>
diff --git a/contrib/llvm-project/clang/lib/Format/FormatTokenSource.h b/contrib/llvm-project/clang/lib/Format/FormatTokenSource.h
index 7819244eb7d1..8f00e5f4582c 100644
--- a/contrib/llvm-project/clang/lib/Format/FormatTokenSource.h
+++ b/contrib/llvm-project/clang/lib/Format/FormatTokenSource.h
@@ -15,10 +15,7 @@
#ifndef LLVM_CLANG_LIB_FORMAT_FORMATTOKENSOURCE_H
#define LLVM_CLANG_LIB_FORMAT_FORMATTOKENSOURCE_H
-#include "FormatToken.h"
#include "UnwrappedLineParser.h"
-#include "llvm/ADT/DenseMap.h"
-#include <cstddef>
#define DEBUG_TYPE "format-token-source"
@@ -75,6 +72,15 @@ public:
// getNextToken() -> a1
// getNextToken() -> a2
virtual FormatToken *insertTokens(ArrayRef<FormatToken *> Tokens) = 0;
+
+ [[nodiscard]] FormatToken *getNextNonComment() {
+ FormatToken *Tok;
+ do {
+ Tok = getNextToken();
+ assert(Tok);
+ } while (Tok->is(tok::comment));
+ return Tok;
+ }
};
class IndexedTokenSource : public FormatTokenSource {
@@ -167,7 +173,7 @@ private:
return Next;
}
- void dbgToken(int Position, llvm::StringRef Indent = "") {
+ void dbgToken(int Position, StringRef Indent = "") {
FormatToken *Tok = Tokens[Position];
llvm::dbgs() << Indent << "[" << Position
<< "] Token: " << Tok->Tok.getName() << " / " << Tok->TokenText
diff --git a/contrib/llvm-project/clang/lib/Format/MacroCallReconstructor.cpp b/contrib/llvm-project/clang/lib/Format/MacroCallReconstructor.cpp
index cbdd1683c54d..101acefdfe7a 100644
--- a/contrib/llvm-project/clang/lib/Format/MacroCallReconstructor.cpp
+++ b/contrib/llvm-project/clang/lib/Format/MacroCallReconstructor.cpp
@@ -33,7 +33,7 @@ void forEachToken(const UnwrappedLine &Line, const T &Call,
FormatToken *Parent = nullptr) {
bool First = true;
for (const auto &N : Line.Tokens) {
- Call(N.Tok, Parent, First);
+ Call(N.Tok, Parent, First, Line.Level);
First = false;
for (const auto &Child : N.Children)
forEachToken(Child, Call, N.Tok);
@@ -44,7 +44,7 @@ MacroCallReconstructor::MacroCallReconstructor(
unsigned Level,
const llvm::DenseMap<FormatToken *, std::unique_ptr<UnwrappedLine>>
&ActiveExpansions)
- : Level(Level), IdToReconstructed(ActiveExpansions) {
+ : Result(Level), IdToReconstructed(ActiveExpansions) {
Result.Tokens.push_back(std::make_unique<LineNode>());
ActiveReconstructedLines.push_back(&Result);
}
@@ -52,9 +52,8 @@ MacroCallReconstructor::MacroCallReconstructor(
void MacroCallReconstructor::addLine(const UnwrappedLine &Line) {
assert(State != Finalized);
LLVM_DEBUG(llvm::dbgs() << "MCR: new line...\n");
- forEachToken(Line, [&](FormatToken *Token, FormatToken *Parent, bool First) {
- add(Token, Parent, First);
- });
+ forEachToken(Line, [&](FormatToken *Token, FormatToken *Parent, bool First,
+ unsigned Level) { add(Token, Parent, First, Level); });
assert(InProgress || finished());
}
@@ -62,8 +61,8 @@ UnwrappedLine MacroCallReconstructor::takeResult() && {
finalize();
assert(Result.Tokens.size() == 1 &&
Result.Tokens.front()->Children.size() == 1);
- UnwrappedLine Final =
- createUnwrappedLine(*Result.Tokens.front()->Children.front(), Level);
+ UnwrappedLine Final = createUnwrappedLine(
+ *Result.Tokens.front()->Children.front(), Result.Level);
assert(!Final.Tokens.empty());
return Final;
}
@@ -72,7 +71,8 @@ UnwrappedLine MacroCallReconstructor::takeResult() && {
// ExpandedParent in the incoming unwrapped line. \p First specifies whether it
// is the first token in a given unwrapped line.
void MacroCallReconstructor::add(FormatToken *Token,
- FormatToken *ExpandedParent, bool First) {
+ FormatToken *ExpandedParent, bool First,
+ unsigned Level) {
LLVM_DEBUG(
llvm::dbgs() << "MCR: Token: " << Token->TokenText << ", Parent: "
<< (ExpandedParent ? ExpandedParent->TokenText : "<null>")
@@ -102,7 +102,7 @@ void MacroCallReconstructor::add(FormatToken *Token,
First = true;
}
- prepareParent(ExpandedParent, First);
+ prepareParent(ExpandedParent, First, Level);
if (Token->MacroCtx) {
// If this token was generated by a macro call, add the reconstructed
@@ -129,7 +129,7 @@ void MacroCallReconstructor::add(FormatToken *Token,
// is the parent of ActiveReconstructedLines.back() in the reconstructed
// unwrapped line.
void MacroCallReconstructor::prepareParent(FormatToken *ExpandedParent,
- bool NewLine) {
+ bool NewLine, unsigned Level) {
LLVM_DEBUG({
llvm::dbgs() << "ParentMap:\n";
debugParentMap();
@@ -172,7 +172,7 @@ void MacroCallReconstructor::prepareParent(FormatToken *ExpandedParent,
}
assert(!ActiveReconstructedLines.empty());
ActiveReconstructedLines.back()->Tokens.back()->Children.push_back(
- std::make_unique<ReconstructedLine>());
+ std::make_unique<ReconstructedLine>(Level));
ActiveReconstructedLines.push_back(
&*ActiveReconstructedLines.back()->Tokens.back()->Children.back());
} else if (parentLine().Tokens.back()->Tok != Parent) {
@@ -424,7 +424,8 @@ bool MacroCallReconstructor::processNextReconstructed() {
SpelledParentToReconstructedParent[MacroCallStructure.back()
.ParentLastToken] = Token;
appendToken(Token);
- prepareParent(Token, /*NewLine=*/true);
+ prepareParent(Token, /*NewLine=*/true,
+ MacroCallStructure.back().Line->Level);
Token->MacroParent = true;
return false;
}
@@ -435,7 +436,8 @@ bool MacroCallReconstructor::processNextReconstructed() {
[MacroCallStructure.back().Line->Tokens.back()->Tok] = Token;
Token->MacroParent = true;
appendToken(Token, MacroCallStructure.back().Line);
- prepareParent(Token, /*NewLine=*/true);
+ prepareParent(Token, /*NewLine=*/true,
+ MacroCallStructure.back().Line->Level);
return true;
}
if (Token->is(tok::r_paren)) {
@@ -509,16 +511,36 @@ MacroCallReconstructor::createUnwrappedLine(const ReconstructedLine &Line,
for (const auto &N : Line.Tokens) {
Result.Tokens.push_back(N->Tok);
UnwrappedLineNode &Current = Result.Tokens.back();
- for (const auto &Child : N->Children) {
- if (Child->Tokens.empty())
- continue;
- Current.Children.push_back(createUnwrappedLine(*Child, Level + 1));
- }
- if (Current.Children.size() == 1 &&
- Current.Tok->isOneOf(tok::l_paren, tok::comma)) {
- Result.Tokens.splice(Result.Tokens.end(),
- Current.Children.front().Tokens);
- Current.Children.clear();
+ auto NumChildren =
+ std::count_if(N->Children.begin(), N->Children.end(),
+ [](const auto &Child) { return !Child->Tokens.empty(); });
+ if (NumChildren == 1 && Current.Tok->isOneOf(tok::l_paren, tok::comma)) {
+ // If we only have one child, and the child is due to a macro expansion
+ // (either attached to a left parenthesis or comma), merge the child into
+ // the current line to prevent forced breaks for macro arguments.
+ auto *Child = std::find_if(
+ N->Children.begin(), N->Children.end(),
+ [](const auto &Child) { return !Child->Tokens.empty(); });
+ auto Line = createUnwrappedLine(**Child, Level);
+ Result.Tokens.splice(Result.Tokens.end(), Line.Tokens);
+ } else if (NumChildren > 0) {
+ // When there are multiple children with different indent, make sure that
+ // we indent them:
+ // 1. One level below the current line's level.
+ // 2. At the correct level relative to each other.
+ unsigned MinChildLevel =
+ std::min_element(N->Children.begin(), N->Children.end(),
+ [](const auto &E1, const auto &E2) {
+ return E1->Level < E2->Level;
+ })
+ ->get()
+ ->Level;
+ for (const auto &Child : N->Children) {
+ if (Child->Tokens.empty())
+ continue;
+ Current.Children.push_back(createUnwrappedLine(
+ *Child, Level + 1 + (Child->Level - MinChildLevel)));
+ }
}
}
return Result;
diff --git a/contrib/llvm-project/clang/lib/Format/MacroExpander.cpp b/contrib/llvm-project/clang/lib/Format/MacroExpander.cpp
index 5a1cdd884c5e..5768ff37fefc 100644
--- a/contrib/llvm-project/clang/lib/Format/MacroExpander.cpp
+++ b/contrib/llvm-project/clang/lib/Format/MacroExpander.cpp
@@ -119,7 +119,7 @@ private:
};
MacroExpander::MacroExpander(
- const std::vector<std::string> &Macros, clang::SourceManager &SourceMgr,
+ const std::vector<std::string> &Macros, SourceManager &SourceMgr,
const FormatStyle &Style,
llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator,
IdentifierTable &IdentTable)
@@ -134,7 +134,7 @@ MacroExpander::~MacroExpander() = default;
void MacroExpander::parseDefinition(const std::string &Macro) {
Buffers.push_back(
llvm::MemoryBuffer::getMemBufferCopy(Macro, "<scratch space>"));
- clang::FileID FID = SourceMgr.createFileID(Buffers.back()->getMemBufferRef());
+ FileID FID = SourceMgr.createFileID(Buffers.back()->getMemBufferRef());
FormatTokenLexer Lex(SourceMgr, FID, 0, Style, encoding::Encoding_UTF8,
Allocator, IdentTable);
const auto Tokens = Lex.lex();
@@ -150,20 +150,20 @@ void MacroExpander::parseDefinition(const std::string &Macro) {
}
}
-bool MacroExpander::defined(llvm::StringRef Name) const {
+bool MacroExpander::defined(StringRef Name) const {
return FunctionLike.contains(Name) || ObjectLike.contains(Name);
}
-bool MacroExpander::objectLike(llvm::StringRef Name) const {
+bool MacroExpander::objectLike(StringRef Name) const {
return ObjectLike.contains(Name);
}
-bool MacroExpander::hasArity(llvm::StringRef Name, unsigned Arity) const {
+bool MacroExpander::hasArity(StringRef Name, unsigned Arity) const {
auto it = FunctionLike.find(Name);
return it != FunctionLike.end() && it->second.contains(Arity);
}
-llvm::SmallVector<FormatToken *, 8>
+SmallVector<FormatToken *, 8>
MacroExpander::expand(FormatToken *ID,
std::optional<ArgsList> OptionalArgs) const {
if (OptionalArgs)
diff --git a/contrib/llvm-project/clang/lib/Format/Macros.h b/contrib/llvm-project/clang/lib/Format/Macros.h
index 1964624e828c..e05f734b0db8 100644
--- a/contrib/llvm-project/clang/lib/Format/Macros.h
+++ b/contrib/llvm-project/clang/lib/Format/Macros.h
@@ -39,15 +39,9 @@
#define CLANG_LIB_FORMAT_MACROS_H
#include <list>
-#include <map>
-#include <string>
-#include <vector>
#include "FormatToken.h"
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
namespace clang {
namespace format {
@@ -85,7 +79,7 @@ struct UnwrappedLineNode;
///
class MacroExpander {
public:
- using ArgsList = llvm::ArrayRef<llvm::SmallVector<FormatToken *, 8>>;
+ using ArgsList = ArrayRef<SmallVector<FormatToken *, 8>>;
/// Construct a macro expander from a set of macro definitions.
/// Macro definitions must be encoded as UTF-8.
@@ -101,27 +95,27 @@ public:
/// Macros that cannot be parsed will be silently discarded.
///
MacroExpander(const std::vector<std::string> &Macros,
- clang::SourceManager &SourceMgr, const FormatStyle &Style,
+ SourceManager &SourceMgr, const FormatStyle &Style,
llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator,
IdentifierTable &IdentTable);
~MacroExpander();
/// Returns whether any macro \p Name is defined, regardless of overloads.
- bool defined(llvm::StringRef Name) const;
+ bool defined(StringRef Name) const;
/// Returns whetherh there is an object-like overload, i.e. where the macro
/// has no arguments and should not consume subsequent parentheses.
- bool objectLike(llvm::StringRef Name) const;
+ bool objectLike(StringRef Name) const;
/// Returns whether macro \p Name provides an overload with the given arity.
- bool hasArity(llvm::StringRef Name, unsigned Arity) const;
+ bool hasArity(StringRef Name, unsigned Arity) const;
/// Returns the expanded stream of format tokens for \p ID, where
/// each element in \p Args is a positional argument to the macro call.
/// If \p Args is not set, the object-like overload is used.
/// If \p Args is set, the overload with the arity equal to \c Args.size() is
/// used.
- llvm::SmallVector<FormatToken *, 8>
+ SmallVector<FormatToken *, 8>
expand(FormatToken *ID, std::optional<ArgsList> OptionalArgs) const;
private:
@@ -130,7 +124,7 @@ private:
void parseDefinition(const std::string &Macro);
- clang::SourceManager &SourceMgr;
+ SourceManager &SourceMgr;
const FormatStyle &Style;
llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator;
IdentifierTable &IdentTable;
@@ -231,8 +225,9 @@ public:
UnwrappedLine takeResult() &&;
private:
- void add(FormatToken *Token, FormatToken *ExpandedParent, bool First);
- void prepareParent(FormatToken *ExpandedParent, bool First);
+ void add(FormatToken *Token, FormatToken *ExpandedParent, bool First,
+ unsigned Level);
+ void prepareParent(FormatToken *ExpandedParent, bool First, unsigned Level);
FormatToken *getParentInResult(FormatToken *Parent);
void reconstruct(FormatToken *Token);
void startReconstruction(FormatToken *Token);
@@ -265,14 +260,16 @@ private:
LineNode() = default;
LineNode(FormatToken *Tok) : Tok(Tok) {}
FormatToken *Tok = nullptr;
- llvm::SmallVector<std::unique_ptr<ReconstructedLine>> Children;
+ SmallVector<std::unique_ptr<ReconstructedLine>> Children;
};
// Line in which we build up the resulting unwrapped line.
// FIXME: Investigate changing UnwrappedLine to a pointer type and using it
// instead of rolling our own type.
struct ReconstructedLine {
- llvm::SmallVector<std::unique_ptr<LineNode>> Tokens;
+ explicit ReconstructedLine(unsigned Level) : Level(Level) {}
+ unsigned Level;
+ SmallVector<std::unique_ptr<LineNode>> Tokens;
};
// The line in which we collect the resulting reconstructed output.
@@ -288,7 +285,7 @@ private:
// Stack of currently "open" lines, where each line's predecessor's last
// token is the parent token for that line.
- llvm::SmallVector<ReconstructedLine *> ActiveReconstructedLines;
+ SmallVector<ReconstructedLine *> ActiveReconstructedLines;
// Maps from the expanded token to the token that takes its place in the
// reconstructed token stream in terms of parent-child relationships.
@@ -328,7 +325,7 @@ private:
};
// Stack of macro calls for which we're in the middle of an expansion.
- llvm::SmallVector<Expansion> ActiveExpansions;
+ SmallVector<Expansion> ActiveExpansions;
struct MacroCallState {
MacroCallState(ReconstructedLine *Line, FormatToken *ParentLastToken,
@@ -371,10 +368,7 @@ private:
// |- ,
// | \- <argument>
// \- )
- llvm::SmallVector<MacroCallState> MacroCallStructure;
-
- // Level the generated UnwrappedLine will be at.
- const unsigned Level;
+ SmallVector<MacroCallState> MacroCallStructure;
// Maps from identifier of the macro call to an unwrapped line containing
// all tokens of the macro call.
diff --git a/contrib/llvm-project/clang/lib/Format/QualifierAlignmentFixer.cpp b/contrib/llvm-project/clang/lib/Format/QualifierAlignmentFixer.cpp
index 84941746f0df..593f8efff25a 100644
--- a/contrib/llvm-project/clang/lib/Format/QualifierAlignmentFixer.cpp
+++ b/contrib/llvm-project/clang/lib/Format/QualifierAlignmentFixer.cpp
@@ -272,7 +272,7 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight(
// The case `long const long int volatile` -> `long long int const volatile`
// The case `long long volatile int const` -> `long long int const volatile`
// The case `const long long volatile int` -> `long long int const volatile`
- if (TypeToken->isSimpleTypeSpecifier()) {
+ if (TypeToken->isTypeName(LangOpts)) {
// The case `const decltype(foo)` -> `const decltype(foo)`
// The case `const typeof(foo)` -> `const typeof(foo)`
// The case `const _Atomic(foo)` -> `const _Atomic(foo)`
@@ -280,8 +280,10 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight(
return Tok;
const FormatToken *LastSimpleTypeSpecifier = TypeToken;
- while (isQualifierOrType(LastSimpleTypeSpecifier->getNextNonComment()))
+ while (isQualifierOrType(LastSimpleTypeSpecifier->getNextNonComment(),
+ LangOpts)) {
LastSimpleTypeSpecifier = LastSimpleTypeSpecifier->getNextNonComment();
+ }
rotateTokens(SourceMgr, Fixes, Tok, LastSimpleTypeSpecifier,
/*Left=*/false);
@@ -291,7 +293,7 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight(
// The case `unsigned short const` -> `unsigned short const`
// The case:
// `unsigned short volatile const` -> `unsigned short const volatile`
- if (PreviousCheck && PreviousCheck->isSimpleTypeSpecifier()) {
+ if (PreviousCheck && PreviousCheck->isTypeName(LangOpts)) {
if (LastQual != Tok)
rotateTokens(SourceMgr, Fixes, Tok, LastQual, /*Left=*/false);
return Tok;
@@ -408,11 +410,11 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeLeft(
// The case `volatile long long const int` -> `const volatile long long int`
// The case `const long long volatile int` -> `const volatile long long int`
// The case `long volatile long int const` -> `const volatile long long int`
- if (TypeToken->isSimpleTypeSpecifier()) {
+ if (TypeToken->isTypeName(LangOpts)) {
const FormatToken *LastSimpleTypeSpecifier = TypeToken;
while (isConfiguredQualifierOrType(
LastSimpleTypeSpecifier->getPreviousNonComment(),
- ConfiguredQualifierTokens)) {
+ ConfiguredQualifierTokens, LangOpts)) {
LastSimpleTypeSpecifier =
LastSimpleTypeSpecifier->getPreviousNonComment();
}
@@ -561,6 +563,8 @@ void LeftRightQualifierAlignmentFixer::fixQualifierAlignment(
for (const auto *Tok = First; Tok && Tok != Last && Tok->Next;
Tok = Tok->Next) {
+ if (Tok->MustBreakBefore)
+ break;
if (Tok->is(tok::comment))
continue;
if (RightAlign) {
@@ -608,22 +612,21 @@ void prepareLeftRightOrderingForQualifierAlignmentFixer(
}
}
-bool LeftRightQualifierAlignmentFixer::isQualifierOrType(
- const FormatToken *const Tok) {
- return Tok && (Tok->isSimpleTypeSpecifier() || Tok->is(tok::kw_auto) ||
+bool isQualifierOrType(const FormatToken *Tok, const LangOptions &LangOpts) {
+ return Tok && (Tok->isTypeName(LangOpts) || Tok->is(tok::kw_auto) ||
isQualifier(Tok));
}
-bool LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType(
- const FormatToken *const Tok,
- const std::vector<tok::TokenKind> &Qualifiers) {
- return Tok && (Tok->isSimpleTypeSpecifier() || Tok->is(tok::kw_auto) ||
+bool isConfiguredQualifierOrType(const FormatToken *Tok,
+ const std::vector<tok::TokenKind> &Qualifiers,
+ const LangOptions &LangOpts) {
+ return Tok && (Tok->isTypeName(LangOpts) || Tok->is(tok::kw_auto) ||
isConfiguredQualifier(Tok, Qualifiers));
}
// If a token is an identifier and it's upper case, it could
// be a macro and hence we need to be able to ignore it.
-bool LeftRightQualifierAlignmentFixer::isPossibleMacro(const FormatToken *Tok) {
+bool isPossibleMacro(const FormatToken *Tok) {
if (!Tok)
return false;
if (Tok->isNot(tok::identifier))
diff --git a/contrib/llvm-project/clang/lib/Format/QualifierAlignmentFixer.h b/contrib/llvm-project/clang/lib/Format/QualifierAlignmentFixer.h
index e922d8005595..a0a0d597ebf3 100644
--- a/contrib/llvm-project/clang/lib/Format/QualifierAlignmentFixer.h
+++ b/contrib/llvm-project/clang/lib/Format/QualifierAlignmentFixer.h
@@ -32,6 +32,15 @@ void prepareLeftRightOrderingForQualifierAlignmentFixer(
std::vector<std::string> &RightOrder,
std::vector<tok::TokenKind> &Qualifiers);
+// Is the Token a simple or qualifier type
+bool isQualifierOrType(const FormatToken *Tok, const LangOptions &LangOpts);
+bool isConfiguredQualifierOrType(const FormatToken *Tok,
+ const std::vector<tok::TokenKind> &Qualifiers,
+ const LangOptions &LangOpts);
+
+// Is the Token likely a Macro
+bool isPossibleMacro(const FormatToken *Tok);
+
class LeftRightQualifierAlignmentFixer : public TokenAnalyzer {
std::string Qualifier;
bool RightAlign;
@@ -69,15 +78,6 @@ public:
const FormatToken *Tok,
const std::string &Qualifier,
tok::TokenKind QualifierType);
-
- // Is the Token a simple or qualifier type
- static bool isQualifierOrType(const FormatToken *Tok);
- static bool
- isConfiguredQualifierOrType(const FormatToken *Tok,
- const std::vector<tok::TokenKind> &Qualifiers);
-
- // Is the Token likely a Macro
- static bool isPossibleMacro(const FormatToken *Tok);
};
} // end namespace format
diff --git a/contrib/llvm-project/clang/lib/Format/SortJavaScriptImports.cpp b/contrib/llvm-project/clang/lib/Format/SortJavaScriptImports.cpp
index 1a6a1b19e702..1acce26ff279 100644
--- a/contrib/llvm-project/clang/lib/Format/SortJavaScriptImports.cpp
+++ b/contrib/llvm-project/clang/lib/Format/SortJavaScriptImports.cpp
@@ -34,8 +34,6 @@ namespace format {
class FormatTokenLexer;
-using clang::format::FormatStyle;
-
// An imported symbol in a JavaScript ES6 import/export, possibly aliased.
struct JsImportedSymbol {
StringRef Symbol;
@@ -178,7 +176,7 @@ public:
}
}
}
- llvm::StringRef PreviousText = getSourceText(InsertionPoint);
+ StringRef PreviousText = getSourceText(InsertionPoint);
if (ReferencesText == PreviousText)
return {Result, 0};
@@ -209,7 +207,7 @@ public:
// FIXME: better error handling. For now, just print error message and skip
// the replacement for the release version.
if (Err) {
- llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+ llvm::errs() << toString(std::move(Err)) << "\n";
assert(false);
}
@@ -276,7 +274,7 @@ private:
SortChunk.push_back(*Start);
++Start;
}
- llvm::stable_sort(SortChunk);
+ stable_sort(SortChunk);
mergeModuleReferences(SortChunk);
ReferencesSorted.insert(ReferencesSorted.end(), SortChunk.begin(),
SortChunk.end());
@@ -334,10 +332,10 @@ private:
// Sort the individual symbols within the import.
// E.g. `import {b, a} from 'x';` -> `import {a, b} from 'x';`
SmallVector<JsImportedSymbol, 1> Symbols = Reference.Symbols;
- llvm::stable_sort(
- Symbols, [&](const JsImportedSymbol &LHS, const JsImportedSymbol &RHS) {
- return LHS.Symbol.compare_insensitive(RHS.Symbol) < 0;
- });
+ stable_sort(Symbols,
+ [&](const JsImportedSymbol &LHS, const JsImportedSymbol &RHS) {
+ return LHS.Symbol.compare_insensitive(RHS.Symbol) < 0;
+ });
if (!Reference.SymbolsMerged && Symbols == Reference.Symbols) {
// Symbols didn't change, just emit the entire module reference.
StringRef ReferenceStmt = getSourceText(Reference.Range);
@@ -349,7 +347,7 @@ private:
// ... then the references in order ...
if (!Symbols.empty()) {
Buffer += getSourceText(Symbols.front().Range);
- for (const JsImportedSymbol &Symbol : llvm::drop_begin(Symbols)) {
+ for (const JsImportedSymbol &Symbol : drop_begin(Symbols)) {
Buffer += ",";
Buffer += getSourceText(Symbol.Range);
}
diff --git a/contrib/llvm-project/clang/lib/Format/SortJavaScriptImports.h b/contrib/llvm-project/clang/lib/Format/SortJavaScriptImports.h
index 7336db9537b0..b55b149aab4c 100644
--- a/contrib/llvm-project/clang/lib/Format/SortJavaScriptImports.h
+++ b/contrib/llvm-project/clang/lib/Format/SortJavaScriptImports.h
@@ -14,10 +14,7 @@
#ifndef LLVM_CLANG_LIB_FORMAT_SORTJAVASCRIPTIMPORTS_H
#define LLVM_CLANG_LIB_FORMAT_SORTJAVASCRIPTIMPORTS_H
-#include "clang/Basic/LLVM.h"
#include "clang/Format/Format.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
namespace clang {
namespace format {
diff --git a/contrib/llvm-project/clang/lib/Format/TokenAnalyzer.cpp b/contrib/llvm-project/clang/lib/Format/TokenAnalyzer.cpp
index bd648c430f9b..804a2b0f5e8c 100644
--- a/contrib/llvm-project/clang/lib/Format/TokenAnalyzer.cpp
+++ b/contrib/llvm-project/clang/lib/Format/TokenAnalyzer.cpp
@@ -84,7 +84,7 @@ Environment::Environment(StringRef Code, StringRef FileName,
NextStartColumn(NextStartColumn), LastStartColumn(LastStartColumn) {}
TokenAnalyzer::TokenAnalyzer(const Environment &Env, const FormatStyle &Style)
- : Style(Style), Env(Env),
+ : Style(Style), LangOpts(getFormattingLangOpts(Style)), Env(Env),
AffectedRangeMgr(Env.getSourceManager(), Env.getCharRanges()),
UnwrappedLines(1),
Encoding(encoding::detectEncoding(
@@ -101,7 +101,7 @@ std::pair<tooling::Replacements, unsigned>
TokenAnalyzer::process(bool SkipAnnotation) {
tooling::Replacements Result;
llvm::SpecificBumpPtrAllocator<FormatToken> Allocator;
- IdentifierTable IdentTable(getFormattingLangOpts(Style));
+ IdentifierTable IdentTable(LangOpts);
FormatTokenLexer Lex(Env.getSourceManager(), Env.getFileID(),
Env.getFirstStartColumn(), Style, Encoding, Allocator,
IdentTable);
diff --git a/contrib/llvm-project/clang/lib/Format/TokenAnalyzer.h b/contrib/llvm-project/clang/lib/Format/TokenAnalyzer.h
index 4086dab1c94c..ef559099d325 100644
--- a/contrib/llvm-project/clang/lib/Format/TokenAnalyzer.h
+++ b/contrib/llvm-project/clang/lib/Format/TokenAnalyzer.h
@@ -17,19 +17,8 @@
#define LLVM_CLANG_LIB_FORMAT_TOKENANALYZER_H
#include "AffectedRangeManager.h"
-#include "Encoding.h"
-#include "FormatToken.h"
#include "FormatTokenLexer.h"
#include "TokenAnnotator.h"
-#include "UnwrappedLineParser.h"
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/DiagnosticOptions.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Format/Format.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/Debug.h"
-#include <memory>
namespace clang {
namespace format {
@@ -103,6 +92,7 @@ protected:
void finishRun() override;
FormatStyle Style;
+ LangOptions LangOpts;
// Stores Style, FileID and SourceManager etc.
const Environment &Env;
// AffectedRangeMgr stores ranges to be fixed.
diff --git a/contrib/llvm-project/clang/lib/Format/TokenAnnotator.cpp b/contrib/llvm-project/clang/lib/Format/TokenAnnotator.cpp
index c1f166248192..21924a8fe17d 100644
--- a/contrib/llvm-project/clang/lib/Format/TokenAnnotator.cpp
+++ b/contrib/llvm-project/clang/lib/Format/TokenAnnotator.cpp
@@ -126,7 +126,9 @@ public:
const AdditionalKeywords &Keywords,
SmallVector<ScopeType> &Scopes)
: Style(Style), Line(Line), CurrentToken(Line.First), AutoFound(false),
- Keywords(Keywords), Scopes(Scopes) {
+ IsCpp(Style.isCpp()), LangOpts(getFormattingLangOpts(Style)),
+ Keywords(Keywords), Scopes(Scopes), TemplateDeclarationDepth(0) {
+ assert(IsCpp == LangOpts.CXXOperatorNames);
Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/false));
resetTokenMetadata();
}
@@ -174,10 +176,6 @@ private:
Left->ParentBracket = Contexts.back().ContextKind;
ScopedContextCreator ContextCreator(*this, tok::less, 12);
- // If this angle is in the context of an expression, we need to be more
- // hesitant to detect it as opening template parameters.
- bool InExprContext = Contexts.back().IsExpression;
-
Contexts.back().IsExpression = false;
// If there's a template keyword before the opening angle bracket, this is a
// template parameter, not an argument.
@@ -229,11 +227,8 @@ private:
next();
continue;
}
- if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace) ||
- (CurrentToken->isOneOf(tok::colon, tok::question) && InExprContext &&
- !Style.isCSharp() && !Style.isProto())) {
+ if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace))
return false;
- }
// If a && or || is found and interpreted as a binary operator, this set
// of angles is likely part of something like "a < b && c > d". If the
// angles are inside an expression, the ||/&& might also be a binary
@@ -256,6 +251,18 @@ private:
}
}
}
+ if (Style.isTableGen()) {
+ if (CurrentToken->isOneOf(tok::comma, tok::equal)) {
+ // They appear as separators. Unless they are not in class definition.
+ next();
+ continue;
+ }
+ // In angle, there must be Value like tokens. Types are also able to be
+ // parsed in the same way with Values.
+ if (!parseTableGenValue())
+ return false;
+ continue;
+ }
if (!consumeToken())
return false;
}
@@ -365,10 +372,6 @@ private:
OpeningParen.Previous->is(tok::kw__Generic)) {
Contexts.back().ContextType = Context::C11GenericSelection;
Contexts.back().IsExpression = true;
- } else if (Line.InPPDirective &&
- (!OpeningParen.Previous ||
- OpeningParen.Previous->isNot(tok::identifier))) {
- Contexts.back().IsExpression = true;
} else if (Contexts[Contexts.size() - 2].CaretFound) {
// This is the parameter list of an ObjC block.
Contexts.back().IsExpression = false;
@@ -381,13 +384,48 @@ private:
OpeningParen.Previous->MatchingParen->isOneOf(
TT_ObjCBlockLParen, TT_FunctionTypeLParen)) {
Contexts.back().IsExpression = false;
- } else if (!Line.MustBeDeclaration && !Line.InPPDirective) {
+ } else if (Line.InPPDirective) {
+ auto IsExpr = [&OpeningParen] {
+ const auto *Tok = OpeningParen.Previous;
+ if (!Tok || Tok->isNot(tok::identifier))
+ return true;
+ Tok = Tok->Previous;
+ while (Tok && Tok->endsSequence(tok::coloncolon, tok::identifier)) {
+ assert(Tok->Previous);
+ Tok = Tok->Previous->Previous;
+ }
+ return !Tok || !Tok->Tok.getIdentifierInfo();
+ };
+ Contexts.back().IsExpression = IsExpr();
+ } else if (!Line.MustBeDeclaration) {
bool IsForOrCatch =
OpeningParen.Previous &&
OpeningParen.Previous->isOneOf(tok::kw_for, tok::kw_catch);
Contexts.back().IsExpression = !IsForOrCatch;
}
+ if (Style.isTableGen()) {
+ if (FormatToken *Prev = OpeningParen.Previous) {
+ if (Prev->is(TT_TableGenCondOperator)) {
+ Contexts.back().IsTableGenCondOpe = true;
+ Contexts.back().IsExpression = true;
+ } else if (Contexts.size() > 1 &&
+ Contexts[Contexts.size() - 2].IsTableGenBangOpe) {
+ // Hack to handle bang operators. The parent context's flag
+ // was set by parseTableGenSimpleValue().
+ // We have to specify the context outside because the prev of "(" may
+ // be ">", not the bang operator in this case.
+ Contexts.back().IsTableGenBangOpe = true;
+ Contexts.back().IsExpression = true;
+ } else {
+ // Otherwise, this paren seems DAGArg.
+ if (!parseTableGenDAGArg())
+ return false;
+ return parseTableGenDAGArgAndList(&OpeningParen);
+ }
+ }
+ }
+
// Infer the role of the l_paren based on the previous token if we haven't
// detected one yet.
if (PrevNonComment && OpeningParen.is(TT_Unknown)) {
@@ -528,7 +566,7 @@ private:
(CurrentToken->is(tok::l_paren) && CurrentToken->Next &&
CurrentToken->Next->isOneOf(tok::star, tok::amp, tok::caret));
if ((CurrentToken->Previous->isOneOf(tok::kw_const, tok::kw_auto) ||
- CurrentToken->Previous->isSimpleTypeSpecifier()) &&
+ CurrentToken->Previous->isTypeName(LangOpts)) &&
!(CurrentToken->is(tok::l_brace) ||
(CurrentToken->is(tok::l_paren) && !ProbablyFunctionTypeLParen))) {
Contexts.back().IsExpression = false;
@@ -549,6 +587,22 @@ private:
if (CurrentToken->is(tok::comma))
Contexts.back().CanBeExpression = true;
+ if (Style.isTableGen()) {
+ if (CurrentToken->is(tok::comma)) {
+ if (Contexts.back().IsTableGenCondOpe)
+ CurrentToken->setType(TT_TableGenCondOperatorComma);
+ next();
+ } else if (CurrentToken->is(tok::colon)) {
+ if (Contexts.back().IsTableGenCondOpe)
+ CurrentToken->setType(TT_TableGenCondOperatorColon);
+ next();
+ }
+ // In TableGen there must be Values in parens.
+ if (!parseTableGenValue())
+ return false;
+ continue;
+ }
+
FormatToken *Tok = CurrentToken;
if (!consumeToken())
return false;
@@ -595,8 +649,8 @@ private:
return true;
// Limit this to being an access modifier that follows.
- if (AttrTok->isOneOf(tok::kw_public, tok::kw_private, tok::kw_protected,
- tok::comment, tok::kw_class, tok::kw_static,
+ if (AttrTok->isAccessSpecifierKeyword() ||
+ AttrTok->isOneOf(tok::comment, tok::kw_class, tok::kw_static,
tok::l_square, Keywords.kw_internal)) {
return true;
}
@@ -626,13 +680,13 @@ private:
// In C++, this can happen either in array of templates (foo<int>[10])
// or when array is a nested template type (unique_ptr<type1<type2>[]>).
bool CppArrayTemplates =
- Style.isCpp() && Parent && Parent->is(TT_TemplateCloser) &&
+ IsCpp && Parent && Parent->is(TT_TemplateCloser) &&
(Contexts.back().CanBeExpression || Contexts.back().IsExpression ||
Contexts.back().ContextType == Context::TemplateArgument);
const bool IsInnerSquare = Contexts.back().InCpp11AttributeSpecifier;
const bool IsCpp11AttributeSpecifier =
- isCppAttribute(Style.isCpp(), *Left) || IsInnerSquare;
+ isCppAttribute(IsCpp, *Left) || IsInnerSquare;
// Treat C# Attributes [STAThread] much like C++ attributes [[...]].
bool IsCSharpAttributeSpecifier =
@@ -640,12 +694,11 @@ private:
Contexts.back().InCSharpAttributeSpecifier;
bool InsideInlineASM = Line.startsWith(tok::kw_asm);
- bool IsCppStructuredBinding = Left->isCppStructuredBinding(Style);
+ bool IsCppStructuredBinding = Left->isCppStructuredBinding(IsCpp);
bool StartsObjCMethodExpr =
!IsCppStructuredBinding && !InsideInlineASM && !CppArrayTemplates &&
- Style.isCpp() && !IsCpp11AttributeSpecifier &&
- !IsCSharpAttributeSpecifier && Contexts.back().CanBeExpression &&
- Left->isNot(TT_LambdaLSquare) &&
+ IsCpp && !IsCpp11AttributeSpecifier && !IsCSharpAttributeSpecifier &&
+ Contexts.back().CanBeExpression && Left->isNot(TT_LambdaLSquare) &&
!CurrentToken->isOneOf(tok::l_brace, tok::r_square) &&
(!Parent ||
Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren,
@@ -673,7 +726,7 @@ private:
Contexts.back().ContextKind == tok::l_brace &&
Parent->isOneOf(tok::l_brace, tok::comma)) {
Left->setType(TT_JsComputedPropertyName);
- } else if (Style.isCpp() && Contexts.back().ContextKind == tok::l_brace &&
+ } else if (IsCpp && Contexts.back().ContextKind == tok::l_brace &&
Parent && Parent->isOneOf(tok::l_brace, tok::comma)) {
Left->setType(TT_DesignatedInitializerLSquare);
} else if (IsCSharpAttributeSpecifier) {
@@ -776,8 +829,7 @@ private:
Parent->overwriteFixedType(TT_BinaryOperator);
}
// An arrow after an ObjC method expression is not a lambda arrow.
- if (CurrentToken->getType() == TT_ObjCMethodExpr &&
- CurrentToken->Next &&
+ if (CurrentToken->is(TT_ObjCMethodExpr) && CurrentToken->Next &&
CurrentToken->Next->is(TT_TrailingReturnArrow)) {
CurrentToken->Next->overwriteFixedType(TT_Unknown);
}
@@ -803,6 +855,8 @@ private:
if (Left->BlockParameterCount > 1)
Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = 0;
}
+ if (Style.isTableGen() && Left->is(TT_TableGenListOpener))
+ CurrentToken->setType(TT_TableGenListCloser);
next();
return true;
}
@@ -833,6 +887,19 @@ private:
Left->setType(TT_ArrayInitializerLSquare);
}
FormatToken *Tok = CurrentToken;
+ if (Style.isTableGen()) {
+ if (CurrentToken->isOneOf(tok::comma, tok::minus, tok::ellipsis)) {
+ // '-' and '...' appears as a separator in slice.
+ next();
+ } else {
+ // In TableGen there must be a list of Values in square brackets.
+ // It must be ValueList or SliceElements.
+ if (!parseTableGenValue())
+ return false;
+ }
+ updateParameterCount(Left, Tok);
+ continue;
+ }
if (!consumeToken())
return false;
updateParameterCount(Left, Tok);
@@ -840,6 +907,242 @@ private:
return false;
}
+ void skipToNextNonComment() {
+ next();
+ while (CurrentToken && CurrentToken->is(tok::comment))
+ next();
+ }
+
+ // Simplified parser for TableGen Value. Returns true on success.
+ // It consists of SimpleValues, SimpleValues with Suffixes, and Value followed
+ // by '#', paste operator.
+ // There also exists the case the Value is parsed as NameValue.
+ // In this case, the Value ends if '{' is found.
+ bool parseTableGenValue(bool ParseNameMode = false) {
+ if (!CurrentToken)
+ return false;
+ while (CurrentToken->is(tok::comment))
+ next();
+ if (!parseTableGenSimpleValue())
+ return false;
+ if (!CurrentToken)
+ return true;
+ // Value "#" [Value]
+ if (CurrentToken->is(tok::hash)) {
+ if (CurrentToken->Next &&
+ CurrentToken->Next->isOneOf(tok::colon, tok::semi, tok::l_brace)) {
+ // Trailing paste operator.
+ // These are only the allowed cases in TGParser::ParseValue().
+ CurrentToken->setType(TT_TableGenTrailingPasteOperator);
+ next();
+ return true;
+ }
+ FormatToken *HashTok = CurrentToken;
+ skipToNextNonComment();
+ HashTok->setType(TT_Unknown);
+ if (!parseTableGenValue(ParseNameMode))
+ return false;
+ }
+ // In name mode, '{' is regarded as the end of the value.
+ // See TGParser::ParseValue in TGParser.cpp
+ if (ParseNameMode && CurrentToken->is(tok::l_brace))
+ return true;
+ // These tokens indicates this is a value with suffixes.
+ if (CurrentToken->isOneOf(tok::l_brace, tok::l_square, tok::period)) {
+ CurrentToken->setType(TT_TableGenValueSuffix);
+ FormatToken *Suffix = CurrentToken;
+ skipToNextNonComment();
+ if (Suffix->is(tok::l_square))
+ return parseSquare();
+ if (Suffix->is(tok::l_brace)) {
+ Scopes.push_back(getScopeType(*Suffix));
+ return parseBrace();
+ }
+ }
+ return true;
+ }
+
+ // TokVarName ::= "$" ualpha (ualpha | "0"..."9")*
+ // Appears as a part of DagArg.
+ // This does not change the current token on fail.
+ bool tryToParseTableGenTokVar() {
+ if (!CurrentToken)
+ return false;
+ if (CurrentToken->is(tok::identifier) &&
+ CurrentToken->TokenText.front() == '$') {
+ skipToNextNonComment();
+ return true;
+ }
+ return false;
+ }
+
+ // DagArg ::= Value [":" TokVarName] | TokVarName
+ // Appears as a part of SimpleValue6.
+ bool parseTableGenDAGArg(bool AlignColon = false) {
+ if (tryToParseTableGenTokVar())
+ return true;
+ if (parseTableGenValue()) {
+ if (CurrentToken && CurrentToken->is(tok::colon)) {
+ if (AlignColon)
+ CurrentToken->setType(TT_TableGenDAGArgListColonToAlign);
+ else
+ CurrentToken->setType(TT_TableGenDAGArgListColon);
+ skipToNextNonComment();
+ return tryToParseTableGenTokVar();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ // Judge if the token is a operator ID to insert line break in DAGArg.
+ // That is, TableGenBreakingDAGArgOperators is empty (by the definition of the
+ // option) or the token is in the list.
+ bool isTableGenDAGArgBreakingOperator(const FormatToken &Tok) {
+ auto &Opes = Style.TableGenBreakingDAGArgOperators;
+ // If the list is empty, all operators are breaking operators.
+ if (Opes.empty())
+ return true;
+ // Otherwise, the operator is limited to normal identifiers.
+ if (Tok.isNot(tok::identifier) ||
+ Tok.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator)) {
+ return false;
+ }
+ // The case next is colon, it is not a operator of identifier.
+ if (!Tok.Next || Tok.Next->is(tok::colon))
+ return false;
+ return std::find(Opes.begin(), Opes.end(), Tok.TokenText.str()) !=
+ Opes.end();
+ }
+
+ // SimpleValue6 ::= "(" DagArg [DagArgList] ")"
+ // This parses SimpleValue 6's inside part of "(" ")"
+ bool parseTableGenDAGArgAndList(FormatToken *Opener) {
+ FormatToken *FirstTok = CurrentToken;
+ if (!parseTableGenDAGArg())
+ return false;
+ bool BreakInside = false;
+ if (Style.TableGenBreakInsideDAGArg != FormatStyle::DAS_DontBreak) {
+ // Specialized detection for DAGArgOperator, that determines the way of
+ // line break for this DAGArg elements.
+ if (isTableGenDAGArgBreakingOperator(*FirstTok)) {
+ // Special case for identifier DAGArg operator.
+ BreakInside = true;
+ Opener->setType(TT_TableGenDAGArgOpenerToBreak);
+ if (FirstTok->isOneOf(TT_TableGenBangOperator,
+ TT_TableGenCondOperator)) {
+ // Special case for bang/cond operators. Set the whole operator as
+ // the DAGArg operator. Always break after it.
+ CurrentToken->Previous->setType(TT_TableGenDAGArgOperatorToBreak);
+ } else if (FirstTok->is(tok::identifier)) {
+ if (Style.TableGenBreakInsideDAGArg == FormatStyle::DAS_BreakAll)
+ FirstTok->setType(TT_TableGenDAGArgOperatorToBreak);
+ else
+ FirstTok->setType(TT_TableGenDAGArgOperatorID);
+ }
+ }
+ }
+ // Parse the [DagArgList] part
+ bool FirstDAGArgListElm = true;
+ while (CurrentToken) {
+ if (!FirstDAGArgListElm && CurrentToken->is(tok::comma)) {
+ CurrentToken->setType(BreakInside ? TT_TableGenDAGArgListCommaToBreak
+ : TT_TableGenDAGArgListComma);
+ skipToNextNonComment();
+ }
+ if (CurrentToken && CurrentToken->is(tok::r_paren)) {
+ CurrentToken->setType(TT_TableGenDAGArgCloser);
+ Opener->MatchingParen = CurrentToken;
+ CurrentToken->MatchingParen = Opener;
+ skipToNextNonComment();
+ return true;
+ }
+ if (!parseTableGenDAGArg(
+ BreakInside &&
+ Style.AlignConsecutiveTableGenBreakingDAGArgColons.Enabled)) {
+ return false;
+ }
+ FirstDAGArgListElm = false;
+ }
+ return false;
+ }
+
+ bool parseTableGenSimpleValue() {
+ assert(Style.isTableGen());
+ if (!CurrentToken)
+ return false;
+ FormatToken *Tok = CurrentToken;
+ skipToNextNonComment();
+ // SimpleValue 1, 2, 3: Literals
+ if (Tok->isOneOf(tok::numeric_constant, tok::string_literal,
+ TT_TableGenMultiLineString, tok::kw_true, tok::kw_false,
+ tok::question, tok::kw_int)) {
+ return true;
+ }
+ // SimpleValue 4: ValueList, Type
+ if (Tok->is(tok::l_brace)) {
+ Scopes.push_back(getScopeType(*Tok));
+ return parseBrace();
+ }
+ // SimpleValue 5: List initializer
+ if (Tok->is(tok::l_square)) {
+ Tok->setType(TT_TableGenListOpener);
+ if (!parseSquare())
+ return false;
+ if (Tok->is(tok::less)) {
+ CurrentToken->setType(TT_TemplateOpener);
+ return parseAngle();
+ }
+ return true;
+ }
+ // SimpleValue 6: DAGArg [DAGArgList]
+ // SimpleValue6 ::= "(" DagArg [DagArgList] ")"
+ if (Tok->is(tok::l_paren)) {
+ Tok->setType(TT_TableGenDAGArgOpener);
+ return parseTableGenDAGArgAndList(Tok);
+ }
+ // SimpleValue 9: Bang operator
+ if (Tok->is(TT_TableGenBangOperator)) {
+ if (CurrentToken && CurrentToken->is(tok::less)) {
+ CurrentToken->setType(TT_TemplateOpener);
+ skipToNextNonComment();
+ if (!parseAngle())
+ return false;
+ }
+ if (!CurrentToken || CurrentToken->isNot(tok::l_paren))
+ return false;
+ skipToNextNonComment();
+ // FIXME: Hack using inheritance to child context
+ Contexts.back().IsTableGenBangOpe = true;
+ bool Result = parseParens();
+ Contexts.back().IsTableGenBangOpe = false;
+ return Result;
+ }
+ // SimpleValue 9: Cond operator
+ if (Tok->is(TT_TableGenCondOperator)) {
+ Tok = CurrentToken;
+ skipToNextNonComment();
+ if (!Tok || Tok->isNot(tok::l_paren))
+ return false;
+ bool Result = parseParens();
+ return Result;
+ }
+ // We have to check identifier at the last because the kind of bang/cond
+ // operators are also identifier.
+ // SimpleValue 7: Identifiers
+ if (Tok->is(tok::identifier)) {
+ // SimpleValue 8: Anonymous record
+ if (CurrentToken && CurrentToken->is(tok::less)) {
+ CurrentToken->setType(TT_TemplateOpener);
+ skipToNextNonComment();
+ return parseAngle();
+ }
+ return true;
+ }
+
+ return false;
+ }
+
bool couldBeInStructArrayInitializer() const {
if (Contexts.size() < 2)
return false;
@@ -880,6 +1183,8 @@ private:
OpeningBrace.getPreviousNonComment()->isNot(Keywords.kw_apostrophe))) {
Contexts.back().VerilogMayBeConcatenation = true;
}
+ if (Style.isTableGen())
+ Contexts.back().ColonIsDictLiteral = false;
unsigned CommaCount = 0;
while (CurrentToken) {
@@ -906,8 +1211,8 @@ private:
FormatToken *Previous = CurrentToken->getPreviousNonComment();
if (Previous->is(TT_JsTypeOptionalQuestion))
Previous = Previous->getPreviousNonComment();
- if ((CurrentToken->is(tok::colon) &&
- (!Contexts.back().ColonIsDictLiteral || !Style.isCpp())) ||
+ if ((CurrentToken->is(tok::colon) && !Style.isTableGen() &&
+ (!Contexts.back().ColonIsDictLiteral || !IsCpp)) ||
Style.isProto()) {
OpeningBrace.setType(TT_DictLiteral);
if (Previous->Tok.getIdentifierInfo() ||
@@ -915,10 +1220,12 @@ private:
Previous->setType(TT_SelectorName);
}
}
- if (CurrentToken->is(tok::colon) && OpeningBrace.is(TT_Unknown))
+ if (CurrentToken->is(tok::colon) && OpeningBrace.is(TT_Unknown) &&
+ !Style.isTableGen()) {
OpeningBrace.setType(TT_DictLiteral);
- else if (Style.isJavaScript())
+ } else if (Style.isJavaScript()) {
OpeningBrace.overwriteFixedType(TT_DictLiteral);
+ }
}
if (CurrentToken->is(tok::comma)) {
if (Style.isJavaScript())
@@ -961,20 +1268,26 @@ private:
}
bool parseTemplateDeclaration() {
- if (CurrentToken && CurrentToken->is(tok::less)) {
- CurrentToken->setType(TT_TemplateOpener);
- next();
- if (!parseAngle())
- return false;
- if (CurrentToken)
- CurrentToken->Previous->ClosesTemplateDeclaration = true;
- return true;
- }
- return false;
+ if (!CurrentToken || CurrentToken->isNot(tok::less))
+ return false;
+
+ CurrentToken->setType(TT_TemplateOpener);
+ next();
+
+ TemplateDeclarationDepth++;
+ const bool WellFormed = parseAngle();
+ TemplateDeclarationDepth--;
+ if (!WellFormed)
+ return false;
+
+ if (CurrentToken && TemplateDeclarationDepth == 0)
+ CurrentToken->Previous->ClosesTemplateDeclaration = true;
+
+ return true;
}
bool consumeToken() {
- if (Style.isCpp()) {
+ if (IsCpp) {
const auto *Prev = CurrentToken->getPreviousNonComment();
if (Prev && Prev->is(tok::r_square) && Prev->is(TT_AttributeSquare) &&
CurrentToken->isOneOf(tok::kw_if, tok::kw_switch, tok::kw_case,
@@ -989,6 +1302,9 @@ private:
// operators.
if (Tok->is(TT_VerilogTableItem))
return true;
+ // Multi-line string itself is a single annotated token.
+ if (Tok->is(TT_TableGenMultiLineString))
+ return true;
switch (Tok->Tok.getKind()) {
case tok::plus:
case tok::minus:
@@ -1050,6 +1366,8 @@ private:
Line.First->startsSequence(tok::kw_export, Keywords.kw_module) ||
Line.First->startsSequence(tok::kw_export, Keywords.kw_import)) {
Tok->setType(TT_ModulePartitionColon);
+ } else if (Line.First->is(tok::kw_asm)) {
+ Tok->setType(TT_InlineASMColon);
} else if (Contexts.back().ColonIsDictLiteral || Style.isProto()) {
Tok->setType(TT_DictLiteral);
if (Style.Language == FormatStyle::LK_TextProto) {
@@ -1109,6 +1427,8 @@ private:
Tok->setType(TT_CtorInitializerColon);
} else {
Tok->setType(TT_InheritanceColon);
+ if (Prev->isAccessSpecifierKeyword())
+ Line.Type = LT_AccessModifier;
}
} else if (canBeObjCSelectorComponent(*Tok->Previous) && Tok->Next &&
(Tok->Next->isOneOf(tok::r_paren, tok::comma) ||
@@ -1117,9 +1437,6 @@ 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 &&
- !Line.InPragmaDirective) {
- Tok->setType(TT_InlineASMColon);
}
break;
case tok::pipe:
@@ -1130,6 +1447,14 @@ private:
Tok->setType(TT_JsTypeOperator);
break;
case tok::kw_if:
+ if (Style.isTableGen()) {
+ // In TableGen it has the form 'if' <value> 'then'.
+ if (!parseTableGenValue())
+ return false;
+ if (CurrentToken && CurrentToken->is(Keywords.kw_then))
+ next(); // skip then
+ break;
+ }
if (CurrentToken &&
CurrentToken->isOneOf(tok::kw_constexpr, tok::identifier)) {
next();
@@ -1153,7 +1478,7 @@ private:
if (CurrentToken && CurrentToken->is(Keywords.kw_await))
next();
}
- if (Style.isCpp() && CurrentToken && CurrentToken->is(tok::kw_co_await))
+ if (IsCpp && CurrentToken && CurrentToken->is(tok::kw_co_await))
next();
Contexts.back().ColonIsForRangeExpr = true;
if (!CurrentToken || CurrentToken->isNot(tok::l_paren))
@@ -1225,23 +1550,27 @@ private:
return false;
if (Line.MustBeDeclaration && Contexts.size() == 1 &&
!Contexts.back().IsExpression && !Line.startsWith(TT_ObjCProperty) &&
+ !Line.startsWith(tok::l_paren) &&
!Tok->isOneOf(TT_TypeDeclarationParen, TT_RequiresExpressionLParen)) {
if (const auto *Previous = Tok->Previous;
!Previous ||
(!Previous->isAttribute() &&
!Previous->isOneOf(TT_RequiresClause, TT_LeadingJavaAnnotation))) {
Line.MightBeFunctionDecl = true;
+ Tok->MightBeFunctionDeclParen = true;
}
}
break;
case tok::l_square:
+ if (Style.isTableGen())
+ Tok->setType(TT_TableGenListOpener);
if (!parseSquare())
return false;
break;
case tok::l_brace:
if (Style.Language == FormatStyle::LK_TextProto) {
FormatToken *Previous = Tok->getPreviousNonComment();
- if (Previous && Previous->getType() != TT_DictLiteral)
+ if (Previous && Previous->isNot(TT_DictLiteral))
Previous->setType(TT_SelectorName);
}
Scopes.push_back(getScopeType(*Tok));
@@ -1261,9 +1590,11 @@ private:
Tok->Previous->isOneOf(TT_SelectorName, TT_DictLiteral))) {
Tok->setType(TT_DictLiteral);
FormatToken *Previous = Tok->getPreviousNonComment();
- if (Previous && Previous->getType() != TT_DictLiteral)
+ if (Previous && Previous->isNot(TT_DictLiteral))
Previous->setType(TT_SelectorName);
}
+ if (Style.isTableGen())
+ Tok->setType(TT_TemplateOpener);
} else {
Tok->setType(TT_BinaryOperator);
NonTemplateLess.insert(Tok);
@@ -1423,11 +1754,28 @@ private:
if (!Tok->getPreviousNonComment())
Line.IsContinuation = true;
}
+ if (Style.isTableGen()) {
+ if (Tok->is(Keywords.kw_assert)) {
+ if (!parseTableGenValue())
+ return false;
+ } else if (Tok->isOneOf(Keywords.kw_def, Keywords.kw_defm) &&
+ (!Tok->Next ||
+ !Tok->Next->isOneOf(tok::colon, tok::l_brace))) {
+ // The case NameValue appears.
+ if (!parseTableGenValue(true))
+ return false;
+ }
+ }
break;
case tok::arrow:
if (Tok->Previous && Tok->Previous->is(tok::kw_noexcept))
Tok->setType(TT_TrailingReturnArrow);
break;
+ case tok::equal:
+ // In TableGen, there must be a value after "=";
+ if (Style.isTableGen() && !parseTableGenValue())
+ return false;
+ break;
default:
break;
}
@@ -1564,6 +1912,8 @@ private:
case tok::pp_elif:
Contexts.back().IsExpression = true;
next();
+ if (CurrentToken)
+ CurrentToken->SpacesRequiredBefore = true;
parseLine();
break;
default:
@@ -1658,6 +2008,8 @@ public:
if (!consumeToken())
return LT_Invalid;
}
+ if (Line.Type == LT_AccessModifier)
+ return LT_AccessModifier;
if (KeywordVirtualFound)
return LT_VirtualFunctionDecl;
if (ImportStatement)
@@ -1757,6 +2109,9 @@ private:
// Whether the braces may mean concatenation instead of structure or array
// literal.
bool VerilogMayBeConcatenation = false;
+ bool IsTableGenDAGArg = false;
+ bool IsTableGenBangOpe = false;
+ bool IsTableGenCondOpe = false;
enum {
Unknown,
// Like the part after `:` in a constructor.
@@ -1986,7 +2341,7 @@ private:
if (Current.Previous) {
bool IsIdentifier =
Style.isJavaScript()
- ? Keywords.IsJavaScriptIdentifier(
+ ? Keywords.isJavaScriptIdentifier(
*Current.Previous, /* AcceptIdentifierName= */ true)
: Current.Previous->is(tok::identifier);
if (IsIdentifier ||
@@ -2009,7 +2364,8 @@ private:
// Line.MightBeFunctionDecl can only be true after the parentheses of a
// function declaration have been found. In this case, 'Current' is a
// trailing token of this declaration and thus cannot be a name.
- if (Current.is(Keywords.kw_instanceof)) {
+ if ((Style.isJavaScript() || Style.Language == FormatStyle::LK_Java) &&
+ Current.is(Keywords.kw_instanceof)) {
Current.setType(TT_BinaryOperator);
} else if (isStartOfName(Current) &&
(!Line.MightBeFunctionDecl || Current.NestingLevel != 0)) {
@@ -2061,6 +2417,9 @@ private:
// In JavaScript, `interface X { foo?(): bar; }` is an optional method
// on the interface, not a ternary expression.
Current.setType(TT_JsTypeOptionalQuestion);
+ } else if (Style.isTableGen()) {
+ // In TableGen, '?' is just an identifier like token.
+ Current.setType(TT_Unknown);
} else {
Current.setType(TT_ConditionalExpr);
}
@@ -2108,9 +2467,9 @@ private:
Current.setType(TT_CastRParen);
if (Current.MatchingParen && Current.Next &&
!Current.Next->isBinaryOperator() &&
- !Current.Next->isOneOf(tok::semi, tok::colon, tok::l_brace,
- tok::comma, tok::period, tok::arrow,
- tok::coloncolon, tok::kw_noexcept)) {
+ !Current.Next->isOneOf(
+ tok::semi, tok::colon, tok::l_brace, tok::l_paren, tok::comma,
+ tok::period, tok::arrow, tok::coloncolon, tok::kw_noexcept)) {
if (FormatToken *AfterParen = Current.MatchingParen->Next;
AfterParen && AfterParen->isNot(tok::caret)) {
// Make sure this isn't the return type of an Obj-C block declaration.
@@ -2239,6 +2598,9 @@ private:
// keywords such as let and def* defines names.
if (Keywords.isTableGenDefinition(*PreviousNotConst))
return true;
+ // Otherwise C++ style declarations is available only inside the brace.
+ if (Contexts.back().ContextKind != tok::l_brace)
+ return false;
}
bool IsPPKeyword = PreviousNotConst->is(tok::identifier) &&
@@ -2263,15 +2625,17 @@ private:
return false;
// int a or auto a.
- if (PreviousNotConst->isOneOf(tok::identifier, tok::kw_auto))
+ if (PreviousNotConst->isOneOf(tok::identifier, tok::kw_auto) &&
+ PreviousNotConst->isNot(TT_StatementAttributeLikeMacro)) {
return true;
+ }
// *a or &a or &&a.
if (PreviousNotConst->is(TT_PointerOrReference))
return true;
// MyClass a;
- if (PreviousNotConst->isSimpleTypeSpecifier())
+ if (PreviousNotConst->isTypeName(LangOpts))
return true;
// type[] a in Java
@@ -2287,7 +2651,7 @@ private:
/// Determine whether '(' is starting a C++ cast.
bool lParenStartsCppCast(const FormatToken &Tok) {
// C-style casts are only used in C++.
- if (!Style.isCpp())
+ if (!IsCpp)
return false;
FormatToken *LeftOfParens = Tok.getPreviousNonComment();
@@ -2307,20 +2671,27 @@ private:
/// Determine whether ')' is ending a cast.
bool rParenEndsCast(const FormatToken &Tok) {
+ assert(Tok.is(tok::r_paren));
+
+ if (!Tok.MatchingParen || !Tok.Previous)
+ return false;
+
// C-style casts are only used in C++, C# and Java.
- if (!Style.isCSharp() && !Style.isCpp() &&
- Style.Language != FormatStyle::LK_Java) {
+ if (!IsCpp && !Style.isCSharp() && Style.Language != FormatStyle::LK_Java)
return false;
- }
+
+ const auto *LParen = Tok.MatchingParen;
+ const auto *BeforeRParen = Tok.Previous;
+ const auto *AfterRParen = Tok.Next;
// Empty parens aren't casts and there are no casts at the end of the line.
- if (Tok.Previous == Tok.MatchingParen || !Tok.Next || !Tok.MatchingParen)
+ if (BeforeRParen == LParen || !AfterRParen)
return false;
- if (Tok.MatchingParen->is(TT_OverloadedOperatorLParen))
+ if (LParen->is(TT_OverloadedOperatorLParen))
return false;
- FormatToken *LeftOfParens = Tok.MatchingParen->getPreviousNonComment();
+ auto *LeftOfParens = LParen->getPreviousNonComment();
if (LeftOfParens) {
// If there is a closing parenthesis left of the current
// parentheses, look past it as these might be chained casts.
@@ -2376,37 +2747,41 @@ private:
}
}
- if (Tok.Next->isOneOf(tok::question, tok::ampamp))
+ if (AfterRParen->is(tok::question) ||
+ (AfterRParen->is(tok::ampamp) && !BeforeRParen->isTypeName(LangOpts))) {
return false;
+ }
// `foreach((A a, B b) in someList)` should not be seen as a cast.
- if (Tok.Next->is(Keywords.kw_in) && Style.isCSharp())
+ if (AfterRParen->is(Keywords.kw_in) && Style.isCSharp())
return false;
// Functions which end with decorations like volatile, noexcept are unlikely
// to be casts.
- if (Tok.Next->isOneOf(tok::kw_noexcept, tok::kw_volatile, tok::kw_const,
- tok::kw_requires, tok::kw_throw, tok::arrow,
- Keywords.kw_override, Keywords.kw_final) ||
- isCppAttribute(Style.isCpp(), *Tok.Next)) {
+ if (AfterRParen->isOneOf(tok::kw_noexcept, tok::kw_volatile, tok::kw_const,
+ tok::kw_requires, tok::kw_throw, tok::arrow,
+ Keywords.kw_override, Keywords.kw_final) ||
+ isCppAttribute(IsCpp, *AfterRParen)) {
return false;
}
// As Java has no function types, a "(" after the ")" likely means that this
// is a cast.
- if (Style.Language == FormatStyle::LK_Java && Tok.Next->is(tok::l_paren))
+ if (Style.Language == FormatStyle::LK_Java && AfterRParen->is(tok::l_paren))
return true;
// If a (non-string) literal follows, this is likely a cast.
- if (Tok.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof) ||
- (Tok.Next->Tok.isLiteral() && Tok.Next->isNot(tok::string_literal))) {
+ if (AfterRParen->isOneOf(tok::kw_sizeof, tok::kw_alignof) ||
+ (AfterRParen->Tok.isLiteral() &&
+ AfterRParen->isNot(tok::string_literal))) {
return true;
}
// Heuristically try to determine whether the parentheses contain a type.
- auto IsQualifiedPointerOrReference = [](FormatToken *T) {
+ auto IsQualifiedPointerOrReference = [](const FormatToken *T,
+ const LangOptions &LangOpts) {
// This is used to handle cases such as x = (foo *const)&y;
- assert(!T->isSimpleTypeSpecifier() && "Should have already been checked");
+ assert(!T->isTypeName(LangOpts) && "Should have already been checked");
// Strip trailing qualifiers such as const or volatile when checking
// whether the parens could be a cast to a pointer/reference type.
while (T) {
@@ -2436,12 +2811,11 @@ private:
return T && T->is(TT_PointerOrReference);
};
bool ParensAreType =
- !Tok.Previous ||
- Tok.Previous->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) ||
- Tok.Previous->isSimpleTypeSpecifier() ||
- IsQualifiedPointerOrReference(Tok.Previous);
+ BeforeRParen->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) ||
+ BeforeRParen->isTypeName(LangOpts) ||
+ IsQualifiedPointerOrReference(BeforeRParen, LangOpts);
bool ParensCouldEndDecl =
- Tok.Next->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater);
+ AfterRParen->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater);
if (ParensAreType && !ParensCouldEndDecl)
return true;
@@ -2453,49 +2827,54 @@ private:
// Certain token types inside the parentheses mean that this can't be a
// cast.
- for (const FormatToken *Token = Tok.MatchingParen->Next; Token != &Tok;
- Token = Token->Next) {
+ for (const auto *Token = LParen->Next; Token != &Tok; Token = Token->Next)
if (Token->is(TT_BinaryOperator))
return false;
- }
// If the following token is an identifier or 'this', this is a cast. All
// cases where this can be something else are handled above.
- if (Tok.Next->isOneOf(tok::identifier, tok::kw_this))
+ if (AfterRParen->isOneOf(tok::identifier, tok::kw_this))
return true;
// Look for a cast `( x ) (`.
- if (Tok.Next->is(tok::l_paren) && Tok.Previous && Tok.Previous->Previous) {
- if (Tok.Previous->is(tok::identifier) &&
- Tok.Previous->Previous->is(tok::l_paren)) {
+ if (AfterRParen->is(tok::l_paren) && BeforeRParen->Previous) {
+ if (BeforeRParen->is(tok::identifier) &&
+ BeforeRParen->Previous->is(tok::l_paren)) {
return true;
}
}
- if (!Tok.Next->Next)
+ if (!AfterRParen->Next)
return false;
+ if (AfterRParen->is(tok::l_brace) &&
+ AfterRParen->getBlockKind() == BK_BracedInit) {
+ return true;
+ }
+
// If the next token after the parenthesis is a unary operator, assume
// that this is cast, unless there are unexpected tokens inside the
// parenthesis.
- const bool NextIsAmpOrStar = Tok.Next->isOneOf(tok::amp, tok::star);
- if (!(Tok.Next->isUnaryOperator() || NextIsAmpOrStar) ||
- Tok.Next->is(tok::plus) ||
- !Tok.Next->Next->isOneOf(tok::identifier, tok::numeric_constant)) {
+ const bool NextIsAmpOrStar = AfterRParen->isOneOf(tok::amp, tok::star);
+ if (!(AfterRParen->isUnaryOperator() || NextIsAmpOrStar) ||
+ AfterRParen->is(tok::plus) ||
+ !AfterRParen->Next->isOneOf(tok::identifier, tok::numeric_constant)) {
return false;
}
+
if (NextIsAmpOrStar &&
- (Tok.Next->Next->is(tok::numeric_constant) || Line.InPPDirective)) {
+ (AfterRParen->Next->is(tok::numeric_constant) || Line.InPPDirective)) {
return false;
}
- if (Line.InPPDirective && Tok.Next->is(tok::minus))
+
+ if (Line.InPPDirective && AfterRParen->is(tok::minus))
return false;
+
// Search for unexpected tokens.
- for (FormatToken *Prev = Tok.Previous; Prev != Tok.MatchingParen;
- Prev = Prev->Previous) {
+ for (auto *Prev = BeforeRParen; Prev != LParen; Prev = Prev->Previous)
if (!Prev->isOneOf(tok::kw_const, tok::identifier, tok::coloncolon))
return false;
- }
+
return true;
}
@@ -2562,6 +2941,8 @@ private:
return TT_UnaryOperator;
if (PrevToken->is(TT_TypeName))
return TT_PointerOrReference;
+ if (PrevToken->isOneOf(tok::kw_new, tok::kw_delete) && Tok.is(tok::ampamp))
+ return TT_BinaryOperator;
const FormatToken *NextToken = Tok.getNextNonComment();
@@ -2709,6 +3090,8 @@ private:
AnnotatedLine &Line;
FormatToken *CurrentToken;
bool AutoFound;
+ bool IsCpp;
+ LangOptions LangOpts;
const AdditionalKeywords &Keywords;
SmallVector<ScopeType> &Scopes;
@@ -2718,6 +3101,8 @@ private:
// same decision irrespective of the decisions for tokens leading up to it.
// Store this information to prevent this from causing exponential runtime.
llvm::SmallPtrSet<FormatToken *, 16> NonTemplateLess;
+
+ int TemplateDeclarationDepth;
};
static const int PrecedenceUnaryOperator = prec::PointerToMember + 1;
@@ -3055,7 +3440,8 @@ private:
} else {
break;
}
- } else if (Tok->is(tok::hash)) {
+ } else if (Tok->is(Keywords.kw_verilogHash)) {
+ // Delay control.
if (Next->is(tok::l_paren))
Next = Next->MatchingParen;
if (Next)
@@ -3164,7 +3550,8 @@ static unsigned maxNestingDepth(const AnnotatedLine &Line) {
// Returns the name of a function with no return type, e.g. a constructor or
// destructor.
-static FormatToken *getFunctionName(const AnnotatedLine &Line) {
+static FormatToken *getFunctionName(const AnnotatedLine &Line,
+ FormatToken *&OpeningParen) {
for (FormatToken *Tok = Line.getFirstNonComment(), *Name = nullptr; Tok;
Tok = Tok->getNextNonComment()) {
// Skip C++11 attributes both before and after the function name.
@@ -3177,10 +3564,12 @@ static FormatToken *getFunctionName(const AnnotatedLine &Line) {
// Make sure the name is followed by a pair of parentheses.
if (Name) {
- return Tok->is(tok::l_paren) && Tok->isNot(TT_FunctionTypeLParen) &&
- Tok->MatchingParen
- ? Name
- : nullptr;
+ if (Tok->is(tok::l_paren) && Tok->isNot(TT_FunctionTypeLParen) &&
+ Tok->MatchingParen) {
+ OpeningParen = Tok;
+ return Name;
+ }
+ return nullptr;
}
// Skip keywords that may precede the constructor/destructor name.
@@ -3256,11 +3645,14 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) {
ExpressionParser ExprParser(Style, Keywords, Line);
ExprParser.parse();
- if (Style.isCpp()) {
- auto *Tok = getFunctionName(Line);
+ if (IsCpp) {
+ FormatToken *OpeningParen = nullptr;
+ auto *Tok = getFunctionName(Line, OpeningParen);
if (Tok && ((!Scopes.empty() && Scopes.back() == ST_Class) ||
Line.endsWith(TT_FunctionLBrace) || isCtorOrDtorName(Tok))) {
Tok->setFinalizedType(TT_CtorDtorDeclName);
+ assert(OpeningParen);
+ OpeningParen->setFinalizedType(TT_FunctionDeclarationLParen);
}
}
@@ -3283,7 +3675,8 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) {
// This function heuristically determines whether 'Current' starts the name of a
// function declaration.
-static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
+static bool isFunctionDeclarationName(const LangOptions &LangOpts,
+ const FormatToken &Current,
const AnnotatedLine &Line,
FormatToken *&ClosingParen) {
assert(Current.Previous);
@@ -3294,7 +3687,15 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
if (!Current.Tok.getIdentifierInfo())
return false;
- auto skipOperatorName = [](const FormatToken *Next) -> const FormatToken * {
+ const auto &Previous = *Current.Previous;
+
+ if (const auto *PrevPrev = Previous.Previous;
+ PrevPrev && PrevPrev->is(TT_ObjCDecl)) {
+ return false;
+ }
+
+ auto skipOperatorName =
+ [&LangOpts](const FormatToken *Next) -> const FormatToken * {
for (; Next; Next = Next->Next) {
if (Next->is(TT_OverloadedOperatorLParen))
return Next;
@@ -3313,7 +3714,7 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
Next = Next->Next;
continue;
}
- if ((Next->isSimpleTypeSpecifier() || Next->is(tok::identifier)) &&
+ if ((Next->isTypeName(LangOpts) || Next->is(tok::identifier)) &&
Next->Next && Next->Next->isPointerOrReference()) {
// For operator void*(), operator char*(), operator Foo*().
Next = Next->Next;
@@ -3329,21 +3730,22 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
return nullptr;
};
+ const auto *Next = Current.Next;
+ const bool IsCpp = LangOpts.CXXOperatorNames;
+
// Find parentheses of parameter list.
- const FormatToken *Next = Current.Next;
if (Current.is(tok::kw_operator)) {
- const auto *Previous = Current.Previous;
- if (Previous->Tok.getIdentifierInfo() &&
- !Previous->isOneOf(tok::kw_return, tok::kw_co_return)) {
+ if (Previous.Tok.getIdentifierInfo() &&
+ !Previous.isOneOf(tok::kw_return, tok::kw_co_return)) {
return true;
}
- if (Previous->is(tok::r_paren) && Previous->is(TT_TypeDeclarationParen)) {
- assert(Previous->MatchingParen);
- assert(Previous->MatchingParen->is(tok::l_paren));
- assert(Previous->MatchingParen->is(TT_TypeDeclarationParen));
+ if (Previous.is(tok::r_paren) && Previous.is(TT_TypeDeclarationParen)) {
+ assert(Previous.MatchingParen);
+ assert(Previous.MatchingParen->is(tok::l_paren));
+ assert(Previous.MatchingParen->is(TT_TypeDeclarationParen));
return true;
}
- if (!Previous->isPointerOrReference() && Previous->isNot(TT_TemplateCloser))
+ if (!Previous.isPointerOrReference() && Previous.isNot(TT_TemplateCloser))
return false;
Next = skipOperatorName(Next);
} else {
@@ -3411,9 +3813,8 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
Tok = Tok->MatchingParen;
continue;
}
- if (Tok->is(tok::kw_const) || Tok->isSimpleTypeSpecifier() ||
- Tok->isOneOf(TT_PointerOrReference, TT_StartOfName, tok::ellipsis,
- TT_TypeName)) {
+ if (Tok->is(tok::kw_const) || Tok->isTypeName(LangOpts) ||
+ Tok->isOneOf(TT_PointerOrReference, TT_StartOfName, tok::ellipsis)) {
return true;
}
if (Tok->isOneOf(tok::l_brace, TT_ObjCMethodExpr) || Tok->Tok.isLiteral())
@@ -3425,15 +3826,16 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
bool TokenAnnotator::mustBreakForReturnType(const AnnotatedLine &Line) const {
assert(Line.MightBeFunctionDecl);
- if ((Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_TopLevel ||
- Style.AlwaysBreakAfterReturnType ==
- FormatStyle::RTBS_TopLevelDefinitions) &&
+ if ((Style.BreakAfterReturnType == FormatStyle::RTBS_TopLevel ||
+ Style.BreakAfterReturnType == FormatStyle::RTBS_TopLevelDefinitions) &&
Line.Level > 0) {
return false;
}
- switch (Style.AlwaysBreakAfterReturnType) {
+ switch (Style.BreakAfterReturnType) {
case FormatStyle::RTBS_None:
+ case FormatStyle::RTBS_Automatic:
+ case FormatStyle::RTBS_ExceptShortType:
return false;
case FormatStyle::RTBS_All:
case FormatStyle::RTBS_TopLevel:
@@ -3462,7 +3864,6 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
if (AlignArrayOfStructures)
calculateArrayInitializerColumnList(Line);
- const bool IsCpp = Style.isCpp();
bool SeenName = false;
bool LineIsFunctionDeclaration = false;
FormatToken *ClosingParen = nullptr;
@@ -3475,11 +3876,17 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
AfterLastAttribute = Tok;
if (const bool IsCtorOrDtor = Tok->is(TT_CtorDtorDeclName);
IsCtorOrDtor ||
- isFunctionDeclarationName(Style.isCpp(), *Tok, Line, ClosingParen)) {
+ isFunctionDeclarationName(LangOpts, *Tok, Line, ClosingParen)) {
if (!IsCtorOrDtor)
Tok->setFinalizedType(TT_FunctionDeclarationName);
LineIsFunctionDeclaration = true;
SeenName = true;
+ if (ClosingParen) {
+ auto *OpeningParen = ClosingParen->MatchingParen;
+ assert(OpeningParen);
+ if (OpeningParen->is(TT_Unknown))
+ OpeningParen->setType(TT_FunctionDeclarationLParen);
+ }
break;
}
}
@@ -3513,7 +3920,7 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
do {
Tok = Tok->Next;
} while (Tok && Tok->isNot(TT_OverloadedOperatorLParen));
- if (!Tok)
+ if (!Tok || !Tok->MatchingParen)
break;
const auto *LeftParen = Tok;
for (Tok = Tok->Next; Tok && Tok != LeftParen->MatchingParen;
@@ -3968,11 +4375,24 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return Left.is(tok::hash);
if (Left.isOneOf(tok::hashhash, tok::hash))
return Right.is(tok::hash);
+ if (Left.is(BK_Block) && Right.is(tok::r_brace) &&
+ Right.MatchingParen == &Left && Line.Children.empty()) {
+ return Style.SpaceInEmptyBlock;
+ }
if ((Left.is(tok::l_paren) && Right.is(tok::r_paren)) ||
(Left.is(tok::l_brace) && Left.isNot(BK_Block) &&
Right.is(tok::r_brace) && Right.isNot(BK_Block))) {
return Style.SpacesInParensOptions.InEmptyParentheses;
}
+ if (Style.SpacesInParens == FormatStyle::SIPO_Custom &&
+ Style.SpacesInParensOptions.ExceptDoubleParentheses &&
+ Left.is(tok::r_paren) && Right.is(tok::r_paren)) {
+ auto *InnerLParen = Left.MatchingParen;
+ if (InnerLParen && InnerLParen->Previous == Right.MatchingParen) {
+ InnerLParen->SpacesRequiredBefore = 0;
+ return false;
+ }
+ }
if (Style.SpacesInParensOptions.InConditionalStatements) {
const FormatToken *LeftParen = nullptr;
if (Left.is(tok::l_paren))
@@ -3998,9 +4418,11 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (Left.is(tok::kw_auto) && Right.isOneOf(tok::l_paren, tok::l_brace))
return false;
+ const auto *BeforeLeft = Left.Previous;
+
// operator co_await(x)
- if (Right.is(tok::l_paren) && Left.is(tok::kw_co_await) && Left.Previous &&
- Left.Previous->is(tok::kw_operator)) {
+ if (Right.is(tok::l_paren) && Left.is(tok::kw_co_await) && BeforeLeft &&
+ BeforeLeft->is(tok::kw_operator)) {
return false;
}
// co_await (x), co_yield (x), co_return (x)
@@ -4035,8 +4457,10 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
}
if (Left.is(tok::colon))
return Left.isNot(TT_ObjCMethodExpr);
- if (Left.is(tok::coloncolon))
- return false;
+ if (Left.is(tok::coloncolon)) {
+ return Right.is(tok::star) && Right.is(TT_PointerOrReference) &&
+ Style.PointerAlignment != FormatStyle::PAS_Left;
+ }
if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less)) {
if (Style.Language == FormatStyle::LK_TextProto ||
(Style.Language == FormatStyle::LK_Proto &&
@@ -4051,8 +4475,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return false;
}
if (Right.is(tok::ellipsis)) {
- return Left.Tok.isLiteral() || (Left.is(tok::identifier) && Left.Previous &&
- Left.Previous->is(tok::kw_case));
+ return Left.Tok.isLiteral() || (Left.is(tok::identifier) && BeforeLeft &&
+ BeforeLeft->is(tok::kw_case));
}
if (Left.is(tok::l_square) && Right.is(tok::amp))
return Style.SpacesInSquareBrackets;
@@ -4077,7 +4501,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (Left.Tok.isLiteral())
return true;
// for (auto a = 0, b = 0; const auto & c : {1, 2, 3})
- if (Left.isTypeOrIdentifier() && Right.Next && Right.Next->Next &&
+ if (Left.isTypeOrIdentifier(LangOpts) && Right.Next && Right.Next->Next &&
Right.Next->Next->is(TT_RangeBasedForLoopColon)) {
return getTokenPointerOrReferenceAlignment(Right) !=
FormatStyle::PAS_Left;
@@ -4120,7 +4544,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (Right.is(tok::l_brace) && Right.is(BK_Block))
return true;
// for (auto a = 0, b = 0; const auto& c : {1, 2, 3})
- if (Left.Previous && Left.Previous->isTypeOrIdentifier() && Right.Next &&
+ if (BeforeLeft && BeforeLeft->isTypeOrIdentifier(LangOpts) && Right.Next &&
Right.Next->is(TT_RangeBasedForLoopColon)) {
return getTokenPointerOrReferenceAlignment(Left) !=
FormatStyle::PAS_Right;
@@ -4143,12 +4567,17 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
startsWithInitStatement(Line)))) {
return false;
}
- return Left.Previous && !Left.Previous->isOneOf(
- tok::l_paren, tok::coloncolon, tok::l_square);
+ if (!BeforeLeft)
+ return false;
+ if (BeforeLeft->is(tok::coloncolon)) {
+ return Left.is(tok::star) &&
+ Style.PointerAlignment != FormatStyle::PAS_Right;
+ }
+ return !BeforeLeft->isOneOf(tok::l_paren, tok::l_square);
}
// Ensure right pointer alignment with ellipsis e.g. int *...P
- if (Left.is(tok::ellipsis) && Left.Previous &&
- Left.Previous->isPointerOrReference()) {
+ if (Left.is(tok::ellipsis) && BeforeLeft &&
+ BeforeLeft->isPointerOrReference()) {
return Style.PointerAlignment != FormatStyle::PAS_Right;
}
@@ -4159,7 +4588,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (Right.isPointerOrReference()) {
const FormatToken *Previous = &Left;
while (Previous && Previous->isNot(tok::kw_operator)) {
- if (Previous->is(tok::identifier) || Previous->isSimpleTypeSpecifier()) {
+ if (Previous->is(tok::identifier) || Previous->isTypeName(LangOpts)) {
Previous = Previous->getPreviousNonComment();
continue;
}
@@ -4295,14 +4724,13 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (Right.is(TT_OverloadedOperatorLParen))
return spaceRequiredBeforeParens(Right);
// Function declaration or definition
- if (Line.MightBeFunctionDecl && (Left.is(TT_FunctionDeclarationName))) {
- if (Line.mightBeFunctionDefinition()) {
- return Style.SpaceBeforeParensOptions.AfterFunctionDefinitionName ||
- spaceRequiredBeforeParens(Right);
- } else {
- return Style.SpaceBeforeParensOptions.AfterFunctionDeclarationName ||
- spaceRequiredBeforeParens(Right);
- }
+ if (Line.MightBeFunctionDecl && Right.is(TT_FunctionDeclarationLParen)) {
+ if (spaceRequiredBeforeParens(Right))
+ return true;
+ const auto &Options = Style.SpaceBeforeParensOptions;
+ return Line.mightBeFunctionDefinition()
+ ? Options.AfterFunctionDefinitionName
+ : Options.AfterFunctionDeclarationName;
}
// Lambda
if (Line.Type != LT_PreprocessorDirective && Left.is(tok::r_square) &&
@@ -4310,13 +4738,13 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return Style.SpaceBeforeParensOptions.AfterFunctionDefinitionName ||
spaceRequiredBeforeParens(Right);
}
- if (!Left.Previous || Left.Previous->isNot(tok::period)) {
+ if (!BeforeLeft || !BeforeLeft->isOneOf(tok::period, tok::arrow)) {
if (Left.isOneOf(tok::kw_try, Keywords.kw___except, tok::kw_catch)) {
return Style.SpaceBeforeParensOptions.AfterControlStatements ||
spaceRequiredBeforeParens(Right);
}
if (Left.isOneOf(tok::kw_new, tok::kw_delete)) {
- return ((!Line.MightBeFunctionDecl || !Left.Previous) &&
+ return ((!Line.MightBeFunctionDecl || !BeforeLeft) &&
Style.SpaceBeforeParens != FormatStyle::SBPO_Never) ||
spaceRequiredBeforeParens(Right);
}
@@ -4348,7 +4776,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (!Style.isVerilog() &&
(Left.isOneOf(tok::identifier, tok::greater, tok::r_square,
tok::r_paren) ||
- Left.isSimpleTypeSpecifier()) &&
+ Left.isTypeName(LangOpts)) &&
Right.is(tok::l_brace) && Right.getNextNonComment() &&
Right.isNot(BK_Block)) {
return false;
@@ -4384,8 +4812,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
// Objective-C dictionary literal -> no space before closing brace.
return false;
}
- if (Right.getType() == TT_TrailingAnnotation &&
- Right.isOneOf(tok::amp, tok::ampamp) &&
+ if (Right.is(TT_TrailingAnnotation) && Right.isOneOf(tok::amp, tok::ampamp) &&
Left.isOneOf(tok::kw_const, tok::kw_volatile) &&
(!Right.Next || Right.Next->is(tok::semi))) {
// Match const and volatile ref-qualifiers without any additional
@@ -4406,16 +4833,21 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
if (Left.Finalized)
return Right.hasWhitespaceBefore();
+ const bool IsVerilog = Style.isVerilog();
+ assert(!IsVerilog || !IsCpp);
+
// Never ever merge two words.
- if (Keywords.isWordLike(Right) && Keywords.isWordLike(Left))
+ if (Keywords.isWordLike(Right, IsVerilog) &&
+ Keywords.isWordLike(Left, IsVerilog)) {
return true;
+ }
// Leave a space between * and /* to avoid C4138 `comment end` found outside
// of comment.
if (Left.is(tok::star) && Right.is(tok::comment))
return true;
- if (Style.isCpp()) {
+ if (IsCpp) {
if (Left.is(TT_OverloadedOperator) &&
Right.isOneOf(TT_TemplateOpener, TT_TemplateCloser)) {
return true;
@@ -4460,6 +4892,12 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
Right.is(TT_TemplateOpener)) {
return true;
}
+ // C++ Core Guidelines suppression tag, e.g. `[[suppress(type.5)]]`.
+ if (Left.is(tok::identifier) && Right.is(tok::numeric_constant))
+ return Right.TokenText[0] != '.';
+ // `Left` is a keyword (including C++ alternative operator) or identifier.
+ if (Left.Tok.getIdentifierInfo() && Right.Tok.isLiteral())
+ return true;
} else if (Style.isProto()) {
if (Right.is(tok::period) &&
Left.isOneOf(Keywords.kw_optional, Keywords.kw_required,
@@ -4557,11 +4995,11 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
// space between method modifier and opening parenthesis of a tuple return
// type
- if (Left.isOneOf(tok::kw_public, tok::kw_private, tok::kw_protected,
- tok::kw_virtual, tok::kw_extern, tok::kw_static,
- Keywords.kw_internal, Keywords.kw_abstract,
- Keywords.kw_sealed, Keywords.kw_override,
- Keywords.kw_async, Keywords.kw_unsafe) &&
+ if ((Left.isAccessSpecifierKeyword() ||
+ Left.isOneOf(tok::kw_virtual, tok::kw_extern, tok::kw_static,
+ Keywords.kw_internal, Keywords.kw_abstract,
+ Keywords.kw_sealed, Keywords.kw_override,
+ Keywords.kw_async, Keywords.kw_unsafe)) &&
Right.is(tok::l_paren)) {
return true;
}
@@ -4587,7 +5025,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
}
// In tagged template literals ("html`bar baz`"), there is no space between
// the tag identifier and the template string.
- if (Keywords.IsJavaScriptIdentifier(Left,
+ if (Keywords.isJavaScriptIdentifier(Left,
/* AcceptIdentifierName= */ false) &&
Right.is(TT_TemplateString)) {
return false;
@@ -4670,6 +5108,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return true; // "x! as string", "x! in y"
}
} else if (Style.Language == FormatStyle::LK_Java) {
+ if (Left.is(TT_CaseLabelArrow) || Right.is(TT_CaseLabelArrow))
+ return true;
if (Left.is(tok::r_square) && Right.is(tok::l_brace))
return true;
// spaces inside square brackets.
@@ -4680,19 +5120,16 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return Style.SpaceBeforeParensOptions.AfterControlStatements ||
spaceRequiredBeforeParens(Right);
}
- if ((Left.isOneOf(tok::kw_static, tok::kw_public, tok::kw_private,
- tok::kw_protected) ||
- Left.isOneOf(Keywords.kw_final, Keywords.kw_abstract,
+ if ((Left.isAccessSpecifierKeyword() ||
+ Left.isOneOf(tok::kw_static, Keywords.kw_final, Keywords.kw_abstract,
Keywords.kw_native)) &&
Right.is(TT_TemplateOpener)) {
return true;
}
- } else if (Style.isVerilog()) {
+ } else if (IsVerilog) {
// An escaped identifier ends with whitespace.
- if (Style.isVerilog() && Left.is(tok::identifier) &&
- Left.TokenText[0] == '\\') {
+ if (Left.is(tok::identifier) && Left.TokenText[0] == '\\')
return true;
- }
// Add space between things in a primitive's state table unless in a
// transition like `(0?)`.
if ((Left.is(TT_VerilogTableItem) &&
@@ -4770,7 +5207,45 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
Left.endsSequence(tok::greatergreater, tok::l_brace))) {
return false;
}
+ } else if (Style.isTableGen()) {
+ // Avoid to connect [ and {. [{ is start token of multiline string.
+ if (Left.is(tok::l_square) && Right.is(tok::l_brace))
+ return true;
+ if (Left.is(tok::r_brace) && Right.is(tok::r_square))
+ return true;
+ // Do not insert around colon in DAGArg and cond operator.
+ if (Right.isOneOf(TT_TableGenDAGArgListColon,
+ TT_TableGenDAGArgListColonToAlign) ||
+ Left.isOneOf(TT_TableGenDAGArgListColon,
+ TT_TableGenDAGArgListColonToAlign)) {
+ return false;
+ }
+ if (Right.is(TT_TableGenCondOperatorColon))
+ return false;
+ if (Left.isOneOf(TT_TableGenDAGArgOperatorID,
+ TT_TableGenDAGArgOperatorToBreak) &&
+ Right.isNot(TT_TableGenDAGArgCloser)) {
+ return true;
+ }
+ // Do not insert bang operators and consequent openers.
+ if (Right.isOneOf(tok::l_paren, tok::less) &&
+ Left.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator)) {
+ return false;
+ }
+ // Trailing paste requires space before '{' or ':', the case in name values.
+ // Not before ';', the case in normal values.
+ if (Left.is(TT_TableGenTrailingPasteOperator) &&
+ Right.isOneOf(tok::l_brace, tok::colon)) {
+ return true;
+ }
+ // Otherwise paste operator does not prefer space around.
+ if (Left.is(tok::hash) || Right.is(tok::hash))
+ return false;
+ // Sure not to connect after defining keywords.
+ if (Keywords.isTableGenDefinition(Left))
+ return true;
}
+
if (Left.is(TT_ImplicitStringLiteral))
return Right.hasWhitespaceBefore();
if (Line.Type == LT_ObjCMethodDecl) {
@@ -4850,21 +5325,11 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return true;
}
if (Left.is(TT_UnaryOperator)) {
- if (Right.isNot(tok::l_paren)) {
- // The alternative operators for ~ and ! are "compl" and "not".
- // If they are used instead, we do not want to combine them with
- // the token to the right, unless that is a left paren.
- if (Left.is(tok::exclaim) && Left.TokenText == "not")
- return true;
- if (Left.is(tok::tilde) && Left.TokenText == "compl")
- return true;
- // Lambda captures allow for a lone &, so "&]" needs to be properly
- // handled.
- if (Left.is(tok::amp) && Right.is(tok::r_square))
- return Style.SpacesInSquareBrackets;
- }
- return (Style.SpaceAfterLogicalNot && Left.is(tok::exclaim)) ||
- Right.is(TT_BinaryOperator);
+ // Lambda captures allow for a lone &, so "&]" needs to be properly
+ // handled.
+ if (Left.is(tok::amp) && Right.is(tok::r_square))
+ return Style.SpacesInSquareBrackets;
+ return Style.SpaceAfterLogicalNot && Left.is(tok::exclaim);
}
// If the next token is a binary operator or a selector name, we have
@@ -4983,6 +5448,15 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
if (Right.NewlinesBefore > 1 && Style.MaxEmptyLinesToKeep > 0)
return true;
+ if (Style.BreakFunctionDefinitionParameters && Line.MightBeFunctionDecl &&
+ Line.mightBeFunctionDefinition() && Left.MightBeFunctionDeclParen &&
+ Left.ParameterCount > 0) {
+ return true;
+ }
+
+ const auto *BeforeLeft = Left.Previous;
+ const auto *AfterRight = Right.Next;
+
if (Style.isCSharp()) {
if (Left.is(TT_FatArrow) && Right.is(tok::l_brace) &&
Style.BraceWrapping.AfterFunction) {
@@ -4994,7 +5468,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
}
if (Right.is(TT_CSharpGenericTypeConstraint))
return true;
- if (Right.Next && Right.Next->is(TT_FatArrow) &&
+ if (AfterRight && AfterRight->is(TT_FatArrow) &&
(Right.is(tok::numeric_constant) ||
(Right.is(tok::identifier) && Right.TokenText == "_"))) {
return true;
@@ -5011,15 +5485,14 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
Left.is(tok::r_square) && Right.is(tok::l_square)) {
return true;
}
-
} else if (Style.isJavaScript()) {
// FIXME: This might apply to other languages and token kinds.
- if (Right.is(tok::string_literal) && Left.is(tok::plus) && Left.Previous &&
- Left.Previous->is(tok::string_literal)) {
+ if (Right.is(tok::string_literal) && Left.is(tok::plus) && BeforeLeft &&
+ BeforeLeft->is(tok::string_literal)) {
return true;
}
if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace) && Line.Level == 0 &&
- Left.Previous && Left.Previous->is(tok::equal) &&
+ BeforeLeft && BeforeLeft->is(tok::equal) &&
Line.First->isOneOf(tok::identifier, Keywords.kw_import, tok::kw_export,
tok::kw_const) &&
// kw_var/kw_let are pseudo-tokens that are tok::identifier, so match
@@ -5038,8 +5511,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
// instead of bin-packing.
return true;
}
- if (Right.is(tok::r_brace) && Left.is(tok::l_brace) && Left.Previous &&
- Left.Previous->is(TT_FatArrow)) {
+ if (Right.is(tok::r_brace) && Left.is(tok::l_brace) && BeforeLeft &&
+ BeforeLeft->is(TT_FatArrow)) {
// JS arrow function (=> {...}).
switch (Style.AllowShortLambdasOnASingleLine) {
case FormatStyle::SLS_All:
@@ -5067,8 +5540,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
FormatStyle::SFS_InlineOnly);
}
} else if (Style.Language == FormatStyle::LK_Java) {
- if (Right.is(tok::plus) && Left.is(tok::string_literal) && Right.Next &&
- Right.Next->is(tok::string_literal)) {
+ if (Right.is(tok::plus) && Left.is(tok::string_literal) && AfterRight &&
+ AfterRight->is(tok::string_literal)) {
return true;
}
} else if (Style.isVerilog()) {
@@ -5092,7 +5565,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
if (!Keywords.isVerilogBegin(Right) && Keywords.isVerilogEndOfLabel(Left))
return true;
} else if (Style.BreakAdjacentStringLiterals &&
- (Style.isCpp() || Style.isProto() ||
+ (IsCpp || Style.isProto() ||
Style.Language == FormatStyle::LK_TableGen)) {
if (Left.isStringLiteral() && Right.isStringLiteral())
return true;
@@ -5121,6 +5594,24 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
}
return Style.BreakArrays;
}
+ } else if (Style.isTableGen()) {
+ // Break the comma in side cond operators.
+ // !cond(case1:1,
+ // case2:0);
+ if (Left.is(TT_TableGenCondOperatorComma))
+ return true;
+ if (Left.is(TT_TableGenDAGArgOperatorToBreak) &&
+ Right.isNot(TT_TableGenDAGArgCloser)) {
+ return true;
+ }
+ if (Left.is(TT_TableGenDAGArgListCommaToBreak))
+ return true;
+ if (Right.is(TT_TableGenDAGArgCloser) && Right.MatchingParen &&
+ Right.MatchingParen->is(TT_TableGenDAGArgOpenerToBreak) &&
+ &Left != Right.MatchingParen->Next) {
+ // Check to avoid empty DAGArg such as (ins).
+ return Style.TableGenBreakInsideDAGArg == FormatStyle::DAS_BreakAll;
+ }
}
if (Line.startsWith(tok::kw_asm) && Right.is(TT_InlineASMColon) &&
@@ -5159,10 +5650,13 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
return true;
if (Left.IsUnterminatedLiteral)
return true;
- if (Right.is(tok::lessless) && Right.Next && Left.is(tok::string_literal) &&
- Right.Next->is(tok::string_literal)) {
- return true;
+
+ if (BeforeLeft && BeforeLeft->is(tok::lessless) &&
+ Left.is(tok::string_literal) && Right.is(tok::lessless) && AfterRight &&
+ AfterRight->is(tok::string_literal)) {
+ return Right.NewlinesBefore > 0;
}
+
if (Right.is(TT_RequiresClause)) {
switch (Style.RequiresClausePosition) {
case FormatStyle::RCPS_OwnLine:
@@ -5180,7 +5674,9 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
// concept ...
if (Right.is(tok::kw_concept))
return Style.BreakBeforeConceptDeclarations == FormatStyle::BBCDS_Always;
- return Style.AlwaysBreakTemplateDeclarations == FormatStyle::BTDS_Yes;
+ return Style.BreakTemplateDeclarations == FormatStyle::BTDS_Yes ||
+ (Style.BreakTemplateDeclarations == FormatStyle::BTDS_Leave &&
+ Right.NewlinesBefore > 0);
}
if (Left.ClosesRequiresClause && Right.isNot(tok::semi)) {
switch (Style.RequiresClausePosition) {
@@ -5235,8 +5731,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
// string literal accordingly. Thus, we try keep existing line breaks.
return Right.IsMultiline && Right.NewlinesBefore > 0;
}
- if ((Left.is(tok::l_brace) || (Left.is(tok::less) && Left.Previous &&
- Left.Previous->is(tok::equal))) &&
+ if ((Left.is(tok::l_brace) ||
+ (Left.is(tok::less) && BeforeLeft && BeforeLeft->is(tok::equal))) &&
Right.NestingLevel == 1 && Style.Language == FormatStyle::LK_Proto) {
// Don't put enums or option definitions onto single lines in protocol
// buffers.
@@ -5248,9 +5744,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
if (isAllmanBrace(Left) || isAllmanBrace(Right)) {
auto *FirstNonComment = Line.getFirstNonComment();
bool AccessSpecifier =
- FirstNonComment &&
- FirstNonComment->isOneOf(Keywords.kw_internal, tok::kw_public,
- tok::kw_private, tok::kw_protected);
+ FirstNonComment && (FirstNonComment->is(Keywords.kw_internal) ||
+ FirstNonComment->isAccessSpecifierKeyword());
if (Style.BraceWrapping.AfterEnum) {
if (Line.startsWith(tok::kw_enum) ||
@@ -5350,7 +5845,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
//
// We ensure elsewhere that extensions are always on their own line.
if (Style.isProto() && Right.is(TT_SelectorName) &&
- Right.isNot(tok::r_square) && Right.Next) {
+ Right.isNot(tok::r_square) && AfterRight) {
// Keep `@submessage` together in:
// @submessage { key: value }
if (Left.is(tok::at))
@@ -5359,7 +5854,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
// selector { ...
// selector: { ...
// selector: @base { ...
- FormatToken *LBrace = Right.Next;
+ const auto *LBrace = AfterRight;
if (LBrace && LBrace->is(tok::colon)) {
LBrace = LBrace->Next;
if (LBrace && LBrace->is(tok::at)) {
@@ -5436,13 +5931,13 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
} else if (Style.isJavaScript()) {
const FormatToken *NonComment = Right.getPreviousNonComment();
if (NonComment &&
- NonComment->isOneOf(
- tok::kw_return, Keywords.kw_yield, tok::kw_continue, tok::kw_break,
- tok::kw_throw, Keywords.kw_interface, Keywords.kw_type,
- tok::kw_static, tok::kw_public, tok::kw_private, tok::kw_protected,
- Keywords.kw_readonly, Keywords.kw_override, Keywords.kw_abstract,
- Keywords.kw_get, Keywords.kw_set, Keywords.kw_async,
- Keywords.kw_await)) {
+ (NonComment->isAccessSpecifierKeyword() ||
+ NonComment->isOneOf(
+ tok::kw_return, Keywords.kw_yield, tok::kw_continue, tok::kw_break,
+ tok::kw_throw, Keywords.kw_interface, Keywords.kw_type,
+ tok::kw_static, Keywords.kw_readonly, Keywords.kw_override,
+ Keywords.kw_abstract, Keywords.kw_get, Keywords.kw_set,
+ Keywords.kw_async, Keywords.kw_await))) {
return false; // Otherwise automatic semicolon insertion would trigger.
}
if (Right.NestingLevel == 0 &&
@@ -5514,6 +6009,23 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
return false;
if (Left.is(TT_TemplateString) && Left.opensScope())
return true;
+ } else if (Style.isTableGen()) {
+ // Avoid to break after "def", "class", "let" and so on.
+ if (Keywords.isTableGenDefinition(Left))
+ return false;
+ // Avoid to break after '(' in the cases that is in bang operators.
+ if (Right.is(tok::l_paren)) {
+ return !Left.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator,
+ TT_TemplateCloser);
+ }
+ // Avoid to break between the value and its suffix part.
+ if (Left.is(TT_TableGenValueSuffix))
+ return false;
+ // Avoid to break around paste operator.
+ if (Left.is(tok::hash) || Right.is(tok::hash))
+ return false;
+ if (Left.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator))
+ return false;
}
if (Left.is(tok::at))
@@ -5613,7 +6125,11 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
return Style.BreakBeforeConceptDeclarations != FormatStyle::BBCDS_Never;
if (Right.is(TT_RequiresClause))
return true;
- if (Left.ClosesTemplateDeclaration || Left.is(TT_FunctionAnnotationRParen))
+ if (Left.ClosesTemplateDeclaration) {
+ return Style.BreakTemplateDeclarations != FormatStyle::BTDS_Leave ||
+ Right.NewlinesBefore > 0;
+ }
+ if (Left.is(TT_FunctionAnnotationRParen))
return true;
if (Left.ClosesRequiresClause)
return true;
diff --git a/contrib/llvm-project/clang/lib/Format/TokenAnnotator.h b/contrib/llvm-project/clang/lib/Format/TokenAnnotator.h
index 05a6daa87d80..f4f2bba0eb21 100644
--- a/contrib/llvm-project/clang/lib/Format/TokenAnnotator.h
+++ b/contrib/llvm-project/clang/lib/Format/TokenAnnotator.h
@@ -16,13 +16,14 @@
#define LLVM_CLANG_LIB_FORMAT_TOKENANNOTATOR_H
#include "UnwrappedLineParser.h"
-#include "clang/Format/Format.h"
namespace clang {
namespace format {
enum LineType {
LT_Invalid,
+ // Contains public/private/protected followed by TT_InheritanceColon.
+ LT_AccessModifier,
LT_ImportStatement,
LT_ObjCDecl, // An @interface, @implementation, or @protocol line.
LT_ObjCMethodDecl,
@@ -46,7 +47,7 @@ enum ScopeType {
class AnnotatedLine {
public:
AnnotatedLine(const UnwrappedLine &Line)
- : First(Line.Tokens.front().Tok), Level(Line.Level),
+ : First(Line.Tokens.front().Tok), Type(LT_Other), Level(Line.Level),
PPLevel(Line.PPLevel),
MatchingOpeningBlockLineIndex(Line.MatchingOpeningBlockLineIndex),
MatchingClosingBlockLineIndex(Line.MatchingClosingBlockLineIndex),
@@ -212,7 +213,10 @@ private:
class TokenAnnotator {
public:
TokenAnnotator(const FormatStyle &Style, const AdditionalKeywords &Keywords)
- : Style(Style), Keywords(Keywords) {}
+ : Style(Style), IsCpp(Style.isCpp()),
+ LangOpts(getFormattingLangOpts(Style)), Keywords(Keywords) {
+ assert(IsCpp == LangOpts.CXXOperatorNames);
+ }
/// Adapts the indent levels of comment lines to the indent of the
/// subsequent line.
@@ -260,6 +264,9 @@ private:
const FormatStyle &Style;
+ bool IsCpp;
+ LangOptions LangOpts;
+
const AdditionalKeywords &Keywords;
SmallVector<ScopeType> Scopes;
diff --git a/contrib/llvm-project/clang/lib/Format/UnwrappedLineFormatter.cpp b/contrib/llvm-project/clang/lib/Format/UnwrappedLineFormatter.cpp
index adeb07243487..1804c1437fd4 100644
--- a/contrib/llvm-project/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/contrib/llvm-project/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -57,7 +57,7 @@ public:
/// Update the indent state given that \p Line is going to be formatted
/// next.
void nextLine(const AnnotatedLine &Line) {
- Offset = getIndentOffset(*Line.First);
+ Offset = getIndentOffset(Line);
// Update the indent level cache size so that we can rely on it
// having the right size in adjustToUnmodifiedline.
if (Line.Level >= IndentForLevel.size())
@@ -111,42 +111,41 @@ private:
///
/// For example, 'public:' labels in classes are offset by 1 or 2
/// characters to the left from their level.
- int getIndentOffset(const FormatToken &RootToken) {
+ int getIndentOffset(const AnnotatedLine &Line) {
if (Style.Language == FormatStyle::LK_Java || Style.isJavaScript() ||
Style.isCSharp()) {
return 0;
}
- auto IsAccessModifier = [this, &RootToken]() {
- if (RootToken.isAccessSpecifier(Style.isCpp())) {
+ auto IsAccessModifier = [&](const FormatToken &RootToken) {
+ if (Line.Type == LT_AccessModifier || RootToken.isObjCAccessSpecifier())
return true;
- } else if (RootToken.isObjCAccessSpecifier()) {
- return true;
- }
+
+ const auto *Next = RootToken.Next;
+
// Handle Qt signals.
- else if (RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) &&
- RootToken.Next && RootToken.Next->is(tok::colon)) {
- return true;
- } else if (RootToken.Next &&
- RootToken.Next->isOneOf(Keywords.kw_slots,
- Keywords.kw_qslots) &&
- RootToken.Next->Next && RootToken.Next->Next->is(tok::colon)) {
+ if (RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) &&
+ Next && Next->is(tok::colon)) {
return true;
}
- // Handle malformed access specifier e.g. 'private' without trailing ':'.
- else if (!RootToken.Next && RootToken.isAccessSpecifier(false)) {
+
+ if (Next && Next->isOneOf(Keywords.kw_slots, Keywords.kw_qslots) &&
+ Next->Next && Next->Next->is(tok::colon)) {
return true;
}
- return false;
+
+ // Handle malformed access specifier e.g. 'private' without trailing ':'.
+ return !Next && RootToken.isAccessSpecifier(false);
};
- if (IsAccessModifier()) {
+ if (IsAccessModifier(*Line.First)) {
// The AccessModifierOffset may be overridden by IndentAccessModifiers,
// in which case we take a negative value of the IndentWidth to simulate
// the upper indent level.
return Style.IndentAccessModifiers ? -Style.IndentWidth
: Style.AccessModifierOffset;
}
+
return 0;
}
@@ -515,6 +514,12 @@ private:
}
}
+ if (TheLine->First->is(TT_SwitchExpressionLabel)) {
+ return Style.AllowShortCaseExpressionOnASingleLine
+ ? tryMergeShortCaseLabels(I, E, Limit)
+ : 0;
+ }
+
if (TheLine->Last->is(tok::l_brace)) {
bool ShouldMerge = false;
// Try to merge records.
@@ -796,8 +801,12 @@ private:
}
}
- if (const auto *LastNonComment = Line.getLastNonComment();
- LastNonComment && LastNonComment->is(tok::l_brace)) {
+ if (Line.endsWith(tok::l_brace)) {
+ if (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never &&
+ Line.First->is(TT_BlockLBrace)) {
+ return 0;
+ }
+
if (IsSplitBlock && Line.First == Line.Last &&
I > AnnotatedLines.begin() &&
(I[-1]->endsWith(tok::kw_else) || IsCtrlStmt(*I[-1]))) {
@@ -1221,7 +1230,7 @@ private:
// While not empty, take first element and follow edges.
while (!Queue.empty()) {
// Quit if we still haven't found a solution by now.
- if (Count > 25000000)
+ if (Count > 25'000'000)
return 0;
Penalty = Queue.top().first.first;
@@ -1235,7 +1244,7 @@ private:
// Cut off the analysis of certain solutions if the analysis gets too
// complex. See description of IgnoreStackForComparison.
- if (Count > 50000)
+ if (Count > 50'000)
Node->State.IgnoreStackForComparison = true;
if (!Seen.insert(&Node->State).second) {
@@ -1469,11 +1478,13 @@ static auto computeNewlines(const AnnotatedLine &Line,
Newlines = std::min(Newlines, 1u);
if (Newlines == 0 && !RootToken.IsFirst)
Newlines = 1;
- if (RootToken.IsFirst && !RootToken.HasUnescapedNewline)
+ if (RootToken.IsFirst &&
+ (!Style.KeepEmptyLines.AtStartOfFile || !RootToken.HasUnescapedNewline)) {
Newlines = 0;
+ }
// Remove empty lines after "{".
- if (!Style.KeepEmptyLinesAtTheStartOfBlocks && PreviousLine &&
+ if (!Style.KeepEmptyLines.AtStartOfBlock && PreviousLine &&
PreviousLine->Last->is(tok::l_brace) &&
!PreviousLine->startsWithNamespace() &&
!(PrevPrevLine && PrevPrevLine->startsWithNamespace() &&
@@ -1545,9 +1556,9 @@ void UnwrappedLineFormatter::formatFirstToken(
unsigned NewlineIndent) {
FormatToken &RootToken = *Line.First;
if (RootToken.is(tok::eof)) {
- unsigned Newlines =
- std::min(RootToken.NewlinesBefore,
- Style.KeepEmptyLinesAtEOF ? Style.MaxEmptyLinesToKeep + 1 : 1);
+ unsigned Newlines = std::min(
+ RootToken.NewlinesBefore,
+ Style.KeepEmptyLines.AtEndOfFile ? Style.MaxEmptyLinesToKeep + 1 : 1);
unsigned TokenIndent = Newlines ? NewlineIndent : 0;
Whitespaces->replaceWhitespace(RootToken, Newlines, TokenIndent,
TokenIndent);
diff --git a/contrib/llvm-project/clang/lib/Format/UnwrappedLineFormatter.h b/contrib/llvm-project/clang/lib/Format/UnwrappedLineFormatter.h
index ee6d31de8c42..9b8acf427a2a 100644
--- a/contrib/llvm-project/clang/lib/Format/UnwrappedLineFormatter.h
+++ b/contrib/llvm-project/clang/lib/Format/UnwrappedLineFormatter.h
@@ -16,8 +16,6 @@
#define LLVM_CLANG_LIB_FORMAT_UNWRAPPEDLINEFORMATTER_H
#include "ContinuationIndenter.h"
-#include "clang/Format/Format.h"
-#include <map>
namespace clang {
namespace format {
diff --git a/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp b/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp
index f70affb732a0..d406a531a5c0 100644
--- a/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp
@@ -47,7 +47,8 @@ void printLine(llvm::raw_ostream &OS, const UnwrappedLine &Line,
OS << Prefix;
NewLine = false;
}
- OS << I->Tok->Tok.getName() << "[" << "T=" << (unsigned)I->Tok->getType()
+ OS << I->Tok->Tok.getName() << "["
+ << "T=" << (unsigned)I->Tok->getType()
<< ", OC=" << I->Tok->OriginalColumn << ", \"" << I->Tok->TokenText
<< "\"] ";
for (SmallVectorImpl<UnwrappedLine>::const_iterator
@@ -90,6 +91,12 @@ private:
} // end anonymous namespace
+std::ostream &operator<<(std::ostream &Stream, const UnwrappedLine &Line) {
+ llvm::raw_os_ostream OS(Stream);
+ printLine(OS, Line);
+ return Stream;
+}
+
class ScopedLineState {
public:
ScopedLineState(UnwrappedLineParser &Parser,
@@ -105,6 +112,7 @@ public:
Parser.Line->PPLevel = PreBlockLine->PPLevel;
Parser.Line->InPPDirective = PreBlockLine->InPPDirective;
Parser.Line->InMacroBody = PreBlockLine->InMacroBody;
+ Parser.Line->UnbracedBodyLevel = PreBlockLine->UnbracedBodyLevel;
}
~ScopedLineState() {
@@ -153,14 +161,17 @@ UnwrappedLineParser::UnwrappedLineParser(
llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator,
IdentifierTable &IdentTable)
: Line(new UnwrappedLine), MustBreakBeforeNextToken(false),
- CurrentLines(&Lines), Style(Style), Keywords(Keywords),
+ CurrentLines(&Lines), Style(Style), IsCpp(Style.isCpp()),
+ LangOpts(getFormattingLangOpts(Style)), Keywords(Keywords),
CommentPragmasRegex(Style.CommentPragmas), Tokens(nullptr),
Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1),
IncludeGuard(Style.IndentPPDirectives == FormatStyle::PPDIS_None
? IG_Rejected
: IG_Inited),
IncludeGuardToken(nullptr), FirstStartColumn(FirstStartColumn),
- Macros(Style.Macros, SourceMgr, Style, Allocator, IdentTable) {}
+ Macros(Style.Macros, SourceMgr, Style, Allocator, IdentTable) {
+ assert(IsCpp == LangOpts.CXXOperatorNames);
+}
void UnwrappedLineParser::reset() {
PPBranchLevel = -1;
@@ -357,13 +368,15 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace,
do {
if (FormatTok->isAttribute()) {
nextToken();
+ if (FormatTok->is(tok::l_paren))
+ parseParens();
continue;
}
- tok::TokenKind kind = FormatTok->Tok.getKind();
- if (FormatTok->getType() == TT_MacroBlockBegin)
- kind = tok::l_brace;
- else if (FormatTok->getType() == TT_MacroBlockEnd)
- kind = tok::r_brace;
+ tok::TokenKind Kind = FormatTok->Tok.getKind();
+ if (FormatTok->is(TT_MacroBlockBegin))
+ Kind = tok::l_brace;
+ else if (FormatTok->is(TT_MacroBlockEnd))
+ Kind = tok::r_brace;
auto ParseDefault = [this, OpeningBrace, IfKind, &IfLBrace, &HasDoWhile,
&HasLabel, &StatementCount] {
@@ -374,7 +387,7 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace,
assert(StatementCount > 0 && "StatementCount overflow!");
};
- switch (kind) {
+ switch (Kind) {
case tok::comment:
nextToken();
addUnwrappedLine();
@@ -389,9 +402,10 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace,
ParseDefault();
continue;
}
- if (!InRequiresExpression && FormatTok->isNot(TT_MacroBlockBegin) &&
- tryToParseBracedList()) {
- continue;
+ if (!InRequiresExpression && FormatTok->isNot(TT_MacroBlockBegin)) {
+ if (tryToParseBracedList())
+ continue;
+ FormatTok->setFinalizedType(TT_BlockLBrace);
}
parseBlock();
++StatementCount;
@@ -421,15 +435,11 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace,
break;
case tok::kw_default: {
unsigned StoredPosition = Tokens->getPosition();
- FormatToken *Next;
- do {
- Next = Tokens->getNextToken();
- assert(Next);
- } while (Next->is(tok::comment));
+ auto *Next = Tokens->getNextNonComment();
FormatTok = Tokens->setPosition(StoredPosition);
- if (Next->isNot(tok::colon)) {
- // default not followed by ':' is not a case label; treat it like
- // an identifier.
+ if (!Next->isOneOf(tok::colon, tok::arrow)) {
+ // default not followed by `:` or `->` is not a case label; treat it
+ // like an identifier.
parseStructuralElement();
break;
}
@@ -448,6 +458,7 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace,
}
if (!SwitchLabelEncountered &&
(Style.IndentCaseLabels ||
+ (OpeningBrace && OpeningBrace->is(TT_SwitchExpressionLBrace)) ||
(Line->InPPDirective && Line->Level == 1))) {
++Line->Level;
}
@@ -491,12 +502,9 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
assert(Tok->is(tok::l_brace));
do {
- FormatToken *NextTok;
- do {
- NextTok = Tokens->getNextToken();
- } while (NextTok->is(tok::comment));
+ auto *NextTok = Tokens->getNextNonComment();
- if (!Line->InMacroBody) {
+ if (!Line->InMacroBody && !Style.isTableGen()) {
// Skip PPDirective lines and comments.
while (NextTok->is(tok::hash)) {
do {
@@ -534,11 +542,11 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
case tok::r_brace:
if (LBraceStack.empty())
break;
- if (LBraceStack.back().Tok->is(BK_Unknown)) {
+ if (auto *LBrace = LBraceStack.back().Tok; LBrace->is(BK_Unknown)) {
bool ProbablyBracedList = false;
if (Style.Language == FormatStyle::LK_Proto) {
ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square);
- } else {
+ } else if (LBrace->isNot(TT_EnumLBrace)) {
// Using OriginalColumn to distinguish between ObjC methods and
// binary operators is a bit hacky.
bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) &&
@@ -552,14 +560,14 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
// If we already marked the opening brace as braced list, the closing
// must also be part of it.
- ProbablyBracedList = LBraceStack.back().Tok->is(TT_BracedListLBrace);
+ ProbablyBracedList = LBrace->is(TT_BracedListLBrace);
ProbablyBracedList = ProbablyBracedList ||
(Style.isJavaScript() &&
NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,
Keywords.kw_as));
- ProbablyBracedList = ProbablyBracedList ||
- (Style.isCpp() && NextTok->is(tok::l_paren));
+ ProbablyBracedList =
+ ProbablyBracedList || (IsCpp && NextTok->is(tok::l_paren));
// If there is a comma, semicolon or right paren after the closing
// brace, we assume this is a braced initializer list.
@@ -599,7 +607,7 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
}
// Cpp macro definition body that is a nonempty braced list or block:
- if (Style.isCpp() && Line->InMacroBody && PrevTok != FormatTok &&
+ if (IsCpp && Line->InMacroBody && PrevTok != FormatTok &&
!FormatTok->Previous && NextTok->is(tok::eof) &&
// A statement can end with only `;` (simple statement), a block
// closing brace (compound statement), or `:` (label statement).
@@ -608,13 +616,9 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
ProbablyBracedList = true;
}
}
- if (ProbablyBracedList) {
- Tok->setBlockKind(BK_BracedInit);
- LBraceStack.back().Tok->setBlockKind(BK_BracedInit);
- } else {
- Tok->setBlockKind(BK_Block);
- LBraceStack.back().Tok->setBlockKind(BK_Block);
- }
+ const auto BlockKind = ProbablyBracedList ? BK_BracedInit : BK_Block;
+ Tok->setBlockKind(BlockKind);
+ LBrace->setBlockKind(BlockKind);
}
LBraceStack.pop_back();
break;
@@ -819,8 +823,11 @@ FormatToken *UnwrappedLineParser::parseBlock(bool MustBeDeclaration,
return IfLBrace;
}
- if (FormatTok->is(tok::r_brace) && Tok->is(TT_NamespaceLBrace))
- FormatTok->setFinalizedType(TT_NamespaceRBrace);
+ if (FormatTok->is(tok::r_brace)) {
+ FormatTok->setBlockKind(BK_Block);
+ if (Tok->is(TT_NamespaceLBrace))
+ FormatTok->setFinalizedType(TT_NamespaceRBrace);
+ }
const bool IsFunctionRBrace =
FormatTok->is(tok::r_brace) && Tok->is(TT_FunctionLBrace);
@@ -1177,20 +1184,14 @@ void UnwrappedLineParser::parsePPDefine() {
Line->InMacroBody = true;
if (Style.SkipMacroDefinitionBody) {
- do {
+ while (!eof()) {
FormatTok->Finalized = true;
- nextToken();
- } while (!eof());
+ FormatTok = Tokens->getNextToken();
+ }
addUnwrappedLine();
return;
}
- if (FormatTok->is(tok::identifier) &&
- Tokens->peekNextToken()->is(tok::colon)) {
- nextToken();
- nextToken();
- }
-
// 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
@@ -1219,7 +1220,6 @@ void UnwrappedLineParser::parsePPUnknown() {
static bool tokenCanStartNewLine(const FormatToken &Tok) {
// Semicolon can be a null-statement, l_square can be a start of a macro or
// a C++11 attribute, but this doesn't seem to be common.
- assert(Tok.isNot(TT_AttributeSquare));
return !Tok.isOneOf(tok::semi, tok::l_brace,
// Tokens that can only be used as binary operators and a
// part of overloaded operator names.
@@ -1425,7 +1425,7 @@ void UnwrappedLineParser::parseStructuralElement(
return;
}
- if (Style.isCpp()) {
+ if (IsCpp) {
while (FormatTok->is(tok::l_square) && handleCppAttributes()) {
}
} else if (Style.isVerilog()) {
@@ -1458,6 +1458,15 @@ void UnwrappedLineParser::parseStructuralElement(
}
// Tokens that only make sense at the beginning of a line.
+ if (FormatTok->isAccessSpecifierKeyword()) {
+ if (Style.Language == FormatStyle::LK_Java || Style.isJavaScript() ||
+ Style.isCSharp()) {
+ nextToken();
+ } else {
+ parseAccessSpecifier();
+ }
+ return;
+ }
switch (FormatTok->Tok.getKind()) {
case tok::kw_asm:
nextToken();
@@ -1479,16 +1488,6 @@ void UnwrappedLineParser::parseStructuralElement(
case tok::kw_namespace:
parseNamespace();
return;
- case tok::kw_public:
- case tok::kw_protected:
- case tok::kw_private:
- if (Style.Language == FormatStyle::LK_Java || Style.isJavaScript() ||
- Style.isCSharp()) {
- nextToken();
- } else {
- parseAccessSpecifier();
- }
- return;
case tok::kw_if: {
if (Style.isJavaScript() && Line->MustBeDeclaration) {
// field/method declaration.
@@ -1521,9 +1520,9 @@ void UnwrappedLineParser::parseStructuralElement(
// 'switch: string' field declaration.
break;
}
- parseSwitch();
+ parseSwitch(/*IsExpr=*/false);
return;
- case tok::kw_default:
+ case tok::kw_default: {
// In Verilog default along with other labels are handled in the next loop.
if (Style.isVerilog())
break;
@@ -1531,14 +1530,22 @@ void UnwrappedLineParser::parseStructuralElement(
// 'default: string' field declaration.
break;
}
+ auto *Default = FormatTok;
nextToken();
if (FormatTok->is(tok::colon)) {
FormatTok->setFinalizedType(TT_CaseLabelColon);
parseLabel();
return;
}
+ if (FormatTok->is(tok::arrow)) {
+ FormatTok->setFinalizedType(TT_CaseLabelArrow);
+ Default->setFinalizedType(TT_SwitchExpressionLabel);
+ parseLabel();
+ return;
+ }
// e.g. "default void f() {}" in a Java interface.
break;
+ }
case tok::kw_case:
// Proto: there are no switch/case statements.
if (Style.Language == FormatStyle::LK_Proto) {
@@ -1599,7 +1606,7 @@ void UnwrappedLineParser::parseStructuralElement(
parseJavaScriptEs6ImportExport();
return;
}
- if (Style.isCpp()) {
+ if (IsCpp) {
nextToken();
if (FormatTok->is(tok::kw_namespace)) {
parseNamespace();
@@ -1643,12 +1650,11 @@ void UnwrappedLineParser::parseStructuralElement(
addUnwrappedLine();
return;
}
- if (Style.isCpp() && parseModuleImport())
+ if (IsCpp && parseModuleImport())
return;
}
- if (Style.isCpp() &&
- FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,
- Keywords.kw_slots, Keywords.kw_qslots)) {
+ if (IsCpp && FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,
+ Keywords.kw_slots, Keywords.kw_qslots)) {
nextToken();
if (FormatTok->is(tok::colon)) {
nextToken();
@@ -1656,11 +1662,11 @@ void UnwrappedLineParser::parseStructuralElement(
return;
}
}
- if (Style.isCpp() && FormatTok->is(TT_StatementMacro)) {
+ if (IsCpp && FormatTok->is(TT_StatementMacro)) {
parseStatementMacro();
return;
}
- if (Style.isCpp() && FormatTok->is(TT_NamespaceMacro)) {
+ if (IsCpp && FormatTok->is(TT_NamespaceMacro)) {
parseNamespace();
return;
}
@@ -1671,7 +1677,8 @@ void UnwrappedLineParser::parseStructuralElement(
if (!Style.isJavaScript() && !Style.isVerilog() && !Style.isTableGen() &&
Tokens->peekNextToken()->is(tok::colon) && !Line->MustBeDeclaration) {
nextToken();
- Line->Tokens.begin()->Tok->MustBreakBefore = true;
+ if (!Line->InMacroBody || CurrentLines->size() > 1)
+ Line->Tokens.begin()->Tok->MustBreakBefore = true;
FormatTok->setFinalizedType(TT_GotoLabelColon);
parseLabel(!Style.IndentGotoLabels);
if (HasLabel)
@@ -1684,9 +1691,15 @@ void UnwrappedLineParser::parseStructuralElement(
break;
}
- const bool InRequiresExpression =
- OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace);
- do {
+ for (const bool InRequiresExpression =
+ OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace);
+ !eof();) {
+ if (IsCpp && FormatTok->isCppAlternativeOperatorKeyword()) {
+ if (auto *Next = Tokens->peekNextToken(/*SkipComment=*/true);
+ Next && Next->isBinaryOperator()) {
+ FormatTok->Tok.setKind(tok::identifier);
+ }
+ }
const FormatToken *Previous = FormatTok->Previous;
switch (FormatTok->Tok.getKind()) {
case tok::at:
@@ -1756,7 +1769,7 @@ void UnwrappedLineParser::parseStructuralElement(
}
break;
case tok::kw_requires: {
- if (Style.isCpp()) {
+ if (IsCpp) {
bool ParsedClause = parseRequires();
if (ParsedClause)
return;
@@ -1766,8 +1779,9 @@ void UnwrappedLineParser::parseStructuralElement(
break;
}
case tok::kw_enum:
- // Ignore if this is part of "template <enum ...".
- if (Previous && Previous->is(tok::less)) {
+ // Ignore if this is part of "template <enum ..." or "... -> enum" or
+ // "template <..., enum ...>".
+ if (Previous && Previous->isOneOf(tok::less, tok::arrow, tok::comma)) {
nextToken();
break;
}
@@ -1777,7 +1791,7 @@ void UnwrappedLineParser::parseStructuralElement(
if (!parseEnum())
break;
// This only applies to C++ and Verilog.
- if (!Style.isCpp() && !Style.isVerilog()) {
+ if (!IsCpp && !Style.isVerilog()) {
addUnwrappedLine();
return;
}
@@ -1845,7 +1859,7 @@ void UnwrappedLineParser::parseStructuralElement(
parseParens();
// Break the unwrapped line if a K&R C function definition has a parameter
// declaration.
- if (OpeningBrace || !Style.isCpp() || !Previous || eof())
+ if (OpeningBrace || !IsCpp || !Previous || eof())
break;
if (isC78ParameterDecl(FormatTok,
Tokens->peekNextToken(/*SkipComment=*/true),
@@ -1863,8 +1877,7 @@ void UnwrappedLineParser::parseStructuralElement(
case tok::caret:
nextToken();
// Block return type.
- if (FormatTok->Tok.isAnyIdentifier() ||
- FormatTok->isSimpleTypeSpecifier()) {
+ if (FormatTok->Tok.isAnyIdentifier() || FormatTok->isTypeName(LangOpts)) {
nextToken();
// Return types: pointers are ok too.
while (FormatTok->is(tok::star))
@@ -1897,7 +1910,8 @@ void UnwrappedLineParser::parseStructuralElement(
} else if (Style.BraceWrapping.AfterFunction) {
addUnwrappedLine();
}
- FormatTok->setFinalizedType(TT_FunctionLBrace);
+ if (!Previous || Previous->isNot(TT_TypeDeclarationParen))
+ FormatTok->setFinalizedType(TT_FunctionLBrace);
parseBlock();
IsDecltypeAutoFunction = false;
addUnwrappedLine();
@@ -1974,13 +1988,13 @@ void UnwrappedLineParser::parseStructuralElement(
}
}
- if (!Style.isCpp() && FormatTok->is(Keywords.kw_interface)) {
+ if (!IsCpp && FormatTok->is(Keywords.kw_interface)) {
if (parseStructLike())
return;
break;
}
- if (Style.isCpp() && FormatTok->is(TT_StatementMacro)) {
+ if (IsCpp && FormatTok->is(TT_StatementMacro)) {
parseStatementMacro();
return;
}
@@ -2065,6 +2079,11 @@ void UnwrappedLineParser::parseStructuralElement(
case tok::kw_new:
parseNew();
break;
+ case tok::kw_switch:
+ if (Style.Language == FormatStyle::LK_Java)
+ parseSwitch(/*IsExpr=*/true);
+ nextToken();
+ break;
case tok::kw_case:
// Proto: there are no switch/case statements.
if (Style.Language == FormatStyle::LK_Proto) {
@@ -2112,7 +2131,7 @@ void UnwrappedLineParser::parseStructuralElement(
nextToken();
break;
}
- } while (!eof());
+ }
}
bool UnwrappedLineParser::tryToParsePropertyAccessor() {
@@ -2137,8 +2156,8 @@ bool UnwrappedLineParser::tryToParsePropertyAccessor() {
bool HasSpecialAccessor = false;
bool IsTrivialPropertyAccessor = true;
while (!eof()) {
- if (Tok->isOneOf(tok::semi, tok::kw_public, tok::kw_private,
- tok::kw_protected, Keywords.kw_internal, Keywords.kw_get,
+ if (Tok->isAccessSpecifierKeyword() ||
+ Tok->isOneOf(tok::semi, Keywords.kw_internal, Keywords.kw_get,
Keywords.kw_init, Keywords.kw_set)) {
if (Tok->isOneOf(Keywords.kw_get, Keywords.kw_init, Keywords.kw_set))
HasSpecialAccessor = true;
@@ -2208,7 +2227,7 @@ bool UnwrappedLineParser::tryToParsePropertyAccessor() {
bool UnwrappedLineParser::tryToParseLambda() {
assert(FormatTok->is(tok::l_square));
- if (!Style.isCpp()) {
+ if (!IsCpp) {
nextToken();
return false;
}
@@ -2220,7 +2239,7 @@ bool UnwrappedLineParser::tryToParseLambda() {
bool InTemplateParameterList = false;
while (FormatTok->isNot(tok::l_brace)) {
- if (FormatTok->isSimpleTypeSpecifier()) {
+ if (FormatTok->isTypeName(LangOpts) || FormatTok->isAttribute()) {
nextToken();
continue;
}
@@ -2241,6 +2260,8 @@ bool UnwrappedLineParser::tryToParseLambda() {
break;
case tok::kw_auto:
case tok::kw_class:
+ case tok::kw_struct:
+ case tok::kw_union:
case tok::kw_template:
case tok::kw_typename:
case tok::amp:
@@ -2337,7 +2358,7 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
!Previous->isOneOf(tok::kw_return, tok::kw_co_await,
tok::kw_co_yield, tok::kw_co_return)) ||
Previous->closesScope())) ||
- LeftSquare->isCppStructuredBinding(Style)) {
+ LeftSquare->isCppStructuredBinding(IsCpp)) {
return false;
}
if (FormatTok->is(tok::l_square) || tok::isLiteral(FormatTok->Tok.getKind()))
@@ -2418,6 +2439,7 @@ bool UnwrappedLineParser::tryToParseChildBlock() {
}
bool UnwrappedLineParser::parseBracedList(bool IsAngleBracket, bool IsEnum) {
+ assert(!IsAngleBracket || !IsEnum);
bool HasError = false;
// FIXME: Once we have an expression parser in the UnwrappedLineParser,
@@ -2440,8 +2462,11 @@ bool UnwrappedLineParser::parseBracedList(bool IsAngleBracket, bool IsEnum) {
}
}
if (FormatTok->is(IsAngleBracket ? tok::greater : tok::r_brace)) {
- if (IsEnum && !Style.AllowShortEnumsOnASingleLine)
- addUnwrappedLine();
+ if (IsEnum) {
+ FormatTok->setBlockKind(BK_Block);
+ if (!Style.AllowShortEnumsOnASingleLine)
+ addUnwrappedLine();
+ }
nextToken();
return !HasError;
}
@@ -2521,10 +2546,10 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) {
if (Style.Language == FormatStyle::LK_Java && FormatTok->is(tok::l_brace))
parseChildBlock();
break;
- case tok::r_paren:
+ case tok::r_paren: {
+ const auto *Prev = LeftParen->Previous;
if (!MightBeStmtExpr && !MightBeFoldExpr && !Line->InMacroBody &&
Style.RemoveParentheses > FormatStyle::RPS_Leave) {
- const auto *Prev = LeftParen->Previous;
const auto *Next = Tokens->peekNextToken();
const bool DoubleParens =
Prev && Prev->is(tok::l_paren) && Next && Next->is(tok::r_paren);
@@ -2546,8 +2571,13 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) {
FormatTok->Optional = true;
}
}
+ if (Prev && Prev->is(TT_TypenameMacro)) {
+ LeftParen->setFinalizedType(TT_TypeDeclarationParen);
+ FormatTok->setFinalizedType(TT_TypeDeclarationParen);
+ }
nextToken();
return SeenEqual;
+ }
case tok::r_brace:
// A "}" inside parenthesis is an error if there wasn't a matching "{".
return SeenEqual;
@@ -2588,6 +2618,9 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) {
else
nextToken();
break;
+ case tok::kw_switch:
+ parseSwitch(/*IsExpr=*/true);
+ break;
case tok::kw_requires: {
auto RequiresToken = FormatTok;
nextToken();
@@ -2683,7 +2716,9 @@ void UnwrappedLineParser::parseUnbracedBody(bool CheckEOF) {
addUnwrappedLine();
++Line->Level;
+ ++Line->UnbracedBodyLevel;
parseStructuralElement();
+ --Line->UnbracedBodyLevel;
if (Tok) {
assert(!Line->InPPDirective);
@@ -2926,9 +2961,15 @@ void UnwrappedLineParser::parseTryCatch() {
assert(FormatTok->isOneOf(tok::kw_try, tok::kw___try) && "'try' expected");
nextToken();
bool NeedsUnwrappedLine = false;
+ bool HasCtorInitializer = false;
if (FormatTok->is(tok::colon)) {
+ auto *Colon = FormatTok;
// We are in a function try block, what comes is an initializer list.
nextToken();
+ if (FormatTok->is(tok::identifier)) {
+ HasCtorInitializer = true;
+ Colon->setFinalizedType(TT_CtorInitializerColon);
+ }
// In case identifiers were removed by clang-tidy, what might follow is
// multiple commas in sequence - before the first identifier.
@@ -2937,14 +2978,11 @@ void UnwrappedLineParser::parseTryCatch() {
while (FormatTok->is(tok::identifier)) {
nextToken();
- if (FormatTok->is(tok::l_paren))
+ if (FormatTok->is(tok::l_paren)) {
parseParens();
- if (FormatTok->Previous && FormatTok->Previous->is(tok::identifier) &&
- FormatTok->is(tok::l_brace)) {
- do {
- nextToken();
- } while (FormatTok->isNot(tok::r_brace));
+ } else if (FormatTok->is(tok::l_brace)) {
nextToken();
+ parseBracedList();
}
// In case identifiers were removed by clang-tidy, what might follow is
@@ -2960,6 +2998,8 @@ void UnwrappedLineParser::parseTryCatch() {
keepAncestorBraces();
if (FormatTok->is(tok::l_brace)) {
+ if (HasCtorInitializer)
+ FormatTok->setFinalizedType(TT_FunctionLBrace);
CompoundStatementIndenter Indenter(this, Style, Line->Level);
parseBlock();
if (Style.BraceWrapping.BeforeCatch)
@@ -3155,7 +3195,7 @@ void UnwrappedLineParser::parseForOrWhileLoop(bool HasParens) {
// JS' for await ( ...
if (Style.isJavaScript() && FormatTok->is(Keywords.kw_await))
nextToken();
- if (Style.isCpp() && FormatTok->is(tok::kw_co_await))
+ if (IsCpp && FormatTok->is(tok::kw_co_await))
nextToken();
if (HasParens && FormatTok->is(tok::l_paren)) {
// The type is only set for Verilog basically because we were afraid to
@@ -3206,10 +3246,11 @@ void UnwrappedLineParser::parseDoWhile() {
void UnwrappedLineParser::parseLabel(bool LeftAlignLabel) {
nextToken();
unsigned OldLineLevel = Line->Level;
- if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0))
- --Line->Level;
+
if (LeftAlignLabel)
Line->Level = 0;
+ else if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0))
+ --Line->Level;
if (!Style.IndentCaseBlocks && CommentsBeforeNextToken.empty() &&
FormatTok->is(tok::l_brace)) {
@@ -3244,6 +3285,7 @@ void UnwrappedLineParser::parseLabel(bool LeftAlignLabel) {
void UnwrappedLineParser::parseCaseLabel() {
assert(FormatTok->is(tok::kw_case) && "'case' expected");
+ auto *Case = FormatTok;
// FIXME: fix handling of complex expressions here.
do {
@@ -3252,11 +3294,16 @@ void UnwrappedLineParser::parseCaseLabel() {
FormatTok->setFinalizedType(TT_CaseLabelColon);
break;
}
+ if (Style.Language == FormatStyle::LK_Java && FormatTok->is(tok::arrow)) {
+ FormatTok->setFinalizedType(TT_CaseLabelArrow);
+ Case->setFinalizedType(TT_SwitchExpressionLabel);
+ break;
+ }
} while (!eof());
parseLabel();
}
-void UnwrappedLineParser::parseSwitch() {
+void UnwrappedLineParser::parseSwitch(bool IsExpr) {
assert(FormatTok->is(tok::kw_switch) && "'switch' expected");
nextToken();
if (FormatTok->is(tok::l_paren))
@@ -3266,10 +3313,15 @@ void UnwrappedLineParser::parseSwitch() {
if (FormatTok->is(tok::l_brace)) {
CompoundStatementIndenter Indenter(this, Style, Line->Level);
- FormatTok->setFinalizedType(TT_ControlStatementLBrace);
- parseBlock();
+ FormatTok->setFinalizedType(IsExpr ? TT_SwitchExpressionLBrace
+ : TT_ControlStatementLBrace);
+ if (IsExpr)
+ parseChildBlock();
+ else
+ parseBlock();
setPreviousRBraceType(TT_ControlStatementRBrace);
- addUnwrappedLine();
+ if (!IsExpr)
+ addUnwrappedLine();
} else {
addUnwrappedLine();
++Line->Level;
@@ -3282,8 +3334,8 @@ void UnwrappedLineParser::parseSwitch() {
}
// Operators that can follow a C variable.
-static bool isCOperatorFollowingVar(tok::TokenKind kind) {
- switch (kind) {
+static bool isCOperatorFollowingVar(tok::TokenKind Kind) {
+ switch (Kind) {
case tok::ampamp:
case tok::ampequal:
case tok::arrow:
@@ -3355,7 +3407,7 @@ void UnwrappedLineParser::parseAccessSpecifier() {
/// \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.
-bool clang::format::UnwrappedLineParser::parseRequires() {
+bool UnwrappedLineParser::parseRequires() {
assert(FormatTok->is(tok::kw_requires) && "'requires' expected");
auto RequiresToken = FormatTok;
@@ -3418,7 +3470,7 @@ bool clang::format::UnwrappedLineParser::parseRequires() {
break;
}
default:
- if (PreviousNonComment->isTypeOrIdentifier()) {
+ if (PreviousNonComment->isTypeOrIdentifier(LangOpts)) {
// This is a requires clause.
parseRequiresClause(RequiresToken);
return true;
@@ -3457,11 +3509,6 @@ bool clang::format::UnwrappedLineParser::parseRequires() {
return false;
}
break;
- case tok::r_paren:
- case tok::pipepipe:
- FormatTok = Tokens->setPosition(StoredPosition);
- parseRequiresClause(RequiresToken);
- return true;
case tok::eof:
// Break out of the loop.
Lookahead = 50;
@@ -3469,6 +3516,7 @@ bool clang::format::UnwrappedLineParser::parseRequires() {
case tok::coloncolon:
LastWasColonColon = true;
break;
+ case tok::kw_decltype:
case tok::identifier:
if (FoundType && !LastWasColonColon && OpenAngles == 0) {
FormatTok = Tokens->setPosition(StoredPosition);
@@ -3485,7 +3533,7 @@ bool clang::format::UnwrappedLineParser::parseRequires() {
--OpenAngles;
break;
default:
- if (NextToken->isSimpleTypeSpecifier()) {
+ if (NextToken->isTypeName(LangOpts)) {
FormatTok = Tokens->setPosition(StoredPosition);
parseRequiresExpression(RequiresToken);
return false;
@@ -3718,14 +3766,19 @@ bool UnwrappedLineParser::parseEnum() {
if (Style.Language == FormatStyle::LK_Proto && FormatTok->is(tok::equal))
return false;
- // Eat up enum class ...
- if (FormatTok->isOneOf(tok::kw_class, tok::kw_struct))
- nextToken();
+ if (IsCpp) {
+ // Eat up enum class ...
+ if (FormatTok->isOneOf(tok::kw_class, tok::kw_struct))
+ nextToken();
+ while (FormatTok->is(tok::l_square))
+ if (!handleCppAttributes())
+ return false;
+ }
while (FormatTok->Tok.getIdentifierInfo() ||
FormatTok->isOneOf(tok::colon, tok::coloncolon, tok::less,
tok::greater, tok::comma, tok::question,
- tok::l_square, tok::r_square)) {
+ tok::l_square)) {
if (Style.isVerilog()) {
FormatTok->setFinalizedType(TT_VerilogDimensionedTypeName);
nextToken();
@@ -3738,12 +3791,11 @@ bool UnwrappedLineParser::parseEnum() {
// We can have macros or attributes in between 'enum' and the enum name.
if (FormatTok->is(tok::l_paren))
parseParens();
- assert(FormatTok->isNot(TT_AttributeSquare));
if (FormatTok->is(tok::identifier)) {
nextToken();
// If there are two identifiers in a row, this is likely an elaborate
// return type. In Java, this can be "implements", etc.
- if (Style.isCpp() && FormatTok->is(tok::identifier))
+ if (IsCpp && FormatTok->is(tok::identifier))
return false;
}
}
@@ -3918,6 +3970,8 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
const FormatToken &InitialToken = *FormatTok;
nextToken();
+ const FormatToken *ClassName = nullptr;
+ bool IsDerived = false;
auto IsNonMacroIdentifier = [](const FormatToken *Tok) {
return Tok->is(tok::identifier) && Tok->TokenText != Tok->TokenText.upper();
};
@@ -3942,14 +3996,37 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
}
if (FormatTok->is(tok::l_square) && handleCppAttributes())
continue;
+ const auto *Previous = FormatTok;
nextToken();
- // We can have macros in between 'class' and the class name.
- if (!IsNonMacroIdentifier(FormatTok->Previous) &&
- FormatTok->is(tok::l_paren)) {
- parseParens();
+ switch (FormatTok->Tok.getKind()) {
+ case tok::l_paren:
+ // We can have macros in between 'class' and the class name.
+ if (!IsNonMacroIdentifier(Previous) ||
+ // e.g. `struct macro(a) S { int i; };`
+ Previous->Previous == &InitialToken) {
+ parseParens();
+ }
+ break;
+ case tok::coloncolon:
+ break;
+ default:
+ if (!ClassName && Previous->is(tok::identifier) &&
+ Previous->isNot(TT_AttributeMacro)) {
+ ClassName = Previous;
+ }
}
}
+ auto IsListInitialization = [&] {
+ if (!ClassName || IsDerived)
+ return false;
+ assert(FormatTok->is(tok::l_brace));
+ const auto *Prev = FormatTok->getPreviousNonComment();
+ assert(Prev);
+ return Prev != ClassName && Prev->is(tok::identifier) &&
+ Prev->isNot(Keywords.kw_final) && tryToParseBracedList();
+ };
+
if (FormatTok->isOneOf(tok::colon, tok::less)) {
int AngleNestingLevel = 0;
do {
@@ -3958,19 +4035,28 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
else if (FormatTok->is(tok::greater))
--AngleNestingLevel;
- if (AngleNestingLevel == 0 && FormatTok->is(tok::l_paren) &&
- IsNonMacroIdentifier(FormatTok->Previous)) {
- break;
+ if (AngleNestingLevel == 0) {
+ if (FormatTok->is(tok::colon)) {
+ IsDerived = true;
+ } else if (FormatTok->is(tok::identifier) &&
+ FormatTok->Previous->is(tok::coloncolon)) {
+ ClassName = FormatTok;
+ } else if (FormatTok->is(tok::l_paren) &&
+ IsNonMacroIdentifier(FormatTok->Previous)) {
+ break;
+ }
}
if (FormatTok->is(tok::l_brace)) {
+ if (AngleNestingLevel == 0 && IsListInitialization())
+ return;
calculateBraceTypes(/*ExpectClassBody=*/true);
if (!tryToParseBracedList())
break;
}
if (FormatTok->is(tok::l_square)) {
FormatToken *Previous = FormatTok->Previous;
- if (!Previous ||
- !(Previous->is(tok::r_paren) || Previous->isTypeOrIdentifier())) {
+ if (!Previous || (Previous->isNot(tok::r_paren) &&
+ !Previous->isTypeOrIdentifier(LangOpts))) {
// Don't try parsing a lambda if we had a closing parenthesis before,
// it was probably a pointer to an array: int (*)[].
if (!tryToParseLambda())
@@ -4007,6 +4093,8 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
}
};
if (FormatTok->is(tok::l_brace)) {
+ if (IsListInitialization())
+ return;
auto [OpenBraceType, ClosingBraceType] = GetBraceTypes(InitialToken);
FormatTok->setFinalizedType(OpenBraceType);
if (ParseAsExpr) {
@@ -4711,14 +4799,13 @@ void UnwrappedLineParser::readToken(int LevelDifference) {
do {
FormatTok = Tokens->getNextToken();
assert(FormatTok);
- while (FormatTok->getType() == TT_ConflictStart ||
- FormatTok->getType() == TT_ConflictEnd ||
- FormatTok->getType() == TT_ConflictAlternative) {
- if (FormatTok->getType() == TT_ConflictStart)
+ while (FormatTok->isOneOf(TT_ConflictStart, TT_ConflictEnd,
+ TT_ConflictAlternative)) {
+ if (FormatTok->is(TT_ConflictStart))
conditionalCompilationStart(/*Unreachable=*/false);
- else if (FormatTok->getType() == TT_ConflictAlternative)
+ else if (FormatTok->is(TT_ConflictAlternative))
conditionalCompilationAlternative();
- else if (FormatTok->getType() == TT_ConflictEnd)
+ else if (FormatTok->is(TT_ConflictEnd))
conditionalCompilationEnd();
FormatTok = Tokens->getNextToken();
FormatTok->MustBreakBefore = true;
@@ -4764,6 +4851,8 @@ void UnwrappedLineParser::readToken(int LevelDifference) {
PPBranchLevel > 0) {
Line->Level += PPBranchLevel;
}
+ assert(Line->Level >= Line->UnbracedBodyLevel);
+ Line->Level -= Line->UnbracedBodyLevel;
flushComments(isOnNewLine(*FormatTok));
parsePPDirective();
PreviousWasComment = FormatTok->is(tok::comment);
diff --git a/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.h b/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.h
index 739298690bbd..d5eeb3d57149 100644
--- a/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.h
+++ b/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.h
@@ -15,17 +15,8 @@
#ifndef LLVM_CLANG_LIB_FORMAT_UNWRAPPEDLINEPARSER_H
#define LLVM_CLANG_LIB_FORMAT_UNWRAPPEDLINEPARSER_H
-#include "Encoding.h"
-#include "FormatToken.h"
#include "Macros.h"
-#include "clang/Basic/IdentifierTable.h"
-#include "clang/Format/Format.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/BitVector.h"
-#include "llvm/Support/Regex.h"
-#include <list>
#include <stack>
-#include <vector>
namespace clang {
namespace format {
@@ -58,6 +49,9 @@ struct UnwrappedLine {
/// Whether it is part of a macro body.
bool InMacroBody = false;
+ /// Nesting level of unbraced body of a control statement.
+ unsigned UnbracedBodyLevel = 0;
+
bool MustBeDeclaration = false;
/// Whether the parser has seen \c decltype(auto) in this line.
@@ -166,7 +160,7 @@ private:
void parseDoWhile();
void parseLabel(bool LeftAlignLabel = false);
void parseCaseLabel();
- void parseSwitch();
+ void parseSwitch(bool IsExpr);
void parseNamespace();
bool parseModuleImport();
void parseNew();
@@ -324,6 +318,8 @@ private:
llvm::BitVector DeclarationScopeStack;
const FormatStyle &Style;
+ bool IsCpp;
+ LangOptions LangOpts;
const AdditionalKeywords &Keywords;
llvm::Regex CommentPragmasRegex;
@@ -420,6 +416,8 @@ struct UnwrappedLineNode {
SmallVector<UnwrappedLine, 0> Children;
};
+std::ostream &operator<<(std::ostream &Stream, const UnwrappedLine &Line);
+
} // end namespace format
} // end namespace clang
diff --git a/contrib/llvm-project/clang/lib/Format/WhitespaceManager.cpp b/contrib/llvm-project/clang/lib/Format/WhitespaceManager.cpp
index 7525e6ee650b..a31874a7c319 100644
--- a/contrib/llvm-project/clang/lib/Format/WhitespaceManager.cpp
+++ b/contrib/llvm-project/clang/lib/Format/WhitespaceManager.cpp
@@ -107,10 +107,16 @@ const tooling::Replacements &WhitespaceManager::generateReplacements() {
llvm::sort(Changes, Change::IsBeforeInFile(SourceMgr));
calculateLineBreakInformation();
alignConsecutiveMacros();
- alignConsecutiveShortCaseStatements();
+ alignConsecutiveShortCaseStatements(/*IsExpr=*/true);
+ alignConsecutiveShortCaseStatements(/*IsExpr=*/false);
alignConsecutiveDeclarations();
alignConsecutiveBitFields();
alignConsecutiveAssignments();
+ if (Style.isTableGen()) {
+ alignConsecutiveTableGenBreakingDAGArgColons();
+ alignConsecutiveTableGenCondOperatorColons();
+ alignConsecutiveTableGenDefinitions();
+ }
alignChainedConditionals();
alignTrailingComments();
alignEscapedNewlines();
@@ -123,11 +129,14 @@ const tooling::Replacements &WhitespaceManager::generateReplacements() {
void WhitespaceManager::calculateLineBreakInformation() {
Changes[0].PreviousEndOfTokenColumn = 0;
Change *LastOutsideTokenChange = &Changes[0];
- for (unsigned i = 1, e = Changes.size(); i != e; ++i) {
+ for (unsigned I = 1, e = Changes.size(); I != e; ++I) {
+ auto &C = Changes[I];
+ auto &P = Changes[I - 1];
+ auto &PrevTokLength = P.TokenLength;
SourceLocation OriginalWhitespaceStart =
- Changes[i].OriginalWhitespaceRange.getBegin();
+ C.OriginalWhitespaceRange.getBegin();
SourceLocation PreviousOriginalWhitespaceEnd =
- Changes[i - 1].OriginalWhitespaceRange.getEnd();
+ P.OriginalWhitespaceRange.getEnd();
unsigned OriginalWhitespaceStartOffset =
SourceMgr.getFileOffset(OriginalWhitespaceStart);
unsigned PreviousOriginalWhitespaceEndOffset =
@@ -162,31 +171,28 @@ void WhitespaceManager::calculateLineBreakInformation() {
// line of the token.
auto NewlinePos = Text.find_first_of('\n');
if (NewlinePos == StringRef::npos) {
- Changes[i - 1].TokenLength = OriginalWhitespaceStartOffset -
- PreviousOriginalWhitespaceEndOffset +
- Changes[i].PreviousLinePostfix.size() +
- Changes[i - 1].CurrentLinePrefix.size();
+ PrevTokLength = OriginalWhitespaceStartOffset -
+ PreviousOriginalWhitespaceEndOffset +
+ C.PreviousLinePostfix.size() + P.CurrentLinePrefix.size();
+ if (!P.IsInsideToken)
+ PrevTokLength = std::min(PrevTokLength, P.Tok->ColumnWidth);
} else {
- Changes[i - 1].TokenLength =
- NewlinePos + Changes[i - 1].CurrentLinePrefix.size();
+ PrevTokLength = NewlinePos + P.CurrentLinePrefix.size();
}
// If there are multiple changes in this token, sum up all the changes until
// the end of the line.
- if (Changes[i - 1].IsInsideToken && Changes[i - 1].NewlinesBefore == 0) {
- LastOutsideTokenChange->TokenLength +=
- Changes[i - 1].TokenLength + Changes[i - 1].Spaces;
- } else {
- LastOutsideTokenChange = &Changes[i - 1];
- }
+ if (P.IsInsideToken && P.NewlinesBefore == 0)
+ LastOutsideTokenChange->TokenLength += PrevTokLength + P.Spaces;
+ else
+ LastOutsideTokenChange = &P;
- Changes[i].PreviousEndOfTokenColumn =
- Changes[i - 1].StartOfTokenColumn + Changes[i - 1].TokenLength;
+ C.PreviousEndOfTokenColumn = P.StartOfTokenColumn + PrevTokLength;
- Changes[i - 1].IsTrailingComment =
- (Changes[i].NewlinesBefore > 0 || Changes[i].Tok->is(tok::eof) ||
- (Changes[i].IsInsideToken && Changes[i].Tok->is(tok::comment))) &&
- Changes[i - 1].Tok->is(tok::comment) &&
+ P.IsTrailingComment =
+ (C.NewlinesBefore > 0 || C.Tok->is(tok::eof) ||
+ (C.IsInsideToken && C.Tok->is(tok::comment))) &&
+ P.Tok->is(tok::comment) &&
// FIXME: This is a dirty hack. The problem is that
// BreakableLineCommentSection does comment reflow changes and here is
// the aligning of trailing comments. Consider the case where we reflow
@@ -459,16 +465,16 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
if (i + 1 != Changes.size())
Changes[i + 1].PreviousEndOfTokenColumn += Shift;
- // If PointerAlignment is PAS_Right, keep *s or &s next to the token
+ // If PointerAlignment is PAS_Right, keep *s or &s next to the token,
+ // except if the token is equal, then a space is needed.
if ((Style.PointerAlignment == FormatStyle::PAS_Right ||
Style.ReferenceAlignment == FormatStyle::RAS_Right) &&
- CurrentChange.Spaces != 0) {
+ CurrentChange.Spaces != 0 && CurrentChange.Tok->isNot(tok::equal)) {
const bool ReferenceNotRightAligned =
Style.ReferenceAlignment != FormatStyle::RAS_Right &&
Style.ReferenceAlignment != FormatStyle::RAS_Pointer;
for (int Previous = i - 1;
- Previous >= 0 &&
- Changes[Previous].Tok->getType() == TT_PointerOrReference;
+ Previous >= 0 && Changes[Previous].Tok->is(TT_PointerOrReference);
--Previous) {
assert(Changes[Previous].Tok->isPointerOrReference());
if (Changes[Previous].Tok->isNot(tok::star)) {
@@ -849,7 +855,12 @@ void WhitespaceManager::alignConsecutiveAssignments() {
}
void WhitespaceManager::alignConsecutiveBitFields() {
- if (!Style.AlignConsecutiveBitFields.Enabled)
+ alignConsecutiveColons(Style.AlignConsecutiveBitFields, TT_BitFieldColon);
+}
+
+void WhitespaceManager::alignConsecutiveColons(
+ const FormatStyle::AlignConsecutiveStyle &AlignStyle, TokenType Type) {
+ if (!AlignStyle.Enabled)
return;
AlignTokens(
@@ -863,27 +874,32 @@ void WhitespaceManager::alignConsecutiveBitFields() {
if (&C != &Changes.back() && (&C + 1)->NewlinesBefore > 0)
return false;
- return C.Tok->is(TT_BitFieldColon);
+ return C.Tok->is(Type);
},
- Changes, /*StartAt=*/0, Style.AlignConsecutiveBitFields);
+ Changes, /*StartAt=*/0, AlignStyle);
}
-void WhitespaceManager::alignConsecutiveShortCaseStatements() {
+void WhitespaceManager::alignConsecutiveShortCaseStatements(bool IsExpr) {
if (!Style.AlignConsecutiveShortCaseStatements.Enabled ||
- !Style.AllowShortCaseLabelsOnASingleLine) {
+ !(IsExpr ? Style.AllowShortCaseExpressionOnASingleLine
+ : Style.AllowShortCaseLabelsOnASingleLine)) {
return;
}
+ const auto Type = IsExpr ? TT_CaseLabelArrow : TT_CaseLabelColon;
+ const auto &Option = Style.AlignConsecutiveShortCaseStatements;
+ const bool AlignArrowOrColon =
+ IsExpr ? Option.AlignCaseArrows : Option.AlignCaseColons;
+
auto Matches = [&](const Change &C) {
- if (Style.AlignConsecutiveShortCaseStatements.AlignCaseColons)
- return C.Tok->is(TT_CaseLabelColon);
+ if (AlignArrowOrColon)
+ return C.Tok->is(Type);
// Ignore 'IsInsideToken' to allow matching trailing comments which
// need to be reflowed as that causes the token to appear in two
// different changes, which will cause incorrect alignment as we'll
// reflow early due to detecting multiple aligning tokens per line.
- return !C.IsInsideToken && C.Tok->Previous &&
- C.Tok->Previous->is(TT_CaseLabelColon);
+ return !C.IsInsideToken && C.Tok->Previous && C.Tok->Previous->is(Type);
};
unsigned MinColumn = 0;
@@ -934,7 +950,7 @@ void WhitespaceManager::alignConsecutiveShortCaseStatements() {
if (Changes[I].Tok->isNot(tok::comment))
LineIsComment = false;
- if (Changes[I].Tok->is(TT_CaseLabelColon)) {
+ if (Changes[I].Tok->is(Type)) {
LineIsEmptyCase =
!Changes[I].Tok->Next || Changes[I].Tok->Next->isTrailingComment();
@@ -972,6 +988,21 @@ void WhitespaceManager::alignConsecutiveShortCaseStatements() {
Changes);
}
+void WhitespaceManager::alignConsecutiveTableGenBreakingDAGArgColons() {
+ alignConsecutiveColons(Style.AlignConsecutiveTableGenBreakingDAGArgColons,
+ TT_TableGenDAGArgListColonToAlign);
+}
+
+void WhitespaceManager::alignConsecutiveTableGenCondOperatorColons() {
+ alignConsecutiveColons(Style.AlignConsecutiveTableGenCondOperatorColons,
+ TT_TableGenCondOperatorColon);
+}
+
+void WhitespaceManager::alignConsecutiveTableGenDefinitions() {
+ alignConsecutiveColons(Style.AlignConsecutiveTableGenDefinitionColons,
+ TT_InheritanceColon);
+}
+
void WhitespaceManager::alignConsecutiveDeclarations() {
if (!Style.AlignConsecutiveDeclarations.Enabled)
return;
@@ -1085,7 +1116,7 @@ void WhitespaceManager::alignTrailingComments() {
// leave the comments.
if (RestoredLineLength >= Style.ColumnLimit && Style.ColumnLimit > 0)
break;
- C.Spaces = OriginalSpaces;
+ C.Spaces = C.NewlinesBefore > 0 ? C.Tok->OriginalColumn : OriginalSpaces;
continue;
}
@@ -1214,22 +1245,29 @@ void WhitespaceManager::alignTrailingComments(unsigned Start, unsigned End,
}
void WhitespaceManager::alignEscapedNewlines() {
- if (Style.AlignEscapedNewlines == FormatStyle::ENAS_DontAlign)
+ const auto Align = Style.AlignEscapedNewlines;
+ if (Align == FormatStyle::ENAS_DontAlign)
return;
- bool AlignLeft = Style.AlignEscapedNewlines == FormatStyle::ENAS_Left;
- unsigned MaxEndOfLine = AlignLeft ? 0 : Style.ColumnLimit;
+ const bool WithLastLine = Align == FormatStyle::ENAS_LeftWithLastLine;
+ const bool AlignLeft = Align == FormatStyle::ENAS_Left || WithLastLine;
+ const auto MaxColumn = Style.ColumnLimit;
+ unsigned MaxEndOfLine = AlignLeft ? 0 : MaxColumn;
unsigned StartOfMacro = 0;
for (unsigned i = 1, e = Changes.size(); i < e; ++i) {
Change &C = Changes[i];
- if (C.NewlinesBefore > 0) {
- if (C.ContinuesPPDirective) {
- MaxEndOfLine = std::max(C.PreviousEndOfTokenColumn + 2, MaxEndOfLine);
- } else {
- alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine);
- MaxEndOfLine = AlignLeft ? 0 : Style.ColumnLimit;
- StartOfMacro = i;
- }
+ if (C.NewlinesBefore == 0 && (!WithLastLine || C.Tok->isNot(tok::eof)))
+ continue;
+ const bool InPPDirective = C.ContinuesPPDirective;
+ const auto BackslashColumn = C.PreviousEndOfTokenColumn + 2;
+ if (InPPDirective ||
+ (WithLastLine && (MaxColumn == 0 || BackslashColumn <= MaxColumn))) {
+ MaxEndOfLine = std::max(BackslashColumn, MaxEndOfLine);
+ }
+ if (!InPPDirective) {
+ alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine);
+ MaxEndOfLine = AlignLeft ? 0 : MaxColumn;
+ StartOfMacro = i;
}
}
alignEscapedNewlines(StartOfMacro + 1, Changes.size(), MaxEndOfLine);
@@ -1469,7 +1507,7 @@ WhitespaceManager::CellDescriptions WhitespaceManager::getCells(unsigned Start,
while (NextNonComment && NextNonComment->is(tok::comma))
NextNonComment = NextNonComment->getNextNonComment();
auto j = i;
- while (Changes[j].Tok != NextNonComment && j < End)
+ while (j < End && Changes[j].Tok != NextNonComment)
++j;
if (j < End && Changes[j].NewlinesBefore == 0 &&
Changes[j].Tok->isNot(tok::r_brace)) {
diff --git a/contrib/llvm-project/clang/lib/Format/WhitespaceManager.h b/contrib/llvm-project/clang/lib/Format/WhitespaceManager.h
index 8ac73305871a..7b91d8bf4db7 100644
--- a/contrib/llvm-project/clang/lib/Format/WhitespaceManager.h
+++ b/contrib/llvm-project/clang/lib/Format/WhitespaceManager.h
@@ -17,11 +17,6 @@
#include "TokenAnnotator.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Format/Format.h"
-#include "llvm/ADT/SmallVector.h"
-#include <algorithm>
-#include <string>
-#include <tuple>
namespace clang {
namespace format {
@@ -226,6 +221,11 @@ private:
/// Align consecutive bitfields over all \c Changes.
void alignConsecutiveBitFields();
+ /// Align consecutive colon. For bitfields, TableGen DAGArgs and defintions.
+ void
+ alignConsecutiveColons(const FormatStyle::AlignConsecutiveStyle &AlignStyle,
+ TokenType Type);
+
/// Align consecutive declarations over all \c Changes.
void alignConsecutiveDeclarations();
@@ -233,7 +233,16 @@ private:
void alignChainedConditionals();
/// Align consecutive short case statements over all \c Changes.
- void alignConsecutiveShortCaseStatements();
+ void alignConsecutiveShortCaseStatements(bool IsExpr);
+
+ /// Align consecutive TableGen DAGArg colon over all \c Changes.
+ void alignConsecutiveTableGenBreakingDAGArgColons();
+
+ /// Align consecutive TableGen cond operator colon over all \c Changes.
+ void alignConsecutiveTableGenCondOperatorColons();
+
+ /// Align consecutive TableGen definitions over all \c Changes.
+ void alignConsecutiveTableGenDefinitions();
/// Align trailing comments over all \c Changes.
void alignTrailingComments();