50 auto CreatePrecisionRegex = [&](
StringRef S) {
51 return (
Twine(AlternateFormPrefix) + S +
Twine(
'{') +
Twine(Precision) +
59 return CreatePrecisionRegex(
"([1-9][0-9]*)?[0-9]");
60 return std::string(
"[0-9]+");
63 return CreatePrecisionRegex(
"-?([1-9][0-9]*)?[0-9]");
64 return std::string(
"-?[0-9]+");
67 return CreatePrecisionRegex(
"([1-9A-F][0-9A-F]*)?[0-9A-F]");
68 return (
Twine(AlternateFormPrefix) +
Twine(
"[0-9A-F]+")).str();
71 return CreatePrecisionRegex(
"([1-9a-f][0-9a-f]*)?[0-9a-f]");
72 return (
Twine(AlternateFormPrefix) +
Twine(
"[0-9a-f]+")).str();
75 "trying to match value with invalid format");
82 return make_error<OverflowError>();
85 bool UpperCase =
false;
103 "trying to match value with invalid format");
105 IntValue.
abs().
toString(AbsoluteValueStr, Radix,
false,
111 if (Precision > AbsoluteValueStr.
size()) {
112 unsigned LeadingZeros = Precision - AbsoluteValueStr.
size();
113 return (
Twine(SignPrefix) +
Twine(AlternateFormPrefix) +
114 std::string(LeadingZeros,
'0') + AbsoluteValueStr)
118 return (
Twine(SignPrefix) +
Twine(AlternateFormPrefix) + AbsoluteValueStr)
130 APInt Result = AbsVal;
139 bool Negative = StrVal.consume_front(
"-");
141 bool MissingFormPrefix =
142 !ValueIsSigned && AlternateForm && !StrVal.consume_front(
"0x");
143 (void)MissingFormPrefix;
144 assert(!MissingFormPrefix &&
"missing alternate form prefix");
146 [[maybe_unused]]
bool ParseFailure =
147 StrVal.getAsInteger(Hex ? 16 : 10, ResultValue);
151 assert(!ParseFailure &&
"unable to represent numeric value");
152 return toSigned(ResultValue, Negative);
156 const APInt &RightOperand,
bool &Overflow) {
157 return LeftOperand.
sadd_ov(RightOperand, Overflow);
161 const APInt &RightOperand,
bool &Overflow) {
162 return LeftOperand.
ssub_ov(RightOperand, Overflow);
166 const APInt &RightOperand,
bool &Overflow) {
167 return LeftOperand.
smul_ov(RightOperand, Overflow);
171 const APInt &RightOperand,
bool &Overflow) {
173 if (RightOperand.
isZero())
174 return make_error<OverflowError>();
176 return LeftOperand.
sdiv_ov(RightOperand, Overflow);
180 const APInt &RightOperand,
bool &Overflow) {
182 return LeftOperand.
slt(RightOperand) ? RightOperand : LeftOperand;
186 const APInt &RightOperand,
bool &Overflow) {
188 if (
cantFail(
exprMax(LeftOperand, RightOperand, Overflow)) == LeftOperand)
208 if (!MaybeLeftOp || !MaybeRightOp) {
214 return std::move(Err);
217 APInt LeftOp = *MaybeLeftOp;
218 APInt RightOp = *MaybeRightOp;
223 unsigned NewBitWidth = std::max(LeftBitWidth, RightBitWidth);
224 LeftOp = LeftOp.
sext(NewBitWidth);
225 RightOp = RightOp.
sext(NewBitWidth);
235 LeftOp = LeftOp.
sext(NewBitWidth);
236 RightOp = RightOp.
sext(NewBitWidth);
244 if (!LeftFormat || !RightFormat) {
250 return std::move(Err);
255 *LeftFormat != *RightFormat)
258 "implicit format conflict between '" + LeftOperand->getExpressionStr() +
259 "' (" + LeftFormat->toString() +
") and '" +
260 RightOperand->getExpressionStr() +
"' (" + RightFormat->toString() +
261 "), need an explicit format specifier");
268 assert(ExpressionPointer->getAST() !=
nullptr &&
269 "Substituting empty expression");
274 return Format.getMatchingString(*EvaluatedValue);
285 return "\"" + std::move(*
Literal) +
"\"";
302 Result.reserve(VarVal->size() + 2);
313 const bool NeedsEscaping =
321 OS <<
" (escaped value)";
334 bool IsPseudo = Str[0] ==
'@';
337 if (Str[0] ==
'$' || IsPseudo)
343 (IsPseudo ?
"pseudo " :
"global ") +
349 for (
size_t E = Str.size();
I != E; ++
I)
351 if (Str[
I] !=
'_' && !isAlnum(Str[
I]))
385 if (ParseVarResult->IsPseudo)
387 SM,
Name,
"definition of pseudo numeric variable unsupported");
393 SM,
Name,
"string variable with name '" +
Name +
"' already exists");
398 SM, Expr,
"unexpected characters after numeric variable name");
401 auto VarTableIter =
Context->GlobalNumericVariableTable.find(
Name);
402 if (VarTableIter !=
Context->GlobalNumericVariableTable.end()) {
403 DefinedNumericVariable = VarTableIter->second;
406 SM, Expr,
"format different from previous variable definition");
408 DefinedNumericVariable =
409 Context->makeNumericVariable(
Name, ImplicitFormat, LineNumber);
411 return DefinedNumericVariable;
415 StringRef Name,
bool IsPseudo, std::optional<size_t> LineNumber,
417 if (IsPseudo &&
Name !=
"@LINE")
419 SM,
Name,
"invalid pseudo numeric variable '" +
Name +
"'");
430 Context->GlobalNumericVariableTable.try_emplace(
Name);
432 VarTableIter->second =
Context->makeNumericVariable(
437 if (DefLineNumber && LineNumber && *DefLineNumber == *LineNumber)
440 "numeric variable '" +
Name +
441 "' defined earlier in the same CHECK directive");
447 StringRef &Expr, AllowedOperand AO,
bool MaybeInvalidConstraint,
451 if (AO != AllowedOperand::Any)
453 SM, Expr,
"parenthesized expression not permitted here");
454 return parseParenExpr(Expr, LineNumber, Context, SM);
457 if (AO == AllowedOperand::LineVar || AO == AllowedOperand::Any) {
461 if (ParseVarResult) {
464 if (AO != AllowedOperand::Any)
466 "unexpected function call");
468 return parseCallExpr(Expr, ParseVarResult->Name, LineNumber, Context,
472 return parseNumericVariableUse(ParseVarResult->Name,
473 ParseVarResult->IsPseudo, LineNumber,
477 if (AO == AllowedOperand::LineVar)
487 if (!Expr.
consumeInteger((AO == AllowedOperand::LegacyLiteral) ? 10 : 0,
490 return std::make_unique<ExpressionLiteral>(SaveExpr.
drop_back(Expr.
size()),
496 (MaybeInvalidConstraint ?
"matching constraint or " :
"") +
501Pattern::parseParenExpr(
StringRef &Expr, std::optional<size_t> LineNumber,
514 Expr, AllowedOperand::Any,
false, LineNumber,
519 SubExprResult = parseBinop(OrigExpr, Expr, std::move(*SubExprResult),
false,
520 LineNumber, Context, SM);
524 return SubExprResult;
528 "missing ')' at end of nested expression");
530 return SubExprResult;
535 std::unique_ptr<ExpressionAST> LeftOp,
536 bool IsLegacyLineExpr, std::optional<size_t> LineNumber,
539 if (RemainingExpr.
empty())
540 return std::move(LeftOp);
561 if (RemainingExpr.
empty())
563 "missing operand in expression");
566 IsLegacyLineExpr ? AllowedOperand::LegacyLiteral : AllowedOperand::Any;
568 parseNumericOperand(RemainingExpr, AO,
false,
569 LineNumber, Context, SM);
571 return RightOpResult;
574 return std::make_unique<BinaryOperation>(Expr, EvalBinop, std::move(LeftOp),
575 std::move(*RightOpResult));
580 std::optional<size_t> LineNumber,
596 SM, FuncName,
Twine(
"call to undefined function '") + FuncName +
"'");
610 Expr, AllowedOperand::Any,
false, LineNumber,
612 while (Arg && !Expr.
empty()) {
619 Arg = parseBinop(OuterBinOpExpr, Expr, std::move(*Arg),
false, LineNumber,
626 Args.push_back(std::move(*Arg));
640 "missing ')' at end of call expression");
642 const unsigned NumArgs =
Args.size();
644 return std::make_unique<BinaryOperation>(Expr, *OptFunc, std::move(Args[0]),
649 Twine(
"function '") + FuncName +
650 Twine(
"' takes 2 arguments but ") +
651 Twine(NumArgs) +
" given");
655 StringRef Expr, std::optional<NumericVariable *> &DefinedNumericVariable,
656 bool IsLegacyLineExpr, std::optional<size_t> LineNumber,
658 std::unique_ptr<ExpressionAST> ExpressionASTPointer =
nullptr;
660 DefinedNumericVariable = std::nullopt;
662 unsigned Precision = 0;
665 size_t FormatSpecEnd = Expr.
find(
',');
666 size_t FunctionStart = Expr.
find(
'(');
667 if (FormatSpecEnd !=
StringRef::npos && FormatSpecEnd < FunctionStart) {
674 "invalid matching format specification in expression");
684 "invalid precision in format specifier");
687 if (!FormatExpr.
empty()) {
702 Precision, AlternateForm);
706 Precision, AlternateForm);
710 "invalid format specifier in expression");
717 SM, AlternateFormFlagLoc,
718 "alternate form only supported for hex values");
721 if (!FormatExpr.
empty())
724 "invalid matching format specification in expression");
728 size_t DefEnd = Expr.
find(
':');
730 DefExpr = Expr.
substr(0, DefEnd);
731 Expr = Expr.
substr(DefEnd + 1);
741 if (HasParsedValidConstraint)
743 SM, Expr,
"empty numeric expression should not have a constraint");
750 IsLegacyLineExpr ? AllowedOperand::LineVar : AllowedOperand::Any;
752 Expr, AO, !HasParsedValidConstraint, LineNumber,
Context, SM);
755 IsLegacyLineExpr, LineNumber,
Context, SM);
760 "unexpected characters at end of expression '" + Expr +
"'");
774 else if (ExpressionASTPointer) {
776 ExpressionASTPointer->getImplicitFormat(SM);
784 std::unique_ptr<Expression> ExpressionPointer =
785 std::make_unique<Expression>(std::move(ExpressionASTPointer),
Format);
791 DefExpr,
Context, LineNumber, ExpressionPointer->getFormat(), SM);
798 return std::move(ExpressionPointer);
810 PatternStr = PatternStr.
rtrim(
" \t");
815 "found empty check string with prefix '" + Prefix +
":'");
822 "found non-empty check string for empty check with prefix '" + Prefix +
834 FixedStr = PatternStr;
839 if (!MatchFullLinesHere &&
840 (PatternStr.
size() < 2 ||
842 FixedStr = PatternStr;
846 if (MatchFullLinesHere) {
854 unsigned CurParen = 1;
858 while (!PatternStr.
empty()) {
862 size_t End = PatternStr.
find(
"}}");
866 "found start of regex string with no end '}}'");
874 bool HasAlternation = PatternStr.
contains(
'|');
875 if (HasAlternation) {
880 if (AddRegExToRegEx(PatternStr.
substr(2,
End - 2), CurParen, SM))
903 size_t End = FindRegexVarEnd(UnparsedPatternStr, SM);
910 "Invalid substitution block, no ]] found");
916 PatternStr = UnparsedPatternStr.
substr(
End + 2);
918 bool IsDefinition =
false;
919 bool SubstNeeded =
false;
922 bool IsLegacyLineExpr =
false;
926 std::string WildcardRegexp;
927 size_t SubstInsertIdx = RegExStr.size();
931 size_t VarEndIdx = MatchStr.
find(
':');
943 if (!ParseVarResult) {
948 bool IsPseudo = ParseVarResult->IsPseudo;
951 SubstNeeded = !IsDefinition;
956 "invalid name in string variable definition");
962 if (
Context->GlobalNumericVariableTable.contains(
Name)) {
965 "numeric variable with name '" +
Name +
"' already exists");
969 MatchRegexp = MatchStr;
972 MatchStr = OrigMatchStr;
973 IsLegacyLineExpr = IsNumBlock =
true;
975 if (!MatchStr.
empty()) {
978 "invalid name in string variable use");
987 std::unique_ptr<Expression> ExpressionPointer;
988 std::optional<NumericVariable *> DefinedNumericVariable;
992 IsLegacyLineExpr, LineNumber,
Context,
999 SubstNeeded = ExpressionPointer->getAST() !=
nullptr;
1000 if (DefinedNumericVariable) {
1001 IsDefinition =
true;
1002 DefName = (*DefinedNumericVariable)->getName();
1005 SubstStr = MatchStr;
1009 MatchRegexp = WildcardRegexp;
1019 NumericVariableMatch NumericVariableDefinition = {
1020 *DefinedNumericVariable, CurParen};
1021 NumericVariableDefs[DefName] = NumericVariableDefinition;
1026 Context->GlobalNumericVariableTable[DefName] =
1027 *DefinedNumericVariable;
1029 VariableDefs[DefName] = CurParen;
1036 Context->DefinedVariableTable[DefName] =
true;
1042 if (!MatchRegexp.
empty() && AddRegExToRegEx(MatchRegexp, CurParen, SM))
1053 decltype(VariableDefs)::iterator It;
1055 (It = VariableDefs.find(SubstStr)) != VariableDefs.end()) {
1056 unsigned CaptureParenGroup = It->second;
1057 if (CaptureParenGroup < 1 || CaptureParenGroup > 9) {
1060 "Can't back-reference more than 9 variables");
1063 AddBackrefToRegEx(CaptureParenGroup);
1069 ?
Context->makeNumericSubstitution(
1070 SubstStr, std::move(ExpressionPointer), SubstInsertIdx)
1071 :
Context->makeStringSubstitution(SubstStr, SubstInsertIdx);
1081 size_t FixedMatchEnd =
1082 std::min(PatternStr.
find(
"{{", 1), PatternStr.
find(
"[[", 1));
1084 PatternStr = PatternStr.
substr(FixedMatchEnd);
1087 if (MatchFullLinesHere) {
1099 if (!R.isValid(
Error)) {
1101 "invalid regex: " +
Error);
1105 RegExStr += RS.
str();
1106 CurParen += R.getNumMatches();
1110void Pattern::AddBackrefToRegEx(
unsigned BackrefNum) {
1111 assert(BackrefNum >= 1 && BackrefNum <= 9 &&
"Invalid backref number");
1112 std::string Backref = std::string(
"\\") + std::string(1,
'0' + BackrefNum);
1113 RegExStr += Backref;
1123 if (!FixedStr.
empty()) {
1127 return make_error<NotFoundError>();
1137 if (!Substitutions.empty()) {
1140 Context->LineVariable->setValue(
1141 APInt(
sizeof(*LineNumber) * 8, *LineNumber));
1143 size_t InsertOffset = 0;
1159 return ErrorDiagnostic::get(
1160 SM, Substitution->getFromString(),
1161 "unable to substitute variable or "
1162 "numeric expression: overflow error");
1165 return ErrorDiagnostic::get(SM, E.getVarName(),
1174 InsertOffset +=
Value->size();
1177 return std::move(Errs);
1180 RegExToMatch = TmpStr;
1187 if (!
Regex(RegExToMatch, Flags).
match(Buffer, &MatchInfo))
1188 return make_error<NotFoundError>();
1191 assert(!MatchInfo.
empty() &&
"Didn't get any match");
1195 for (
const auto &VariableDef : VariableDefs) {
1196 assert(VariableDef.second < MatchInfo.
size() &&
"Internal paren error");
1197 Context->GlobalVariableTable[VariableDef.first] =
1198 MatchInfo[VariableDef.second];
1206 TheMatch.
Pos = FullMatch.
data() - Buffer.
data() + MatchStartSkip;
1207 TheMatch.
Len = FullMatch.
size() - MatchStartSkip;
1210 for (
const auto &NumericVariableDef : NumericVariableDefs) {
1211 const NumericVariableMatch &NumericVariableMatch =
1212 NumericVariableDef.getValue();
1213 unsigned CaptureParenGroup = NumericVariableMatch.CaptureParenGroup;
1214 assert(CaptureParenGroup < MatchInfo.
size() &&
"Internal paren error");
1216 NumericVariableMatch.DefinedNumericVariable;
1218 StringRef MatchedValue = MatchInfo[CaptureParenGroup];
1227unsigned Pattern::computeMatchDistance(
StringRef Buffer)
const {
1235 if (ExampleString.empty())
1236 ExampleString = RegExStr;
1240 BufferPrefix = BufferPrefix.
split(
'\n').first;
1247 std::vector<FileCheckDiag> *Diags)
const {
1249 if (!Substitutions.empty()) {
1257 if (!MatchedValue) {
1264 OS << *MatchedValue;
1271 Diags->emplace_back(SM, CheckTy,
getLoc(), MatchTy,
1281 std::vector<FileCheckDiag> *Diags)
const {
1282 if (VariableDefs.empty() && NumericVariableDefs.
empty())
1290 for (
const auto &VariableDef : VariableDefs) {
1292 VC.Name = VariableDef.first;
1299 for (
const auto &VariableDef : NumericVariableDefs) {
1301 VC.Name = VariableDef.getKey();
1302 std::optional<StringRef> StrValue =
1303 VariableDef.getValue().DefinedNumericVariable->getStringValue();
1313 llvm::sort(VarCaptures, [](
const VarCapture &
A,
const VarCapture &
B) {
1316 assert(
A.Range.Start !=
B.Range.Start &&
1317 "unexpected overlapping variable captures");
1318 return A.Range.Start.getPointer() <
B.Range.Start.getPointer();
1321 for (
const VarCapture &VC : VarCaptures) {
1324 OS <<
"captured var \"" << VC.Name <<
"\"";
1326 Diags->emplace_back(SM, CheckTy,
getLoc(), MatchTy, VC.Range,
OS.str());
1335 StringRef Buffer,
size_t Pos,
size_t Len,
1336 std::vector<FileCheckDiag> *Diags,
1337 bool AdjustPrevDiags =
false) {
1342 if (AdjustPrevDiags) {
1343 SMLoc CheckLoc = Diags->rbegin()->CheckLoc;
1344 for (
auto I = Diags->rbegin(), E = Diags->rend();
1345 I != E &&
I->CheckLoc == CheckLoc; ++
I)
1346 I->MatchTy = MatchTy;
1348 Diags->emplace_back(SM, CheckTy, Loc, MatchTy,
Range);
1354 std::vector<FileCheckDiag> *Diags)
const {
1359 size_t NumLinesForward = 0;
1361 double BestQuality = 0;
1364 if (
size_t(4096) *
size_t(2048) <
1365 std::min(
size_t(4096), Buffer.
size()) *
1366 std::max(FixedStr.
size(), RegExStr.size()))
1370 for (
size_t i = 0, e = std::min(
size_t(4096), Buffer.
size()); i != e; ++i) {
1371 if (Buffer[i] ==
'\n')
1376 if (Buffer[i] ==
' ' || Buffer[i] ==
'\t')
1381 unsigned Distance = computeMatchDistance(Buffer.
substr(i));
1382 double Quality = Distance + (NumLinesForward / 100.);
1386 BestQuality = Quality;
1398 "possible intended match here");
1407 auto VarIter = GlobalVariableTable.find(VarName);
1408 if (VarIter == GlobalVariableTable.end())
1409 return make_error<UndefVarError>(VarName);
1411 return VarIter->second;
1414template <
class... Types>
1416 NumericVariables.push_back(std::make_unique<NumericVariable>(
args...));
1417 return NumericVariables.back().get();
1421FileCheckPatternContext::makeStringSubstitution(
StringRef VarName,
1423 Substitutions.push_back(
1424 std::make_unique<StringSubstitution>(
this, VarName, InsertIdx));
1425 return Substitutions.back().get();
1428Substitution *FileCheckPatternContext::makeNumericSubstitution(
1431 Substitutions.push_back(std::make_unique<NumericSubstitution>(
1432 this, ExpressionStr, std::move(
Expression), InsertIdx));
1433 return Substitutions.back().get();
1440 size_t BracketDepth = 0;
1442 while (!Str.empty()) {
1443 if (Str.starts_with(
"]]") && BracketDepth == 0)
1445 if (Str[0] ==
'\\') {
1447 Str = Str.substr(2);
1457 if (BracketDepth == 0) {
1460 "missing closing \"]\" for regex variable");
1466 Str = Str.substr(1);
1481 if (
Ptr <=
End - 2 &&
Ptr[0] ==
'\r' &&
Ptr[1] ==
'\n') {
1494 while (
Ptr + 1 !=
End && (
Ptr[1] ==
' ' ||
Ptr[1] ==
'\t'))
1507 : CheckTy(CheckTy), CheckLoc(CheckLoc), MatchTy(MatchTy),
Note(
Note) {
1517 return (isAlnum(c) || c ==
'-' || c ==
'_');
1521 assert(Count > 0 &&
"zero and negative counts are not supported");
1523 "count supported only for plain CHECK directives");
1529 if (Modifiers.none())
1534 if (isLiteralMatch())
1542 auto WithModifiers = [
this, Prefix](
StringRef Str) -> std::string {
1543 return (Prefix + Str + getModifiersDescription()).str();
1550 return "misspelled";
1553 return WithModifiers(
"-COUNT");
1554 return WithModifiers(
"");
1556 return WithModifiers(
"-NEXT");
1558 return WithModifiers(
"-SAME");
1560 return WithModifiers(
"-NOT");
1562 return WithModifiers(
"-DAG");
1564 return WithModifiers(
"-LABEL");
1566 return WithModifiers(
"-EMPTY");
1568 return std::string(Prefix);
1570 return "implicit EOF";
1579static std::pair<Check::FileCheckType, StringRef>
1582 if (Buffer.
size() <= Prefix.size())
1595 -> std::pair<Check::FileCheckType, StringRef> {
1604 Rest = Rest.
ltrim();
1606 Ret.setLiteralMatch();
1610 Rest = Rest.
ltrim();
1620 if (Rest.
front() ==
'{')
1633 if (Count <= 0 || Count > INT32_MAX)
1635 if (Rest.
front() !=
':' && Rest.
front() !=
'{')
1637 return ConsumeModifiers(
1669static std::pair<Check::FileCheckType, StringRef>
1671 bool Misspelled =
false;
1707 for (
StringRef Prefix : CommentPrefixes)
1712 [](
auto A,
auto B) {
return A.first.size() >
B.first.size(); });
1720 "Buffer must be suffix of Input");
1724 for (
auto &[Prefix, Pos] : Prefixes) {
1730 (Match.
empty() ||
size_t(Match.
data() - Input.
data()) > Pos))
1760static std::pair<StringRef, StringRef>
1762 StringRef &Buffer,
unsigned &LineNumber,
1764 while (!Buffer.
empty()) {
1772 Prefix.data() < Buffer.
data() + Buffer.
size() &&
1773 "Prefix doesn't start inside of buffer!");
1774 size_t Loc = Prefix.data() - Buffer.
data();
1777 LineNumber += Skipped.
count(
'\n');
1787 std::tie(CheckTy, AfterSuffix) =
FindCheckType(Req, Buffer, Prefix);
1791 return {Prefix, AfterSuffix};
1805 assert(!LineVariable &&
"@LINE pseudo numeric variable already created");
1807 LineVariable = makeNumericVariable(
1809 GlobalNumericVariableTable[LineName] = LineVariable;
1819 std::pair<unsigned, unsigned> *ImpPatBufferIDRange) {
1820 if (ImpPatBufferIDRange)
1821 ImpPatBufferIDRange->first = ImpPatBufferIDRange->second = 0;
1824 PatternContext->defineCmdlineVariables(Req.
GlobalDefines, SM);
1830 PatternContext->createLineVariable();
1832 std::vector<FileCheckString::DagNotPrefixInfo> ImplicitNegativeChecks;
1836 std::string Prefix =
"-implicit-check-not='";
1837 std::string Suffix =
"'";
1839 (Prefix + PatternString + Suffix).str(),
"command line");
1842 CmdLine->getBuffer().
substr(Prefix.size(), PatternString.
size());
1844 if (ImpPatBufferIDRange) {
1845 if (ImpPatBufferIDRange->first == ImpPatBufferIDRange->second) {
1846 ImpPatBufferIDRange->first = BufferID;
1847 ImpPatBufferIDRange->second = BufferID + 1;
1849 assert(BufferID == ImpPatBufferIDRange->second &&
1850 "expected consecutive source buffer IDs");
1851 ++ImpPatBufferIDRange->second;
1855 ImplicitNegativeChecks.emplace_back(
1858 ImplicitNegativeChecks.back().DagNotPat.parsePattern(
1859 PatternInBuffer,
"IMPLICIT-CHECK", SM, Req);
1862 std::vector<FileCheckString::DagNotPrefixInfo> DagNotMatches =
1863 ImplicitNegativeChecks;
1866 unsigned LineNumber = 1;
1870 std::set<StringRef> PrefixesNotFound(Req.
CheckPrefixes.begin(),
1872 const size_t DistinctPrefixes = PrefixesNotFound.size();
1879 std::tie(UsedPrefix, AfterSuffix) =
1881 if (UsedPrefix.
empty())
1884 PrefixesNotFound.erase(UsedPrefix);
1887 "Failed to move Buffer's start forward, or pointed prefix outside "
1891 "Parsing after suffix doesn't start inside of buffer!");
1894 const char *UsedPrefixStart = UsedPrefix.
data();
1904 AfterSuffix.
data() - UsedPrefix.
data());
1907 "misspelled directive '" + UsedDirective +
"'");
1914 "unsupported -NOT combo on prefix '" + UsedPrefix +
"'");
1921 "invalid count in -COUNT specification on prefix '" +
1939 Buffer = Buffer.
substr(EOL);
1946 Pattern P(CheckTy, PatternContext.get(), LineNumber);
1947 if (
P.parsePattern(PatternBuffer, UsedPrefix, SM, Req))
1954 "found '" + UsedPrefix +
"-LABEL:'"
1955 " with variable definition or use");
1962 CheckStrings.empty()) {
1968 "found '" + UsedPrefix +
"-" +
Type +
1969 "' without previous '" + UsedPrefix +
": line");
1975 DagNotMatches.emplace_back(
P, UsedPrefix);
1980 CheckStrings.emplace_back(std::move(
P), UsedPrefix, PatternLoc,
1981 std::move(DagNotMatches));
1982 DagNotMatches = ImplicitNegativeChecks;
1987 const bool NoPrefixesFound = PrefixesNotFound.size() == DistinctPrefixes;
1988 const bool SomePrefixesUnexpectedlyNotUsed =
1990 if ((NoPrefixesFound || SomePrefixesUnexpectedlyNotUsed) &&
1992 errs() <<
"error: no check strings found with prefix"
1993 << (PrefixesNotFound.size() > 1 ?
"es " :
" ");
1995 for (
StringRef MissingPrefix : PrefixesNotFound) {
1998 errs() <<
"\'" << MissingPrefix <<
":'";
2007 if (!DagNotMatches.empty()) {
2008 CheckStrings.emplace_back(
2011 std::move(DagNotMatches));
2024 std::vector<FileCheckDiag> *Diags) {
2026 bool HasError = !ExpectedMatch || MatchResult.
TheError;
2027 bool PrintDiag =
true;
2051 assert(!HasError &&
"expected to report more diagnostics for error");
2056 std::string Message =
formatv(
"{0}: {1} string found in input",
2058 (ExpectedMatch ?
"expected" :
"excluded"))
2061 Message +=
formatv(
" ({0} out of {1})", MatchedCount, Pat.
getCount()).str();
2078 Diags->emplace_back(SM, Pat.getCheckTy(), Loc,
2079 FileCheckDiag::MatchFoundErrorNote,
2080 E.getRange(), E.getMessage().str());
2092 bool VerboseVerbose,
2093 std::vector<FileCheckDiag> *Diags) {
2095 bool HasError = ExpectedMatch;
2096 bool HasPatternError =
false;
2102 std::move(MatchError),
2104 HasError = HasPatternError =
true;
2114 bool PrintDiag =
true;
2116 if (!VerboseVerbose)
2132 Buffer, 0, Buffer.
size(), Diags);
2136 Diags->emplace_back(SM, Pat.
getCheckTy(), Loc, MatchTy, NoteRange,
2141 assert(!HasError &&
"expected to report more diagnostics for error");
2147 if (!HasPatternError) {
2148 std::string Message =
formatv(
"{0}: {1} string not found in input",
2150 (ExpectedMatch ?
"expected" :
"excluded"))
2159 "scanning from here");
2177 std::vector<FileCheckDiag> *Diags) {
2179 return printMatch(ExpectedMatch, SM, Prefix, Loc, Pat, MatchedCount, Buffer,
2180 std::move(MatchResult), Req, Diags);
2181 return printNoMatch(ExpectedMatch, SM, Prefix, Loc, Pat, MatchedCount, Buffer,
2188 const char *&FirstNewLine) {
2189 unsigned NumNewLines = 0;
2204 if (NumNewLines == 1)
2205 FirstNewLine =
Range.begin();
2210 bool IsLabelScanMode,
size_t &MatchLen,
2212 std::vector<FileCheckDiag> *Diags)
const {
2214 std::vector<const DagNotPrefixInfo *> NotStrings;
2220 if (!IsLabelScanMode) {
2222 LastPos =
CheckDag(SM, Buffer, NotStrings, Req, Diags);
2228 size_t LastMatchEnd = LastPos;
2229 size_t FirstMatchPos = 0;
2240 Pat, i, MatchBuffer,
2241 std::move(MatchResult), Req, Diags)) {
2246 size_t MatchPos = MatchResult.
TheMatch->Pos;
2248 FirstMatchPos = LastPos + MatchPos;
2251 LastMatchEnd += MatchPos + MatchResult.
TheMatch->Len;
2254 MatchLen = LastMatchEnd - FirstMatchPos;
2258 if (!IsLabelScanMode) {
2259 size_t MatchPos = FirstMatchPos - LastPos;
2283 if (
CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2287 return FirstMatchPos;
2300 const char *FirstNewLine =
nullptr;
2303 if (NumNewLines == 0) {
2305 CheckName +
": is on the same line as previous match");
2307 "'next' match was here");
2309 "previous match ended here");
2313 if (NumNewLines != 1) {
2316 ": is not on the line after the previous match");
2318 "'next' match was here");
2320 "previous match ended here");
2322 "non-matching line after previous match is here");
2334 const char *FirstNewLine =
nullptr;
2337 if (NumNewLines != 0) {
2340 "-SAME: is not on the same line as the previous match");
2342 "'next' match was here");
2344 "previous match ended here");
2353 const std::vector<const DagNotPrefixInfo *> &NotStrings,
2355 bool DirectiveFail =
false;
2356 for (
auto NotInfo : NotStrings) {
2358 "Expect CHECK-NOT!");
2361 false, SM, NotInfo->DagNotPrefix,
2362 NotInfo->DagNotPat.getLoc(), NotInfo->DagNotPat, 1, Buffer,
2363 std::move(MatchResult), Req, Diags)) {
2365 DirectiveFail =
true;
2369 return DirectiveFail;
2374 std::vector<const DagNotPrefixInfo *> &NotStrings,
2376 std::vector<FileCheckDiag> *Diags)
const {
2381 size_t StartPos = 0;
2390 std::list<MatchRange> MatchRanges;
2395 PatItr != PatEnd; ++PatItr) {
2397 const StringRef DNPrefix = PatItr->DagNotPrefix;
2400 "Invalid CHECK-DAG or CHECK-NOT!");
2403 NotStrings.push_back(&*PatItr);
2410 size_t MatchLen = 0, MatchPos = StartPos;
2414 for (
auto MI = MatchRanges.begin(), ME = MatchRanges.end();
true; ++
MI) {
2422 std::move(MatchResult), Req, Diags)) {
2428 MatchLen = MatchResult.
TheMatch->Len;
2431 MatchPos += MatchResult.
TheMatch->Pos;
2432 MatchRange M{MatchPos, MatchPos + MatchLen};
2437 if (MatchRanges.empty())
2438 MatchRanges.insert(MatchRanges.end(), M);
2440 auto Block = MatchRanges.begin();
2447 bool Overlap =
false;
2448 for (;
MI != ME; ++
MI) {
2449 if (M.Pos <
MI->End) {
2452 Overlap =
MI->Pos < M.End;
2458 MatchRanges.insert(
MI, M);
2468 SMRange OldRange(OldStart, OldEnd);
2470 "match discarded, overlaps earlier DAG match here",
2473 SMLoc CheckLoc = Diags->rbegin()->CheckLoc;
2474 for (
auto I = Diags->rbegin(), E = Diags->rend();
2475 I != E &&
I->CheckLoc == CheckLoc; ++
I)
2488 if (std::next(PatItr) == PatEnd ||
2490 if (!NotStrings.empty()) {
2495 Buffer.
slice(StartPos, MatchRanges.begin()->Pos);
2496 if (
CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2503 StartPos = MatchRanges.rbegin()->End;
2505 MatchRanges.clear();
2514 for (
StringRef Prefix : SuppliedPrefixes) {
2515 if (Prefix.empty()) {
2516 errs() <<
"error: supplied " << Kind <<
" prefix must not be the empty "
2520 static const Regex Validator(
"^[a-zA-Z0-9_-]*$");
2521 if (!Validator.
match(Prefix)) {
2522 errs() <<
"error: supplied " << Kind <<
" prefix must start with a "
2523 <<
"letter and contain only alphanumeric characters, hyphens, and "
2524 <<
"underscores: '" << Prefix <<
"'\n";
2527 if (!UniquePrefixes.
insert(Prefix).second) {
2528 errs() <<
"error: supplied " << Kind <<
" prefix must be unique among "
2529 <<
"check and comment prefixes: '" << Prefix <<
"'\n";
2554 assert(GlobalVariableTable.empty() && GlobalNumericVariableTable.empty() &&
2555 "Overriding defined variable with command-line variable definitions");
2557 if (CmdlineDefines.
empty())
2565 std::string CmdlineDefsDiag;
2567 for (
StringRef CmdlineDef : CmdlineDefines) {
2568 std::string DefPrefix = (
"Global define #" +
Twine(++
I) +
": ").str();
2569 size_t EqIdx = CmdlineDef.find(
'=');
2571 CmdlineDefsIndices.
push_back(std::make_pair(CmdlineDefsDiag.size(), 0));
2575 if (CmdlineDef[0] ==
'#') {
2579 CmdlineDefsDiag += (DefPrefix + CmdlineDef +
" (parsed as: [[").str();
2580 std::string SubstitutionStr = std::string(CmdlineDef);
2581 SubstitutionStr[EqIdx] =
':';
2583 std::make_pair(CmdlineDefsDiag.size(), SubstitutionStr.size()));
2584 CmdlineDefsDiag += (SubstitutionStr +
Twine(
"]])\n")).str();
2586 CmdlineDefsDiag += DefPrefix;
2588 std::make_pair(CmdlineDefsDiag.size(), CmdlineDef.size()));
2589 CmdlineDefsDiag += (CmdlineDef +
"\n").str();
2596 std::unique_ptr<MemoryBuffer> CmdLineDefsDiagBuffer =
2598 StringRef CmdlineDefsDiagRef = CmdLineDefsDiagBuffer->getBuffer();
2601 for (std::pair<size_t, size_t> CmdlineDefIndices : CmdlineDefsIndices) {
2602 StringRef CmdlineDef = CmdlineDefsDiagRef.
substr(CmdlineDefIndices.first,
2603 CmdlineDefIndices.second);
2604 if (CmdlineDef.
empty()) {
2608 "missing equal sign in global definition"));
2613 if (CmdlineDef[0] ==
'#') {
2617 std::optional<NumericVariable *> DefinedNumericVariable;
2620 DefinedNumericVariable,
false,
2621 std::nullopt,
this, SM);
2622 if (!ExpressionResult) {
2626 std::unique_ptr<Expression>
Expression = std::move(*ExpressionResult);
2637 assert(DefinedNumericVariable &&
"No variable defined");
2638 (*DefinedNumericVariable)->setValue(*
Value);
2641 GlobalNumericVariableTable[(*DefinedNumericVariable)->getName()] =
2642 *DefinedNumericVariable;
2645 std::pair<StringRef, StringRef> CmdlineNameVal = CmdlineDef.
split(
'=');
2646 StringRef CmdlineName = CmdlineNameVal.first;
2647 StringRef OrigCmdlineName = CmdlineName;
2650 if (!ParseVarResult) {
2657 if (ParseVarResult->IsPseudo || !CmdlineName.
empty()) {
2660 SM, OrigCmdlineName,
2661 "invalid name in string variable definition '" +
2662 OrigCmdlineName +
"'"));
2669 if (GlobalNumericVariableTable.contains(
Name)) {
2672 "numeric variable with name '" +
2673 Name +
"' already exists"));
2676 GlobalVariableTable.insert(CmdlineNameVal);
2683 DefinedVariableTable[
Name] =
true;
2693 if (Var.first()[0] !=
'$')
2694 LocalPatternVars.
push_back(Var.first());
2702 for (
const auto &Var : GlobalNumericVariableTable)
2703 if (Var.first()[0] !=
'$') {
2704 Var.getValue()->clearValue();
2705 LocalNumericVars.
push_back(Var.first());
2708 for (
const auto &Var : LocalPatternVars)
2709 GlobalVariableTable.erase(Var);
2710 for (
const auto &Var : LocalNumericVars)
2711 GlobalNumericVariableTable.erase(Var);
2715 std::vector<FileCheckDiag> *Diags) {
2716 bool ChecksFailed =
false;
2718 unsigned i = 0, j = 0, e = CheckStrings.size();
2722 CheckRegion = Buffer;
2731 size_t MatchLabelLen = 0;
2732 size_t MatchLabelPos =
2733 CheckLabelStr.
Check(SM, Buffer,
true, MatchLabelLen, Req, Diags);
2738 CheckRegion = Buffer.
substr(0, MatchLabelPos + MatchLabelLen);
2739 Buffer = Buffer.
substr(MatchLabelPos + MatchLabelLen);
2747 PatternContext->clearLocalVars();
2749 for (; i != j; ++i) {
2754 size_t MatchLen = 0;
2756 CheckStr.
Check(SM, CheckRegion,
false, MatchLen, Req, Diags);
2759 ChecksFailed =
true;
2764 CheckRegion = CheckRegion.
substr(MatchPos + MatchLen);
2772 return !ChecksFailed;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
BlockVerifier::State From
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static std::pair< StringRef, StringRef > FindFirstMatchingPrefix(const FileCheckRequest &Req, PrefixMatcher &Matcher, StringRef &Buffer, unsigned &LineNumber, Check::FileCheckType &CheckTy)
Searches the buffer for the first prefix in the prefix regular expression.
static size_t SkipWord(StringRef Str, size_t Loc)
static char popFront(StringRef &S)
constexpr StringLiteral SpaceChars
static Error reportMatchResult(bool ExpectedMatch, const SourceMgr &SM, StringRef Prefix, SMLoc Loc, const Pattern &Pat, int MatchedCount, StringRef Buffer, Pattern::MatchResult MatchResult, const FileCheckRequest &Req, std::vector< FileCheckDiag > *Diags)
Returns either (1) ErrorSuccess if there was no error, or (2) ErrorReported if an error was reported.
static Error printNoMatch(bool ExpectedMatch, const SourceMgr &SM, StringRef Prefix, SMLoc Loc, const Pattern &Pat, int MatchedCount, StringRef Buffer, Error MatchError, bool VerboseVerbose, std::vector< FileCheckDiag > *Diags)
Returns either (1) ErrorSuccess if there was no error, or (2) ErrorReported if an error was reported,...
static std::pair< Check::FileCheckType, StringRef > FindCheckType(const FileCheckRequest &Req, StringRef Buffer, StringRef Prefix, bool &Misspelled)
static const char * DefaultCheckPrefixes[]
static const char * DefaultCommentPrefixes[]
static SMRange ProcessMatchResult(FileCheckDiag::MatchType MatchTy, const SourceMgr &SM, SMLoc Loc, Check::FileCheckType CheckTy, StringRef Buffer, size_t Pos, size_t Len, std::vector< FileCheckDiag > *Diags, bool AdjustPrevDiags=false)
static unsigned CountNumNewlinesBetween(StringRef Range, const char *&FirstNewLine)
Counts the number of newlines in the specified range.
static APInt toSigned(APInt AbsVal, bool Negative)
static Error printMatch(bool ExpectedMatch, const SourceMgr &SM, StringRef Prefix, SMLoc Loc, const Pattern &Pat, int MatchedCount, StringRef Buffer, Pattern::MatchResult MatchResult, const FileCheckRequest &Req, std::vector< FileCheckDiag > *Diags)
Returns either (1) ErrorSuccess if there was no error or (2) ErrorReported if an error was reported,...
static bool ValidatePrefixes(StringRef Kind, StringSet<> &UniquePrefixes, ArrayRef< StringRef > SuppliedPrefixes)
static void addDefaultPrefixes(FileCheckRequest &Req)
static unsigned nextAPIntBitWidth(unsigned BitWidth)
static bool IsPartOfWord(char c)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
StringSet - A set-like wrapper for the StringMap.
Class for arbitrary precision integers.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
APInt abs() const
Get the absolute value.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool isNegative() const
Determine sign of this APInt.
LLVM_ABI APInt sadd_ov(const APInt &RHS, bool &Overflow) const
LLVM_ABI APInt sdiv_ov(const APInt &RHS, bool &Overflow) const
static constexpr unsigned APINT_BITS_PER_WORD
Bits in a word.
LLVM_ABI APInt smul_ov(const APInt &RHS, bool &Overflow) const
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
bool isSignBitSet() const
Determine if sign bit of this APInt is set.
bool slt(const APInt &RHS) const
Signed less than comparison.
LLVM_ABI APInt ssub_ov(const APInt &RHS, bool &Overflow) const
LLVM_ABI void toString(SmallVectorImpl< char > &Str, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false) const
Converts an APInt to a string and append it to Str.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool empty() const
empty - Check if the array is empty.
Expected< ExpressionFormat > getImplicitFormat(const SourceMgr &SM) const override
Expected< APInt > eval() const override
Evaluates the value of the binary operation represented by this AST, using EvalBinop on the result of...
LLVM_ABI std::string getDescription(StringRef Prefix) const
bool isLiteralMatch() const
LLVM_ABI std::string getModifiersDescription() const
LLVM_ABI FileCheckType & setCount(int C)
Class to represent an error holding a diagnostic with location information used when printing it.
StringRef getMessage() const
static LLVM_ABI_FOR_TEST char ID
void log(raw_ostream &OS) const override
Print diagnostic associated with this error when printing the error.
static Error get(const SourceMgr &SM, SMLoc Loc, const Twine &ErrMsg, SMRange Range=std::nullopt)
An error that has already been reported.
static Error reportedOrSuccess(bool HasErrorReported)
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
virtual Expected< APInt > eval() const =0
Evaluates and.
StringRef getExpressionStr() const
Class representing an expression and its matching format.
ExpressionAST * getAST() const
Class holding the Pattern global state, shared by all patterns: tables holding values of variables an...
LLVM_ABI_FOR_TEST Error defineCmdlineVariables(ArrayRef< StringRef > CmdlineDefines, SourceMgr &SM)
Defines string and numeric variables from definitions given on the command line, passed as a vector o...
LLVM_ABI_FOR_TEST void createLineVariable()
Create @LINE pseudo variable.
LLVM_ABI_FOR_TEST Expected< StringRef > getPatternVarValue(StringRef VarName)
LLVM_ABI_FOR_TEST void clearLocalVars()
Undefines local variables (variables whose name does not start with a '$' sign), i....
LLVM_ABI bool readCheckFile(SourceMgr &SM, StringRef Buffer, std::pair< unsigned, unsigned > *ImpPatBufferIDRange=nullptr)
Reads the check file from Buffer and records the expected strings it contains.
LLVM_ABI StringRef CanonicalizeFile(MemoryBuffer &MB, SmallVectorImpl< char > &OutputBuffer)
Canonicalizes whitespaces in the file.
LLVM_ABI FileCheck(FileCheckRequest Req)
LLVM_ABI bool checkInput(SourceMgr &SM, StringRef Buffer, std::vector< FileCheckDiag > *Diags=nullptr)
Checks the input to FileCheck provided in the Buffer against the expected strings read from the check...
LLVM_ABI bool ValidateCheckPrefixes()
This interface provides simple read-only access to a block of memory, and provides simple methods for...
size_t getBufferSize() const
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
const char * getBufferEnd() const
const char * getBufferStart() const
static LLVM_ABI_FOR_TEST char ID
Expected< std::string > getResultForDiagnostics() const override
Expected< std::string > getResultRegex() const override
Expected< APInt > eval() const override
Class representing a numeric variable and its associated current value.
void setValue(APInt NewValue, std::optional< StringRef > NewStrValue=std::nullopt)
Sets value of this numeric variable to NewValue, and sets the input buffer string from which it was p...
ExpressionFormat getImplicitFormat() const
std::optional< APInt > getValue() const
std::optional< size_t > getDefLineNumber() const
This is a utility class that provides an abstraction for the common functionality between Instruction...
Class to represent an overflow error that might result when manipulating a value.
static LLVM_ABI_FOR_TEST char ID
This class represents success/failure for parsing-like operations that find it important to chain tog...
static LLVM_ABI_FOR_TEST Expected< VariableProperties > parseVariable(StringRef &Str, const SourceMgr &SM)
Parses the string at the start of Str for a variable name.
LLVM_ABI_FOR_TEST MatchResult match(StringRef Buffer, const SourceMgr &SM) const
Matches the pattern string against the input buffer Buffer.
void printFuzzyMatch(const SourceMgr &SM, StringRef Buffer, std::vector< FileCheckDiag > *Diags) const
void printSubstitutions(const SourceMgr &SM, StringRef Buffer, SMRange MatchRange, FileCheckDiag::MatchType MatchTy, std::vector< FileCheckDiag > *Diags) const
Prints the value of successful substitutions.
static LLVM_ABI_FOR_TEST Expected< std::unique_ptr< Expression > > parseNumericSubstitutionBlock(StringRef Expr, std::optional< NumericVariable * > &DefinedNumericVariable, bool IsLegacyLineExpr, std::optional< size_t > LineNumber, FileCheckPatternContext *Context, const SourceMgr &SM)
Parses Expr for a numeric substitution block at line LineNumber, or before input is parsed if LineNum...
LLVM_ABI_FOR_TEST void printVariableDefs(const SourceMgr &SM, FileCheckDiag::MatchType MatchTy, std::vector< FileCheckDiag > *Diags) const
static LLVM_ABI_FOR_TEST bool isValidVarNameStart(char C)
Check::FileCheckType getCheckTy() const
LLVM_ABI_FOR_TEST bool parsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM, const FileCheckRequest &Req)
Parses the pattern in PatternStr and initializes this Pattern instance accordingly.
@ Newline
Compile for newline-sensitive matching.
@ IgnoreCase
Compile for matching that ignores upper/lower case distinctions.
static LLVM_ABI std::string escape(StringRef String)
Turn String into a regex by escaping its special characters.
LLVM_ABI bool match(StringRef String, SmallVectorImpl< StringRef > *Matches=nullptr, std::string *Error=nullptr) const
matches - Match the regex against a given String.
Represents a location in source code.
static SMLoc getFromPointer(const char *Ptr)
Represents a range in source code.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void reserve(size_type N)
void push_back(const T &Elt)
pointer data()
Return a pointer to the vector's buffer, even if empty().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
LLVM_ABI std::pair< unsigned, unsigned > getLineAndColumn(SMLoc Loc, unsigned BufferID=0) const
Find the line and column number for the specified location in the specified file.
LLVM_ABI void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges={}, ArrayRef< SMFixIt > FixIts={}, bool ShowColors=true) const
Emit a message about the specified location with the specified string.
unsigned AddNewSourceBuffer(std::unique_ptr< MemoryBuffer > F, SMLoc IncludeLoc)
Add a new source buffer to this source manager.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
StringMapEntry - This is used to represent one value that is inserted into a StringMap.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool consumeInteger(unsigned Radix, T &Result)
Parse the current string as an integer of the specified radix.
std::string str() const
str - Get the contents as an std::string.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
LLVM_ABI unsigned edit_distance(StringRef Other, bool AllowReplacements=true, unsigned MaxEditDistance=0) const
Determine the edit distance between this string and another string.
char back() const
back - Get the last character in the string.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
constexpr size_t size() const
size - Get the string size.
char front() const
front - Get the first character in the string.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
StringRef ltrim(char Char) const
Return string with consecutive Char characters starting from the the left removed.
bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
bool consume_front(StringRef Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
size_t find_first_of(char C, size_t From=0) const
Find the first character in the string that is C, or npos if not found.
StringRef rtrim(char Char) const
Return string with consecutive Char characters starting from the right removed.
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
StringRef trim(char Char) const
Return string with consecutive Char characters starting from the left and right removed.
LLVM_ABI size_t find_insensitive(char C, size_t From=0) const
Search for the first character C in the string, ignoring case.
size_t count(char C) const
Return the number of occurrences of C in the string.
static constexpr size_t npos
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
LLVM_ABI size_t find_first_not_of(char C, size_t From=0) const
Find the first character in the string that is not C or npos if not found.
StringSet - A wrapper for StringMap that provides set-like functionality.
void insert_range(Range &&R)
std::pair< typename Base::iterator, bool > insert(StringRef key)
Expected< std::string > getResultRegex() const override
Expected< std::string > getResultForDiagnostics() const override
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
Class representing a substitution to perform in the RegExStr string.
StringRef getFromString() const
FileCheckPatternContext * Context
Pointer to a class instance holding, among other things, the table with the values of live string var...
virtual Expected< std::string > getResultRegex() const =0
virtual Expected< std::string > getResultForDiagnostics() const =0
StringRef FromStr
The string that needs to be substituted for something else.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
Class to represent an undefined variable error, which quotes that variable's name when printed.
static LLVM_ABI_FOR_TEST char ID
LLVM Value Representation.
raw_ostream & write_escaped(StringRef Str, bool UseHexEscapes=false)
Output Str, turning '\', '\t', ' ', '"', and anything that doesn't satisfy llvm::isPrint into an esca...
A raw_ostream that writes to an std::string.
A raw_ostream that writes to an SmallVector or SmallString.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ C
The default llvm calling convention, compatible with C.
@ CheckBadNot
Marks when parsing found a -NOT check combined with another CHECK suffix.
@ CheckBadCount
Marks when parsing found a -COUNT directive with invalid count value.
@ CheckEOF
Indicates the pattern only matches the end of file.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
LLVM_ABI_FOR_TEST Expected< APInt > exprAdd(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
Performs operation and.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
Error joinErrors(Error E1, Error E2)
Concatenate errors.
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI_FOR_TEST Expected< APInt > exprMul(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
constexpr unsigned BitWidth
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Expected< APInt > exprMax(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
LLVM_ABI_FOR_TEST Expected< APInt > exprDiv(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
Expected< APInt > exprMin(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
LLVM_ABI_FOR_TEST Expected< APInt > exprSub(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
void consumeError(Error Err)
Consume a Error without doing anything.
Implement std::hash so that hash_code can be used in STL containers.
StringRef match(StringRef Buffer)
Find the next match of a prefix in Buffer.
SmallVector< std::pair< StringRef, size_t > > Prefixes
Prefixes and their first occurrence past the current position.
PrefixMatcher(ArrayRef< StringRef > CheckPrefixes, ArrayRef< StringRef > CommentPrefixes, StringRef Input)
unsigned InputStartLine
The search range if MatchTy starts with MatchNone, or the match range otherwise.
LLVM_ABI FileCheckDiag(const SourceMgr &SM, const Check::FileCheckType &CheckTy, SMLoc CheckLoc, MatchType MatchTy, SMRange InputRange, StringRef Note="")
MatchType
What type of match result does this diagnostic describe?
@ MatchFoundButWrongLine
Indicates a match for an expected pattern, but the match is on the wrong line.
@ MatchNoneAndExcluded
Indicates no match for an excluded pattern.
@ MatchFoundButExcluded
Indicates a match for an excluded pattern.
@ MatchFuzzy
Indicates a fuzzy match that serves as a suggestion for the next intended match for an expected patte...
@ MatchFoundButDiscarded
Indicates a discarded match for an expected pattern.
@ MatchNoneForInvalidPattern
Indicates no match due to an expected or excluded pattern that has proven to be invalid at match time...
@ MatchFoundAndExpected
Indicates a good match for an expected pattern.
@ MatchNoneButExpected
Indicates no match for an expected pattern, but this might follow good matches when multiple matches ...
Contains info about various FileCheck options.
bool IsDefaultCheckPrefix
std::vector< StringRef > GlobalDefines
bool NoCanonicalizeWhiteSpace
std::vector< StringRef > ImplicitCheckNot
std::vector< StringRef > CommentPrefixes
std::vector< StringRef > CheckPrefixes
bool AllowDeprecatedDagOverlap
A check that we found in the input file.
bool CheckNext(const SourceMgr &SM, StringRef Buffer) const
Verifies that there is a single line in the given Buffer.
Pattern Pat
The pattern to match.
bool CheckSame(const SourceMgr &SM, StringRef Buffer) const
Verifies that there is no newline in the given Buffer.
std::vector< DagNotPrefixInfo > DagNotStrings
Hold the DAG/NOT strings occurring in the input file.
SMLoc Loc
The location in the match file that the check string was specified.
StringRef Prefix
Which prefix name this check matched.
size_t CheckDag(const SourceMgr &SM, StringRef Buffer, std::vector< const DagNotPrefixInfo * > &NotStrings, const FileCheckRequest &Req, std::vector< FileCheckDiag > *Diags) const
Matches "dag strings" and their mixed "not strings".
size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode, size_t &MatchLen, FileCheckRequest &Req, std::vector< FileCheckDiag > *Diags) const
Matches check string and its "not strings" and/or "dag strings".
bool CheckNot(const SourceMgr &SM, StringRef Buffer, const std::vector< const DagNotPrefixInfo * > &NotStrings, const FileCheckRequest &Req, std::vector< FileCheckDiag > *Diags) const
Verifies that none of the strings in NotStrings are found in the given Buffer.
std::optional< Match > TheMatch
Parsing information about a variable.