[llvm] [cmake] Add possibility to use ChooseMSVCCRT.cmake when include LLVM library
[llvm-core.git] / unittests / Support / FileCheckTest.cpp
blobfd1df57ca73c123f0f394b62be445f136de8c45a
1 //===- llvm/unittest/Support/FileCheckTest.cpp - FileCheck tests --===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Support/FileCheck.h"
10 #include "gtest/gtest.h"
11 #include <unordered_set>
13 using namespace llvm;
14 namespace {
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());
27 Value = Max.eval();
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) {
33 bool First = true;
34 std::string Str;
35 for (StringRef S : Set) {
36 Str += Twine(First ? "{" + S : ", " + S).str();
37 First = false;
39 Str += '}';
40 return Str;
43 static void
44 expectUndefErrors(std::unordered_set<std::string> ExpectedUndefVarNames,
45 Error Err) {
46 handleAllErrors(std::move(Err), [&](const FileCheckUndefVarError &E) {
47 ExpectedUndefVarNames.erase(E.getVarName());
48 });
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());
72 FooVar.setValue(42);
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.
84 FooVar.clearValue();
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);
93 FooVar.setValue(42);
94 std::unique_ptr<FileCheckNumericVariableUse> FooVarUse =
95 std::make_unique<FileCheckNumericVariableUse>("FOO", &FooVar);
96 FileCheckNumericVariable BarVar = FileCheckNumericVariable("BAR", 2);
97 BarVar.setValue(18);
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
109 // variable.
110 FooVar.clearValue();
111 Value = Binop.eval();
112 ASSERT_FALSE(Value);
113 expectUndefError("FOO", Value.takeError());
115 // 2 undefined variables: eval fails, error contains names of all undefined
116 // variables.
117 BarVar.clearValue();
118 Value = Binop.eval();
119 ASSERT_FALSE(Value);
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());
140 return StrBufferRef;
143 TEST_F(FileCheckTest, ParseVar) {
144 SourceMgr SM;
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 {
213 private:
214 size_t LineNumber = 1;
215 SourceMgr SM;
216 FileCheckRequest Req;
217 FileCheckPatternContext Context;
218 FileCheckPattern P =
219 FileCheckPattern(Check::CheckPlain, &Context, LineNumber++);
221 public:
222 PatternTester() {
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
227 // constructor.
228 EXPECT_FALSE(
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.
236 initNextPattern();
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;
246 return errorToBool(
247 P.parseNumericSubstitutionBlock(ExprBufferRef, DefinedNumericVariable,
248 false, LineNumber - 1, &Context, SM)
249 .takeError());
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);
259 size_t MatchLen;
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+"));
320 // Valid expression.
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) {
402 SourceMgr SM;
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
409 // variable's name.
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
417 // the right value.
418 FileCheckNumericVariable LineVar = FileCheckNumericVariable("@LINE", 1);
419 FileCheckNumericVariable NVar = FileCheckNumericVariable("N", 1);
420 LineVar.setValue(42);
421 NVar.setValue(10);
422 auto LineVarUse =
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());
442 NVar.clearValue();
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;
458 SourceMgr SM;
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);
533 ExpressionAST =
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);
603 } // namespace