Path: blob/main/contrib/llvm-project/llvm/lib/FileCheck/FileCheckImpl.h
35233 views
//===-- FileCheckImpl.h - Private FileCheck Interface ------------*- C++ -*-==//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file defines the private interfaces of FileCheck. Its purpose is to9// allow unit testing of FileCheck and to separate the interface from the10// implementation. It is only meant to be used by FileCheck.11//12//===----------------------------------------------------------------------===//1314#ifndef LLVM_LIB_FILECHECK_FILECHECKIMPL_H15#define LLVM_LIB_FILECHECK_FILECHECKIMPL_H1617#include "llvm/ADT/APInt.h"18#include "llvm/ADT/StringMap.h"19#include "llvm/ADT/StringRef.h"20#include "llvm/FileCheck/FileCheck.h"21#include "llvm/Support/Error.h"22#include "llvm/Support/SourceMgr.h"23#include <map>24#include <optional>25#include <string>26#include <vector>2728namespace llvm {2930//===----------------------------------------------------------------------===//31// Numeric substitution handling code.32//===----------------------------------------------------------------------===//3334/// Type representing the format an expression value should be textualized into35/// for matching. Used to represent both explicit format specifiers as well as36/// implicit format from using numeric variables.37struct ExpressionFormat {38enum class Kind {39/// Denote absence of format. Used for implicit format of literals and40/// empty expressions.41NoFormat,42/// Value is an unsigned integer and should be printed as a decimal number.43Unsigned,44/// Value is a signed integer and should be printed as a decimal number.45Signed,46/// Value should be printed as an uppercase hex number.47HexUpper,48/// Value should be printed as a lowercase hex number.49HexLower50};5152private:53Kind Value;54unsigned Precision = 0;55/// printf-like "alternate form" selected.56bool AlternateForm = false;5758public:59/// Evaluates a format to true if it can be used in a match.60explicit operator bool() const { return Value != Kind::NoFormat; }6162/// Define format equality: formats are equal if neither is NoFormat and63/// their kinds and precision are the same.64bool operator==(const ExpressionFormat &Other) const {65return Value != Kind::NoFormat && Value == Other.Value &&66Precision == Other.Precision && AlternateForm == Other.AlternateForm;67}6869bool operator!=(const ExpressionFormat &Other) const {70return !(*this == Other);71}7273bool operator==(Kind OtherValue) const { return Value == OtherValue; }7475bool operator!=(Kind OtherValue) const { return !(*this == OtherValue); }7677/// \returns the format specifier corresponding to this format as a string.78StringRef toString() const;7980ExpressionFormat() : Value(Kind::NoFormat){};81explicit ExpressionFormat(Kind Value) : Value(Value), Precision(0){};82explicit ExpressionFormat(Kind Value, unsigned Precision)83: Value(Value), Precision(Precision){};84explicit ExpressionFormat(Kind Value, unsigned Precision, bool AlternateForm)85: Value(Value), Precision(Precision), AlternateForm(AlternateForm){};8687/// \returns a wildcard regular expression string that matches any value in88/// the format represented by this instance and no other value, or an error89/// if the format is NoFormat.90Expected<std::string> getWildcardRegex() const;9192/// \returns the string representation of \p Value in the format represented93/// by this instance, or an error if conversion to this format failed or the94/// format is NoFormat.95Expected<std::string> getMatchingString(APInt Value) const;9697/// \returns the value corresponding to string representation \p StrVal98/// according to the matching format represented by this instance.99APInt valueFromStringRepr(StringRef StrVal, const SourceMgr &SM) const;100};101102/// Class to represent an overflow error that might result when manipulating a103/// value.104class OverflowError : public ErrorInfo<OverflowError> {105public:106static char ID;107108std::error_code convertToErrorCode() const override {109return std::make_error_code(std::errc::value_too_large);110}111112void log(raw_ostream &OS) const override { OS << "overflow error"; }113};114115/// Performs operation and \returns its result or an error in case of failure,116/// such as if an overflow occurs.117Expected<APInt> exprAdd(const APInt &Lhs, const APInt &Rhs, bool &Overflow);118Expected<APInt> exprSub(const APInt &Lhs, const APInt &Rhs, bool &Overflow);119Expected<APInt> exprMul(const APInt &Lhs, const APInt &Rhs, bool &Overflow);120Expected<APInt> exprDiv(const APInt &Lhs, const APInt &Rhs, bool &Overflow);121Expected<APInt> exprMax(const APInt &Lhs, const APInt &Rhs, bool &Overflow);122Expected<APInt> exprMin(const APInt &Lhs, const APInt &Rhs, bool &Overflow);123124/// Base class representing the AST of a given expression.125class ExpressionAST {126private:127StringRef ExpressionStr;128129public:130ExpressionAST(StringRef ExpressionStr) : ExpressionStr(ExpressionStr) {}131132virtual ~ExpressionAST() = default;133134StringRef getExpressionStr() const { return ExpressionStr; }135136/// Evaluates and \returns the value of the expression represented by this137/// AST or an error if evaluation fails.138virtual Expected<APInt> eval() const = 0;139140/// \returns either the implicit format of this AST, a diagnostic against141/// \p SM if implicit formats of the AST's components conflict, or NoFormat142/// if the AST has no implicit format (e.g. AST is made up of a single143/// literal).144virtual Expected<ExpressionFormat>145getImplicitFormat(const SourceMgr &SM) const {146return ExpressionFormat();147}148};149150/// Class representing an unsigned literal in the AST of an expression.151class ExpressionLiteral : public ExpressionAST {152private:153/// Actual value of the literal.154APInt Value;155156public:157explicit ExpressionLiteral(StringRef ExpressionStr, APInt Val)158: ExpressionAST(ExpressionStr), Value(Val) {}159160/// \returns the literal's value.161Expected<APInt> eval() const override { return Value; }162};163164/// Class to represent an undefined variable error, which quotes that165/// variable's name when printed.166class UndefVarError : public ErrorInfo<UndefVarError> {167private:168StringRef VarName;169170public:171static char ID;172173UndefVarError(StringRef VarName) : VarName(VarName) {}174175StringRef getVarName() const { return VarName; }176177std::error_code convertToErrorCode() const override {178return inconvertibleErrorCode();179}180181/// Print name of variable associated with this error.182void log(raw_ostream &OS) const override {183OS << "undefined variable: " << VarName;184}185};186187/// Class representing an expression and its matching format.188class Expression {189private:190/// Pointer to AST of the expression.191std::unique_ptr<ExpressionAST> AST;192193/// Format to use (e.g. hex upper case letters) when matching the value.194ExpressionFormat Format;195196public:197/// Generic constructor for an expression represented by the given \p AST and198/// whose matching format is \p Format.199Expression(std::unique_ptr<ExpressionAST> AST, ExpressionFormat Format)200: AST(std::move(AST)), Format(Format) {}201202/// \returns pointer to AST of the expression. Pointer is guaranteed to be203/// valid as long as this object is.204ExpressionAST *getAST() const { return AST.get(); }205206ExpressionFormat getFormat() const { return Format; }207};208209/// Class representing a numeric variable and its associated current value.210class NumericVariable {211private:212/// Name of the numeric variable.213StringRef Name;214215/// Format to use for expressions using this variable without an explicit216/// format.217ExpressionFormat ImplicitFormat;218219/// Value of numeric variable, if defined, or std::nullopt otherwise.220std::optional<APInt> Value;221222/// The input buffer's string from which Value was parsed, or std::nullopt.223/// See comments on getStringValue for a discussion of the std::nullopt case.224std::optional<StringRef> StrValue;225226/// Line number where this variable is defined, or std::nullopt if defined227/// before input is parsed. Used to determine whether a variable is defined on228/// the same line as a given use.229std::optional<size_t> DefLineNumber;230231public:232/// Constructor for a variable \p Name with implicit format \p ImplicitFormat233/// defined at line \p DefLineNumber or defined before input is parsed if234/// \p DefLineNumber is std::nullopt.235explicit NumericVariable(StringRef Name, ExpressionFormat ImplicitFormat,236std::optional<size_t> DefLineNumber = std::nullopt)237: Name(Name), ImplicitFormat(ImplicitFormat),238DefLineNumber(DefLineNumber) {}239240/// \returns name of this numeric variable.241StringRef getName() const { return Name; }242243/// \returns implicit format of this numeric variable.244ExpressionFormat getImplicitFormat() const { return ImplicitFormat; }245246/// \returns this variable's value.247std::optional<APInt> getValue() const { return Value; }248249/// \returns the input buffer's string from which this variable's value was250/// parsed, or std::nullopt if the value is not yet defined or was not parsed251/// from the input buffer. For example, the value of @LINE is not parsed from252/// the input buffer, and some numeric variables are parsed from the command253/// line instead.254std::optional<StringRef> getStringValue() const { return StrValue; }255256/// Sets value of this numeric variable to \p NewValue, and sets the input257/// buffer string from which it was parsed to \p NewStrValue. See comments on258/// getStringValue for a discussion of when the latter can be std::nullopt.259void setValue(APInt NewValue,260std::optional<StringRef> NewStrValue = std::nullopt) {261Value = NewValue;262StrValue = NewStrValue;263}264265/// Clears value of this numeric variable, regardless of whether it is266/// currently defined or not.267void clearValue() {268Value = std::nullopt;269StrValue = std::nullopt;270}271272/// \returns the line number where this variable is defined, if any, or273/// std::nullopt if defined before input is parsed.274std::optional<size_t> getDefLineNumber() const { return DefLineNumber; }275};276277/// Class representing the use of a numeric variable in the AST of an278/// expression.279class NumericVariableUse : public ExpressionAST {280private:281/// Pointer to the class instance for the variable this use is about.282NumericVariable *Variable;283284public:285NumericVariableUse(StringRef Name, NumericVariable *Variable)286: ExpressionAST(Name), Variable(Variable) {}287/// \returns the value of the variable referenced by this instance.288Expected<APInt> eval() const override;289290/// \returns implicit format of this numeric variable.291Expected<ExpressionFormat>292getImplicitFormat(const SourceMgr &SM) const override {293return Variable->getImplicitFormat();294}295};296297/// Type of functions evaluating a given binary operation.298using binop_eval_t = Expected<APInt> (*)(const APInt &, const APInt &, bool &);299300/// Class representing a single binary operation in the AST of an expression.301class BinaryOperation : public ExpressionAST {302private:303/// Left operand.304std::unique_ptr<ExpressionAST> LeftOperand;305306/// Right operand.307std::unique_ptr<ExpressionAST> RightOperand;308309/// Pointer to function that can evaluate this binary operation.310binop_eval_t EvalBinop;311312public:313BinaryOperation(StringRef ExpressionStr, binop_eval_t EvalBinop,314std::unique_ptr<ExpressionAST> LeftOp,315std::unique_ptr<ExpressionAST> RightOp)316: ExpressionAST(ExpressionStr), EvalBinop(EvalBinop) {317LeftOperand = std::move(LeftOp);318RightOperand = std::move(RightOp);319}320321/// Evaluates the value of the binary operation represented by this AST,322/// using EvalBinop on the result of recursively evaluating the operands.323/// \returns the expression value or an error if an undefined numeric324/// variable is used in one of the operands.325Expected<APInt> eval() const override;326327/// \returns the implicit format of this AST, if any, a diagnostic against328/// \p SM if the implicit formats of the AST's components conflict, or no329/// format if the AST has no implicit format (e.g. AST is made of a single330/// literal).331Expected<ExpressionFormat>332getImplicitFormat(const SourceMgr &SM) const override;333};334335class FileCheckPatternContext;336337/// Class representing a substitution to perform in the RegExStr string.338class Substitution {339protected:340/// Pointer to a class instance holding, among other things, the table with341/// the values of live string variables at the start of any given CHECK line.342/// Used for substituting string variables with the text they were defined343/// as. Expressions are linked to the numeric variables they use at344/// parse time and directly access the value of the numeric variable to345/// evaluate their value.346FileCheckPatternContext *Context;347348/// The string that needs to be substituted for something else. For a349/// string variable this is its name, otherwise this is the whole expression.350StringRef FromStr;351352// Index in RegExStr of where to do the substitution.353size_t InsertIdx;354355public:356Substitution(FileCheckPatternContext *Context, StringRef VarName,357size_t InsertIdx)358: Context(Context), FromStr(VarName), InsertIdx(InsertIdx) {}359360virtual ~Substitution() = default;361362/// \returns the string to be substituted for something else.363StringRef getFromString() const { return FromStr; }364365/// \returns the index where the substitution is to be performed in RegExStr.366size_t getIndex() const { return InsertIdx; }367368/// \returns a string containing the result of the substitution represented369/// by this class instance or an error if substitution failed.370virtual Expected<std::string> getResult() const = 0;371};372373class StringSubstitution : public Substitution {374public:375StringSubstitution(FileCheckPatternContext *Context, StringRef VarName,376size_t InsertIdx)377: Substitution(Context, VarName, InsertIdx) {}378379/// \returns the text that the string variable in this substitution matched380/// when defined, or an error if the variable is undefined.381Expected<std::string> getResult() const override;382};383384class NumericSubstitution : public Substitution {385private:386/// Pointer to the class representing the expression whose value is to be387/// substituted.388std::unique_ptr<Expression> ExpressionPointer;389390public:391NumericSubstitution(FileCheckPatternContext *Context, StringRef ExpressionStr,392std::unique_ptr<Expression> ExpressionPointer,393size_t InsertIdx)394: Substitution(Context, ExpressionStr, InsertIdx),395ExpressionPointer(std::move(ExpressionPointer)) {}396397/// \returns a string containing the result of evaluating the expression in398/// this substitution, or an error if evaluation failed.399Expected<std::string> getResult() const override;400};401402//===----------------------------------------------------------------------===//403// Pattern handling code.404//===----------------------------------------------------------------------===//405406/// Class holding the Pattern global state, shared by all patterns: tables407/// holding values of variables and whether they are defined or not at any408/// given time in the matching process.409class FileCheckPatternContext {410friend class Pattern;411412private:413/// When matching a given pattern, this holds the value of all the string414/// variables defined in previous patterns. In a pattern, only the last415/// definition for a given variable is recorded in this table.416/// Back-references are used for uses after any the other definition.417StringMap<StringRef> GlobalVariableTable;418419/// Map of all string variables defined so far. Used at parse time to detect420/// a name conflict between a numeric variable and a string variable when421/// the former is defined on a later line than the latter.422StringMap<bool> DefinedVariableTable;423424/// When matching a given pattern, this holds the pointers to the classes425/// representing the numeric variables defined in previous patterns. When426/// matching a pattern all definitions for that pattern are recorded in the427/// NumericVariableDefs table in the Pattern instance of that pattern.428StringMap<NumericVariable *> GlobalNumericVariableTable;429430/// Pointer to the class instance representing the @LINE pseudo variable for431/// easily updating its value.432NumericVariable *LineVariable = nullptr;433434/// Vector holding pointers to all parsed numeric variables. Used to435/// automatically free them once they are guaranteed to no longer be used.436std::vector<std::unique_ptr<NumericVariable>> NumericVariables;437438/// Vector holding pointers to all parsed expressions. Used to automatically439/// free the expressions once they are guaranteed to no longer be used.440std::vector<std::unique_ptr<Expression>> Expressions;441442/// Vector holding pointers to all substitutions. Used to automatically free443/// them once they are guaranteed to no longer be used.444std::vector<std::unique_ptr<Substitution>> Substitutions;445446public:447/// \returns the value of string variable \p VarName or an error if no such448/// variable has been defined.449Expected<StringRef> getPatternVarValue(StringRef VarName);450451/// Defines string and numeric variables from definitions given on the452/// command line, passed as a vector of [#]VAR=VAL strings in453/// \p CmdlineDefines. \returns an error list containing diagnostics against454/// \p SM for all definition parsing failures, if any, or Success otherwise.455Error defineCmdlineVariables(ArrayRef<StringRef> CmdlineDefines,456SourceMgr &SM);457458/// Create @LINE pseudo variable. Value is set when pattern are being459/// matched.460void createLineVariable();461462/// Undefines local variables (variables whose name does not start with a '$'463/// sign), i.e. removes them from GlobalVariableTable and from464/// GlobalNumericVariableTable and also clears the value of numeric465/// variables.466void clearLocalVars();467468private:469/// Makes a new numeric variable and registers it for destruction when the470/// context is destroyed.471template <class... Types> NumericVariable *makeNumericVariable(Types... args);472473/// Makes a new string substitution and registers it for destruction when the474/// context is destroyed.475Substitution *makeStringSubstitution(StringRef VarName, size_t InsertIdx);476477/// Makes a new numeric substitution and registers it for destruction when478/// the context is destroyed.479Substitution *makeNumericSubstitution(StringRef ExpressionStr,480std::unique_ptr<Expression> Expression,481size_t InsertIdx);482};483484/// Class to represent an error holding a diagnostic with location information485/// used when printing it.486class ErrorDiagnostic : public ErrorInfo<ErrorDiagnostic> {487private:488SMDiagnostic Diagnostic;489SMRange Range;490491public:492static char ID;493494ErrorDiagnostic(SMDiagnostic &&Diag, SMRange Range)495: Diagnostic(Diag), Range(Range) {}496497std::error_code convertToErrorCode() const override {498return inconvertibleErrorCode();499}500501/// Print diagnostic associated with this error when printing the error.502void log(raw_ostream &OS) const override { Diagnostic.print(nullptr, OS); }503504StringRef getMessage() const { return Diagnostic.getMessage(); }505SMRange getRange() const { return Range; }506507static Error get(const SourceMgr &SM, SMLoc Loc, const Twine &ErrMsg,508SMRange Range = std::nullopt) {509return make_error<ErrorDiagnostic>(510SM.GetMessage(Loc, SourceMgr::DK_Error, ErrMsg), Range);511}512513static Error get(const SourceMgr &SM, StringRef Buffer, const Twine &ErrMsg) {514SMLoc Start = SMLoc::getFromPointer(Buffer.data());515SMLoc End = SMLoc::getFromPointer(Buffer.data() + Buffer.size());516return get(SM, Start, ErrMsg, SMRange(Start, End));517}518};519520class NotFoundError : public ErrorInfo<NotFoundError> {521public:522static char ID;523524std::error_code convertToErrorCode() const override {525return inconvertibleErrorCode();526}527528/// Print diagnostic associated with this error when printing the error.529void log(raw_ostream &OS) const override {530OS << "String not found in input";531}532};533534/// An error that has already been reported.535///536/// This class is designed to support a function whose callers may need to know537/// whether the function encountered and reported an error but never need to538/// know the nature of that error. For example, the function has a return type539/// of \c Error and always returns either \c ErrorReported or \c ErrorSuccess.540/// That interface is similar to that of a function returning bool to indicate541/// an error except, in the former case, (1) there is no confusion over polarity542/// and (2) the caller must either check the result or explicitly ignore it with543/// a call like \c consumeError.544class ErrorReported final : public ErrorInfo<ErrorReported> {545public:546static char ID;547548std::error_code convertToErrorCode() const override {549return inconvertibleErrorCode();550}551552/// Print diagnostic associated with this error when printing the error.553void log(raw_ostream &OS) const override {554OS << "error previously reported";555}556557static inline Error reportedOrSuccess(bool HasErrorReported) {558if (HasErrorReported)559return make_error<ErrorReported>();560return Error::success();561}562};563564class Pattern {565SMLoc PatternLoc;566567/// A fixed string to match as the pattern or empty if this pattern requires568/// a regex match.569StringRef FixedStr;570571/// A regex string to match as the pattern or empty if this pattern requires572/// a fixed string to match.573std::string RegExStr;574575/// Entries in this vector represent a substitution of a string variable or576/// an expression in the RegExStr regex at match time. For example, in the577/// case of a CHECK directive with the pattern "foo[[bar]]baz[[#N+1]]",578/// RegExStr will contain "foobaz" and we'll get two entries in this vector579/// that tells us to insert the value of string variable "bar" at offset 3580/// and the value of expression "N+1" at offset 6.581std::vector<Substitution *> Substitutions;582583/// Maps names of string variables defined in a pattern to the number of584/// their parenthesis group in RegExStr capturing their last definition.585///586/// E.g. for the pattern "foo[[bar:.*]]baz([[bar]][[QUUX]][[bar:.*]])",587/// RegExStr will be "foo(.*)baz(\1<quux value>(.*))" where <quux value> is588/// the value captured for QUUX on the earlier line where it was defined, and589/// VariableDefs will map "bar" to the third parenthesis group which captures590/// the second definition of "bar".591///592/// Note: uses std::map rather than StringMap to be able to get the key when593/// iterating over values.594std::map<StringRef, unsigned> VariableDefs;595596/// Structure representing the definition of a numeric variable in a pattern.597/// It holds the pointer to the class instance holding the value and matching598/// format of the numeric variable whose value is being defined and the599/// number of the parenthesis group in RegExStr to capture that value.600struct NumericVariableMatch {601/// Pointer to class instance holding the value and matching format of the602/// numeric variable being defined.603NumericVariable *DefinedNumericVariable;604605/// Number of the parenthesis group in RegExStr that captures the value of606/// this numeric variable definition.607unsigned CaptureParenGroup;608};609610/// Holds the number of the parenthesis group in RegExStr and pointer to the611/// corresponding NumericVariable class instance of all numeric variable612/// definitions. Used to set the matched value of all those variables.613StringMap<NumericVariableMatch> NumericVariableDefs;614615/// Pointer to a class instance holding the global state shared by all616/// patterns:617/// - separate tables with the values of live string and numeric variables618/// respectively at the start of any given CHECK line;619/// - table holding whether a string variable has been defined at any given620/// point during the parsing phase.621FileCheckPatternContext *Context;622623Check::FileCheckType CheckTy;624625/// Line number for this CHECK pattern or std::nullopt if it is an implicit626/// pattern. Used to determine whether a variable definition is made on an627/// earlier line to the one with this CHECK.628std::optional<size_t> LineNumber;629630/// Ignore case while matching if set to true.631bool IgnoreCase = false;632633public:634Pattern(Check::FileCheckType Ty, FileCheckPatternContext *Context,635std::optional<size_t> Line = std::nullopt)636: Context(Context), CheckTy(Ty), LineNumber(Line) {}637638/// \returns the location in source code.639SMLoc getLoc() const { return PatternLoc; }640641/// \returns the pointer to the global state for all patterns in this642/// FileCheck instance.643FileCheckPatternContext *getContext() const { return Context; }644645/// \returns whether \p C is a valid first character for a variable name.646static bool isValidVarNameStart(char C);647648/// Parsing information about a variable.649struct VariableProperties {650StringRef Name;651bool IsPseudo;652};653654/// Parses the string at the start of \p Str for a variable name. \returns655/// a VariableProperties structure holding the variable name and whether it656/// is the name of a pseudo variable, or an error holding a diagnostic657/// against \p SM if parsing fail. If parsing was successful, also strips658/// \p Str from the variable name.659static Expected<VariableProperties> parseVariable(StringRef &Str,660const SourceMgr &SM);661/// Parses \p Expr for a numeric substitution block at line \p LineNumber,662/// or before input is parsed if \p LineNumber is None. Parameter663/// \p IsLegacyLineExpr indicates whether \p Expr should be a legacy @LINE664/// expression and \p Context points to the class instance holding the live665/// string and numeric variables. \returns a pointer to the class instance666/// representing the expression whose value must be substitued, or an error667/// holding a diagnostic against \p SM if parsing fails. If substitution was668/// successful, sets \p DefinedNumericVariable to point to the class669/// representing the numeric variable defined in this numeric substitution670/// block, or std::nullopt if this block does not define any variable.671static Expected<std::unique_ptr<Expression>> parseNumericSubstitutionBlock(672StringRef Expr, std::optional<NumericVariable *> &DefinedNumericVariable,673bool IsLegacyLineExpr, std::optional<size_t> LineNumber,674FileCheckPatternContext *Context, const SourceMgr &SM);675/// Parses the pattern in \p PatternStr and initializes this Pattern instance676/// accordingly.677///678/// \p Prefix provides which prefix is being matched, \p Req describes the679/// global options that influence the parsing such as whitespace680/// canonicalization, \p SM provides the SourceMgr used for error reports.681/// \returns true in case of an error, false otherwise.682bool parsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM,683const FileCheckRequest &Req);684struct Match {685size_t Pos;686size_t Len;687};688struct MatchResult {689std::optional<Match> TheMatch;690Error TheError;691MatchResult(size_t MatchPos, size_t MatchLen, Error E)692: TheMatch(Match{MatchPos, MatchLen}), TheError(std::move(E)) {}693MatchResult(Match M, Error E) : TheMatch(M), TheError(std::move(E)) {}694MatchResult(Error E) : TheError(std::move(E)) {}695};696/// Matches the pattern string against the input buffer \p Buffer.697///698/// \returns either (1) an error resulting in no match or (2) a match possibly699/// with an error encountered while processing the match.700///701/// The GlobalVariableTable StringMap in the FileCheckPatternContext class702/// instance provides the current values of FileCheck string variables and is703/// updated if this match defines new values. Likewise, the704/// GlobalNumericVariableTable StringMap in the same class provides the705/// current values of FileCheck numeric variables and is updated if this706/// match defines new numeric values.707MatchResult match(StringRef Buffer, const SourceMgr &SM) const;708/// Prints the value of successful substitutions.709void printSubstitutions(const SourceMgr &SM, StringRef Buffer,710SMRange MatchRange, FileCheckDiag::MatchType MatchTy,711std::vector<FileCheckDiag> *Diags) const;712void printFuzzyMatch(const SourceMgr &SM, StringRef Buffer,713std::vector<FileCheckDiag> *Diags) const;714715bool hasVariable() const {716return !(Substitutions.empty() && VariableDefs.empty());717}718void printVariableDefs(const SourceMgr &SM, FileCheckDiag::MatchType MatchTy,719std::vector<FileCheckDiag> *Diags) const;720721Check::FileCheckType getCheckTy() const { return CheckTy; }722723int getCount() const { return CheckTy.getCount(); }724725private:726bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM);727void AddBackrefToRegEx(unsigned BackrefNum);728/// Computes an arbitrary estimate for the quality of matching this pattern729/// at the start of \p Buffer; a distance of zero should correspond to a730/// perfect match.731unsigned computeMatchDistance(StringRef Buffer) const;732/// Finds the closing sequence of a regex variable usage or definition.733///734/// \p Str has to point in the beginning of the definition (right after the735/// opening sequence). \p SM holds the SourceMgr used for error reporting.736/// \returns the offset of the closing sequence within Str, or npos if it737/// was not found.738static size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM);739740/// Parses \p Expr for the name of a numeric variable to be defined at line741/// \p LineNumber, or before input is parsed if \p LineNumber is None.742/// \returns a pointer to the class instance representing that variable,743/// creating it if needed, or an error holding a diagnostic against \p SM744/// should defining such a variable be invalid.745static Expected<NumericVariable *> parseNumericVariableDefinition(746StringRef &Expr, FileCheckPatternContext *Context,747std::optional<size_t> LineNumber, ExpressionFormat ImplicitFormat,748const SourceMgr &SM);749/// Parses \p Name as a (pseudo if \p IsPseudo is true) numeric variable use750/// at line \p LineNumber, or before input is parsed if \p LineNumber is751/// None. Parameter \p Context points to the class instance holding the live752/// string and numeric variables. \returns the pointer to the class instance753/// representing that variable if successful, or an error holding a754/// diagnostic against \p SM otherwise.755static Expected<std::unique_ptr<NumericVariableUse>> parseNumericVariableUse(756StringRef Name, bool IsPseudo, std::optional<size_t> LineNumber,757FileCheckPatternContext *Context, const SourceMgr &SM);758enum class AllowedOperand { LineVar, LegacyLiteral, Any };759/// Parses \p Expr for use of a numeric operand at line \p LineNumber, or760/// before input is parsed if \p LineNumber is None. Accepts literal values,761/// numeric variables and function calls, depending on the value of \p AO.762/// \p MaybeInvalidConstraint indicates whether the text being parsed could763/// be an invalid constraint. \p Context points to the class instance holding764/// the live string and numeric variables. \returns the class representing765/// that operand in the AST of the expression or an error holding a766/// diagnostic against \p SM otherwise. If \p Expr starts with a "(" this767/// function will attempt to parse a parenthesized expression.768static Expected<std::unique_ptr<ExpressionAST>>769parseNumericOperand(StringRef &Expr, AllowedOperand AO, bool ConstraintParsed,770std::optional<size_t> LineNumber,771FileCheckPatternContext *Context, const SourceMgr &SM);772/// Parses and updates \p RemainingExpr for a binary operation at line773/// \p LineNumber, or before input is parsed if \p LineNumber is None. The774/// left operand of this binary operation is given in \p LeftOp and \p Expr775/// holds the string for the full expression, including the left operand.776/// Parameter \p IsLegacyLineExpr indicates whether we are parsing a legacy777/// @LINE expression. Parameter \p Context points to the class instance778/// holding the live string and numeric variables. \returns the class779/// representing the binary operation in the AST of the expression, or an780/// error holding a diagnostic against \p SM otherwise.781static Expected<std::unique_ptr<ExpressionAST>>782parseBinop(StringRef Expr, StringRef &RemainingExpr,783std::unique_ptr<ExpressionAST> LeftOp, bool IsLegacyLineExpr,784std::optional<size_t> LineNumber, FileCheckPatternContext *Context,785const SourceMgr &SM);786787/// Parses a parenthesized expression inside \p Expr at line \p LineNumber, or788/// before input is parsed if \p LineNumber is None. \p Expr must start with789/// a '('. Accepts both literal values and numeric variables. Parameter \p790/// Context points to the class instance holding the live string and numeric791/// variables. \returns the class representing that operand in the AST of the792/// expression or an error holding a diagnostic against \p SM otherwise.793static Expected<std::unique_ptr<ExpressionAST>>794parseParenExpr(StringRef &Expr, std::optional<size_t> LineNumber,795FileCheckPatternContext *Context, const SourceMgr &SM);796797/// Parses \p Expr for an argument list belonging to a call to function \p798/// FuncName at line \p LineNumber, or before input is parsed if \p LineNumber799/// is None. Parameter \p FuncLoc is the source location used for diagnostics.800/// Parameter \p Context points to the class instance holding the live string801/// and numeric variables. \returns the class representing that call in the802/// AST of the expression or an error holding a diagnostic against \p SM803/// otherwise.804static Expected<std::unique_ptr<ExpressionAST>>805parseCallExpr(StringRef &Expr, StringRef FuncName,806std::optional<size_t> LineNumber,807FileCheckPatternContext *Context, const SourceMgr &SM);808};809810//===----------------------------------------------------------------------===//811// Check Strings.812//===----------------------------------------------------------------------===//813814/// A check that we found in the input file.815struct FileCheckString {816/// The pattern to match.817Pattern Pat;818819/// Which prefix name this check matched.820StringRef Prefix;821822/// The location in the match file that the check string was specified.823SMLoc Loc;824825/// Hold the information about the DAG/NOT strings in the program, which are826/// not explicitly stored otherwise. This allows for better and more accurate827/// diagnostic messages.828struct DagNotPrefixInfo {829Pattern DagNotPat;830StringRef DagNotPrefix;831832DagNotPrefixInfo(const Pattern &P, StringRef S)833: DagNotPat(P), DagNotPrefix(S) {}834};835836/// Hold the DAG/NOT strings occurring in the input file.837std::vector<DagNotPrefixInfo> DagNotStrings;838839FileCheckString(const Pattern &P, StringRef S, SMLoc L)840: Pat(P), Prefix(S), Loc(L) {}841842/// Matches check string and its "not strings" and/or "dag strings".843size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode,844size_t &MatchLen, FileCheckRequest &Req,845std::vector<FileCheckDiag> *Diags) const;846847/// Verifies that there is a single line in the given \p Buffer. Errors are848/// reported against \p SM.849bool CheckNext(const SourceMgr &SM, StringRef Buffer) const;850/// Verifies that there is no newline in the given \p Buffer. Errors are851/// reported against \p SM.852bool CheckSame(const SourceMgr &SM, StringRef Buffer) const;853/// Verifies that none of the strings in \p NotStrings are found in the given854/// \p Buffer. Errors are reported against \p SM and diagnostics recorded in855/// \p Diags according to the verbosity level set in \p Req.856bool CheckNot(const SourceMgr &SM, StringRef Buffer,857const std::vector<const DagNotPrefixInfo *> &NotStrings,858const FileCheckRequest &Req,859std::vector<FileCheckDiag> *Diags) const;860/// Matches "dag strings" and their mixed "not strings".861size_t CheckDag(const SourceMgr &SM, StringRef Buffer,862std::vector<const DagNotPrefixInfo *> &NotStrings,863const FileCheckRequest &Req,864std::vector<FileCheckDiag> *Diags) const;865};866867} // namespace llvm868869#endif870871872