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 //===----------------------------------------------------------------------===//
8
9 #include "llvm/Support/FileCheck.h"
10 #include "../lib/Support/FileCheckImpl.h"
11 #include "gtest/gtest.h"
12 #include <unordered_set>
13
14 using namespace llvm;
15
16 namespace {
17
18 class FileCheckTest : public ::testing::Test {};
19
TEST_F(FileCheckTest,Literal)20 TEST_F(FileCheckTest, Literal) {
21 // Eval returns the literal's value.
22 ExpressionLiteral Ten(10);
23 Expected<uint64_t> Value = Ten.eval();
24 ASSERT_TRUE(bool(Value));
25 EXPECT_EQ(10U, *Value);
26
27 // Max value can be correctly represented.
28 ExpressionLiteral 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);
32 }
33
toString(const std::unordered_set<std::string> & Set)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;
40 }
41 Str += '}';
42 return Str;
43 }
44
45 static void
expectUndefErrors(std::unordered_set<std::string> ExpectedUndefVarNames,Error Err)46 expectUndefErrors(std::unordered_set<std::string> ExpectedUndefVarNames,
47 Error Err) {
48 handleAllErrors(std::move(Err), [&](const UndefVarError &E) {
49 ExpectedUndefVarNames.erase(E.getVarName());
50 });
51 EXPECT_TRUE(ExpectedUndefVarNames.empty()) << toString(ExpectedUndefVarNames);
52 }
53
54 // Return whether Err contains any UndefVarError whose associated name is not
55 // ExpectedUndefVarName.
expectUndefError(const Twine & ExpectedUndefVarName,Error Err)56 static void expectUndefError(const Twine &ExpectedUndefVarName, Error Err) {
57 expectUndefErrors({ExpectedUndefVarName.str()}, std::move(Err));
58 }
59
doAdd(uint64_t OpL,uint64_t OpR)60 uint64_t doAdd(uint64_t OpL, uint64_t OpR) { return OpL + OpR; }
61
TEST_F(FileCheckTest,NumericVariable)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 NumericVariable FooVar("FOO", 1);
66 EXPECT_EQ("FOO", FooVar.getName());
67 NumericVariableUse FooVarUse("FOO", &FooVar);
68 EXPECT_FALSE(FooVar.getValue());
69 Expected<uint64_t> EvalResult = FooVarUse.eval();
70 ASSERT_FALSE(EvalResult);
71 expectUndefError("FOO", EvalResult.takeError());
72
73 FooVar.setValue(42);
74
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);
82
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());
90 }
91
TEST_F(FileCheckTest,Binop)92 TEST_F(FileCheckTest, Binop) {
93 NumericVariable FooVar("FOO", 1);
94 FooVar.setValue(42);
95 std::unique_ptr<NumericVariableUse> FooVarUse =
96 std::make_unique<NumericVariableUse>("FOO", &FooVar);
97 NumericVariable BarVar("BAR", 2);
98 BarVar.setValue(18);
99 std::unique_ptr<NumericVariableUse> BarVarUse =
100 std::make_unique<NumericVariableUse>("BAR", &BarVar);
101 BinaryOperation Binop(doAdd, std::move(FooVarUse), std::move(BarVarUse));
102
103 // Defined variable: eval returns right value.
104 Expected<uint64_t> Value = Binop.eval();
105 ASSERT_TRUE(bool(Value));
106 EXPECT_EQ(60U, *Value);
107
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());
114
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());
121 }
122
TEST_F(FileCheckTest,ValidVarNameStart)123 TEST_F(FileCheckTest, ValidVarNameStart) {
124 EXPECT_TRUE(Pattern::isValidVarNameStart('a'));
125 EXPECT_TRUE(Pattern::isValidVarNameStart('G'));
126 EXPECT_TRUE(Pattern::isValidVarNameStart('_'));
127 EXPECT_FALSE(Pattern::isValidVarNameStart('2'));
128 EXPECT_FALSE(Pattern::isValidVarNameStart('$'));
129 EXPECT_FALSE(Pattern::isValidVarNameStart('@'));
130 EXPECT_FALSE(Pattern::isValidVarNameStart('+'));
131 EXPECT_FALSE(Pattern::isValidVarNameStart('-'));
132 EXPECT_FALSE(Pattern::isValidVarNameStart(':'));
133 }
134
bufferize(SourceMgr & SM,StringRef Str)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;
141 }
142
TEST_F(FileCheckTest,ParseVar)143 TEST_F(FileCheckTest, ParseVar) {
144 SourceMgr SM;
145 StringRef OrigVarName = bufferize(SM, "GoodVar42");
146 StringRef VarName = OrigVarName;
147 Expected<Pattern::VariableProperties> ParsedVarResult =
148 Pattern::parseVariable(VarName, SM);
149 ASSERT_TRUE(bool(ParsedVarResult));
150 EXPECT_EQ(ParsedVarResult->Name, OrigVarName);
151 EXPECT_TRUE(VarName.empty());
152 EXPECT_FALSE(ParsedVarResult->IsPseudo);
153
154 VarName = OrigVarName = bufferize(SM, "$GoodGlobalVar");
155 ParsedVarResult = Pattern::parseVariable(VarName, SM);
156 ASSERT_TRUE(bool(ParsedVarResult));
157 EXPECT_EQ(ParsedVarResult->Name, OrigVarName);
158 EXPECT_TRUE(VarName.empty());
159 EXPECT_FALSE(ParsedVarResult->IsPseudo);
160
161 VarName = OrigVarName = bufferize(SM, "@GoodPseudoVar");
162 ParsedVarResult = Pattern::parseVariable(VarName, SM);
163 ASSERT_TRUE(bool(ParsedVarResult));
164 EXPECT_EQ(ParsedVarResult->Name, OrigVarName);
165 EXPECT_TRUE(VarName.empty());
166 EXPECT_TRUE(ParsedVarResult->IsPseudo);
167
168 VarName = bufferize(SM, "42BadVar");
169 ParsedVarResult = Pattern::parseVariable(VarName, SM);
170 EXPECT_TRUE(errorToBool(ParsedVarResult.takeError()));
171
172 VarName = bufferize(SM, "$@");
173 ParsedVarResult = Pattern::parseVariable(VarName, SM);
174 EXPECT_TRUE(errorToBool(ParsedVarResult.takeError()));
175
176 VarName = OrigVarName = bufferize(SM, "B@dVar");
177 ParsedVarResult = Pattern::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);
182
183 VarName = OrigVarName = bufferize(SM, "B$dVar");
184 ParsedVarResult = Pattern::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);
189
190 VarName = bufferize(SM, "BadVar+");
191 ParsedVarResult = Pattern::parseVariable(VarName, SM);
192 ASSERT_TRUE(bool(ParsedVarResult));
193 EXPECT_EQ(VarName, "+");
194 EXPECT_EQ(ParsedVarResult->Name, "BadVar");
195 EXPECT_FALSE(ParsedVarResult->IsPseudo);
196
197 VarName = bufferize(SM, "BadVar-");
198 ParsedVarResult = Pattern::parseVariable(VarName, SM);
199 ASSERT_TRUE(bool(ParsedVarResult));
200 EXPECT_EQ(VarName, "-");
201 EXPECT_EQ(ParsedVarResult->Name, "BadVar");
202 EXPECT_FALSE(ParsedVarResult->IsPseudo);
203
204 VarName = bufferize(SM, "BadVar:");
205 ParsedVarResult = Pattern::parseVariable(VarName, SM);
206 ASSERT_TRUE(bool(ParsedVarResult));
207 EXPECT_EQ(VarName, ":");
208 EXPECT_EQ(ParsedVarResult->Name, "BadVar");
209 EXPECT_FALSE(ParsedVarResult->IsPseudo);
210 }
211
212 class PatternTester {
213 private:
214 size_t LineNumber = 1;
215 SourceMgr SM;
216 FileCheckRequest Req;
217 FileCheckPatternContext Context;
218 Pattern P{Check::CheckPlain, &Context, LineNumber++};
219
220 public:
PatternTester()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();
236 }
237
initNextPattern()238 void initNextPattern() {
239 P = Pattern(Check::CheckPlain, &Context, LineNumber++);
240 }
241
parseSubstExpect(StringRef Expr)242 bool parseSubstExpect(StringRef Expr) {
243 StringRef ExprBufferRef = bufferize(SM, Expr);
244 Optional<NumericVariable *> DefinedNumericVariable;
245 return errorToBool(
246 P.parseNumericSubstitutionBlock(ExprBufferRef, DefinedNumericVariable,
247 false, LineNumber - 1, &Context, SM)
248 .takeError());
249 }
250
parsePatternExpect(StringRef Pattern)251 bool parsePatternExpect(StringRef Pattern) {
252 StringRef PatBufferRef = bufferize(SM, Pattern);
253 return P.parsePattern(PatBufferRef, "CHECK", SM, Req);
254 }
255
matchExpect(StringRef Buffer)256 bool matchExpect(StringRef Buffer) {
257 StringRef BufferRef = bufferize(SM, Buffer);
258 size_t MatchLen;
259 return errorToBool(P.match(BufferRef, MatchLen, SM).takeError());
260 }
261 };
262
TEST_F(FileCheckTest,ParseExpr)263 TEST_F(FileCheckTest, ParseExpr) {
264 PatternTester Tester;
265
266 // Variable definition.
267
268 // Definition of invalid variable.
269 EXPECT_TRUE(Tester.parseSubstExpect("10VAR:"));
270 EXPECT_TRUE(Tester.parseSubstExpect("@FOO:"));
271 EXPECT_TRUE(Tester.parseSubstExpect("@LINE:"));
272
273 // Conflict with pattern variable.
274 EXPECT_TRUE(Tester.parseSubstExpect("BAR:"));
275
276 // Garbage after name of variable being defined.
277 EXPECT_TRUE(Tester.parseSubstExpect("VAR GARBAGE:"));
278
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]]"));
285
286 // Numeric expression.
287
288 // Unacceptable variable.
289 EXPECT_TRUE(Tester.parseSubstExpect("10VAR"));
290 EXPECT_TRUE(Tester.parseSubstExpect("@FOO"));
291
292 // Only valid variable.
293 EXPECT_FALSE(Tester.parseSubstExpect("@LINE"));
294 EXPECT_FALSE(Tester.parseSubstExpect("FOO"));
295 EXPECT_FALSE(Tester.parseSubstExpect("UNDEF"));
296
297 // Valid empty expression.
298 EXPECT_FALSE(Tester.parseSubstExpect(""));
299
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"));
306
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"));
312
313 // Unsupported operator.
314 EXPECT_TRUE(Tester.parseSubstExpect("@LINE/2"));
315
316 // Missing offset operand.
317 EXPECT_TRUE(Tester.parseSubstExpect("@LINE+"));
318
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]]"));
327 }
328
TEST_F(FileCheckTest,ParsePattern)329 TEST_F(FileCheckTest, ParsePattern) {
330 PatternTester Tester;
331
332 // Space in pattern variable expression.
333 EXPECT_TRUE(Tester.parsePatternExpect("[[ BAR]]"));
334
335 // Invalid variable name.
336 EXPECT_TRUE(Tester.parsePatternExpect("[[42INVALID]]"));
337
338 // Invalid pattern variable definition.
339 EXPECT_TRUE(Tester.parsePatternExpect("[[@PAT:]]"));
340 EXPECT_TRUE(Tester.parsePatternExpect("[[PAT+2:]]"));
341
342 // Collision with numeric variable.
343 EXPECT_TRUE(Tester.parsePatternExpect("[[FOO:]]"));
344
345 // Valid use of pattern variable.
346 EXPECT_FALSE(Tester.parsePatternExpect("[[BAR]]"));
347
348 // Valid pattern variable definition.
349 EXPECT_FALSE(Tester.parsePatternExpect("[[PAT:[0-9]+]]"));
350
351 // Invalid numeric expressions.
352 EXPECT_TRUE(Tester.parsePatternExpect("[[#42INVALID]]"));
353 EXPECT_TRUE(Tester.parsePatternExpect("[[#@FOO]]"));
354 EXPECT_TRUE(Tester.parsePatternExpect("[[#@LINE/2]]"));
355
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:]]"));
360 }
361
TEST_F(FileCheckTest,Match)362 TEST_F(FileCheckTest, Match) {
363 PatternTester Tester;
364
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"));
369
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"));
376
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"));
383
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"));
398 }
399
TEST_F(FileCheckTest,Substitution)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)));
406
407 // Substitution of an undefined string variable fails and error holds that
408 // variable's name.
409 StringSubstitution StringSubstitution(&Context, "VAR404", 42);
410 Expected<std::string> SubstValue = StringSubstitution.getResult();
411 ASSERT_FALSE(bool(SubstValue));
412 expectUndefError("VAR404", SubstValue.takeError());
413
414 // Substitutions of defined pseudo and non-pseudo numeric variables return
415 // the right value.
416 NumericVariable LineVar("@LINE", 1);
417 NumericVariable NVar("N", 1);
418 LineVar.setValue(42);
419 NVar.setValue(10);
420 auto LineVarUse = std::make_unique<NumericVariableUse>("@LINE", &LineVar);
421 auto NVarUse = std::make_unique<NumericVariableUse>("N", &NVar);
422 NumericSubstitution SubstitutionLine(&Context, "@LINE", std::move(LineVarUse),
423 12);
424 NumericSubstitution SubstitutionN(&Context, "N", std::move(NVarUse), 30);
425 SubstValue = SubstitutionLine.getResult();
426 ASSERT_TRUE(bool(SubstValue));
427 EXPECT_EQ("42", *SubstValue);
428 SubstValue = SubstitutionN.getResult();
429 ASSERT_TRUE(bool(SubstValue));
430 EXPECT_EQ("10", *SubstValue);
431
432 // Substitution of an undefined numeric variable fails, error holds name of
433 // undefined variable.
434 LineVar.clearValue();
435 SubstValue = SubstitutionLine.getResult();
436 ASSERT_FALSE(bool(SubstValue));
437 expectUndefError("@LINE", SubstValue.takeError());
438 NVar.clearValue();
439 SubstValue = SubstitutionN.getResult();
440 ASSERT_FALSE(bool(SubstValue));
441 expectUndefError("N", SubstValue.takeError());
442
443 // Substitution of a defined string variable returns the right value.
444 Pattern P(Check::CheckPlain, &Context, 1);
445 StringSubstitution = llvm::StringSubstitution(&Context, "FOO", 42);
446 SubstValue = StringSubstitution.getResult();
447 ASSERT_TRUE(bool(SubstValue));
448 EXPECT_EQ("BAR", *SubstValue);
449 }
450
TEST_F(FileCheckTest,FileCheckContext)451 TEST_F(FileCheckTest, FileCheckContext) {
452 FileCheckPatternContext Cxt;
453 std::vector<std::string> GlobalDefines;
454 SourceMgr SM;
455
456 // Missing equal sign.
457 GlobalDefines.emplace_back(std::string("LocalVar"));
458 EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
459 GlobalDefines.clear();
460 GlobalDefines.emplace_back(std::string("#LocalNumVar"));
461 EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
462
463 // Empty variable name.
464 GlobalDefines.clear();
465 GlobalDefines.emplace_back(std::string("=18"));
466 EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
467 GlobalDefines.clear();
468 GlobalDefines.emplace_back(std::string("#=18"));
469 EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
470
471 // Invalid variable name.
472 GlobalDefines.clear();
473 GlobalDefines.emplace_back(std::string("18LocalVar=18"));
474 EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
475 GlobalDefines.clear();
476 GlobalDefines.emplace_back(std::string("#18LocalNumVar=18"));
477 EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
478
479 // Name conflict between pattern and numeric variable.
480 GlobalDefines.clear();
481 GlobalDefines.emplace_back(std::string("LocalVar=18"));
482 GlobalDefines.emplace_back(std::string("#LocalVar=36"));
483 EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
484 Cxt = FileCheckPatternContext();
485 GlobalDefines.clear();
486 GlobalDefines.emplace_back(std::string("#LocalNumVar=18"));
487 GlobalDefines.emplace_back(std::string("LocalNumVar=36"));
488 EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
489 Cxt = FileCheckPatternContext();
490
491 // Invalid numeric value for numeric variable.
492 GlobalDefines.clear();
493 GlobalDefines.emplace_back(std::string("#LocalNumVar=x"));
494 EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
495
496 // Define local variables from command-line.
497 GlobalDefines.clear();
498 // Clear local variables to remove dummy numeric variable x that
499 // parseNumericSubstitutionBlock would have created and stored in
500 // GlobalNumericVariableTable.
501 Cxt.clearLocalVars();
502 GlobalDefines.emplace_back(std::string("LocalVar=FOO"));
503 GlobalDefines.emplace_back(std::string("EmptyVar="));
504 GlobalDefines.emplace_back(std::string("#LocalNumVar1=18"));
505 GlobalDefines.emplace_back(std::string("#LocalNumVar2=LocalNumVar1+2"));
506 ASSERT_FALSE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
507
508 // Check defined variables are present and undefined is absent.
509 StringRef LocalVarStr = "LocalVar";
510 StringRef LocalNumVar1Ref = bufferize(SM, "LocalNumVar1");
511 StringRef LocalNumVar2Ref = bufferize(SM, "LocalNumVar2");
512 StringRef EmptyVarStr = "EmptyVar";
513 StringRef UnknownVarStr = "UnknownVar";
514 Expected<StringRef> LocalVar = Cxt.getPatternVarValue(LocalVarStr);
515 Pattern P(Check::CheckPlain, &Cxt, 1);
516 Optional<NumericVariable *> DefinedNumericVariable;
517 Expected<std::unique_ptr<ExpressionAST>> ExpressionASTPointer =
518 P.parseNumericSubstitutionBlock(LocalNumVar1Ref, DefinedNumericVariable,
519 /*IsLegacyLineExpr=*/false,
520 /*LineNumber=*/1, &Cxt, SM);
521 ASSERT_TRUE(bool(LocalVar));
522 EXPECT_EQ(*LocalVar, "FOO");
523 Expected<StringRef> EmptyVar = Cxt.getPatternVarValue(EmptyVarStr);
524 Expected<StringRef> UnknownVar = Cxt.getPatternVarValue(UnknownVarStr);
525 ASSERT_TRUE(bool(ExpressionASTPointer));
526 Expected<uint64_t> ExpressionVal = (*ExpressionASTPointer)->eval();
527 ASSERT_TRUE(bool(ExpressionVal));
528 EXPECT_EQ(*ExpressionVal, 18U);
529 ExpressionASTPointer =
530 P.parseNumericSubstitutionBlock(LocalNumVar2Ref, DefinedNumericVariable,
531 /*IsLegacyLineExpr=*/false,
532 /*LineNumber=*/1, &Cxt, SM);
533 ASSERT_TRUE(bool(ExpressionASTPointer));
534 ExpressionVal = (*ExpressionASTPointer)->eval();
535 ASSERT_TRUE(bool(ExpressionVal));
536 EXPECT_EQ(*ExpressionVal, 20U);
537 ASSERT_TRUE(bool(EmptyVar));
538 EXPECT_EQ(*EmptyVar, "");
539 EXPECT_TRUE(errorToBool(UnknownVar.takeError()));
540
541 // Clear local variables and check they become absent.
542 Cxt.clearLocalVars();
543 LocalVar = Cxt.getPatternVarValue(LocalVarStr);
544 EXPECT_TRUE(errorToBool(LocalVar.takeError()));
545 // Check a numeric expression's evaluation fails if called after clearing of
546 // local variables, if it was created before. This is important because local
547 // variable clearing due to --enable-var-scope happens after numeric
548 // expressions are linked to the numeric variables they use.
549 EXPECT_TRUE(errorToBool((*ExpressionASTPointer)->eval().takeError()));
550 P = Pattern(Check::CheckPlain, &Cxt, 2);
551 ExpressionASTPointer = P.parseNumericSubstitutionBlock(
552 LocalNumVar1Ref, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
553 /*LineNumber=*/2, &Cxt, SM);
554 ASSERT_TRUE(bool(ExpressionASTPointer));
555 ExpressionVal = (*ExpressionASTPointer)->eval();
556 EXPECT_TRUE(errorToBool(ExpressionVal.takeError()));
557 ExpressionASTPointer = P.parseNumericSubstitutionBlock(
558 LocalNumVar2Ref, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
559 /*LineNumber=*/2, &Cxt, SM);
560 ASSERT_TRUE(bool(ExpressionASTPointer));
561 ExpressionVal = (*ExpressionASTPointer)->eval();
562 EXPECT_TRUE(errorToBool(ExpressionVal.takeError()));
563 EmptyVar = Cxt.getPatternVarValue(EmptyVarStr);
564 EXPECT_TRUE(errorToBool(EmptyVar.takeError()));
565 // Clear again because parseNumericSubstitutionBlock would have created a
566 // dummy variable and stored it in GlobalNumericVariableTable.
567 Cxt.clearLocalVars();
568
569 // Redefine global variables and check variables are defined again.
570 GlobalDefines.emplace_back(std::string("$GlobalVar=BAR"));
571 GlobalDefines.emplace_back(std::string("#$GlobalNumVar=36"));
572 ASSERT_FALSE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
573 StringRef GlobalVarStr = "$GlobalVar";
574 StringRef GlobalNumVarRef = bufferize(SM, "$GlobalNumVar");
575 Expected<StringRef> GlobalVar = Cxt.getPatternVarValue(GlobalVarStr);
576 ASSERT_TRUE(bool(GlobalVar));
577 EXPECT_EQ(*GlobalVar, "BAR");
578 P = Pattern(Check::CheckPlain, &Cxt, 3);
579 ExpressionASTPointer = P.parseNumericSubstitutionBlock(
580 GlobalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
581 /*LineNumber=*/3, &Cxt, SM);
582 ASSERT_TRUE(bool(ExpressionASTPointer));
583 ExpressionVal = (*ExpressionASTPointer)->eval();
584 ASSERT_TRUE(bool(ExpressionVal));
585 EXPECT_EQ(*ExpressionVal, 36U);
586
587 // Clear local variables and check global variables remain defined.
588 Cxt.clearLocalVars();
589 EXPECT_FALSE(errorToBool(Cxt.getPatternVarValue(GlobalVarStr).takeError()));
590 P = Pattern(Check::CheckPlain, &Cxt, 4);
591 ExpressionASTPointer = P.parseNumericSubstitutionBlock(
592 GlobalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
593 /*LineNumber=*/4, &Cxt, SM);
594 ASSERT_TRUE(bool(ExpressionASTPointer));
595 ExpressionVal = (*ExpressionASTPointer)->eval();
596 ASSERT_TRUE(bool(ExpressionVal));
597 EXPECT_EQ(*ExpressionVal, 36U);
598 }
599 } // namespace
600