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 EXPECT_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 EXPECT_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 static void expectUndefError(const Twine
&ExpectedUndefVarName
, Error Err
) {
53 expectUndefErrors({ExpectedUndefVarName
.str()}, std::move(Err
));
56 TEST_F(FileCheckTest
, NumericVariable
) {
57 // Undefined variable: getValue and eval fail, error returned by eval holds
58 // the name of the undefined variable and setValue does not trigger assert.
59 FileCheckNumericVariable FooVar
= FileCheckNumericVariable(1, "FOO");
60 EXPECT_EQ("FOO", FooVar
.getName());
61 FileCheckNumericVariableUse FooVarUse
=
62 FileCheckNumericVariableUse("FOO", &FooVar
);
63 EXPECT_FALSE(FooVar
.getValue());
64 Expected
<uint64_t> EvalResult
= FooVarUse
.eval();
65 EXPECT_FALSE(EvalResult
);
66 expectUndefError("FOO", EvalResult
.takeError());
69 // Defined variable: getValue and eval return value set.
70 Optional
<uint64_t> Value
= FooVar
.getValue();
71 EXPECT_TRUE(bool(Value
));
72 EXPECT_EQ(42U, *Value
);
73 EvalResult
= FooVarUse
.eval();
74 EXPECT_TRUE(bool(EvalResult
));
75 EXPECT_EQ(42U, *EvalResult
);
77 // Clearing variable: getValue and eval fail. Error returned by eval holds
78 // the name of the cleared variable.
80 Value
= FooVar
.getValue();
82 EvalResult
= FooVarUse
.eval();
83 EXPECT_FALSE(EvalResult
);
84 expectUndefError("FOO", EvalResult
.takeError());
87 uint64_t doAdd(uint64_t OpL
, uint64_t OpR
) { return OpL
+ OpR
; }
89 TEST_F(FileCheckTest
, Binop
) {
90 FileCheckNumericVariable FooVar
= FileCheckNumericVariable("FOO", 42);
91 std::unique_ptr
<FileCheckNumericVariableUse
> FooVarUse
=
92 llvm::make_unique
<FileCheckNumericVariableUse
>("FOO", &FooVar
);
93 FileCheckNumericVariable BarVar
= FileCheckNumericVariable("BAR", 18);
94 std::unique_ptr
<FileCheckNumericVariableUse
> BarVarUse
=
95 llvm::make_unique
<FileCheckNumericVariableUse
>("BAR", &BarVar
);
96 FileCheckASTBinop Binop
=
97 FileCheckASTBinop(doAdd
, std::move(FooVarUse
), std::move(BarVarUse
));
99 // Defined variable: eval returns right value.
100 Expected
<uint64_t> Value
= Binop
.eval();
101 EXPECT_TRUE(bool(Value
));
102 EXPECT_EQ(60U, *Value
);
104 // 1 undefined variable: eval fails, error contains name of undefined
107 Value
= Binop
.eval();
109 expectUndefError("FOO", Value
.takeError());
111 // 2 undefined variables: eval fails, error contains names of all undefined
114 Value
= Binop
.eval();
116 expectUndefErrors({"FOO", "BAR"}, Value
.takeError());
119 TEST_F(FileCheckTest
, ValidVarNameStart
) {
120 EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('a'));
121 EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('G'));
122 EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('_'));
123 EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('2'));
124 EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('$'));
125 EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('@'));
126 EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('+'));
127 EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('-'));
128 EXPECT_FALSE(FileCheckPattern::isValidVarNameStart(':'));
131 static StringRef
bufferize(SourceMgr
&SM
, StringRef Str
) {
132 std::unique_ptr
<MemoryBuffer
> Buffer
=
133 MemoryBuffer::getMemBufferCopy(Str
, "TestBuffer");
134 StringRef StrBufferRef
= Buffer
->getBuffer();
135 SM
.AddNewSourceBuffer(std::move(Buffer
), SMLoc());
139 TEST_F(FileCheckTest
, ParseVar
) {
141 StringRef OrigVarName
= bufferize(SM
, "GoodVar42");
142 StringRef VarName
= OrigVarName
;
143 Expected
<FileCheckPattern::VariableProperties
> ParsedVarResult
=
144 FileCheckPattern::parseVariable(VarName
, SM
);
145 EXPECT_TRUE(bool(ParsedVarResult
));
146 EXPECT_EQ(ParsedVarResult
->Name
, OrigVarName
);
147 EXPECT_TRUE(VarName
.empty());
148 EXPECT_FALSE(ParsedVarResult
->IsPseudo
);
150 VarName
= OrigVarName
= bufferize(SM
, "$GoodGlobalVar");
151 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
152 EXPECT_TRUE(bool(ParsedVarResult
));
153 EXPECT_EQ(ParsedVarResult
->Name
, OrigVarName
);
154 EXPECT_TRUE(VarName
.empty());
155 EXPECT_FALSE(ParsedVarResult
->IsPseudo
);
157 VarName
= OrigVarName
= bufferize(SM
, "@GoodPseudoVar");
158 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
159 EXPECT_TRUE(bool(ParsedVarResult
));
160 EXPECT_EQ(ParsedVarResult
->Name
, OrigVarName
);
161 EXPECT_TRUE(VarName
.empty());
162 EXPECT_TRUE(ParsedVarResult
->IsPseudo
);
164 VarName
= bufferize(SM
, "42BadVar");
165 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
166 EXPECT_TRUE(errorToBool(ParsedVarResult
.takeError()));
168 VarName
= bufferize(SM
, "$@");
169 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
170 EXPECT_TRUE(errorToBool(ParsedVarResult
.takeError()));
172 VarName
= OrigVarName
= bufferize(SM
, "B@dVar");
173 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
174 EXPECT_TRUE(bool(ParsedVarResult
));
175 EXPECT_EQ(VarName
, OrigVarName
.substr(1));
176 EXPECT_EQ(ParsedVarResult
->Name
, "B");
177 EXPECT_FALSE(ParsedVarResult
->IsPseudo
);
179 VarName
= OrigVarName
= bufferize(SM
, "B$dVar");
180 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
181 EXPECT_TRUE(bool(ParsedVarResult
));
182 EXPECT_EQ(VarName
, OrigVarName
.substr(1));
183 EXPECT_EQ(ParsedVarResult
->Name
, "B");
184 EXPECT_FALSE(ParsedVarResult
->IsPseudo
);
186 VarName
= bufferize(SM
, "BadVar+");
187 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
188 EXPECT_TRUE(bool(ParsedVarResult
));
189 EXPECT_EQ(VarName
, "+");
190 EXPECT_EQ(ParsedVarResult
->Name
, "BadVar");
191 EXPECT_FALSE(ParsedVarResult
->IsPseudo
);
193 VarName
= bufferize(SM
, "BadVar-");
194 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
195 EXPECT_TRUE(bool(ParsedVarResult
));
196 EXPECT_EQ(VarName
, "-");
197 EXPECT_EQ(ParsedVarResult
->Name
, "BadVar");
198 EXPECT_FALSE(ParsedVarResult
->IsPseudo
);
200 VarName
= bufferize(SM
, "BadVar:");
201 ParsedVarResult
= FileCheckPattern::parseVariable(VarName
, SM
);
202 EXPECT_TRUE(bool(ParsedVarResult
));
203 EXPECT_EQ(VarName
, ":");
204 EXPECT_EQ(ParsedVarResult
->Name
, "BadVar");
205 EXPECT_FALSE(ParsedVarResult
->IsPseudo
);
208 class PatternTester
{
210 size_t LineNumber
= 1;
212 FileCheckRequest Req
;
213 FileCheckPatternContext Context
;
215 FileCheckPattern(Check::CheckPlain
, &Context
, LineNumber
++);
219 std::vector
<std::string
> GlobalDefines
;
220 GlobalDefines
.emplace_back(std::string("#FOO=42"));
221 GlobalDefines
.emplace_back(std::string("BAR=BAZ"));
223 errorToBool(Context
.defineCmdlineVariables(GlobalDefines
, SM
)));
224 Context
.createLineVariable();
225 // Call parsePattern to have @LINE defined.
226 P
.parsePattern("N/A", "CHECK", SM
, Req
);
227 // parsePattern does not expect to be called twice for the same line and
228 // will set FixedStr and RegExStr incorrectly if it is. Therefore prepare
229 // a pattern for a different line.
233 void initNextPattern() {
234 P
= FileCheckPattern(Check::CheckPlain
, &Context
, LineNumber
++);
237 bool parseNumVarDefExpect(StringRef Expr
) {
238 StringRef ExprBufferRef
= bufferize(SM
, Expr
);
239 return errorToBool(FileCheckPattern::parseNumericVariableDefinition(
240 ExprBufferRef
, &Context
, LineNumber
, SM
)
244 bool parseSubstExpect(StringRef Expr
) {
245 StringRef ExprBufferRef
= bufferize(SM
, Expr
);
246 Optional
<FileCheckNumericVariable
*> DefinedNumericVariable
;
247 return errorToBool(P
.parseNumericSubstitutionBlock(
248 ExprBufferRef
, DefinedNumericVariable
, false, 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
, ParseNumericVariableDefinition
) {
265 PatternTester Tester
;
267 // Invalid definition of pseudo.
268 EXPECT_TRUE(Tester
.parseNumVarDefExpect("@LINE"));
270 // Conflict with pattern variable.
271 EXPECT_TRUE(Tester
.parseNumVarDefExpect("BAR"));
274 EXPECT_FALSE(Tester
.parseNumVarDefExpect("FOO"));
277 TEST_F(FileCheckTest
, ParseExpr
) {
278 PatternTester Tester
;
280 // Variable definition.
282 // Definition of invalid variable.
283 EXPECT_TRUE(Tester
.parseSubstExpect("10VAR:"));
284 EXPECT_TRUE(Tester
.parseSubstExpect("@FOO:"));
285 EXPECT_TRUE(Tester
.parseSubstExpect("@LINE:"));
287 // Garbage after name of variable being defined.
288 EXPECT_TRUE(Tester
.parseSubstExpect("VAR GARBAGE:"));
290 // Variable defined to numeric expression.
291 EXPECT_TRUE(Tester
.parseSubstExpect("VAR1: FOO"));
293 // Acceptable variable definition.
294 EXPECT_FALSE(Tester
.parseSubstExpect("VAR1:"));
295 EXPECT_FALSE(Tester
.parseSubstExpect(" VAR2:"));
296 EXPECT_FALSE(Tester
.parseSubstExpect("VAR3 :"));
297 EXPECT_FALSE(Tester
.parseSubstExpect("VAR3: "));
299 // Numeric expression.
301 // Unacceptable variable.
302 EXPECT_TRUE(Tester
.parseSubstExpect("10VAR"));
303 EXPECT_TRUE(Tester
.parseSubstExpect("@FOO"));
305 // Only valid variable.
306 EXPECT_FALSE(Tester
.parseSubstExpect("@LINE"));
307 EXPECT_FALSE(Tester
.parseSubstExpect("FOO"));
308 EXPECT_FALSE(Tester
.parseSubstExpect("UNDEF"));
310 // Use variable defined on same line.
311 EXPECT_FALSE(Tester
.parsePatternExpect("[[#LINE1VAR:]]"));
312 EXPECT_TRUE(Tester
.parseSubstExpect("LINE1VAR"));
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
.parsePatternExpect("[[#FOO+FOO]]"));
325 EXPECT_FALSE(Tester
.parsePatternExpect("[[#FOO+3-FOO]]"));
328 TEST_F(FileCheckTest
, ParsePattern
) {
329 PatternTester Tester
;
331 // Space in pattern variable expression.
332 EXPECT_TRUE(Tester
.parsePatternExpect("[[ BAR]]"));
334 // Invalid variable name.
335 EXPECT_TRUE(Tester
.parsePatternExpect("[[42INVALID]]"));
337 // Invalid pattern variable definition.
338 EXPECT_TRUE(Tester
.parsePatternExpect("[[@PAT:]]"));
339 EXPECT_TRUE(Tester
.parsePatternExpect("[[PAT+2:]]"));
341 // Collision with numeric variable.
342 EXPECT_TRUE(Tester
.parsePatternExpect("[[FOO:]]"));
344 // Valid use of pattern variable.
345 EXPECT_FALSE(Tester
.parsePatternExpect("[[BAR]]"));
347 // Valid pattern variable definition.
348 EXPECT_FALSE(Tester
.parsePatternExpect("[[PAT:[0-9]+]]"));
350 // Invalid numeric expressions.
351 EXPECT_TRUE(Tester
.parsePatternExpect("[[#42INVALID]]"));
352 EXPECT_TRUE(Tester
.parsePatternExpect("[[#@FOO]]"));
353 EXPECT_TRUE(Tester
.parsePatternExpect("[[#@LINE/2]]"));
354 EXPECT_TRUE(Tester
.parsePatternExpect("[[#YUP:@LINE]]"));
356 // Valid numeric expressions and numeric variable definition.
357 EXPECT_FALSE(Tester
.parsePatternExpect("[[#FOO]]"));
358 EXPECT_FALSE(Tester
.parsePatternExpect("[[#@LINE+2]]"));
359 EXPECT_FALSE(Tester
.parsePatternExpect("[[#NUMVAR:]]"));
362 TEST_F(FileCheckTest
, Match
) {
363 PatternTester Tester
;
365 // Check matching a definition only matches a number.
366 Tester
.parsePatternExpect("[[#NUMVAR:]]");
367 EXPECT_TRUE(Tester
.matchExpect("FAIL"));
368 EXPECT_FALSE(Tester
.matchExpect("18"));
370 // Check matching the variable defined matches the correct number only
371 Tester
.initNextPattern();
372 Tester
.parsePatternExpect("[[#NUMVAR]] [[#NUMVAR+2]]");
373 EXPECT_TRUE(Tester
.matchExpect("19 21"));
374 EXPECT_TRUE(Tester
.matchExpect("18 21"));
375 EXPECT_FALSE(Tester
.matchExpect("18 20"));
377 // Check matching a numeric expression using @LINE after match failure uses
378 // the correct value for @LINE.
379 Tester
.initNextPattern();
380 EXPECT_FALSE(Tester
.parsePatternExpect("[[#@LINE]]"));
381 // Ok, @LINE is 4 now.
382 EXPECT_FALSE(Tester
.matchExpect("4"));
383 Tester
.initNextPattern();
384 // @LINE is now 5, match with substitution failure.
385 EXPECT_FALSE(Tester
.parsePatternExpect("[[#UNKNOWN]]"));
386 EXPECT_TRUE(Tester
.matchExpect("FOO"));
387 Tester
.initNextPattern();
388 // Check that @LINE is 6 as expected.
389 EXPECT_FALSE(Tester
.parsePatternExpect("[[#@LINE]]"));
390 EXPECT_FALSE(Tester
.matchExpect("6"));
393 TEST_F(FileCheckTest
, Substitution
) {
395 FileCheckPatternContext Context
;
396 std::vector
<std::string
> GlobalDefines
;
397 GlobalDefines
.emplace_back(std::string("FOO=BAR"));
398 EXPECT_FALSE(errorToBool(Context
.defineCmdlineVariables(GlobalDefines
, SM
)));
400 // Substitution of an undefined string variable fails and error holds that
402 FileCheckStringSubstitution StringSubstitution
=
403 FileCheckStringSubstitution(&Context
, "VAR404", 42);
404 Expected
<std::string
> SubstValue
= StringSubstitution
.getResult();
405 EXPECT_FALSE(bool(SubstValue
));
406 expectUndefError("VAR404", SubstValue
.takeError());
408 // Substitutions of defined pseudo and non-pseudo numeric variables return
410 FileCheckNumericVariable LineVar
= FileCheckNumericVariable("@LINE", 42);
411 FileCheckNumericVariable NVar
= FileCheckNumericVariable("N", 10);
413 llvm::make_unique
<FileCheckNumericVariableUse
>("@LINE", &LineVar
);
414 auto NVarUse
= llvm::make_unique
<FileCheckNumericVariableUse
>("N", &NVar
);
415 FileCheckNumericSubstitution SubstitutionLine
= FileCheckNumericSubstitution(
416 &Context
, "@LINE", std::move(LineVarUse
), 12);
417 FileCheckNumericSubstitution SubstitutionN
=
418 FileCheckNumericSubstitution(&Context
, "N", std::move(NVarUse
), 30);
419 SubstValue
= SubstitutionLine
.getResult();
420 EXPECT_TRUE(bool(SubstValue
));
421 EXPECT_EQ("42", *SubstValue
);
422 SubstValue
= SubstitutionN
.getResult();
423 EXPECT_TRUE(bool(SubstValue
));
424 EXPECT_EQ("10", *SubstValue
);
426 // Substitution of an undefined numeric variable fails, error holds name of
427 // undefined variable.
428 LineVar
.clearValue();
429 SubstValue
= SubstitutionLine
.getResult();
430 EXPECT_FALSE(bool(SubstValue
));
431 expectUndefError("@LINE", SubstValue
.takeError());
433 SubstValue
= SubstitutionN
.getResult();
434 EXPECT_FALSE(bool(SubstValue
));
435 expectUndefError("N", SubstValue
.takeError());
437 // Substitution of a defined string variable returns the right value.
438 FileCheckPattern P
= FileCheckPattern(Check::CheckPlain
, &Context
, 1);
439 StringSubstitution
= FileCheckStringSubstitution(&Context
, "FOO", 42);
440 SubstValue
= StringSubstitution
.getResult();
441 EXPECT_TRUE(bool(SubstValue
));
442 EXPECT_EQ("BAR", *SubstValue
);
445 TEST_F(FileCheckTest
, FileCheckContext
) {
446 FileCheckPatternContext Cxt
= FileCheckPatternContext();
447 std::vector
<std::string
> GlobalDefines
;
450 // Missing equal sign.
451 GlobalDefines
.emplace_back(std::string("LocalVar"));
452 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
453 GlobalDefines
.clear();
454 GlobalDefines
.emplace_back(std::string("#LocalNumVar"));
455 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
457 // Empty variable name.
458 GlobalDefines
.clear();
459 GlobalDefines
.emplace_back(std::string("=18"));
460 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
461 GlobalDefines
.clear();
462 GlobalDefines
.emplace_back(std::string("#=18"));
463 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
465 // Invalid variable name.
466 GlobalDefines
.clear();
467 GlobalDefines
.emplace_back(std::string("18LocalVar=18"));
468 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
469 GlobalDefines
.clear();
470 GlobalDefines
.emplace_back(std::string("#18LocalNumVar=18"));
471 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
473 // Name conflict between pattern and numeric variable.
474 GlobalDefines
.clear();
475 GlobalDefines
.emplace_back(std::string("LocalVar=18"));
476 GlobalDefines
.emplace_back(std::string("#LocalVar=36"));
477 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
478 Cxt
= FileCheckPatternContext();
479 GlobalDefines
.clear();
480 GlobalDefines
.emplace_back(std::string("#LocalNumVar=18"));
481 GlobalDefines
.emplace_back(std::string("LocalNumVar=36"));
482 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
483 Cxt
= FileCheckPatternContext();
485 // Invalid numeric value for numeric variable.
486 GlobalDefines
.clear();
487 GlobalDefines
.emplace_back(std::string("#LocalNumVar=x"));
488 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
490 // Define local variables from command-line.
491 GlobalDefines
.clear();
492 GlobalDefines
.emplace_back(std::string("LocalVar=FOO"));
493 GlobalDefines
.emplace_back(std::string("EmptyVar="));
494 GlobalDefines
.emplace_back(std::string("#LocalNumVar=18"));
495 EXPECT_FALSE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
497 // Check defined variables are present and undefined is absent.
498 StringRef LocalVarStr
= "LocalVar";
499 StringRef LocalNumVarRef
= bufferize(SM
, "LocalNumVar");
500 StringRef EmptyVarStr
= "EmptyVar";
501 StringRef UnknownVarStr
= "UnknownVar";
502 Expected
<StringRef
> LocalVar
= Cxt
.getPatternVarValue(LocalVarStr
);
503 FileCheckPattern P
= FileCheckPattern(Check::CheckPlain
, &Cxt
, 1);
504 Optional
<FileCheckNumericVariable
*> DefinedNumericVariable
;
505 Expected
<std::unique_ptr
<FileCheckExpressionAST
>> ExpressionAST
=
506 P
.parseNumericSubstitutionBlock(LocalNumVarRef
, DefinedNumericVariable
,
507 /*IsLegacyLineExpr=*/false, SM
);
508 EXPECT_TRUE(bool(LocalVar
));
509 EXPECT_EQ(*LocalVar
, "FOO");
510 Expected
<StringRef
> EmptyVar
= Cxt
.getPatternVarValue(EmptyVarStr
);
511 Expected
<StringRef
> UnknownVar
= Cxt
.getPatternVarValue(UnknownVarStr
);
512 EXPECT_TRUE(bool(ExpressionAST
));
513 Expected
<uint64_t> ExpressionVal
= (*ExpressionAST
)->eval();
514 EXPECT_TRUE(bool(ExpressionVal
));
515 EXPECT_EQ(*ExpressionVal
, 18U);
516 EXPECT_TRUE(bool(EmptyVar
));
517 EXPECT_EQ(*EmptyVar
, "");
518 EXPECT_TRUE(errorToBool(UnknownVar
.takeError()));
520 // Clear local variables and check they become absent.
521 Cxt
.clearLocalVars();
522 LocalVar
= Cxt
.getPatternVarValue(LocalVarStr
);
523 EXPECT_TRUE(errorToBool(LocalVar
.takeError()));
524 // Check a numeric expression's evaluation fails if called after clearing of
525 // local variables, if it was created before. This is important because local
526 // variable clearing due to --enable-var-scope happens after numeric
527 // expressions are linked to the numeric variables they use.
528 EXPECT_TRUE(errorToBool((*ExpressionAST
)->eval().takeError()));
529 P
= FileCheckPattern(Check::CheckPlain
, &Cxt
, 2);
530 ExpressionAST
= P
.parseNumericSubstitutionBlock(
531 LocalNumVarRef
, DefinedNumericVariable
, /*IsLegacyLineExpr=*/false, SM
);
532 EXPECT_TRUE(bool(ExpressionAST
));
533 ExpressionVal
= (*ExpressionAST
)->eval();
534 EXPECT_TRUE(errorToBool(ExpressionVal
.takeError()));
535 EmptyVar
= Cxt
.getPatternVarValue(EmptyVarStr
);
536 EXPECT_TRUE(errorToBool(EmptyVar
.takeError()));
537 // Clear again because parseNumericSubstitutionBlock would have created a
538 // dummy variable and stored it in GlobalNumericVariableTable.
539 Cxt
.clearLocalVars();
541 // Redefine global variables and check variables are defined again.
542 GlobalDefines
.emplace_back(std::string("$GlobalVar=BAR"));
543 GlobalDefines
.emplace_back(std::string("#$GlobalNumVar=36"));
544 EXPECT_FALSE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
545 StringRef GlobalVarStr
= "$GlobalVar";
546 StringRef GlobalNumVarRef
= bufferize(SM
, "$GlobalNumVar");
547 Expected
<StringRef
> GlobalVar
= Cxt
.getPatternVarValue(GlobalVarStr
);
548 EXPECT_TRUE(bool(GlobalVar
));
549 EXPECT_EQ(*GlobalVar
, "BAR");
550 P
= FileCheckPattern(Check::CheckPlain
, &Cxt
, 3);
551 ExpressionAST
= P
.parseNumericSubstitutionBlock(
552 GlobalNumVarRef
, DefinedNumericVariable
, /*IsLegacyLineExpr=*/false, SM
);
553 EXPECT_TRUE(bool(ExpressionAST
));
554 ExpressionVal
= (*ExpressionAST
)->eval();
555 EXPECT_TRUE(bool(ExpressionVal
));
556 EXPECT_EQ(*ExpressionVal
, 36U);
558 // Clear local variables and check global variables remain defined.
559 Cxt
.clearLocalVars();
560 EXPECT_FALSE(errorToBool(Cxt
.getPatternVarValue(GlobalVarStr
).takeError()));
561 P
= FileCheckPattern(Check::CheckPlain
, &Cxt
, 4);
562 ExpressionAST
= P
.parseNumericSubstitutionBlock(
563 GlobalNumVarRef
, DefinedNumericVariable
, /*IsLegacyLineExpr=*/false, SM
);
564 EXPECT_TRUE(bool(ExpressionAST
));
565 ExpressionVal
= (*ExpressionAST
)->eval();
566 EXPECT_TRUE(bool(ExpressionVal
));
567 EXPECT_EQ(*ExpressionVal
, 36U);