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 "../lib/Support/FileCheckImpl.h"
11 #include "gtest/gtest.h"
12 #include <unordered_set>
18 class FileCheckTest
: public ::testing::Test
{};
20 TEST_F(FileCheckTest
, Literal
) {
21 // Eval returns the literal's value.
22 FileCheckExpressionLiteral
Ten(10);
23 Expected
<uint64_t> Value
= Ten
.eval();
24 ASSERT_TRUE(bool(Value
));
25 EXPECT_EQ(10U, *Value
);
27 // Max value can be correctly represented.
28 FileCheckExpressionLiteral
Max(std::numeric_limits
<uint64_t>::max());
30 ASSERT_TRUE(bool(Value
));
31 EXPECT_EQ(std::numeric_limits
<uint64_t>::max(), *Value
);
34 static std::string
toString(const std::unordered_set
<std::string
> &Set
) {
37 for (StringRef S
: Set
) {
38 Str
+= Twine(First
? "{" + S
: ", " + S
).str();
46 expectUndefErrors(std::unordered_set
<std::string
> ExpectedUndefVarNames
,
48 handleAllErrors(std::move(Err
), [&](const FileCheckUndefVarError
&E
) {
49 ExpectedUndefVarNames
.erase(E
.getVarName());
51 EXPECT_TRUE(ExpectedUndefVarNames
.empty()) << toString(ExpectedUndefVarNames
);
54 // Return whether Err contains any FileCheckUndefVarError whose associated name
55 // is not ExpectedUndefVarName.
56 static void expectUndefError(const Twine
&ExpectedUndefVarName
, Error Err
) {
57 expectUndefErrors({ExpectedUndefVarName
.str()}, std::move(Err
));
60 uint64_t doAdd(uint64_t OpL
, uint64_t OpR
) { return OpL
+ OpR
; }
62 TEST_F(FileCheckTest
, NumericVariable
) {
63 // Undefined variable: getValue and eval fail, error returned by eval holds
64 // the name of the undefined variable.
65 FileCheckNumericVariable
FooVar("FOO", 1);
66 EXPECT_EQ("FOO", FooVar
.getName());
67 FileCheckNumericVariableUse
FooVarUse("FOO", &FooVar
);
68 EXPECT_FALSE(FooVar
.getValue());
69 Expected
<uint64_t> EvalResult
= FooVarUse
.eval();
70 ASSERT_FALSE(EvalResult
);
71 expectUndefError("FOO", EvalResult
.takeError());
75 // Defined variable: getValue and eval return value set.
76 Optional
<uint64_t> Value
= FooVar
.getValue();
77 ASSERT_TRUE(bool(Value
));
78 EXPECT_EQ(42U, *Value
);
79 EvalResult
= FooVarUse
.eval();
80 ASSERT_TRUE(bool(EvalResult
));
81 EXPECT_EQ(42U, *EvalResult
);
83 // Clearing variable: getValue and eval fail. Error returned by eval holds
84 // the name of the cleared variable.
86 EXPECT_FALSE(FooVar
.getValue());
87 EvalResult
= FooVarUse
.eval();
88 ASSERT_FALSE(EvalResult
);
89 expectUndefError("FOO", EvalResult
.takeError());
92 TEST_F(FileCheckTest
, Binop
) {
93 FileCheckNumericVariable
FooVar("FOO", 1);
95 std::unique_ptr
<FileCheckNumericVariableUse
> FooVarUse
=
96 std::make_unique
<FileCheckNumericVariableUse
>("FOO", &FooVar
);
97 FileCheckNumericVariable
BarVar("BAR", 2);
99 std::unique_ptr
<FileCheckNumericVariableUse
> BarVarUse
=
100 std::make_unique
<FileCheckNumericVariableUse
>("BAR", &BarVar
);
101 FileCheckASTBinop
Binop(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
;
218 FileCheckPattern P
{Check::CheckPlain
, &Context
, LineNumber
++};
222 std::vector
<std::string
> GlobalDefines
;
223 GlobalDefines
.emplace_back(std::string("#FOO=42"));
224 GlobalDefines
.emplace_back(std::string("BAR=BAZ"));
225 // An ASSERT_FALSE would make more sense but cannot be used in a
228 errorToBool(Context
.defineCmdlineVariables(GlobalDefines
, SM
)));
229 Context
.createLineVariable();
230 // Call parsePattern to have @LINE defined.
231 P
.parsePattern("N/A", "CHECK", SM
, Req
);
232 // parsePattern does not expect to be called twice for the same line and
233 // will set FixedStr and RegExStr incorrectly if it is. Therefore prepare
234 // a pattern for a different line.
238 void initNextPattern() {
239 P
= FileCheckPattern(Check::CheckPlain
, &Context
, LineNumber
++);
242 bool parseSubstExpect(StringRef Expr
) {
243 StringRef ExprBufferRef
= bufferize(SM
, Expr
);
244 Optional
<FileCheckNumericVariable
*> DefinedNumericVariable
;
246 P
.parseNumericSubstitutionBlock(ExprBufferRef
, DefinedNumericVariable
,
247 false, LineNumber
- 1, &Context
, SM
)
251 bool parsePatternExpect(StringRef Pattern
) {
252 StringRef PatBufferRef
= bufferize(SM
, Pattern
);
253 return P
.parsePattern(PatBufferRef
, "CHECK", SM
, Req
);
256 bool matchExpect(StringRef Buffer
) {
257 StringRef BufferRef
= bufferize(SM
, Buffer
);
259 return errorToBool(P
.match(BufferRef
, MatchLen
, SM
).takeError());
263 TEST_F(FileCheckTest
, ParseExpr
) {
264 PatternTester Tester
;
266 // Variable definition.
268 // Definition of invalid variable.
269 EXPECT_TRUE(Tester
.parseSubstExpect("10VAR:"));
270 EXPECT_TRUE(Tester
.parseSubstExpect("@FOO:"));
271 EXPECT_TRUE(Tester
.parseSubstExpect("@LINE:"));
273 // Conflict with pattern variable.
274 EXPECT_TRUE(Tester
.parseSubstExpect("BAR:"));
276 // Garbage after name of variable being defined.
277 EXPECT_TRUE(Tester
.parseSubstExpect("VAR GARBAGE:"));
279 // Acceptable variable definition.
280 EXPECT_FALSE(Tester
.parseSubstExpect("VAR1:"));
281 EXPECT_FALSE(Tester
.parseSubstExpect(" VAR2:"));
282 EXPECT_FALSE(Tester
.parseSubstExpect("VAR3 :"));
283 EXPECT_FALSE(Tester
.parseSubstExpect("VAR3: "));
284 EXPECT_FALSE(Tester
.parsePatternExpect("[[#FOOBAR: FOO+1]]"));
286 // Numeric expression.
288 // Unacceptable variable.
289 EXPECT_TRUE(Tester
.parseSubstExpect("10VAR"));
290 EXPECT_TRUE(Tester
.parseSubstExpect("@FOO"));
292 // Only valid variable.
293 EXPECT_FALSE(Tester
.parseSubstExpect("@LINE"));
294 EXPECT_FALSE(Tester
.parseSubstExpect("FOO"));
295 EXPECT_FALSE(Tester
.parseSubstExpect("UNDEF"));
297 // Valid empty expression.
298 EXPECT_FALSE(Tester
.parseSubstExpect(""));
300 // Invalid use of variable defined on the same line from expression. Note
301 // that the same pattern object is used for the parsePatternExpect and
302 // parseSubstExpect since no initNextPattern is called, thus appearing as
303 // being on the same line from the pattern's point of view.
304 ASSERT_FALSE(Tester
.parsePatternExpect("[[#LINE1VAR:FOO+1]]"));
305 EXPECT_TRUE(Tester
.parseSubstExpect("LINE1VAR"));
307 // Invalid use of variable defined on same line from input. As above, the
308 // absence of a call to initNextPattern makes it appear to be on the same
309 // line from the pattern's point of view.
310 ASSERT_FALSE(Tester
.parsePatternExpect("[[#LINE2VAR:]]"));
311 EXPECT_TRUE(Tester
.parseSubstExpect("LINE2VAR"));
313 // Unsupported operator.
314 EXPECT_TRUE(Tester
.parseSubstExpect("@LINE/2"));
316 // Missing offset operand.
317 EXPECT_TRUE(Tester
.parseSubstExpect("@LINE+"));
320 EXPECT_FALSE(Tester
.parseSubstExpect("@LINE+5"));
321 EXPECT_FALSE(Tester
.parseSubstExpect("FOO+4"));
322 Tester
.initNextPattern();
323 EXPECT_FALSE(Tester
.parseSubstExpect("FOOBAR"));
324 EXPECT_FALSE(Tester
.parseSubstExpect("LINE1VAR"));
325 EXPECT_FALSE(Tester
.parsePatternExpect("[[#FOO+FOO]]"));
326 EXPECT_FALSE(Tester
.parsePatternExpect("[[#FOO+3-FOO]]"));
329 TEST_F(FileCheckTest
, ParsePattern
) {
330 PatternTester Tester
;
332 // Space in pattern variable expression.
333 EXPECT_TRUE(Tester
.parsePatternExpect("[[ BAR]]"));
335 // Invalid variable name.
336 EXPECT_TRUE(Tester
.parsePatternExpect("[[42INVALID]]"));
338 // Invalid pattern variable definition.
339 EXPECT_TRUE(Tester
.parsePatternExpect("[[@PAT:]]"));
340 EXPECT_TRUE(Tester
.parsePatternExpect("[[PAT+2:]]"));
342 // Collision with numeric variable.
343 EXPECT_TRUE(Tester
.parsePatternExpect("[[FOO:]]"));
345 // Valid use of pattern variable.
346 EXPECT_FALSE(Tester
.parsePatternExpect("[[BAR]]"));
348 // Valid pattern variable definition.
349 EXPECT_FALSE(Tester
.parsePatternExpect("[[PAT:[0-9]+]]"));
351 // Invalid numeric expressions.
352 EXPECT_TRUE(Tester
.parsePatternExpect("[[#42INVALID]]"));
353 EXPECT_TRUE(Tester
.parsePatternExpect("[[#@FOO]]"));
354 EXPECT_TRUE(Tester
.parsePatternExpect("[[#@LINE/2]]"));
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 an empty expression only matches a number.
366 Tester
.parsePatternExpect("[[#]]");
367 EXPECT_TRUE(Tester
.matchExpect("FAIL"));
368 EXPECT_FALSE(Tester
.matchExpect("18"));
370 // Check matching a definition only matches a number.
371 Tester
.initNextPattern();
372 Tester
.parsePatternExpect("[[#NUMVAR:]]");
373 EXPECT_TRUE(Tester
.matchExpect("FAIL"));
374 EXPECT_TRUE(Tester
.matchExpect(""));
375 EXPECT_FALSE(Tester
.matchExpect("18"));
377 // Check matching the variable defined matches the correct number only
378 Tester
.initNextPattern();
379 Tester
.parsePatternExpect("[[#NUMVAR]] [[#NUMVAR+2]]");
380 EXPECT_TRUE(Tester
.matchExpect("19 21"));
381 EXPECT_TRUE(Tester
.matchExpect("18 21"));
382 EXPECT_FALSE(Tester
.matchExpect("18 20"));
384 // Check matching a numeric expression using @LINE after match failure uses
385 // the correct value for @LINE.
386 Tester
.initNextPattern();
387 EXPECT_FALSE(Tester
.parsePatternExpect("[[#@LINE]]"));
388 // Ok, @LINE is 5 now.
389 EXPECT_FALSE(Tester
.matchExpect("5"));
390 Tester
.initNextPattern();
391 // @LINE is now 6, match with substitution failure.
392 EXPECT_FALSE(Tester
.parsePatternExpect("[[#UNKNOWN]]"));
393 EXPECT_TRUE(Tester
.matchExpect("FOO"));
394 Tester
.initNextPattern();
395 // Check that @LINE is 7 as expected.
396 EXPECT_FALSE(Tester
.parsePatternExpect("[[#@LINE]]"));
397 EXPECT_FALSE(Tester
.matchExpect("7"));
400 TEST_F(FileCheckTest
, Substitution
) {
402 FileCheckPatternContext Context
;
403 std::vector
<std::string
> GlobalDefines
;
404 GlobalDefines
.emplace_back(std::string("FOO=BAR"));
405 EXPECT_FALSE(errorToBool(Context
.defineCmdlineVariables(GlobalDefines
, SM
)));
407 // Substitution of an undefined string variable fails and error holds that
409 FileCheckStringSubstitution
StringSubstitution(&Context
, "VAR404", 42);
410 Expected
<std::string
> SubstValue
= StringSubstitution
.getResult();
411 ASSERT_FALSE(bool(SubstValue
));
412 expectUndefError("VAR404", SubstValue
.takeError());
414 // Substitutions of defined pseudo and non-pseudo numeric variables return
416 FileCheckNumericVariable
LineVar("@LINE", 1);
417 FileCheckNumericVariable
NVar("N", 1);
418 LineVar
.setValue(42);
421 std::make_unique
<FileCheckNumericVariableUse
>("@LINE", &LineVar
);
422 auto NVarUse
= std::make_unique
<FileCheckNumericVariableUse
>("N", &NVar
);
423 FileCheckNumericSubstitution
SubstitutionLine(&Context
, "@LINE",
424 std::move(LineVarUse
), 12);
425 FileCheckNumericSubstitution
SubstitutionN(&Context
, "N", std::move(NVarUse
),
427 SubstValue
= SubstitutionLine
.getResult();
428 ASSERT_TRUE(bool(SubstValue
));
429 EXPECT_EQ("42", *SubstValue
);
430 SubstValue
= SubstitutionN
.getResult();
431 ASSERT_TRUE(bool(SubstValue
));
432 EXPECT_EQ("10", *SubstValue
);
434 // Substitution of an undefined numeric variable fails, error holds name of
435 // undefined variable.
436 LineVar
.clearValue();
437 SubstValue
= SubstitutionLine
.getResult();
438 ASSERT_FALSE(bool(SubstValue
));
439 expectUndefError("@LINE", SubstValue
.takeError());
441 SubstValue
= SubstitutionN
.getResult();
442 ASSERT_FALSE(bool(SubstValue
));
443 expectUndefError("N", SubstValue
.takeError());
445 // Substitution of a defined string variable returns the right value.
446 FileCheckPattern
P(Check::CheckPlain
, &Context
, 1);
447 StringSubstitution
= FileCheckStringSubstitution(&Context
, "FOO", 42);
448 SubstValue
= StringSubstitution
.getResult();
449 ASSERT_TRUE(bool(SubstValue
));
450 EXPECT_EQ("BAR", *SubstValue
);
453 TEST_F(FileCheckTest
, FileCheckContext
) {
454 FileCheckPatternContext Cxt
;
455 std::vector
<std::string
> GlobalDefines
;
458 // Missing equal sign.
459 GlobalDefines
.emplace_back(std::string("LocalVar"));
460 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
461 GlobalDefines
.clear();
462 GlobalDefines
.emplace_back(std::string("#LocalNumVar"));
463 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
465 // Empty variable name.
466 GlobalDefines
.clear();
467 GlobalDefines
.emplace_back(std::string("=18"));
468 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
469 GlobalDefines
.clear();
470 GlobalDefines
.emplace_back(std::string("#=18"));
471 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
473 // Invalid variable name.
474 GlobalDefines
.clear();
475 GlobalDefines
.emplace_back(std::string("18LocalVar=18"));
476 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
477 GlobalDefines
.clear();
478 GlobalDefines
.emplace_back(std::string("#18LocalNumVar=18"));
479 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
481 // Name conflict between pattern and numeric variable.
482 GlobalDefines
.clear();
483 GlobalDefines
.emplace_back(std::string("LocalVar=18"));
484 GlobalDefines
.emplace_back(std::string("#LocalVar=36"));
485 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
486 Cxt
= FileCheckPatternContext();
487 GlobalDefines
.clear();
488 GlobalDefines
.emplace_back(std::string("#LocalNumVar=18"));
489 GlobalDefines
.emplace_back(std::string("LocalNumVar=36"));
490 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
491 Cxt
= FileCheckPatternContext();
493 // Invalid numeric value for numeric variable.
494 GlobalDefines
.clear();
495 GlobalDefines
.emplace_back(std::string("#LocalNumVar=x"));
496 EXPECT_TRUE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
498 // Define local variables from command-line.
499 GlobalDefines
.clear();
500 // Clear local variables to remove dummy numeric variable x that
501 // parseNumericSubstitutionBlock would have created and stored in
502 // GlobalNumericVariableTable.
503 Cxt
.clearLocalVars();
504 GlobalDefines
.emplace_back(std::string("LocalVar=FOO"));
505 GlobalDefines
.emplace_back(std::string("EmptyVar="));
506 GlobalDefines
.emplace_back(std::string("#LocalNumVar1=18"));
507 GlobalDefines
.emplace_back(std::string("#LocalNumVar2=LocalNumVar1+2"));
508 ASSERT_FALSE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
510 // Check defined variables are present and undefined is absent.
511 StringRef LocalVarStr
= "LocalVar";
512 StringRef LocalNumVar1Ref
= bufferize(SM
, "LocalNumVar1");
513 StringRef LocalNumVar2Ref
= bufferize(SM
, "LocalNumVar2");
514 StringRef EmptyVarStr
= "EmptyVar";
515 StringRef UnknownVarStr
= "UnknownVar";
516 Expected
<StringRef
> LocalVar
= Cxt
.getPatternVarValue(LocalVarStr
);
517 FileCheckPattern
P(Check::CheckPlain
, &Cxt
, 1);
518 Optional
<FileCheckNumericVariable
*> DefinedNumericVariable
;
519 Expected
<std::unique_ptr
<FileCheckExpressionAST
>> ExpressionAST
=
520 P
.parseNumericSubstitutionBlock(LocalNumVar1Ref
, DefinedNumericVariable
,
521 /*IsLegacyLineExpr=*/false,
522 /*LineNumber=*/1, &Cxt
, SM
);
523 ASSERT_TRUE(bool(LocalVar
));
524 EXPECT_EQ(*LocalVar
, "FOO");
525 Expected
<StringRef
> EmptyVar
= Cxt
.getPatternVarValue(EmptyVarStr
);
526 Expected
<StringRef
> UnknownVar
= Cxt
.getPatternVarValue(UnknownVarStr
);
527 ASSERT_TRUE(bool(ExpressionAST
));
528 Expected
<uint64_t> ExpressionVal
= (*ExpressionAST
)->eval();
529 ASSERT_TRUE(bool(ExpressionVal
));
530 EXPECT_EQ(*ExpressionVal
, 18U);
532 P
.parseNumericSubstitutionBlock(LocalNumVar2Ref
, DefinedNumericVariable
,
533 /*IsLegacyLineExpr=*/false,
534 /*LineNumber=*/1, &Cxt
, SM
);
535 ASSERT_TRUE(bool(ExpressionAST
));
536 ExpressionVal
= (*ExpressionAST
)->eval();
537 ASSERT_TRUE(bool(ExpressionVal
));
538 EXPECT_EQ(*ExpressionVal
, 20U);
539 ASSERT_TRUE(bool(EmptyVar
));
540 EXPECT_EQ(*EmptyVar
, "");
541 EXPECT_TRUE(errorToBool(UnknownVar
.takeError()));
543 // Clear local variables and check they become absent.
544 Cxt
.clearLocalVars();
545 LocalVar
= Cxt
.getPatternVarValue(LocalVarStr
);
546 EXPECT_TRUE(errorToBool(LocalVar
.takeError()));
547 // Check a numeric expression's evaluation fails if called after clearing of
548 // local variables, if it was created before. This is important because local
549 // variable clearing due to --enable-var-scope happens after numeric
550 // expressions are linked to the numeric variables they use.
551 EXPECT_TRUE(errorToBool((*ExpressionAST
)->eval().takeError()));
552 P
= FileCheckPattern(Check::CheckPlain
, &Cxt
, 2);
553 ExpressionAST
= P
.parseNumericSubstitutionBlock(
554 LocalNumVar1Ref
, DefinedNumericVariable
, /*IsLegacyLineExpr=*/false,
555 /*LineNumber=*/2, &Cxt
, SM
);
556 ASSERT_TRUE(bool(ExpressionAST
));
557 ExpressionVal
= (*ExpressionAST
)->eval();
558 EXPECT_TRUE(errorToBool(ExpressionVal
.takeError()));
559 ExpressionAST
= P
.parseNumericSubstitutionBlock(
560 LocalNumVar2Ref
, DefinedNumericVariable
, /*IsLegacyLineExpr=*/false,
561 /*LineNumber=*/2, &Cxt
, SM
);
562 ASSERT_TRUE(bool(ExpressionAST
));
563 ExpressionVal
= (*ExpressionAST
)->eval();
564 EXPECT_TRUE(errorToBool(ExpressionVal
.takeError()));
565 EmptyVar
= Cxt
.getPatternVarValue(EmptyVarStr
);
566 EXPECT_TRUE(errorToBool(EmptyVar
.takeError()));
567 // Clear again because parseNumericSubstitutionBlock would have created a
568 // dummy variable and stored it in GlobalNumericVariableTable.
569 Cxt
.clearLocalVars();
571 // Redefine global variables and check variables are defined again.
572 GlobalDefines
.emplace_back(std::string("$GlobalVar=BAR"));
573 GlobalDefines
.emplace_back(std::string("#$GlobalNumVar=36"));
574 ASSERT_FALSE(errorToBool(Cxt
.defineCmdlineVariables(GlobalDefines
, SM
)));
575 StringRef GlobalVarStr
= "$GlobalVar";
576 StringRef GlobalNumVarRef
= bufferize(SM
, "$GlobalNumVar");
577 Expected
<StringRef
> GlobalVar
= Cxt
.getPatternVarValue(GlobalVarStr
);
578 ASSERT_TRUE(bool(GlobalVar
));
579 EXPECT_EQ(*GlobalVar
, "BAR");
580 P
= FileCheckPattern(Check::CheckPlain
, &Cxt
, 3);
581 ExpressionAST
= P
.parseNumericSubstitutionBlock(
582 GlobalNumVarRef
, DefinedNumericVariable
, /*IsLegacyLineExpr=*/false,
583 /*LineNumber=*/3, &Cxt
, SM
);
584 ASSERT_TRUE(bool(ExpressionAST
));
585 ExpressionVal
= (*ExpressionAST
)->eval();
586 ASSERT_TRUE(bool(ExpressionVal
));
587 EXPECT_EQ(*ExpressionVal
, 36U);
589 // Clear local variables and check global variables remain defined.
590 Cxt
.clearLocalVars();
591 EXPECT_FALSE(errorToBool(Cxt
.getPatternVarValue(GlobalVarStr
).takeError()));
592 P
= FileCheckPattern(Check::CheckPlain
, &Cxt
, 4);
593 ExpressionAST
= P
.parseNumericSubstitutionBlock(
594 GlobalNumVarRef
, DefinedNumericVariable
, /*IsLegacyLineExpr=*/false,
595 /*LineNumber=*/4, &Cxt
, SM
);
596 ASSERT_TRUE(bool(ExpressionAST
));
597 ExpressionVal
= (*ExpressionAST
)->eval();
598 ASSERT_TRUE(bool(ExpressionVal
));
599 EXPECT_EQ(*ExpressionVal
, 36U);