51 auto CreatePrecisionRegex = [&](
StringRef S) {
52 return (
Twine(AlternateFormPrefix) + S +
Twine(
'{') +
Twine(Precision) +
60 return CreatePrecisionRegex(
"([1-9][0-9]*)?[0-9]");
61 return std::string(
"[0-9]+");
64 return CreatePrecisionRegex(
"-?([1-9][0-9]*)?[0-9]");
65 return std::string(
"-?[0-9]+");
68 return CreatePrecisionRegex(
"([1-9A-F][0-9A-F]*)?[0-9A-F]");
69 return (
Twine(AlternateFormPrefix) +
Twine(
"[0-9A-F]+")).str();
72 return CreatePrecisionRegex(
"([1-9a-f][0-9a-f]*)?[0-9a-f]");
73 return (
Twine(AlternateFormPrefix) +
Twine(
"[0-9a-f]+")).str();
76 "trying to match value with invalid format");
83 return make_error<OverflowError>();
86 bool UpperCase =
false;
104 "trying to match value with invalid format");
106 IntValue.
abs().
toString(AbsoluteValueStr, Radix,
false,
112 if (Precision > AbsoluteValueStr.
size()) {
113 unsigned LeadingZeros = Precision - AbsoluteValueStr.
size();
114 return (
Twine(SignPrefix) +
Twine(AlternateFormPrefix) +
115 std::string(LeadingZeros,
'0') + AbsoluteValueStr)
119 return (
Twine(SignPrefix) +
Twine(AlternateFormPrefix) + AbsoluteValueStr)
131 APInt Result = AbsVal;
140 bool Negative = StrVal.consume_front(
"-");
142 bool MissingFormPrefix =
143 !ValueIsSigned && AlternateForm && !StrVal.consume_front(
"0x");
144 (void)MissingFormPrefix;
145 assert(!MissingFormPrefix &&
"missing alternate form prefix");
147 [[maybe_unused]]
bool ParseFailure =
148 StrVal.getAsInteger(Hex ? 16 : 10, ResultValue);
152 assert(!ParseFailure &&
"unable to represent numeric value");
153 return toSigned(ResultValue, Negative);
157 const APInt &RightOperand,
bool &Overflow) {
158 return LeftOperand.
sadd_ov(RightOperand, Overflow);
162 const APInt &RightOperand,
bool &Overflow) {
163 return LeftOperand.
ssub_ov(RightOperand, Overflow);
167 const APInt &RightOperand,
bool &Overflow) {
168 return LeftOperand.
smul_ov(RightOperand, Overflow);
172 const APInt &RightOperand,
bool &Overflow) {
174 if (RightOperand.
isZero())
175 return make_error<OverflowError>();
177 return LeftOperand.
sdiv_ov(RightOperand, Overflow);
181 const APInt &RightOperand,
bool &Overflow) {
183 return LeftOperand.
slt(RightOperand) ? RightOperand : LeftOperand;
187 const APInt &RightOperand,
bool &Overflow) {
189 if (
cantFail(
exprMax(LeftOperand, RightOperand, Overflow)) == LeftOperand)
209 if (!MaybeLeftOp || !MaybeRightOp) {
215 return std::move(Err);
218 APInt LeftOp = *MaybeLeftOp;
219 APInt RightOp = *MaybeRightOp;
224 unsigned NewBitWidth = std::max(LeftBitWidth, RightBitWidth);
225 LeftOp = LeftOp.
sext(NewBitWidth);
226 RightOp = RightOp.
sext(NewBitWidth);
236 LeftOp = LeftOp.
sext(NewBitWidth);
237 RightOp = RightOp.
sext(NewBitWidth);
245 if (!LeftFormat || !RightFormat) {
251 return std::move(Err);
256 *LeftFormat != *RightFormat)
259 "implicit format conflict between '" + LeftOperand->getExpressionStr() +
260 "' (" + LeftFormat->toString() +
") and '" +
261 RightOperand->getExpressionStr() +
"' (" + RightFormat->toString() +
262 "), need an explicit format specifier");
269 assert(ExpressionPointer->getAST() !=
nullptr &&
270 "Substituting empty expression");
275 return Format.getMatchingString(*EvaluatedValue);
294 bool IsPseudo = Str[0] ==
'@';
297 if (Str[0] ==
'$' || IsPseudo)
303 (IsPseudo ?
"pseudo " :
"global ") +
309 for (
size_t E = Str.size();
I != E; ++
I)
311 if (Str[
I] !=
'_' && !isAlnum(Str[
I]))
345 if (ParseVarResult->IsPseudo)
347 SM,
Name,
"definition of pseudo numeric variable unsupported");
353 SM,
Name,
"string variable with name '" +
Name +
"' already exists");
358 SM, Expr,
"unexpected characters after numeric variable name");
361 auto VarTableIter = Context->GlobalNumericVariableTable.find(
Name);
362 if (VarTableIter != Context->GlobalNumericVariableTable.end()) {
363 DefinedNumericVariable = VarTableIter->second;
366 SM, Expr,
"format different from previous variable definition");
368 DefinedNumericVariable =
369 Context->makeNumericVariable(
Name, ImplicitFormat, LineNumber);
371 return DefinedNumericVariable;
375 StringRef Name,
bool IsPseudo, std::optional<size_t> LineNumber,
377 if (IsPseudo &&
Name !=
"@LINE")
379 SM,
Name,
"invalid pseudo numeric variable '" +
Name +
"'");
389 auto VarTableIter = Context->GlobalNumericVariableTable.find(
Name);
391 if (VarTableIter != Context->GlobalNumericVariableTable.end())
400 if (DefLineNumber && LineNumber && *DefLineNumber == *LineNumber)
403 "numeric variable '" +
Name +
404 "' defined earlier in the same CHECK directive");
410 StringRef &Expr, AllowedOperand AO,
bool MaybeInvalidConstraint,
414 if (AO != AllowedOperand::Any)
416 SM, Expr,
"parenthesized expression not permitted here");
417 return parseParenExpr(Expr, LineNumber, Context, SM);
420 if (AO == AllowedOperand::LineVar || AO == AllowedOperand::Any) {
424 if (ParseVarResult) {
427 if (AO != AllowedOperand::Any)
429 "unexpected function call");
431 return parseCallExpr(Expr, ParseVarResult->Name, LineNumber, Context,
435 return parseNumericVariableUse(ParseVarResult->Name,
436 ParseVarResult->IsPseudo, LineNumber,
440 if (AO == AllowedOperand::LineVar)
450 if (!Expr.
consumeInteger((AO == AllowedOperand::LegacyLiteral) ? 10 : 0,
453 return std::make_unique<ExpressionLiteral>(SaveExpr.
drop_back(Expr.
size()),
459 (MaybeInvalidConstraint ?
"matching constraint or " :
"") +
464Pattern::parseParenExpr(
StringRef &Expr, std::optional<size_t> LineNumber,
477 Expr, AllowedOperand::Any,
false, LineNumber,
482 SubExprResult = parseBinop(OrigExpr, Expr, std::move(*SubExprResult),
false,
483 LineNumber, Context, SM);
487 return SubExprResult;
491 "missing ')' at end of nested expression");
493 return SubExprResult;
498 std::unique_ptr<ExpressionAST> LeftOp,
499 bool IsLegacyLineExpr, std::optional<size_t> LineNumber,
502 if (RemainingExpr.
empty())
503 return std::move(LeftOp);
524 if (RemainingExpr.
empty())
526 "missing operand in expression");
529 IsLegacyLineExpr ? AllowedOperand::LegacyLiteral : AllowedOperand::Any;
531 parseNumericOperand(RemainingExpr, AO,
false,
532 LineNumber, Context, SM);
534 return RightOpResult;
537 return std::make_unique<BinaryOperation>(Expr, EvalBinop, std::move(LeftOp),
538 std::move(*RightOpResult));
543 std::optional<size_t> LineNumber,
559 SM, FuncName,
Twine(
"call to undefined function '") + FuncName +
"'");
573 Expr, AllowedOperand::Any,
false, LineNumber,
575 while (Arg && !Expr.
empty()) {
582 Arg = parseBinop(OuterBinOpExpr, Expr, std::move(*Arg),
false, LineNumber,
589 Args.push_back(std::move(*Arg));
603 "missing ')' at end of call expression");
605 const unsigned NumArgs =
Args.size();
607 return std::make_unique<BinaryOperation>(Expr, *OptFunc, std::move(Args[0]),
612 Twine(
"function '") + FuncName +
613 Twine(
"' takes 2 arguments but ") +
614 Twine(NumArgs) +
" given");
618 StringRef Expr, std::optional<NumericVariable *> &DefinedNumericVariable,
619 bool IsLegacyLineExpr, std::optional<size_t> LineNumber,
621 std::unique_ptr<ExpressionAST> ExpressionASTPointer =
nullptr;
623 DefinedNumericVariable = std::nullopt;
625 unsigned Precision = 0;
628 size_t FormatSpecEnd = Expr.
find(
',');
629 size_t FunctionStart = Expr.
find(
'(');
630 if (FormatSpecEnd !=
StringRef::npos && FormatSpecEnd < FunctionStart) {
637 "invalid matching format specification in expression");
647 "invalid precision in format specifier");
650 if (!FormatExpr.
empty()) {
665 Precision, AlternateForm);
669 Precision, AlternateForm);
673 "invalid format specifier in expression");
680 SM, AlternateFormFlagLoc,
681 "alternate form only supported for hex values");
684 if (!FormatExpr.
empty())
687 "invalid matching format specification in expression");
691 size_t DefEnd = Expr.
find(
':');
693 DefExpr = Expr.
substr(0, DefEnd);
694 Expr = Expr.
substr(DefEnd + 1);
704 if (HasParsedValidConstraint)
706 SM, Expr,
"empty numeric expression should not have a constraint");
713 IsLegacyLineExpr ? AllowedOperand::LineVar : AllowedOperand::Any;
715 Expr, AO, !HasParsedValidConstraint, LineNumber, Context, SM);
718 IsLegacyLineExpr, LineNumber, Context, SM);
723 "unexpected characters at end of expression '" + Expr +
"'");
737 else if (ExpressionASTPointer) {
739 ExpressionASTPointer->getImplicitFormat(SM);
747 std::unique_ptr<Expression> ExpressionPointer =
748 std::make_unique<Expression>(std::move(ExpressionASTPointer),
Format);
754 DefExpr, Context, LineNumber, ExpressionPointer->getFormat(), SM);
761 return std::move(ExpressionPointer);
773 PatternStr = PatternStr.
rtrim(
" \t");
778 "found empty check string with prefix '" + Prefix +
":'");
785 "found non-empty check string for empty check with prefix '" + Prefix +
797 FixedStr = PatternStr;
802 if (!MatchFullLinesHere &&
803 (PatternStr.
size() < 2 ||
805 FixedStr = PatternStr;
809 if (MatchFullLinesHere) {
817 unsigned CurParen = 1;
821 while (!PatternStr.
empty()) {
825 size_t End = PatternStr.
find(
"}}");
829 "found start of regex string with no end '}}'");
837 bool HasAlternation = PatternStr.
contains(
'|');
838 if (HasAlternation) {
843 if (AddRegExToRegEx(PatternStr.
substr(2,
End - 2), CurParen, SM))
866 size_t End = FindRegexVarEnd(UnparsedPatternStr, SM);
873 "Invalid substitution block, no ]] found");
879 PatternStr = UnparsedPatternStr.
substr(
End + 2);
881 bool IsDefinition =
false;
882 bool SubstNeeded =
false;
885 bool IsLegacyLineExpr =
false;
889 std::string WildcardRegexp;
890 size_t SubstInsertIdx = RegExStr.size();
894 size_t VarEndIdx = MatchStr.
find(
':');
906 if (!ParseVarResult) {
911 bool IsPseudo = ParseVarResult->IsPseudo;
914 SubstNeeded = !IsDefinition;
919 "invalid name in string variable definition");
925 if (Context->GlobalNumericVariableTable.contains(
Name)) {
928 "numeric variable with name '" +
Name +
"' already exists");
932 MatchRegexp = MatchStr;
935 MatchStr = OrigMatchStr;
936 IsLegacyLineExpr = IsNumBlock =
true;
938 if (!MatchStr.
empty()) {
941 "invalid name in string variable use");
950 std::unique_ptr<Expression> ExpressionPointer;
951 std::optional<NumericVariable *> DefinedNumericVariable;
955 IsLegacyLineExpr, LineNumber, Context,
962 SubstNeeded = ExpressionPointer->getAST() !=
nullptr;
963 if (DefinedNumericVariable) {
965 DefName = (*DefinedNumericVariable)->getName();
972 MatchRegexp = WildcardRegexp;
982 NumericVariableMatch NumericVariableDefinition = {
983 *DefinedNumericVariable, CurParen};
984 NumericVariableDefs[DefName] = NumericVariableDefinition;
989 Context->GlobalNumericVariableTable[DefName] =
990 *DefinedNumericVariable;
992 VariableDefs[DefName] = CurParen;
999 Context->DefinedVariableTable[DefName] =
true;
1005 if (!MatchRegexp.
empty() && AddRegExToRegEx(MatchRegexp, CurParen, SM))
1016 if (!IsNumBlock && VariableDefs.find(SubstStr) != VariableDefs.end()) {
1017 unsigned CaptureParenGroup = VariableDefs[SubstStr];
1018 if (CaptureParenGroup < 1 || CaptureParenGroup > 9) {
1021 "Can't back-reference more than 9 variables");
1024 AddBackrefToRegEx(CaptureParenGroup);
1030 ? Context->makeNumericSubstitution(
1031 SubstStr, std::move(ExpressionPointer), SubstInsertIdx)
1032 : Context->makeStringSubstitution(SubstStr, SubstInsertIdx);
1042 size_t FixedMatchEnd =
1043 std::min(PatternStr.
find(
"{{", 1), PatternStr.
find(
"[[", 1));
1045 PatternStr = PatternStr.
substr(FixedMatchEnd);
1048 if (MatchFullLinesHere) {
1060 if (!R.isValid(
Error)) {
1062 "invalid regex: " +
Error);
1066 RegExStr += RS.
str();
1067 CurParen += R.getNumMatches();
1071void Pattern::AddBackrefToRegEx(
unsigned BackrefNum) {
1072 assert(BackrefNum >= 1 && BackrefNum <= 9 &&
"Invalid backref number");
1073 std::string Backref = std::string(
"\\") + std::string(1,
'0' + BackrefNum);
1074 RegExStr += Backref;
1084 if (!FixedStr.
empty()) {
1088 return make_error<NotFoundError>();
1098 if (!Substitutions.empty()) {
1102 APInt(
sizeof(*LineNumber) * 8, *LineNumber));
1104 size_t InsertOffset = 0;
1120 return ErrorDiagnostic::get(
1121 SM, Substitution->getFromString(),
1122 "unable to substitute variable or "
1123 "numeric expression: overflow error");
1126 return ErrorDiagnostic::get(SM, E.getVarName(),
1135 InsertOffset +=
Value->size();
1138 return std::move(Errs);
1141 RegExToMatch = TmpStr;
1148 if (!
Regex(RegExToMatch, Flags).
match(Buffer, &MatchInfo))
1149 return make_error<NotFoundError>();
1152 assert(!MatchInfo.
empty() &&
"Didn't get any match");
1156 for (
const auto &VariableDef : VariableDefs) {
1157 assert(VariableDef.second < MatchInfo.
size() &&
"Internal paren error");
1158 Context->GlobalVariableTable[VariableDef.first] =
1159 MatchInfo[VariableDef.second];
1167 TheMatch.
Pos = FullMatch.
data() - Buffer.
data() + MatchStartSkip;
1168 TheMatch.
Len = FullMatch.
size() - MatchStartSkip;
1171 for (
const auto &NumericVariableDef : NumericVariableDefs) {
1172 const NumericVariableMatch &NumericVariableMatch =
1173 NumericVariableDef.getValue();
1174 unsigned CaptureParenGroup = NumericVariableMatch.CaptureParenGroup;
1175 assert(CaptureParenGroup < MatchInfo.
size() &&
"Internal paren error");
1177 NumericVariableMatch.DefinedNumericVariable;
1179 StringRef MatchedValue = MatchInfo[CaptureParenGroup];
1188unsigned Pattern::computeMatchDistance(
StringRef Buffer)
const {
1196 if (ExampleString.empty())
1197 ExampleString = RegExStr;
1201 BufferPrefix = BufferPrefix.
split(
'\n').first;
1208 std::vector<FileCheckDiag> *Diags)
const {
1210 if (!Substitutions.empty()) {
1217 if (!MatchedValue) {
1231 Diags->emplace_back(SM, CheckTy,
getLoc(), MatchTy,
1241 std::vector<FileCheckDiag> *Diags)
const {
1242 if (VariableDefs.empty() && NumericVariableDefs.
empty())
1250 for (
const auto &VariableDef : VariableDefs) {
1252 VC.Name = VariableDef.first;
1259 for (
const auto &VariableDef : NumericVariableDefs) {
1261 VC.Name = VariableDef.getKey();
1262 std::optional<StringRef> StrValue =
1263 VariableDef.getValue().DefinedNumericVariable->getStringValue();
1273 llvm::sort(VarCaptures, [](
const VarCapture &
A,
const VarCapture &
B) {
1276 assert(
A.Range.Start !=
B.Range.Start &&
1277 "unexpected overlapping variable captures");
1278 return A.Range.Start.getPointer() <
B.Range.Start.getPointer();
1281 for (
const VarCapture &VC : VarCaptures) {
1284 OS <<
"captured var \"" << VC.Name <<
"\"";
1286 Diags->emplace_back(SM, CheckTy,
getLoc(), MatchTy, VC.Range,
OS.str());
1295 StringRef Buffer,
size_t Pos,
size_t Len,
1296 std::vector<FileCheckDiag> *Diags,
1297 bool AdjustPrevDiags =
false) {
1302 if (AdjustPrevDiags) {
1303 SMLoc CheckLoc = Diags->rbegin()->CheckLoc;
1304 for (
auto I = Diags->rbegin(), E = Diags->rend();
1305 I != E &&
I->CheckLoc == CheckLoc; ++
I)
1306 I->MatchTy = MatchTy;
1308 Diags->emplace_back(SM, CheckTy, Loc, MatchTy,
Range);
1314 std::vector<FileCheckDiag> *Diags)
const {
1319 size_t NumLinesForward = 0;
1321 double BestQuality = 0;
1324 for (
size_t i = 0, e = std::min(
size_t(4096), Buffer.
size()); i != e; ++i) {
1325 if (Buffer[i] ==
'\n')
1330 if (Buffer[i] ==
' ' || Buffer[i] ==
'\t')
1335 unsigned Distance = computeMatchDistance(Buffer.
substr(i));
1336 double Quality = Distance + (NumLinesForward / 100.);
1340 BestQuality = Quality;
1352 "possible intended match here");
1361 auto VarIter = GlobalVariableTable.find(VarName);
1362 if (VarIter == GlobalVariableTable.end())
1363 return make_error<UndefVarError>(VarName);
1365 return VarIter->second;
1368template <
class... Types>
1370 NumericVariables.push_back(std::make_unique<NumericVariable>(
args...));
1371 return NumericVariables.back().get();
1375FileCheckPatternContext::makeStringSubstitution(
StringRef VarName,
1377 Substitutions.push_back(
1378 std::make_unique<StringSubstitution>(
this, VarName, InsertIdx));
1379 return Substitutions.back().get();
1382Substitution *FileCheckPatternContext::makeNumericSubstitution(
1385 Substitutions.push_back(std::make_unique<NumericSubstitution>(
1386 this, ExpressionStr, std::move(
Expression), InsertIdx));
1387 return Substitutions.back().get();
1394 size_t BracketDepth = 0;
1396 while (!Str.empty()) {
1397 if (Str.starts_with(
"]]") && BracketDepth == 0)
1399 if (Str[0] ==
'\\') {
1401 Str = Str.substr(2);
1411 if (BracketDepth == 0) {
1414 "missing closing \"]\" for regex variable");
1420 Str = Str.substr(1);
1435 if (
Ptr <=
End - 2 &&
Ptr[0] ==
'\r' &&
Ptr[1] ==
'\n') {
1448 while (
Ptr + 1 !=
End && (
Ptr[1] ==
' ' ||
Ptr[1] ==
'\t'))
1461 : CheckTy(CheckTy), CheckLoc(CheckLoc), MatchTy(MatchTy),
Note(
Note) {
1471 return (isAlnum(c) || c ==
'-' || c ==
'_');
1475 assert(Count > 0 &&
"zero and negative counts are not supported");
1477 "count supported only for plain CHECK directives");
1483 if (Modifiers.none())
1488 if (isLiteralMatch())
1496 auto WithModifiers = [
this, Prefix](
StringRef Str) -> std::string {
1497 return (Prefix + Str + getModifiersDescription()).str();
1504 return "misspelled";
1507 return WithModifiers(
"-COUNT");
1508 return WithModifiers(
"");
1510 return WithModifiers(
"-NEXT");
1512 return WithModifiers(
"-SAME");
1514 return WithModifiers(
"-NOT");
1516 return WithModifiers(
"-DAG");
1518 return WithModifiers(
"-LABEL");
1520 return WithModifiers(
"-EMPTY");
1522 return std::string(Prefix);
1524 return "implicit EOF";
1533static std::pair<Check::FileCheckType, StringRef>
1536 if (Buffer.
size() <= Prefix.size())
1549 -> std::pair<Check::FileCheckType, StringRef> {
1558 Rest = Rest.
ltrim();
1560 Ret.setLiteralMatch();
1564 Rest = Rest.
ltrim();
1574 if (Rest.
front() ==
'{')
1587 if (Count <= 0 || Count > INT32_MAX)
1589 if (Rest.
front() !=
':' && Rest.
front() !=
'{')
1591 return ConsumeModifiers(
1623static std::pair<Check::FileCheckType, StringRef>
1625 bool Misspelled =
false;
1663 for (
StringRef Prefix : CommentPrefixes)
1668 [](
auto A,
auto B) {
return A.first.size() >
B.first.size(); });
1676 "Buffer must be suffix of Input");
1680 for (
auto &[Prefix, Pos] : Prefixes) {
1716static std::pair<StringRef, StringRef>
1718 StringRef &Buffer,
unsigned &LineNumber,
1720 while (!Buffer.
empty()) {
1728 Prefix.data() < Buffer.
data() + Buffer.
size() &&
1729 "Prefix doesn't start inside of buffer!");
1730 size_t Loc = Prefix.data() - Buffer.
data();
1733 LineNumber += Skipped.
count(
'\n');
1743 std::tie(CheckTy, AfterSuffix) =
FindCheckType(Req, Buffer, Prefix);
1747 return {Prefix, AfterSuffix};
1761 assert(!LineVariable &&
"@LINE pseudo numeric variable already created");
1763 LineVariable = makeNumericVariable(
1765 GlobalNumericVariableTable[LineName] = LineVariable;
1776 std::pair<unsigned, unsigned> *ImpPatBufferIDRange) {
1777 if (ImpPatBufferIDRange)
1778 ImpPatBufferIDRange->first = ImpPatBufferIDRange->second = 0;
1781 PatternContext->defineCmdlineVariables(Req.
GlobalDefines, SM);
1787 PatternContext->createLineVariable();
1789 std::vector<FileCheckString::DagNotPrefixInfo> ImplicitNegativeChecks;
1793 std::string Prefix =
"-implicit-check-not='";
1794 std::string Suffix =
"'";
1796 (Prefix + PatternString + Suffix).str(),
"command line");
1799 CmdLine->getBuffer().
substr(Prefix.size(), PatternString.
size());
1801 if (ImpPatBufferIDRange) {
1802 if (ImpPatBufferIDRange->first == ImpPatBufferIDRange->second) {
1803 ImpPatBufferIDRange->first = BufferID;
1804 ImpPatBufferIDRange->second = BufferID + 1;
1806 assert(BufferID == ImpPatBufferIDRange->second &&
1807 "expected consecutive source buffer IDs");
1808 ++ImpPatBufferIDRange->second;
1812 ImplicitNegativeChecks.emplace_back(
1815 ImplicitNegativeChecks.back().DagNotPat.parsePattern(
1816 PatternInBuffer,
"IMPLICIT-CHECK", SM, Req);
1819 std::vector<FileCheckString::DagNotPrefixInfo> DagNotMatches =
1820 ImplicitNegativeChecks;
1823 unsigned LineNumber = 1;
1827 std::set<StringRef> PrefixesNotFound(Req.
CheckPrefixes.begin(),
1829 const size_t DistinctPrefixes = PrefixesNotFound.size();
1836 std::tie(UsedPrefix, AfterSuffix) =
1838 if (UsedPrefix.
empty())
1841 PrefixesNotFound.erase(UsedPrefix);
1844 "Failed to move Buffer's start forward, or pointed prefix outside "
1848 "Parsing after suffix doesn't start inside of buffer!");
1851 const char *UsedPrefixStart = UsedPrefix.
data();
1861 AfterSuffix.
data() - UsedPrefix.
data());
1864 "misspelled directive '" + UsedDirective +
"'");
1871 "unsupported -NOT combo on prefix '" + UsedPrefix +
"'");
1878 "invalid count in -COUNT specification on prefix '" +
1896 Buffer = Buffer.
substr(EOL);
1903 Pattern P(CheckTy, PatternContext.get(), LineNumber);
1904 if (
P.parsePattern(PatternBuffer, UsedPrefix, SM, Req))
1911 "found '" + UsedPrefix +
"-LABEL:'"
1912 " with variable definition or use");
1919 CheckStrings->empty()) {
1925 "found '" + UsedPrefix +
"-" +
Type +
1926 "' without previous '" + UsedPrefix +
": line");
1932 DagNotMatches.emplace_back(
P, UsedPrefix);
1937 CheckStrings->emplace_back(
P, UsedPrefix, PatternLoc);
1938 std::swap(DagNotMatches, CheckStrings->back().DagNotStrings);
1939 DagNotMatches = ImplicitNegativeChecks;
1944 const bool NoPrefixesFound = PrefixesNotFound.size() == DistinctPrefixes;
1945 const bool SomePrefixesUnexpectedlyNotUsed =
1947 if ((NoPrefixesFound || SomePrefixesUnexpectedlyNotUsed) &&
1949 errs() <<
"error: no check strings found with prefix"
1950 << (PrefixesNotFound.size() > 1 ?
"es " :
" ");
1952 for (
StringRef MissingPrefix : PrefixesNotFound) {
1955 errs() <<
"\'" << MissingPrefix <<
":'";
1964 if (!DagNotMatches.empty()) {
1965 CheckStrings->emplace_back(
1968 std::swap(DagNotMatches, CheckStrings->back().DagNotStrings);
1981 std::vector<FileCheckDiag> *Diags) {
1983 bool HasError = !ExpectedMatch || MatchResult.
TheError;
1984 bool PrintDiag =
true;
2008 assert(!HasError &&
"expected to report more diagnostics for error");
2013 std::string Message =
formatv(
"{0}: {1} string found in input",
2015 (ExpectedMatch ?
"expected" :
"excluded"))
2018 Message +=
formatv(
" ({0} out of {1})", MatchedCount, Pat.
getCount()).str();
2035 Diags->emplace_back(SM, Pat.getCheckTy(), Loc,
2036 FileCheckDiag::MatchFoundErrorNote,
2037 E.getRange(), E.getMessage().str());
2049 bool VerboseVerbose,
2050 std::vector<FileCheckDiag> *Diags) {
2052 bool HasError = ExpectedMatch;
2053 bool HasPatternError =
false;
2059 std::move(MatchError),
2061 HasError = HasPatternError =
true;
2071 bool PrintDiag =
true;
2073 if (!VerboseVerbose)
2089 Buffer, 0, Buffer.
size(), Diags);
2093 Diags->emplace_back(SM, Pat.
getCheckTy(), Loc, MatchTy, NoteRange,
2098 assert(!HasError &&
"expected to report more diagnostics for error");
2104 if (!HasPatternError) {
2105 std::string Message =
formatv(
"{0}: {1} string not found in input",
2107 (ExpectedMatch ?
"expected" :
"excluded"))
2116 "scanning from here");
2134 std::vector<FileCheckDiag> *Diags) {
2136 return printMatch(ExpectedMatch, SM, Prefix, Loc, Pat, MatchedCount, Buffer,
2137 std::move(MatchResult), Req, Diags);
2138 return printNoMatch(ExpectedMatch, SM, Prefix, Loc, Pat, MatchedCount, Buffer,
2145 const char *&FirstNewLine) {
2146 unsigned NumNewLines = 0;
2161 if (NumNewLines == 1)
2162 FirstNewLine =
Range.begin();
2167 bool IsLabelScanMode,
size_t &MatchLen,
2169 std::vector<FileCheckDiag> *Diags)
const {
2171 std::vector<const DagNotPrefixInfo *> NotStrings;
2177 if (!IsLabelScanMode) {
2179 LastPos =
CheckDag(SM, Buffer, NotStrings, Req, Diags);
2185 size_t LastMatchEnd = LastPos;
2186 size_t FirstMatchPos = 0;
2197 Pat, i, MatchBuffer,
2198 std::move(MatchResult), Req, Diags)) {
2203 size_t MatchPos = MatchResult.
TheMatch->Pos;
2205 FirstMatchPos = LastPos + MatchPos;
2208 LastMatchEnd += MatchPos + MatchResult.
TheMatch->Len;
2211 MatchLen = LastMatchEnd - FirstMatchPos;
2215 if (!IsLabelScanMode) {
2216 size_t MatchPos = FirstMatchPos - LastPos;
2240 if (
CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2244 return FirstMatchPos;
2257 const char *FirstNewLine =
nullptr;
2260 if (NumNewLines == 0) {
2262 CheckName +
": is on the same line as previous match");
2264 "'next' match was here");
2266 "previous match ended here");
2270 if (NumNewLines != 1) {
2273 ": is not on the line after the previous match");
2275 "'next' match was here");
2277 "previous match ended here");
2279 "non-matching line after previous match is here");
2291 const char *FirstNewLine =
nullptr;
2294 if (NumNewLines != 0) {
2297 "-SAME: is not on the same line as the previous match");
2299 "'next' match was here");
2301 "previous match ended here");
2310 const std::vector<const DagNotPrefixInfo *> &NotStrings,
2312 bool DirectiveFail =
false;
2313 for (
auto NotInfo : NotStrings) {
2315 "Expect CHECK-NOT!");
2318 false, SM, NotInfo->DagNotPrefix,
2319 NotInfo->DagNotPat.getLoc(), NotInfo->DagNotPat, 1, Buffer,
2320 std::move(MatchResult), Req, Diags)) {
2322 DirectiveFail =
true;
2326 return DirectiveFail;
2331 std::vector<const DagNotPrefixInfo *> &NotStrings,
2333 std::vector<FileCheckDiag> *Diags)
const {
2338 size_t StartPos = 0;
2347 std::list<MatchRange> MatchRanges;
2352 PatItr != PatEnd; ++PatItr) {
2354 const StringRef DNPrefix = PatItr->DagNotPrefix;
2357 "Invalid CHECK-DAG or CHECK-NOT!");
2360 NotStrings.push_back(&*PatItr);
2367 size_t MatchLen = 0, MatchPos = StartPos;
2371 for (
auto MI = MatchRanges.begin(), ME = MatchRanges.end();
true; ++
MI) {
2379 std::move(MatchResult), Req, Diags)) {
2385 MatchLen = MatchResult.
TheMatch->Len;
2388 MatchPos += MatchResult.
TheMatch->Pos;
2389 MatchRange M{MatchPos, MatchPos + MatchLen};
2394 if (MatchRanges.empty())
2395 MatchRanges.insert(MatchRanges.end(), M);
2397 auto Block = MatchRanges.begin();
2404 bool Overlap =
false;
2405 for (;
MI != ME; ++
MI) {
2406 if (M.Pos <
MI->End) {
2409 Overlap =
MI->Pos < M.End;
2415 MatchRanges.insert(
MI, M);
2425 SMRange OldRange(OldStart, OldEnd);
2427 "match discarded, overlaps earlier DAG match here",
2430 SMLoc CheckLoc = Diags->rbegin()->CheckLoc;
2431 for (
auto I = Diags->rbegin(), E = Diags->rend();
2432 I != E &&
I->CheckLoc == CheckLoc; ++
I)
2445 if (std::next(PatItr) == PatEnd ||
2447 if (!NotStrings.empty()) {
2452 Buffer.
slice(StartPos, MatchRanges.begin()->Pos);
2453 if (
CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2460 StartPos = MatchRanges.rbegin()->End;
2462 MatchRanges.clear();
2471 for (
StringRef Prefix : SuppliedPrefixes) {
2472 if (Prefix.empty()) {
2473 errs() <<
"error: supplied " << Kind <<
" prefix must not be the empty "
2477 static const Regex Validator(
"^[a-zA-Z0-9_-]*$");
2478 if (!Validator.
match(Prefix)) {
2479 errs() <<
"error: supplied " << Kind <<
" prefix must start with a "
2480 <<
"letter and contain only alphanumeric characters, hyphens, and "
2481 <<
"underscores: '" << Prefix <<
"'\n";
2484 if (!UniquePrefixes.
insert(Prefix).second) {
2485 errs() <<
"error: supplied " << Kind <<
" prefix must be unique among "
2486 <<
"check and comment prefixes: '" << Prefix <<
"'\n";
2498 UniquePrefixes.
insert(Prefix);
2502 UniquePrefixes.
insert(Prefix);
2515 assert(GlobalVariableTable.empty() && GlobalNumericVariableTable.empty() &&
2516 "Overriding defined variable with command-line variable definitions");
2518 if (CmdlineDefines.
empty())
2526 std::string CmdlineDefsDiag;
2528 for (
StringRef CmdlineDef : CmdlineDefines) {
2529 std::string DefPrefix = (
"Global define #" +
Twine(++
I) +
": ").str();
2530 size_t EqIdx = CmdlineDef.find(
'=');
2532 CmdlineDefsIndices.
push_back(std::make_pair(CmdlineDefsDiag.size(), 0));
2536 if (CmdlineDef[0] ==
'#') {
2540 CmdlineDefsDiag += (DefPrefix + CmdlineDef +
" (parsed as: [[").str();
2541 std::string SubstitutionStr = std::string(CmdlineDef);
2542 SubstitutionStr[EqIdx] =
':';
2544 std::make_pair(CmdlineDefsDiag.size(), SubstitutionStr.size()));
2545 CmdlineDefsDiag += (SubstitutionStr +
Twine(
"]])\n")).str();
2547 CmdlineDefsDiag += DefPrefix;
2549 std::make_pair(CmdlineDefsDiag.size(), CmdlineDef.size()));
2550 CmdlineDefsDiag += (CmdlineDef +
"\n").str();
2557 std::unique_ptr<MemoryBuffer> CmdLineDefsDiagBuffer =
2559 StringRef CmdlineDefsDiagRef = CmdLineDefsDiagBuffer->getBuffer();
2562 for (std::pair<size_t, size_t> CmdlineDefIndices : CmdlineDefsIndices) {
2563 StringRef CmdlineDef = CmdlineDefsDiagRef.
substr(CmdlineDefIndices.first,
2564 CmdlineDefIndices.second);
2565 if (CmdlineDef.
empty()) {
2569 "missing equal sign in global definition"));
2574 if (CmdlineDef[0] ==
'#') {
2578 std::optional<NumericVariable *> DefinedNumericVariable;
2581 DefinedNumericVariable,
false,
2582 std::nullopt,
this, SM);
2583 if (!ExpressionResult) {
2587 std::unique_ptr<Expression>
Expression = std::move(*ExpressionResult);
2598 assert(DefinedNumericVariable &&
"No variable defined");
2599 (*DefinedNumericVariable)->setValue(*
Value);
2602 GlobalNumericVariableTable[(*DefinedNumericVariable)->getName()] =
2603 *DefinedNumericVariable;
2606 std::pair<StringRef, StringRef> CmdlineNameVal = CmdlineDef.
split(
'=');
2607 StringRef CmdlineName = CmdlineNameVal.first;
2608 StringRef OrigCmdlineName = CmdlineName;
2611 if (!ParseVarResult) {
2618 if (ParseVarResult->IsPseudo || !CmdlineName.
empty()) {
2621 SM, OrigCmdlineName,
2622 "invalid name in string variable definition '" +
2623 OrigCmdlineName +
"'"));
2630 if (GlobalNumericVariableTable.contains(
Name)) {
2633 "numeric variable with name '" +
2634 Name +
"' already exists"));
2637 GlobalVariableTable.insert(CmdlineNameVal);
2644 DefinedVariableTable[
Name] =
true;
2654 if (Var.first()[0] !=
'$')
2655 LocalPatternVars.
push_back(Var.first());
2663 for (
const auto &Var : GlobalNumericVariableTable)
2664 if (Var.first()[0] !=
'$') {
2665 Var.getValue()->clearValue();
2666 LocalNumericVars.
push_back(Var.first());
2669 for (
const auto &Var : LocalPatternVars)
2670 GlobalVariableTable.erase(Var);
2671 for (
const auto &Var : LocalNumericVars)
2672 GlobalNumericVariableTable.erase(Var);
2676 std::vector<FileCheckDiag> *Diags) {
2677 bool ChecksFailed =
false;
2679 unsigned i = 0, j = 0, e = CheckStrings->size();
2683 CheckRegion = Buffer;
2692 size_t MatchLabelLen = 0;
2693 size_t MatchLabelPos =
2694 CheckLabelStr.
Check(SM, Buffer,
true, MatchLabelLen, Req, Diags);
2699 CheckRegion = Buffer.
substr(0, MatchLabelPos + MatchLabelLen);
2700 Buffer = Buffer.
substr(MatchLabelPos + MatchLabelLen);
2708 PatternContext->clearLocalVars();
2710 for (; i != j; ++i) {
2715 size_t MatchLen = 0;
2717 CheckStr.
Check(SM, CheckRegion,
false, MatchLen, Req, Diags);
2720 ChecksFailed =
true;
2725 CheckRegion = CheckRegion.
substr(MatchPos + MatchLen);
2733 return !ChecksFailed;
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 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))
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
StringSet - A set-like wrapper for the StringMap.
Class for arbitrary precision integers.
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.
APInt sadd_ov(const APInt &RHS, bool &Overflow) const
APInt sdiv_ov(const APInt &RHS, bool &Overflow) const
@ APINT_BITS_PER_WORD
Bits in a word.
APInt smul_ov(const APInt &RHS, bool &Overflow) const
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.
APInt ssub_ov(const APInt &RHS, bool &Overflow) const
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...
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.
StringRef getMessage() const
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...
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....
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.
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 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< 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.
This class represents success/failure for parsing-like operations that find it important to chain tog...
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...
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.
bool contains(StringRef Key) const
contains - Return true if the element is in the map, false otherwise.
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.
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.
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.
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.
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.
std::optional< int64_t > toSigned(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an signed constant.
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.
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.
auto formatv(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< Ts >(Vals))...))>
Expected< APInt > exprAdd(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
Performs operation and.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Error joinErrors(Error E1, Error E2)
Concatenate errors.
void sort(IteratorTy Start, IteratorTy End)
Expected< APInt > exprMul(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
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)
Expected< APInt > exprDiv(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
Expected< APInt > exprMin(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
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.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
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.
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.