FileCheckTest.cpp 25 KB

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