[clang] [clang-format] Support of TableGen basic format restrictions. (PR #81611)
Hirofumi Nakamura via cfe-commits
cfe-commits at lists.llvm.org
Wed Feb 14 05:09:49 PST 2024
https://github.com/hnakamura5 updated https://github.com/llvm/llvm-project/pull/81611
>From 7ee4b35f0aed434053b6fd6329ef39de97bc22db Mon Sep 17 00:00:00 2001
From: hnakamura5 <k.nakamura.hirofumi at gmail.com>
Date: Tue, 13 Feb 2024 23:50:15 +0900
Subject: [PATCH 1/4] [clang-format] Support of TableGen basic format
restrictions.
- Allow/force to break the line or not.
- Allow to insert space or not.
---
clang/lib/Format/ContinuationIndenter.cpp | 14 +-
clang/lib/Format/TokenAnnotator.cpp | 56 ++++
clang/unittests/Format/FormatTestTableGen.cpp | 263 ++++++++++++++++++
3 files changed, 331 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp
index 0b2ef97af44d83..1879af94f6da49 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -821,6 +821,7 @@ 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) &&
!(Current.MacroParent && Previous.MacroParent) &&
(Current.isNot(TT_LineComment) ||
Previous.isOneOf(BK_BracedInit, TT_VerilogMultiLineListLParen))) {
@@ -1250,7 +1251,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
return CurrentState.Indent;
}
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;
@@ -1278,6 +1279,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 &&
@@ -1696,7 +1703,9 @@ 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->is(TT_TableGenDAGArgListComma)))) {
NewParenState.Indent = std::max(
std::max(State.Column, NewParenState.Indent), CurrentState.LastSpace);
}
@@ -1942,6 +1951,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();
}
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index d353388a862b56..636d098881c97e 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -5072,7 +5072,38 @@ 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.is(TT_TableGenDAGArgListColon) ||
+ Left.is(TT_TableGenDAGArgListColon)) {
+ return false;
+ }
+ if (Right.is(TT_TableGenCondOperatorColon))
+ return false;
+ // Do not insert bang operators and consequent openers.
+ if (Right.isOneOf(tok::l_paren, tok::greater) &&
+ 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) {
@@ -5424,6 +5455,13 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
return Style.BreakArrays;
}
}
+ if (Style.isTableGen()) {
+ // Break the comma in side cond operators.
+ // !cond(case1:1,
+ // case2:0);
+ if (Left.is(TT_TableGenCondOperatorComma))
+ return true;
+ }
if (Line.startsWith(tok::kw_asm) && Right.is(TT_InlineASMColon) &&
Style.BreakBeforeInlineASMColon == FormatStyle::BBIAS_Always) {
@@ -5822,6 +5860,24 @@ 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 split the value and its suffix part.
+ if (Left.is(TT_TableGenValueSuffix))
+ return false;
+ // 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.is(tok::at))
diff --git a/clang/unittests/Format/FormatTestTableGen.cpp b/clang/unittests/Format/FormatTestTableGen.cpp
index 123f47d6d7f884..77ddb4ed228864 100644
--- a/clang/unittests/Format/FormatTestTableGen.cpp
+++ b/clang/unittests/Format/FormatTestTableGen.cpp
@@ -55,5 +55,268 @@ TEST_F(FormatTestTableGen, NoSpacesInSquareBracketLists) {
verifyFormat("def flag : Flag<[\"-\", \"--\"], \"foo\">;");
}
+TEST_F(FormatTestTableGen, LiteralsAndIdentifiers) {
+ verifyFormat("def LiteralAndIdentifiers {\n"
+ " let someInteger = -42;\n"
+ " let 0startID = $TokVarName;\n"
+ " let 0xstartInteger = 0x42;\n"
+ " let someIdentifier = $TokVarName;\n"
+ "}\n");
+}
+
+TEST_F(FormatTestTableGen, BangOperators) {
+ verifyFormat("def BangOperators {\n"
+ " let IfOpe = !if(\n"
+ " !not(!and(!gt(!add(1, 2), !sub(3, 4)), !isa<Ty>($x))),\n"
+ " !foldl(0, !listconcat(!range(5, 6), !range(7, 8)),\n"
+ " total, rec, !add(total, rec.Number)),\n"
+ " !tail(!range(9, 10)));\n"
+ " let ForeachOpe = !foreach(\n"
+ " arg, arglist,\n"
+ " !if(!isa<SomeType>(arg.Type),\n"
+ " !add(!cast<SomeOtherType>(arg).Number, x), arg));\n"
+ " let CondOpe1 = !cond(!eq(size, 1): 1,\n"
+ " !eq(size, 2): 1,\n"
+ " !eq(size, 4): 1,\n"
+ " !eq(size, 8): 1,\n"
+ " !eq(size, 16): 1,\n"
+ " true: 0);\n"
+ " let CondOpe2 = !cond(!lt(x, 0): \"negativenegative\",\n"
+ " !eq(x, 0): \"zerozero\",\n"
+ " true: \"positivepositive\");\n"
+ " let CondOpe2WithComment = !cond(!lt(x, 0): // negative\n"
+ " \"negativenegative\",\n"
+ " !eq(x, 0): // zero\n"
+ " \"zerozero\",\n"
+ " true: // default\n"
+ " \"positivepositive\");\n"
+ "}\n");
+}
+
+TEST_F(FormatTestTableGen, Include) {
+ verifyFormat("include \"test/IncludeFile.h\"\n");
+}
+
+TEST_F(FormatTestTableGen, Types) {
+ verifyFormat("def Types : list<int>, bits<3>, list<list<string>> {}\n");
+}
+
+TEST_F(FormatTestTableGen, SimpleValue1_SingleLiterals) {
+ verifyFormat("def SimpleValue {\n"
+ " let Integer = 42;\n"
+ " let String = \"some string\";\n"
+ "}\n");
+}
+
+TEST_F(FormatTestTableGen, SimpleValue1_MultilineString) {
+ // verifyFormat does not understand multiline TableGen code-literals
+ std::string DefWithCode =
+ "def SimpleValueCode {\n"
+ " let Code =\n"
+ " [{ A TokCode is nothing more than a multi-line string literal "
+ "delimited by \\[{ and }\\]. It can break across lines and the line "
+ "breaks are retained in the string. "
+ "(https://llvm.org/docs/TableGen/ProgRef.html#grammar-token-TokCode)}];\n"
+ "}\n";
+ std::string DefWithCodeMessingUp =
+ "def SimpleValueCode {\n"
+ " let Code= "
+ "[{ A TokCode is nothing more than a multi-line string literal "
+ "delimited by \\[{ and }\\]. It can break across lines and the line "
+ "breaks are retained in the string. "
+ "(https://llvm.org/docs/TableGen/ProgRef.html#grammar-token-TokCode)}];\n"
+ " } \n";
+ EXPECT_EQ(DefWithCode, format(DefWithCodeMessingUp));
+}
+
+TEST_F(FormatTestTableGen, SimpleValue2) {
+ verifyFormat("def SimpleValue2 {\n"
+ " let True = true;\n"
+ " let False = false;\n"
+ "}\n");
+}
+
+TEST_F(FormatTestTableGen, SimpleValue3) {
+ verifyFormat("class SimpleValue3<int x> { int Question = ?; }\n");
+}
+
+TEST_F(FormatTestTableGen, SimpleValue4) {
+ verifyFormat("def SimpleValue4 { let ValueList = {1, 2, 3}; }\n");
+}
+
+TEST_F(FormatTestTableGen, SimpleValue5) {
+ verifyFormat("def SimpleValue5 {\n"
+ " let SquareList = [1, 4, 9];\n"
+ " let SquareListWithType = [\"a\", \"b\", \"c\"]<string>;\n"
+ " let SquareListListWithType = [[1, 2], [3, 4, 5], [7]]<\n"
+ " list<int>>;\n"
+ " let SquareBitsListWithType = [ {1, 2},\n"
+ " {3, 4} ]<list<bits<8>>>;\n"
+ "}\n");
+}
+
+TEST_F(FormatTestTableGen, SimpleValue6) {
+ verifyFormat("def SimpleValue6 {\n"
+ " let DAGArgIns = (ins i32:$src1, i32:$src2);\n"
+ " let DAGArgOuts = (outs i32:$dst1, i32:$dst2, i32:$dst3,\n"
+ " i32:$dst4, i32:$dst5, i32:$dst6, i32:$dst7);\n"
+ " let DAGArgOutsWithComment = (outs i32:$dst1, // dst1\n"
+ " i32:$dst2, // dst2\n"
+ " i32:$dst3, // dst3\n"
+ " i32:$dst4, // dst4\n"
+ " i32:$dst5, // dst5\n"
+ " i32:$dst6, // dst6\n"
+ " i32:$dst7 // dst7\n"
+ " );\n"
+ " let DAGArgBang = (!cast<SomeType>(\"Some\") i32:$src1,\n"
+ " i32:$src2);\n"
+ "}\n");
+}
+
+TEST_F(FormatTestTableGen, SimpleValue7) {
+ verifyFormat("def SimpleValue7 { let Identifier = SimpleValue; }\n");
+}
+
+TEST_F(FormatTestTableGen, SimpleValue8) {
+ verifyFormat("def SimpleValue8 { let Class = SimpleValue3<3>; }\n");
+}
+
+TEST_F(FormatTestTableGen, ValueSuffix) {
+ verifyFormat("def SuffixedValues {\n"
+ " let Bit = value{17};\n"
+ " let Bits = value{8...15};\n"
+ " let List = value[1];\n"
+ " let Slice1 = value[1, ];\n"
+ " let Slice2 = value[4...7, 17, 2...3, 4];\n"
+ " let Field = value.field;\n"
+ "}\n");
+}
+
+TEST_F(FormatTestTableGen, PasteOperator) {
+ verifyFormat(
+ "def Paste#\"Operator\" { string Paste = \"Paste\"#operator; }\n");
+
+ verifyFormat("def [\"Traring\", \"Paste\"]# {\n"
+ " string X = Traring#;\n"
+ " string Y = List<\"Operator\">#;\n"
+ " string Z = [\"Traring\", \"Paste\", \"Traring\", \"Paste\",\n"
+ " \"Traring\", \"Paste\"]#;\n"
+ "}\n");
+}
+
+TEST_F(FormatTestTableGen, ClassDefinition) {
+ verifyFormat("class Class<int x, int y = 1, string z = \"z\", int w = -1>\n"
+ " : Parent1, Parent2<x, y> {\n"
+ " int Item1 = 1;\n"
+ " int Item2;\n"
+ " code Item3 = [{ Item3 }];\n"
+ " let Item4 = 4;\n"
+ " let Item5{1, 2} = 5;\n"
+ " defvar Item6 = 6;\n"
+ " let Item7 = ?;\n"
+ " assert !ge(x, 0), \"Assert7\";\n"
+ "}\n");
+
+ verifyFormat("class FPFormat<bits<3> val> { bits<3> Value = val; }\n");
+}
+
+TEST_F(FormatTestTableGen, Def) {
+ verifyFormat("def Def : Parent1<Def>, Parent2(defs Def) {\n"
+ " code Item1 = [{ Item1 }];\n"
+ " let Item2{1, 3...4} = {1, 2};\n"
+ " defvar Item3 = (ops nodty:$node1, nodty:$node2);\n"
+ " assert !le(Item2, 0), \"Assert4\";\n"
+ "}\n");
+
+ verifyFormat("class FPFormat<bits<3> val> { bits<3> Value = val; }\n");
+
+ verifyFormat("def NotFP : FPFormat<0>;\n");
+}
+
+TEST_F(FormatTestTableGen, Let) {
+ verifyFormat("let x = 1, y = value<type>,\n"
+ " z = !and(!gt(!add(1, 2), !sub(3, 4)), !isa<Ty>($x)) in {\n"
+ " class Class1 : Parent<x, y> { let Item1 = z; }\n"
+ "}\n");
+}
+
+TEST_F(FormatTestTableGen, MultiClass) {
+ verifyFormat("multiclass Multiclass<int x> {\n"
+ " def : Def1<(item type:$src1),\n"
+ " (!if(!ge(x, 0), !mul(!add(x, 1), !sub(x, 2)),\n"
+ " !sub(x, 2)))>;\n"
+ " def Def2 : value<type>;\n"
+ " def Def3 : type { let value = 1; }\n"
+ " defm : SomeMultiClass<Def1, Def2>;\n"
+ " defvar DefVar = 6;\n"
+ " foreach i = [1, 2, 3] in {\n"
+ " def : Foreach#i<(item type:$src1),\n"
+ " (!if(!gt(x, i),\n"
+ " !mul(!add(x, i), !sub(x, i)),\n"
+ " !sub(x, !add(i, 1))))>;\n"
+ " }\n"
+ " if !gt(x, 0) then {\n"
+ " def : IfThen<x>;\n"
+ " } else {\n"
+ " def : IfElse<x>;\n"
+ " }\n"
+ " if (dagid x, 0) then {\n"
+ " def : If2<1>;\n"
+ " }\n"
+ " let y = 1, z = 2 in {\n"
+ " multiclass Multiclass2<int x> {\n"
+ " foreach i = [1, 2, 3] in {\n"
+ " def : Foreach#i<(item type:$src1),\n"
+ " (!if(!gt(z, i),\n"
+ " !mul(!add(y, i), !sub(x, i)),\n"
+ " !sub(z, !add(i, 1))))>;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}\n");
+}
+
+TEST_F(FormatTestTableGen, Defm) {
+ verifyFormat("defm : Multiclass<0>;\n");
+
+ verifyFormat("defm Defm1 : Multiclass<1>;\n");
+}
+
+TEST_F(FormatTestTableGen, Defset) {
+ verifyFormat("defset list<Class> DefSet1 = {\n"
+ " def Def1 : Class<1>;\n"
+ " def Def2 : Class<2>;\n"
+ "}\n");
+}
+
+TEST_F(FormatTestTableGen, Defvar) {
+ verifyFormat("defvar DefVar1 = !cond(!ge(!size(PaseOperator.Paste), 1): 1,\n"
+ " true: 0);\n");
+}
+
+TEST_F(FormatTestTableGen, ForEach) {
+ verifyFormat(
+ "foreach i = [1, 2, 3] in {\n"
+ " def : Foreach#i<(item type:$src1),\n"
+ " (!if(!lt(x, i),\n"
+ " !shl(!mul(x, i), !size(\"string\")),\n"
+ " !size(!strconcat(\"a\", \"b\", \"c\"))))>;\n"
+ "}\n");
+}
+
+TEST_F(FormatTestTableGen, Dump) { verifyFormat("dump \"Dump\";\n"); }
+
+TEST_F(FormatTestTableGen, If) {
+ verifyFormat("if !gt(x, 0) then {\n"
+ " def : IfThen<x>;\n"
+ "} else {\n"
+ " def : IfElse<x>;\n"
+ "}\n");
+}
+
+TEST_F(FormatTestTableGen, Assert) {
+ verifyFormat("assert !le(DefVar1, 0), \"Assert1\";\n");
+}
+
} // namespace format
} // end namespace clang
>From b291f901e42673542ebc5ddd3a7a7d2c92d6b967 Mon Sep 17 00:00:00 2001
From: hnakamura5 <k.nakamura.hirofumi at gmail.com>
Date: Wed, 14 Feb 2024 00:12:22 +0900
Subject: [PATCH 2/4] fixed a mistake of > and <.
---
clang/lib/Format/TokenAnnotator.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 636d098881c97e..3185ad3a5de295 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -5086,7 +5086,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
if (Right.is(TT_TableGenCondOperatorColon))
return false;
// Do not insert bang operators and consequent openers.
- if (Right.isOneOf(tok::l_paren, tok::greater) &&
+ if (Right.isOneOf(tok::l_paren, tok::less) &&
Left.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator)) {
return false;
}
>From c5621a6a8d9fe9ee4cac74bebe1be3fdedffedd0 Mon Sep 17 00:00:00 2001
From: hnakamura5 <k.nakamura.hirofumi at gmail.com>
Date: Wed, 14 Feb 2024 00:32:03 +0900
Subject: [PATCH 3/4] fixed duplicated cases for TT_TableGenValueSuffix in
canBreakBefore.
---
clang/lib/Format/TokenAnnotator.cpp | 3 ---
1 file changed, 3 deletions(-)
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 3185ad3a5de295..48367c15781a63 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -5869,9 +5869,6 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
return !Left.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator,
TT_TemplateCloser);
}
- // Avoid to split the value and its suffix part.
- if (Left.is(TT_TableGenValueSuffix))
- return false;
// Avoid to break between the value and its suffix part.
if (Left.is(TT_TableGenValueSuffix))
return false;
>From 36925ce59679fbbf3ce77ce60d01b06977ab670a Mon Sep 17 00:00:00 2001
From: hnakamura5 <k.nakamura.hirofumi at gmail.com>
Date: Wed, 14 Feb 2024 22:07:29 +0900
Subject: [PATCH 4/4] Defined verifyFormat 2 string version, and messed up the
string a little bit more.
---
clang/unittests/Format/FormatTestTableGen.cpp | 24 ++++++++++++-------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/clang/unittests/Format/FormatTestTableGen.cpp b/clang/unittests/Format/FormatTestTableGen.cpp
index 77ddb4ed228864..72df48644ebe2a 100644
--- a/clang/unittests/Format/FormatTestTableGen.cpp
+++ b/clang/unittests/Format/FormatTestTableGen.cpp
@@ -40,6 +40,10 @@ class FormatTestTableGen : public ::testing::Test {
EXPECT_EQ(Code.str(), format(Code)) << "Expected code is not stable";
EXPECT_EQ(Code.str(), format(test::messUp(Code)));
}
+
+ static void verifyFormat(llvm::StringRef Result, llvm::StringRef MessedUp) {
+ EXPECT_EQ(Result, format(MessedUp));
+ }
};
TEST_F(FormatTestTableGen, FormatStringBreak) {
@@ -109,24 +113,26 @@ TEST_F(FormatTestTableGen, SimpleValue1_SingleLiterals) {
}
TEST_F(FormatTestTableGen, SimpleValue1_MultilineString) {
- // verifyFormat does not understand multiline TableGen code-literals
+ // test::messUp does not understand multiline TableGen code-literals.
+ // We have to give the result and the strings to format manually.
std::string DefWithCode =
"def SimpleValueCode {\n"
" let Code =\n"
" [{ A TokCode is nothing more than a multi-line string literal "
"delimited by \\[{ and }\\]. It can break across lines and the line "
- "breaks are retained in the string. "
+ "breaks are retained in the string. \n"
"(https://llvm.org/docs/TableGen/ProgRef.html#grammar-token-TokCode)}];\n"
"}\n";
- std::string DefWithCodeMessingUp =
- "def SimpleValueCode {\n"
- " let Code= "
- "[{ A TokCode is nothing more than a multi-line string literal "
+ std::string DefWithCodeMessedUp =
+ "def SimpleValueCode { let \n"
+ "Code= \n"
+ " [{ A TokCode is nothing more than a multi-line string literal "
"delimited by \\[{ and }\\]. It can break across lines and the line "
- "breaks are retained in the string. "
- "(https://llvm.org/docs/TableGen/ProgRef.html#grammar-token-TokCode)}];\n"
+ "breaks are retained in the string. \n"
+ "(https://llvm.org/docs/TableGen/ProgRef.html#grammar-token-TokCode)}] \n"
+ " ; \n"
" } \n";
- EXPECT_EQ(DefWithCode, format(DefWithCodeMessingUp));
+ verifyFormat(DefWithCode, DefWithCodeMessedUp);
}
TEST_F(FormatTestTableGen, SimpleValue2) {
More information about the cfe-commits
mailing list