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