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: getValue and eval fail, error returned by eval holds
62 // the name of the undefined variable.
63 FileCheckNumericVariable FooVar
= FileCheckNumericVariable("FOO", 1);
64 EXPECT_EQ("FOO", FooVar
.getName());
65 FileCheckNumericVariableUse FooVarUse
=
66 FileCheckNumericVariableUse("FOO", &FooVar
);
67 EXPECT_FALSE(FooVar
.getValue());
68 Expected
<uint64_t> EvalResult
= FooVarUse
.eval();
69 ASSERT_FALSE(EvalResult
);
70 expectUndefError("FOO", EvalResult
.takeError());
74 // Defined variable: getValue and eval return value set.
75 Optional
<uint64_t> Value
= FooVar
.getValue();
76 ASSERT_TRUE(bool(Value
));
77 EXPECT_EQ(42U, *Value
);
78 EvalResult
= FooVarUse
.eval();
79 ASSERT_TRUE(bool(EvalResult
));
80 EXPECT_EQ(42U, *EvalResult
);
82 // Clearing variable: getValue and eval fail. Error returned by eval holds
83 // the name of the cleared variable.
85 EXPECT_FALSE(FooVar
.getValue());
86 EvalResult
= FooVarUse
.eval();
87 ASSERT_FALSE(EvalResult
);
88 expectUndefError("FOO", EvalResult
.takeError());
91 TEST_F(FileCheckTest
, Binop
) {
92 FileCheckNumericVariable FooVar
= FileCheckNumericVariable("FOO", 1);
94 std::unique_ptr
<FileCheckNumericVariableUse
> FooVarUse
=
95 std::make_unique
<FileCheckNumericVariableUse
>("FOO", &FooVar
);
96 FileCheckNumericVariable BarVar
= FileCheckNumericVariable("BAR", 2);
98 std::unique_ptr
<FileCheckNumericVariableUse
> BarVarUse
=
99 std::make_unique
<FileCheckNumericVariableUse
>("BAR", &BarVar
);
100 FileCheckASTBinop Binop
=
101 FileCheckASTBinop(doAdd
, std::move(FooVarUse
), std::move(BarVarUse
));
103 // Defined variable: eval returns right value.
104 Expected
<uint64_t> Value
= Binop
.eval();
105 ASSERT_TRUE(bool(Value
));
106 EXPECT_EQ(60U, *Value
);
108 // 1 undefined variable: eval fails, error contains name of undefined
111 Value
= Binop
.eval();
113 expectUndefError("FOO", Value
.takeError());
115 // 2 undefined variables: eval fails, error contains names of all undefined
118 Value
= Binop
.eval();
120 expectUndefErrors({"FOO", "BAR"}, Value
.takeError());
123 TEST_F(FileCheckTest
, ValidVarNameStart
) {
124 EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('a'));
125 EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('G'));
126 EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('_'));
127 EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('2'));
128 EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('$'));
129 EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('@'));
130 EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('+'));
131 EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('-'));
132 EXPECT_FALSE(FileCheckPattern::isValidVarNameStart(':'));
135 static StringRef
bufferize(SourceMgr
&SM
, StringRef Str
) {
136 std::unique_ptr
<MemoryBuffer
> Buffer
=
137 MemoryBuffer::getMemBufferCopy(Str
, "TestBuffer");
138 StringRef StrBufferRef
= Buffer
->getBuffer();
139 SM
.AddNewSourceBuffer(std::move(Buffer
), SMLoc());
143 TEST_F(FileCheckTest
, ParseVar
) {
145 StringRef OrigVarName
= bufferize(SM
, "GoodVar42");
146 StringRef VarName
= OrigVarName
;
147 Expected
<FileCheckPattern::VariableProperties
> ParsedVarResult
=
148 FileCheckPattern::parseVariable(VarName
, SM
);
149 ASSERT_TRUE(bool(ParsedVarResult
));
150 EXPECT_EQ(ParsedVarResult
->Name
, OrigVarName
);
151 EXPECT_TRUE(VarName
.empty());
152 EXPECT_FALSE(ParsedVarResult
->IsPseudo
);
154 VarName
= OrigVarName
= bufferize(SM
, "$GoodGlobalVar");
155 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
156 ASSERT_TRUE(bool(ParsedVarResult
));
157 EXPECT_EQ(ParsedVarResult
->Name
, OrigVarName
);
158 EXPECT_TRUE(VarName
.empty());
159 EXPECT_FALSE(ParsedVarResult
->IsPseudo
);
161 VarName
= OrigVarName
= bufferize(SM
, "@GoodPseudoVar");
162 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
163 ASSERT_TRUE(bool(ParsedVarResult
));
164 EXPECT_EQ(ParsedVarResult
->Name
, OrigVarName
);
165 EXPECT_TRUE(VarName
.empty());
166 EXPECT_TRUE(ParsedVarResult
->IsPseudo
);
168 VarName
= bufferize(SM
, "42BadVar");
169 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
170 EXPECT_TRUE(errorToBool(ParsedVarResult
.takeError()));
172 VarName
= bufferize(SM
, "$@");
173 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
174 EXPECT_TRUE(errorToBool(ParsedVarResult
.takeError()));
176 VarName
= OrigVarName
= bufferize(SM
, "B@dVar");
177 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
178 ASSERT_TRUE(bool(ParsedVarResult
));
179 EXPECT_EQ(VarName
, OrigVarName
.substr(1));
180 EXPECT_EQ(ParsedVarResult
->Name
, "B");
181 EXPECT_FALSE(ParsedVarResult
->IsPseudo
);
183 VarName
= OrigVarName
= bufferize(SM
, "B$dVar");
184 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
185 ASSERT_TRUE(bool(ParsedVarResult
));
186 EXPECT_EQ(VarName
, OrigVarName
.substr(1));
187 EXPECT_EQ(ParsedVarResult
->Name
, "B");
188 EXPECT_FALSE(ParsedVarResult
->IsPseudo
);
190 VarName
= bufferize(SM
, "BadVar+");
191 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
192 ASSERT_TRUE(bool(ParsedVarResult
));
193 EXPECT_EQ(VarName
, "+");
194 EXPECT_EQ(ParsedVarResult
->Name
, "BadVar");
195 EXPECT_FALSE(ParsedVarResult
->IsPseudo
);
197 VarName
= bufferize(SM
, "BadVar-");
198 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
199 ASSERT_TRUE(bool(ParsedVarResult
));
200 EXPECT_EQ(VarName
, "-");
201 EXPECT_EQ(ParsedVarResult
->Name
, "BadVar");
202 EXPECT_FALSE(ParsedVarResult
->IsPseudo
);
204 VarName
= bufferize(SM
, "BadVar:");
205 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
206 ASSERT_TRUE(bool(ParsedVarResult
));
207 EXPECT_EQ(VarName
, ":");
208 EXPECT_EQ(ParsedVarResult
->Name
, "BadVar");
209 EXPECT_FALSE(ParsedVarResult
->IsPseudo
);
212 class PatternTester
{
214 size_t LineNumber
= 1;
216 FileCheckRequest Req
;
217 FileCheckPatternContext Context
;
219 FileCheckPattern(Check::CheckPlain
, &Context
, LineNumber
++);
223 std::vector
<std::string
> GlobalDefines
;
224 GlobalDefines
.emplace_back(std::string("#FOO=42"));
225 GlobalDefines
.emplace_back(std::string("BAR=BAZ"));
226 // An ASSERT_FALSE would make more sense but cannot be used in a
229 errorToBool(Context
.defineCmdlineVariables(GlobalDefines
, SM
)));
230 Context
.createLineVariable();
231 // Call parsePattern to have @LINE defined.
232 P
.parsePattern("N/A", "CHECK", SM
, Req
);
233 // parsePattern does not expect to be called twice for the same line and
234 // will set FixedStr and RegExStr incorrectly if it is. Therefore prepare
235 // a pattern for a different line.
239 void initNextPattern() {
240 P
= FileCheckPattern(Check::CheckPlain
, &Context
, LineNumber
++);
243 bool parseSubstExpect(StringRef Expr
) {
244 StringRef ExprBufferRef
= bufferize(SM
, Expr
);
245 Optional
<FileCheckNumericVariable
*> DefinedNumericVariable
;
247 P
.parseNumericSubstitutionBlock(ExprBufferRef
, DefinedNumericVariable
,
248 false, LineNumber
- 1, &Context
, SM
)
252 bool parsePatternExpect(StringRef Pattern
) {
253 StringRef PatBufferRef
= bufferize(SM
, Pattern
);
254 return P
.parsePattern(PatBufferRef
, "CHECK", SM
, Req
);
257 bool matchExpect(StringRef Buffer
) {
258 StringRef BufferRef
= bufferize(SM
, Buffer
);
260 return errorToBool(P
.match(BufferRef
, MatchLen
, SM
).takeError());
264 TEST_F(FileCheckTest
, ParseExpr
) {
265 PatternTester Tester
;
267 // Variable definition.
269 // Definition of invalid variable.
270 EXPECT_TRUE(Tester
.parseSubstExpect("10VAR:"));
271 EXPECT_TRUE(Tester
.parseSubstExpect("@FOO:"));
272 EXPECT_TRUE(Tester
.parseSubstExpect("@LINE:"));
274 // Conflict with pattern variable.
275 EXPECT_TRUE(Tester
.parseSubstExpect("BAR:"));
277 // Garbage after name of variable being defined.
278 EXPECT_TRUE(Tester
.parseSubstExpect("VAR GARBAGE:"));
280 // Acceptable variable definition.
281 EXPECT_FALSE(Tester
.parseSubstExpect("VAR1:"));
282 EXPECT_FALSE(Tester
.parseSubstExpect(" VAR2:"));
283 EXPECT_FALSE(Tester
.parseSubstExpect("VAR3 :"));
284 EXPECT_FALSE(Tester
.parseSubstExpect("VAR3: "));
285 EXPECT_FALSE(Tester
.parsePatternExpect("[[#FOOBAR: FOO+1]]"));
287 // Numeric expression.
289 // Unacceptable variable.
290 EXPECT_TRUE(Tester
.parseSubstExpect("10VAR"));
291 EXPECT_TRUE(Tester
.parseSubstExpect("@FOO"));
293 // Only valid variable.
294 EXPECT_FALSE(Tester
.parseSubstExpect("@LINE"));
295 EXPECT_FALSE(Tester
.parseSubstExpect("FOO"));
296 EXPECT_FALSE(Tester
.parseSubstExpect("UNDEF"));
298 // Valid empty expression.
299 EXPECT_FALSE(Tester
.parseSubstExpect(""));
301 // Invalid use of variable defined on the same line from expression. Note
302 // that the same pattern object is used for the parsePatternExpect and
303 // parseSubstExpect since no initNextPattern is called, thus appearing as
304 // being on the same line from the pattern's point of view.
305 ASSERT_FALSE(Tester
.parsePatternExpect("[[#LINE1VAR:FOO+1]]"));
306 EXPECT_TRUE(Tester
.parseSubstExpect("LINE1VAR"));
308 // Invalid use of variable defined on same line from input. As above, the
309 // absence of a call to initNextPattern makes it appear to be on the same
310 // line from the pattern's point of view.
311 ASSERT_FALSE(Tester
.parsePatternExpect("[[#LINE2VAR:]]"));
312 EXPECT_TRUE(Tester
.parseSubstExpect("LINE2VAR"));
314 // Unsupported operator.
315 EXPECT_TRUE(Tester
.parseSubstExpect("@LINE/2"));
317 // Missing offset operand.
318 EXPECT_TRUE(Tester
.parseSubstExpect("@LINE+"));
321 EXPECT_FALSE(Tester
.parseSubstExpect("@LINE+5"));
322 EXPECT_FALSE(Tester
.parseSubstExpect("FOO+4"));
323 Tester
.initNextPattern();
324 EXPECT_FALSE(Tester
.parseSubstExpect("FOOBAR"));
325 EXPECT_FALSE(Tester
.parseSubstExpect("LINE1VAR"));
326 EXPECT_FALSE(Tester
.parsePatternExpect("[[#FOO+FOO]]"));
327 EXPECT_FALSE(Tester
.parsePatternExpect("[[#FOO+3-FOO]]"));
330 TEST_F(FileCheckTest
, ParsePattern
) {
331 PatternTester Tester
;
333 // Space in pattern variable expression.
334 EXPECT_TRUE(Tester
.parsePatternExpect("[[ BAR]]"));
336 // Invalid variable name.
337 EXPECT_TRUE(Tester
.parsePatternExpect("[[42INVALID]]"));
339 // Invalid pattern variable definition.
340 EXPECT_TRUE(Tester
.parsePatternExpect("[[@PAT:]]"));
341 EXPECT_TRUE(Tester
.parsePatternExpect("[[PAT+2:]]"));
343 // Collision with numeric variable.
344 EXPECT_TRUE(Tester
.parsePatternExpect("[[FOO:]]"));
346 // Valid use of pattern variable.
347 EXPECT_FALSE(Tester
.parsePatternExpect("[[BAR]]"));
349 // Valid pattern variable definition.
350 EXPECT_FALSE(Tester
.parsePatternExpect("[[PAT:[0-9]+]]"));
352 // Invalid numeric expressions.
353 EXPECT_TRUE(Tester
.parsePatternExpect("[[#42INVALID]]"));
354 EXPECT_TRUE(Tester
.parsePatternExpect("[[#@FOO]]"));
355 EXPECT_TRUE(Tester
.parsePatternExpect("[[#@LINE/2]]"));
357 // Valid numeric expressions and numeric variable definition.
358 EXPECT_FALSE(Tester
.parsePatternExpect("[[#FOO]]"));
359 EXPECT_FALSE(Tester
.parsePatternExpect("[[#@LINE+2]]"));
360 EXPECT_FALSE(Tester
.parsePatternExpect("[[#NUMVAR:]]"));
363 TEST_F(FileCheckTest
, Match
) {
364 PatternTester Tester
;
366 // Check matching an empty expression only matches a number.
367 Tester
.parsePatternExpect("[[#]]");
368 EXPECT_TRUE(Tester
.matchExpect("FAIL"));
369 EXPECT_FALSE(Tester
.matchExpect("18"));
371 // Check matching a definition only matches a number.
372 Tester
.initNextPattern();
373 Tester
.parsePatternExpect("[[#NUMVAR:]]");
374 EXPECT_TRUE(Tester
.matchExpect("FAIL"));
375 EXPECT_TRUE(Tester
.matchExpect(""));
376 EXPECT_FALSE(Tester
.matchExpect("18"));
378 // Check matching the variable defined matches the correct number only
379 Tester
.initNextPattern();
380 Tester
.parsePatternExpect("[[#NUMVAR]] [[#NUMVAR+2]]");
381 EXPECT_TRUE(Tester
.matchExpect("19 21"));
382 EXPECT_TRUE(Tester
.matchExpect("18 21"));
383 EXPECT_FALSE(Tester
.matchExpect("18 20"));
385 // Check matching a numeric expression using @LINE after match failure uses
386 // the correct value for @LINE.
387 Tester
.initNextPattern();
388 EXPECT_FALSE(Tester
.parsePatternExpect("[[#@LINE]]"));
389 // Ok, @LINE is 5 now.
390 EXPECT_FALSE(Tester
.matchExpect("5"));
391 Tester
.initNextPattern();
392 // @LINE is now 6, match with substitution failure.
393 EXPECT_FALSE(Tester
.parsePatternExpect("[[#UNKNOWN]]"));
394 EXPECT_TRUE(Tester
.matchExpect("FOO"));
395 Tester
.initNextPattern();
396 // Check that @LINE is 7 as expected.
397 EXPECT_FALSE(Tester
.parsePatternExpect("[[#@LINE]]"));
398 EXPECT_FALSE(Tester
.matchExpect("7"));
401 TEST_F(FileCheckTest
, Substitution
) {
403 FileCheckPatternContext Context
;
404 std::vector
<std::string
> GlobalDefines
;
405 GlobalDefines
.emplace_back(std::string("FOO=BAR"));
406 EXPECT_FALSE(errorToBool(Context
.defineCmdlineVariables(GlobalDefines
, SM
)));
408 // Substitution of an undefined string variable fails and error holds that
410 FileCheckStringSubstitution StringSubstitution
=
411 FileCheckStringSubstitution(&Context
, "VAR404", 42);
412 Expected
<std::string
> SubstValue
= StringSubstitution
.getResult();
413 ASSERT_FALSE(bool(SubstValue
));
414 expectUndefError("VAR404", SubstValue
.takeError());
416 // Substitutions of defined pseudo and non-pseudo numeric variables return
418 FileCheckNumericVariable LineVar
= FileCheckNumericVariable("@LINE", 1);
419 FileCheckNumericVariable NVar
= FileCheckNumericVariable("N", 1);
420 LineVar
.setValue(42);
423 std::make_unique
<FileCheckNumericVariableUse
>("@LINE", &LineVar
);
424 auto NVarUse
= std::make_unique
<FileCheckNumericVariableUse
>("N", &NVar
);
425 FileCheckNumericSubstitution SubstitutionLine
= FileCheckNumericSubstitution(
426 &Context
, "@LINE", std::move(LineVarUse
), 12);
427 FileCheckNumericSubstitution SubstitutionN
=
428 FileCheckNumericSubstitution(&Context
, "N", std::move(NVarUse
), 30);
429 SubstValue
= SubstitutionLine
.getResult();
430 ASSERT_TRUE(bool(SubstValue
));
431 EXPECT_EQ("42", *SubstValue
);
432 SubstValue
= SubstitutionN
.getResult();
433 ASSERT_TRUE(bool(SubstValue
));
434 EXPECT_EQ("10", *SubstValue
);
436 // Substitution of an undefined numeric variable fails, error holds name of
437 // undefined variable.
438 LineVar
.clearValue();
439 SubstValue
= SubstitutionLine
.getResult();
440 ASSERT_FALSE(bool(SubstValue
));
441 expectUndefError("@LINE", SubstValue
.takeError());
443 SubstValue
= SubstitutionN
.getResult();
444 ASSERT_FALSE(bool(SubstValue
));
445 expectUndefError("N", SubstValue
.takeError());
447 // Substitution of a defined string variable returns the right value.
448 FileCheckPattern P
= FileCheckPattern(Check::CheckPlain
, &Context
, 1);
449 StringSubstitution
= FileCheckStringSubstitution(&Context
, "FOO", 42);
450 SubstValue
= StringSubstitution
.getResult();
451 ASSERT_TRUE(bool(SubstValue
));
452 EXPECT_EQ("BAR", *SubstValue
);
455 TEST_F(FileCheckTest
, FileCheckContext
) {
456 FileCheckPatternContext Cxt
= FileCheckPatternContext();
457 std::vector
<std::string
> GlobalDefines
;
460 // Missing equal sign.
461 GlobalDefines
.emplace_back(std::string("LocalVar"));
462 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
463 GlobalDefines
.clear();
464 GlobalDefines
.emplace_back(std::string("#LocalNumVar"));
465 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
467 // Empty variable name.
468 GlobalDefines
.clear();
469 GlobalDefines
.emplace_back(std::string("=18"));
470 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
471 GlobalDefines
.clear();
472 GlobalDefines
.emplace_back(std::string("#=18"));
473 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
475 // Invalid variable name.
476 GlobalDefines
.clear();
477 GlobalDefines
.emplace_back(std::string("18LocalVar=18"));
478 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
479 GlobalDefines
.clear();
480 GlobalDefines
.emplace_back(std::string("#18LocalNumVar=18"));
481 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
483 // Name conflict between pattern and numeric variable.
484 GlobalDefines
.clear();
485 GlobalDefines
.emplace_back(std::string("LocalVar=18"));
486 GlobalDefines
.emplace_back(std::string("#LocalVar=36"));
487 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
488 Cxt
= FileCheckPatternContext();
489 GlobalDefines
.clear();
490 GlobalDefines
.emplace_back(std::string("#LocalNumVar=18"));
491 GlobalDefines
.emplace_back(std::string("LocalNumVar=36"));
492 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
493 Cxt
= FileCheckPatternContext();
495 // Invalid numeric value for numeric variable.
496 GlobalDefines
.clear();
497 GlobalDefines
.emplace_back(std::string("#LocalNumVar=x"));
498 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
500 // Define local variables from command-line.
501 GlobalDefines
.clear();
502 // Clear local variables to remove dummy numeric variable x that
503 // parseNumericSubstitutionBlock would have created and stored in
504 // GlobalNumericVariableTable.
505 Cxt
.clearLocalVars();
506 GlobalDefines
.emplace_back(std::string("LocalVar=FOO"));
507 GlobalDefines
.emplace_back(std::string("EmptyVar="));
508 GlobalDefines
.emplace_back(std::string("#LocalNumVar1=18"));
509 GlobalDefines
.emplace_back(std::string("#LocalNumVar2=LocalNumVar1+2"));
510 ASSERT_FALSE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
512 // Check defined variables are present and undefined is absent.
513 StringRef LocalVarStr
= "LocalVar";
514 StringRef LocalNumVar1Ref
= bufferize(SM
, "LocalNumVar1");
515 StringRef LocalNumVar2Ref
= bufferize(SM
, "LocalNumVar2");
516 StringRef EmptyVarStr
= "EmptyVar";
517 StringRef UnknownVarStr
= "UnknownVar";
518 Expected
<StringRef
> LocalVar
= Cxt
.getPatternVarValue(LocalVarStr
);
519 FileCheckPattern P
= FileCheckPattern(Check::CheckPlain
, &Cxt
, 1);
520 Optional
<FileCheckNumericVariable
*> DefinedNumericVariable
;
521 Expected
<std::unique_ptr
<FileCheckExpressionAST
>> ExpressionAST
=
522 P
.parseNumericSubstitutionBlock(LocalNumVar1Ref
, DefinedNumericVariable
,
523 /*IsLegacyLineExpr=*/false,
524 /*LineNumber=*/1, &Cxt
, SM
);
525 ASSERT_TRUE(bool(LocalVar
));
526 EXPECT_EQ(*LocalVar
, "FOO");
527 Expected
<StringRef
> EmptyVar
= Cxt
.getPatternVarValue(EmptyVarStr
);
528 Expected
<StringRef
> UnknownVar
= Cxt
.getPatternVarValue(UnknownVarStr
);
529 ASSERT_TRUE(bool(ExpressionAST
));
530 Expected
<uint64_t> ExpressionVal
= (*ExpressionAST
)->eval();
531 ASSERT_TRUE(bool(ExpressionVal
));
532 EXPECT_EQ(*ExpressionVal
, 18U);
534 P
.parseNumericSubstitutionBlock(LocalNumVar2Ref
, DefinedNumericVariable
,
535 /*IsLegacyLineExpr=*/false,
536 /*LineNumber=*/1, &Cxt
, SM
);
537 ASSERT_TRUE(bool(ExpressionAST
));
538 ExpressionVal
= (*ExpressionAST
)->eval();
539 ASSERT_TRUE(bool(ExpressionVal
));
540 EXPECT_EQ(*ExpressionVal
, 20U);
541 ASSERT_TRUE(bool(EmptyVar
));
542 EXPECT_EQ(*EmptyVar
, "");
543 EXPECT_TRUE(errorToBool(UnknownVar
.takeError()));
545 // Clear local variables and check they become absent.
546 Cxt
.clearLocalVars();
547 LocalVar
= Cxt
.getPatternVarValue(LocalVarStr
);
548 EXPECT_TRUE(errorToBool(LocalVar
.takeError()));
549 // Check a numeric expression's evaluation fails if called after clearing of
550 // local variables, if it was created before. This is important because local
551 // variable clearing due to --enable-var-scope happens after numeric
552 // expressions are linked to the numeric variables they use.
553 EXPECT_TRUE(errorToBool((*ExpressionAST
)->eval().takeError()));
554 P
= FileCheckPattern(Check::CheckPlain
, &Cxt
, 2);
555 ExpressionAST
= P
.parseNumericSubstitutionBlock(
556 LocalNumVar1Ref
, DefinedNumericVariable
, /*IsLegacyLineExpr=*/false,
557 /*LineNumber=*/2, &Cxt
, SM
);
558 ASSERT_TRUE(bool(ExpressionAST
));
559 ExpressionVal
= (*ExpressionAST
)->eval();
560 EXPECT_TRUE(errorToBool(ExpressionVal
.takeError()));
561 ExpressionAST
= P
.parseNumericSubstitutionBlock(
562 LocalNumVar2Ref
, DefinedNumericVariable
, /*IsLegacyLineExpr=*/false,
563 /*LineNumber=*/2, &Cxt
, SM
);
564 ASSERT_TRUE(bool(ExpressionAST
));
565 ExpressionVal
= (*ExpressionAST
)->eval();
566 EXPECT_TRUE(errorToBool(ExpressionVal
.takeError()));
567 EmptyVar
= Cxt
.getPatternVarValue(EmptyVarStr
);
568 EXPECT_TRUE(errorToBool(EmptyVar
.takeError()));
569 // Clear again because parseNumericSubstitutionBlock would have created a
570 // dummy variable and stored it in GlobalNumericVariableTable.
571 Cxt
.clearLocalVars();
573 // Redefine global variables and check variables are defined again.
574 GlobalDefines
.emplace_back(std::string("$GlobalVar=BAR"));
575 GlobalDefines
.emplace_back(std::string("#$GlobalNumVar=36"));
576 ASSERT_FALSE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
577 StringRef GlobalVarStr
= "$GlobalVar";
578 StringRef GlobalNumVarRef
= bufferize(SM
, "$GlobalNumVar");
579 Expected
<StringRef
> GlobalVar
= Cxt
.getPatternVarValue(GlobalVarStr
);
580 ASSERT_TRUE(bool(GlobalVar
));
581 EXPECT_EQ(*GlobalVar
, "BAR");
582 P
= FileCheckPattern(Check::CheckPlain
, &Cxt
, 3);
583 ExpressionAST
= P
.parseNumericSubstitutionBlock(
584 GlobalNumVarRef
, DefinedNumericVariable
, /*IsLegacyLineExpr=*/false,
585 /*LineNumber=*/3, &Cxt
, SM
);
586 ASSERT_TRUE(bool(ExpressionAST
));
587 ExpressionVal
= (*ExpressionAST
)->eval();
588 ASSERT_TRUE(bool(ExpressionVal
));
589 EXPECT_EQ(*ExpressionVal
, 36U);
591 // Clear local variables and check global variables remain defined.
592 Cxt
.clearLocalVars();
593 EXPECT_FALSE(errorToBool(Cxt
.getPatternVarValue(GlobalVarStr
).takeError()));
594 P
= FileCheckPattern(Check::CheckPlain
, &Cxt
, 4);
595 ExpressionAST
= P
.parseNumericSubstitutionBlock(
596 GlobalNumVarRef
, DefinedNumericVariable
, /*IsLegacyLineExpr=*/false,
597 /*LineNumber=*/4, &Cxt
, SM
);
598 ASSERT_TRUE(bool(ExpressionAST
));
599 ExpressionVal
= (*ExpressionAST
)->eval();
600 ASSERT_TRUE(bool(ExpressionVal
));
601 EXPECT_EQ(*ExpressionVal
, 36U);