[obj2yaml] - Stop triggering UB when dumping corrupted strings.
[llvm-complete.git] / unittests / Support / FileCheckTest.cpp
blob66465f104eb5e3cb3a38d830d79f34aa167b7a7c
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 "../lib/Support/FileCheckImpl.h"
11 #include "gtest/gtest.h"
12 #include <unordered_set>
14 using namespace llvm;
16 namespace {
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());
29 Value = Max.eval();
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) {
35 bool First = true;
36 std::string Str;
37 for (StringRef S : Set) {
38 Str += Twine(First ? "{" + S : ", " + S).str();
39 First = false;
41 Str += '}';
42 return Str;
45 static void
46 expectUndefErrors(std::unordered_set<std::string> ExpectedUndefVarNames,
47 Error Err) {
48 handleAllErrors(std::move(Err), [&](const FileCheckUndefVarError &E) {
49 ExpectedUndefVarNames.erase(E.getVarName());
50 });
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());
73 FooVar.setValue(42);
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.
85 FooVar.clearValue();
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);
94 FooVar.setValue(42);
95 std::unique_ptr<FileCheckNumericVariableUse> FooVarUse =
96 std::make_unique<FileCheckNumericVariableUse>("FOO", &FooVar);
97 FileCheckNumericVariable BarVar("BAR", 2);
98 BarVar.setValue(18);
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
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{Check::CheckPlain, &Context, LineNumber++};
220 public:
221 PatternTester() {
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
226 // constructor.
227 EXPECT_FALSE(
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.
235 initNextPattern();
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;
245 return errorToBool(
246 P.parseNumericSubstitutionBlock(ExprBufferRef, DefinedNumericVariable,
247 false, LineNumber - 1, &Context, SM)
248 .takeError());
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);
258 size_t MatchLen;
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+"));
319 // Valid expression.
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) {
401 SourceMgr SM;
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
408 // variable's name.
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
415 // the right value.
416 FileCheckNumericVariable LineVar("@LINE", 1);
417 FileCheckNumericVariable NVar("N", 1);
418 LineVar.setValue(42);
419 NVar.setValue(10);
420 auto LineVarUse =
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),
426 30);
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());
440 NVar.clearValue();
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;
456 SourceMgr SM;
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);
531 ExpressionAST =
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);
601 } // namespace