FileCheckTest.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  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. #include "llvm/Support/FileCheck.h"
  9. #include "gtest/gtest.h"
  10. using namespace llvm;
  11. namespace {
  12. class FileCheckTest : public ::testing::Test {};
  13. TEST_F(FileCheckTest, NumericVariable) {
  14. // Undefined variable: getValue and clearValue fails, setValue works.
  15. FileCheckNumericVariable FooVar = FileCheckNumericVariable(1, "FOO");
  16. EXPECT_EQ("FOO", FooVar.getName());
  17. llvm::Optional<uint64_t> Value = FooVar.getValue();
  18. EXPECT_FALSE(Value);
  19. EXPECT_TRUE(FooVar.clearValue());
  20. EXPECT_FALSE(FooVar.setValue(42));
  21. // Defined variable: getValue returns value set, setValue fails.
  22. Value = FooVar.getValue();
  23. EXPECT_TRUE(Value);
  24. EXPECT_EQ(42U, *Value);
  25. EXPECT_TRUE(FooVar.setValue(43));
  26. Value = FooVar.getValue();
  27. EXPECT_TRUE(Value);
  28. EXPECT_EQ(42U, *Value);
  29. // Clearing variable: getValue fails, clearValue again fails.
  30. EXPECT_FALSE(FooVar.clearValue());
  31. Value = FooVar.getValue();
  32. EXPECT_FALSE(Value);
  33. EXPECT_TRUE(FooVar.clearValue());
  34. }
  35. uint64_t doAdd(uint64_t OpL, uint64_t OpR) { return OpL + OpR; }
  36. static void expectUndefError(const Twine &ExpectedStr, Error Err) {
  37. handleAllErrors(std::move(Err), [&](const FileCheckUndefVarError &E) {
  38. EXPECT_EQ(ExpectedStr.str(), E.getVarName());
  39. });
  40. }
  41. TEST_F(FileCheckTest, Expression) {
  42. FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO", 42);
  43. FileCheckExpression Expression = FileCheckExpression(doAdd, &FooVar, 18);
  44. // Defined variable: eval returns right value.
  45. Expected<uint64_t> Value = Expression.eval();
  46. EXPECT_TRUE(static_cast<bool>(Value));
  47. EXPECT_EQ(60U, *Value);
  48. // Undefined variable: eval fails, undefined variable returned. We call
  49. // getUndefVarName first to check that it can be called without calling
  50. // eval() first.
  51. FooVar.clearValue();
  52. Error EvalError = Expression.eval().takeError();
  53. EXPECT_TRUE(errorToBool(std::move(EvalError)));
  54. expectUndefError("FOO", std::move(EvalError));
  55. }
  56. TEST_F(FileCheckTest, ValidVarNameStart) {
  57. EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('a'));
  58. EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('G'));
  59. EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('_'));
  60. EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('2'));
  61. EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('$'));
  62. EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('@'));
  63. EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('+'));
  64. EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('-'));
  65. EXPECT_FALSE(FileCheckPattern::isValidVarNameStart(':'));
  66. }
  67. static StringRef bufferize(SourceMgr &SM, StringRef Str) {
  68. std::unique_ptr<MemoryBuffer> Buffer =
  69. MemoryBuffer::getMemBufferCopy(Str, "TestBuffer");
  70. StringRef StrBufferRef = Buffer->getBuffer();
  71. SM.AddNewSourceBuffer(std::move(Buffer), SMLoc());
  72. return StrBufferRef;
  73. }
  74. TEST_F(FileCheckTest, ParseVar) {
  75. SourceMgr SM;
  76. StringRef OrigVarName = bufferize(SM, "GoodVar42");
  77. StringRef VarName = OrigVarName;
  78. bool IsPseudo = true;
  79. Expected<StringRef> ParsedName =
  80. FileCheckPattern::parseVariable(VarName, IsPseudo, SM);
  81. EXPECT_TRUE(static_cast<bool>(ParsedName));
  82. EXPECT_EQ(*ParsedName, OrigVarName);
  83. EXPECT_TRUE(VarName.empty());
  84. EXPECT_FALSE(IsPseudo);
  85. VarName = OrigVarName = bufferize(SM, "$GoodGlobalVar");
  86. IsPseudo = true;
  87. ParsedName = FileCheckPattern::parseVariable(VarName, IsPseudo, SM);
  88. EXPECT_TRUE(static_cast<bool>(ParsedName));
  89. EXPECT_EQ(*ParsedName, OrigVarName);
  90. EXPECT_TRUE(VarName.empty());
  91. EXPECT_FALSE(IsPseudo);
  92. VarName = OrigVarName = bufferize(SM, "@GoodPseudoVar");
  93. IsPseudo = true;
  94. ParsedName = FileCheckPattern::parseVariable(VarName, IsPseudo, SM);
  95. EXPECT_TRUE(static_cast<bool>(ParsedName));
  96. EXPECT_EQ(*ParsedName, OrigVarName);
  97. EXPECT_TRUE(VarName.empty());
  98. EXPECT_TRUE(IsPseudo);
  99. VarName = bufferize(SM, "42BadVar");
  100. ParsedName = FileCheckPattern::parseVariable(VarName, IsPseudo, SM);
  101. EXPECT_TRUE(errorToBool(ParsedName.takeError()));
  102. VarName = bufferize(SM, "$@");
  103. ParsedName = FileCheckPattern::parseVariable(VarName, IsPseudo, SM);
  104. EXPECT_TRUE(errorToBool(ParsedName.takeError()));
  105. VarName = OrigVarName = bufferize(SM, "B@dVar");
  106. IsPseudo = true;
  107. ParsedName = FileCheckPattern::parseVariable(VarName, IsPseudo, SM);
  108. EXPECT_TRUE(static_cast<bool>(ParsedName));
  109. EXPECT_EQ(VarName, OrigVarName.substr(1));
  110. EXPECT_EQ(*ParsedName, "B");
  111. EXPECT_FALSE(IsPseudo);
  112. VarName = OrigVarName = bufferize(SM, "B$dVar");
  113. IsPseudo = true;
  114. ParsedName = FileCheckPattern::parseVariable(VarName, IsPseudo, SM);
  115. EXPECT_TRUE(static_cast<bool>(ParsedName));
  116. EXPECT_EQ(VarName, OrigVarName.substr(1));
  117. EXPECT_EQ(*ParsedName, "B");
  118. EXPECT_FALSE(IsPseudo);
  119. VarName = bufferize(SM, "BadVar+");
  120. IsPseudo = true;
  121. ParsedName = FileCheckPattern::parseVariable(VarName, IsPseudo, SM);
  122. EXPECT_TRUE(static_cast<bool>(ParsedName));
  123. EXPECT_EQ(VarName, "+");
  124. EXPECT_EQ(*ParsedName, "BadVar");
  125. EXPECT_FALSE(IsPseudo);
  126. VarName = bufferize(SM, "BadVar-");
  127. IsPseudo = true;
  128. ParsedName = FileCheckPattern::parseVariable(VarName, IsPseudo, SM);
  129. EXPECT_TRUE(static_cast<bool>(ParsedName));
  130. EXPECT_EQ(VarName, "-");
  131. EXPECT_EQ(*ParsedName, "BadVar");
  132. EXPECT_FALSE(IsPseudo);
  133. VarName = bufferize(SM, "BadVar:");
  134. IsPseudo = true;
  135. ParsedName = FileCheckPattern::parseVariable(VarName, IsPseudo, SM);
  136. EXPECT_TRUE(static_cast<bool>(ParsedName));
  137. EXPECT_EQ(VarName, ":");
  138. EXPECT_EQ(*ParsedName, "BadVar");
  139. EXPECT_FALSE(IsPseudo);
  140. }
  141. class PatternTester {
  142. private:
  143. size_t LineNumber = 1;
  144. SourceMgr SM;
  145. FileCheckRequest Req;
  146. FileCheckPatternContext Context;
  147. FileCheckPattern P =
  148. FileCheckPattern(Check::CheckPlain, &Context, LineNumber++);
  149. public:
  150. PatternTester() {
  151. std::vector<std::string> GlobalDefines;
  152. GlobalDefines.emplace_back(std::string("#FOO=42"));
  153. GlobalDefines.emplace_back(std::string("BAR=BAZ"));
  154. EXPECT_FALSE(
  155. errorToBool(Context.defineCmdlineVariables(GlobalDefines, SM)));
  156. Context.createLineVariable();
  157. // Call parsePattern to have @LINE defined.
  158. P.parsePattern("N/A", "CHECK", SM, Req);
  159. // parsePattern does not expect to be called twice for the same line and
  160. // will set FixedStr and RegExStr incorrectly if it is. Therefore prepare
  161. // a pattern for a different line.
  162. initNextPattern();
  163. }
  164. void initNextPattern() {
  165. P = FileCheckPattern(Check::CheckPlain, &Context, LineNumber++);
  166. }
  167. bool parseNumVarDefExpect(StringRef Expr) {
  168. StringRef ExprBufferRef = bufferize(SM, Expr);
  169. return errorToBool(FileCheckPattern::parseNumericVariableDefinition(
  170. ExprBufferRef, &Context, LineNumber, SM)
  171. .takeError());
  172. }
  173. bool parseSubstExpect(StringRef Expr) {
  174. StringRef ExprBufferRef = bufferize(SM, Expr);
  175. Optional<FileCheckNumericVariable *> DefinedNumericVariable;
  176. return errorToBool(P.parseNumericSubstitutionBlock(
  177. ExprBufferRef, DefinedNumericVariable, SM)
  178. .takeError());
  179. }
  180. bool parsePatternExpect(StringRef Pattern) {
  181. StringRef PatBufferRef = bufferize(SM, Pattern);
  182. return P.parsePattern(PatBufferRef, "CHECK", SM, Req);
  183. }
  184. bool matchExpect(StringRef Buffer) {
  185. StringRef BufferRef = bufferize(SM, Buffer);
  186. size_t MatchLen;
  187. return errorToBool(P.match(BufferRef, MatchLen, SM).takeError());
  188. }
  189. };
  190. TEST_F(FileCheckTest, ParseNumericVariableDefinition) {
  191. PatternTester Tester;
  192. // Invalid definition of pseudo.
  193. EXPECT_TRUE(Tester.parseNumVarDefExpect("@LINE"));
  194. // Conflict with pattern variable.
  195. EXPECT_TRUE(Tester.parseNumVarDefExpect("BAR"));
  196. // Defined variable.
  197. EXPECT_FALSE(Tester.parseNumVarDefExpect("FOO"));
  198. }
  199. TEST_F(FileCheckTest, ParseExpr) {
  200. PatternTester Tester;
  201. // Variable definition.
  202. // Definition of invalid variable.
  203. EXPECT_TRUE(Tester.parseSubstExpect("10VAR:"));
  204. EXPECT_TRUE(Tester.parseSubstExpect("@FOO:"));
  205. EXPECT_TRUE(Tester.parseSubstExpect("@LINE:"));
  206. // Garbage after name of variable being defined.
  207. EXPECT_TRUE(Tester.parseSubstExpect("VAR GARBAGE:"));
  208. // Variable defined to numeric expression.
  209. EXPECT_TRUE(Tester.parseSubstExpect("VAR1: FOO"));
  210. // Acceptable variable definition.
  211. EXPECT_FALSE(Tester.parseSubstExpect("VAR1:"));
  212. EXPECT_FALSE(Tester.parseSubstExpect(" VAR2:"));
  213. EXPECT_FALSE(Tester.parseSubstExpect("VAR3 :"));
  214. EXPECT_FALSE(Tester.parseSubstExpect("VAR3: "));
  215. // Numeric expression.
  216. // Unacceptable variable.
  217. EXPECT_TRUE(Tester.parseSubstExpect("10VAR"));
  218. EXPECT_TRUE(Tester.parseSubstExpect("@FOO"));
  219. // Only valid variable.
  220. EXPECT_FALSE(Tester.parseSubstExpect("@LINE"));
  221. EXPECT_FALSE(Tester.parseSubstExpect("FOO"));
  222. EXPECT_FALSE(Tester.parseSubstExpect("UNDEF"));
  223. // Use variable defined on same line.
  224. EXPECT_FALSE(Tester.parsePatternExpect("[[#LINE1VAR:]]"));
  225. EXPECT_TRUE(Tester.parseSubstExpect("LINE1VAR"));
  226. // Unsupported operator.
  227. EXPECT_TRUE(Tester.parseSubstExpect("@LINE/2"));
  228. // Missing offset operand.
  229. EXPECT_TRUE(Tester.parseSubstExpect("@LINE+"));
  230. // Cannot parse offset operand.
  231. EXPECT_TRUE(Tester.parseSubstExpect("@LINE+x"));
  232. // Unexpected string at end of numeric expression.
  233. EXPECT_TRUE(Tester.parseSubstExpect("@LINE+5x"));
  234. // Valid expression.
  235. EXPECT_FALSE(Tester.parseSubstExpect("@LINE+5"));
  236. EXPECT_FALSE(Tester.parseSubstExpect("FOO+4"));
  237. }
  238. TEST_F(FileCheckTest, ParsePattern) {
  239. PatternTester Tester;
  240. // Space in pattern variable expression.
  241. EXPECT_TRUE(Tester.parsePatternExpect("[[ BAR]]"));
  242. // Invalid variable name.
  243. EXPECT_TRUE(Tester.parsePatternExpect("[[42INVALID]]"));
  244. // Invalid pattern variable definition.
  245. EXPECT_TRUE(Tester.parsePatternExpect("[[@PAT:]]"));
  246. EXPECT_TRUE(Tester.parsePatternExpect("[[PAT+2:]]"));
  247. // Collision with numeric variable.
  248. EXPECT_TRUE(Tester.parsePatternExpect("[[FOO:]]"));
  249. // Valid use of pattern variable.
  250. EXPECT_FALSE(Tester.parsePatternExpect("[[BAR]]"));
  251. // Valid pattern variable definition.
  252. EXPECT_FALSE(Tester.parsePatternExpect("[[PAT:[0-9]+]]"));
  253. // Invalid numeric expressions.
  254. EXPECT_TRUE(Tester.parsePatternExpect("[[#42INVALID]]"));
  255. EXPECT_TRUE(Tester.parsePatternExpect("[[#@FOO]]"));
  256. EXPECT_TRUE(Tester.parsePatternExpect("[[#@LINE/2]]"));
  257. EXPECT_TRUE(Tester.parsePatternExpect("[[#2+@LINE]]"));
  258. EXPECT_TRUE(Tester.parsePatternExpect("[[#YUP:@LINE]]"));
  259. // Valid numeric expressions and numeric variable definition.
  260. EXPECT_FALSE(Tester.parsePatternExpect("[[#FOO]]"));
  261. EXPECT_FALSE(Tester.parsePatternExpect("[[#@LINE+2]]"));
  262. EXPECT_FALSE(Tester.parsePatternExpect("[[#NUMVAR:]]"));
  263. }
  264. TEST_F(FileCheckTest, Match) {
  265. PatternTester Tester;
  266. // Check matching a definition only matches a number.
  267. Tester.parsePatternExpect("[[#NUMVAR:]]");
  268. EXPECT_TRUE(Tester.matchExpect("FAIL"));
  269. EXPECT_FALSE(Tester.matchExpect("18"));
  270. // Check matching the variable defined matches the correct number only
  271. Tester.initNextPattern();
  272. Tester.parsePatternExpect("[[#NUMVAR]] [[#NUMVAR+2]]");
  273. EXPECT_TRUE(Tester.matchExpect("19 21"));
  274. EXPECT_TRUE(Tester.matchExpect("18 21"));
  275. EXPECT_FALSE(Tester.matchExpect("18 20"));
  276. }
  277. TEST_F(FileCheckTest, Substitution) {
  278. SourceMgr SM;
  279. FileCheckPatternContext Context;
  280. std::vector<std::string> GlobalDefines;
  281. GlobalDefines.emplace_back(std::string("FOO=BAR"));
  282. EXPECT_FALSE(errorToBool(Context.defineCmdlineVariables(GlobalDefines, SM)));
  283. // Substitution of an undefined string variable fails and error holds that
  284. // variable's name.
  285. FileCheckStringSubstitution StringSubstitution =
  286. FileCheckStringSubstitution(&Context, "VAR404", 42);
  287. Expected<std::string> SubstValue = StringSubstitution.getResult();
  288. EXPECT_FALSE(static_cast<bool>(SubstValue));
  289. expectUndefError("VAR404", SubstValue.takeError());
  290. // Substitutions of defined pseudo and non-pseudo numeric variables return
  291. // the right value.
  292. FileCheckNumericVariable LineVar = FileCheckNumericVariable("@LINE", 42);
  293. FileCheckNumericVariable NVar = FileCheckNumericVariable("N", 10);
  294. FileCheckExpression LineExpression = FileCheckExpression(doAdd, &LineVar, 0);
  295. FileCheckExpression NExpression = FileCheckExpression(doAdd, &NVar, 3);
  296. FileCheckNumericSubstitution SubstitutionLine =
  297. FileCheckNumericSubstitution(&Context, "@LINE", &LineExpression, 12);
  298. FileCheckNumericSubstitution SubstitutionN =
  299. FileCheckNumericSubstitution(&Context, "N", &NExpression, 30);
  300. Expected<std::string> Value = SubstitutionLine.getResult();
  301. EXPECT_TRUE(static_cast<bool>(Value));
  302. EXPECT_EQ("42", *Value);
  303. Value = SubstitutionN.getResult();
  304. EXPECT_TRUE(static_cast<bool>(Value));
  305. EXPECT_EQ("13", *Value);
  306. // Substitution of an undefined numeric variable fails.
  307. LineVar.clearValue();
  308. SubstValue = SubstitutionLine.getResult().takeError();
  309. EXPECT_FALSE(static_cast<bool>(SubstValue));
  310. expectUndefError("@LINE", SubstValue.takeError());
  311. NVar.clearValue();
  312. SubstValue = SubstitutionN.getResult().takeError();
  313. EXPECT_FALSE(static_cast<bool>(SubstValue));
  314. expectUndefError("N", SubstValue.takeError());
  315. // Substitution of a defined string variable returns the right value.
  316. FileCheckPattern P = FileCheckPattern(Check::CheckPlain, &Context, 1);
  317. StringSubstitution = FileCheckStringSubstitution(&Context, "FOO", 42);
  318. Value = StringSubstitution.getResult();
  319. EXPECT_TRUE(static_cast<bool>(Value));
  320. EXPECT_EQ("BAR", *Value);
  321. }
  322. TEST_F(FileCheckTest, FileCheckContext) {
  323. FileCheckPatternContext Cxt = FileCheckPatternContext();
  324. std::vector<std::string> GlobalDefines;
  325. SourceMgr SM;
  326. // Missing equal sign.
  327. GlobalDefines.emplace_back(std::string("LocalVar"));
  328. EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
  329. GlobalDefines.clear();
  330. GlobalDefines.emplace_back(std::string("#LocalNumVar"));
  331. EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
  332. // Empty variable name.
  333. GlobalDefines.clear();
  334. GlobalDefines.emplace_back(std::string("=18"));
  335. EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
  336. GlobalDefines.clear();
  337. GlobalDefines.emplace_back(std::string("#=18"));
  338. EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
  339. // Invalid variable name.
  340. GlobalDefines.clear();
  341. GlobalDefines.emplace_back(std::string("18LocalVar=18"));
  342. EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
  343. GlobalDefines.clear();
  344. GlobalDefines.emplace_back(std::string("#18LocalNumVar=18"));
  345. EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
  346. // Name conflict between pattern and numeric variable.
  347. GlobalDefines.clear();
  348. GlobalDefines.emplace_back(std::string("LocalVar=18"));
  349. GlobalDefines.emplace_back(std::string("#LocalVar=36"));
  350. EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
  351. Cxt = FileCheckPatternContext();
  352. GlobalDefines.clear();
  353. GlobalDefines.emplace_back(std::string("#LocalNumVar=18"));
  354. GlobalDefines.emplace_back(std::string("LocalNumVar=36"));
  355. EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
  356. Cxt = FileCheckPatternContext();
  357. // Invalid numeric value for numeric variable.
  358. GlobalDefines.clear();
  359. GlobalDefines.emplace_back(std::string("#LocalNumVar=x"));
  360. EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
  361. // Define local variables from command-line.
  362. GlobalDefines.clear();
  363. GlobalDefines.emplace_back(std::string("LocalVar=FOO"));
  364. GlobalDefines.emplace_back(std::string("EmptyVar="));
  365. GlobalDefines.emplace_back(std::string("#LocalNumVar=18"));
  366. EXPECT_FALSE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
  367. // Check defined variables are present and undefined is absent.
  368. StringRef LocalVarStr = "LocalVar";
  369. StringRef LocalNumVarRef = bufferize(SM, "LocalNumVar");
  370. StringRef EmptyVarStr = "EmptyVar";
  371. StringRef UnknownVarStr = "UnknownVar";
  372. Expected<StringRef> LocalVar = Cxt.getPatternVarValue(LocalVarStr);
  373. FileCheckPattern P = FileCheckPattern(Check::CheckPlain, &Cxt, 1);
  374. Optional<FileCheckNumericVariable *> DefinedNumericVariable;
  375. Expected<FileCheckExpression *> Expression = P.parseNumericSubstitutionBlock(
  376. LocalNumVarRef, DefinedNumericVariable, SM);
  377. Expected<StringRef> EmptyVar = Cxt.getPatternVarValue(EmptyVarStr);
  378. Expected<StringRef> UnknownVar = Cxt.getPatternVarValue(UnknownVarStr);
  379. EXPECT_TRUE(static_cast<bool>(LocalVar));
  380. EXPECT_EQ(*LocalVar, "FOO");
  381. EXPECT_TRUE(static_cast<bool>(Expression));
  382. Expected<uint64_t> ExpressionVal = (*Expression)->eval();
  383. EXPECT_TRUE(static_cast<bool>(ExpressionVal));
  384. EXPECT_EQ(*ExpressionVal, 18U);
  385. EXPECT_TRUE(static_cast<bool>(EmptyVar));
  386. EXPECT_EQ(*EmptyVar, "");
  387. EXPECT_TRUE(errorToBool(UnknownVar.takeError()));
  388. // Clear local variables and check they become absent.
  389. Cxt.clearLocalVars();
  390. LocalVar = Cxt.getPatternVarValue(LocalVarStr);
  391. EXPECT_TRUE(errorToBool(LocalVar.takeError()));
  392. // Check a numeric expression's evaluation fails if called after clearing of
  393. // local variables, if it was created before. This is important because local
  394. // variable clearing due to --enable-var-scope happens after numeric
  395. // expressions are linked to the numeric variables they use.
  396. EXPECT_TRUE(errorToBool((*Expression)->eval().takeError()));
  397. P = FileCheckPattern(Check::CheckPlain, &Cxt, 2);
  398. Expression = P.parseNumericSubstitutionBlock(LocalNumVarRef,
  399. DefinedNumericVariable, SM);
  400. EXPECT_TRUE(bool(Expression));
  401. ExpressionVal = (*Expression)->eval();
  402. EXPECT_TRUE(errorToBool(ExpressionVal.takeError()));
  403. EmptyVar = Cxt.getPatternVarValue(EmptyVarStr);
  404. EXPECT_TRUE(errorToBool(EmptyVar.takeError()));
  405. // Clear again because parseNumericSubstitutionBlock would have created a
  406. // dummy variable and stored it in GlobalNumericVariableTable.
  407. Cxt.clearLocalVars();
  408. // Redefine global variables and check variables are defined again.
  409. GlobalDefines.emplace_back(std::string("$GlobalVar=BAR"));
  410. GlobalDefines.emplace_back(std::string("#$GlobalNumVar=36"));
  411. EXPECT_FALSE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
  412. StringRef GlobalVarStr = "$GlobalVar";
  413. StringRef GlobalNumVarRef = bufferize(SM, "$GlobalNumVar");
  414. Expected<StringRef> GlobalVar = Cxt.getPatternVarValue(GlobalVarStr);
  415. EXPECT_TRUE(static_cast<bool>(GlobalVar));
  416. EXPECT_EQ(*GlobalVar, "BAR");
  417. P = FileCheckPattern(Check::CheckPlain, &Cxt, 3);
  418. Expression = P.parseNumericSubstitutionBlock(GlobalNumVarRef,
  419. DefinedNumericVariable, SM);
  420. EXPECT_TRUE(static_cast<bool>(Expression));
  421. ExpressionVal = (*Expression)->eval();
  422. EXPECT_TRUE(static_cast<bool>(ExpressionVal));
  423. EXPECT_EQ(*ExpressionVal, 36U);
  424. // Clear local variables and check global variables remain defined.
  425. Cxt.clearLocalVars();
  426. EXPECT_FALSE(errorToBool(Cxt.getPatternVarValue(GlobalVarStr).takeError()));
  427. P = FileCheckPattern(Check::CheckPlain, &Cxt, 4);
  428. Expression = P.parseNumericSubstitutionBlock(GlobalNumVarRef,
  429. DefinedNumericVariable, SM);
  430. EXPECT_TRUE(static_cast<bool>(Expression));
  431. ExpressionVal = (*Expression)->eval();
  432. EXPECT_TRUE(static_cast<bool>(ExpressionVal));
  433. EXPECT_EQ(*ExpressionVal, 36U);
  434. }
  435. } // namespace