aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/FileCheck/FileCheck.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/FileCheck/FileCheck.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/FileCheck/FileCheck.cpp382
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;