FileCheckTest.cpp 23 KB

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