FileCheck.cpp 63 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745
  1. //===- FileCheck.cpp - Check that File's Contents match what is expected --===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // FileCheck does a line-by line check of a file that validates whether it
  10. // contains the expected content. This is useful for regression tests etc.
  11. //
  12. // This file implements most of the API that will be used by the FileCheck utility
  13. // as well as various unittests.
  14. //===----------------------------------------------------------------------===//
  15. #include "llvm/Support/FileCheck.h"
  16. #include "llvm/ADT/StringSet.h"
  17. #include "llvm/Support/FormatVariadic.h"
  18. #include <cstdint>
  19. #include <list>
  20. #include <map>
  21. #include <tuple>
  22. #include <utility>
  23. using namespace llvm;
  24. bool FileCheckNumericVariable::setValue(uint64_t NewValue) {
  25. if (Value)
  26. return true;
  27. Value = NewValue;
  28. return false;
  29. }
  30. bool FileCheckNumericVariable::clearValue() {
  31. if (!Value)
  32. return true;
  33. Value = llvm::None;
  34. return false;
  35. }
  36. llvm::Optional<uint64_t> FileCheckNumExpr::eval() const {
  37. llvm::Optional<uint64_t> LeftOp = this->LeftOp->getValue();
  38. // Variable is undefined.
  39. if (!LeftOp)
  40. return llvm::None;
  41. return EvalBinop(*LeftOp, RightOp);
  42. }
  43. StringRef FileCheckNumExpr::getUndefVarName() const {
  44. if (!LeftOp->getValue())
  45. return LeftOp->getName();
  46. return StringRef();
  47. }
  48. llvm::Optional<std::string> FileCheckNumericSubstitution::getResult() const {
  49. llvm::Optional<uint64_t> EvaluatedValue = NumExpr->eval();
  50. if (!EvaluatedValue)
  51. return llvm::None;
  52. return utostr(*EvaluatedValue);
  53. }
  54. llvm::Optional<std::string> FileCheckStringSubstitution::getResult() const {
  55. // Look up the value and escape it so that we can put it into the regex.
  56. llvm::Optional<StringRef> VarVal = Context->getPatternVarValue(FromStr);
  57. if (!VarVal)
  58. return llvm::None;
  59. return Regex::escape(*VarVal);
  60. }
  61. StringRef FileCheckNumericSubstitution::getUndefVarName() const {
  62. // Although a use of an undefined numeric variable is detected at parse
  63. // time, a numeric variable can be undefined later by ClearLocalVariables.
  64. return NumExpr->getUndefVarName();
  65. }
  66. StringRef FileCheckStringSubstitution::getUndefVarName() const {
  67. if (!Context->getPatternVarValue(FromStr))
  68. return FromStr;
  69. return StringRef();
  70. }
  71. bool FileCheckPattern::isValidVarNameStart(char C) {
  72. return C == '_' || isalpha(C);
  73. }
  74. bool FileCheckPattern::parseVariable(StringRef Str, bool &IsPseudo,
  75. unsigned &TrailIdx) {
  76. if (Str.empty())
  77. return true;
  78. bool ParsedOneChar = false;
  79. unsigned I = 0;
  80. IsPseudo = Str[0] == '@';
  81. // Global vars start with '$'.
  82. if (Str[0] == '$' || IsPseudo)
  83. ++I;
  84. for (unsigned E = Str.size(); I != E; ++I) {
  85. if (!ParsedOneChar && !isValidVarNameStart(Str[I]))
  86. return true;
  87. // Variable names are composed of alphanumeric characters and underscores.
  88. if (Str[I] != '_' && !isalnum(Str[I]))
  89. break;
  90. ParsedOneChar = true;
  91. }
  92. TrailIdx = I;
  93. return false;
  94. }
  95. // StringRef holding all characters considered as horizontal whitespaces by
  96. // FileCheck input canonicalization.
  97. StringRef SpaceChars = " \t";
  98. // Parsing helper function that strips the first character in S and returns it.
  99. static char popFront(StringRef &S) {
  100. char C = S.front();
  101. S = S.drop_front();
  102. return C;
  103. }
  104. static uint64_t add(uint64_t LeftOp, uint64_t RightOp) {
  105. return LeftOp + RightOp;
  106. }
  107. static uint64_t sub(uint64_t LeftOp, uint64_t RightOp) {
  108. return LeftOp - RightOp;
  109. }
  110. FileCheckNumExpr *
  111. FileCheckPattern::parseNumericSubstitution(StringRef Name, bool IsPseudo,
  112. StringRef Trailer,
  113. const SourceMgr &SM) const {
  114. if (IsPseudo && !Name.equals("@LINE")) {
  115. SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
  116. "invalid pseudo numeric variable '" + Name + "'");
  117. return nullptr;
  118. }
  119. // This method is indirectly called from ParsePattern for all numeric
  120. // variable definitions and uses in the order in which they appear in the
  121. // CHECK pattern. For each definition, the pointer to the class instance of
  122. // the corresponding numeric variable definition is stored in
  123. // GlobalNumericVariableTable. Therefore, the pointer we get below is for the
  124. // class instance corresponding to the last definition of this variable use.
  125. auto VarTableIter = Context->GlobalNumericVariableTable.find(Name);
  126. if (VarTableIter == Context->GlobalNumericVariableTable.end()) {
  127. SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
  128. "using undefined numeric variable '" + Name + "'");
  129. return nullptr;
  130. }
  131. FileCheckNumericVariable *LeftOp = VarTableIter->second;
  132. // Check if this is a supported operation and select a function to perform
  133. // it.
  134. Trailer = Trailer.ltrim(SpaceChars);
  135. if (Trailer.empty()) {
  136. return Context->makeNumExpr(add, LeftOp, 0);
  137. }
  138. SMLoc OpLoc = SMLoc::getFromPointer(Trailer.data());
  139. char Operator = popFront(Trailer);
  140. binop_eval_t EvalBinop;
  141. switch (Operator) {
  142. case '+':
  143. EvalBinop = add;
  144. break;
  145. case '-':
  146. EvalBinop = sub;
  147. break;
  148. default:
  149. SM.PrintMessage(OpLoc, SourceMgr::DK_Error,
  150. Twine("unsupported numeric operation '") + Twine(Operator) +
  151. "'");
  152. return nullptr;
  153. }
  154. // Parse right operand.
  155. Trailer = Trailer.ltrim(SpaceChars);
  156. if (Trailer.empty()) {
  157. SM.PrintMessage(SMLoc::getFromPointer(Trailer.data()), SourceMgr::DK_Error,
  158. "missing operand in numeric expression");
  159. return nullptr;
  160. }
  161. uint64_t RightOp;
  162. if (Trailer.consumeInteger(10, RightOp)) {
  163. SM.PrintMessage(SMLoc::getFromPointer(Trailer.data()), SourceMgr::DK_Error,
  164. "invalid offset in numeric expression '" + Trailer + "'");
  165. return nullptr;
  166. }
  167. Trailer = Trailer.ltrim(SpaceChars);
  168. if (!Trailer.empty()) {
  169. SM.PrintMessage(SMLoc::getFromPointer(Trailer.data()), SourceMgr::DK_Error,
  170. "unexpected characters at end of numeric expression '" +
  171. Trailer + "'");
  172. return nullptr;
  173. }
  174. return Context->makeNumExpr(EvalBinop, LeftOp, RightOp);
  175. }
  176. bool FileCheckPattern::ParsePattern(StringRef PatternStr, StringRef Prefix,
  177. SourceMgr &SM, unsigned LineNumber,
  178. const FileCheckRequest &Req) {
  179. bool MatchFullLinesHere = Req.MatchFullLines && CheckTy != Check::CheckNot;
  180. this->LineNumber = LineNumber;
  181. PatternLoc = SMLoc::getFromPointer(PatternStr.data());
  182. // Create fake @LINE pseudo variable definition.
  183. StringRef LinePseudo = "@LINE";
  184. uint64_t LineNumber64 = LineNumber;
  185. FileCheckNumericVariable *LinePseudoVar =
  186. Context->makeNumericVariable(LinePseudo, LineNumber64);
  187. Context->GlobalNumericVariableTable[LinePseudo] = LinePseudoVar;
  188. if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines))
  189. // Ignore trailing whitespace.
  190. while (!PatternStr.empty() &&
  191. (PatternStr.back() == ' ' || PatternStr.back() == '\t'))
  192. PatternStr = PatternStr.substr(0, PatternStr.size() - 1);
  193. // Check that there is something on the line.
  194. if (PatternStr.empty() && CheckTy != Check::CheckEmpty) {
  195. SM.PrintMessage(PatternLoc, SourceMgr::DK_Error,
  196. "found empty check string with prefix '" + Prefix + ":'");
  197. return true;
  198. }
  199. if (!PatternStr.empty() && CheckTy == Check::CheckEmpty) {
  200. SM.PrintMessage(
  201. PatternLoc, SourceMgr::DK_Error,
  202. "found non-empty check string for empty check with prefix '" + Prefix +
  203. ":'");
  204. return true;
  205. }
  206. if (CheckTy == Check::CheckEmpty) {
  207. RegExStr = "(\n$)";
  208. return false;
  209. }
  210. // Check to see if this is a fixed string, or if it has regex pieces.
  211. if (!MatchFullLinesHere &&
  212. (PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos &&
  213. PatternStr.find("[[") == StringRef::npos))) {
  214. FixedStr = PatternStr;
  215. return false;
  216. }
  217. if (MatchFullLinesHere) {
  218. RegExStr += '^';
  219. if (!Req.NoCanonicalizeWhiteSpace)
  220. RegExStr += " *";
  221. }
  222. // Paren value #0 is for the fully matched string. Any new parenthesized
  223. // values add from there.
  224. unsigned CurParen = 1;
  225. // Otherwise, there is at least one regex piece. Build up the regex pattern
  226. // by escaping scary characters in fixed strings, building up one big regex.
  227. while (!PatternStr.empty()) {
  228. // RegEx matches.
  229. if (PatternStr.startswith("{{")) {
  230. // This is the start of a regex match. Scan for the }}.
  231. size_t End = PatternStr.find("}}");
  232. if (End == StringRef::npos) {
  233. SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
  234. SourceMgr::DK_Error,
  235. "found start of regex string with no end '}}'");
  236. return true;
  237. }
  238. // Enclose {{}} patterns in parens just like [[]] even though we're not
  239. // capturing the result for any purpose. This is required in case the
  240. // expression contains an alternation like: CHECK: abc{{x|z}}def. We
  241. // want this to turn into: "abc(x|z)def" not "abcx|zdef".
  242. RegExStr += '(';
  243. ++CurParen;
  244. if (AddRegExToRegEx(PatternStr.substr(2, End - 2), CurParen, SM))
  245. return true;
  246. RegExStr += ')';
  247. PatternStr = PatternStr.substr(End + 2);
  248. continue;
  249. }
  250. // String and numeric substitution blocks. String substitution blocks come
  251. // in two forms: [[foo:.*]] and [[foo]]. The former matches .* (or some
  252. // other regex) and assigns it to the string variable 'foo'. The latter
  253. // substitutes foo's value. Numeric substitution blocks start with a
  254. // '#' sign after the double brackets and only have the substitution form.
  255. // Both string and numeric variables must satisfy the regular expression
  256. // "[a-zA-Z_][0-9a-zA-Z_]*" to be valid, as this helps catch some common
  257. // errors.
  258. if (PatternStr.startswith("[[")) {
  259. StringRef UnparsedPatternStr = PatternStr.substr(2);
  260. // Find the closing bracket pair ending the match. End is going to be an
  261. // offset relative to the beginning of the match string.
  262. size_t End = FindRegexVarEnd(UnparsedPatternStr, SM);
  263. StringRef MatchStr = UnparsedPatternStr.substr(0, End);
  264. bool IsNumBlock = MatchStr.consume_front("#");
  265. if (End == StringRef::npos) {
  266. SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
  267. SourceMgr::DK_Error,
  268. "Invalid substitution block, no ]] found");
  269. return true;
  270. }
  271. // Strip the substitution block we are parsing. End points to the start
  272. // of the "]]" closing the expression so account for it in computing the
  273. // index of the first unparsed character.
  274. PatternStr = UnparsedPatternStr.substr(End + 2);
  275. size_t VarEndIdx = MatchStr.find(":");
  276. if (IsNumBlock)
  277. MatchStr = MatchStr.ltrim(SpaceChars);
  278. else {
  279. size_t SpacePos = MatchStr.substr(0, VarEndIdx).find_first_of(" \t");
  280. if (SpacePos != StringRef::npos) {
  281. SM.PrintMessage(SMLoc::getFromPointer(MatchStr.data() + SpacePos),
  282. SourceMgr::DK_Error, "unexpected whitespace");
  283. return true;
  284. }
  285. }
  286. // Get the variable name (e.g. "foo") and verify it is well formed.
  287. bool IsPseudo;
  288. unsigned TrailIdx;
  289. if (parseVariable(MatchStr, IsPseudo, TrailIdx)) {
  290. SM.PrintMessage(SMLoc::getFromPointer(MatchStr.data()),
  291. SourceMgr::DK_Error, "invalid variable name");
  292. return true;
  293. }
  294. size_t SubstInsertIdx = RegExStr.size();
  295. FileCheckNumExpr *NumExpr;
  296. StringRef Name = MatchStr.substr(0, TrailIdx);
  297. StringRef Trailer = MatchStr.substr(TrailIdx);
  298. bool IsVarDef = (VarEndIdx != StringRef::npos);
  299. if (IsVarDef) {
  300. if (IsPseudo || !Trailer.consume_front(":")) {
  301. SM.PrintMessage(SMLoc::getFromPointer(MatchStr.data()),
  302. SourceMgr::DK_Error,
  303. "invalid name in string variable definition");
  304. return true;
  305. }
  306. // Detect collisions between string and numeric variables when the
  307. // former is created later than the latter.
  308. if (Context->GlobalNumericVariableTable.find(Name) !=
  309. Context->GlobalNumericVariableTable.end()) {
  310. SM.PrintMessage(
  311. SMLoc::getFromPointer(MatchStr.data()), SourceMgr::DK_Error,
  312. "numeric variable with name '" + Name + "' already exists");
  313. return true;
  314. }
  315. }
  316. if (IsNumBlock || (!IsVarDef && IsPseudo)) {
  317. NumExpr = parseNumericSubstitution(Name, IsPseudo, Trailer, SM);
  318. if (NumExpr == nullptr)
  319. return true;
  320. IsNumBlock = true;
  321. }
  322. // Handle substitutions: [[foo]] and [[#<foo expr>]].
  323. if (!IsVarDef) {
  324. // Handle substitution of string variables that were defined earlier on
  325. // the same line by emitting a backreference.
  326. if (!IsNumBlock && VariableDefs.find(Name) != VariableDefs.end()) {
  327. unsigned CaptureParen = VariableDefs[Name];
  328. if (CaptureParen < 1 || CaptureParen > 9) {
  329. SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
  330. SourceMgr::DK_Error,
  331. "Can't back-reference more than 9 variables");
  332. return true;
  333. }
  334. AddBackrefToRegEx(CaptureParen);
  335. } else {
  336. // Handle substitution of string variables ([[<var>]]) defined in
  337. // previous CHECK patterns, and substitution of numeric expressions.
  338. FileCheckSubstitution *Substitution =
  339. IsNumBlock
  340. ? Context->makeNumericSubstitution(MatchStr, NumExpr,
  341. SubstInsertIdx)
  342. : Context->makeStringSubstitution(MatchStr, SubstInsertIdx);
  343. Substitutions.push_back(Substitution);
  344. }
  345. continue;
  346. }
  347. // Handle variable definitions: [[foo:.*]].
  348. VariableDefs[Name] = CurParen;
  349. RegExStr += '(';
  350. ++CurParen;
  351. if (AddRegExToRegEx(Trailer, CurParen, SM))
  352. return true;
  353. RegExStr += ')';
  354. }
  355. // Handle fixed string matches.
  356. // Find the end, which is the start of the next regex.
  357. size_t FixedMatchEnd = PatternStr.find("{{");
  358. FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[["));
  359. RegExStr += Regex::escape(PatternStr.substr(0, FixedMatchEnd));
  360. PatternStr = PatternStr.substr(FixedMatchEnd);
  361. }
  362. if (MatchFullLinesHere) {
  363. if (!Req.NoCanonicalizeWhiteSpace)
  364. RegExStr += " *";
  365. RegExStr += '$';
  366. }
  367. return false;
  368. }
  369. bool FileCheckPattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM) {
  370. Regex R(RS);
  371. std::string Error;
  372. if (!R.isValid(Error)) {
  373. SM.PrintMessage(SMLoc::getFromPointer(RS.data()), SourceMgr::DK_Error,
  374. "invalid regex: " + Error);
  375. return true;
  376. }
  377. RegExStr += RS.str();
  378. CurParen += R.getNumMatches();
  379. return false;
  380. }
  381. void FileCheckPattern::AddBackrefToRegEx(unsigned BackrefNum) {
  382. assert(BackrefNum >= 1 && BackrefNum <= 9 && "Invalid backref number");
  383. std::string Backref = std::string("\\") + std::string(1, '0' + BackrefNum);
  384. RegExStr += Backref;
  385. }
  386. size_t FileCheckPattern::match(StringRef Buffer, size_t &MatchLen) const {
  387. // If this is the EOF pattern, match it immediately.
  388. if (CheckTy == Check::CheckEOF) {
  389. MatchLen = 0;
  390. return Buffer.size();
  391. }
  392. // If this is a fixed string pattern, just match it now.
  393. if (!FixedStr.empty()) {
  394. MatchLen = FixedStr.size();
  395. return Buffer.find(FixedStr);
  396. }
  397. // Regex match.
  398. // If there are substitutions, we need to create a temporary string with the
  399. // actual value.
  400. StringRef RegExToMatch = RegExStr;
  401. std::string TmpStr;
  402. if (!Substitutions.empty()) {
  403. TmpStr = RegExStr;
  404. size_t InsertOffset = 0;
  405. // Substitute all string variables and numeric expressions whose values are
  406. // only now known. Use of string variables defined on the same line are
  407. // handled by back-references.
  408. for (const auto &Substitution : Substitutions) {
  409. // Substitute and check for failure (e.g. use of undefined variable).
  410. llvm::Optional<std::string> Value = Substitution->getResult();
  411. if (!Value)
  412. return StringRef::npos;
  413. // Plop it into the regex at the adjusted offset.
  414. TmpStr.insert(TmpStr.begin() + Substitution->getIndex() + InsertOffset,
  415. Value->begin(), Value->end());
  416. InsertOffset += Value->size();
  417. }
  418. // Match the newly constructed regex.
  419. RegExToMatch = TmpStr;
  420. }
  421. SmallVector<StringRef, 4> MatchInfo;
  422. if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo))
  423. return StringRef::npos;
  424. // Successful regex match.
  425. assert(!MatchInfo.empty() && "Didn't get any match");
  426. StringRef FullMatch = MatchInfo[0];
  427. // If this defines any string variables, remember their values.
  428. for (const auto &VariableDef : VariableDefs) {
  429. assert(VariableDef.second < MatchInfo.size() && "Internal paren error");
  430. Context->GlobalVariableTable[VariableDef.first] =
  431. MatchInfo[VariableDef.second];
  432. }
  433. // Like CHECK-NEXT, CHECK-EMPTY's match range is considered to start after
  434. // the required preceding newline, which is consumed by the pattern in the
  435. // case of CHECK-EMPTY but not CHECK-NEXT.
  436. size_t MatchStartSkip = CheckTy == Check::CheckEmpty;
  437. MatchLen = FullMatch.size() - MatchStartSkip;
  438. return FullMatch.data() - Buffer.data() + MatchStartSkip;
  439. }
  440. unsigned FileCheckPattern::computeMatchDistance(StringRef Buffer) const {
  441. // Just compute the number of matching characters. For regular expressions, we
  442. // just compare against the regex itself and hope for the best.
  443. //
  444. // FIXME: One easy improvement here is have the regex lib generate a single
  445. // example regular expression which matches, and use that as the example
  446. // string.
  447. StringRef ExampleString(FixedStr);
  448. if (ExampleString.empty())
  449. ExampleString = RegExStr;
  450. // Only compare up to the first line in the buffer, or the string size.
  451. StringRef BufferPrefix = Buffer.substr(0, ExampleString.size());
  452. BufferPrefix = BufferPrefix.split('\n').first;
  453. return BufferPrefix.edit_distance(ExampleString);
  454. }
  455. void FileCheckPattern::printSubstitutions(const SourceMgr &SM, StringRef Buffer,
  456. SMRange MatchRange) const {
  457. // Print what we know about substitutions.
  458. if (!Substitutions.empty()) {
  459. for (const auto &Substitution : Substitutions) {
  460. SmallString<256> Msg;
  461. raw_svector_ostream OS(Msg);
  462. llvm::Optional<std::string> MatchedValue = Substitution->getResult();
  463. // Substitution failed or is not known at match time, print the undefined
  464. // variable it uses.
  465. if (!MatchedValue) {
  466. StringRef UndefVarName = Substitution->getUndefVarName();
  467. if (UndefVarName.empty())
  468. continue;
  469. OS << "uses undefined variable \"";
  470. OS.write_escaped(UndefVarName) << "\"";
  471. } else {
  472. // Substitution succeeded. Print substituted value.
  473. OS << "with \"";
  474. OS.write_escaped(Substitution->getFromString()) << "\" equal to \"";
  475. OS.write_escaped(*MatchedValue) << "\"";
  476. }
  477. if (MatchRange.isValid())
  478. SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note, OS.str(),
  479. {MatchRange});
  480. else
  481. SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
  482. SourceMgr::DK_Note, OS.str());
  483. }
  484. }
  485. }
  486. static SMRange ProcessMatchResult(FileCheckDiag::MatchType MatchTy,
  487. const SourceMgr &SM, SMLoc Loc,
  488. Check::FileCheckType CheckTy,
  489. StringRef Buffer, size_t Pos, size_t Len,
  490. std::vector<FileCheckDiag> *Diags,
  491. bool AdjustPrevDiag = false) {
  492. SMLoc Start = SMLoc::getFromPointer(Buffer.data() + Pos);
  493. SMLoc End = SMLoc::getFromPointer(Buffer.data() + Pos + Len);
  494. SMRange Range(Start, End);
  495. if (Diags) {
  496. if (AdjustPrevDiag)
  497. Diags->rbegin()->MatchTy = MatchTy;
  498. else
  499. Diags->emplace_back(SM, CheckTy, Loc, MatchTy, Range);
  500. }
  501. return Range;
  502. }
  503. void FileCheckPattern::printFuzzyMatch(
  504. const SourceMgr &SM, StringRef Buffer,
  505. std::vector<FileCheckDiag> *Diags) const {
  506. // Attempt to find the closest/best fuzzy match. Usually an error happens
  507. // because some string in the output didn't exactly match. In these cases, we
  508. // would like to show the user a best guess at what "should have" matched, to
  509. // save them having to actually check the input manually.
  510. size_t NumLinesForward = 0;
  511. size_t Best = StringRef::npos;
  512. double BestQuality = 0;
  513. // Use an arbitrary 4k limit on how far we will search.
  514. for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) {
  515. if (Buffer[i] == '\n')
  516. ++NumLinesForward;
  517. // Patterns have leading whitespace stripped, so skip whitespace when
  518. // looking for something which looks like a pattern.
  519. if (Buffer[i] == ' ' || Buffer[i] == '\t')
  520. continue;
  521. // Compute the "quality" of this match as an arbitrary combination of the
  522. // match distance and the number of lines skipped to get to this match.
  523. unsigned Distance = computeMatchDistance(Buffer.substr(i));
  524. double Quality = Distance + (NumLinesForward / 100.);
  525. if (Quality < BestQuality || Best == StringRef::npos) {
  526. Best = i;
  527. BestQuality = Quality;
  528. }
  529. }
  530. // Print the "possible intended match here" line if we found something
  531. // reasonable and not equal to what we showed in the "scanning from here"
  532. // line.
  533. if (Best && Best != StringRef::npos && BestQuality < 50) {
  534. SMRange MatchRange =
  535. ProcessMatchResult(FileCheckDiag::MatchFuzzy, SM, getLoc(),
  536. getCheckTy(), Buffer, Best, 0, Diags);
  537. SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note,
  538. "possible intended match here");
  539. // FIXME: If we wanted to be really friendly we would show why the match
  540. // failed, as it can be hard to spot simple one character differences.
  541. }
  542. }
  543. llvm::Optional<StringRef>
  544. FileCheckPatternContext::getPatternVarValue(StringRef VarName) {
  545. auto VarIter = GlobalVariableTable.find(VarName);
  546. if (VarIter == GlobalVariableTable.end())
  547. return llvm::None;
  548. return VarIter->second;
  549. }
  550. FileCheckNumExpr *
  551. FileCheckPatternContext::makeNumExpr(binop_eval_t EvalBinop,
  552. FileCheckNumericVariable *OperandLeft,
  553. uint64_t OperandRight) {
  554. NumExprs.push_back(llvm::make_unique<FileCheckNumExpr>(EvalBinop, OperandLeft,
  555. OperandRight));
  556. return NumExprs.back().get();
  557. }
  558. FileCheckNumericVariable *
  559. FileCheckPatternContext::makeNumericVariable(StringRef Name, uint64_t Value) {
  560. NumericVariables.push_back(
  561. llvm::make_unique<FileCheckNumericVariable>(Name, Value));
  562. return NumericVariables.back().get();
  563. }
  564. FileCheckSubstitution *
  565. FileCheckPatternContext::makeStringSubstitution(StringRef VarName,
  566. size_t InsertIdx) {
  567. Substitutions.push_back(
  568. llvm::make_unique<FileCheckStringSubstitution>(this, VarName, InsertIdx));
  569. return Substitutions.back().get();
  570. }
  571. FileCheckSubstitution *FileCheckPatternContext::makeNumericSubstitution(
  572. StringRef Expr, FileCheckNumExpr *NumExpr, size_t InsertIdx) {
  573. Substitutions.push_back(llvm::make_unique<FileCheckNumericSubstitution>(
  574. this, Expr, NumExpr, InsertIdx));
  575. return Substitutions.back().get();
  576. }
  577. size_t FileCheckPattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) {
  578. // Offset keeps track of the current offset within the input Str
  579. size_t Offset = 0;
  580. // [...] Nesting depth
  581. size_t BracketDepth = 0;
  582. while (!Str.empty()) {
  583. if (Str.startswith("]]") && BracketDepth == 0)
  584. return Offset;
  585. if (Str[0] == '\\') {
  586. // Backslash escapes the next char within regexes, so skip them both.
  587. Str = Str.substr(2);
  588. Offset += 2;
  589. } else {
  590. switch (Str[0]) {
  591. default:
  592. break;
  593. case '[':
  594. BracketDepth++;
  595. break;
  596. case ']':
  597. if (BracketDepth == 0) {
  598. SM.PrintMessage(SMLoc::getFromPointer(Str.data()),
  599. SourceMgr::DK_Error,
  600. "missing closing \"]\" for regex variable");
  601. exit(1);
  602. }
  603. BracketDepth--;
  604. break;
  605. }
  606. Str = Str.substr(1);
  607. Offset++;
  608. }
  609. }
  610. return StringRef::npos;
  611. }
  612. StringRef
  613. llvm::FileCheck::CanonicalizeFile(MemoryBuffer &MB,
  614. SmallVectorImpl<char> &OutputBuffer) {
  615. OutputBuffer.reserve(MB.getBufferSize());
  616. for (const char *Ptr = MB.getBufferStart(), *End = MB.getBufferEnd();
  617. Ptr != End; ++Ptr) {
  618. // Eliminate trailing dosish \r.
  619. if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') {
  620. continue;
  621. }
  622. // If current char is not a horizontal whitespace or if horizontal
  623. // whitespace canonicalization is disabled, dump it to output as is.
  624. if (Req.NoCanonicalizeWhiteSpace || (*Ptr != ' ' && *Ptr != '\t')) {
  625. OutputBuffer.push_back(*Ptr);
  626. continue;
  627. }
  628. // Otherwise, add one space and advance over neighboring space.
  629. OutputBuffer.push_back(' ');
  630. while (Ptr + 1 != End && (Ptr[1] == ' ' || Ptr[1] == '\t'))
  631. ++Ptr;
  632. }
  633. // Add a null byte and then return all but that byte.
  634. OutputBuffer.push_back('\0');
  635. return StringRef(OutputBuffer.data(), OutputBuffer.size() - 1);
  636. }
  637. FileCheckDiag::FileCheckDiag(const SourceMgr &SM,
  638. const Check::FileCheckType &CheckTy,
  639. SMLoc CheckLoc, MatchType MatchTy,
  640. SMRange InputRange)
  641. : CheckTy(CheckTy), MatchTy(MatchTy) {
  642. auto Start = SM.getLineAndColumn(InputRange.Start);
  643. auto End = SM.getLineAndColumn(InputRange.End);
  644. InputStartLine = Start.first;
  645. InputStartCol = Start.second;
  646. InputEndLine = End.first;
  647. InputEndCol = End.second;
  648. Start = SM.getLineAndColumn(CheckLoc);
  649. CheckLine = Start.first;
  650. CheckCol = Start.second;
  651. }
  652. static bool IsPartOfWord(char c) {
  653. return (isalnum(c) || c == '-' || c == '_');
  654. }
  655. Check::FileCheckType &Check::FileCheckType::setCount(int C) {
  656. assert(Count > 0 && "zero and negative counts are not supported");
  657. assert((C == 1 || Kind == CheckPlain) &&
  658. "count supported only for plain CHECK directives");
  659. Count = C;
  660. return *this;
  661. }
  662. std::string Check::FileCheckType::getDescription(StringRef Prefix) const {
  663. switch (Kind) {
  664. case Check::CheckNone:
  665. return "invalid";
  666. case Check::CheckPlain:
  667. if (Count > 1)
  668. return Prefix.str() + "-COUNT";
  669. return Prefix;
  670. case Check::CheckNext:
  671. return Prefix.str() + "-NEXT";
  672. case Check::CheckSame:
  673. return Prefix.str() + "-SAME";
  674. case Check::CheckNot:
  675. return Prefix.str() + "-NOT";
  676. case Check::CheckDAG:
  677. return Prefix.str() + "-DAG";
  678. case Check::CheckLabel:
  679. return Prefix.str() + "-LABEL";
  680. case Check::CheckEmpty:
  681. return Prefix.str() + "-EMPTY";
  682. case Check::CheckEOF:
  683. return "implicit EOF";
  684. case Check::CheckBadNot:
  685. return "bad NOT";
  686. case Check::CheckBadCount:
  687. return "bad COUNT";
  688. }
  689. llvm_unreachable("unknown FileCheckType");
  690. }
  691. static std::pair<Check::FileCheckType, StringRef>
  692. FindCheckType(StringRef Buffer, StringRef Prefix) {
  693. if (Buffer.size() <= Prefix.size())
  694. return {Check::CheckNone, StringRef()};
  695. char NextChar = Buffer[Prefix.size()];
  696. StringRef Rest = Buffer.drop_front(Prefix.size() + 1);
  697. // Verify that the : is present after the prefix.
  698. if (NextChar == ':')
  699. return {Check::CheckPlain, Rest};
  700. if (NextChar != '-')
  701. return {Check::CheckNone, StringRef()};
  702. if (Rest.consume_front("COUNT-")) {
  703. int64_t Count;
  704. if (Rest.consumeInteger(10, Count))
  705. // Error happened in parsing integer.
  706. return {Check::CheckBadCount, Rest};
  707. if (Count <= 0 || Count > INT32_MAX)
  708. return {Check::CheckBadCount, Rest};
  709. if (!Rest.consume_front(":"))
  710. return {Check::CheckBadCount, Rest};
  711. return {Check::FileCheckType(Check::CheckPlain).setCount(Count), Rest};
  712. }
  713. if (Rest.consume_front("NEXT:"))
  714. return {Check::CheckNext, Rest};
  715. if (Rest.consume_front("SAME:"))
  716. return {Check::CheckSame, Rest};
  717. if (Rest.consume_front("NOT:"))
  718. return {Check::CheckNot, Rest};
  719. if (Rest.consume_front("DAG:"))
  720. return {Check::CheckDAG, Rest};
  721. if (Rest.consume_front("LABEL:"))
  722. return {Check::CheckLabel, Rest};
  723. if (Rest.consume_front("EMPTY:"))
  724. return {Check::CheckEmpty, Rest};
  725. // You can't combine -NOT with another suffix.
  726. if (Rest.startswith("DAG-NOT:") || Rest.startswith("NOT-DAG:") ||
  727. Rest.startswith("NEXT-NOT:") || Rest.startswith("NOT-NEXT:") ||
  728. Rest.startswith("SAME-NOT:") || Rest.startswith("NOT-SAME:") ||
  729. Rest.startswith("EMPTY-NOT:") || Rest.startswith("NOT-EMPTY:"))
  730. return {Check::CheckBadNot, Rest};
  731. return {Check::CheckNone, Rest};
  732. }
  733. // From the given position, find the next character after the word.
  734. static size_t SkipWord(StringRef Str, size_t Loc) {
  735. while (Loc < Str.size() && IsPartOfWord(Str[Loc]))
  736. ++Loc;
  737. return Loc;
  738. }
  739. /// Searches the buffer for the first prefix in the prefix regular expression.
  740. ///
  741. /// This searches the buffer using the provided regular expression, however it
  742. /// enforces constraints beyond that:
  743. /// 1) The found prefix must not be a suffix of something that looks like
  744. /// a valid prefix.
  745. /// 2) The found prefix must be followed by a valid check type suffix using \c
  746. /// FindCheckType above.
  747. ///
  748. /// \returns a pair of StringRefs into the Buffer, which combines:
  749. /// - the first match of the regular expression to satisfy these two is
  750. /// returned,
  751. /// otherwise an empty StringRef is returned to indicate failure.
  752. /// - buffer rewound to the location right after parsed suffix, for parsing
  753. /// to continue from
  754. ///
  755. /// If this routine returns a valid prefix, it will also shrink \p Buffer to
  756. /// start at the beginning of the returned prefix, increment \p LineNumber for
  757. /// each new line consumed from \p Buffer, and set \p CheckTy to the type of
  758. /// check found by examining the suffix.
  759. ///
  760. /// If no valid prefix is found, the state of Buffer, LineNumber, and CheckTy
  761. /// is unspecified.
  762. static std::pair<StringRef, StringRef>
  763. FindFirstMatchingPrefix(Regex &PrefixRE, StringRef &Buffer,
  764. unsigned &LineNumber, Check::FileCheckType &CheckTy) {
  765. SmallVector<StringRef, 2> Matches;
  766. while (!Buffer.empty()) {
  767. // Find the first (longest) match using the RE.
  768. if (!PrefixRE.match(Buffer, &Matches))
  769. // No match at all, bail.
  770. return {StringRef(), StringRef()};
  771. StringRef Prefix = Matches[0];
  772. Matches.clear();
  773. assert(Prefix.data() >= Buffer.data() &&
  774. Prefix.data() < Buffer.data() + Buffer.size() &&
  775. "Prefix doesn't start inside of buffer!");
  776. size_t Loc = Prefix.data() - Buffer.data();
  777. StringRef Skipped = Buffer.substr(0, Loc);
  778. Buffer = Buffer.drop_front(Loc);
  779. LineNumber += Skipped.count('\n');
  780. // Check that the matched prefix isn't a suffix of some other check-like
  781. // word.
  782. // FIXME: This is a very ad-hoc check. it would be better handled in some
  783. // other way. Among other things it seems hard to distinguish between
  784. // intentional and unintentional uses of this feature.
  785. if (Skipped.empty() || !IsPartOfWord(Skipped.back())) {
  786. // Now extract the type.
  787. StringRef AfterSuffix;
  788. std::tie(CheckTy, AfterSuffix) = FindCheckType(Buffer, Prefix);
  789. // If we've found a valid check type for this prefix, we're done.
  790. if (CheckTy != Check::CheckNone)
  791. return {Prefix, AfterSuffix};
  792. }
  793. // If we didn't successfully find a prefix, we need to skip this invalid
  794. // prefix and continue scanning. We directly skip the prefix that was
  795. // matched and any additional parts of that check-like word.
  796. Buffer = Buffer.drop_front(SkipWord(Buffer, Prefix.size()));
  797. }
  798. // We ran out of buffer while skipping partial matches so give up.
  799. return {StringRef(), StringRef()};
  800. }
  801. bool llvm::FileCheck::ReadCheckFile(
  802. SourceMgr &SM, StringRef Buffer, Regex &PrefixRE,
  803. std::vector<FileCheckString> &CheckStrings) {
  804. if (PatternContext.defineCmdlineVariables(Req.GlobalDefines, SM))
  805. return true;
  806. std::vector<FileCheckPattern> ImplicitNegativeChecks;
  807. for (const auto &PatternString : Req.ImplicitCheckNot) {
  808. // Create a buffer with fake command line content in order to display the
  809. // command line option responsible for the specific implicit CHECK-NOT.
  810. std::string Prefix = "-implicit-check-not='";
  811. std::string Suffix = "'";
  812. std::unique_ptr<MemoryBuffer> CmdLine = MemoryBuffer::getMemBufferCopy(
  813. Prefix + PatternString + Suffix, "command line");
  814. StringRef PatternInBuffer =
  815. CmdLine->getBuffer().substr(Prefix.size(), PatternString.size());
  816. SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc());
  817. ImplicitNegativeChecks.push_back(
  818. FileCheckPattern(Check::CheckNot, &PatternContext));
  819. ImplicitNegativeChecks.back().ParsePattern(PatternInBuffer,
  820. "IMPLICIT-CHECK", SM, 0, Req);
  821. }
  822. std::vector<FileCheckPattern> DagNotMatches = ImplicitNegativeChecks;
  823. // LineNumber keeps track of the line on which CheckPrefix instances are
  824. // found.
  825. unsigned LineNumber = 1;
  826. while (1) {
  827. Check::FileCheckType CheckTy;
  828. // See if a prefix occurs in the memory buffer.
  829. StringRef UsedPrefix;
  830. StringRef AfterSuffix;
  831. std::tie(UsedPrefix, AfterSuffix) =
  832. FindFirstMatchingPrefix(PrefixRE, Buffer, LineNumber, CheckTy);
  833. if (UsedPrefix.empty())
  834. break;
  835. assert(UsedPrefix.data() == Buffer.data() &&
  836. "Failed to move Buffer's start forward, or pointed prefix outside "
  837. "of the buffer!");
  838. assert(AfterSuffix.data() >= Buffer.data() &&
  839. AfterSuffix.data() < Buffer.data() + Buffer.size() &&
  840. "Parsing after suffix doesn't start inside of buffer!");
  841. // Location to use for error messages.
  842. const char *UsedPrefixStart = UsedPrefix.data();
  843. // Skip the buffer to the end of parsed suffix (or just prefix, if no good
  844. // suffix was processed).
  845. Buffer = AfterSuffix.empty() ? Buffer.drop_front(UsedPrefix.size())
  846. : AfterSuffix;
  847. // Complain about useful-looking but unsupported suffixes.
  848. if (CheckTy == Check::CheckBadNot) {
  849. SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Error,
  850. "unsupported -NOT combo on prefix '" + UsedPrefix + "'");
  851. return true;
  852. }
  853. // Complain about invalid count specification.
  854. if (CheckTy == Check::CheckBadCount) {
  855. SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Error,
  856. "invalid count in -COUNT specification on prefix '" +
  857. UsedPrefix + "'");
  858. return true;
  859. }
  860. // Okay, we found the prefix, yay. Remember the rest of the line, but ignore
  861. // leading whitespace.
  862. if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines))
  863. Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
  864. // Scan ahead to the end of line.
  865. size_t EOL = Buffer.find_first_of("\n\r");
  866. // Remember the location of the start of the pattern, for diagnostics.
  867. SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data());
  868. // Parse the pattern.
  869. FileCheckPattern P(CheckTy, &PatternContext);
  870. if (P.ParsePattern(Buffer.substr(0, EOL), UsedPrefix, SM, LineNumber, Req))
  871. return true;
  872. // Verify that CHECK-LABEL lines do not define or use variables
  873. if ((CheckTy == Check::CheckLabel) && P.hasVariable()) {
  874. SM.PrintMessage(
  875. SMLoc::getFromPointer(UsedPrefixStart), SourceMgr::DK_Error,
  876. "found '" + UsedPrefix + "-LABEL:'"
  877. " with variable definition or use");
  878. return true;
  879. }
  880. Buffer = Buffer.substr(EOL);
  881. // Verify that CHECK-NEXT/SAME/EMPTY lines have at least one CHECK line before them.
  882. if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame ||
  883. CheckTy == Check::CheckEmpty) &&
  884. CheckStrings.empty()) {
  885. StringRef Type = CheckTy == Check::CheckNext
  886. ? "NEXT"
  887. : CheckTy == Check::CheckEmpty ? "EMPTY" : "SAME";
  888. SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),
  889. SourceMgr::DK_Error,
  890. "found '" + UsedPrefix + "-" + Type +
  891. "' without previous '" + UsedPrefix + ": line");
  892. return true;
  893. }
  894. // Handle CHECK-DAG/-NOT.
  895. if (CheckTy == Check::CheckDAG || CheckTy == Check::CheckNot) {
  896. DagNotMatches.push_back(P);
  897. continue;
  898. }
  899. // Okay, add the string we captured to the output vector and move on.
  900. CheckStrings.emplace_back(P, UsedPrefix, PatternLoc);
  901. std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
  902. DagNotMatches = ImplicitNegativeChecks;
  903. }
  904. // Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first
  905. // prefix as a filler for the error message.
  906. if (!DagNotMatches.empty()) {
  907. CheckStrings.emplace_back(
  908. FileCheckPattern(Check::CheckEOF, &PatternContext),
  909. *Req.CheckPrefixes.begin(), SMLoc::getFromPointer(Buffer.data()));
  910. std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
  911. }
  912. if (CheckStrings.empty()) {
  913. errs() << "error: no check strings found with prefix"
  914. << (Req.CheckPrefixes.size() > 1 ? "es " : " ");
  915. auto I = Req.CheckPrefixes.begin();
  916. auto E = Req.CheckPrefixes.end();
  917. if (I != E) {
  918. errs() << "\'" << *I << ":'";
  919. ++I;
  920. }
  921. for (; I != E; ++I)
  922. errs() << ", \'" << *I << ":'";
  923. errs() << '\n';
  924. return true;
  925. }
  926. return false;
  927. }
  928. static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM,
  929. StringRef Prefix, SMLoc Loc, const FileCheckPattern &Pat,
  930. int MatchedCount, StringRef Buffer, size_t MatchPos,
  931. size_t MatchLen, const FileCheckRequest &Req,
  932. std::vector<FileCheckDiag> *Diags) {
  933. bool PrintDiag = true;
  934. if (ExpectedMatch) {
  935. if (!Req.Verbose)
  936. return;
  937. if (!Req.VerboseVerbose && Pat.getCheckTy() == Check::CheckEOF)
  938. return;
  939. // Due to their verbosity, we don't print verbose diagnostics here if we're
  940. // gathering them for a different rendering, but we always print other
  941. // diagnostics.
  942. PrintDiag = !Diags;
  943. }
  944. SMRange MatchRange = ProcessMatchResult(
  945. ExpectedMatch ? FileCheckDiag::MatchFoundAndExpected
  946. : FileCheckDiag::MatchFoundButExcluded,
  947. SM, Loc, Pat.getCheckTy(), Buffer, MatchPos, MatchLen, Diags);
  948. if (!PrintDiag)
  949. return;
  950. std::string Message = formatv("{0}: {1} string found in input",
  951. Pat.getCheckTy().getDescription(Prefix),
  952. (ExpectedMatch ? "expected" : "excluded"))
  953. .str();
  954. if (Pat.getCount() > 1)
  955. Message += formatv(" ({0} out of {1})", MatchedCount, Pat.getCount()).str();
  956. SM.PrintMessage(
  957. Loc, ExpectedMatch ? SourceMgr::DK_Remark : SourceMgr::DK_Error, Message);
  958. SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note, "found here",
  959. {MatchRange});
  960. Pat.printSubstitutions(SM, Buffer, MatchRange);
  961. }
  962. static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM,
  963. const FileCheckString &CheckStr, int MatchedCount,
  964. StringRef Buffer, size_t MatchPos, size_t MatchLen,
  965. FileCheckRequest &Req,
  966. std::vector<FileCheckDiag> *Diags) {
  967. PrintMatch(ExpectedMatch, SM, CheckStr.Prefix, CheckStr.Loc, CheckStr.Pat,
  968. MatchedCount, Buffer, MatchPos, MatchLen, Req, Diags);
  969. }
  970. static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM,
  971. StringRef Prefix, SMLoc Loc,
  972. const FileCheckPattern &Pat, int MatchedCount,
  973. StringRef Buffer, bool VerboseVerbose,
  974. std::vector<FileCheckDiag> *Diags) {
  975. bool PrintDiag = true;
  976. if (!ExpectedMatch) {
  977. if (!VerboseVerbose)
  978. return;
  979. // Due to their verbosity, we don't print verbose diagnostics here if we're
  980. // gathering them for a different rendering, but we always print other
  981. // diagnostics.
  982. PrintDiag = !Diags;
  983. }
  984. // If the current position is at the end of a line, advance to the start of
  985. // the next line.
  986. Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));
  987. SMRange SearchRange = ProcessMatchResult(
  988. ExpectedMatch ? FileCheckDiag::MatchNoneButExpected
  989. : FileCheckDiag::MatchNoneAndExcluded,
  990. SM, Loc, Pat.getCheckTy(), Buffer, 0, Buffer.size(), Diags);
  991. if (!PrintDiag)
  992. return;
  993. // Print "not found" diagnostic.
  994. std::string Message = formatv("{0}: {1} string not found in input",
  995. Pat.getCheckTy().getDescription(Prefix),
  996. (ExpectedMatch ? "expected" : "excluded"))
  997. .str();
  998. if (Pat.getCount() > 1)
  999. Message += formatv(" ({0} out of {1})", MatchedCount, Pat.getCount()).str();
  1000. SM.PrintMessage(
  1001. Loc, ExpectedMatch ? SourceMgr::DK_Error : SourceMgr::DK_Remark, Message);
  1002. // Print the "scanning from here" line.
  1003. SM.PrintMessage(SearchRange.Start, SourceMgr::DK_Note, "scanning from here");
  1004. // Allow the pattern to print additional information if desired.
  1005. Pat.printSubstitutions(SM, Buffer);
  1006. if (ExpectedMatch)
  1007. Pat.printFuzzyMatch(SM, Buffer, Diags);
  1008. }
  1009. static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM,
  1010. const FileCheckString &CheckStr, int MatchedCount,
  1011. StringRef Buffer, bool VerboseVerbose,
  1012. std::vector<FileCheckDiag> *Diags) {
  1013. PrintNoMatch(ExpectedMatch, SM, CheckStr.Prefix, CheckStr.Loc, CheckStr.Pat,
  1014. MatchedCount, Buffer, VerboseVerbose, Diags);
  1015. }
  1016. /// Counts the number of newlines in the specified range.
  1017. static unsigned CountNumNewlinesBetween(StringRef Range,
  1018. const char *&FirstNewLine) {
  1019. unsigned NumNewLines = 0;
  1020. while (1) {
  1021. // Scan for newline.
  1022. Range = Range.substr(Range.find_first_of("\n\r"));
  1023. if (Range.empty())
  1024. return NumNewLines;
  1025. ++NumNewLines;
  1026. // Handle \n\r and \r\n as a single newline.
  1027. if (Range.size() > 1 && (Range[1] == '\n' || Range[1] == '\r') &&
  1028. (Range[0] != Range[1]))
  1029. Range = Range.substr(1);
  1030. Range = Range.substr(1);
  1031. if (NumNewLines == 1)
  1032. FirstNewLine = Range.begin();
  1033. }
  1034. }
  1035. size_t FileCheckString::Check(const SourceMgr &SM, StringRef Buffer,
  1036. bool IsLabelScanMode, size_t &MatchLen,
  1037. FileCheckRequest &Req,
  1038. std::vector<FileCheckDiag> *Diags) const {
  1039. size_t LastPos = 0;
  1040. std::vector<const FileCheckPattern *> NotStrings;
  1041. // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL
  1042. // bounds; we have not processed variable definitions within the bounded block
  1043. // yet so cannot handle any final CHECK-DAG yet; this is handled when going
  1044. // over the block again (including the last CHECK-LABEL) in normal mode.
  1045. if (!IsLabelScanMode) {
  1046. // Match "dag strings" (with mixed "not strings" if any).
  1047. LastPos = CheckDag(SM, Buffer, NotStrings, Req, Diags);
  1048. if (LastPos == StringRef::npos)
  1049. return StringRef::npos;
  1050. }
  1051. // Match itself from the last position after matching CHECK-DAG.
  1052. size_t LastMatchEnd = LastPos;
  1053. size_t FirstMatchPos = 0;
  1054. // Go match the pattern Count times. Majority of patterns only match with
  1055. // count 1 though.
  1056. assert(Pat.getCount() != 0 && "pattern count can not be zero");
  1057. for (int i = 1; i <= Pat.getCount(); i++) {
  1058. StringRef MatchBuffer = Buffer.substr(LastMatchEnd);
  1059. size_t CurrentMatchLen;
  1060. // get a match at current start point
  1061. size_t MatchPos = Pat.match(MatchBuffer, CurrentMatchLen);
  1062. if (i == 1)
  1063. FirstMatchPos = LastPos + MatchPos;
  1064. // report
  1065. if (MatchPos == StringRef::npos) {
  1066. PrintNoMatch(true, SM, *this, i, MatchBuffer, Req.VerboseVerbose, Diags);
  1067. return StringRef::npos;
  1068. }
  1069. PrintMatch(true, SM, *this, i, MatchBuffer, MatchPos, CurrentMatchLen, Req,
  1070. Diags);
  1071. // move start point after the match
  1072. LastMatchEnd += MatchPos + CurrentMatchLen;
  1073. }
  1074. // Full match len counts from first match pos.
  1075. MatchLen = LastMatchEnd - FirstMatchPos;
  1076. // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT
  1077. // or CHECK-NOT
  1078. if (!IsLabelScanMode) {
  1079. size_t MatchPos = FirstMatchPos - LastPos;
  1080. StringRef MatchBuffer = Buffer.substr(LastPos);
  1081. StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos);
  1082. // If this check is a "CHECK-NEXT", verify that the previous match was on
  1083. // the previous line (i.e. that there is one newline between them).
  1084. if (CheckNext(SM, SkippedRegion)) {
  1085. ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine, SM, Loc,
  1086. Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen,
  1087. Diags, Req.Verbose);
  1088. return StringRef::npos;
  1089. }
  1090. // If this check is a "CHECK-SAME", verify that the previous match was on
  1091. // the same line (i.e. that there is no newline between them).
  1092. if (CheckSame(SM, SkippedRegion)) {
  1093. ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine, SM, Loc,
  1094. Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen,
  1095. Diags, Req.Verbose);
  1096. return StringRef::npos;
  1097. }
  1098. // If this match had "not strings", verify that they don't exist in the
  1099. // skipped region.
  1100. if (CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
  1101. return StringRef::npos;
  1102. }
  1103. return FirstMatchPos;
  1104. }
  1105. bool FileCheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
  1106. if (Pat.getCheckTy() != Check::CheckNext &&
  1107. Pat.getCheckTy() != Check::CheckEmpty)
  1108. return false;
  1109. Twine CheckName =
  1110. Prefix +
  1111. Twine(Pat.getCheckTy() == Check::CheckEmpty ? "-EMPTY" : "-NEXT");
  1112. // Count the number of newlines between the previous match and this one.
  1113. const char *FirstNewLine = nullptr;
  1114. unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
  1115. if (NumNewLines == 0) {
  1116. SM.PrintMessage(Loc, SourceMgr::DK_Error,
  1117. CheckName + ": is on the same line as previous match");
  1118. SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
  1119. "'next' match was here");
  1120. SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
  1121. "previous match ended here");
  1122. return true;
  1123. }
  1124. if (NumNewLines != 1) {
  1125. SM.PrintMessage(Loc, SourceMgr::DK_Error,
  1126. CheckName +
  1127. ": is not on the line after the previous match");
  1128. SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
  1129. "'next' match was here");
  1130. SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
  1131. "previous match ended here");
  1132. SM.PrintMessage(SMLoc::getFromPointer(FirstNewLine), SourceMgr::DK_Note,
  1133. "non-matching line after previous match is here");
  1134. return true;
  1135. }
  1136. return false;
  1137. }
  1138. bool FileCheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const {
  1139. if (Pat.getCheckTy() != Check::CheckSame)
  1140. return false;
  1141. // Count the number of newlines between the previous match and this one.
  1142. const char *FirstNewLine = nullptr;
  1143. unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
  1144. if (NumNewLines != 0) {
  1145. SM.PrintMessage(Loc, SourceMgr::DK_Error,
  1146. Prefix +
  1147. "-SAME: is not on the same line as the previous match");
  1148. SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
  1149. "'next' match was here");
  1150. SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
  1151. "previous match ended here");
  1152. return true;
  1153. }
  1154. return false;
  1155. }
  1156. bool FileCheckString::CheckNot(
  1157. const SourceMgr &SM, StringRef Buffer,
  1158. const std::vector<const FileCheckPattern *> &NotStrings,
  1159. const FileCheckRequest &Req, std::vector<FileCheckDiag> *Diags) const {
  1160. for (const FileCheckPattern *Pat : NotStrings) {
  1161. assert((Pat->getCheckTy() == Check::CheckNot) && "Expect CHECK-NOT!");
  1162. size_t MatchLen = 0;
  1163. size_t Pos = Pat->match(Buffer, MatchLen);
  1164. if (Pos == StringRef::npos) {
  1165. PrintNoMatch(false, SM, Prefix, Pat->getLoc(), *Pat, 1, Buffer,
  1166. Req.VerboseVerbose, Diags);
  1167. continue;
  1168. }
  1169. PrintMatch(false, SM, Prefix, Pat->getLoc(), *Pat, 1, Buffer, Pos, MatchLen,
  1170. Req, Diags);
  1171. return true;
  1172. }
  1173. return false;
  1174. }
  1175. size_t
  1176. FileCheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
  1177. std::vector<const FileCheckPattern *> &NotStrings,
  1178. const FileCheckRequest &Req,
  1179. std::vector<FileCheckDiag> *Diags) const {
  1180. if (DagNotStrings.empty())
  1181. return 0;
  1182. // The start of the search range.
  1183. size_t StartPos = 0;
  1184. struct MatchRange {
  1185. size_t Pos;
  1186. size_t End;
  1187. };
  1188. // A sorted list of ranges for non-overlapping CHECK-DAG matches. Match
  1189. // ranges are erased from this list once they are no longer in the search
  1190. // range.
  1191. std::list<MatchRange> MatchRanges;
  1192. // We need PatItr and PatEnd later for detecting the end of a CHECK-DAG
  1193. // group, so we don't use a range-based for loop here.
  1194. for (auto PatItr = DagNotStrings.begin(), PatEnd = DagNotStrings.end();
  1195. PatItr != PatEnd; ++PatItr) {
  1196. const FileCheckPattern &Pat = *PatItr;
  1197. assert((Pat.getCheckTy() == Check::CheckDAG ||
  1198. Pat.getCheckTy() == Check::CheckNot) &&
  1199. "Invalid CHECK-DAG or CHECK-NOT!");
  1200. if (Pat.getCheckTy() == Check::CheckNot) {
  1201. NotStrings.push_back(&Pat);
  1202. continue;
  1203. }
  1204. assert((Pat.getCheckTy() == Check::CheckDAG) && "Expect CHECK-DAG!");
  1205. // CHECK-DAG always matches from the start.
  1206. size_t MatchLen = 0, MatchPos = StartPos;
  1207. // Search for a match that doesn't overlap a previous match in this
  1208. // CHECK-DAG group.
  1209. for (auto MI = MatchRanges.begin(), ME = MatchRanges.end(); true; ++MI) {
  1210. StringRef MatchBuffer = Buffer.substr(MatchPos);
  1211. size_t MatchPosBuf = Pat.match(MatchBuffer, MatchLen);
  1212. // With a group of CHECK-DAGs, a single mismatching means the match on
  1213. // that group of CHECK-DAGs fails immediately.
  1214. if (MatchPosBuf == StringRef::npos) {
  1215. PrintNoMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, MatchBuffer,
  1216. Req.VerboseVerbose, Diags);
  1217. return StringRef::npos;
  1218. }
  1219. // Re-calc it as the offset relative to the start of the original string.
  1220. MatchPos += MatchPosBuf;
  1221. if (Req.VerboseVerbose)
  1222. PrintMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, Buffer, MatchPos,
  1223. MatchLen, Req, Diags);
  1224. MatchRange M{MatchPos, MatchPos + MatchLen};
  1225. if (Req.AllowDeprecatedDagOverlap) {
  1226. // We don't need to track all matches in this mode, so we just maintain
  1227. // one match range that encompasses the current CHECK-DAG group's
  1228. // matches.
  1229. if (MatchRanges.empty())
  1230. MatchRanges.insert(MatchRanges.end(), M);
  1231. else {
  1232. auto Block = MatchRanges.begin();
  1233. Block->Pos = std::min(Block->Pos, M.Pos);
  1234. Block->End = std::max(Block->End, M.End);
  1235. }
  1236. break;
  1237. }
  1238. // Iterate previous matches until overlapping match or insertion point.
  1239. bool Overlap = false;
  1240. for (; MI != ME; ++MI) {
  1241. if (M.Pos < MI->End) {
  1242. // !Overlap => New match has no overlap and is before this old match.
  1243. // Overlap => New match overlaps this old match.
  1244. Overlap = MI->Pos < M.End;
  1245. break;
  1246. }
  1247. }
  1248. if (!Overlap) {
  1249. // Insert non-overlapping match into list.
  1250. MatchRanges.insert(MI, M);
  1251. break;
  1252. }
  1253. if (Req.VerboseVerbose) {
  1254. // Due to their verbosity, we don't print verbose diagnostics here if
  1255. // we're gathering them for a different rendering, but we always print
  1256. // other diagnostics.
  1257. if (!Diags) {
  1258. SMLoc OldStart = SMLoc::getFromPointer(Buffer.data() + MI->Pos);
  1259. SMLoc OldEnd = SMLoc::getFromPointer(Buffer.data() + MI->End);
  1260. SMRange OldRange(OldStart, OldEnd);
  1261. SM.PrintMessage(OldStart, SourceMgr::DK_Note,
  1262. "match discarded, overlaps earlier DAG match here",
  1263. {OldRange});
  1264. } else
  1265. Diags->rbegin()->MatchTy = FileCheckDiag::MatchFoundButDiscarded;
  1266. }
  1267. MatchPos = MI->End;
  1268. }
  1269. if (!Req.VerboseVerbose)
  1270. PrintMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, Buffer, MatchPos,
  1271. MatchLen, Req, Diags);
  1272. // Handle the end of a CHECK-DAG group.
  1273. if (std::next(PatItr) == PatEnd ||
  1274. std::next(PatItr)->getCheckTy() == Check::CheckNot) {
  1275. if (!NotStrings.empty()) {
  1276. // If there are CHECK-NOTs between two CHECK-DAGs or from CHECK to
  1277. // CHECK-DAG, verify that there are no 'not' strings occurred in that
  1278. // region.
  1279. StringRef SkippedRegion =
  1280. Buffer.slice(StartPos, MatchRanges.begin()->Pos);
  1281. if (CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
  1282. return StringRef::npos;
  1283. // Clear "not strings".
  1284. NotStrings.clear();
  1285. }
  1286. // All subsequent CHECK-DAGs and CHECK-NOTs should be matched from the
  1287. // end of this CHECK-DAG group's match range.
  1288. StartPos = MatchRanges.rbegin()->End;
  1289. // Don't waste time checking for (impossible) overlaps before that.
  1290. MatchRanges.clear();
  1291. }
  1292. }
  1293. return StartPos;
  1294. }
  1295. // A check prefix must contain only alphanumeric, hyphens and underscores.
  1296. static bool ValidateCheckPrefix(StringRef CheckPrefix) {
  1297. Regex Validator("^[a-zA-Z0-9_-]*$");
  1298. return Validator.match(CheckPrefix);
  1299. }
  1300. bool llvm::FileCheck::ValidateCheckPrefixes() {
  1301. StringSet<> PrefixSet;
  1302. for (StringRef Prefix : Req.CheckPrefixes) {
  1303. // Reject empty prefixes.
  1304. if (Prefix == "")
  1305. return false;
  1306. if (!PrefixSet.insert(Prefix).second)
  1307. return false;
  1308. if (!ValidateCheckPrefix(Prefix))
  1309. return false;
  1310. }
  1311. return true;
  1312. }
  1313. Regex llvm::FileCheck::buildCheckPrefixRegex() {
  1314. // I don't think there's a way to specify an initial value for cl::list,
  1315. // so if nothing was specified, add the default
  1316. if (Req.CheckPrefixes.empty())
  1317. Req.CheckPrefixes.push_back("CHECK");
  1318. // We already validated the contents of CheckPrefixes so just concatenate
  1319. // them as alternatives.
  1320. SmallString<32> PrefixRegexStr;
  1321. for (StringRef Prefix : Req.CheckPrefixes) {
  1322. if (Prefix != Req.CheckPrefixes.front())
  1323. PrefixRegexStr.push_back('|');
  1324. PrefixRegexStr.append(Prefix);
  1325. }
  1326. return Regex(PrefixRegexStr);
  1327. }
  1328. bool FileCheckPatternContext::defineCmdlineVariables(
  1329. std::vector<std::string> &CmdlineDefines, SourceMgr &SM) {
  1330. assert(GlobalVariableTable.empty() && GlobalNumericVariableTable.empty() &&
  1331. "Overriding defined variable with command-line variable definitions");
  1332. if (CmdlineDefines.empty())
  1333. return false;
  1334. // Create a string representing the vector of command-line definitions. Each
  1335. // definition is on its own line and prefixed with a definition number to
  1336. // clarify which definition a given diagnostic corresponds to.
  1337. unsigned I = 0;
  1338. bool ErrorFound = false;
  1339. std::string CmdlineDefsDiag;
  1340. StringRef Prefix1 = "Global define #";
  1341. StringRef Prefix2 = ": ";
  1342. for (StringRef CmdlineDef : CmdlineDefines)
  1343. CmdlineDefsDiag +=
  1344. (Prefix1 + Twine(++I) + Prefix2 + CmdlineDef + "\n").str();
  1345. // Create a buffer with fake command line content in order to display
  1346. // parsing diagnostic with location information and point to the
  1347. // global definition with invalid syntax.
  1348. std::unique_ptr<MemoryBuffer> CmdLineDefsDiagBuffer =
  1349. MemoryBuffer::getMemBufferCopy(CmdlineDefsDiag, "Global defines");
  1350. StringRef CmdlineDefsDiagRef = CmdLineDefsDiagBuffer->getBuffer();
  1351. SM.AddNewSourceBuffer(std::move(CmdLineDefsDiagBuffer), SMLoc());
  1352. SmallVector<StringRef, 4> CmdlineDefsDiagVec;
  1353. CmdlineDefsDiagRef.split(CmdlineDefsDiagVec, '\n', -1 /*MaxSplit*/,
  1354. false /*KeepEmpty*/);
  1355. for (StringRef CmdlineDefDiag : CmdlineDefsDiagVec) {
  1356. unsigned DefStart = CmdlineDefDiag.find(Prefix2) + Prefix2.size();
  1357. StringRef CmdlineDef = CmdlineDefDiag.substr(DefStart);
  1358. if (CmdlineDef.find('=') == StringRef::npos) {
  1359. SM.PrintMessage(SMLoc::getFromPointer(CmdlineDef.data()),
  1360. SourceMgr::DK_Error,
  1361. "Missing equal sign in global definition");
  1362. ErrorFound = true;
  1363. continue;
  1364. }
  1365. // Numeric variable definition.
  1366. if (CmdlineDef[0] == '#') {
  1367. bool IsPseudo;
  1368. unsigned TrailIdx;
  1369. size_t EqIdx = CmdlineDef.find('=');
  1370. StringRef CmdlineName = CmdlineDef.substr(1, EqIdx - 1);
  1371. if (FileCheckPattern::parseVariable(CmdlineName, IsPseudo, TrailIdx) ||
  1372. IsPseudo || TrailIdx != CmdlineName.size() || CmdlineName.empty()) {
  1373. SM.PrintMessage(SMLoc::getFromPointer(CmdlineName.data()),
  1374. SourceMgr::DK_Error,
  1375. "invalid name in numeric variable definition '" +
  1376. CmdlineName + "'");
  1377. ErrorFound = true;
  1378. continue;
  1379. }
  1380. // Detect collisions between string and numeric variables when the latter
  1381. // is created later than the former.
  1382. if (DefinedVariableTable.find(CmdlineName) !=
  1383. DefinedVariableTable.end()) {
  1384. SM.PrintMessage(
  1385. SMLoc::getFromPointer(CmdlineName.data()), SourceMgr::DK_Error,
  1386. "string variable with name '" + CmdlineName + "' already exists");
  1387. ErrorFound = true;
  1388. continue;
  1389. }
  1390. StringRef CmdlineVal = CmdlineDef.substr(EqIdx + 1);
  1391. uint64_t Val;
  1392. if (CmdlineVal.getAsInteger(10, Val)) {
  1393. SM.PrintMessage(SMLoc::getFromPointer(CmdlineVal.data()),
  1394. SourceMgr::DK_Error,
  1395. "invalid value in numeric variable definition '" +
  1396. CmdlineVal + "'");
  1397. ErrorFound = true;
  1398. continue;
  1399. }
  1400. auto DefinedNumericVariable = makeNumericVariable(CmdlineName, Val);
  1401. // Record this variable definition.
  1402. GlobalNumericVariableTable[CmdlineName] = DefinedNumericVariable;
  1403. } else {
  1404. // String variable definition.
  1405. std::pair<StringRef, StringRef> CmdlineNameVal = CmdlineDef.split('=');
  1406. StringRef Name = CmdlineNameVal.first;
  1407. bool IsPseudo;
  1408. unsigned TrailIdx;
  1409. if (FileCheckPattern::parseVariable(Name, IsPseudo, TrailIdx) ||
  1410. IsPseudo || TrailIdx != Name.size() || Name.empty()) {
  1411. SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
  1412. "invalid name in string variable definition '" + Name +
  1413. "'");
  1414. ErrorFound = true;
  1415. continue;
  1416. }
  1417. // Detect collisions between string and numeric variables when the former
  1418. // is created later than the latter.
  1419. if (GlobalNumericVariableTable.find(Name) !=
  1420. GlobalNumericVariableTable.end()) {
  1421. SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
  1422. "numeric variable with name '" + Name +
  1423. "' already exists");
  1424. ErrorFound = true;
  1425. continue;
  1426. }
  1427. GlobalVariableTable.insert(CmdlineNameVal);
  1428. // Mark the string variable as defined to detect collisions between
  1429. // string and numeric variables in DefineCmdlineVariables when the latter
  1430. // is created later than the former. We cannot reuse GlobalVariableTable
  1431. // for that by populating it with an empty string since we would then
  1432. // lose the ability to detect the use of an undefined variable in
  1433. // match().
  1434. DefinedVariableTable[Name] = true;
  1435. }
  1436. }
  1437. return ErrorFound;
  1438. }
  1439. void FileCheckPatternContext::clearLocalVars() {
  1440. SmallVector<StringRef, 16> LocalPatternVars, LocalNumericVars;
  1441. for (const StringMapEntry<StringRef> &Var : GlobalVariableTable)
  1442. if (Var.first()[0] != '$')
  1443. LocalPatternVars.push_back(Var.first());
  1444. // Numeric substitution reads the value of a variable directly, not via
  1445. // GlobalNumericVariableTable. Therefore, we clear local variables by
  1446. // clearing their value which will lead to a numeric substitution failure. We
  1447. // also mark the variable for removal from GlobalNumericVariableTable since
  1448. // this is what defineCmdlineVariables checks to decide that no global
  1449. // variable has been defined.
  1450. for (const auto &Var : GlobalNumericVariableTable)
  1451. if (Var.first()[0] != '$') {
  1452. Var.getValue()->clearValue();
  1453. LocalNumericVars.push_back(Var.first());
  1454. }
  1455. for (const auto &Var : LocalPatternVars)
  1456. GlobalVariableTable.erase(Var);
  1457. for (const auto &Var : LocalNumericVars)
  1458. GlobalNumericVariableTable.erase(Var);
  1459. }
  1460. bool llvm::FileCheck::CheckInput(SourceMgr &SM, StringRef Buffer,
  1461. ArrayRef<FileCheckString> CheckStrings,
  1462. std::vector<FileCheckDiag> *Diags) {
  1463. bool ChecksFailed = false;
  1464. unsigned i = 0, j = 0, e = CheckStrings.size();
  1465. while (true) {
  1466. StringRef CheckRegion;
  1467. if (j == e) {
  1468. CheckRegion = Buffer;
  1469. } else {
  1470. const FileCheckString &CheckLabelStr = CheckStrings[j];
  1471. if (CheckLabelStr.Pat.getCheckTy() != Check::CheckLabel) {
  1472. ++j;
  1473. continue;
  1474. }
  1475. // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG
  1476. size_t MatchLabelLen = 0;
  1477. size_t MatchLabelPos =
  1478. CheckLabelStr.Check(SM, Buffer, true, MatchLabelLen, Req, Diags);
  1479. if (MatchLabelPos == StringRef::npos)
  1480. // Immediately bail if CHECK-LABEL fails, nothing else we can do.
  1481. return false;
  1482. CheckRegion = Buffer.substr(0, MatchLabelPos + MatchLabelLen);
  1483. Buffer = Buffer.substr(MatchLabelPos + MatchLabelLen);
  1484. ++j;
  1485. }
  1486. // Do not clear the first region as it's the one before the first
  1487. // CHECK-LABEL and it would clear variables defined on the command-line
  1488. // before they get used.
  1489. if (i != 0 && Req.EnableVarScope)
  1490. PatternContext.clearLocalVars();
  1491. for (; i != j; ++i) {
  1492. const FileCheckString &CheckStr = CheckStrings[i];
  1493. // Check each string within the scanned region, including a second check
  1494. // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG)
  1495. size_t MatchLen = 0;
  1496. size_t MatchPos =
  1497. CheckStr.Check(SM, CheckRegion, false, MatchLen, Req, Diags);
  1498. if (MatchPos == StringRef::npos) {
  1499. ChecksFailed = true;
  1500. i = j;
  1501. break;
  1502. }
  1503. CheckRegion = CheckRegion.substr(MatchPos + MatchLen);
  1504. }
  1505. if (j == e)
  1506. break;
  1507. }
  1508. // Success if no checks failed.
  1509. return !ChecksFailed;
  1510. }