1 //===- llvm/unittest/Support/FileCheckTest.cpp - FileCheck tests --===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Support/FileCheck.h"
10 #include "gtest/gtest.h"
11 #include <unordered_set>
16 class FileCheckTest
: public ::testing::Test
{};
18 TEST_F(FileCheckTest
, Literal
) {
19 // Eval returns the literal's value.
20 FileCheckExpressionLiteral
Ten(10);
21 Expected
<uint64_t> Value
= Ten
.eval();
22 ASSERT_TRUE(bool(Value
));
23 EXPECT_EQ(10U, *Value
);
25 // Max value can be correctly represented.
26 FileCheckExpressionLiteral
Max(std::numeric_limits
<uint64_t>::max());
28 ASSERT_TRUE(bool(Value
));
29 EXPECT_EQ(std::numeric_limits
<uint64_t>::max(), *Value
);
32 static std::string
toString(const std::unordered_set
<std::string
> &Set
) {
35 for (StringRef S
: Set
) {
36 Str
+= Twine(First
? "{" + S
: ", " + S
).str();
44 expectUndefErrors(std::unordered_set
<std::string
> ExpectedUndefVarNames
,
46 handleAllErrors(std::move(Err
), [&](const FileCheckUndefVarError
&E
) {
47 ExpectedUndefVarNames
.erase(E
.getVarName());
49 EXPECT_TRUE(ExpectedUndefVarNames
.empty()) << toString(ExpectedUndefVarNames
);
52 // Return whether Err contains any FileCheckUndefVarError whose associated name
53 // is not ExpectedUndefVarName.
54 static void expectUndefError(const Twine
&ExpectedUndefVarName
, Error Err
) {
55 expectUndefErrors({ExpectedUndefVarName
.str()}, std::move(Err
));
58 uint64_t doAdd(uint64_t OpL
, uint64_t OpR
) { return OpL
+ OpR
; }
60 TEST_F(FileCheckTest
, NumericVariable
) {
61 // Undefined variable: isValueKnownAtMatchTime returns false, getValue and
62 // eval fail, error returned by eval holds the name of the undefined
64 FileCheckNumericVariable FooVar
= FileCheckNumericVariable("FOO", 1);
65 EXPECT_EQ("FOO", FooVar
.getName());
66 EXPECT_FALSE(FooVar
.isValueKnownAtMatchTime());
67 FileCheckNumericVariableUse FooVarUse
=
68 FileCheckNumericVariableUse("FOO", &FooVar
);
69 EXPECT_FALSE(FooVar
.getValue());
70 Expected
<uint64_t> EvalResult
= FooVarUse
.eval();
71 ASSERT_FALSE(EvalResult
);
72 expectUndefError("FOO", EvalResult
.takeError());
76 // Defined variable: isValueKnownAtMatchTime returns true, getValue and eval
78 EXPECT_TRUE(FooVar
.isValueKnownAtMatchTime());
79 Optional
<uint64_t> Value
= FooVar
.getValue();
80 ASSERT_TRUE(bool(Value
));
81 EXPECT_EQ(42U, *Value
);
82 EvalResult
= FooVarUse
.eval();
83 ASSERT_TRUE(bool(EvalResult
));
84 EXPECT_EQ(42U, *EvalResult
);
86 // Variable defined by numeric expression: isValueKnownAtMatchTime
87 // returns true, getValue and eval return value of expression, setValue
89 std::unique_ptr
<FileCheckNumericVariableUse
> FooVarUsePtr
=
90 std::make_unique
<FileCheckNumericVariableUse
>("FOO", &FooVar
);
91 std::unique_ptr
<FileCheckExpressionLiteral
> One
=
92 std::make_unique
<FileCheckExpressionLiteral
>(1);
93 FileCheckASTBinop Binop
=
94 FileCheckASTBinop(doAdd
, std::move(FooVarUsePtr
), std::move(One
));
95 FileCheckNumericVariable FoobarExprVar
=
96 FileCheckNumericVariable("FOOBAR", 2, &Binop
);
97 EXPECT_TRUE(FoobarExprVar
.isValueKnownAtMatchTime());
98 ASSERT_FALSE(FoobarExprVar
.getValue());
99 FileCheckNumericVariableUse FoobarExprVarUse
=
100 FileCheckNumericVariableUse("FOOBAR", &FoobarExprVar
);
101 EvalResult
= FoobarExprVarUse
.eval();
102 ASSERT_TRUE(bool(EvalResult
));
103 EXPECT_EQ(43U, *EvalResult
);
104 EXPECT_TRUE(FoobarExprVar
.getExpressionAST());
105 FoobarExprVar
.setValue(43);
106 EXPECT_FALSE(FoobarExprVar
.getExpressionAST());
107 FoobarExprVar
= FileCheckNumericVariable("FOOBAR", 2, &Binop
);
108 EXPECT_TRUE(FoobarExprVar
.getExpressionAST());
110 // Clearing variable: getValue and eval fail. Error returned by eval holds
111 // the name of the cleared variable.
113 FoobarExprVar
.clearValue();
114 EXPECT_FALSE(FoobarExprVar
.getExpressionAST());
115 EXPECT_FALSE(FooVar
.getValue());
116 EXPECT_FALSE(FoobarExprVar
.getValue());
117 EvalResult
= FooVarUse
.eval();
118 ASSERT_FALSE(EvalResult
);
119 expectUndefError("FOO", EvalResult
.takeError());
120 EvalResult
= FoobarExprVarUse
.eval();
121 ASSERT_FALSE(EvalResult
);
122 expectUndefError("FOOBAR", EvalResult
.takeError());
125 TEST_F(FileCheckTest
, Binop
) {
126 FileCheckNumericVariable FooVar
= FileCheckNumericVariable("FOO", 1);
128 std::unique_ptr
<FileCheckNumericVariableUse
> FooVarUse
=
129 std::make_unique
<FileCheckNumericVariableUse
>("FOO", &FooVar
);
130 FileCheckNumericVariable BarVar
= FileCheckNumericVariable("BAR", 2);
132 std::unique_ptr
<FileCheckNumericVariableUse
> BarVarUse
=
133 std::make_unique
<FileCheckNumericVariableUse
>("BAR", &BarVar
);
134 FileCheckASTBinop Binop
=
135 FileCheckASTBinop(doAdd
, std::move(FooVarUse
), std::move(BarVarUse
));
137 // Defined variable: eval returns right value.
138 Expected
<uint64_t> Value
= Binop
.eval();
139 ASSERT_TRUE(bool(Value
));
140 EXPECT_EQ(60U, *Value
);
142 // 1 undefined variable: eval fails, error contains name of undefined
145 Value
= Binop
.eval();
147 expectUndefError("FOO", Value
.takeError());
149 // 2 undefined variables: eval fails, error contains names of all undefined
152 Value
= Binop
.eval();
154 expectUndefErrors({"FOO", "BAR"}, Value
.takeError());
157 TEST_F(FileCheckTest
, ValidVarNameStart
) {
158 EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('a'));
159 EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('G'));
160 EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('_'));
161 EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('2'));
162 EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('$'));
163 EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('@'));
164 EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('+'));
165 EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('-'));
166 EXPECT_FALSE(FileCheckPattern::isValidVarNameStart(':'));
169 static StringRef
bufferize(SourceMgr
&SM
, StringRef Str
) {
170 std::unique_ptr
<MemoryBuffer
> Buffer
=
171 MemoryBuffer::getMemBufferCopy(Str
, "TestBuffer");
172 StringRef StrBufferRef
= Buffer
->getBuffer();
173 SM
.AddNewSourceBuffer(std::move(Buffer
), SMLoc());
177 TEST_F(FileCheckTest
, ParseVar
) {
179 StringRef OrigVarName
= bufferize(SM
, "GoodVar42");
180 StringRef VarName
= OrigVarName
;
181 Expected
<FileCheckPattern::VariableProperties
> ParsedVarResult
=
182 FileCheckPattern::parseVariable(VarName
, SM
);
183 ASSERT_TRUE(bool(ParsedVarResult
));
184 EXPECT_EQ(ParsedVarResult
->Name
, OrigVarName
);
185 EXPECT_TRUE(VarName
.empty());
186 EXPECT_FALSE(ParsedVarResult
->IsPseudo
);
188 VarName
= OrigVarName
= bufferize(SM
, "$GoodGlobalVar");
189 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
190 ASSERT_TRUE(bool(ParsedVarResult
));
191 EXPECT_EQ(ParsedVarResult
->Name
, OrigVarName
);
192 EXPECT_TRUE(VarName
.empty());
193 EXPECT_FALSE(ParsedVarResult
->IsPseudo
);
195 VarName
= OrigVarName
= bufferize(SM
, "@GoodPseudoVar");
196 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
197 ASSERT_TRUE(bool(ParsedVarResult
));
198 EXPECT_EQ(ParsedVarResult
->Name
, OrigVarName
);
199 EXPECT_TRUE(VarName
.empty());
200 EXPECT_TRUE(ParsedVarResult
->IsPseudo
);
202 VarName
= bufferize(SM
, "42BadVar");
203 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
204 EXPECT_TRUE(errorToBool(ParsedVarResult
.takeError()));
206 VarName
= bufferize(SM
, "$@");
207 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
208 EXPECT_TRUE(errorToBool(ParsedVarResult
.takeError()));
210 VarName
= OrigVarName
= bufferize(SM
, "B@dVar");
211 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
212 ASSERT_TRUE(bool(ParsedVarResult
));
213 EXPECT_EQ(VarName
, OrigVarName
.substr(1));
214 EXPECT_EQ(ParsedVarResult
->Name
, "B");
215 EXPECT_FALSE(ParsedVarResult
->IsPseudo
);
217 VarName
= OrigVarName
= bufferize(SM
, "B$dVar");
218 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
219 ASSERT_TRUE(bool(ParsedVarResult
));
220 EXPECT_EQ(VarName
, OrigVarName
.substr(1));
221 EXPECT_EQ(ParsedVarResult
->Name
, "B");
222 EXPECT_FALSE(ParsedVarResult
->IsPseudo
);
224 VarName
= bufferize(SM
, "BadVar+");
225 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
226 ASSERT_TRUE(bool(ParsedVarResult
));
227 EXPECT_EQ(VarName
, "+");
228 EXPECT_EQ(ParsedVarResult
->Name
, "BadVar");
229 EXPECT_FALSE(ParsedVarResult
->IsPseudo
);
231 VarName
= bufferize(SM
, "BadVar-");
232 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
233 ASSERT_TRUE(bool(ParsedVarResult
));
234 EXPECT_EQ(VarName
, "-");
235 EXPECT_EQ(ParsedVarResult
->Name
, "BadVar");
236 EXPECT_FALSE(ParsedVarResult
->IsPseudo
);
238 VarName
= bufferize(SM
, "BadVar:");
239 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
240 ASSERT_TRUE(bool(ParsedVarResult
));
241 EXPECT_EQ(VarName
, ":");
242 EXPECT_EQ(ParsedVarResult
->Name
, "BadVar");
243 EXPECT_FALSE(ParsedVarResult
->IsPseudo
);
246 class PatternTester
{
248 size_t LineNumber
= 1;
250 FileCheckRequest Req
;
251 FileCheckPatternContext Context
;
253 FileCheckPattern(Check::CheckPlain
, &Context
, LineNumber
++);
257 std::vector
<std::string
> GlobalDefines
;
258 GlobalDefines
.emplace_back(std::string("#FOO=42"));
259 GlobalDefines
.emplace_back(std::string("BAR=BAZ"));
260 // An ASSERT_FALSE would make more sense but cannot be used in a
263 errorToBool(Context
.defineCmdlineVariables(GlobalDefines
, SM
)));
264 Context
.createLineVariable();
265 // Call parsePattern to have @LINE defined.
266 P
.parsePattern("N/A", "CHECK", SM
, Req
);
267 // parsePattern does not expect to be called twice for the same line and
268 // will set FixedStr and RegExStr incorrectly if it is. Therefore prepare
269 // a pattern for a different line.
273 void initNextPattern() {
274 P
= FileCheckPattern(Check::CheckPlain
, &Context
, LineNumber
++);
277 bool parseSubstExpect(StringRef Expr
) {
278 StringRef ExprBufferRef
= bufferize(SM
, Expr
);
279 Optional
<FileCheckNumericVariable
*> DefinedNumericVariable
;
281 P
.parseNumericSubstitutionBlock(ExprBufferRef
, DefinedNumericVariable
,
282 false, LineNumber
- 1, &Context
, SM
)
286 bool parsePatternExpect(StringRef Pattern
) {
287 StringRef PatBufferRef
= bufferize(SM
, Pattern
);
288 return P
.parsePattern(PatBufferRef
, "CHECK", SM
, Req
);
291 bool matchExpect(StringRef Buffer
) {
292 StringRef BufferRef
= bufferize(SM
, Buffer
);
294 return errorToBool(P
.match(BufferRef
, MatchLen
, SM
).takeError());
298 TEST_F(FileCheckTest
, ParseExpr
) {
299 PatternTester Tester
;
301 // Variable definition.
303 // Definition of invalid variable.
304 EXPECT_TRUE(Tester
.parseSubstExpect("10VAR:"));
305 EXPECT_TRUE(Tester
.parseSubstExpect("@FOO:"));
306 EXPECT_TRUE(Tester
.parseSubstExpect("@LINE:"));
308 // Conflict with pattern variable.
309 EXPECT_TRUE(Tester
.parseSubstExpect("BAR:"));
311 // Garbage after name of variable being defined.
312 EXPECT_TRUE(Tester
.parseSubstExpect("VAR GARBAGE:"));
314 // Acceptable variable definition.
315 EXPECT_FALSE(Tester
.parseSubstExpect("VAR1:"));
316 EXPECT_FALSE(Tester
.parseSubstExpect(" VAR2:"));
317 EXPECT_FALSE(Tester
.parseSubstExpect("VAR3 :"));
318 EXPECT_FALSE(Tester
.parseSubstExpect("VAR3: "));
319 EXPECT_FALSE(Tester
.parsePatternExpect("[[#FOOBAR: FOO+1]]"));
321 // Numeric expression.
323 // Unacceptable variable.
324 EXPECT_TRUE(Tester
.parseSubstExpect("10VAR"));
325 EXPECT_TRUE(Tester
.parseSubstExpect("@FOO"));
327 // Only valid variable.
328 EXPECT_FALSE(Tester
.parseSubstExpect("@LINE"));
329 EXPECT_FALSE(Tester
.parseSubstExpect("FOO"));
330 EXPECT_FALSE(Tester
.parseSubstExpect("UNDEF"));
332 // Valid empty expression.
333 EXPECT_FALSE(Tester
.parseSubstExpect(""));
335 // Valid use of variable defined on the same line from expression. Note that
336 // the same pattern object is used for the parsePatternExpect and
337 // parseSubstExpect since no initNextPattern is called, thus appearing as
338 // being on the same line from the pattern's point of view.
339 ASSERT_FALSE(Tester
.parsePatternExpect("[[#LINE1VAR:FOO+1]]"));
340 EXPECT_FALSE(Tester
.parseSubstExpect("LINE1VAR"));
342 // Invalid use of variable defined on same line from input. As above, the
343 // absence of a call to initNextPattern makes it appear to be on the same
344 // line from the pattern's point of view.
345 ASSERT_FALSE(Tester
.parsePatternExpect("[[#LINE2VAR:]]"));
346 EXPECT_TRUE(Tester
.parseSubstExpect("LINE2VAR"));
348 // Unsupported operator.
349 EXPECT_TRUE(Tester
.parseSubstExpect("@LINE/2"));
351 // Missing offset operand.
352 EXPECT_TRUE(Tester
.parseSubstExpect("@LINE+"));
355 EXPECT_FALSE(Tester
.parseSubstExpect("@LINE+5"));
356 EXPECT_FALSE(Tester
.parseSubstExpect("FOO+4"));
357 EXPECT_FALSE(Tester
.parseSubstExpect("FOOBAR"));
358 Tester
.initNextPattern();
359 EXPECT_FALSE(Tester
.parsePatternExpect("[[#FOO+FOO]]"));
360 EXPECT_FALSE(Tester
.parsePatternExpect("[[#FOO+3-FOO]]"));
363 TEST_F(FileCheckTest
, ParsePattern
) {
364 PatternTester Tester
;
366 // Space in pattern variable expression.
367 EXPECT_TRUE(Tester
.parsePatternExpect("[[ BAR]]"));
369 // Invalid variable name.
370 EXPECT_TRUE(Tester
.parsePatternExpect("[[42INVALID]]"));
372 // Invalid pattern variable definition.
373 EXPECT_TRUE(Tester
.parsePatternExpect("[[@PAT:]]"));
374 EXPECT_TRUE(Tester
.parsePatternExpect("[[PAT+2:]]"));
376 // Collision with numeric variable.
377 EXPECT_TRUE(Tester
.parsePatternExpect("[[FOO:]]"));
379 // Valid use of pattern variable.
380 EXPECT_FALSE(Tester
.parsePatternExpect("[[BAR]]"));
382 // Valid pattern variable definition.
383 EXPECT_FALSE(Tester
.parsePatternExpect("[[PAT:[0-9]+]]"));
385 // Invalid numeric expressions.
386 EXPECT_TRUE(Tester
.parsePatternExpect("[[#42INVALID]]"));
387 EXPECT_TRUE(Tester
.parsePatternExpect("[[#@FOO]]"));
388 EXPECT_TRUE(Tester
.parsePatternExpect("[[#@LINE/2]]"));
390 // Valid numeric expressions and numeric variable definition.
391 EXPECT_FALSE(Tester
.parsePatternExpect("[[#FOO]]"));
392 EXPECT_FALSE(Tester
.parsePatternExpect("[[#@LINE+2]]"));
393 EXPECT_FALSE(Tester
.parsePatternExpect("[[#NUMVAR:]]"));
396 TEST_F(FileCheckTest
, Match
) {
397 PatternTester Tester
;
399 // Check matching an empty expression only matches a number.
400 Tester
.parsePatternExpect("[[#]]");
401 EXPECT_TRUE(Tester
.matchExpect("FAIL"));
402 EXPECT_FALSE(Tester
.matchExpect("18"));
404 // Check matching a definition only matches a number.
405 Tester
.initNextPattern();
406 Tester
.parsePatternExpect("[[#NUMVAR:]]");
407 EXPECT_TRUE(Tester
.matchExpect("FAIL"));
408 EXPECT_TRUE(Tester
.matchExpect(""));
409 EXPECT_FALSE(Tester
.matchExpect("18"));
411 // Check matching the variable defined matches the correct number only
412 Tester
.initNextPattern();
413 Tester
.parsePatternExpect("[[#NUMVAR]] [[#NUMVAR+2]]");
414 EXPECT_TRUE(Tester
.matchExpect("19 21"));
415 EXPECT_TRUE(Tester
.matchExpect("18 21"));
416 EXPECT_FALSE(Tester
.matchExpect("18 20"));
418 // Check matching a numeric expression using @LINE after match failure uses
419 // the correct value for @LINE.
420 Tester
.initNextPattern();
421 EXPECT_FALSE(Tester
.parsePatternExpect("[[#@LINE]]"));
422 // Ok, @LINE is 5 now.
423 EXPECT_FALSE(Tester
.matchExpect("5"));
424 Tester
.initNextPattern();
425 // @LINE is now 6, match with substitution failure.
426 EXPECT_FALSE(Tester
.parsePatternExpect("[[#UNKNOWN]]"));
427 EXPECT_TRUE(Tester
.matchExpect("FOO"));
428 Tester
.initNextPattern();
429 // Check that @LINE is 7 as expected.
430 EXPECT_FALSE(Tester
.parsePatternExpect("[[#@LINE]]"));
431 EXPECT_FALSE(Tester
.matchExpect("7"));
434 TEST_F(FileCheckTest
, Substitution
) {
436 FileCheckPatternContext Context
;
437 std::vector
<std::string
> GlobalDefines
;
438 GlobalDefines
.emplace_back(std::string("FOO=BAR"));
439 EXPECT_FALSE(errorToBool(Context
.defineCmdlineVariables(GlobalDefines
, SM
)));
441 // Substitution of an undefined string variable fails and error holds that
443 FileCheckStringSubstitution StringSubstitution
=
444 FileCheckStringSubstitution(&Context
, "VAR404", 42);
445 Expected
<std::string
> SubstValue
= StringSubstitution
.getResult();
446 ASSERT_FALSE(bool(SubstValue
));
447 expectUndefError("VAR404", SubstValue
.takeError());
449 // Substitutions of defined pseudo and non-pseudo numeric variables return
451 FileCheckNumericVariable LineVar
= FileCheckNumericVariable("@LINE", 1);
452 FileCheckNumericVariable NVar
= FileCheckNumericVariable("N", 1);
453 LineVar
.setValue(42);
456 std::make_unique
<FileCheckNumericVariableUse
>("@LINE", &LineVar
);
457 auto NVarUse
= std::make_unique
<FileCheckNumericVariableUse
>("N", &NVar
);
458 FileCheckNumericSubstitution SubstitutionLine
= FileCheckNumericSubstitution(
459 &Context
, "@LINE", std::move(LineVarUse
), 12);
460 FileCheckNumericSubstitution SubstitutionN
=
461 FileCheckNumericSubstitution(&Context
, "N", std::move(NVarUse
), 30);
462 SubstValue
= SubstitutionLine
.getResult();
463 ASSERT_TRUE(bool(SubstValue
));
464 EXPECT_EQ("42", *SubstValue
);
465 SubstValue
= SubstitutionN
.getResult();
466 ASSERT_TRUE(bool(SubstValue
));
467 EXPECT_EQ("10", *SubstValue
);
469 // Substitution of an undefined numeric variable fails, error holds name of
470 // undefined variable.
471 LineVar
.clearValue();
472 SubstValue
= SubstitutionLine
.getResult();
473 ASSERT_FALSE(bool(SubstValue
));
474 expectUndefError("@LINE", SubstValue
.takeError());
476 SubstValue
= SubstitutionN
.getResult();
477 ASSERT_FALSE(bool(SubstValue
));
478 expectUndefError("N", SubstValue
.takeError());
480 // Substitution of a defined string variable returns the right value.
481 FileCheckPattern P
= FileCheckPattern(Check::CheckPlain
, &Context
, 1);
482 StringSubstitution
= FileCheckStringSubstitution(&Context
, "FOO", 42);
483 SubstValue
= StringSubstitution
.getResult();
484 ASSERT_TRUE(bool(SubstValue
));
485 EXPECT_EQ("BAR", *SubstValue
);
488 TEST_F(FileCheckTest
, FileCheckContext
) {
489 FileCheckPatternContext Cxt
= FileCheckPatternContext();
490 std::vector
<std::string
> GlobalDefines
;
493 // Missing equal sign.
494 GlobalDefines
.emplace_back(std::string("LocalVar"));
495 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
496 GlobalDefines
.clear();
497 GlobalDefines
.emplace_back(std::string("#LocalNumVar"));
498 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
500 // Empty variable name.
501 GlobalDefines
.clear();
502 GlobalDefines
.emplace_back(std::string("=18"));
503 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
504 GlobalDefines
.clear();
505 GlobalDefines
.emplace_back(std::string("#=18"));
506 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
508 // Invalid variable name.
509 GlobalDefines
.clear();
510 GlobalDefines
.emplace_back(std::string("18LocalVar=18"));
511 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
512 GlobalDefines
.clear();
513 GlobalDefines
.emplace_back(std::string("#18LocalNumVar=18"));
514 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
516 // Name conflict between pattern and numeric variable.
517 GlobalDefines
.clear();
518 GlobalDefines
.emplace_back(std::string("LocalVar=18"));
519 GlobalDefines
.emplace_back(std::string("#LocalVar=36"));
520 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
521 Cxt
= FileCheckPatternContext();
522 GlobalDefines
.clear();
523 GlobalDefines
.emplace_back(std::string("#LocalNumVar=18"));
524 GlobalDefines
.emplace_back(std::string("LocalNumVar=36"));
525 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
526 Cxt
= FileCheckPatternContext();
528 // Invalid numeric value for numeric variable.
529 GlobalDefines
.clear();
530 GlobalDefines
.emplace_back(std::string("#LocalNumVar=x"));
531 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
533 // Define local variables from command-line.
534 GlobalDefines
.clear();
535 // Clear local variables to remove dummy numeric variable x that
536 // parseNumericSubstitutionBlock would have created and stored in
537 // GlobalNumericVariableTable.
538 Cxt
.clearLocalVars();
539 GlobalDefines
.emplace_back(std::string("LocalVar=FOO"));
540 GlobalDefines
.emplace_back(std::string("EmptyVar="));
541 GlobalDefines
.emplace_back(std::string("#LocalNumVar1=18"));
542 GlobalDefines
.emplace_back(std::string("#LocalNumVar2=LocalNumVar1+2"));
543 ASSERT_FALSE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
545 // Check defined variables are present and undefined is absent.
546 StringRef LocalVarStr
= "LocalVar";
547 StringRef LocalNumVar1Ref
= bufferize(SM
, "LocalNumVar1");
548 StringRef LocalNumVar2Ref
= bufferize(SM
, "LocalNumVar2");
549 StringRef EmptyVarStr
= "EmptyVar";
550 StringRef UnknownVarStr
= "UnknownVar";
551 Expected
<StringRef
> LocalVar
= Cxt
.getPatternVarValue(LocalVarStr
);
552 FileCheckPattern P
= FileCheckPattern(Check::CheckPlain
, &Cxt
, 1);
553 Optional
<FileCheckNumericVariable
*> DefinedNumericVariable
;
554 Expected
<std::unique_ptr
<FileCheckExpressionAST
>> ExpressionAST
=
555 P
.parseNumericSubstitutionBlock(LocalNumVar1Ref
, DefinedNumericVariable
,
556 /*IsLegacyLineExpr=*/false,
557 /*LineNumber=*/1, &Cxt
, SM
);
558 ASSERT_TRUE(bool(LocalVar
));
559 EXPECT_EQ(*LocalVar
, "FOO");
560 Expected
<StringRef
> EmptyVar
= Cxt
.getPatternVarValue(EmptyVarStr
);
561 Expected
<StringRef
> UnknownVar
= Cxt
.getPatternVarValue(UnknownVarStr
);
562 ASSERT_TRUE(bool(ExpressionAST
));
563 Expected
<uint64_t> ExpressionVal
= (*ExpressionAST
)->eval();
564 ASSERT_TRUE(bool(ExpressionVal
));
565 EXPECT_EQ(*ExpressionVal
, 18U);
567 P
.parseNumericSubstitutionBlock(LocalNumVar2Ref
, DefinedNumericVariable
,
568 /*IsLegacyLineExpr=*/false,
569 /*LineNumber=*/1, &Cxt
, SM
);
570 ASSERT_TRUE(bool(ExpressionAST
));
571 ExpressionVal
= (*ExpressionAST
)->eval();
572 ASSERT_TRUE(bool(ExpressionVal
));
573 EXPECT_EQ(*ExpressionVal
, 20U);
574 ASSERT_TRUE(bool(EmptyVar
));
575 EXPECT_EQ(*EmptyVar
, "");
576 EXPECT_TRUE(errorToBool(UnknownVar
.takeError()));
578 // Clear local variables and check they become absent.
579 Cxt
.clearLocalVars();
580 LocalVar
= Cxt
.getPatternVarValue(LocalVarStr
);
581 EXPECT_TRUE(errorToBool(LocalVar
.takeError()));
582 // Check a numeric expression's evaluation fails if called after clearing of
583 // local variables, if it was created before. This is important because local
584 // variable clearing due to --enable-var-scope happens after numeric
585 // expressions are linked to the numeric variables they use.
586 EXPECT_TRUE(errorToBool((*ExpressionAST
)->eval().takeError()));
587 P
= FileCheckPattern(Check::CheckPlain
, &Cxt
, 2);
588 ExpressionAST
= P
.parseNumericSubstitutionBlock(
589 LocalNumVar1Ref
, DefinedNumericVariable
, /*IsLegacyLineExpr=*/false,
590 /*LineNumber=*/2, &Cxt
, SM
);
591 ASSERT_TRUE(bool(ExpressionAST
));
592 ExpressionVal
= (*ExpressionAST
)->eval();
593 EXPECT_TRUE(errorToBool(ExpressionVal
.takeError()));
594 ExpressionAST
= P
.parseNumericSubstitutionBlock(
595 LocalNumVar2Ref
, DefinedNumericVariable
, /*IsLegacyLineExpr=*/false,
596 /*LineNumber=*/2, &Cxt
, SM
);
597 ASSERT_TRUE(bool(ExpressionAST
));
598 ExpressionVal
= (*ExpressionAST
)->eval();
599 EXPECT_TRUE(errorToBool(ExpressionVal
.takeError()));
600 EmptyVar
= Cxt
.getPatternVarValue(EmptyVarStr
);
601 EXPECT_TRUE(errorToBool(EmptyVar
.takeError()));
602 // Clear again because parseNumericSubstitutionBlock would have created a
603 // dummy variable and stored it in GlobalNumericVariableTable.
604 Cxt
.clearLocalVars();
606 // Redefine global variables and check variables are defined again.
607 GlobalDefines
.emplace_back(std::string("$GlobalVar=BAR"));
608 GlobalDefines
.emplace_back(std::string("#$GlobalNumVar=36"));
609 ASSERT_FALSE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
610 StringRef GlobalVarStr
= "$GlobalVar";
611 StringRef GlobalNumVarRef
= bufferize(SM
, "$GlobalNumVar");
612 Expected
<StringRef
> GlobalVar
= Cxt
.getPatternVarValue(GlobalVarStr
);
613 ASSERT_TRUE(bool(GlobalVar
));
614 EXPECT_EQ(*GlobalVar
, "BAR");
615 P
= FileCheckPattern(Check::CheckPlain
, &Cxt
, 3);
616 ExpressionAST
= P
.parseNumericSubstitutionBlock(
617 GlobalNumVarRef
, DefinedNumericVariable
, /*IsLegacyLineExpr=*/false,
618 /*LineNumber=*/3, &Cxt
, SM
);
619 ASSERT_TRUE(bool(ExpressionAST
));
620 ExpressionVal
= (*ExpressionAST
)->eval();
621 ASSERT_TRUE(bool(ExpressionVal
));
622 EXPECT_EQ(*ExpressionVal
, 36U);
624 // Clear local variables and check global variables remain defined.
625 Cxt
.clearLocalVars();
626 EXPECT_FALSE(errorToBool(Cxt
.getPatternVarValue(GlobalVarStr
).takeError()));
627 P
= FileCheckPattern(Check::CheckPlain
, &Cxt
, 4);
628 ExpressionAST
= P
.parseNumericSubstitutionBlock(
629 GlobalNumVarRef
, DefinedNumericVariable
, /*IsLegacyLineExpr=*/false,
630 /*LineNumber=*/4, &Cxt
, SM
);
631 ASSERT_TRUE(bool(ExpressionAST
));
632 ExpressionVal
= (*ExpressionAST
)->eval();
633 ASSERT_TRUE(bool(ExpressionVal
));
634 EXPECT_EQ(*ExpressionVal
, 36U);