1//===- unittest/Format/FormatTestTableGen.cpp -----------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "FormatTestUtils.h"
10#include "clang/Format/Format.h"
11#include "llvm/Support/Debug.h"
12#include "gtest/gtest.h"
13
14#define DEBUG_TYPE "format-test"
15
16namespace clang {
17namespace format {
18
19class FormatTestTableGen : public testing::Test {
20protected:
21 static std::string format(StringRef Code, unsigned Offset, unsigned Length,
22 const FormatStyle &Style) {
23 LLVM_DEBUG(llvm::errs() << "---\n");
24 LLVM_DEBUG(llvm::errs() << Code << "\n\n");
25 std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
26 tooling::Replacements Replaces = reformat(Style, Code, Ranges);
27 auto Result = applyAllReplacements(Code, Replaces);
28 EXPECT_TRUE(static_cast<bool>(Result));
29 LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
30 return *Result;
31 }
32
33 static std::string format(StringRef Code) {
34 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_TableGen);
35 Style.ColumnLimit = 60; // To make writing tests easier.
36 return format(Code, Offset: 0, Length: Code.size(), Style);
37 }
38
39 static void verifyFormat(StringRef Code) {
40 EXPECT_EQ(Code.str(), format(Code)) << "Expected code is not stable";
41 EXPECT_EQ(Code.str(), format(test::messUp(Code)));
42 }
43
44 static void verifyFormat(StringRef Result, StringRef MessedUp) {
45 EXPECT_EQ(Result, format(MessedUp));
46 }
47
48 static void verifyFormat(StringRef Code, const FormatStyle &Style) {
49 EXPECT_EQ(Code.str(), format(Code, 0, Code.size(), Style))
50 << "Expected code is not stable";
51 auto MessUp = test::messUp(Code);
52 EXPECT_EQ(Code.str(), format(MessUp, 0, MessUp.size(), Style));
53 }
54};
55
56TEST_F(FormatTestTableGen, FormatStringBreak) {
57 verifyFormat(Code: "include \"OptParser.td\"\n"
58 "def flag : Flag<\"--foo\">,\n"
59 " HelpText<\n"
60 " \"This is a very, very, very, very, \"\n"
61 " \"very, very, very, very, very, very, \"\n"
62 " \"very long help string\">;");
63}
64
65TEST_F(FormatTestTableGen, NoSpacesInSquareBracketLists) {
66 verifyFormat(Code: "def flag : Flag<[\"-\", \"--\"], \"foo\">;");
67}
68
69TEST_F(FormatTestTableGen, LiteralsAndIdentifiers) {
70 verifyFormat(Code: "def LiteralAndIdentifiers {\n"
71 " let someInteger = -42;\n"
72 " let 0startID = $TokVarName;\n"
73 " let 0xstartInteger = 0x42;\n"
74 " let someIdentifier = $TokVarName;\n"
75 "}");
76}
77
78TEST_F(FormatTestTableGen, BangOperators) {
79 verifyFormat(Code: "def BangOperators {\n"
80 " let IfOpe = !if(\n"
81 " !not(!and(!gt(!add(1, 2), !sub(3, 4)), !isa<Ty>($x))),\n"
82 " !foldl(0, !listconcat(!range(5, 6), !range(7, 8)),\n"
83 " total, rec, !add(total, rec.Number)),\n"
84 " !tail(!range(9, 10)));\n"
85 " let ForeachOpe = !foreach(\n"
86 " arg, arglist,\n"
87 " !if(!isa<SomeType>(arg.Type),\n"
88 " !add(!cast<SomeOtherType>(arg).Number, x), arg));\n"
89 " let CondOpe1 = !cond(!eq(size, 1): 1,\n"
90 " !eq(size, 2): 1,\n"
91 " !eq(size, 4): 1,\n"
92 " !eq(size, 8): 1,\n"
93 " !eq(size, 16): 1,\n"
94 " true: 0);\n"
95 " let CondOpe2 = !cond(!lt(x, 0): \"negativenegative\",\n"
96 " !eq(x, 0): \"zerozero\",\n"
97 " true: \"positivepositive\");\n"
98 " let CondOpe2WithComment = !cond(!lt(x, 0): // negative\n"
99 " \"negativenegative\",\n"
100 " !eq(x, 0): // zero\n"
101 " \"zerozero\",\n"
102 " true: // default\n"
103 " \"positivepositive\");\n"
104 " let CondOpe3WithCommentAfterLParen = !cond(\n"
105 " // comment\n"
106 " !eq(/* comment */ x, 0): \"zero\");\n"
107 "}");
108}
109
110TEST_F(FormatTestTableGen, Include) {
111 verifyFormat(Code: "include \"test/IncludeFile.h\"");
112}
113
114TEST_F(FormatTestTableGen, Types) {
115 verifyFormat(Code: "def Types : list<int>, bits<3>, list<list<string>> {}");
116}
117
118TEST_F(FormatTestTableGen, SimpleValue1_SingleLiterals) {
119 verifyFormat(Code: "def SimpleValue {\n"
120 " let Integer = 42;\n"
121 " let String = \"some string\";\n"
122 "}");
123}
124
125TEST_F(FormatTestTableGen, SimpleValue1_MultilineString) {
126 // test::messUp does not understand multiline TableGen code-literals.
127 // We have to give the result and the strings to format manually.
128 StringRef DefWithCode =
129 "def SimpleValueCode {\n"
130 " let Code =\n"
131 " [{ A TokCode is nothing more than a multi-line string literal "
132 "delimited by \\[{ and }\\]. It can break across lines and the line "
133 "breaks are retained in the string. \n"
134 "(https://llvm.org/docs/TableGen/ProgRef.html#grammar-token-TokCode)}];\n"
135 "}";
136 StringRef DefWithCodeMessedUp =
137 "def SimpleValueCode { let \n"
138 "Code= \n"
139 " [{ A TokCode is nothing more than a multi-line string "
140 "literal "
141 "delimited by \\[{ and }\\]. It can break across lines and the line "
142 "breaks are retained in the string. \n"
143 "(https://llvm.org/docs/TableGen/ProgRef.html#grammar-token-TokCode)}] \n"
144 " ; \n"
145 " } ";
146 verifyFormat(Result: DefWithCode, MessedUp: DefWithCodeMessedUp);
147}
148
149TEST_F(FormatTestTableGen, SimpleValue2) {
150 verifyFormat(Code: "def SimpleValue2 {\n"
151 " let True = true;\n"
152 " let False = false;\n"
153 "}");
154}
155
156TEST_F(FormatTestTableGen, SimpleValue3) {
157 verifyFormat(Code: "class SimpleValue3<int x> { int Question = ?; }");
158}
159
160TEST_F(FormatTestTableGen, SimpleValue4) {
161 verifyFormat(Code: "def SimpleValue4 { let ValueList = {1, 2, 3}; }");
162}
163
164TEST_F(FormatTestTableGen, SimpleValue5) {
165 verifyFormat(Code: "def SimpleValue5 {\n"
166 " let SquareList = [1, 4, 9];\n"
167 " let SquareListWithType = [\"a\", \"b\", \"c\"]<string>;\n"
168 " let SquareListListWithType = [[1, 2], [3, 4, 5], [7]]<\n"
169 " list<int>>;\n"
170 " let SquareBitsListWithType = [ {1, 2},\n"
171 " {3, 4} ]<list<bits<8>>>;\n"
172 "}");
173}
174
175TEST_F(FormatTestTableGen, SimpleValue6) {
176 verifyFormat(Code: "def SimpleValue6 {\n"
177 " let DAGArgIns = (ins i32:$src1, i32:$src2);\n"
178 " let DAGArgOuts = (outs i32:$dst1, i32:$dst2, i32:$dst3,\n"
179 " i32:$dst4, i32:$dst5, i32:$dst6, i32:$dst7);\n"
180 " let DAGArgOutsWithComment = (outs i32:$dst1, // dst1\n"
181 " i32:$dst2, // dst2\n"
182 " i32:$dst3, // dst3\n"
183 " i32:$dst4, // dst4\n"
184 " i32:$dst5, // dst5\n"
185 " i32:$dst6, // dst6\n"
186 " i32:$dst7 // dst7\n"
187 " );\n"
188 " let DAGArgBang = (!cast<SomeType>(\"Some\") i32:$src1,\n"
189 " i32:$src2);\n"
190 "}");
191}
192
193TEST_F(FormatTestTableGen, SimpleValue7) {
194 verifyFormat(Code: "def SimpleValue7 { let Identifier = SimpleValue; }");
195}
196
197TEST_F(FormatTestTableGen, SimpleValue8) {
198 verifyFormat(Code: "def SimpleValue8 { let Class = SimpleValue3<3>; }");
199}
200
201TEST_F(FormatTestTableGen, ValueSuffix) {
202 verifyFormat(Code: "def SuffixedValues {\n"
203 " let Bit = value{17};\n"
204 " let Bits = value{8...15};\n"
205 " let List = value[1];\n"
206 " let Slice1 = value[1, ];\n"
207 " let Slice2 = value[4...7, 17, 2...3, 4];\n"
208 " let Field = value.field;\n"
209 "}");
210}
211
212TEST_F(FormatTestTableGen, PasteOperator) {
213 verifyFormat(Code: "def Paste#\"Operator\" { string Paste = \"Paste\"#operator; }");
214
215 verifyFormat(Code: "def [\"Traring\", \"Paste\"]# {\n"
216 " string X = Traring#;\n"
217 " string Y = List<\"Operator\">#;\n"
218 " string Z = [\"Traring\", \"Paste\", \"Traring\", \"Paste\",\n"
219 " \"Traring\", \"Paste\"]#;\n"
220 "}");
221
222 verifyFormat(Result: "def x#x {}", MessedUp: "def x\n"
223 "#x {}");
224 verifyFormat(Result: "def x#x {}", MessedUp: "def x\n"
225 "#\n"
226 "x {}");
227 verifyFormat(Code: "def x#x");
228}
229
230TEST_F(FormatTestTableGen, ClassDefinition) {
231 verifyFormat(Code: "class Class<int x, int y = 1, string z = \"z\", int w = -1>\n"
232 " : Parent1, Parent2<x, y> {\n"
233 " int Item1 = 1;\n"
234 " int Item2;\n"
235 " code Item3 = [{ Item3 }];\n"
236 " let Item4 = 4;\n"
237 " let Item5{1, 2} = 5;\n"
238 " defvar Item6 = 6;\n"
239 " let Item7 = ?;\n"
240 " assert !ge(x, 0), \"Assert7\";\n"
241 "}");
242
243 verifyFormat(Code: "class FPFormat<bits<3> val> { bits<3> Value = val; }");
244}
245
246TEST_F(FormatTestTableGen, Def) {
247 verifyFormat(Code: "def Def : Parent1<Def>, Parent2(defs Def) {\n"
248 " code Item1 = [{ Item1 }];\n"
249 " let Item2{1, 3...4} = {1, 2};\n"
250 " defvar Item3 = (ops nodty:$node1, nodty:$node2);\n"
251 " assert !le(Item2, 0), \"Assert4\";\n"
252 "}");
253
254 verifyFormat(Code: "class FPFormat<bits<3> val> { bits<3> Value = val; }");
255
256 verifyFormat(Code: "def NotFP : FPFormat<0>;");
257}
258
259TEST_F(FormatTestTableGen, Let) {
260 verifyFormat(Code: "let x = 1, y = value<type>,\n"
261 " z = !and(!gt(!add(1, 2), !sub(3, 4)), !isa<Ty>($x)) in {\n"
262 " class Class1 : Parent<x, y> { let Item1 = z; }\n"
263 "}");
264}
265
266TEST_F(FormatTestTableGen, MultiClass) {
267 verifyFormat(Code: "multiclass Multiclass<int x> {\n"
268 " def : Def1<(item type:$src1),\n"
269 " (!if(!ge(x, 0), !mul(!add(x, 1), !sub(x, 2)),\n"
270 " !sub(x, 2)))>;\n"
271 " def Def2 : value<type>;\n"
272 " def Def3 : type { let value = 1; }\n"
273 " defm : SomeMultiClass<Def1, Def2>;\n"
274 " defvar DefVar = 6;\n"
275 " foreach i = [1, 2, 3] in {\n"
276 " def : Foreach#i<(item type:$src1),\n"
277 " (!if(!gt(x, i),\n"
278 " !mul(!add(x, i), !sub(x, i)),\n"
279 " !sub(x, !add(i, 1))))>;\n"
280 " }\n"
281 " if !gt(x, 0) then {\n"
282 " def : IfThen<x>;\n"
283 " } else {\n"
284 " def : IfElse<x>;\n"
285 " }\n"
286 " if (dagid x, 0) then {\n"
287 " def : If2<1>;\n"
288 " }\n"
289 " let y = 1, z = 2 in {\n"
290 " multiclass Multiclass2<int x> {\n"
291 " foreach i = [1, 2, 3] in {\n"
292 " def : Foreach#i<(item type:$src1),\n"
293 " (!if(!gt(z, i),\n"
294 " !mul(!add(y, i), !sub(x, i)),\n"
295 " !sub(z, !add(i, 1))))>;\n"
296 " }\n"
297 " }\n"
298 " }\n"
299 "}");
300}
301
302TEST_F(FormatTestTableGen, MultiClassesWithPasteOperator) {
303 // This is a sensitive example for the handling of the paste operators in
304 // brace type calculation.
305 verifyFormat(Code: "multiclass MultiClass1<int i> {\n"
306 " def : Def#x<i>;\n"
307 " def : Def#y<i>;\n"
308 "}\n"
309 "multiclass MultiClass2<int i> { def : Def#x<i>; }");
310}
311
312TEST_F(FormatTestTableGen, Defm) {
313 verifyFormat(Code: "defm : Multiclass<0>;");
314
315 verifyFormat(Code: "defm Defm1 : Multiclass<1>;");
316}
317
318TEST_F(FormatTestTableGen, Defset) {
319 verifyFormat(Code: "defset list<Class> DefSet1 = {\n"
320 " def Def1 : Class<1>;\n"
321 " def Def2 : Class<2>;\n"
322 "}");
323}
324
325TEST_F(FormatTestTableGen, Defvar) {
326 verifyFormat(Code: "defvar DefVar1 = !cond(!ge(!size(PaseOperator.Paste), 1): 1,\n"
327 " true: 0);");
328}
329
330TEST_F(FormatTestTableGen, ForEach) {
331 verifyFormat(
332 Code: "foreach i = [1, 2, 3] in {\n"
333 " def : Foreach#i<(item type:$src1),\n"
334 " (!if(!lt(x, i),\n"
335 " !shl(!mul(x, i), !size(\"string\")),\n"
336 " !size(!strconcat(\"a\", \"b\", \"c\"))))>;\n"
337 "}");
338}
339
340TEST_F(FormatTestTableGen, Dump) { verifyFormat(Code: "dump \"Dump\";"); }
341
342TEST_F(FormatTestTableGen, If) {
343 verifyFormat(Code: "if !gt(x, 0) then {\n"
344 " def : IfThen<x>;\n"
345 "} else {\n"
346 " def : IfElse<x>;\n"
347 "}");
348}
349
350TEST_F(FormatTestTableGen, Assert) {
351 verifyFormat(Code: "assert !le(DefVar1, 0), \"Assert1\";");
352}
353
354TEST_F(FormatTestTableGen, DAGArgBreakElements) {
355 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_TableGen);
356 Style.ColumnLimit = 60;
357 // By default, the DAGArg does not have a break inside.
358 ASSERT_EQ(Style.TableGenBreakInsideDAGArg, FormatStyle::DAS_DontBreak);
359 verifyFormat(Code: "def Def : Parent {\n"
360 " let dagarg = (ins a:$src1, aa:$src2, aaa:$src3)\n"
361 "}",
362 Style);
363 // This option forces to break inside the DAGArg.
364 Style.TableGenBreakInsideDAGArg = FormatStyle::DAS_BreakElements;
365 verifyFormat(Code: "def Def : Parent {\n"
366 " let dagarg = (ins a:$src1,\n"
367 " aa:$src2,\n"
368 " aaa:$src3);\n"
369 "}",
370 Style);
371 verifyFormat(Code: "def Def : Parent {\n"
372 " let dagarg = (other a:$src1,\n"
373 " aa:$src2,\n"
374 " aaa:$src3);\n"
375 "}",
376 Style);
377 // Then, limit the DAGArg operator only to "ins".
378 Style.TableGenBreakingDAGArgOperators = {"ins"};
379 verifyFormat(Code: "def Def : Parent {\n"
380 " let dagarg = (ins a:$src1,\n"
381 " aa:$src2,\n"
382 " aaa:$src3);\n"
383 "}",
384 Style);
385 verifyFormat(Code: "def Def : Parent {\n"
386 " let dagarg = (other a:$src1, aa:$src2, aaa:$src3)\n"
387 "}",
388 Style);
389}
390
391TEST_F(FormatTestTableGen, DAGArgBreakAll) {
392 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_TableGen);
393 Style.ColumnLimit = 60;
394 // By default, the DAGArg does not have a break inside.
395 verifyFormat(Code: "def Def : Parent {\n"
396 " let dagarg = (ins a:$src1, aa:$src2, aaa:$src3)\n"
397 "}",
398 Style);
399 // This option forces to break inside the DAGArg.
400 Style.TableGenBreakInsideDAGArg = FormatStyle::DAS_BreakAll;
401 verifyFormat(Code: "def Def : Parent {\n"
402 " let dagarg = (ins\n"
403 " a:$src1,\n"
404 " aa:$src2,\n"
405 " aaa:$src3\n"
406 " );\n"
407 "}",
408 Style);
409 verifyFormat(Code: "def Def : Parent {\n"
410 " let dagarg = (other\n"
411 " a:$src1,\n"
412 " aa:$src2,\n"
413 " aaa:$src3\n"
414 " );\n"
415 "}",
416 Style);
417 // Then, limit the DAGArg operator only to "ins".
418 Style.TableGenBreakingDAGArgOperators = {"ins"};
419 verifyFormat(Code: "def Def : Parent {\n"
420 " let dagarg = (ins\n"
421 " a:$src1,\n"
422 " aa:$src2,\n"
423 " aaa:$src3\n"
424 " );\n"
425 "}",
426 Style);
427 verifyFormat(Code: "def Def : Parent {\n"
428 " let dagarg = (other a:$src1, aa:$src2, aaa:$src3);\n"
429 "}",
430 Style);
431}
432
433TEST_F(FormatTestTableGen, DAGArgAlignment) {
434 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_TableGen);
435 Style.ColumnLimit = 60;
436 Style.TableGenBreakInsideDAGArg = FormatStyle::DAS_BreakAll;
437 Style.TableGenBreakingDAGArgOperators = {"ins", "outs"};
438 verifyFormat(Code: "def Def : Parent {\n"
439 " let dagarg = (ins\n"
440 " a:$src1,\n"
441 " aa:$src2,\n"
442 " aaa:$src3\n"
443 " )\n"
444 "}",
445 Style);
446 verifyFormat(Code: "def Def : Parent {\n"
447 " let dagarg = (not a:$src1, aa:$src2, aaa:$src2)\n"
448 "}",
449 Style);
450 Style.AlignConsecutiveTableGenBreakingDAGArgColons.Enabled = true;
451 verifyFormat(Code: "def Def : Parent {\n"
452 " let dagarg = (ins\n"
453 " a :$src1,\n"
454 " aa :$src2,\n"
455 " aaa:$src3\n"
456 " )\n"
457 "}",
458 Style);
459 verifyFormat(Code: "def Def : Parent {\n"
460 " let dagarg = (not a:$src1, aa:$src2, aaa:$src2)\n"
461 "}",
462 Style);
463}
464
465TEST_F(FormatTestTableGen, CondOperatorAlignment) {
466 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_TableGen);
467 Style.ColumnLimit = 60;
468 verifyFormat(Code: "let CondOpe1 = !cond(!eq(size, 1): 1,\n"
469 " !eq(size, 16): 1,\n"
470 " true: 0);",
471 Style);
472 Style.AlignConsecutiveTableGenCondOperatorColons.Enabled = true;
473 verifyFormat(Code: "let CondOpe1 = !cond(!eq(size, 1) : 1,\n"
474 " !eq(size, 16): 1,\n"
475 " true : 0);",
476 Style);
477}
478
479TEST_F(FormatTestTableGen, DefAlignment) {
480 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_TableGen);
481 Style.ColumnLimit = 60;
482 verifyFormat(Code: "def Def : Parent {}\n"
483 "def DefDef : Parent {}\n"
484 "def DefDefDef : Parent {}",
485 Style);
486 Style.AlignConsecutiveTableGenDefinitionColons.Enabled = true;
487 verifyFormat(Code: "def Def : Parent {}\n"
488 "def DefDef : Parent {}\n"
489 "def DefDefDef : Parent {}",
490 Style);
491}
492
493} // namespace format
494} // end namespace clang
495

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of clang/unittests/Format/FormatTestTableGen.cpp