LLVM: lib/FileCheck/FileCheck.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
23#include
24#include
25#include
26#include
27#include
28
29using namespace llvm;
30
32 switch (Value) {
43 }
45}
46
49
50 auto CreatePrecisionRegex = [&](StringRef S) {
51 return (Twine(AlternateFormPrefix) + S + Twine('{') + Twine(Precision) +
52 "}")
53 .str();
54 };
55
56 switch (Value) {
58 if (Precision)
59 return CreatePrecisionRegex("([1-9][0-9]*)?[0-9]");
60 return std::string("[0-9]+");
62 if (Precision)
63 return CreatePrecisionRegex("-?([1-9][0-9]*)?[0-9]");
64 return std::string("-?[0-9]+");
66 if (Precision)
67 return CreatePrecisionRegex("([1-9A-F][0-9A-F]*)?[0-9A-F]");
68 return (Twine(AlternateFormPrefix) + Twine("[0-9A-F]+")).str();
70 if (Precision)
71 return CreatePrecisionRegex("([1-9a-f][0-9a-f]*)?[0-9a-f]");
72 return (Twine(AlternateFormPrefix) + Twine("[0-9a-f]+")).str();
73 default:
75 "trying to match value with invalid format");
76 }
77}
78
83
84 unsigned Radix;
85 bool UpperCase = false;
88 switch (Value) {
91 Radix = 10;
92 break;
94 UpperCase = true;
95 Radix = 16;
96 break;
98 Radix = 16;
99 UpperCase = false;
100 break;
101 default:
103 "trying to match value with invalid format");
104 }
105 IntValue.abs().toString(AbsoluteValueStr, Radix, false,
106 false,
107 UpperCase);
108
110
111 if (Precision > AbsoluteValueStr.size()) {
112 unsigned LeadingZeros = Precision - AbsoluteValueStr.size();
113 return (Twine(SignPrefix) + Twine(AlternateFormPrefix) +
114 std::string(LeadingZeros, '0') + AbsoluteValueStr)
115 .str();
116 }
117
118 return (Twine(SignPrefix) + Twine(AlternateFormPrefix) + AbsoluteValueStr)
119 .str();
120}
121
126
130 APInt Result = AbsVal;
131 if (Negative)
132 Result.negate();
133 return Result;
134}
135
139 bool Negative = StrVal.consume_front("-");
141 bool MissingFormPrefix =
142 !ValueIsSigned && AlternateForm && !StrVal.consume_front("0x");
143 (void)MissingFormPrefix;
144 assert(!MissingFormPrefix && "missing alternate form prefix");
145 APInt ResultValue;
146 [[maybe_unused]] bool ParseFailure =
147 StrVal.getAsInteger(Hex ? 16 : 10, ResultValue);
148
149
150
151 assert(!ParseFailure && "unable to represent numeric value");
152 return toSigned(ResultValue, Negative);
153}
154
156 const APInt &RightOperand, bool &Overflow) {
157 return LeftOperand.sadd_ov(RightOperand, Overflow);
158}
159
161 const APInt &RightOperand, bool &Overflow) {
162 return LeftOperand.ssub_ov(RightOperand, Overflow);
163}
164
166 const APInt &RightOperand, bool &Overflow) {
167 return LeftOperand.smul_ov(RightOperand, Overflow);
168}
169
171 const APInt &RightOperand, bool &Overflow) {
172
173 if (RightOperand.isZero())
175
176 return LeftOperand.sdiv_ov(RightOperand, Overflow);
177}
178
180 const APInt &RightOperand, bool &Overflow) {
181 Overflow = false;
182 return LeftOperand.slt(RightOperand) ? RightOperand : LeftOperand;
183}
184
186 const APInt &RightOperand, bool &Overflow) {
187 Overflow = false;
188 if (cantFail(exprMax(LeftOperand, RightOperand, Overflow)) == LeftOperand)
189 return RightOperand;
190
191 return LeftOperand;
192}
193
195 std::optional Value = Variable->getValue();
198
200}
201
205
206
207
208 if (!MaybeLeftOp || !MaybeRightOp) {
210 if (!MaybeLeftOp)
212 if (!MaybeRightOp)
214 return std::move(Err);
215 }
216
217 APInt LeftOp = *MaybeLeftOp;
218 APInt RightOp = *MaybeRightOp;
219 bool Overflow;
220
221 unsigned LeftBitWidth = LeftOp.getBitWidth();
222 unsigned RightBitWidth = RightOp.getBitWidth();
223 unsigned NewBitWidth = std::max(LeftBitWidth, RightBitWidth);
224 LeftOp = LeftOp.sext(NewBitWidth);
225 RightOp = RightOp.sext(NewBitWidth);
226 do {
227 Expected MaybeResult = EvalBinop(LeftOp, RightOp, Overflow);
228 if (!MaybeResult)
230
231 if (!Overflow)
232 return MaybeResult;
233
235 LeftOp = LeftOp.sext(NewBitWidth);
236 RightOp = RightOp.sext(NewBitWidth);
237 } while (true);
238}
239
244 if (!LeftFormat || !RightFormat) {
246 if (!LeftFormat)
248 if (!RightFormat)
250 return std::move(Err);
251 }
252
255 *LeftFormat != *RightFormat)
258 "implicit format conflict between '" + LeftOperand->getExpressionStr() +
259 "' (" + LeftFormat->toString() + ") and '" +
260 RightOperand->getExpressionStr() + "' (" + RightFormat->toString() +
261 "), need an explicit format specifier");
262
264 : *RightFormat;
265}
266
268 assert(ExpressionPointer->getAST() != nullptr &&
269 "Substituting empty expression");
270 Expected EvaluatedValue = ExpressionPointer->getAST()->eval();
271 if (!EvaluatedValue)
272 return EvaluatedValue.takeError();
274 return Format.getMatchingString(*EvaluatedValue);
275}
276
278
279
280
284
285 return "\"" + std::move(*Literal) + "\"";
286}
287
289
291 if (!VarVal)
294}
295
298 if (!VarVal)
300
301 std::string Result;
302 Result.reserve(VarVal->size() + 2);
304
305 OS << '"';
306
307
308
309
310
311
312
313 const bool NeedsEscaping =
315 if (NeedsEscaping)
317 else
318 OS << *VarVal;
319 OS << '"';
320 if (NeedsEscaping)
321 OS << " (escaped value)";
322
323 return Result;
324}
325
327
330 if (Str.empty())
332
333 size_t I = 0;
334 bool IsPseudo = Str[0] == '@';
335
336
337 if (Str[0] == '$' || IsPseudo)
338 ++I;
339
340 if (I == Str.size())
343 (IsPseudo ? "pseudo " : "global ") +
344 "variable name");
345
348
349 for (size_t E = Str.size(); I != E; ++I)
350
351 if (Str[I] != '_' && (Str[I]))
352 break;
353
355 Str = Str.substr(I);
357}
358
359
360
362
363
369
375
378 std::optional<size_t> LineNumber, ExpressionFormat ImplicitFormat,
380 Expected ParseVarResult = parseVariable(Expr, SM);
381 if (!ParseVarResult)
382 return ParseVarResult.takeError();
383 StringRef Name = ParseVarResult->Name;
384
385 if (ParseVarResult->IsPseudo)
387 SM, Name, "definition of pseudo numeric variable unsupported");
388
389
390
391 if (Context->DefinedVariableTable.contains(Name))
393 SM, Name, "string variable with name '" + Name + "' already exists");
394
396 if (!Expr.empty())
398 SM, Expr, "unexpected characters after numeric variable name");
399
400 NumericVariable *DefinedNumericVariable;
401 auto VarTableIter = Context->GlobalNumericVariableTable.find(Name);
402 if (VarTableIter != Context->GlobalNumericVariableTable.end()) {
403 DefinedNumericVariable = VarTableIter->second;
404 if (DefinedNumericVariable->getImplicitFormat() != ImplicitFormat)
406 SM, Expr, "format different from previous variable definition");
407 } else
408 DefinedNumericVariable =
409 Context->makeNumericVariable(Name, ImplicitFormat, LineNumber);
410
411 return DefinedNumericVariable;
412}
413
415 StringRef Name, bool IsPseudo, std::optional<size_t> LineNumber,
417 if (IsPseudo && Name != "@LINE")
419 SM, Name, "invalid pseudo numeric variable '" + Name + "'");
420
421
422
423
424
425
426
427
428
429 auto [VarTableIter, Inserted] =
430 Context->GlobalNumericVariableTable.try_emplace(Name);
431 if (Inserted)
432 VarTableIter->second = Context->makeNumericVariable(
434 NumericVariable *NumericVariable = VarTableIter->second;
435
436 std::optional<size_t> DefLineNumber = NumericVariable->getDefLineNumber();
437 if (DefLineNumber && LineNumber && *DefLineNumber == *LineNumber)
439 SM, Name,
440 "numeric variable '" + Name +
441 "' defined earlier in the same CHECK directive");
442
443 return std::make_unique(Name, NumericVariable);
444}
445
447 StringRef &Expr, AllowedOperand AO, bool MaybeInvalidConstraint,
451 if (AO != AllowedOperand::Any)
453 SM, Expr, "parenthesized expression not permitted here");
454 return parseParenExpr(Expr, LineNumber, Context, SM);
455 }
456
457 if (AO == AllowedOperand::LineVar || AO == AllowedOperand::Any) {
458
459 ExpectedPattern::VariableProperties ParseVarResult =
461 if (ParseVarResult) {
462
464 if (AO != AllowedOperand::Any)
466 "unexpected function call");
467
468 return parseCallExpr(Expr, ParseVarResult->Name, LineNumber, Context,
469 SM);
470 }
471
472 return parseNumericVariableUse(ParseVarResult->Name,
473 ParseVarResult->IsPseudo, LineNumber,
474 Context, SM);
475 }
476
477 if (AO == AllowedOperand::LineVar)
478 return ParseVarResult.takeError();
479
481 }
482
483
485 StringRef SaveExpr = Expr;
487 if (!Expr.consumeInteger((AO == AllowedOperand::LegacyLiteral) ? 10 : 0,
488 LiteralValue)) {
490 return std::make_unique(SaveExpr.drop_back(Expr.size()),
491 LiteralValue);
492 }
494 SM, SaveExpr,
495 Twine("invalid ") +
496 (MaybeInvalidConstraint ? "matching constraint or " : "") +
497 "operand format");
498}
499
501Pattern::parseParenExpr(StringRef &Expr, std::optional<size_t> LineNumber,
505
506
509 if (Expr.empty())
511
512
513 Expected<std::unique_ptr> SubExprResult = parseNumericOperand(
514 Expr, AllowedOperand::Any, false, LineNumber,
515 Context, SM);
517 while (SubExprResult && !Expr.empty() && !Expr.starts_with(")")) {
518 StringRef OrigExpr = Expr;
519 SubExprResult = parseBinop(OrigExpr, Expr, std::move(*SubExprResult), false,
520 LineNumber, Context, SM);
522 }
523 if (!SubExprResult)
524 return SubExprResult;
525
528 "missing ')' at end of nested expression");
529 }
530 return SubExprResult;
531}
532
535 std::unique_ptr LeftOp,
536 bool IsLegacyLineExpr, std::optional<size_t> LineNumber,
539 if (RemainingExpr.empty())
540 return std::move(LeftOp);
541
542
543
547 switch (Operator) {
548 case '+':
550 break;
551 case '-':
553 break;
554 default:
556 SM, OpLoc, Twine("unsupported operation '") + Twine(Operator) + "'");
557 }
558
559
561 if (RemainingExpr.empty())
563 "missing operand in expression");
564
565 AllowedOperand AO =
566 IsLegacyLineExpr ? AllowedOperand::LegacyLiteral : AllowedOperand::Any;
567 Expected<std::unique_ptr> RightOpResult =
568 parseNumericOperand(RemainingExpr, AO, false,
569 LineNumber, Context, SM);
570 if (!RightOpResult)
571 return RightOpResult;
572
574 return std::make_unique(Expr, EvalBinop, std::move(LeftOp),
575 std::move(*RightOpResult));
576}
577
580 std::optional<size_t> LineNumber,
584
585 auto OptFunc = StringSwitch<binop_eval_t>(FuncName)
592 .Default(nullptr);
593
594 if (!OptFunc)
596 SM, FuncName, Twine("call to undefined function '") + FuncName + "'");
597
600
601
606
607
608 StringRef OuterBinOpExpr = Expr;
609 Expected<std::unique_ptr> Arg = parseNumericOperand(
610 Expr, AllowedOperand::Any, false, LineNumber,
611 Context, SM);
612 while (Arg && !Expr.empty()) {
614
616 break;
617
618
619 Arg = parseBinop(OuterBinOpExpr, Expr, std::move(*Arg), false, LineNumber,
620 Context, SM);
621 }
622
623
624 if (!Arg)
626 Args.push_back(std::move(*Arg));
627
628
631 break;
632
636 }
637
640 "missing ')' at end of call expression");
641
642 const unsigned NumArgs = Args.size();
643 if (NumArgs == 2)
644 return std::make_unique(Expr, *OptFunc, std::move(Args[0]),
645 std::move(Args[1]));
646
647
649 Twine("function '") + FuncName +
650 Twine("' takes 2 arguments but ") +
651 Twine(NumArgs) + " given");
652}
653
655 StringRef Expr, std::optional<NumericVariable *> &DefinedNumericVariable,
656 bool IsLegacyLineExpr, std::optional<size_t> LineNumber,
658 std::unique_ptr ExpressionASTPointer = nullptr;
660 DefinedNumericVariable = std::nullopt;
662 unsigned Precision = 0;
663
664
665 size_t FormatSpecEnd = Expr.find(',');
666 size_t FunctionStart = Expr.find('(');
667 if (FormatSpecEnd != StringRef::npos && FormatSpecEnd < FunctionStart) {
669 Expr = Expr.drop_front(FormatSpecEnd + 1);
673 SM, FormatExpr,
674 "invalid matching format specification in expression");
675
676
678 bool AlternateForm = FormatExpr.consume_front("#");
679
680
684 "invalid precision in format specifier");
685 }
686
687 if (!FormatExpr.empty()) {
688
689
691 switch (popFront(FormatExpr)) {
692 case 'u':
693 ExplicitFormat =
695 break;
696 case 'd':
697 ExplicitFormat =
699 break;
700 case 'x':
702 Precision, AlternateForm);
703 break;
704 case 'X':
706 Precision, AlternateForm);
707 break;
708 default:
710 "invalid format specifier in expression");
711 }
712 }
713
717 SM, AlternateFormFlagLoc,
718 "alternate form only supported for hex values");
719
721 if (!FormatExpr.empty())
723 SM, FormatExpr,
724 "invalid matching format specification in expression");
725 }
726
727
728 size_t DefEnd = Expr.find(':');
730 DefExpr = Expr.substr(0, DefEnd);
731 Expr = Expr.substr(DefEnd + 1);
732 }
733
734
736 bool HasParsedValidConstraint = Expr.consume_front("==");
737
738
740 if (Expr.empty()) {
741 if (HasParsedValidConstraint)
743 SM, Expr, "empty numeric expression should not have a constraint");
744 } else {
747
748
749 AllowedOperand AO =
750 IsLegacyLineExpr ? AllowedOperand::LineVar : AllowedOperand::Any;
752 Expr, AO, !HasParsedValidConstraint, LineNumber, Context, SM);
755 IsLegacyLineExpr, LineNumber, Context, SM);
756
759 SM, Expr,
760 "unexpected characters at end of expression '" + Expr + "'");
761 }
764 ExpressionASTPointer = std::move(*ParseResult);
765 }
766
767
768
769
770
772 if (ExplicitFormat)
773 Format = ExplicitFormat;
774 else if (ExpressionASTPointer) {
776 ExpressionASTPointer->getImplicitFormat(SM);
777 if (!ImplicitFormat)
778 return ImplicitFormat.takeError();
779 Format = *ImplicitFormat;
780 }
783
784 std::unique_ptr ExpressionPointer =
785 std::make_unique(std::move(ExpressionASTPointer), Format);
786
787
791 DefExpr, Context, LineNumber, ExpressionPointer->getFormat(), SM);
792
796 }
797
798 return std::move(ExpressionPointer);
799}
800
805
807
809
810 PatternStr = PatternStr.rtrim(" \t");
811
812
815 "found empty check string with prefix '" + Prefix + ":'");
816 return true;
817 }
818
822 "found non-empty check string for empty check with prefix '" + Prefix +
823 ":'");
824 return true;
825 }
826
828 RegExStr = "(\n$)";
829 return false;
830 }
831
832
833 if (CheckTy.isLiteralMatch()) {
834 FixedStr = PatternStr;
835 return false;
836 }
837
838
839 if (!MatchFullLinesHere &&
840 (PatternStr.size() < 2 ||
841 (!PatternStr.contains("{{") && !PatternStr.contains("[[")))) {
842 FixedStr = PatternStr;
843 return false;
844 }
845
846 if (MatchFullLinesHere) {
847 RegExStr += '^';
849 RegExStr += " *";
850 }
851
852
853
854 unsigned CurParen = 1;
855
856
857
858 while (!PatternStr.empty()) {
859
861
862 size_t End = PatternStr.find("}}");
866 "found start of regex string with no end '}}'");
867 return true;
868 }
869
870
871
872
873
874 bool HasAlternation = PatternStr.contains('|');
875 if (HasAlternation) {
876 RegExStr += '(';
877 ++CurParen;
878 }
879
880 if (AddRegExToRegEx(PatternStr.substr(2, End - 2), CurParen, SM))
881 return true;
882 if (HasAlternation)
883 RegExStr += ')';
884
885 PatternStr = PatternStr.substr(End + 2);
886 continue;
887 }
888
889
890
891
892
893
894
895
896
897
898
901
902
903 size_t End = FindRegexVarEnd(UnparsedPatternStr, SM);
906
910 "Invalid substitution block, no ]] found");
911 return true;
912 }
913
914
915
916 PatternStr = UnparsedPatternStr.substr(End + 2);
917
918 bool IsDefinition = false;
919 bool SubstNeeded = false;
920
921
922 bool IsLegacyLineExpr = false;
926 std::string WildcardRegexp;
927 size_t SubstInsertIdx = RegExStr.size();
928
929
930 if (!IsNumBlock) {
931 size_t VarEndIdx = MatchStr.find(':');
936 return true;
937 }
938
939
940 StringRef OrigMatchStr = MatchStr;
943 if (!ParseVarResult) {
945 return true;
946 }
947 StringRef Name = ParseVarResult->Name;
948 bool IsPseudo = ParseVarResult->IsPseudo;
949
951 SubstNeeded = !IsDefinition;
952 if (IsDefinition) {
953 if ((IsPseudo || !MatchStr.consume_front(":"))) {
956 "invalid name in string variable definition");
957 return true;
958 }
959
960
961
962 if (Context->GlobalNumericVariableTable.contains(Name)) {
965 "numeric variable with name '" + Name + "' already exists");
966 return true;
967 }
968 DefName = Name;
969 MatchRegexp = MatchStr;
970 } else {
971 if (IsPseudo) {
972 MatchStr = OrigMatchStr;
973 IsLegacyLineExpr = IsNumBlock = true;
974 } else {
975 if (!MatchStr.empty()) {
978 "invalid name in string variable use");
979 return true;
980 }
981 SubstStr = Name;
982 }
983 }
984 }
985
986
987 std::unique_ptr ExpressionPointer;
988 std::optional<NumericVariable *> DefinedNumericVariable;
989 if (IsNumBlock) {
992 IsLegacyLineExpr, LineNumber, Context,
993 SM);
996 return true;
997 }
998 ExpressionPointer = std::move(*ParseResult);
999 SubstNeeded = ExpressionPointer->getAST() != nullptr;
1000 if (DefinedNumericVariable) {
1001 IsDefinition = true;
1002 DefName = (*DefinedNumericVariable)->getName();
1003 }
1004 if (SubstNeeded)
1005 SubstStr = MatchStr;
1006 else {
1008 WildcardRegexp = cantFail(Format.getWildcardRegex());
1009 MatchRegexp = WildcardRegexp;
1010 }
1011 }
1012
1013
1014 if (IsDefinition) {
1015 RegExStr += '(';
1016 ++SubstInsertIdx;
1017
1018 if (IsNumBlock) {
1019 NumericVariableMatch NumericVariableDefinition = {
1020 *DefinedNumericVariable, CurParen};
1021 NumericVariableDefs[DefName] = NumericVariableDefinition;
1022
1023
1024
1025
1026 Context->GlobalNumericVariableTable[DefName] =
1027 *DefinedNumericVariable;
1028 } else {
1029 VariableDefs[DefName] = CurParen;
1030
1031
1032
1033
1034
1035
1036 Context->DefinedVariableTable[DefName] = true;
1037 }
1038
1039 ++CurParen;
1040 }
1041
1042 if (!MatchRegexp.empty() && AddRegExToRegEx(MatchRegexp, CurParen, SM))
1043 return true;
1044
1045 if (IsDefinition)
1046 RegExStr += ')';
1047
1048
1049 if (SubstNeeded) {
1050
1051
1052
1053 decltype(VariableDefs)::iterator It;
1054 if (!IsNumBlock &&
1055 (It = VariableDefs.find(SubstStr)) != VariableDefs.end()) {
1056 unsigned CaptureParenGroup = It->second;
1057 if (CaptureParenGroup < 1 || CaptureParenGroup > 9) {
1060 "Can't back-reference more than 9 variables");
1061 return true;
1062 }
1063 AddBackrefToRegEx(CaptureParenGroup);
1064 } else {
1065
1066
1068 IsNumBlock
1069 ? Context->makeNumericSubstitution(
1070 SubstStr, std::move(ExpressionPointer), SubstInsertIdx)
1071 : Context->makeStringSubstitution(SubstStr, SubstInsertIdx);
1073 }
1074 }
1075
1076 continue;
1077 }
1078
1079
1080
1081 size_t FixedMatchEnd =
1082 std::min(PatternStr.find("{{", 1), PatternStr.find("[[", 1));
1084 PatternStr = PatternStr.substr(FixedMatchEnd);
1085 }
1086
1087 if (MatchFullLinesHere) {
1089 RegExStr += " *";
1090 RegExStr += '$';
1091 }
1092
1093 return false;
1094}
1095
1096bool Pattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM) {
1098 std::string Error;
1099 if (!R.isValid(Error)) {
1101 "invalid regex: " + Error);
1102 return true;
1103 }
1104
1105 RegExStr += RS.str();
1106 CurParen += R.getNumMatches();
1107 return false;
1108}
1109
1110void Pattern::AddBackrefToRegEx(unsigned BackrefNum) {
1111 assert(BackrefNum >= 1 && BackrefNum <= 9 && "Invalid backref number");
1112 std::string Backref = std::string("\\") + std::string(1, '0' + BackrefNum);
1113 RegExStr += Backref;
1114}
1115
1118
1121
1122
1123 if (!FixedStr.empty()) {
1124 size_t Pos =
1129 }
1130
1131
1132
1133
1134
1135 StringRef RegExToMatch = RegExStr;
1136 std::string TmpStr;
1137 if (!Substitutions.empty()) {
1138 TmpStr = RegExStr;
1139 if (LineNumber)
1140 Context->LineVariable->setValue(
1141 APInt(sizeof(*LineNumber) * 8, *LineNumber));
1142
1143 size_t InsertOffset = 0;
1144
1145
1146
1148 for (const auto &Substitution : Substitutions) {
1149
1152
1153
1154
1157 Value.takeError(),
1159 return ErrorDiagnostic::get(
1160 SM, Substitution->getFromString(),
1161 "unable to substitute variable or "
1162 "numeric expression: overflow error");
1163 },
1165 return ErrorDiagnostic::get(SM, E.getVarName(),
1166 E.message());
1167 }));
1168 continue;
1169 }
1170
1171
1174 InsertOffset += Value->size();
1175 }
1176 if (Errs)
1177 return std::move(Errs);
1178
1179
1180 RegExToMatch = TmpStr;
1181 }
1182
1185 if (IgnoreCase)
1187 if ((RegExToMatch, Flags).match(Buffer, &MatchInfo))
1189
1190
1191 assert(!MatchInfo.empty() && "Didn't get any match");
1192 StringRef FullMatch = MatchInfo[0];
1193
1194
1195 for (const auto &VariableDef : VariableDefs) {
1196 assert(VariableDef.second < MatchInfo.size() && "Internal paren error");
1197 Context->GlobalVariableTable[VariableDef.first] =
1198 MatchInfo[VariableDef.second];
1199 }
1200
1201
1202
1203
1206 TheMatch.Pos = FullMatch.data() - Buffer.data() + MatchStartSkip;
1207 TheMatch.Len = FullMatch.size() - MatchStartSkip;
1208
1209
1210 for (const auto &NumericVariableDef : NumericVariableDefs) {
1211 const NumericVariableMatch &NumericVariableMatch =
1212 NumericVariableDef.getValue();
1213 unsigned CaptureParenGroup = NumericVariableMatch.CaptureParenGroup;
1214 assert(CaptureParenGroup < MatchInfo.size() && "Internal paren error");
1216 NumericVariableMatch.DefinedNumericVariable;
1217
1218 StringRef MatchedValue = MatchInfo[CaptureParenGroup];
1221
1222
1223
1224
1225
1226
1227 Context->GlobalNumericVariableTable.try_emplace(NumericVariableDef.getKey(),
1228 DefinedNumericVariable);
1229 DefinedNumericVariable->setValue(Value, MatchedValue);
1230 }
1231
1233}
1234
1235unsigned Pattern::computeMatchDistance(StringRef Buffer) const {
1236
1237
1238
1239
1240
1241
1242 StringRef ExampleString(FixedStr);
1243 if (ExampleString.empty())
1244 ExampleString = RegExStr;
1245
1246
1247 StringRef BufferPrefix = Buffer.substr(0, ExampleString.size());
1248 BufferPrefix = BufferPrefix.split('\n').first;
1249 return BufferPrefix.edit_distance(ExampleString);
1250}
1251
1255 std::vector *Diags) const {
1256
1257 if (!Substitutions.empty()) {
1258 for (const auto &Substitution : Substitutions) {
1261
1264
1265 if (!MatchedValue) {
1267 continue;
1268 }
1269
1270 OS << "with \"";
1272 OS << *MatchedValue;
1273
1274
1275
1276
1277
1278 if (Diags)
1279 Diags->emplace_back(SM, CheckTy, getLoc(), MatchTy,
1281 else
1283 }
1284 }
1285}
1286
1289 std::vector *Diags) const {
1290 if (VariableDefs.empty() && NumericVariableDefs.empty())
1291 return;
1292
1293 struct VarCapture {
1296 };
1298 for (const auto &VariableDef : VariableDefs) {
1299 VarCapture VC;
1300 VC.Name = VariableDef.first;
1301 StringRef Value = Context->GlobalVariableTable[VC.Name];
1304 VC.Range = SMRange(Start, End);
1306 }
1307 for (const auto &VariableDef : NumericVariableDefs) {
1308 VarCapture VC;
1309 VC.Name = VariableDef.getKey();
1310 std::optional StrValue =
1311 VariableDef.getValue().DefinedNumericVariable->getStringValue();
1312 if (!StrValue)
1313 continue;
1316 VC.Range = SMRange(Start, End);
1318 }
1319
1320
1321 llvm::sort(VarCaptures, [](const VarCapture &A, const VarCapture &B) {
1323 return false;
1324 assert(A.Range.Start != B.Range.Start &&
1325 "unexpected overlapping variable captures");
1326 return A.Range.Start.getPointer() < B.Range.Start.getPointer();
1327 });
1328
1329 for (const VarCapture &VC : VarCaptures) {
1332 OS << "captured var \"" << VC.Name << "\"";
1333 if (Diags)
1334 Diags->emplace_back(SM, CheckTy, getLoc(), MatchTy, VC.Range, OS.str());
1335 else
1337 }
1338}
1339
1343 StringRef Buffer, size_t Pos, size_t Len,
1344 std::vector *Diags,
1345 bool AdjustPrevDiags = false) {
1349 if (Diags) {
1350 if (AdjustPrevDiags) {
1351 SMLoc CheckLoc = Diags->rbegin()->CheckLoc;
1352 for (auto I = Diags->rbegin(), E = Diags->rend();
1353 I != E && I->CheckLoc == CheckLoc; ++I)
1354 I->MatchTy = MatchTy;
1355 } else
1356 Diags->emplace_back(SM, CheckTy, Loc, MatchTy, Range);
1357 }
1359}
1360
1362 std::vector *Diags) const {
1363
1364
1365
1366
1367 size_t NumLinesForward = 0;
1369 double BestQuality = 0;
1370
1371
1372 if (size_t(4096) * size_t(2048) <
1373 std::min(size_t(4096), Buffer.size()) *
1374 std::max(FixedStr.size(), RegExStr.size()))
1375 return;
1376
1377
1378 for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) {
1379 if (Buffer[i] == '\n')
1380 ++NumLinesForward;
1381
1382
1383
1384 if (Buffer[i] == ' ' || Buffer[i] == '\t')
1385 continue;
1386
1387
1388
1389 unsigned Distance = computeMatchDistance(Buffer.substr(i));
1390 double Quality = Distance + (NumLinesForward / 100.);
1391
1393 Best = i;
1394 BestQuality = Quality;
1395 }
1396 }
1397
1398
1399
1400
1401 if (Best && Best != StringRef::npos && BestQuality < 50) {
1404 getCheckTy(), Buffer, Best, 0, Diags);
1406 "possible intended match here");
1407
1408
1409
1410 }
1411}
1412
1415 auto VarIter = GlobalVariableTable.find(VarName);
1416 if (VarIter == GlobalVariableTable.end())
1418
1419 return VarIter->second;
1420}
1421
1422template <class... Types>
1423NumericVariable *FileCheckPatternContext::makeNumericVariable(Types... args) {
1424 NumericVariables.push_back(std::make_unique(args...));
1425 return NumericVariables.back().get();
1426}
1427
1429FileCheckPatternContext::makeStringSubstitution(StringRef VarName,
1430 size_t InsertIdx) {
1431 Substitutions.push_back(
1432 std::make_unique(this, VarName, InsertIdx));
1433 return Substitutions.back().get();
1434}
1435
1436Substitution *FileCheckPatternContext::makeNumericSubstitution(
1438 size_t InsertIdx) {
1439 Substitutions.push_back(std::make_unique(
1440 this, ExpressionStr, std::move(Expression), InsertIdx));
1441 return Substitutions.back().get();
1442}
1443
1445
1447
1448 size_t BracketDepth = 0;
1449
1450 while (!Str.empty()) {
1451 if (Str.starts_with("]]") && BracketDepth == 0)
1453 if (Str[0] == '\\') {
1454
1455 Str = Str.substr(2);
1457 } else {
1458 switch (Str[0]) {
1459 default:
1460 break;
1461 case '[':
1462 BracketDepth++;
1463 break;
1464 case ']':
1465 if (BracketDepth == 0) {
1468 "missing closing \"]\" for regex variable");
1469 exit(1);
1470 }
1471 BracketDepth--;
1472 break;
1473 }
1474 Str = Str.substr(1);
1476 }
1477 }
1478
1480}
1481
1485
1487 Ptr != End; ++Ptr) {
1488
1489 if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') {
1490 continue;
1491 }
1492
1493
1494
1495 if (Req.NoCanonicalizeWhiteSpace || (*Ptr != ' ' && *Ptr != '\t')) {
1497 continue;
1498 }
1499
1500
1502 while (Ptr + 1 != End && (Ptr[1] == ' ' || Ptr[1] == '\t'))
1503 ++Ptr;
1504 }
1505
1506
1509}
1510
1523
1525 return (isAlnum(c) || c == '-' || c == '_');
1526}
1527
1529 assert(Count > 0 && "zero and negative counts are not supported");
1531 "count supported only for plain CHECK directives");
1532 Count = C;
1533 return *this;
1534}
1535
1537 if (Modifiers.none())
1538 return "";
1539 std::string Ret;
1541 OS << '{';
1543 OS << "LITERAL";
1544 OS << '}';
1545 return Ret;
1546}
1547
1549
1550 auto WithModifiers = [this, Prefix](StringRef Str) -> std::string {
1552 };
1553
1554 switch (Kind) {
1556 return "invalid";
1558 return "misspelled";
1560 if (Count > 1)
1561 return WithModifiers("-COUNT");
1562 return WithModifiers("");
1564 return WithModifiers("-NEXT");
1566 return WithModifiers("-SAME");
1568 return WithModifiers("-NOT");
1570 return WithModifiers("-DAG");
1572 return WithModifiers("-LABEL");
1574 return WithModifiers("-EMPTY");
1576 return std::string(Prefix);
1578 return "implicit EOF";
1580 return "bad NOT";
1582 return "bad COUNT";
1583 }
1585}
1586
1587static std::pair<Check::FileCheckType, StringRef>
1589 bool &Misspelled) {
1590 if (Buffer.size() <= Prefix.size())
1592
1594
1598
1600 }
1601
1603 -> std::pair<Check::FileCheckType, StringRef> {
1605 return {Ret, Rest};
1608
1609
1610 do {
1611
1612 Rest = Rest.ltrim();
1614 Ret.setLiteralMatch();
1615 else
1617
1618 Rest = Rest.ltrim();
1622 return {Ret, Rest};
1623 };
1624
1625
1628 if (Rest.front() == '{')
1630
1632 Misspelled = true;
1635
1639
1643 if (Rest.front() != ':' && Rest.front() != '{')
1645 return ConsumeModifiers(
1647 }
1648
1649
1655
1658
1661
1664
1667
1670
1673
1675}
1676
1677static std::pair<Check::FileCheckType, StringRef>
1679 bool Misspelled = false;
1680 auto Res = FindCheckType(Req, Buffer, Prefix, Misspelled);
1683 return Res;
1684}
1685
1686
1692
1695
1704
1706
1709
1713 for (StringRef Prefix : CheckPrefixes)
1714 Prefixes.push_back({Prefix, Input.find(Prefix)});
1716 Prefixes.push_back({Prefix, Input.find(Prefix)});
1717
1718
1720 [](auto A, auto B) { return A.first.size() > B.first.size(); });
1721 }
1722
1723
1724
1728 "Buffer must be suffix of Input");
1729
1730 size_t From = Buffer.data() - Input.data();
1732 for (auto &[Prefix, Pos] : Prefixes) {
1733
1734 if (Pos < From)
1735 Pos = Input.find(Prefix, From);
1736
1738 (Match.empty() || size_t(Match.data() - Input.data()) > Pos))
1739 Match = StringRef(Input.substr(Pos, Prefix.size()));
1740 }
1741 return Match;
1742 }
1743};
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768static std::pair<StringRef, StringRef>
1770 StringRef &Buffer, unsigned &LineNumber,
1772 while (!Buffer.empty()) {
1773
1774 StringRef Prefix = Matcher.match(Buffer);
1775 if (Prefix.empty())
1776
1778
1779 assert(Prefix.data() >= Buffer.data() &&
1780 Prefix.data() < Buffer.data() + Buffer.size() &&
1781 "Prefix doesn't start inside of buffer!");
1782 size_t Loc = Prefix.data() - Buffer.data();
1785 LineNumber += Skipped.count('\n');
1786
1787
1788
1789
1790
1791
1792 if (Skipped.empty() || (Skipped.back())) {
1793
1795 std::tie(CheckTy, AfterSuffix) = FindCheckType(Req, Buffer, Prefix);
1796
1797
1799 return {Prefix, AfterSuffix};
1800 }
1801
1802
1803
1804
1806 }
1807
1808
1810}
1811
1813 assert(!LineVariable && "@LINE pseudo numeric variable already created");
1815 LineVariable = makeNumericVariable(
1817 GlobalNumericVariableTable[LineName] = LineVariable;
1818}
1819
1822
1824
1827 std::pair<unsigned, unsigned> *ImpPatBufferIDRange) {
1828 if (ImpPatBufferIDRange)
1829 ImpPatBufferIDRange->first = ImpPatBufferIDRange->second = 0;
1830
1831 Error DefineError =
1832 PatternContext->defineCmdlineVariables(Req.GlobalDefines, SM);
1833 if (DefineError) {
1835 return true;
1836 }
1837
1838 PatternContext->createLineVariable();
1839
1840 std::vectorFileCheckString::DagNotPrefixInfo ImplicitNegativeChecks;
1841 for (StringRef PatternString : Req.ImplicitCheckNot) {
1842
1843
1844 std::string Prefix = "-implicit-check-not='";
1845 std::string Suffix = "'";
1847 (Prefix + PatternString + Suffix).str(), "command line");
1848
1850 CmdLine->getBuffer().substr(Prefix.size(), PatternString.size());
1852 if (ImpPatBufferIDRange) {
1853 if (ImpPatBufferIDRange->first == ImpPatBufferIDRange->second) {
1854 ImpPatBufferIDRange->first = BufferID;
1855 ImpPatBufferIDRange->second = BufferID + 1;
1856 } else {
1857 assert(BufferID == ImpPatBufferIDRange->second &&
1858 "expected consecutive source buffer IDs");
1859 ++ImpPatBufferIDRange->second;
1860 }
1861 }
1862
1863 ImplicitNegativeChecks.emplace_back(
1866 ImplicitNegativeChecks.back().DagNotPat.parsePattern(
1867 PatternInBuffer, "IMPLICIT-CHECK", SM, Req);
1868 }
1869
1870 std::vectorFileCheckString::DagNotPrefixInfo DagNotMatches =
1871 ImplicitNegativeChecks;
1872
1873
1874 unsigned LineNumber = 1;
1875
1877 PrefixMatcher Matcher(Req.CheckPrefixes, Req.CommentPrefixes, Buffer);
1878 std::set PrefixesNotFound(Req.CheckPrefixes.begin(),
1879 Req.CheckPrefixes.end());
1880 const size_t DistinctPrefixes = PrefixesNotFound.size();
1881 while (true) {
1883
1884
1887 std::tie(UsedPrefix, AfterSuffix) =
1889 if (UsedPrefix.empty())
1890 break;
1892 PrefixesNotFound.erase(UsedPrefix);
1893
1895 "Failed to move Buffer's start forward, or pointed prefix outside "
1896 "of the buffer!");
1898 AfterSuffix.data() < Buffer.data() + Buffer.size() &&
1899 "Parsing after suffix doesn't start inside of buffer!");
1900
1901
1902 const char *UsedPrefixStart = UsedPrefix.data();
1903
1904
1905
1907 : AfterSuffix;
1908
1909
1912 AfterSuffix.data() - UsedPrefix.data());
1915 "misspelled directive '" + UsedDirective + "'");
1916 return true;
1917 }
1918
1919
1922 "unsupported -NOT combo on prefix '" + UsedPrefix + "'");
1923 return true;
1924 }
1925
1926
1929 "invalid count in -COUNT specification on prefix '" +
1930 UsedPrefix + "'");
1931 return true;
1932 }
1933
1934
1935
1936 if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines))
1938
1939
1941
1942
1944
1945
1947 Buffer = Buffer.substr(EOL);
1948
1949
1951 continue;
1952
1953
1954 Pattern P(CheckTy, PatternContext.get(), LineNumber);
1955 if (P.parsePattern(PatternBuffer, UsedPrefix, SM, Req))
1956 return true;
1957
1958
1962 "found '" + UsedPrefix + "-LABEL:'"
1963 " with variable definition or use");
1964 return true;
1965 }
1966
1967
1970 CheckStrings.empty()) {
1972 ? "NEXT"
1976 "found '" + UsedPrefix + "-" + Type +
1977 "' without previous '" + UsedPrefix + ": line");
1978 return true;
1979 }
1980
1981
1983 DagNotMatches.emplace_back(P, UsedPrefix);
1984 continue;
1985 }
1986
1987
1988 CheckStrings.emplace_back(std::move(P), UsedPrefix, PatternLoc,
1989 std::move(DagNotMatches));
1990 DagNotMatches = ImplicitNegativeChecks;
1991 }
1992
1993
1994
1995 const bool NoPrefixesFound = PrefixesNotFound.size() == DistinctPrefixes;
1996 const bool SomePrefixesUnexpectedlyNotUsed =
1997 !Req.AllowUnusedPrefixes && !PrefixesNotFound.empty();
1998 if ((NoPrefixesFound || SomePrefixesUnexpectedlyNotUsed) &&
1999 (ImplicitNegativeChecks.empty() || !Req.IsDefaultCheckPrefix)) {
2000 errs() << "error: no check strings found with prefix"
2001 << (PrefixesNotFound.size() > 1 ? "es " : " ");
2002 bool First = true;
2003 for (StringRef MissingPrefix : PrefixesNotFound) {
2005 errs() << ", ";
2006 errs() << "\'" << MissingPrefix << ":'";
2008 }
2009 errs() << '\n';
2010 return true;
2011 }
2012
2013
2014
2015 if (!DagNotMatches.empty()) {
2016 CheckStrings.emplace_back(
2019 std::move(DagNotMatches));
2020 }
2021
2022 return false;
2023}
2024
2025
2026
2029 int MatchedCount, StringRef Buffer,
2032 std::vector *Diags) {
2033
2034 bool HasError = !ExpectedMatch || MatchResult.TheError;
2035 bool PrintDiag = true;
2036 if (!HasError) {
2041
2042
2043
2044 PrintDiag = !Diags;
2045 }
2046
2047
2052 Buffer, MatchResult.TheMatch->Pos,
2053 MatchResult.TheMatch->Len, Diags);
2054 if (Diags) {
2057 }
2058 if (!PrintDiag) {
2059 assert(!HasError && "expected to report more diagnostics for error");
2061 }
2062
2063
2064 std::string Message = formatv("{0}: {1} string found in input",
2066 (ExpectedMatch ? "expected" : "excluded"))
2067 .str();
2069 Message += formatv(" ({0} out of {1})", MatchedCount, Pat.getCount()).str();
2073 {MatchRange});
2074
2075
2078
2079
2080
2081
2084 E.log(errs());
2085 if (Diags) {
2086 Diags->emplace_back(SM, Pat.getCheckTy(), Loc,
2087 FileCheckDiag::MatchFoundErrorNote,
2088 E.getRange(), E.getMessage().str());
2089 }
2090 });
2092}
2093
2094
2095
2096
2099 int MatchedCount, StringRef Buffer, Error MatchError,
2100 bool VerboseVerbose,
2101 std::vector *Diags) {
2102
2103 bool HasError = ExpectedMatch;
2104 bool HasPatternError = false;
2110 std::move(MatchError),
2112 HasError = HasPatternError = true;
2115 if (Diags)
2116 ErrorMsgs.push_back(E.getMessage().str());
2117 },
2118
2120
2121
2122 bool PrintDiag = true;
2123 if (!HasError) {
2124 if (!VerboseVerbose)
2126
2127
2128
2129 PrintDiag = !Diags;
2130 }
2131
2132
2133
2134
2135
2136
2137
2138
2140 Buffer, 0, Buffer.size(), Diags);
2141 if (Diags) {
2143 for (StringRef ErrorMsg : ErrorMsgs)
2144 Diags->emplace_back(SM, Pat.getCheckTy(), Loc, MatchTy, NoteRange,
2145 ErrorMsg);
2147 }
2148 if (!PrintDiag) {
2149 assert(!HasError && "expected to report more diagnostics for error");
2151 }
2152
2153
2154
2155 if (!HasPatternError) {
2156 std::string Message = formatv("{0}: {1} string not found in input",
2158 (ExpectedMatch ? "expected" : "excluded"))
2159 .str();
2161 Message +=
2162 formatv(" ({0} out of {1})", MatchedCount, Pat.getCount()).str();
2165 Message);
2167 "scanning from here");
2168 }
2169
2170
2171
2173 if (ExpectedMatch)
2176}
2177
2178
2179
2182 int MatchedCount, StringRef Buffer,
2185 std::vector *Diags) {
2187 return printMatch(ExpectedMatch, SM, Prefix, Loc, Pat, MatchedCount, Buffer,
2188 std::move(MatchResult), Req, Diags);
2189 return printNoMatch(ExpectedMatch, SM, Prefix, Loc, Pat, MatchedCount, Buffer,
2191 Diags);
2192}
2193
2194
2196 const char *&FirstNewLine) {
2197 unsigned NumNewLines = 0;
2198 while (true) {
2199
2201 if (Range.empty())
2202 return NumNewLines;
2203
2204 ++NumNewLines;
2205
2206
2207 if (Range.size() > 1 && (Range[1] == '\n' || Range[1] == '\r') &&
2211
2212 if (NumNewLines == 1)
2213 FirstNewLine = Range.begin();
2214 }
2215}
2216
2218 bool IsLabelScanMode, size_t &MatchLen,
2220 std::vector *Diags) const {
2221 size_t LastPos = 0;
2222 std::vector<const DagNotPrefixInfo *> NotStrings;
2223
2224
2225
2226
2227
2228 if (!IsLabelScanMode) {
2229
2230 LastPos = CheckDag(SM, Buffer, NotStrings, Req, Diags);
2233 }
2234
2235
2236 size_t LastMatchEnd = LastPos;
2237 size_t FirstMatchPos = 0;
2238
2239
2240 assert(Pat.getCount() != 0 && "pattern count can not be zero");
2241 for (int i = 1; i <= Pat.getCount(); i++) {
2243
2245
2246
2248 Pat, i, MatchBuffer,
2249 std::move(MatchResult), Req, Diags)) {
2252 }
2253
2254 size_t MatchPos = MatchResult.TheMatch->Pos;
2255 if (i == 1)
2256 FirstMatchPos = LastPos + MatchPos;
2257
2258
2259 LastMatchEnd += MatchPos + MatchResult.TheMatch->Len;
2260 }
2261
2262 MatchLen = LastMatchEnd - FirstMatchPos;
2263
2264
2265
2266 if (!IsLabelScanMode) {
2267 size_t MatchPos = FirstMatchPos - LastPos;
2269 StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos);
2270
2271
2272
2273 if (CheckNext(SM, SkippedRegion)) {
2275 Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen,
2278 }
2279
2280
2281
2282 if (CheckSame(SM, SkippedRegion)) {
2284 Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen,
2287 }
2288
2289
2290
2291 if (CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2293 }
2294
2295 return FirstMatchPos;
2296}
2297
2301 return false;
2302
2303 Twine CheckName =
2306
2307
2308 const char *FirstNewLine = nullptr;
2310
2311 if (NumNewLines == 0) {
2313 CheckName + ": is on the same line as previous match");
2315 "'next' match was here");
2317 "previous match ended here");
2318 return true;
2319 }
2320
2321 if (NumNewLines != 1) {
2323 CheckName +
2324 ": is not on the line after the previous match");
2326 "'next' match was here");
2328 "previous match ended here");
2330 "non-matching line after previous match is here");
2331 return true;
2332 }
2333
2334 return false;
2335}
2336
2339 return false;
2340
2341
2342 const char *FirstNewLine = nullptr;
2344
2345 if (NumNewLines != 0) {
2348 "-SAME: is not on the same line as the previous match");
2350 "'next' match was here");
2352 "previous match ended here");
2353 return true;
2354 }
2355
2356 return false;
2357}
2358
2361 const std::vector<const DagNotPrefixInfo *> &NotStrings,
2362 const FileCheckRequest &Req, std::vector *Diags) const {
2363 bool DirectiveFail = false;
2364 for (auto NotInfo : NotStrings) {
2366 "Expect CHECK-NOT!");
2369 false, SM, NotInfo->DagNotPrefix,
2370 NotInfo->DagNotPat.getLoc(), NotInfo->DagNotPat, 1, Buffer,
2371 std::move(MatchResult), Req, Diags)) {
2373 DirectiveFail = true;
2374 continue;
2375 }
2376 }
2377 return DirectiveFail;
2378}
2379
2380size_t
2382 std::vector<const DagNotPrefixInfo *> &NotStrings,
2384 std::vector *Diags) const {
2386 return 0;
2387
2388
2389 size_t StartPos = 0;
2390
2391 struct MatchRange {
2392 size_t Pos;
2393 size_t End;
2394 };
2395
2396
2397
2398 std::list MatchRanges;
2399
2400
2401
2403 PatItr != PatEnd; ++PatItr) {
2404 const Pattern &Pat = PatItr->DagNotPat;
2405 const StringRef DNPrefix = PatItr->DagNotPrefix;
2408 "Invalid CHECK-DAG or CHECK-NOT!");
2409
2411 NotStrings.push_back(&*PatItr);
2412 continue;
2413 }
2414
2416
2417
2418 size_t MatchLen = 0, MatchPos = StartPos;
2419
2420
2421
2422 for (auto MI = MatchRanges.begin(), ME = MatchRanges.end(); true; ++MI) {
2425
2426
2429 Pat.getLoc(), Pat, 1, MatchBuffer,
2430 std::move(MatchResult), Req, Diags)) {
2434 }
2435 }
2436 MatchLen = MatchResult.TheMatch->Len;
2437
2438
2439 MatchPos += MatchResult.TheMatch->Pos;
2440 MatchRange M{MatchPos, MatchPos + MatchLen};
2442
2443
2444
2445 if (MatchRanges.empty())
2446 MatchRanges.insert(MatchRanges.end(), M);
2447 else {
2448 auto Block = MatchRanges.begin();
2449 Block->Pos = std::min(Block->Pos, M.Pos);
2450 Block->End = std::max(Block->End, M.End);
2451 }
2452 break;
2453 }
2454
2455 bool Overlap = false;
2457 if (M.Pos < MI->End) {
2458
2459
2460 Overlap = MI->Pos < M.End;
2461 break;
2462 }
2463 }
2464 if (!Overlap) {
2465
2466 MatchRanges.insert(MI, M);
2467 break;
2468 }
2470
2471
2472
2473 if (!Diags) {
2476 SMRange OldRange(OldStart, OldEnd);
2478 "match discarded, overlaps earlier DAG match here",
2479 {OldRange});
2480 } else {
2481 SMLoc CheckLoc = Diags->rbegin()->CheckLoc;
2482 for (auto I = Diags->rbegin(), E = Diags->rend();
2483 I != E && I->CheckLoc == CheckLoc; ++I)
2485 }
2486 }
2487 MatchPos = MI->End;
2488 }
2491 true, SM, DNPrefix, Pat.getLoc(), Pat, 1, Buffer,
2493 Diags));
2494
2495
2496 if (std::next(PatItr) == PatEnd ||
2497 std::next(PatItr)->DagNotPat.getCheckTy() == Check::CheckNot) {
2498 if (!NotStrings.empty()) {
2499
2500
2501
2503 Buffer.slice(StartPos, MatchRanges.begin()->Pos);
2504 if (CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
2506
2507 NotStrings.clear();
2508 }
2509
2510
2511 StartPos = MatchRanges.rbegin()->End;
2512
2513 MatchRanges.clear();
2514 }
2515 }
2516
2517 return StartPos;
2518}
2519
2522 for (StringRef Prefix : SuppliedPrefixes) {
2523 if (Prefix.empty()) {
2524 errs() << "error: supplied " << Kind << " prefix must not be the empty "
2525 << "string\n";
2526 return false;
2527 }
2528 static const Regex Validator("^[a-zA-Z0-9_-]*$");
2529 if (!Validator.match(Prefix)) {
2530 errs() << "error: supplied " << Kind << " prefix must start with a "
2531 << "letter and contain only alphanumeric characters, hyphens, and "
2532 << "underscores: '" << Prefix << "'\n";
2533 return false;
2534 }
2535 if (!UniquePrefixes.insert(Prefix).second) {
2536 errs() << "error: supplied " << Kind << " prefix must be unique among "
2537 << "check and comment prefixes: '" << Prefix << "'\n";
2538 return false;
2539 }
2540 }
2541 return true;
2542}
2543
2546
2547 if (Req.CheckPrefixes.empty())
2549 if (Req.CommentPrefixes.empty())
2551
2552
2553 if (("check", UniquePrefixes, Req.CheckPrefixes))
2554 return false;
2555 if (("comment", UniquePrefixes, Req.CommentPrefixes))
2556 return false;
2557 return true;
2558}
2559
2562 assert(GlobalVariableTable.empty() && GlobalNumericVariableTable.empty() &&
2563 "Overriding defined variable with command-line variable definitions");
2564
2565 if (CmdlineDefines.empty())
2567
2568
2569
2570
2571 unsigned I = 0;
2573 std::string CmdlineDefsDiag;
2575 for (StringRef CmdlineDef : CmdlineDefines) {
2576 std::string DefPrefix = ("Global define #" + Twine(++I) + ": ").str();
2577 size_t EqIdx = CmdlineDef.find('=');
2579 CmdlineDefsIndices.push_back(std::make_pair(CmdlineDefsDiag.size(), 0));
2580 continue;
2581 }
2582
2583 if (CmdlineDef[0] == '#') {
2584
2585
2586
2587 CmdlineDefsDiag += (DefPrefix + CmdlineDef + " (parsed as: [[").str();
2588 std::string SubstitutionStr = std::string(CmdlineDef);
2589 SubstitutionStr[EqIdx] = ':';
2591 std::make_pair(CmdlineDefsDiag.size(), SubstitutionStr.size()));
2592 CmdlineDefsDiag += (SubstitutionStr + Twine("]])\n")).str();
2593 } else {
2594 CmdlineDefsDiag += DefPrefix;
2596 std::make_pair(CmdlineDefsDiag.size(), CmdlineDef.size()));
2597 CmdlineDefsDiag += (CmdlineDef + "\n").str();
2598 }
2599 }
2600
2601
2602
2603
2604 std::unique_ptr CmdLineDefsDiagBuffer =
2606 StringRef CmdlineDefsDiagRef = CmdLineDefsDiagBuffer->getBuffer();
2608
2609 for (std::pair<size_t, size_t> CmdlineDefIndices : CmdlineDefsIndices) {
2610 StringRef CmdlineDef = CmdlineDefsDiagRef.substr(CmdlineDefIndices.first,
2611 CmdlineDefIndices.second);
2612 if (CmdlineDef.empty()) {
2614 std::move(Errs),
2616 "missing equal sign in global definition"));
2617 continue;
2618 }
2619
2620
2621 if (CmdlineDef[0] == '#') {
2622
2623
2625 std::optional<NumericVariable *> DefinedNumericVariable;
2628 DefinedNumericVariable, false,
2629 std::nullopt, this, SM);
2630 if (!ExpressionResult) {
2632 continue;
2633 }
2634 std::unique_ptr Expression = std::move(*ExpressionResult);
2635
2636
2637
2638
2642 continue;
2643 }
2644
2645 assert(DefinedNumericVariable && "No variable defined");
2646 (*DefinedNumericVariable)->setValue(*Value);
2647
2648
2649 GlobalNumericVariableTable[(*DefinedNumericVariable)->getName()] =
2650 *DefinedNumericVariable;
2651 } else {
2652
2653 std::pair<StringRef, StringRef> CmdlineNameVal = CmdlineDef.split('=');
2654 StringRef CmdlineName = CmdlineNameVal.first;
2655 StringRef OrigCmdlineName = CmdlineName;
2658 if (!ParseVarResult) {
2660 continue;
2661 }
2662
2663
2664
2665 if (ParseVarResult->IsPseudo || !CmdlineName.empty()) {
2668 SM, OrigCmdlineName,
2669 "invalid name in string variable definition '" +
2670 OrigCmdlineName + "'"));
2671 continue;
2672 }
2673 StringRef Name = ParseVarResult->Name;
2674
2675
2676
2677 if (GlobalNumericVariableTable.contains(Name)) {
2680 "numeric variable with name '" +
2681 Name + "' already exists"));
2682 continue;
2683 }
2684 GlobalVariableTable.insert(CmdlineNameVal);
2685
2686
2687
2688
2689
2690
2691 DefinedVariableTable[Name] = true;
2692 }
2693 }
2694
2695 return Errs;
2696}
2697
2701 if (Var.first()[0] != '$')
2702 LocalPatternVars.push_back(Var.first());
2703
2704
2705
2706
2707
2708
2709
2710 for (const auto &Var : GlobalNumericVariableTable)
2711 if (Var.first()[0] != '$') {
2712 Var.getValue()->clearValue();
2713 LocalNumericVars.push_back(Var.first());
2714 }
2715
2716 for (const auto &Var : LocalPatternVars)
2717 GlobalVariableTable.erase(Var);
2718 for (const auto &Var : LocalNumericVars)
2719 GlobalNumericVariableTable.erase(Var);
2720}
2721
2723 std::vector *Diags) {
2724 bool ChecksFailed = false;
2725
2726 unsigned i = 0, j = 0, e = CheckStrings.size();
2727 while (true) {
2729 if (j == e) {
2730 CheckRegion = Buffer;
2731 } else {
2734 ++j;
2735 continue;
2736 }
2737
2738
2739 size_t MatchLabelLen = 0;
2740 size_t MatchLabelPos =
2741 CheckLabelStr.Check(SM, Buffer, true, MatchLabelLen, Req, Diags);
2743
2744 return false;
2745
2746 CheckRegion = Buffer.substr(0, MatchLabelPos + MatchLabelLen);
2747 Buffer = Buffer.substr(MatchLabelPos + MatchLabelLen);
2748 ++j;
2749 }
2750
2751
2752
2753
2754 if (i != 0 && Req.EnableVarScope)
2755 PatternContext->clearLocalVars();
2756
2757 for (; i != j; ++i) {
2759
2760
2761
2762 size_t MatchLen = 0;
2763 size_t MatchPos =
2764 CheckStr.Check(SM, CheckRegion, false, MatchLen, Req, Diags);
2765
2767 ChecksFailed = true;
2768 i = j;
2769 break;
2770 }
2771
2772 CheckRegion = CheckRegion.substr(MatchPos + MatchLen);
2773 }
2774
2775 if (j == e)
2776 break;
2777 }
2778
2779
2780 return !ChecksFailed;
2781}
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
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.
Definition FileCheck.cpp:1769
static size_t SkipWord(StringRef Str, size_t Loc)
Definition FileCheck.cpp:1687
static char popFront(StringRef &S)
Definition FileCheck.cpp:364
constexpr StringLiteral SpaceChars
Definition FileCheck.cpp:361
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.
Definition FileCheck.cpp:2180
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,...
Definition FileCheck.cpp:2097
static std::pair< Check::FileCheckType, StringRef > FindCheckType(const FileCheckRequest &Req, StringRef Buffer, StringRef Prefix, bool &Misspelled)
Definition FileCheck.cpp:1588
static const char * DefaultCheckPrefixes[]
Definition FileCheck.cpp:1693
static const char * DefaultCommentPrefixes[]
Definition FileCheck.cpp:1694
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)
Definition FileCheck.cpp:1340
static unsigned CountNumNewlinesBetween(StringRef Range, const char *&FirstNewLine)
Counts the number of newlines in the specified range.
Definition FileCheck.cpp:2195
static APInt toSigned(APInt AbsVal, bool Negative)
Definition FileCheck.cpp:127
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,...
Definition FileCheck.cpp:2027
static bool ValidatePrefixes(StringRef Kind, StringSet<> &UniquePrefixes, ArrayRef< StringRef > SuppliedPrefixes)
Definition FileCheck.cpp:2520
static void addDefaultPrefixes(FileCheckRequest &Req)
Definition FileCheck.cpp:1696
static unsigned nextAPIntBitWidth(unsigned BitWidth)
Definition FileCheck.cpp:122
static bool IsPartOfWord(char c)
Definition FileCheck.cpp:1524
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
StringSet - A set-like wrapper for the StringMap.
Class for arbitrary precision integers.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
APInt abs() const
Get the absolute value.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool isNegative() const
Determine sign of this APInt.
LLVM_ABI APInt sadd_ov(const APInt &RHS, bool &Overflow) const
LLVM_ABI APInt sdiv_ov(const APInt &RHS, bool &Overflow) const
static constexpr unsigned APINT_BITS_PER_WORD
Bits in a word.
LLVM_ABI APInt smul_ov(const APInt &RHS, bool &Overflow) const
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
bool isSignBitSet() const
Determine if sign bit of this APInt is set.
bool slt(const APInt &RHS) const
Signed less than comparison.
LLVM_ABI APInt ssub_ov(const APInt &RHS, bool &Overflow) const
LLVM_ABI void toString(SmallVectorImpl< char > &Str, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false) const
Converts an APInt to a string and append it to Str.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool empty() const
empty - Check if the array is empty.
Expected< ExpressionFormat > getImplicitFormat(const SourceMgr &SM) const override
Definition FileCheck.cpp:241
Expected< APInt > eval() const override
Evaluates the value of the binary operation represented by this AST, using EvalBinop on the result of...
Definition FileCheck.cpp:202
LLVM_ABI std::string getDescription(StringRef Prefix) const
Definition FileCheck.cpp:1548
bool isLiteralMatch() const
LLVM_ABI std::string getModifiersDescription() const
Definition FileCheck.cpp:1536
LLVM_ABI FileCheckType & setCount(int C)
Definition FileCheck.cpp:1528
Class to represent an error holding a diagnostic with location information used when printing it.
static LLVM_ABI_FOR_TEST char ID
static Error get(const SourceMgr &SM, SMLoc Loc, const Twine &ErrMsg, SMRange Range={})
An error that has already been reported.
static Error reportedOrSuccess(bool HasErrorReported)
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
virtual Expected< APInt > eval() const =0
Evaluates and.
StringRef getExpressionStr() const
Class representing an expression and its matching format.
ExpressionAST * getAST() const
Class holding the Pattern global state, shared by all patterns: tables holding values of variables an...
LLVM_ABI_FOR_TEST Error defineCmdlineVariables(ArrayRef< StringRef > CmdlineDefines, SourceMgr &SM)
Defines string and numeric variables from definitions given on the command line, passed as a vector o...
Definition FileCheck.cpp:2560
LLVM_ABI_FOR_TEST void createLineVariable()
Create @LINE pseudo variable.
Definition FileCheck.cpp:1812
LLVM_ABI_FOR_TEST Expected< StringRef > getPatternVarValue(StringRef VarName)
Definition FileCheck.cpp:1414
LLVM_ABI_FOR_TEST void clearLocalVars()
Undefines local variables (variables whose name does not start with a '$' sign), i....
Definition FileCheck.cpp:2698
LLVM_ABI bool readCheckFile(SourceMgr &SM, StringRef Buffer, std::pair< unsigned, unsigned > *ImpPatBufferIDRange=nullptr)
Reads the check file from Buffer and records the expected strings it contains.
Definition FileCheck.cpp:1825
LLVM_ABI StringRef CanonicalizeFile(MemoryBuffer &MB, SmallVectorImpl< char > &OutputBuffer)
Canonicalizes whitespaces in the file.
Definition FileCheck.cpp:1482
LLVM_ABI FileCheck(FileCheckRequest Req)
Definition FileCheck.cpp:1820
LLVM_ABI bool checkInput(SourceMgr &SM, StringRef Buffer, std::vector< FileCheckDiag > *Diags=nullptr)
Checks the input to FileCheck provided in the Buffer against the expected strings read from the check...
Definition FileCheck.cpp:2722
LLVM_ABI bool ValidateCheckPrefixes()
Definition FileCheck.cpp:2544
This interface provides simple read-only access to a block of memory, and provides simple methods for...
size_t getBufferSize() const
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
const char * getBufferEnd() const
const char * getBufferStart() const
static LLVM_ABI_FOR_TEST char ID
Expected< std::string > getResultForDiagnostics() const override
Definition FileCheck.cpp:277
Expected< std::string > getResultRegex() const override
Definition FileCheck.cpp:267
Expected< APInt > eval() const override
Definition FileCheck.cpp:194
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< size_t > getDefLineNumber() const
Class to represent an overflow error that might result when manipulating a value.
static LLVM_ABI_FOR_TEST char ID
This class represents success/failure for parsing-like operations that find it important to chain tog...
static LLVM_ABI_FOR_TEST Expected< VariableProperties > parseVariable(StringRef &Str, const SourceMgr &SM)
Parses the string at the start of Str for a variable name.
Definition FileCheck.cpp:329
LLVM_ABI_FOR_TEST MatchResult match(StringRef Buffer, const SourceMgr &SM) const
Matches the pattern string against the input buffer Buffer.
Definition FileCheck.cpp:1116
void printFuzzyMatch(const SourceMgr &SM, StringRef Buffer, std::vector< FileCheckDiag > *Diags) const
Definition FileCheck.cpp:1361
void printSubstitutions(const SourceMgr &SM, StringRef Buffer, SMRange MatchRange, FileCheckDiag::MatchType MatchTy, std::vector< FileCheckDiag > *Diags) const
Prints the value of successful substitutions.
Definition FileCheck.cpp:1252
static LLVM_ABI_FOR_TEST Expected< std::unique_ptr< Expression > > parseNumericSubstitutionBlock(StringRef Expr, std::optional< NumericVariable * > &DefinedNumericVariable, bool IsLegacyLineExpr, std::optional< size_t > LineNumber, FileCheckPatternContext *Context, const SourceMgr &SM)
Parses Expr for a numeric substitution block at line LineNumber, or before input is parsed if LineNum...
Definition FileCheck.cpp:654
LLVM_ABI_FOR_TEST void printVariableDefs(const SourceMgr &SM, FileCheckDiag::MatchType MatchTy, std::vector< FileCheckDiag > *Diags) const
Definition FileCheck.cpp:1287
static LLVM_ABI_FOR_TEST bool isValidVarNameStart(char C)
Definition FileCheck.cpp:326
Check::FileCheckType getCheckTy() const
LLVM_ABI_FOR_TEST bool parsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM, const FileCheckRequest &Req)
Parses the pattern in PatternStr and initializes this Pattern instance accordingly.
Definition FileCheck.cpp:801
@ Newline
Compile for newline-sensitive matching.
@ IgnoreCase
Compile for matching that ignores upper/lower case distinctions.
static LLVM_ABI std::string escape(StringRef String)
Turn String into a regex by escaping its special characters.
LLVM_ABI bool match(StringRef String, SmallVectorImpl< StringRef > *Matches=nullptr, std::string *Error=nullptr) const
matches - Match the regex against a given String.
Represents a location in source code.
static SMLoc getFromPointer(const char *Ptr)
Represents a range in source code.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
LLVM_ABI std::pair< unsigned, unsigned > getLineAndColumn(SMLoc Loc, unsigned BufferID=0) const
Find the line and column number for the specified location in the specified file.
LLVM_ABI void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges={}, ArrayRef< SMFixIt > FixIts={}, bool ShowColors=true) const
Emit a message about the specified location with the specified string.
unsigned AddNewSourceBuffer(std::unique_ptr< MemoryBuffer > F, SMLoc IncludeLoc)
Add a new source buffer to this source manager.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
StringMapEntry - This is used to represent one value that is inserted into a StringMap.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
static constexpr size_t npos
bool consumeInteger(unsigned Radix, T &Result)
Parse the current string as an integer of the specified radix.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
LLVM_ABI unsigned edit_distance(StringRef Other, bool AllowReplacements=true, unsigned MaxEditDistance=0) const
Determine the edit distance between this string and another string.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
constexpr size_t size() const
size - Get the string size.
char front() const
front - Get the first character in the string.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
StringRef ltrim(char Char) const
Return string with consecutive Char characters starting from the the left removed.
bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
bool consume_front(StringRef Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
size_t find_first_of(char C, size_t From=0) const
Find the first character in the string that is C, or npos if not found.
StringRef rtrim(char Char) const
Return string with consecutive Char characters starting from the right removed.
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
StringRef trim(char Char) const
Return string with consecutive Char characters starting from the left and right removed.
LLVM_ABI size_t find_insensitive(char C, size_t From=0) const
Search for the first character C in the string, ignoring case.
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
LLVM_ABI size_t find_first_not_of(char C, size_t From=0) const
Find the first character in the string that is not C or npos if not found.
StringSet - A wrapper for StringMap that provides set-like functionality.
void insert_range(Range &&R)
std::pair< typename Base::iterator, bool > insert(StringRef key)
Expected< std::string > getResultRegex() const override
Definition FileCheck.cpp:288
Expected< std::string > getResultForDiagnostics() const override
Definition FileCheck.cpp:296
Class representing a substitution to perform in the RegExStr string.
StringRef getFromString() const
FileCheckPatternContext * Context
Pointer to a class instance holding, among other things, the table with the values of live string var...
virtual Expected< std::string > getResultRegex() const =0
virtual Expected< std::string > getResultForDiagnostics() const =0
StringRef FromStr
The string that needs to be substituted for something else.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
Class to represent an undefined variable error, which quotes that variable's name when printed.
static LLVM_ABI_FOR_TEST char ID
LLVM Value Representation.
raw_ostream & write_escaped(StringRef Str, bool UseHexEscapes=false)
Output Str, turning '\', '\t', ' ', '"', and anything that doesn't satisfy llvm::isPrint into an esca...
A raw_ostream that writes to an std::string.
A raw_ostream that writes to an SmallVector or SmallString.
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.
LLVM_ABI void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
LLVM_ABI_FOR_TEST Expected< APInt > exprAdd(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
Performs operation and.
Definition FileCheck.cpp:155
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
Expected< APInt >(*)(const APInt &, const APInt &, bool &) binop_eval_t
Type of functions evaluating a given binary operation.
bool isAlpha(char C)
Checks if character C is a valid letter as classified by "C" locale.
Error joinErrors(Error E1, Error E2)
Concatenate errors.
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI_FOR_TEST Expected< APInt > exprMul(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
Definition FileCheck.cpp:165
FunctionAddr VTableAddr Count
bool isAlnum(char C)
Checks whether character C is either a decimal digit or an uppercase or lowercase letter as classifie...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
constexpr unsigned BitWidth
bool isPrint(char C)
Checks whether character C is printable.
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)
Definition FileCheck.cpp:179
LLVM_ABI_FOR_TEST Expected< APInt > exprDiv(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
Definition FileCheck.cpp:170
Expected< APInt > exprMin(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
Definition FileCheck.cpp:185
LLVM_ABI_FOR_TEST Expected< APInt > exprSub(const APInt &Lhs, const APInt &Rhs, bool &Overflow)
Definition FileCheck.cpp:160
void consumeError(Error Err)
Consume a Error without doing anything.
Implement std::hash so that hash_code can be used in STL containers.
Definition FileCheck.cpp:1705
StringRef match(StringRef Buffer)
Find the next match of a prefix in Buffer.
Definition FileCheck.cpp:1725
StringRef Input
Definition FileCheck.cpp:1708
SmallVector< std::pair< StringRef, size_t > > Prefixes
Prefixes and their first occurrence past the current position.
Definition FileCheck.cpp:1707
PrefixMatcher(ArrayRef< StringRef > CheckPrefixes, ArrayRef< StringRef > CommentPrefixes, StringRef Input)
Definition FileCheck.cpp:1710
Type representing the format an expression value should be textualized into for matching.
LLVM_ABI_FOR_TEST APInt valueFromStringRepr(StringRef StrVal, const SourceMgr &SM) const
Definition FileCheck.cpp:136
StringRef toString() const
Definition FileCheck.cpp:31
LLVM_ABI_FOR_TEST Expected< std::string > getMatchingString(APInt Value) const
Definition FileCheck.cpp:80
LLVM_ABI_FOR_TEST Expected< std::string > getWildcardRegex() const
Definition FileCheck.cpp:47
@ HexLower
Value should be printed as a lowercase hex number.
@ HexUpper
Value should be printed as an uppercase hex number.
@ Signed
Value is a signed integer and should be printed as a decimal number.
@ Unsigned
Value is an unsigned integer and should be printed as a decimal number.
@ NoFormat
Denote absence of format.
std::string Note
A note to replace the one normally indicated by MatchTy, or the empty string if none.
enum llvm::FileCheckDiag::MatchType MatchTy
unsigned InputStartLine
The search range if MatchTy starts with MatchNone, or the match range otherwise.
LLVM_ABI FileCheckDiag(const SourceMgr &SM, const Check::FileCheckType &CheckTy, SMLoc CheckLoc, MatchType MatchTy, SMRange InputRange, StringRef Note="")
Definition FileCheck.cpp:1511
Check::FileCheckType CheckTy
What is the FileCheck directive for this diagnostic?
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 ...
SMLoc CheckLoc
Where is the FileCheck directive for this diagnostic?
Contains info about various FileCheck options.
bool IsDefaultCheckPrefix
bool NoCanonicalizeWhiteSpace
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.
Definition FileCheck.cpp:2298
Pattern Pat
The pattern to match.
bool CheckSame(const SourceMgr &SM, StringRef Buffer) const
Verifies that there is no newline in the given Buffer.
Definition FileCheck.cpp:2337
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".
Definition FileCheck.cpp:2381
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".
Definition FileCheck.cpp:2217
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.
Definition FileCheck.cpp:2359
std::optional< Match > TheMatch
Parsing information about a variable.