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] != '_' && isAlnum(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 (Regex(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) {

1322 if (&A == &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() || IsPartOfWord(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;

2456 for (; MI != ME; ++MI) {

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 (ValidatePrefixes("check", UniquePrefixes, Req.CheckPrefixes))

2554 return false;

2555 if (ValidatePrefixes("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.