FileCheckTest.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  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. #include <unordered_set>
  11. using namespace llvm;
  12. namespace {
  13. class FileCheckTest : public ::testing::Test {};
  14. TEST_F(FileCheckTest, Literal) {
  15. // Eval returns the literal's value.
  16. FileCheckExpressionLiteral Ten(10);
  17. Expected<uint64_t> Value = Ten.eval();
  18. ASSERT_TRUE(bool(Value));
  19. EXPECT_EQ(10U, *Value);
  20. // Max value can be correctly represented.
  21. FileCheckExpressionLiteral Max(std::numeric_limits<uint64_t>::max());
  22. Value = Max.eval();
  23. ASSERT_TRUE(bool(Value));
  24. EXPECT_EQ(std::numeric_limits<uint64_t>::max(), *Value);
  25. }
  26. static std::string toString(const std::unordered_set<std::string> &Set) {
  27. bool First = true;
  28. std::string Str;
  29. for (StringRef S : Set) {
  30. Str += Twine(First ? "{" + S : ", " + S).str();
  31. First = false;
  32. }
  33. Str += '}';
  34. return Str;
  35. }
  36. static void
  37. expectUndefErrors(std::unordered_set<std::string> ExpectedUndefVarNames,
  38. Error Err) {
  39. handleAllErrors(std::move(Err), [&](const FileCheckUndefVarError &E) {
  40. ExpectedUndefVarNames.erase(E.getVarName());
  41. });
  42. EXPECT_TRUE(ExpectedUndefVarNames.empty()) << toString(ExpectedUndefVarNames);
  43. }
  44. // Return whether Err contains any FileCheckUndefVarError whose associated name
  45. // is not ExpectedUndefVarName.
  46. static void expectUndefError(const Twine &ExpectedUndefVarName, Error Err) {
  47. expectUndefErrors({ExpectedUndefVarName.str()}, std::move(Err));
  48. }
  49. uint64_t doAdd(uint64_t OpL, uint64_t OpR) { return OpL + OpR; }
  50. TEST_F(FileCheckTest, NumericVariable) {
  51. // Undefined variable: getValue and eval fail, error returned by eval holds
  52. // the name of the undefined variable.
  53. FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO", 1);
  54. EXPECT_EQ("FOO", FooVar.getName());
  55. FileCheckNumericVariableUse FooVarUse =
  56. FileCheckNumericVariableUse("FOO", &FooVar);
  57. EXPECT_FALSE(FooVar.getValue());
  58. Expected<uint64_t> EvalResult = FooVarUse.eval();
  59. ASSERT_FALSE(EvalResult);
  60. expectUndefError("FOO", EvalResult.takeError());
  61. FooVar.setValue(42);
  62. // Defined variable: getValue and eval return value set.
  63. Optional<uint64_t> Value = FooVar.getValue();
  64. ASSERT_TRUE(bool(Value));
  65. EXPECT_EQ(42U, *Value);
  66. EvalResult = FooVarUse.eval();
  67. ASSERT_TRUE(bool(EvalResult));
  68. EXPECT_EQ(42U, *EvalResult);
  69. // Clearing variable: getValue and eval fail. Error returned by eval holds
  70. // the name of the cleared variable.
  71. FooVar.clearValue();
  72. EXPECT_FALSE(FooVar.getValue());
  73. EvalResult = FooVarUse.eval();
  74. ASSERT_FALSE(EvalResult);
  75. expectUndefError("FOO", EvalResult.takeError());
  76. }
  77. TEST_F(FileCheckTest, Binop) {
  78. FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO", 1);
  79. FooVar.setValue(42);
  80. std::unique_ptr<FileCheckNumericVariableUse> FooVarUse =
  81. std::make_unique<FileCheckNumericVariableUse>("FOO", &FooVar);
  82. FileCheckNumericVariable BarVar = FileCheckNumericVariable("BAR", 2);
  83. BarVar.setValue(18);
  84. std::unique_ptr<FileCheckNumericVariableUse> BarVarUse =
  85. std::make_unique<FileCheckNumericVariableUse>("BAR", &BarVar);
  86. FileCheckASTBinop Binop =
  87. FileCheckASTBinop(doAdd, std::move(FooVarUse), std::move(BarVarUse));
  88. // Defined variable: eval returns right value.
  89. Expected<uint64_t> Value = Binop.eval();
  90. ASSERT_TRUE(bool(Value));
  91. EXPECT_EQ(60U, *Value);
  92. // 1 undefined variable: eval fails, error contains name of undefined
  93. // variable.
  94. FooVar.clearValue();
  95. Value = Binop.eval();
  96. ASSERT_FALSE(Value);
  97. expectUndefError("FOO", Value.takeError());
  98. // 2 undefined variables: eval fails, error contains names of all undefined
  99. // variables.
  100. BarVar.clearValue();
  101. Value = Binop.eval();
  102. ASSERT_FALSE(Value);
  103. expectUndefErrors({"FOO", "BAR"}, Value.takeError());
  104. }
  105. TEST_F(FileCheckTest, ValidVarNameStart) {
  106. EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('a'));
  107. EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('G'));
  108. EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('_'));
  109. EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('2'));
  110. EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('$'));
  111. EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('@'));
  112. EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('+'));
  113. EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('-'));
  114. EXPECT_FALSE(FileCheckPattern::isValidVarNameStart(':'));
  115. }
  116. static StringRef bufferize(SourceMgr &SM, StringRef Str) {
  117. std::unique_ptr<MemoryBuffer> Buffer =
  118. MemoryBuffer::getMemBufferCopy(Str, "TestBuffer");
  119. StringRef StrBufferRef = Buffer->getBuffer();
  120. SM.AddNewSourceBuffer(std::move(Buffer), SMLoc());
  121. return StrBufferRef;
  122. }
  123. TEST_F(FileCheckTest, ParseVar) {
  124. SourceMgr SM;
  125. StringRef OrigVarName = bufferize(SM, "GoodVar42");
  126. StringRef VarName = OrigVarName;
  127. Expected<FileCheckPattern::VariableProperties> ParsedVarResult =
  128. FileCheckPattern::parseVariable(VarName, SM);
  129. ASSERT_TRUE(bool(ParsedVarResult));
  130. EXPECT_EQ(ParsedVarResult->Name, OrigVarName);
  131. EXPECT_TRUE(VarName.empty());
  132. EXPECT_FALSE(ParsedVarResult->IsPseudo);
  133. VarName = OrigVarName = bufferize(SM, "$GoodGlobalVar");
  134. ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM);
  135. ASSERT_TRUE(bool(ParsedVarResult));
  136. EXPECT_EQ(ParsedVarResult->Name, OrigVarName);
  137. EXPECT_TRUE(VarName.empty());
  138. EXPECT_FALSE(ParsedVarResult->IsPseudo);
  139. VarName = OrigVarName = bufferize(SM, "@GoodPseudoVar");
  140. ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM);
  141. ASSERT_TRUE(bool(ParsedVarResult));
  142. EXPECT_EQ(ParsedVarResult->Name, OrigVarName);
  143. EXPECT_TRUE(VarName.empty());
  144. EXPECT_TRUE(ParsedVarResult->IsPseudo);
  145. VarName = bufferize(SM, "42BadVar");
  146. ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM);
  147. EXPECT_TRUE(errorToBool(ParsedVarResult.takeError()));
  148. VarName = bufferize(SM, "$@");
  149. ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM);
  150. EXPECT_TRUE(errorToBool(ParsedVarResult.takeError()));
  151. VarName = OrigVarName = bufferize(SM, "B@dVar");
  152. ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM);
  153. ASSERT_TRUE(bool(ParsedVarResult));
  154. EXPECT_EQ(VarName, OrigVarName.substr(1));
  155. EXPECT_EQ(ParsedVarResult->Name, "B");
  156. EXPECT_FALSE(ParsedVarResult->IsPseudo);
  157. VarName = OrigVarName = bufferize(SM, "B$dVar");
  158. ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM);
  159. ASSERT_TRUE(bool(ParsedVarResult));
  160. EXPECT_EQ(VarName, OrigVarName.substr(1));
  161. EXPECT_EQ(ParsedVarResult->Name, "B");
  162. EXPECT_FALSE(ParsedVarResult->IsPseudo);
  163. VarName = bufferize(SM, "BadVar+");
  164. ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM);
  165. ASSERT_TRUE(bool(ParsedVarResult));
  166. EXPECT_EQ(VarName, "+");
  167. EXPECT_EQ(ParsedVarResult->Name, "BadVar");
  168. EXPECT_FALSE(ParsedVarResult->IsPseudo);
  169. VarName = bufferize(SM, "BadVar-");
  170. ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM);
  171. ASSERT_TRUE(bool(ParsedVarResult));
  172. EXPECT_EQ(VarName, "-");
  173. EXPECT_EQ(ParsedVarResult->Name, "BadVar");
  174. EXPECT_FALSE(ParsedVarResult->IsPseudo);
  175. VarName = bufferize(SM, "BadVar:");
  176. ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM);
  177. ASSERT_TRUE(bool(ParsedVarResult));
  178. EXPECT_EQ(VarName, ":");
  179. EXPECT_EQ(ParsedVarResult->Name, "BadVar");
  180. EXPECT_FALSE(ParsedVarResult->IsPseudo);
  181. }
  182. class PatternTester {
  183. private:
  184. size_t LineNumber = 1;
  185. SourceMgr SM;
  186. FileCheckRequest Req;
  187. FileCheckPatternContext Context;
  188. FileCheckPattern P =
  189. FileCheckPattern(Check::CheckPlain, &Context, LineNumber++);
  190. public:
  191. PatternTester() {
  192. std::vector<std::string> GlobalDefines;
  193. GlobalDefines.emplace_back(std::string("#FOO=42"));
  194. GlobalDefines.emplace_back(std::string("BAR=BAZ"));
  195. // An ASSERT_FALSE would make more sense but cannot be used in a
  196. // constructor.
  197. EXPECT_FALSE(
  198. errorToBool(Context.defineCmdlineVariables(GlobalDefines, SM)));
  199. Context.createLineVariable();
  200. // Call parsePattern to have @LINE defined.
  201. P.parsePattern("N/A", "CHECK", SM, Req);
  202. // parsePattern does not expect to be called twice for the same line and
  203. // will set FixedStr and RegExStr incorrectly if it is. Therefore prepare
  204. // a pattern for a different line.
  205. initNextPattern();
  206. }
  207. void initNextPattern() {
  208. P = FileCheckPattern(Check::CheckPlain, &Context, LineNumber++);
  209. }
  210. bool parseSubstExpect(StringRef Expr) {
  211. StringRef ExprBufferRef = bufferize(SM, Expr);
  212. Optional<FileCheckNumericVariable *> DefinedNumericVariable;
  213. return errorToBool(
  214. P.parseNumericSubstitutionBlock(ExprBufferRef, DefinedNumericVariable,
  215. false, LineNumber - 1, &Context, SM)
  216. .takeError());
  217. }
  218. bool parsePatternExpect(StringRef Pattern) {
  219. StringRef PatBufferRef = bufferize(SM, Pattern);
  220. return P.parsePattern(PatBufferRef, "CHECK", SM, Req);
  221. }
  222. bool matchExpect(StringRef Buffer) {
  223. StringRef BufferRef = bufferize(SM, Buffer);
  224. size_t MatchLen;
  225. return errorToBool(P.match(BufferRef, MatchLen, SM).takeError());
  226. }
  227. };
  228. TEST_F(FileCheckTest, ParseExpr) {
  229. PatternTester Tester;
  230. // Variable definition.
  231. // Definition of invalid variable.
  232. EXPECT_TRUE(Tester.parseSubstExpect("10VAR:"));
  233. EXPECT_TRUE(Tester.parseSubstExpect("@FOO:"));
  234. EXPECT_TRUE(Tester.parseSubstExpect("@LINE:"));
  235. // Conflict with pattern variable.
  236. EXPECT_TRUE(Tester.parseSubstExpect("BAR:"));
  237. // Garbage after name of variable being defined.
  238. EXPECT_TRUE(Tester.parseSubstExpect("VAR GARBAGE:"));
  239. // Acceptable variable definition.
  240. EXPECT_FALSE(Tester.parseSubstExpect("VAR1:"));
  241. EXPECT_FALSE(Tester.parseSubstExpect(" VAR2:"));
  242. EXPECT_FALSE(Tester.parseSubstExpect("VAR3 :"));
  243. EXPECT_FALSE(Tester.parseSubstExpect("VAR3: "));
  244. EXPECT_FALSE(Tester.parsePatternExpect("[[#FOOBAR: FOO+1]]"));
  245. // Numeric expression.
  246. // Unacceptable variable.
  247. EXPECT_TRUE(Tester.parseSubstExpect("10VAR"));
  248. EXPECT_TRUE(Tester.parseSubstExpect("@FOO"));
  249. // Only valid variable.
  250. EXPECT_FALSE(Tester.parseSubstExpect("@LINE"));
  251. EXPECT_FALSE(Tester.parseSubstExpect("FOO"));
  252. EXPECT_FALSE(Tester.parseSubstExpect("UNDEF"));
  253. // Valid empty expression.
  254. EXPECT_FALSE(Tester.parseSubstExpect(""));
  255. // Invalid use of variable defined on the same line from expression. Note
  256. // that the same pattern object is used for the parsePatternExpect and
  257. // parseSubstExpect since no initNextPattern is called, thus appearing as
  258. // being on the same line from the pattern's point of view.
  259. ASSERT_FALSE(Tester.parsePatternExpect("[[#LINE1VAR:FOO+1]]"));
  260. EXPECT_TRUE(Tester.parseSubstExpect("LINE1VAR"));
  261. // Invalid use of variable defined on same line from input. As above, the
  262. // absence of a call to initNextPattern makes it appear to be on the same
  263. // line from the pattern's point of view.
  264. ASSERT_FALSE(Tester.parsePatternExpect("[[#LINE2VAR:]]"));
  265. EXPECT_TRUE(Tester.parseSubstExpect("LINE2VAR"));
  266. // Unsupported operator.
  267. EXPECT_TRUE(Tester.parseSubstExpect("@LINE/2"));
  268. // Missing offset operand.
  269. EXPECT_TRUE(Tester.parseSubstExpect("@LINE+"));
  270. // Valid expression.
  271. EXPECT_FALSE(Tester.parseSubstExpect("@LINE+5"));
  272. EXPECT_FALSE(Tester.parseSubstExpect("FOO+4"));
  273. Tester.initNextPattern();
  274. EXPECT_FALSE(Tester.parseSubstExpect("FOOBAR"));
  275. EXPECT_FALSE(Tester.parseSubstExpect("LINE1VAR"));
  276. EXPECT_FALSE(Tester.parsePatternExpect("[[#FOO+FOO]]"));
  277. EXPECT_FALSE(Tester.parsePatternExpect("[[#FOO+3-FOO]]"));
  278. }
  279. TEST_F(FileCheckTest, ParsePattern) {
  280. PatternTester Tester;
  281. // Space in pattern variable expression.
  282. EXPECT_TRUE(Tester.parsePatternExpect("[[ BAR]]"));
  283. // Invalid variable name.
  284. EXPECT_TRUE(Tester.parsePatternExpect("[[42INVALID]]"));
  285. // Invalid pattern variable definition.
  286. EXPECT_TRUE(Tester.parsePatternExpect("[[@PAT:]]"));
  287. EXPECT_TRUE(Tester.parsePatternExpect("[[PAT+2:]]"));
  288. // Collision with numeric variable.
  289. EXPECT_TRUE(Tester.parsePatternExpect("[[FOO:]]"));
  290. // Valid use of pattern variable.
  291. EXPECT_FALSE(Tester.parsePatternExpect("[[BAR]]"));
  292. // Valid pattern variable definition.
  293. EXPECT_FALSE(Tester.parsePatternExpect("[[PAT:[0-9]+]]"));
  294. // Invalid numeric expressions.
  295. EXPECT_TRUE(Tester.parsePatternExpect("[[#42INVALID]]"));
  296. EXPECT_TRUE(Tester.parsePatternExpect("[[#@FOO]]"));
  297. EXPECT_TRUE(Tester.parsePatternExpect("[[#@LINE/2]]"));
  298. // Valid numeric expressions and numeric variable definition.
  299. EXPECT_FALSE(Tester.parsePatternExpect("[[#FOO]]"));
  300. EXPECT_FALSE(Tester.parsePatternExpect("[[#@LINE+2]]"));
  301. EXPECT_FALSE(Tester.parsePatternExpect("[[#NUMVAR:]]"));
  302. }
  303. TEST_F(FileCheckTest, Match) {
  304. PatternTester Tester;
  305. // Check matching an empty expression only matches a number.
  306. Tester.parsePatternExpect("[[#]]");
  307. EXPECT_TRUE(Tester.matchExpect("FAIL"));
  308. EXPECT_FALSE(Tester.matchExpect("18"));
  309. // Check matching a definition only matches a number.
  310. Tester.initNextPattern();
  311. Tester.parsePatternExpect("[[#NUMVAR:]]");
  312. EXPECT_TRUE(Tester.matchExpect("FAIL"));
  313. EXPECT_TRUE(Tester.matchExpect(""));
  314. EXPECT_FALSE(Tester.matchExpect("18"));
  315. // Check matching the variable defined matches the correct number only
  316. Tester.initNextPattern();
  317. Tester.parsePatternExpect("[[#NUMVAR]] [[#NUMVAR+2]]");
  318. EXPECT_TRUE(Tester.matchExpect("19 21"));
  319. EXPECT_TRUE(Tester.matchExpect("18 21"));
  320. EXPECT_FALSE(Tester.matchExpect("18 20"));
  321. // Check matching a numeric expression using @LINE after match failure uses
  322. // the correct value for @LINE.
  323. Tester.initNextPattern();
  324. EXPECT_FALSE(Tester.parsePatternExpect("[[#@LINE]]"));
  325. // Ok, @LINE is 5 now.
  326. EXPECT_FALSE(Tester.matchExpect("5"));
  327. Tester.initNextPattern();
  328. // @LINE is now 6, match with substitution failure.
  329. EXPECT_FALSE(Tester.parsePatternExpect("[[#UNKNOWN]]"));
  330. EXPECT_TRUE(Tester.matchExpect("FOO"));
  331. Tester.initNextPattern();
  332. // Check that @LINE is 7 as expected.
  333. EXPECT_FALSE(Tester.parsePatternExpect("[[#@LINE]]"));
  334. EXPECT_FALSE(Tester.matchExpect("7"));
  335. }
  336. TEST_F(FileCheckTest, Substitution) {
  337. SourceMgr SM;
  338. FileCheckPatternContext Context;
  339. std::vector<std::string> GlobalDefines;
  340. GlobalDefines.emplace_back(std::string("FOO=BAR"));
  341. EXPECT_FALSE(errorToBool(Context.defineCmdlineVariables(GlobalDefines, SM)));
  342. // Substitution of an undefined string variable fails and error holds that
  343. // variable's name.
  344. FileCheckStringSubstitution StringSubstitution =
  345. FileCheckStringSubstitution(&Context, "VAR404", 42);
  346. Expected<std::string> SubstValue = StringSubstitution.getResult();
  347. ASSERT_FALSE(bool(SubstValue));
  348. expectUndefError("VAR404", SubstValue.takeError());
  349. // Substitutions of defined pseudo and non-pseudo numeric variables return
  350. // the right value.
  351. FileCheckNumericVariable LineVar = FileCheckNumericVariable("@LINE", 1);
  352. FileCheckNumericVariable NVar = FileCheckNumericVariable("N", 1);
  353. LineVar.setValue(42);
  354. NVar.setValue(10);
  355. auto LineVarUse =
  356. std::make_unique<FileCheckNumericVariableUse>("@LINE", &LineVar);
  357. auto NVarUse = std::make_unique<FileCheckNumericVariableUse>("N", &NVar);
  358. FileCheckNumericSubstitution SubstitutionLine = FileCheckNumericSubstitution(
  359. &Context, "@LINE", std::move(LineVarUse), 12);
  360. FileCheckNumericSubstitution SubstitutionN =
  361. FileCheckNumericSubstitution(&Context, "N", std::move(NVarUse), 30);
  362. SubstValue = SubstitutionLine.getResult();
  363. ASSERT_TRUE(bool(SubstValue));
  364. EXPECT_EQ("42", *SubstValue);
  365. SubstValue = SubstitutionN.getResult();
  366. ASSERT_TRUE(bool(SubstValue));
  367. EXPECT_EQ("10", *SubstValue);
  368. // Substitution of an undefined numeric variable fails, error holds name of
  369. // undefined variable.
  370. LineVar.clearValue();
  371. SubstValue = SubstitutionLine.getResult();
  372. ASSERT_FALSE(bool(SubstValue));
  373. expectUndefError("@LINE", SubstValue.takeError());
  374. NVar.clearValue();
  375. SubstValue = SubstitutionN.getResult();
  376. ASSERT_FALSE(bool(SubstValue));
  377. expectUndefError("N", SubstValue.takeError());
  378. // Substitution of a defined string variable returns the right value.
  379. FileCheckPattern P = FileCheckPattern(Check::CheckPlain, &Context, 1);
  380. StringSubstitution = FileCheckStringSubstitution(&Context, "FOO", 42);
  381. SubstValue = StringSubstitution.getResult();
  382. ASSERT_TRUE(bool(SubstValue));
  383. EXPECT_EQ("BAR", *SubstValue);
  384. }
  385. TEST_F(FileCheckTest, FileCheckContext) {
  386. FileCheckPatternContext Cxt = FileCheckPatternContext();
  387. std::vector<std::string> GlobalDefines;
  388. SourceMgr SM;
  389. // Missing equal sign.
  390. GlobalDefines.emplace_back(std::string("LocalVar"));
  391. EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
  392. GlobalDefines.clear();
  393. GlobalDefines.emplace_back(std::string("#LocalNumVar"));
  394. EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
  395. // Empty variable name.
  396. GlobalDefines.clear();
  397. GlobalDefines.emplace_back(std::string("=18"));
  398. EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
  399. GlobalDefines.clear();
  400. GlobalDefines.emplace_back(std::string("#=18"));
  401. EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
  402. // Invalid variable name.
  403. GlobalDefines.clear();
  404. GlobalDefines.emplace_back(std::string("18LocalVar=18"));
  405. EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
  406. GlobalDefines.clear();
  407. GlobalDefines.emplace_back(std::string("#18LocalNumVar=18"));
  408. EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
  409. // Name conflict between pattern and numeric variable.
  410. GlobalDefines.clear();
  411. GlobalDefines.emplace_back(std::string("LocalVar=18"));
  412. GlobalDefines.emplace_back(std::string("#LocalVar=36"));
  413. EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
  414. Cxt = FileCheckPatternContext();
  415. GlobalDefines.clear();
  416. GlobalDefines.emplace_back(std::string("#LocalNumVar=18"));
  417. GlobalDefines.emplace_back(std::string("LocalNumVar=36"));
  418. EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
  419. Cxt = FileCheckPatternContext();
  420. // Invalid numeric value for numeric variable.
  421. GlobalDefines.clear();
  422. GlobalDefines.emplace_back(std::string("#LocalNumVar=x"));
  423. EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
  424. // Define local variables from command-line.
  425. GlobalDefines.clear();
  426. // Clear local variables to remove dummy numeric variable x that
  427. // parseNumericSubstitutionBlock would have created and stored in
  428. // GlobalNumericVariableTable.
  429. Cxt.clearLocalVars();
  430. GlobalDefines.emplace_back(std::string("LocalVar=FOO"));
  431. GlobalDefines.emplace_back(std::string("EmptyVar="));
  432. GlobalDefines.emplace_back(std::string("#LocalNumVar1=18"));
  433. GlobalDefines.emplace_back(std::string("#LocalNumVar2=LocalNumVar1+2"));
  434. ASSERT_FALSE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
  435. // Check defined variables are present and undefined is absent.
  436. StringRef LocalVarStr = "LocalVar";
  437. StringRef LocalNumVar1Ref = bufferize(SM, "LocalNumVar1");
  438. StringRef LocalNumVar2Ref = bufferize(SM, "LocalNumVar2");
  439. StringRef EmptyVarStr = "EmptyVar";
  440. StringRef UnknownVarStr = "UnknownVar";
  441. Expected<StringRef> LocalVar = Cxt.getPatternVarValue(LocalVarStr);
  442. FileCheckPattern P = FileCheckPattern(Check::CheckPlain, &Cxt, 1);
  443. Optional<FileCheckNumericVariable *> DefinedNumericVariable;
  444. Expected<std::unique_ptr<FileCheckExpressionAST>> ExpressionAST =
  445. P.parseNumericSubstitutionBlock(LocalNumVar1Ref, DefinedNumericVariable,
  446. /*IsLegacyLineExpr=*/false,
  447. /*LineNumber=*/1, &Cxt, SM);
  448. ASSERT_TRUE(bool(LocalVar));
  449. EXPECT_EQ(*LocalVar, "FOO");
  450. Expected<StringRef> EmptyVar = Cxt.getPatternVarValue(EmptyVarStr);
  451. Expected<StringRef> UnknownVar = Cxt.getPatternVarValue(UnknownVarStr);
  452. ASSERT_TRUE(bool(ExpressionAST));
  453. Expected<uint64_t> ExpressionVal = (*ExpressionAST)->eval();
  454. ASSERT_TRUE(bool(ExpressionVal));
  455. EXPECT_EQ(*ExpressionVal, 18U);
  456. ExpressionAST =
  457. P.parseNumericSubstitutionBlock(LocalNumVar2Ref, DefinedNumericVariable,
  458. /*IsLegacyLineExpr=*/false,
  459. /*LineNumber=*/1, &Cxt, SM);
  460. ASSERT_TRUE(bool(ExpressionAST));
  461. ExpressionVal = (*ExpressionAST)->eval();
  462. ASSERT_TRUE(bool(ExpressionVal));
  463. EXPECT_EQ(*ExpressionVal, 20U);
  464. ASSERT_TRUE(bool(EmptyVar));
  465. EXPECT_EQ(*EmptyVar, "");
  466. EXPECT_TRUE(errorToBool(UnknownVar.takeError()));
  467. // Clear local variables and check they become absent.
  468. Cxt.clearLocalVars();
  469. LocalVar = Cxt.getPatternVarValue(LocalVarStr);
  470. EXPECT_TRUE(errorToBool(LocalVar.takeError()));
  471. // Check a numeric expression's evaluation fails if called after clearing of
  472. // local variables, if it was created before. This is important because local
  473. // variable clearing due to --enable-var-scope happens after numeric
  474. // expressions are linked to the numeric variables they use.
  475. EXPECT_TRUE(errorToBool((*ExpressionAST)->eval().takeError()));
  476. P = FileCheckPattern(Check::CheckPlain, &Cxt, 2);
  477. ExpressionAST = P.parseNumericSubstitutionBlock(
  478. LocalNumVar1Ref, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
  479. /*LineNumber=*/2, &Cxt, SM);
  480. ASSERT_TRUE(bool(ExpressionAST));
  481. ExpressionVal = (*ExpressionAST)->eval();
  482. EXPECT_TRUE(errorToBool(ExpressionVal.takeError()));
  483. ExpressionAST = P.parseNumericSubstitutionBlock(
  484. LocalNumVar2Ref, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
  485. /*LineNumber=*/2, &Cxt, SM);
  486. ASSERT_TRUE(bool(ExpressionAST));
  487. ExpressionVal = (*ExpressionAST)->eval();
  488. EXPECT_TRUE(errorToBool(ExpressionVal.takeError()));
  489. EmptyVar = Cxt.getPatternVarValue(EmptyVarStr);
  490. EXPECT_TRUE(errorToBool(EmptyVar.takeError()));
  491. // Clear again because parseNumericSubstitutionBlock would have created a
  492. // dummy variable and stored it in GlobalNumericVariableTable.
  493. Cxt.clearLocalVars();
  494. // Redefine global variables and check variables are defined again.
  495. GlobalDefines.emplace_back(std::string("$GlobalVar=BAR"));
  496. GlobalDefines.emplace_back(std::string("#$GlobalNumVar=36"));
  497. ASSERT_FALSE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
  498. StringRef GlobalVarStr = "$GlobalVar";
  499. StringRef GlobalNumVarRef = bufferize(SM, "$GlobalNumVar");
  500. Expected<StringRef> GlobalVar = Cxt.getPatternVarValue(GlobalVarStr);
  501. ASSERT_TRUE(bool(GlobalVar));
  502. EXPECT_EQ(*GlobalVar, "BAR");
  503. P = FileCheckPattern(Check::CheckPlain, &Cxt, 3);
  504. ExpressionAST = P.parseNumericSubstitutionBlock(
  505. GlobalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
  506. /*LineNumber=*/3, &Cxt, SM);
  507. ASSERT_TRUE(bool(ExpressionAST));
  508. ExpressionVal = (*ExpressionAST)->eval();
  509. ASSERT_TRUE(bool(ExpressionVal));
  510. EXPECT_EQ(*ExpressionVal, 36U);
  511. // Clear local variables and check global variables remain defined.
  512. Cxt.clearLocalVars();
  513. EXPECT_FALSE(errorToBool(Cxt.getPatternVarValue(GlobalVarStr).takeError()));
  514. P = FileCheckPattern(Check::CheckPlain, &Cxt, 4);
  515. ExpressionAST = P.parseNumericSubstitutionBlock(
  516. GlobalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
  517. /*LineNumber=*/4, &Cxt, SM);
  518. ASSERT_TRUE(bool(ExpressionAST));
  519. ExpressionVal = (*ExpressionAST)->eval();
  520. ASSERT_TRUE(bool(ExpressionVal));
  521. EXPECT_EQ(*ExpressionVal, 36U);
  522. }
  523. } // namespace