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");
91 AbsoluteValue = *SignedValue;
96 AbsoluteValue = *UnsignedValue;
99 std::string AbsoluteValueStr;
103 AbsoluteValueStr = utostr(AbsoluteValue);
111 "trying to match value with invalid format");
116 if (Precision > AbsoluteValueStr.size()) {
117 unsigned LeadingZeros = Precision - AbsoluteValueStr.size();
118 return (
Twine(SignPrefix) +
Twine(AlternateFormPrefix) +
119 std::string(LeadingZeros,
'0') + AbsoluteValueStr)
123 return (
Twine(SignPrefix) +
Twine(AlternateFormPrefix) + AbsoluteValueStr)
136 StringRef IntegerParseErrorStr =
"unable to represent numeric value";
140 if (StrVal.getAsInteger(10, SignedValue))
148 bool MissingFormPrefix = AlternateForm && !StrVal.consume_front(
"0x");
149 if (StrVal.getAsInteger(Hex ? 16 : 10, UnsignedValue))
154 if (MissingFormPrefix)
166 memcpy(&SignedValue, &UnsignedValue,
sizeof(SignedValue));
175 return make_error<OverflowError>();
178 return static_cast<int64_t
>(
Value);
183 return make_error<OverflowError>();
193 int64_t MaxInt64 = std::numeric_limits<int64_t>::max();
195 if (SignedValue >= -MaxInt64)
199 SignedValue += MaxInt64;
200 uint64_t RemainingValueAbsolute = -SignedValue;
209 std::optional<int64_t> Result = checkedAdd<int64_t>(LeftValue, RightValue);
211 return make_error<OverflowError>();
227 std::optional<uint64_t> Result =
228 checkedAddUnsigned<uint64_t>(LeftValue, RightValue);
230 return make_error<OverflowError>();
242 if (RightValue > (
uint64_t)std::numeric_limits<int64_t>::max())
243 return make_error<OverflowError>();
244 std::optional<int64_t> Result =
245 checkedSub(LeftValue,
static_cast<int64_t
>(RightValue));
247 return make_error<OverflowError>();
263 if (LeftValue >= RightValue)
267 uint64_t MaxInt64 = std::numeric_limits<int64_t>::max();
271 int64_t Result = -MaxInt64;
272 int64_t MinInt64 = std::numeric_limits<int64_t>::min();
276 return make_error<OverflowError>();
293 return RightOperand * LeftOperand;
309 std::optional<uint64_t> Result =
310 checkedMulUnsigned<uint64_t>(LeftValue, RightValue);
312 return make_error<OverflowError>();
325 return make_error<OverflowError>();
359 if (
cantFail(
max(LeftOperand, RightOperand)) == LeftOperand)
379 if (!LeftOp || !RightOp) {
385 return std::move(Err);
388 return EvalBinop(*LeftOp, *RightOp);
395 if (!LeftFormat || !RightFormat) {
401 return std::move(Err);
406 *LeftFormat != *RightFormat)
409 "implicit format conflict between '" + LeftOperand->getExpressionStr() +
410 "' (" + LeftFormat->toString() +
") and '" +
411 RightOperand->getExpressionStr() +
"' (" + RightFormat->toString() +
412 "), need an explicit format specifier");
419 assert(ExpressionPointer->getAST() !=
nullptr &&
420 "Substituting empty expression");
422 ExpressionPointer->getAST()->eval();
426 return Format.getMatchingString(*EvaluatedValue);
445 bool IsPseudo = Str[0] ==
'@';
448 if (Str[0] ==
'$' || IsPseudo)
454 for (
size_t E = Str.size();
I !=
E; ++
I)
456 if (Str[
I] !=
'_' && !isAlnum(Str[
I]))
490 if (ParseVarResult->IsPseudo)
492 SM,
Name,
"definition of pseudo numeric variable unsupported");
497 Context->DefinedVariableTable.end())
499 SM,
Name,
"string variable with name '" +
Name +
"' already exists");
504 SM, Expr,
"unexpected characters after numeric variable name");
507 auto VarTableIter =
Context->GlobalNumericVariableTable.find(
Name);
508 if (VarTableIter !=
Context->GlobalNumericVariableTable.end()) {
509 DefinedNumericVariable = VarTableIter->second;
512 SM, Expr,
"format different from previous variable definition");
514 DefinedNumericVariable =
515 Context->makeNumericVariable(
Name, ImplicitFormat, LineNumber);
517 return DefinedNumericVariable;
521 StringRef Name,
bool IsPseudo, std::optional<size_t> LineNumber,
523 if (IsPseudo && !
Name.equals(
"@LINE"))
525 SM,
Name,
"invalid pseudo numeric variable '" +
Name +
"'");
535 auto VarTableIter =
Context->GlobalNumericVariableTable.find(
Name);
537 if (VarTableIter !=
Context->GlobalNumericVariableTable.end())
546 if (DefLineNumber && LineNumber && *DefLineNumber == *LineNumber)
549 "numeric variable '" +
Name +
550 "' defined earlier in the same CHECK directive");
556 StringRef &Expr, AllowedOperand AO,
bool MaybeInvalidConstraint,
560 if (AO != AllowedOperand::Any)
562 SM, Expr,
"parenthesized expression not permitted here");
563 return parseParenExpr(Expr, LineNumber, Context, SM);
566 if (AO == AllowedOperand::LineVar || AO == AllowedOperand::Any) {
570 if (ParseVarResult) {
573 if (AO != AllowedOperand::Any)
575 "unexpected function call");
577 return parseCallExpr(Expr, ParseVarResult->Name, LineNumber, Context,
581 return parseNumericVariableUse(ParseVarResult->Name,
582 ParseVarResult->IsPseudo, LineNumber,
586 if (AO == AllowedOperand::LineVar)
593 int64_t SignedLiteralValue;
597 if (!Expr.
consumeInteger((AO == AllowedOperand::LegacyLiteral) ? 10 : 0,
598 UnsignedLiteralValue))
599 return std::make_unique<ExpressionLiteral>(SaveExpr.
drop_back(Expr.
size()),
600 UnsignedLiteralValue);
602 if (AO == AllowedOperand::Any && !Expr.
consumeInteger(0, SignedLiteralValue))
603 return std::make_unique<ExpressionLiteral>(SaveExpr.
drop_back(Expr.
size()),
609 (MaybeInvalidConstraint ?
"matching constraint or " :
"") +
614Pattern::parseParenExpr(
StringRef &Expr, std::optional<size_t> LineNumber,
627 Expr, AllowedOperand::Any,
false, LineNumber,
632 SubExprResult = parseBinop(OrigExpr, Expr, std::move(*SubExprResult),
false,
633 LineNumber, Context, SM);
637 return SubExprResult;
641 "missing ')' at end of nested expression");
643 return SubExprResult;
648 std::unique_ptr<ExpressionAST> LeftOp,
649 bool IsLegacyLineExpr, std::optional<size_t> LineNumber,
652 if (RemainingExpr.
empty())
653 return std::move(LeftOp);
662 EvalBinop =
operator+;
665 EvalBinop =
operator-;
674 if (RemainingExpr.
empty())
676 "missing operand in expression");
679 IsLegacyLineExpr ? AllowedOperand::LegacyLiteral : AllowedOperand::Any;
681 parseNumericOperand(RemainingExpr, AO,
false,
682 LineNumber, Context, SM);
684 return RightOpResult;
687 return std::make_unique<BinaryOperation>(Expr, EvalBinop, std::move(LeftOp),
688 std::move(*RightOpResult));
693 std::optional<size_t> LineNumber,
699 .
Case(
"add",
operator+)
700 .
Case(
"div",
operator/)
703 .
Case(
"mul",
operator*)
704 .
Case(
"sub",
operator-)
709 SM, FuncName,
Twine(
"call to undefined function '") + FuncName +
"'");
723 Expr, AllowedOperand::Any,
false, LineNumber,
732 Arg = parseBinop(OuterBinOpExpr, Expr, std::move(*
Arg),
false, LineNumber,
738 return Arg.takeError();
739 Args.push_back(std::move(*
Arg));
753 "missing ')' at end of call expression");
755 const unsigned NumArgs =
Args.size();
757 return std::make_unique<BinaryOperation>(Expr, *OptFunc, std::move(Args[0]),
762 Twine(
"function '") + FuncName +
763 Twine(
"' takes 2 arguments but ") +
764 Twine(NumArgs) +
" given");
768 StringRef Expr, std::optional<NumericVariable *> &DefinedNumericVariable,
769 bool IsLegacyLineExpr, std::optional<size_t> LineNumber,
771 std::unique_ptr<ExpressionAST> ExpressionASTPointer =
nullptr;
773 DefinedNumericVariable = std::nullopt;
775 unsigned Precision = 0;
778 size_t FormatSpecEnd = Expr.
find(
',');
779 size_t FunctionStart = Expr.
find(
'(');
780 if (FormatSpecEnd !=
StringRef::npos && FormatSpecEnd < FunctionStart) {
787 "invalid matching format specification in expression");
797 "invalid precision in format specifier");
800 if (!FormatExpr.
empty()) {
815 Precision, AlternateForm);
819 Precision, AlternateForm);
823 "invalid format specifier in expression");
830 SM, AlternateFormFlagLoc,
831 "alternate form only supported for hex values");
834 if (!FormatExpr.
empty())
837 "invalid matching format specification in expression");
841 size_t DefEnd = Expr.
find(
':');
843 DefExpr = Expr.
substr(0, DefEnd);
844 Expr = Expr.
substr(DefEnd + 1);
849 bool HasParsedValidConstraint =
false;
851 HasParsedValidConstraint =
true;
856 if (HasParsedValidConstraint)
858 SM, Expr,
"empty numeric expression should not have a constraint");
865 IsLegacyLineExpr ? AllowedOperand::LineVar : AllowedOperand::Any;
867 Expr, AO, !HasParsedValidConstraint, LineNumber,
Context, SM);
868 while (ParseResult && !Expr.
empty()) {
869 ParseResult = parseBinop(OuterBinOpExpr, Expr, std::move(*ParseResult),
870 IsLegacyLineExpr, LineNumber,
Context, SM);
872 if (ParseResult && IsLegacyLineExpr && !Expr.
empty())
875 "unexpected characters at end of expression '" + Expr +
"'");
879 ExpressionASTPointer = std::move(*ParseResult);
889 else if (ExpressionASTPointer) {
891 ExpressionASTPointer->getImplicitFormat(SM);
899 std::unique_ptr<Expression> ExpressionPointer =
900 std::make_unique<Expression>(std::move(ExpressionASTPointer),
Format);
906 DefExpr,
Context, LineNumber, ExpressionPointer->getFormat(), SM);
910 DefinedNumericVariable = *ParseResult;
913 return std::move(ExpressionPointer);
925 while (!PatternStr.
empty() &&
926 (PatternStr.
back() ==
' ' || PatternStr.
back() ==
'\t'))
927 PatternStr = PatternStr.
substr(0, PatternStr.
size() - 1);
932 "found empty check string with prefix '" + Prefix +
":'");
939 "found non-empty check string for empty check with prefix '" + Prefix +
951 FixedStr = PatternStr;
956 if (!MatchFullLinesHere &&
957 (PatternStr.
size() < 2 ||
959 FixedStr = PatternStr;
963 if (MatchFullLinesHere) {
971 unsigned CurParen = 1;
975 while (!PatternStr.
empty()) {
979 size_t End = PatternStr.
find(
"}}");
983 "found start of regex string with no end '}}'");
994 if (AddRegExToRegEx(PatternStr.
substr(2, End - 2), CurParen, SM))
998 PatternStr = PatternStr.
substr(End + 2);
1016 size_t End = FindRegexVarEnd(UnparsedPatternStr, SM);
1023 "Invalid substitution block, no ]] found");
1029 PatternStr = UnparsedPatternStr.
substr(End + 2);
1031 bool IsDefinition =
false;
1032 bool SubstNeeded =
false;
1035 bool IsLegacyLineExpr =
false;
1039 std::string WildcardRegexp;
1040 size_t SubstInsertIdx = RegExStr.size();
1044 size_t VarEndIdx = MatchStr.
find(
':');
1056 if (!ParseVarResult) {
1061 bool IsPseudo = ParseVarResult->IsPseudo;
1064 SubstNeeded = !IsDefinition;
1069 "invalid name in string variable definition");
1075 if (
Context->GlobalNumericVariableTable.find(
Name) !=
1076 Context->GlobalNumericVariableTable.end()) {
1079 "numeric variable with name '" +
Name +
"' already exists");
1083 MatchRegexp = MatchStr;
1086 MatchStr = OrigMatchStr;
1087 IsLegacyLineExpr = IsNumBlock =
true;
1089 if (!MatchStr.
empty()) {
1092 "invalid name in string variable use");
1101 std::unique_ptr<Expression> ExpressionPointer;
1102 std::optional<NumericVariable *> DefinedNumericVariable;
1106 IsLegacyLineExpr, LineNumber,
Context,
1112 ExpressionPointer = std::move(*ParseResult);
1113 SubstNeeded = ExpressionPointer->getAST() !=
nullptr;
1114 if (DefinedNumericVariable) {
1115 IsDefinition =
true;
1116 DefName = (*DefinedNumericVariable)->getName();
1119 SubstStr = MatchStr;
1123 MatchRegexp = WildcardRegexp;
1133 NumericVariableMatch NumericVariableDefinition = {
1134 *DefinedNumericVariable, CurParen};
1135 NumericVariableDefs[DefName] = NumericVariableDefinition;
1140 Context->GlobalNumericVariableTable[DefName] =
1141 *DefinedNumericVariable;
1143 VariableDefs[DefName] = CurParen;
1150 Context->DefinedVariableTable[DefName] =
true;
1156 if (!MatchRegexp.
empty() && AddRegExToRegEx(MatchRegexp, CurParen, SM))
1167 if (!IsNumBlock && VariableDefs.find(SubstStr) != VariableDefs.end()) {
1168 unsigned CaptureParenGroup = VariableDefs[SubstStr];
1169 if (CaptureParenGroup < 1 || CaptureParenGroup > 9) {
1172 "Can't back-reference more than 9 variables");
1175 AddBackrefToRegEx(CaptureParenGroup);
1181 ?
Context->makeNumericSubstitution(
1182 SubstStr, std::move(ExpressionPointer), SubstInsertIdx)
1183 :
Context->makeStringSubstitution(SubstStr, SubstInsertIdx);
1193 size_t FixedMatchEnd =
1194 std::min(PatternStr.
find(
"{{", 1), PatternStr.
find(
"[[", 1));
1196 PatternStr = PatternStr.
substr(FixedMatchEnd);
1199 if (MatchFullLinesHere) {
1211 if (!R.isValid(
Error)) {
1213 "invalid regex: " +
Error);
1217 RegExStr += RS.
str();
1218 CurParen += R.getNumMatches();
1222void Pattern::AddBackrefToRegEx(
unsigned BackrefNum) {
1223 assert(BackrefNum >= 1 && BackrefNum <= 9 &&
"Invalid backref number");
1224 std::string Backref = std::string(
"\\") + std::string(1,
'0' + BackrefNum);
1225 RegExStr += Backref;
1235 if (!FixedStr.
empty()) {
1239 return make_error<NotFoundError>();
1249 if (!Substitutions.empty()) {
1254 size_t InsertOffset = 0;
1270 return ErrorDiagnostic::get(
1271 SM, Substitution->getFromString(),
1272 "unable to substitute variable or "
1273 "numeric expression: overflow error");
1276 return ErrorDiagnostic::get(SM, E.getVarName(),
1285 InsertOffset +=
Value->size();
1288 return std::move(Errs);
1291 RegExToMatch = TmpStr;
1298 if (!
Regex(RegExToMatch, Flags).
match(Buffer, &MatchInfo))
1299 return make_error<NotFoundError>();
1302 assert(!MatchInfo.
empty() &&
"Didn't get any match");
1306 for (
const auto &VariableDef : VariableDefs) {
1307 assert(VariableDef.second < MatchInfo.
size() &&
"Internal paren error");
1308 Context->GlobalVariableTable[VariableDef.first] =
1309 MatchInfo[VariableDef.second];
1317 TheMatch.
Pos = FullMatch.
data() - Buffer.
data() + MatchStartSkip;
1318 TheMatch.
Len = FullMatch.
size() - MatchStartSkip;
1321 for (
const auto &NumericVariableDef : NumericVariableDefs) {
1322 const NumericVariableMatch &NumericVariableMatch =
1323 NumericVariableDef.getValue();
1324 unsigned CaptureParenGroup = NumericVariableMatch.CaptureParenGroup;
1325 assert(CaptureParenGroup < MatchInfo.
size() &&
"Internal paren error");
1327 NumericVariableMatch.DefinedNumericVariable;
1329 StringRef MatchedValue = MatchInfo[CaptureParenGroup];
1332 Format.valueFromStringRepr(MatchedValue, SM);
1341unsigned Pattern::computeMatchDistance(
StringRef Buffer)
const {
1349 if (ExampleString.empty())
1350 ExampleString = RegExStr;
1354 BufferPrefix = BufferPrefix.
split(
'\n').first;
1361 std::vector<FileCheckDiag> *Diags)
const {
1363 if (!Substitutions.empty()) {
1370 if (!MatchedValue) {
1384 Diags->emplace_back(SM, CheckTy,
getLoc(), MatchTy,
1385 SMRange(Range.Start, Range.Start), OS.
str());
1394 std::vector<FileCheckDiag> *Diags)
const {
1395 if (VariableDefs.empty() && NumericVariableDefs.
empty())
1403 for (
const auto &VariableDef : VariableDefs) {
1405 VC.Name = VariableDef.first;
1409 VC.Range =
SMRange(Start, End);
1412 for (
const auto &VariableDef : NumericVariableDefs) {
1414 VC.Name = VariableDef.getKey();
1415 std::optional<StringRef> StrValue =
1416 VariableDef.getValue().DefinedNumericVariable->getStringValue();
1421 VC.Range =
SMRange(Start, End);
1426 llvm::sort(VarCaptures, [](
const VarCapture &
A,
const VarCapture &
B) {
1429 assert(
A.Range.Start !=
B.Range.Start &&
1430 "unexpected overlapping variable captures");
1431 return A.Range.Start.getPointer() <
B.Range.Start.getPointer();
1434 for (
const VarCapture &VC : VarCaptures) {
1437 OS <<
"captured var \"" << VC.Name <<
"\"";
1439 Diags->emplace_back(SM, CheckTy,
getLoc(), MatchTy, VC.Range, OS.
str());
1448 StringRef Buffer,
size_t Pos,
size_t Len,
1449 std::vector<FileCheckDiag> *Diags,
1450 bool AdjustPrevDiags =
false) {
1455 if (AdjustPrevDiags) {
1456 SMLoc CheckLoc = Diags->rbegin()->CheckLoc;
1457 for (
auto I = Diags->rbegin(),
E = Diags->rend();
1458 I !=
E &&
I->CheckLoc == CheckLoc; ++
I)
1459 I->MatchTy = MatchTy;
1461 Diags->emplace_back(SM, CheckTy, Loc, MatchTy, Range);
1467 std::vector<FileCheckDiag> *Diags)
const {
1472 size_t NumLinesForward = 0;
1474 double BestQuality = 0;
1477 for (
size_t i = 0, e = std::min(
size_t(4096), Buffer.
size()); i != e; ++i) {
1478 if (Buffer[i] ==
'\n')
1483 if (Buffer[i] ==
' ' || Buffer[i] ==
'\t')
1488 unsigned Distance = computeMatchDistance(Buffer.
substr(i));
1489 double Quality = Distance + (NumLinesForward / 100.);
1493 BestQuality = Quality;
1505 "possible intended match here");
1514 auto VarIter = GlobalVariableTable.find(VarName);
1515 if (VarIter == GlobalVariableTable.end())
1516 return make_error<UndefVarError>(VarName);
1518 return VarIter->second;
1521template <
class... Types>
1523 NumericVariables.push_back(std::make_unique<NumericVariable>(
args...));
1524 return NumericVariables.back().get();
1528FileCheckPatternContext::makeStringSubstitution(
StringRef VarName,
1530 Substitutions.push_back(
1531 std::make_unique<StringSubstitution>(
this, VarName, InsertIdx));
1532 return Substitutions.back().get();
1535Substitution *FileCheckPatternContext::makeNumericSubstitution(
1538 Substitutions.push_back(std::make_unique<NumericSubstitution>(
1539 this, ExpressionStr, std::move(
Expression), InsertIdx));
1540 return Substitutions.back().get();
1547 size_t BracketDepth = 0;
1549 while (!Str.empty()) {
1550 if (Str.startswith(
"]]") && BracketDepth == 0)
1552 if (Str[0] ==
'\\') {
1554 Str = Str.substr(2);
1564 if (BracketDepth == 0) {
1567 "missing closing \"]\" for regex variable");
1573 Str = Str.substr(1);
1588 if (
Ptr <= End - 2 &&
Ptr[0] ==
'\r' &&
Ptr[1] ==
'\n') {
1601 while (
Ptr + 1 != End && (
Ptr[1] ==
' ' ||
Ptr[1] ==
'\t'))
1614 : CheckTy(CheckTy), CheckLoc(CheckLoc), MatchTy(MatchTy),
Note(
Note) {
1624 return (isAlnum(c) || c ==
'-' || c ==
'_');
1628 assert(Count > 0 &&
"zero and negative counts are not supported");
1630 "count supported only for plain CHECK directives");
1636 if (Modifiers.none())
1641 if (isLiteralMatch())
1649 auto WithModifiers = [
this, Prefix](
StringRef Str) -> std::string {
1650 return (Prefix + Str + getModifiersDescription()).str();
1657 return "misspelled";
1660 return WithModifiers(
"-COUNT");
1661 return WithModifiers(
"");
1663 return WithModifiers(
"-NEXT");
1665 return WithModifiers(
"-SAME");
1667 return WithModifiers(
"-NOT");
1669 return WithModifiers(
"-DAG");
1671 return WithModifiers(
"-LABEL");
1673 return WithModifiers(
"-EMPTY");
1675 return std::string(Prefix);
1677 return "implicit EOF";
1686static std::pair<Check::FileCheckType, StringRef>
1689 if (Buffer.
size() <= Prefix.size())
1702 -> std::pair<Check::FileCheckType, StringRef> {
1711 Rest = Rest.
ltrim();
1713 Ret.setLiteralMatch();
1717 Rest = Rest.
ltrim();
1727 if (Rest.
front() ==
'{')
1740 if (Count <= 0 || Count > INT32_MAX)
1742 if (Rest.
front() !=
':' && Rest.
front() !=
'{')
1744 return ConsumeModifiers(
1776static std::pair<Check::FileCheckType, StringRef>
1778 bool Misspelled =
false;
1815static std::pair<StringRef, StringRef>
1817 StringRef &Buffer,
unsigned &LineNumber,
1821 while (!Buffer.
empty()) {
1823 if (!PrefixRE.
match(Buffer, &Matches))
1831 Prefix.data() < Buffer.
data() + Buffer.
size() &&
1832 "Prefix doesn't start inside of buffer!");
1833 size_t Loc = Prefix.data() - Buffer.
data();
1836 LineNumber += Skipped.
count(
'\n');
1846 std::tie(CheckTy, AfterSuffix) =
FindCheckType(Req, Buffer, Prefix);
1850 return {Prefix, AfterSuffix};
1864 assert(!LineVariable &&
"@LINE pseudo numeric variable already created");
1866 LineVariable = makeNumericVariable(
1868 GlobalNumericVariableTable[LineName] = LineVariable;
1879 std::pair<unsigned, unsigned> *ImpPatBufferIDRange) {
1880 if (ImpPatBufferIDRange)
1881 ImpPatBufferIDRange->first = ImpPatBufferIDRange->second = 0;
1884 PatternContext->defineCmdlineVariables(Req.
GlobalDefines, SM);
1890 PatternContext->createLineVariable();
1892 std::vector<Pattern> ImplicitNegativeChecks;
1896 std::string Prefix =
"-implicit-check-not='";
1897 std::string Suffix =
"'";
1899 (Prefix + PatternString + Suffix).str(),
"command line");
1902 CmdLine->getBuffer().
substr(Prefix.size(), PatternString.
size());
1904 if (ImpPatBufferIDRange) {
1905 if (ImpPatBufferIDRange->first == ImpPatBufferIDRange->second) {
1906 ImpPatBufferIDRange->first = BufferID;
1907 ImpPatBufferIDRange->second = BufferID + 1;
1909 assert(BufferID == ImpPatBufferIDRange->second &&
1910 "expected consecutive source buffer IDs");
1911 ++ImpPatBufferIDRange->second;
1915 ImplicitNegativeChecks.push_back(
1917 ImplicitNegativeChecks.back().parsePattern(PatternInBuffer,
1918 "IMPLICIT-CHECK", SM, Req);
1921 std::vector<Pattern> DagNotMatches = ImplicitNegativeChecks;
1925 unsigned LineNumber = 1;
1927 std::set<StringRef> PrefixesNotFound(Req.
CheckPrefixes.begin(),
1929 const size_t DistinctPrefixes = PrefixesNotFound.size();
1936 std::tie(UsedPrefix, AfterSuffix) =
1938 if (UsedPrefix.
empty())
1941 PrefixesNotFound.erase(UsedPrefix);
1944 "Failed to move Buffer's start forward, or pointed prefix outside "
1948 "Parsing after suffix doesn't start inside of buffer!");
1951 const char *UsedPrefixStart = UsedPrefix.
data();
1961 AfterSuffix.
data() - UsedPrefix.
data());
1964 "misspelled directive '" + UsedDirective +
"'");
1971 "unsupported -NOT combo on prefix '" + UsedPrefix +
"'");
1978 "invalid count in -COUNT specification on prefix '" +
1996 Buffer = Buffer.
substr(EOL);
2003 Pattern P(CheckTy, PatternContext.get(), LineNumber);
2004 if (
P.parsePattern(PatternBuffer, UsedPrefix, SM, Req))
2011 "found '" + UsedPrefix +
"-LABEL:'"
2012 " with variable definition or use");
2019 CheckStrings->empty()) {
2025 "found '" + UsedPrefix +
"-" +
Type +
2026 "' without previous '" + UsedPrefix +
": line");
2032 DagNotMatches.push_back(
P);
2037 CheckStrings->emplace_back(
P, UsedPrefix, PatternLoc);
2038 std::swap(DagNotMatches, CheckStrings->back().DagNotStrings);
2039 DagNotMatches = ImplicitNegativeChecks;
2044 const bool NoPrefixesFound = PrefixesNotFound.size() == DistinctPrefixes;
2045 const bool SomePrefixesUnexpectedlyNotUsed =
2047 if ((NoPrefixesFound || SomePrefixesUnexpectedlyNotUsed) &&
2049 errs() <<
"error: no check strings found with prefix"
2050 << (PrefixesNotFound.size() > 1 ?
"es " :
" ");
2052 for (
StringRef MissingPrefix : PrefixesNotFound) {
2055 errs() <<
"\'" << MissingPrefix <<
":'";
2064 if (!DagNotMatches.empty()) {
2065 CheckStrings->emplace_back(
2068 std::swap(DagNotMatches, CheckStrings->back().DagNotStrings);
2081 std::vector<FileCheckDiag> *Diags) {
2083 bool HasError = !ExpectedMatch || MatchResult.
TheError;
2084 bool PrintDiag =
true;
2108 assert(!HasError &&
"expected to report more diagnostics for error");
2113 std::string Message =
formatv(
"{0}: {1} string found in input",
2115 (ExpectedMatch ?
"expected" :
"excluded"))
2118 Message +=
formatv(
" ({0} out of {1})", MatchedCount, Pat.
getCount()).str();
2135 Diags->emplace_back(SM, Pat.getCheckTy(), Loc,
2136 FileCheckDiag::MatchFoundErrorNote,
2137 E.getRange(), E.getMessage().str());
2149 bool VerboseVerbose,
2150 std::vector<FileCheckDiag> *Diags) {
2152 bool HasError = ExpectedMatch;
2153 bool HasPatternError =
false;
2159 std::move(MatchError),
2161 HasError = HasPatternError =
true;
2171 bool PrintDiag =
true;
2173 if (!VerboseVerbose)
2189 Buffer, 0, Buffer.
size(), Diags);
2193 Diags->emplace_back(SM, Pat.
getCheckTy(), Loc, MatchTy, NoteRange,
2198 assert(!HasError &&
"expected to report more diagnostics for error");
2204 if (!HasPatternError) {
2205 std::string Message =
formatv(
"{0}: {1} string not found in input",
2207 (ExpectedMatch ?
"expected" :
"excluded"))
2216 "scanning from here");
2234 std::vector<FileCheckDiag> *Diags) {
2236 return printMatch(ExpectedMatch, SM, Prefix, Loc, Pat, MatchedCount, Buffer,
2237 std::move(MatchResult), Req, Diags);
2238 return printNoMatch(ExpectedMatch, SM, Prefix, Loc, Pat, MatchedCount, Buffer,
2245 const char *&FirstNewLine) {
2246 unsigned NumNewLines = 0;
2249 Range = Range.substr(Range.find_first_of(
"\n\r"));
2256 if (Range.size() > 1 && (Range[1] ==
'\n' || Range[1] ==
'\r') &&
2257 (Range[0] != Range[1]))
2258 Range = Range.substr(1);
2259 Range = Range.substr(1);
2261 if (NumNewLines == 1)
2262 FirstNewLine = Range.begin();
2267 bool IsLabelScanMode,
size_t &MatchLen,
2269 std::vector<FileCheckDiag> *Diags)
const {
2271 std::vector<const Pattern *> NotStrings;
2277 if (!IsLabelScanMode) {
2279 LastPos =
CheckDag(SM, Buffer, NotStrings, Req, Diags);
2285 size_t LastMatchEnd = LastPos;
2286 size_t FirstMatchPos = 0;
2297 Pat, i, MatchBuffer,
2298 std::move(MatchResult), Req, Diags)) {
2303 size_t MatchPos = MatchResult.
TheMatch->Pos;
2305 FirstMatchPos = LastPos + MatchPos;
2308 LastMatchEnd += MatchPos + MatchResult.
TheMatch->Len;
2311 MatchLen = LastMatchEnd - FirstMatchPos;
2315 if (!IsLabelScanMode) {
2316 size_t MatchPos = FirstMatchPos - LastPos;
2340 if (
CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2344 return FirstMatchPos;
2357 const char *FirstNewLine =
nullptr;
2360 if (NumNewLines == 0) {
2362 CheckName +
": is on the same line as previous match");
2364 "'next' match was here");
2366 "previous match ended here");
2370 if (NumNewLines != 1) {
2373 ": is not on the line after the previous match");
2375 "'next' match was here");
2377 "previous match ended here");
2379 "non-matching line after previous match is here");
2391 const char *FirstNewLine =
nullptr;
2394 if (NumNewLines != 0) {
2397 "-SAME: is not on the same line as the previous match");
2399 "'next' match was here");
2401 "previous match ended here");
2409 const std::vector<const Pattern *> &NotStrings,
2411 std::vector<FileCheckDiag> *Diags)
const {
2412 bool DirectiveFail =
false;
2418 std::move(MatchResult), Req, Diags)) {
2420 DirectiveFail =
true;
2424 return DirectiveFail;
2428 std::vector<const Pattern *> &NotStrings,
2430 std::vector<FileCheckDiag> *Diags)
const {
2435 size_t StartPos = 0;
2444 std::list<MatchRange> MatchRanges;
2449 PatItr != PatEnd; ++PatItr) {
2453 "Invalid CHECK-DAG or CHECK-NOT!");
2456 NotStrings.push_back(&
Pat);
2463 size_t MatchLen = 0, MatchPos = StartPos;
2467 for (
auto MI = MatchRanges.begin(), ME = MatchRanges.end();
true; ++
MI) {
2475 std::move(MatchResult), Req, Diags)) {
2481 MatchLen = MatchResult.
TheMatch->Len;
2484 MatchPos += MatchResult.
TheMatch->Pos;
2485 MatchRange M{MatchPos, MatchPos + MatchLen};
2490 if (MatchRanges.empty())
2491 MatchRanges.insert(MatchRanges.end(), M);
2493 auto Block = MatchRanges.begin();
2500 bool Overlap =
false;
2501 for (;
MI != ME; ++
MI) {
2502 if (M.Pos <
MI->End) {
2505 Overlap =
MI->Pos < M.End;
2511 MatchRanges.insert(
MI, M);
2521 SMRange OldRange(OldStart, OldEnd);
2523 "match discarded, overlaps earlier DAG match here",
2526 SMLoc CheckLoc = Diags->rbegin()->CheckLoc;
2527 for (
auto I = Diags->rbegin(),
E = Diags->rend();
2528 I !=
E &&
I->CheckLoc == CheckLoc; ++
I)
2541 if (std::next(PatItr) == PatEnd ||
2543 if (!NotStrings.empty()) {
2548 Buffer.
slice(StartPos, MatchRanges.begin()->Pos);
2549 if (
CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2556 StartPos = MatchRanges.rbegin()->End;
2558 MatchRanges.clear();
2567 for (
StringRef Prefix : SuppliedPrefixes) {
2568 if (Prefix.empty()) {
2569 errs() <<
"error: supplied " << Kind <<
" prefix must not be the empty "
2573 static const Regex Validator(
"^[a-zA-Z0-9_-]*$");
2574 if (!Validator.
match(Prefix)) {
2575 errs() <<
"error: supplied " << Kind <<
" prefix must start with a "
2576 <<
"letter and contain only alphanumeric characters, hyphens, and "
2577 <<
"underscores: '" << Prefix <<
"'\n";
2580 if (!UniquePrefixes.
insert(Prefix).second) {
2581 errs() <<
"error: supplied " << Kind <<
" prefix must be unique among "
2582 <<
"check and comment prefixes: '" << Prefix <<
"'\n";
2597 UniquePrefixes.
insert(Prefix);
2601 UniquePrefixes.
insert(Prefix);
2633 PrefixRegexStr.
append(Prefix);
2636 return Regex(PrefixRegexStr);
2641 assert(GlobalVariableTable.empty() && GlobalNumericVariableTable.empty() &&
2642 "Overriding defined variable with command-line variable definitions");
2644 if (CmdlineDefines.
empty())
2652 std::string CmdlineDefsDiag;
2654 for (
StringRef CmdlineDef : CmdlineDefines) {
2655 std::string DefPrefix = (
"Global define #" +
Twine(++
I) +
": ").str();
2656 size_t EqIdx = CmdlineDef.find(
'=');
2658 CmdlineDefsIndices.
push_back(std::make_pair(CmdlineDefsDiag.size(), 0));
2662 if (CmdlineDef[0] ==
'#') {
2666 CmdlineDefsDiag += (DefPrefix + CmdlineDef +
" (parsed as: [[").str();
2667 std::string SubstitutionStr = std::string(CmdlineDef);
2668 SubstitutionStr[EqIdx] =
':';
2670 std::make_pair(CmdlineDefsDiag.size(), SubstitutionStr.size()));
2671 CmdlineDefsDiag += (SubstitutionStr +
Twine(
"]])\n")).str();
2673 CmdlineDefsDiag += DefPrefix;
2675 std::make_pair(CmdlineDefsDiag.size(), CmdlineDef.size()));
2676 CmdlineDefsDiag += (CmdlineDef +
"\n").str();
2683 std::unique_ptr<MemoryBuffer> CmdLineDefsDiagBuffer =
2685 StringRef CmdlineDefsDiagRef = CmdLineDefsDiagBuffer->getBuffer();
2688 for (std::pair<size_t, size_t> CmdlineDefIndices : CmdlineDefsIndices) {
2689 StringRef CmdlineDef = CmdlineDefsDiagRef.
substr(CmdlineDefIndices.first,
2690 CmdlineDefIndices.second);
2691 if (CmdlineDef.
empty()) {
2695 "missing equal sign in global definition"));
2700 if (CmdlineDef[0] ==
'#') {
2704 std::optional<NumericVariable *> DefinedNumericVariable;
2707 DefinedNumericVariable,
false,
2708 std::nullopt,
this, SM);
2709 if (!ExpressionResult) {
2713 std::unique_ptr<Expression>
Expression = std::move(*ExpressionResult);
2724 assert(DefinedNumericVariable &&
"No variable defined");
2725 (*DefinedNumericVariable)->setValue(*
Value);
2728 GlobalNumericVariableTable[(*DefinedNumericVariable)->getName()] =
2729 *DefinedNumericVariable;
2732 std::pair<StringRef, StringRef> CmdlineNameVal = CmdlineDef.
split(
'=');
2733 StringRef CmdlineName = CmdlineNameVal.first;
2734 StringRef OrigCmdlineName = CmdlineName;
2737 if (!ParseVarResult) {
2744 if (ParseVarResult->IsPseudo || !CmdlineName.
empty()) {
2747 SM, OrigCmdlineName,
2748 "invalid name in string variable definition '" +
2749 OrigCmdlineName +
"'"));
2756 if (GlobalNumericVariableTable.find(
Name) !=
2757 GlobalNumericVariableTable.end()) {
2760 "numeric variable with name '" +
2761 Name +
"' already exists"));
2764 GlobalVariableTable.insert(CmdlineNameVal);
2771 DefinedVariableTable[
Name] =
true;
2781 if (Var.first()[0] !=
'$')
2782 LocalPatternVars.
push_back(Var.first());
2790 for (
const auto &Var : GlobalNumericVariableTable)
2791 if (Var.first()[0] !=
'$') {
2792 Var.getValue()->clearValue();
2793 LocalNumericVars.
push_back(Var.first());
2796 for (
const auto &Var : LocalPatternVars)
2797 GlobalVariableTable.erase(Var);
2798 for (
const auto &Var : LocalNumericVars)
2799 GlobalNumericVariableTable.erase(Var);
2803 std::vector<FileCheckDiag> *Diags) {
2804 bool ChecksFailed =
false;
2806 unsigned i = 0, j = 0, e = CheckStrings->size();
2810 CheckRegion = Buffer;
2819 size_t MatchLabelLen = 0;
2820 size_t MatchLabelPos =
2821 CheckLabelStr.
Check(SM, Buffer,
true, MatchLabelLen, Req, Diags);
2826 CheckRegion = Buffer.
substr(0, MatchLabelPos + MatchLabelLen);
2827 Buffer = Buffer.
substr(MatchLabelPos + MatchLabelLen);
2835 PatternContext->clearLocalVars();
2837 for (; i != j; ++i) {
2842 size_t MatchLen = 0;
2844 CheckStr.
Check(SM, CheckRegion,
false, MatchLen, Req, Diags);
2847 ChecksFailed =
true;
2852 CheckRegion = CheckRegion.
substr(MatchPos + MatchLen);
2860 return !ChecksFailed;
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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 std::pair< StringRef, StringRef > FindFirstMatchingPrefix(const FileCheckRequest &Req, Regex &PrefixRE, StringRef &Buffer, unsigned &LineNumber, Check::FileCheckType &CheckTy)
Searches the buffer for the first prefix in the prefix regular expression.
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 int64_t getAsSigned(uint64_t UnsignedValue)
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 bool IsPartOfWord(char c)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
StringSet - A set-like wrapper for the StringMap.
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< ExpressionValue > eval() const override
Evaluates the value of the binary operation represented by this AST, using EvalBinop on the result of...
std::string getDescription(StringRef Prefix) const
bool isLiteralMatch() const
std::string getModifiersDescription() const
FileCheckType & setCount(int C)
Class to represent an error holding a diagnostic with location information used when printing it.
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< ExpressionValue > eval() const =0
Evaluates and.
StringRef getExpressionStr() const
Class representing a numeric value.
ExpressionValue getAbsolute() const
bool isNegative() const
Returns true if value is signed and negative, false otherwise.
Expected< int64_t > getSignedValue() const
Expected< uint64_t > getUnsignedValue() 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...
Error defineCmdlineVariables(ArrayRef< StringRef > CmdlineDefines, SourceMgr &SM)
Defines string and numeric variables from definitions given on the command line, passed as a vector o...
void createLineVariable()
Create @LINE pseudo variable.
Expected< StringRef > getPatternVarValue(StringRef VarName)
void clearLocalVars()
Undefines local variables (variables whose name does not start with a '$' sign), i....
StringRef CanonicalizeFile(MemoryBuffer &MB, SmallVectorImpl< char > &OutputBuffer)
Canonicalizes whitespaces in the file.
FileCheck(FileCheckRequest Req)
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...
bool readCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE, std::pair< unsigned, unsigned > *ImpPatBufferIDRange=nullptr)
Reads the check file from Buffer and records the expected strings it contains.
Regex buildCheckPrefixRegex()
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
Expected< std::string > getResult() const override
Expected< ExpressionValue > eval() const override
Class representing a numeric variable and its associated current value.
ExpressionFormat getImplicitFormat() const
std::optional< ExpressionValue > getValue() const
void setValue(ExpressionValue 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...
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 Expected< VariableProperties > parseVariable(StringRef &Str, const SourceMgr &SM)
Parses the string at the start of Str for a variable name.
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 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...
void printVariableDefs(const SourceMgr &SM, FileCheckDiag::MatchType MatchTy, std::vector< FileCheckDiag > *Diags) const
static bool isValidVarNameStart(char C)
Check::FileCheckType getCheckTy() const
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 std::string escape(StringRef String)
Turn String into a regex by escaping its special characters.
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...
void append(StringRef RHS)
Append from a StringRef.
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.
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.
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).
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.
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.
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 startswith(StringRef Prefix) const
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.
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.
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.
const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
StringSet - A wrapper for StringMap that provides set-like functionality.
std::pair< typename Base::iterator, bool > insert(StringRef key)
Expected< std::string > getResult() 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...
StringRef FromStr
The string that needs to be substituted for something else.
virtual Expected< std::string > getResult() const =0
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.
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.
std::string & str()
Returns the string's reference.
A raw_ostream that writes to an SmallVector or SmallString.
StringRef str() const
Return a StringRef for the vector contents.
#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.
void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
APInt operator*(APInt a, uint64_t RHS)
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.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Expected< ExpressionValue > min(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
Error joinErrors(Error E1, Error E2)
Concatenate errors.
void sort(IteratorTy Start, IteratorTy End)
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Expected< ExpressionValue > max(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
InstructionCost operator/(const InstructionCost &LHS, const InstructionCost &RHS)
std::enable_if_t< std::is_unsigned< T >::value, T > AbsoluteDifference(T X, T Y)
Subtract two unsigned integers, X and Y, of type T and return the absolute value of the result.
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.
APInt operator+(APInt a, const APInt &b)
std::enable_if_t< std::is_signed< T >::value, std::optional< T > > checkedSub(T LHS, T RHS)
Subtract two signed integers LHS and RHS.
void consumeError(Error Err)
Consume a Error without doing anything.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
unsigned InputStartLine
The search range if MatchTy starts with MatchNone, or the match range otherwise.
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.
size_t CheckDag(const SourceMgr &SM, StringRef Buffer, std::vector< const Pattern * > &NotStrings, const FileCheckRequest &Req, std::vector< FileCheckDiag > *Diags) const
Matches "dag strings" and their mixed "not strings".
SMLoc Loc
The location in the match file that the check string was specified.
StringRef Prefix
Which prefix name this check matched.
std::vector< Pattern > DagNotStrings
All of the strings that are disallowed from occurring between this match string and the previous one ...
bool CheckNot(const SourceMgr &SM, StringRef Buffer, const std::vector< const Pattern * > &NotStrings, const FileCheckRequest &Req, std::vector< FileCheckDiag > *Diags) const
Verifies that none of the strings in NotStrings are found in the given Buffer.
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".
std::optional< Match > TheMatch
Parsing information about a variable.