diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/FileCheck/FileCheck.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/FileCheck/FileCheck.cpp | 382 | 
1 files changed, 187 insertions, 195 deletions
diff --git a/contrib/llvm-project/llvm/lib/FileCheck/FileCheck.cpp b/contrib/llvm-project/llvm/lib/FileCheck/FileCheck.cpp index 3e4514f2545b..b728c14d288a 100644 --- a/contrib/llvm-project/llvm/lib/FileCheck/FileCheck.cpp +++ b/contrib/llvm-project/llvm/lib/FileCheck/FileCheck.cpp @@ -78,18 +78,9 @@ Expected<std::string> ExpressionFormat::getWildcardRegex() const {  }  Expected<std::string> -ExpressionFormat::getMatchingString(ExpressionValue IntegerValue) const { -  APInt IntValue = IntegerValue.getAPIntValue(); -  // Error out for values that cannot be represented by the appropriate 64-bit -  // integer (e.g. int64_t for a signed format) to keep the getter of -  // ExpressionValue as an APInt an NFC. -  if (Value == Kind::Signed) { -    if (!IntValue.isSignedIntN(64)) -      return make_error<OverflowError>(); -  } else { -    if (!IntValue.isIntN(64)) -      return make_error<OverflowError>(); -  } +ExpressionFormat::getMatchingString(APInt IntValue) const { +  if (Value != Kind::Signed && IntValue.isNegative()) +    return make_error<OverflowError>();    unsigned Radix;    bool UpperCase = false; @@ -129,140 +120,122 @@ ExpressionFormat::getMatchingString(ExpressionValue IntegerValue) const {        .str();  } -Expected<ExpressionValue> -ExpressionFormat::valueFromStringRepr(StringRef StrVal, -                                      const SourceMgr &SM) const { -  bool ValueIsSigned = Value == Kind::Signed; -  // Both the FileCheck utility and library only call this method with a valid -  // value in StrVal. This is guaranteed by the regex returned by -  // getWildcardRegex() above. Only underflow and overflow errors can thus -  // occur. However new uses of this method could be added in the future so -  // the error message does not make assumptions about StrVal. -  StringRef IntegerParseErrorStr = "unable to represent numeric value"; -  if (ValueIsSigned) { -    int64_t SignedValue; - -    if (StrVal.getAsInteger(10, SignedValue)) -      return ErrorDiagnostic::get(SM, StrVal, IntegerParseErrorStr); +static unsigned nextAPIntBitWidth(unsigned BitWidth) { +  return (BitWidth < APInt::APINT_BITS_PER_WORD) ? APInt::APINT_BITS_PER_WORD +                                                 : BitWidth * 2; +} -    return ExpressionValue(SignedValue); -  } +static APInt toSigned(APInt AbsVal, bool Negative) { +  if (AbsVal.isSignBitSet()) +    AbsVal = AbsVal.zext(nextAPIntBitWidth(AbsVal.getBitWidth())); +  APInt Result = AbsVal; +  if (Negative) +    Result.negate(); +  return Result; +} +APInt ExpressionFormat::valueFromStringRepr(StringRef StrVal, +                                            const SourceMgr &SM) const { +  bool ValueIsSigned = Value == Kind::Signed; +  bool Negative = StrVal.consume_front("-");    bool Hex = Value == Kind::HexUpper || Value == Kind::HexLower; -  uint64_t UnsignedValue; -  bool MissingFormPrefix = AlternateForm && !StrVal.consume_front("0x"); +  bool MissingFormPrefix = +      !ValueIsSigned && AlternateForm && !StrVal.consume_front("0x");    (void)MissingFormPrefix;    assert(!MissingFormPrefix && "missing alternate form prefix"); -  if (StrVal.getAsInteger(Hex ? 16 : 10, UnsignedValue)) -    return ErrorDiagnostic::get(SM, StrVal, IntegerParseErrorStr); - -  return ExpressionValue(UnsignedValue); +  APInt ResultValue; +  [[maybe_unused]] bool ParseFailure = +      StrVal.getAsInteger(Hex ? 16 : 10, ResultValue); +  // Both the FileCheck utility and library only call this method with a valid +  // value in StrVal. This is guaranteed by the regex returned by +  // getWildcardRegex() above. +  assert(!ParseFailure && "unable to represent numeric value"); +  return toSigned(ResultValue, Negative);  } -Expected<ExpressionValue> llvm::operator+(const ExpressionValue &LeftOperand, -                                          const ExpressionValue &RightOperand) { -  bool Overflow; -  APInt Result = LeftOperand.getAPIntValue().sadd_ov( -      RightOperand.getAPIntValue(), Overflow); -  if (Overflow || -      (Result.isNegative() && !Result.isSignedIntN(Result.getBitWidth() - 1))) -    return make_error<OverflowError>(); - -  if (Result.isNegative()) -    return ExpressionValue(Result.getSExtValue()); -  else -    return ExpressionValue(Result.getZExtValue()); +Expected<APInt> llvm::exprAdd(const APInt &LeftOperand, +                              const APInt &RightOperand, bool &Overflow) { +  return LeftOperand.sadd_ov(RightOperand, Overflow);  } -Expected<ExpressionValue> llvm::operator-(const ExpressionValue &LeftOperand, -                                          const ExpressionValue &RightOperand) { -  bool Overflow; -  APInt Result = LeftOperand.getAPIntValue().ssub_ov( -      RightOperand.getAPIntValue(), Overflow); -  if (Overflow || -      (Result.isNegative() && !Result.isSignedIntN(Result.getBitWidth() - 1))) -    return make_error<OverflowError>(); - -  if (Result.isNegative()) -    return ExpressionValue(Result.getSExtValue()); -  else -    return ExpressionValue(Result.getZExtValue()); +Expected<APInt> llvm::exprSub(const APInt &LeftOperand, +                              const APInt &RightOperand, bool &Overflow) { +  return LeftOperand.ssub_ov(RightOperand, Overflow);  } -Expected<ExpressionValue> llvm::operator*(const ExpressionValue &LeftOperand, -                                          const ExpressionValue &RightOperand) { -  bool Overflow; -  APInt Result = LeftOperand.getAPIntValue().smul_ov( -      RightOperand.getAPIntValue(), Overflow); -  if (Overflow || -      (Result.isNegative() && !Result.isSignedIntN(Result.getBitWidth() - 1))) -    return make_error<OverflowError>(); - -  if (Result.isNegative()) -    return ExpressionValue(Result.getSExtValue()); -  else -    return ExpressionValue(Result.getZExtValue()); +Expected<APInt> llvm::exprMul(const APInt &LeftOperand, +                              const APInt &RightOperand, bool &Overflow) { +  return LeftOperand.smul_ov(RightOperand, Overflow);  } -Expected<ExpressionValue> llvm::operator/(const ExpressionValue &LeftOperand, -                                          const ExpressionValue &RightOperand) { +Expected<APInt> llvm::exprDiv(const APInt &LeftOperand, +                              const APInt &RightOperand, bool &Overflow) {    // Check for division by zero. -  if (RightOperand.getAPIntValue().isZero()) +  if (RightOperand.isZero())      return make_error<OverflowError>(); -  bool Overflow; -  APInt Result = LeftOperand.getAPIntValue().sdiv_ov( -      RightOperand.getAPIntValue(), Overflow); -  if (Overflow || -      (Result.isNegative() && !Result.isSignedIntN(Result.getBitWidth() - 1))) -    return make_error<OverflowError>(); - -  if (Result.isNegative()) -    return ExpressionValue(Result.getSExtValue()); -  else -    return ExpressionValue(Result.getZExtValue()); +  return LeftOperand.sdiv_ov(RightOperand, Overflow);  } -Expected<ExpressionValue> llvm::max(const ExpressionValue &LeftOperand, -                                    const ExpressionValue &RightOperand) { -  return LeftOperand.getAPIntValue().slt(RightOperand.getAPIntValue()) -             ? RightOperand -             : LeftOperand; +Expected<APInt> llvm::exprMax(const APInt &LeftOperand, +                              const APInt &RightOperand, bool &Overflow) { +  Overflow = false; +  return LeftOperand.slt(RightOperand) ? RightOperand : LeftOperand;  } -Expected<ExpressionValue> llvm::min(const ExpressionValue &LeftOperand, -                                    const ExpressionValue &RightOperand) { -  if (cantFail(max(LeftOperand, RightOperand)).getAPIntValue() == -      LeftOperand.getAPIntValue()) +Expected<APInt> llvm::exprMin(const APInt &LeftOperand, +                              const APInt &RightOperand, bool &Overflow) { +  Overflow = false; +  if (cantFail(exprMax(LeftOperand, RightOperand, Overflow)) == LeftOperand)      return RightOperand;    return LeftOperand;  } -Expected<ExpressionValue> NumericVariableUse::eval() const { -  std::optional<ExpressionValue> Value = Variable->getValue(); +Expected<APInt> NumericVariableUse::eval() const { +  std::optional<APInt> Value = Variable->getValue();    if (Value)      return *Value;    return make_error<UndefVarError>(getExpressionStr());  } -Expected<ExpressionValue> BinaryOperation::eval() const { -  Expected<ExpressionValue> LeftOp = LeftOperand->eval(); -  Expected<ExpressionValue> RightOp = RightOperand->eval(); +Expected<APInt> BinaryOperation::eval() const { +  Expected<APInt> MaybeLeftOp = LeftOperand->eval(); +  Expected<APInt> MaybeRightOp = RightOperand->eval();    // Bubble up any error (e.g. undefined variables) in the recursive    // evaluation. -  if (!LeftOp || !RightOp) { +  if (!MaybeLeftOp || !MaybeRightOp) {      Error Err = Error::success(); -    if (!LeftOp) -      Err = joinErrors(std::move(Err), LeftOp.takeError()); -    if (!RightOp) -      Err = joinErrors(std::move(Err), RightOp.takeError()); +    if (!MaybeLeftOp) +      Err = joinErrors(std::move(Err), MaybeLeftOp.takeError()); +    if (!MaybeRightOp) +      Err = joinErrors(std::move(Err), MaybeRightOp.takeError());      return std::move(Err);    } -  return EvalBinop(*LeftOp, *RightOp); +  APInt LeftOp = *MaybeLeftOp; +  APInt RightOp = *MaybeRightOp; +  bool Overflow; +  // Ensure both operands have the same bitwidth. +  unsigned LeftBitWidth = LeftOp.getBitWidth(); +  unsigned RightBitWidth = RightOp.getBitWidth(); +  unsigned NewBitWidth = std::max(LeftBitWidth, RightBitWidth); +  LeftOp = LeftOp.sext(NewBitWidth); +  RightOp = RightOp.sext(NewBitWidth); +  do { +    Expected<APInt> MaybeResult = EvalBinop(LeftOp, RightOp, Overflow); +    if (!MaybeResult) +      return MaybeResult.takeError(); + +    if (!Overflow) +      return MaybeResult; + +    NewBitWidth = nextAPIntBitWidth(NewBitWidth); +    LeftOp = LeftOp.sext(NewBitWidth); +    RightOp = RightOp.sext(NewBitWidth); +  } while (true);  }  Expected<ExpressionFormat> @@ -295,8 +268,7 @@ BinaryOperation::getImplicitFormat(const SourceMgr &SM) const {  Expected<std::string> NumericSubstitution::getResult() const {    assert(ExpressionPointer->getAST() != nullptr &&           "Substituting empty expression"); -  Expected<ExpressionValue> EvaluatedValue = -      ExpressionPointer->getAST()->eval(); +  Expected<APInt> EvaluatedValue = ExpressionPointer->getAST()->eval();    if (!EvaluatedValue)      return EvaluatedValue.takeError();    ExpressionFormat Format = ExpressionPointer->getFormat(); @@ -432,7 +404,7 @@ Expected<std::unique_ptr<ExpressionAST>> Pattern::parseNumericOperand(      StringRef &Expr, AllowedOperand AO, bool MaybeInvalidConstraint,      std::optional<size_t> LineNumber, FileCheckPatternContext *Context,      const SourceMgr &SM) { -  if (Expr.startswith("(")) { +  if (Expr.starts_with("(")) {      if (AO != AllowedOperand::Any)        return ErrorDiagnostic::get(            SM, Expr, "parenthesized expression not permitted here"); @@ -445,7 +417,7 @@ Expected<std::unique_ptr<ExpressionAST>> Pattern::parseNumericOperand(          parseVariable(Expr, SM);      if (ParseVarResult) {        // Try to parse a function call. -      if (Expr.ltrim(SpaceChars).startswith("(")) { +      if (Expr.ltrim(SpaceChars).starts_with("(")) {          if (AO != AllowedOperand::Any)            return ErrorDiagnostic::get(SM, ParseVarResult->Name,                                        "unexpected function call"); @@ -466,21 +438,17 @@ Expected<std::unique_ptr<ExpressionAST>> Pattern::parseNumericOperand(    }    // Otherwise, parse it as a literal. -  int64_t SignedLiteralValue; -  uint64_t UnsignedLiteralValue; +  APInt LiteralValue;    StringRef SaveExpr = Expr; -  // Accept both signed and unsigned literal, default to signed literal. +  bool Negative = Expr.consume_front("-");    if (!Expr.consumeInteger((AO == AllowedOperand::LegacyLiteral) ? 10 : 0, -                           UnsignedLiteralValue)) +                           LiteralValue)) { +    LiteralValue = toSigned(LiteralValue, Negative);      return std::make_unique<ExpressionLiteral>(SaveExpr.drop_back(Expr.size()), -                                               UnsignedLiteralValue); -  Expr = SaveExpr; -  if (AO == AllowedOperand::Any && !Expr.consumeInteger(0, SignedLiteralValue)) -    return std::make_unique<ExpressionLiteral>(SaveExpr.drop_back(Expr.size()), -                                               SignedLiteralValue); - +                                               LiteralValue); +  }    return ErrorDiagnostic::get( -      SM, Expr, +      SM, SaveExpr,        Twine("invalid ") +            (MaybeInvalidConstraint ? "matching constraint or " : "") +            "operand format"); @@ -490,7 +458,7 @@ Expected<std::unique_ptr<ExpressionAST>>  Pattern::parseParenExpr(StringRef &Expr, std::optional<size_t> LineNumber,                          FileCheckPatternContext *Context, const SourceMgr &SM) {    Expr = Expr.ltrim(SpaceChars); -  assert(Expr.startswith("(")); +  assert(Expr.starts_with("("));    // Parse right operand.    Expr.consume_front("("); @@ -503,7 +471,7 @@ Pattern::parseParenExpr(StringRef &Expr, std::optional<size_t> LineNumber,        Expr, AllowedOperand::Any, /*MaybeInvalidConstraint=*/false, LineNumber,        Context, SM);    Expr = Expr.ltrim(SpaceChars); -  while (SubExprResult && !Expr.empty() && !Expr.startswith(")")) { +  while (SubExprResult && !Expr.empty() && !Expr.starts_with(")")) {      StringRef OrigExpr = Expr;      SubExprResult = parseBinop(OrigExpr, Expr, std::move(*SubExprResult), false,                                 LineNumber, Context, SM); @@ -535,10 +503,10 @@ Pattern::parseBinop(StringRef Expr, StringRef &RemainingExpr,    binop_eval_t EvalBinop;    switch (Operator) {    case '+': -    EvalBinop = operator+; +    EvalBinop = exprAdd;      break;    case '-': -    EvalBinop = operator-; +    EvalBinop = exprSub;      break;    default:      return ErrorDiagnostic::get( @@ -569,15 +537,15 @@ Pattern::parseCallExpr(StringRef &Expr, StringRef FuncName,                         std::optional<size_t> LineNumber,                         FileCheckPatternContext *Context, const SourceMgr &SM) {    Expr = Expr.ltrim(SpaceChars); -  assert(Expr.startswith("(")); +  assert(Expr.starts_with("("));    auto OptFunc = StringSwitch<binop_eval_t>(FuncName) -                     .Case("add", operator+) -                     .Case("div", operator/) -                     .Case("max", max) -                     .Case("min", min) -                     .Case("mul", operator*) -                     .Case("sub", operator-) +                     .Case("add", exprAdd) +                     .Case("div", exprDiv) +                     .Case("max", exprMax) +                     .Case("min", exprMin) +                     .Case("mul", exprMul) +                     .Case("sub", exprSub)                       .Default(nullptr);    if (!OptFunc) @@ -589,8 +557,8 @@ Pattern::parseCallExpr(StringRef &Expr, StringRef FuncName,    // Parse call arguments, which are comma separated.    SmallVector<std::unique_ptr<ExpressionAST>, 4> Args; -  while (!Expr.empty() && !Expr.startswith(")")) { -    if (Expr.startswith(",")) +  while (!Expr.empty() && !Expr.starts_with(")")) { +    if (Expr.starts_with(","))        return ErrorDiagnostic::get(SM, Expr, "missing argument");      // Parse the argument, which is an arbitary expression. @@ -601,7 +569,7 @@ Pattern::parseCallExpr(StringRef &Expr, StringRef FuncName,      while (Arg && !Expr.empty()) {        Expr = Expr.ltrim(SpaceChars);        // Have we reached an argument terminator? -      if (Expr.startswith(",") || Expr.startswith(")")) +      if (Expr.starts_with(",") || Expr.starts_with(")"))          break;        // Arg = Arg <op> <expr> @@ -620,7 +588,7 @@ Pattern::parseCallExpr(StringRef &Expr, StringRef FuncName,        break;      Expr = Expr.ltrim(SpaceChars); -    if (Expr.startswith(")")) +    if (Expr.starts_with(")"))        return ErrorDiagnostic::get(SM, Expr, "missing argument");    } @@ -850,7 +818,7 @@ bool Pattern::parsePattern(StringRef PatternStr, StringRef Prefix,    // by escaping scary characters in fixed strings, building up one big regex.    while (!PatternStr.empty()) {      // RegEx matches. -    if (PatternStr.startswith("{{")) { +    if (PatternStr.starts_with("{{")) {        // This is the start of a regex match.  Scan for the }}.        size_t End = PatternStr.find("}}");        if (End == StringRef::npos) { @@ -864,12 +832,16 @@ bool Pattern::parsePattern(StringRef PatternStr, StringRef Prefix,        // capturing the result for any purpose.  This is required in case the        // expression contains an alternation like: CHECK:  abc{{x|z}}def.  We        // want this to turn into: "abc(x|z)def" not "abcx|zdef". -      RegExStr += '('; -      ++CurParen; +      bool HasAlternation = PatternStr.contains('|'); +      if (HasAlternation) { +        RegExStr += '('; +        ++CurParen; +      }        if (AddRegExToRegEx(PatternStr.substr(2, End - 2), CurParen, SM))          return true; -      RegExStr += ')'; +      if (HasAlternation) +        RegExStr += ')';        PatternStr = PatternStr.substr(End + 2);        continue; @@ -885,7 +857,7 @@ bool Pattern::parsePattern(StringRef PatternStr, StringRef Prefix,      // names must satisfy the regular expression "[a-zA-Z_][0-9a-zA-Z_]*" to be      // valid, as this helps catch some common errors. If there are extra '['s      // before the "[[", treat them literally. -    if (PatternStr.startswith("[[") && !PatternStr.startswith("[[[")) { +    if (PatternStr.starts_with("[[") && !PatternStr.starts_with("[[[")) {        StringRef UnparsedPatternStr = PatternStr.substr(2);        // Find the closing bracket pair ending the match.  End is going to be an        // offset relative to the beginning of the match string. @@ -1124,7 +1096,8 @@ Pattern::MatchResult Pattern::match(StringRef Buffer,    if (!Substitutions.empty()) {      TmpStr = RegExStr;      if (LineNumber) -      Context->LineVariable->setValue(ExpressionValue(*LineNumber)); +      Context->LineVariable->setValue( +          APInt(sizeof(*LineNumber) * 8, *LineNumber));      size_t InsertOffset = 0;      // Substitute all string variables and expressions whose values are only @@ -1203,11 +1176,8 @@ Pattern::MatchResult Pattern::match(StringRef Buffer,      StringRef MatchedValue = MatchInfo[CaptureParenGroup];      ExpressionFormat Format = DefinedNumericVariable->getImplicitFormat(); -    Expected<ExpressionValue> Value = -        Format.valueFromStringRepr(MatchedValue, SM); -    if (!Value) -      return MatchResult(TheMatch, Value.takeError()); -    DefinedNumericVariable->setValue(*Value, MatchedValue); +    APInt Value = Format.valueFromStringRepr(MatchedValue, SM); +    DefinedNumericVariable->setValue(Value, MatchedValue);    }    return MatchResult(TheMatch, Error::success()); @@ -1422,7 +1392,7 @@ size_t Pattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) {    size_t BracketDepth = 0;    while (!Str.empty()) { -    if (Str.startswith("]]") && BracketDepth == 0) +    if (Str.starts_with("]]") && BracketDepth == 0)        return Offset;      if (Str[0] == '\\') {        // Backslash escapes the next char within regexes, so skip them both. @@ -1621,10 +1591,10 @@ FindCheckType(const FileCheckRequest &Req, StringRef Buffer, StringRef Prefix,    }    // You can't combine -NOT with another suffix. -  if (Rest.startswith("DAG-NOT:") || Rest.startswith("NOT-DAG:") || -      Rest.startswith("NEXT-NOT:") || Rest.startswith("NOT-NEXT:") || -      Rest.startswith("SAME-NOT:") || Rest.startswith("NOT-SAME:") || -      Rest.startswith("EMPTY-NOT:") || Rest.startswith("NOT-EMPTY:")) +  if (Rest.starts_with("DAG-NOT:") || Rest.starts_with("NOT-DAG:") || +      Rest.starts_with("NEXT-NOT:") || Rest.starts_with("NOT-NEXT:") || +      Rest.starts_with("SAME-NOT:") || Rest.starts_with("NOT-SAME:") || +      Rest.starts_with("EMPTY-NOT:") || Rest.starts_with("NOT-EMPTY:"))      return {Check::CheckBadNot, Rest};    if (Rest.consume_front("NEXT")) @@ -1664,6 +1634,60 @@ static size_t SkipWord(StringRef Str, size_t Loc) {    return Loc;  } +static const char *DefaultCheckPrefixes[] = {"CHECK"}; +static const char *DefaultCommentPrefixes[] = {"COM", "RUN"}; + +static void addDefaultPrefixes(FileCheckRequest &Req) { +  if (Req.CheckPrefixes.empty()) { +    for (const char *Prefix : DefaultCheckPrefixes) +      Req.CheckPrefixes.push_back(Prefix); +    Req.IsDefaultCheckPrefix = true; +  } +  if (Req.CommentPrefixes.empty()) +    for (const char *Prefix : DefaultCommentPrefixes) +      Req.CommentPrefixes.push_back(Prefix); +} + +struct PrefixMatcher { +  /// Prefixes and their first occurrence past the current position. +  SmallVector<std::pair<StringRef, size_t>> Prefixes; +  StringRef Input; + +  PrefixMatcher(ArrayRef<StringRef> CheckPrefixes, +                ArrayRef<StringRef> CommentPrefixes, StringRef Input) +      : Input(Input) { +    for (StringRef Prefix : CheckPrefixes) +      Prefixes.push_back({Prefix, Input.find(Prefix)}); +    for (StringRef Prefix : CommentPrefixes) +      Prefixes.push_back({Prefix, Input.find(Prefix)}); + +    // Sort by descending length. +    llvm::sort(Prefixes, +               [](auto A, auto B) { return A.first.size() > B.first.size(); }); +  } + +  /// Find the next match of a prefix in Buffer. +  /// Returns empty StringRef if not found. +  StringRef match(StringRef Buffer) { +    assert(Buffer.data() >= Input.data() && +           Buffer.data() + Buffer.size() == Input.data() + Input.size() && +           "Buffer must be suffix of Input"); + +    size_t From = Buffer.data() - Input.data(); +    StringRef Match; +    for (auto &[Prefix, Pos] : Prefixes) { +      // If the last occurrence was before From, find the next one after From. +      if (Pos < From) +        Pos = Input.find(Prefix, From); +      // Find the first prefix with the lowest position. +      if (Pos != StringRef::npos && +          (Match.empty() || size_t(Match.data() - Input.data()) > Pos)) +        Match = StringRef(Input.substr(Pos, Prefix.size())); +    } +    return Match; +  } +}; +  /// Searches the buffer for the first prefix in the prefix regular expression.  ///  /// This searches the buffer using the provided regular expression, however it @@ -1688,20 +1712,16 @@ static size_t SkipWord(StringRef Str, size_t Loc) {  /// If no valid prefix is found, the state of Buffer, LineNumber, and CheckTy  /// is unspecified.  static std::pair<StringRef, StringRef> -FindFirstMatchingPrefix(const FileCheckRequest &Req, Regex &PrefixRE, +FindFirstMatchingPrefix(const FileCheckRequest &Req, PrefixMatcher &Matcher,                          StringRef &Buffer, unsigned &LineNumber,                          Check::FileCheckType &CheckTy) { -  SmallVector<StringRef, 2> Matches; -    while (!Buffer.empty()) { -    // Find the first (longest) match using the RE. -    if (!PrefixRE.match(Buffer, &Matches)) +    // Find the first (longest) prefix match. +    StringRef Prefix = Matcher.match(Buffer); +    if (Prefix.empty())        // No match at all, bail.        return {StringRef(), StringRef()}; -    StringRef Prefix = Matches[0]; -    Matches.clear(); -      assert(Prefix.data() >= Buffer.data() &&             Prefix.data() < Buffer.data() + Buffer.size() &&             "Prefix doesn't start inside of buffer!"); @@ -1750,7 +1770,7 @@ FileCheck::FileCheck(FileCheckRequest Req)  FileCheck::~FileCheck() = default;  bool FileCheck::readCheckFile( -    SourceMgr &SM, StringRef Buffer, Regex &PrefixRE, +    SourceMgr &SM, StringRef Buffer,      std::pair<unsigned, unsigned> *ImpPatBufferIDRange) {    if (ImpPatBufferIDRange)      ImpPatBufferIDRange->first = ImpPatBufferIDRange->second = 0; @@ -1799,6 +1819,8 @@ bool FileCheck::readCheckFile(    // found.    unsigned LineNumber = 1; +  addDefaultPrefixes(Req); +  PrefixMatcher Matcher(Req.CheckPrefixes, Req.CommentPrefixes, Buffer);    std::set<StringRef> PrefixesNotFound(Req.CheckPrefixes.begin(),                                         Req.CheckPrefixes.end());    const size_t DistinctPrefixes = PrefixesNotFound.size(); @@ -1809,7 +1831,7 @@ bool FileCheck::readCheckFile(      StringRef UsedPrefix;      StringRef AfterSuffix;      std::tie(UsedPrefix, AfterSuffix) = -        FindFirstMatchingPrefix(Req, PrefixRE, Buffer, LineNumber, CheckTy); +        FindFirstMatchingPrefix(Req, Matcher, Buffer, LineNumber, CheckTy);      if (UsedPrefix.empty())        break;      if (CheckTy != Check::CheckComment) @@ -2461,9 +2483,6 @@ static bool ValidatePrefixes(StringRef Kind, StringSet<> &UniquePrefixes,    return true;  } -static const char *DefaultCheckPrefixes[] = {"CHECK"}; -static const char *DefaultCommentPrefixes[] = {"COM", "RUN"}; -  bool FileCheck::ValidateCheckPrefixes() {    StringSet<> UniquePrefixes;    // Add default prefixes to catch user-supplied duplicates of them below. @@ -2484,33 +2503,6 @@ bool FileCheck::ValidateCheckPrefixes() {    return true;  } -Regex FileCheck::buildCheckPrefixRegex() { -  if (Req.CheckPrefixes.empty()) { -    for (const char *Prefix : DefaultCheckPrefixes) -      Req.CheckPrefixes.push_back(Prefix); -    Req.IsDefaultCheckPrefix = true; -  } -  if (Req.CommentPrefixes.empty()) { -    for (const char *Prefix : DefaultCommentPrefixes) -      Req.CommentPrefixes.push_back(Prefix); -  } - -  // We already validated the contents of CheckPrefixes and CommentPrefixes so -  // just concatenate them as alternatives. -  SmallString<32> PrefixRegexStr; -  for (size_t I = 0, E = Req.CheckPrefixes.size(); I != E; ++I) { -    if (I != 0) -      PrefixRegexStr.push_back('|'); -    PrefixRegexStr.append(Req.CheckPrefixes[I]); -  } -  for (StringRef Prefix : Req.CommentPrefixes) { -    PrefixRegexStr.push_back('|'); -    PrefixRegexStr.append(Prefix); -  } - -  return Regex(PrefixRegexStr); -} -  Error FileCheckPatternContext::defineCmdlineVariables(      ArrayRef<StringRef> CmdlineDefines, SourceMgr &SM) {    assert(GlobalVariableTable.empty() && GlobalNumericVariableTable.empty() && @@ -2590,7 +2582,7 @@ Error FileCheckPatternContext::defineCmdlineVariables(        // to, since the expression of a command-line variable definition should        // only use variables defined earlier on the command-line. If not, this        // is an error and we report it. -      Expected<ExpressionValue> Value = Expression->getAST()->eval(); +      Expected<APInt> Value = Expression->getAST()->eval();        if (!Value) {          Errs = joinErrors(std::move(Errs), Value.takeError());          continue;  | 
