15ffd940aSRaphael Isemann //===-- FileCheckImpl.h - Private FileCheck Interface ------------*- C++ -*-==// 25ffd940aSRaphael Isemann // 35ffd940aSRaphael Isemann // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd940aSRaphael Isemann // See https://llvm.org/LICENSE.txt for license information. 55ffd940aSRaphael Isemann // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd940aSRaphael Isemann // 75ffd940aSRaphael Isemann //===----------------------------------------------------------------------===// 85ffd940aSRaphael Isemann // 95ffd940aSRaphael Isemann // This file defines the private interfaces of FileCheck. Its purpose is to 105ffd940aSRaphael Isemann // allow unit testing of FileCheck and to separate the interface from the 115ffd940aSRaphael Isemann // implementation. It is only meant to be used by FileCheck. 125ffd940aSRaphael Isemann // 135ffd940aSRaphael Isemann //===----------------------------------------------------------------------===// 145ffd940aSRaphael Isemann 155ffd940aSRaphael Isemann #ifndef LLVM_LIB_FILECHECK_FILECHECKIMPL_H 165ffd940aSRaphael Isemann #define LLVM_LIB_FILECHECK_FILECHECKIMPL_H 175ffd940aSRaphael Isemann 18cf57fcfaSThomas Preud'homme #include "llvm/ADT/APInt.h" 195ffd940aSRaphael Isemann #include "llvm/ADT/StringMap.h" 205ffd940aSRaphael Isemann #include "llvm/ADT/StringRef.h" 215ffd940aSRaphael Isemann #include "llvm/FileCheck/FileCheck.h" 225ffd940aSRaphael Isemann #include "llvm/Support/Error.h" 235ffd940aSRaphael Isemann #include "llvm/Support/SourceMgr.h" 245ffd940aSRaphael Isemann #include <map> 2594081642SFangrui Song #include <optional> 265ffd940aSRaphael Isemann #include <string> 275ffd940aSRaphael Isemann #include <vector> 285ffd940aSRaphael Isemann 295ffd940aSRaphael Isemann namespace llvm { 305ffd940aSRaphael Isemann 315ffd940aSRaphael Isemann //===----------------------------------------------------------------------===// 325ffd940aSRaphael Isemann // Numeric substitution handling code. 335ffd940aSRaphael Isemann //===----------------------------------------------------------------------===// 345ffd940aSRaphael Isemann 355ffd940aSRaphael Isemann /// Type representing the format an expression value should be textualized into 365ffd940aSRaphael Isemann /// for matching. Used to represent both explicit format specifiers as well as 375ffd940aSRaphael Isemann /// implicit format from using numeric variables. 385ffd940aSRaphael Isemann struct ExpressionFormat { 395ffd940aSRaphael Isemann enum class Kind { 405ffd940aSRaphael Isemann /// Denote absence of format. Used for implicit format of literals and 415ffd940aSRaphael Isemann /// empty expressions. 425ffd940aSRaphael Isemann NoFormat, 435ffd940aSRaphael Isemann /// Value is an unsigned integer and should be printed as a decimal number. 445ffd940aSRaphael Isemann Unsigned, 455ffd940aSRaphael Isemann /// Value is a signed integer and should be printed as a decimal number. 465ffd940aSRaphael Isemann Signed, 475ffd940aSRaphael Isemann /// Value should be printed as an uppercase hex number. 485ffd940aSRaphael Isemann HexUpper, 495ffd940aSRaphael Isemann /// Value should be printed as a lowercase hex number. 505ffd940aSRaphael Isemann HexLower 515ffd940aSRaphael Isemann }; 525ffd940aSRaphael Isemann 535ffd940aSRaphael Isemann private: 545ffd940aSRaphael Isemann Kind Value; 555ffd940aSRaphael Isemann unsigned Precision = 0; 56f9e2a62cSThomas Preud'homme /// printf-like "alternate form" selected. 57f9e2a62cSThomas Preud'homme bool AlternateForm = false; 585ffd940aSRaphael Isemann 595ffd940aSRaphael Isemann public: 605ffd940aSRaphael Isemann /// Evaluates a format to true if it can be used in a match. 615ffd940aSRaphael Isemann explicit operator bool() const { return Value != Kind::NoFormat; } 625ffd940aSRaphael Isemann 635ffd940aSRaphael Isemann /// Define format equality: formats are equal if neither is NoFormat and 645ffd940aSRaphael Isemann /// their kinds and precision are the same. 655ffd940aSRaphael Isemann bool operator==(const ExpressionFormat &Other) const { 665ffd940aSRaphael Isemann return Value != Kind::NoFormat && Value == Other.Value && 67f9e2a62cSThomas Preud'homme Precision == Other.Precision && AlternateForm == Other.AlternateForm; 685ffd940aSRaphael Isemann } 695ffd940aSRaphael Isemann 705ffd940aSRaphael Isemann bool operator!=(const ExpressionFormat &Other) const { 715ffd940aSRaphael Isemann return !(*this == Other); 725ffd940aSRaphael Isemann } 735ffd940aSRaphael Isemann 745ffd940aSRaphael Isemann bool operator==(Kind OtherValue) const { return Value == OtherValue; } 755ffd940aSRaphael Isemann 765ffd940aSRaphael Isemann bool operator!=(Kind OtherValue) const { return !(*this == OtherValue); } 775ffd940aSRaphael Isemann 785ffd940aSRaphael Isemann /// \returns the format specifier corresponding to this format as a string. 795ffd940aSRaphael Isemann StringRef toString() const; 805ffd940aSRaphael Isemann 815ffd940aSRaphael Isemann ExpressionFormat() : Value(Kind::NoFormat){}; 825ffd940aSRaphael Isemann explicit ExpressionFormat(Kind Value) : Value(Value), Precision(0){}; 835ffd940aSRaphael Isemann explicit ExpressionFormat(Kind Value, unsigned Precision) 845ffd940aSRaphael Isemann : Value(Value), Precision(Precision){}; 85f9e2a62cSThomas Preud'homme explicit ExpressionFormat(Kind Value, unsigned Precision, bool AlternateForm) 86f9e2a62cSThomas Preud'homme : Value(Value), Precision(Precision), AlternateForm(AlternateForm){}; 875ffd940aSRaphael Isemann 885ffd940aSRaphael Isemann /// \returns a wildcard regular expression string that matches any value in 895ffd940aSRaphael Isemann /// the format represented by this instance and no other value, or an error 905ffd940aSRaphael Isemann /// if the format is NoFormat. 915ffd940aSRaphael Isemann Expected<std::string> getWildcardRegex() const; 925ffd940aSRaphael Isemann 935ffd940aSRaphael Isemann /// \returns the string representation of \p Value in the format represented 945ffd940aSRaphael Isemann /// by this instance, or an error if conversion to this format failed or the 955ffd940aSRaphael Isemann /// format is NoFormat. 96e15e969aSThomas Preud'homme Expected<std::string> getMatchingString(APInt Value) const; 975ffd940aSRaphael Isemann 985ffd940aSRaphael Isemann /// \returns the value corresponding to string representation \p StrVal 99b743c193SThomas Preud'homme /// according to the matching format represented by this instance. 100b743c193SThomas Preud'homme APInt valueFromStringRepr(StringRef StrVal, const SourceMgr &SM) const; 1015ffd940aSRaphael Isemann }; 1025ffd940aSRaphael Isemann 1035ffd940aSRaphael Isemann /// Class to represent an overflow error that might result when manipulating a 1045ffd940aSRaphael Isemann /// value. 1055ffd940aSRaphael Isemann class OverflowError : public ErrorInfo<OverflowError> { 1065ffd940aSRaphael Isemann public: 1075ffd940aSRaphael Isemann static char ID; 1085ffd940aSRaphael Isemann 1095ffd940aSRaphael Isemann std::error_code convertToErrorCode() const override { 1105ffd940aSRaphael Isemann return std::make_error_code(std::errc::value_too_large); 1115ffd940aSRaphael Isemann } 1125ffd940aSRaphael Isemann 1135ffd940aSRaphael Isemann void log(raw_ostream &OS) const override { OS << "overflow error"; } 1145ffd940aSRaphael Isemann }; 1155ffd940aSRaphael Isemann 1165ffd940aSRaphael Isemann /// Performs operation and \returns its result or an error in case of failure, 1175ffd940aSRaphael Isemann /// such as if an overflow occurs. 118e15e969aSThomas Preud'homme Expected<APInt> exprAdd(const APInt &Lhs, const APInt &Rhs, bool &Overflow); 119e15e969aSThomas Preud'homme Expected<APInt> exprSub(const APInt &Lhs, const APInt &Rhs, bool &Overflow); 120e15e969aSThomas Preud'homme Expected<APInt> exprMul(const APInt &Lhs, const APInt &Rhs, bool &Overflow); 121e15e969aSThomas Preud'homme Expected<APInt> exprDiv(const APInt &Lhs, const APInt &Rhs, bool &Overflow); 122e15e969aSThomas Preud'homme Expected<APInt> exprMax(const APInt &Lhs, const APInt &Rhs, bool &Overflow); 123e15e969aSThomas Preud'homme Expected<APInt> exprMin(const APInt &Lhs, const APInt &Rhs, bool &Overflow); 1245ffd940aSRaphael Isemann 1255ffd940aSRaphael Isemann /// Base class representing the AST of a given expression. 1265ffd940aSRaphael Isemann class ExpressionAST { 1275ffd940aSRaphael Isemann private: 1285ffd940aSRaphael Isemann StringRef ExpressionStr; 1295ffd940aSRaphael Isemann 1305ffd940aSRaphael Isemann public: 1315ffd940aSRaphael Isemann ExpressionAST(StringRef ExpressionStr) : ExpressionStr(ExpressionStr) {} 1325ffd940aSRaphael Isemann 1335ffd940aSRaphael Isemann virtual ~ExpressionAST() = default; 1345ffd940aSRaphael Isemann 1355ffd940aSRaphael Isemann StringRef getExpressionStr() const { return ExpressionStr; } 1365ffd940aSRaphael Isemann 1375ffd940aSRaphael Isemann /// Evaluates and \returns the value of the expression represented by this 1385ffd940aSRaphael Isemann /// AST or an error if evaluation fails. 139e15e969aSThomas Preud'homme virtual Expected<APInt> eval() const = 0; 1405ffd940aSRaphael Isemann 1415ffd940aSRaphael Isemann /// \returns either the implicit format of this AST, a diagnostic against 1425ffd940aSRaphael Isemann /// \p SM if implicit formats of the AST's components conflict, or NoFormat 1435ffd940aSRaphael Isemann /// if the AST has no implicit format (e.g. AST is made up of a single 1445ffd940aSRaphael Isemann /// literal). 1455ffd940aSRaphael Isemann virtual Expected<ExpressionFormat> 1465ffd940aSRaphael Isemann getImplicitFormat(const SourceMgr &SM) const { 1475ffd940aSRaphael Isemann return ExpressionFormat(); 1485ffd940aSRaphael Isemann } 1495ffd940aSRaphael Isemann }; 1505ffd940aSRaphael Isemann 1515ffd940aSRaphael Isemann /// Class representing an unsigned literal in the AST of an expression. 1525ffd940aSRaphael Isemann class ExpressionLiteral : public ExpressionAST { 1535ffd940aSRaphael Isemann private: 1545ffd940aSRaphael Isemann /// Actual value of the literal. 155e15e969aSThomas Preud'homme APInt Value; 1565ffd940aSRaphael Isemann 1575ffd940aSRaphael Isemann public: 1580726cb00SThomas Preud'homme explicit ExpressionLiteral(StringRef ExpressionStr, APInt Val) 1595ffd940aSRaphael Isemann : ExpressionAST(ExpressionStr), Value(Val) {} 1605ffd940aSRaphael Isemann 1615ffd940aSRaphael Isemann /// \returns the literal's value. 162e15e969aSThomas Preud'homme Expected<APInt> eval() const override { return Value; } 1635ffd940aSRaphael Isemann }; 1645ffd940aSRaphael Isemann 1655ffd940aSRaphael Isemann /// Class to represent an undefined variable error, which quotes that 1665ffd940aSRaphael Isemann /// variable's name when printed. 1675ffd940aSRaphael Isemann class UndefVarError : public ErrorInfo<UndefVarError> { 1685ffd940aSRaphael Isemann private: 1695ffd940aSRaphael Isemann StringRef VarName; 1705ffd940aSRaphael Isemann 1715ffd940aSRaphael Isemann public: 1725ffd940aSRaphael Isemann static char ID; 1735ffd940aSRaphael Isemann 1745ffd940aSRaphael Isemann UndefVarError(StringRef VarName) : VarName(VarName) {} 1755ffd940aSRaphael Isemann 1765ffd940aSRaphael Isemann StringRef getVarName() const { return VarName; } 1775ffd940aSRaphael Isemann 1785ffd940aSRaphael Isemann std::error_code convertToErrorCode() const override { 1795ffd940aSRaphael Isemann return inconvertibleErrorCode(); 1805ffd940aSRaphael Isemann } 1815ffd940aSRaphael Isemann 1825ffd940aSRaphael Isemann /// Print name of variable associated with this error. 1835ffd940aSRaphael Isemann void log(raw_ostream &OS) const override { 184fd941036SThomas Preud'homme OS << "undefined variable: " << VarName; 1855ffd940aSRaphael Isemann } 1865ffd940aSRaphael Isemann }; 1875ffd940aSRaphael Isemann 1885ffd940aSRaphael Isemann /// Class representing an expression and its matching format. 1895ffd940aSRaphael Isemann class Expression { 1905ffd940aSRaphael Isemann private: 1915ffd940aSRaphael Isemann /// Pointer to AST of the expression. 1925ffd940aSRaphael Isemann std::unique_ptr<ExpressionAST> AST; 1935ffd940aSRaphael Isemann 1945ffd940aSRaphael Isemann /// Format to use (e.g. hex upper case letters) when matching the value. 1955ffd940aSRaphael Isemann ExpressionFormat Format; 1965ffd940aSRaphael Isemann 1975ffd940aSRaphael Isemann public: 1985ffd940aSRaphael Isemann /// Generic constructor for an expression represented by the given \p AST and 1995ffd940aSRaphael Isemann /// whose matching format is \p Format. 2005ffd940aSRaphael Isemann Expression(std::unique_ptr<ExpressionAST> AST, ExpressionFormat Format) 2015ffd940aSRaphael Isemann : AST(std::move(AST)), Format(Format) {} 2025ffd940aSRaphael Isemann 2035ffd940aSRaphael Isemann /// \returns pointer to AST of the expression. Pointer is guaranteed to be 2045ffd940aSRaphael Isemann /// valid as long as this object is. 2055ffd940aSRaphael Isemann ExpressionAST *getAST() const { return AST.get(); } 2065ffd940aSRaphael Isemann 2075ffd940aSRaphael Isemann ExpressionFormat getFormat() const { return Format; } 2085ffd940aSRaphael Isemann }; 2095ffd940aSRaphael Isemann 2105ffd940aSRaphael Isemann /// Class representing a numeric variable and its associated current value. 2115ffd940aSRaphael Isemann class NumericVariable { 2125ffd940aSRaphael Isemann private: 2135ffd940aSRaphael Isemann /// Name of the numeric variable. 2145ffd940aSRaphael Isemann StringRef Name; 2155ffd940aSRaphael Isemann 2165ffd940aSRaphael Isemann /// Format to use for expressions using this variable without an explicit 2175ffd940aSRaphael Isemann /// format. 2185ffd940aSRaphael Isemann ExpressionFormat ImplicitFormat; 2195ffd940aSRaphael Isemann 220595f1a6aSKazu Hirata /// Value of numeric variable, if defined, or std::nullopt otherwise. 221e15e969aSThomas Preud'homme std::optional<APInt> Value; 2225ffd940aSRaphael Isemann 223595f1a6aSKazu Hirata /// The input buffer's string from which Value was parsed, or std::nullopt. 2241ca0cb71SKazu Hirata /// See comments on getStringValue for a discussion of the std::nullopt case. 22594081642SFangrui Song std::optional<StringRef> StrValue; 2265ffd940aSRaphael Isemann 227595f1a6aSKazu Hirata /// Line number where this variable is defined, or std::nullopt if defined 228595f1a6aSKazu Hirata /// before input is parsed. Used to determine whether a variable is defined on 229595f1a6aSKazu Hirata /// the same line as a given use. 23094081642SFangrui Song std::optional<size_t> DefLineNumber; 2315ffd940aSRaphael Isemann 2325ffd940aSRaphael Isemann public: 2335ffd940aSRaphael Isemann /// Constructor for a variable \p Name with implicit format \p ImplicitFormat 2345ffd940aSRaphael Isemann /// defined at line \p DefLineNumber or defined before input is parsed if 2351ca0cb71SKazu Hirata /// \p DefLineNumber is std::nullopt. 2365ffd940aSRaphael Isemann explicit NumericVariable(StringRef Name, ExpressionFormat ImplicitFormat, 23794081642SFangrui Song std::optional<size_t> DefLineNumber = std::nullopt) 2385ffd940aSRaphael Isemann : Name(Name), ImplicitFormat(ImplicitFormat), 2395ffd940aSRaphael Isemann DefLineNumber(DefLineNumber) {} 2405ffd940aSRaphael Isemann 2415ffd940aSRaphael Isemann /// \returns name of this numeric variable. 2425ffd940aSRaphael Isemann StringRef getName() const { return Name; } 2435ffd940aSRaphael Isemann 2445ffd940aSRaphael Isemann /// \returns implicit format of this numeric variable. 2455ffd940aSRaphael Isemann ExpressionFormat getImplicitFormat() const { return ImplicitFormat; } 2465ffd940aSRaphael Isemann 2475ffd940aSRaphael Isemann /// \returns this variable's value. 248e15e969aSThomas Preud'homme std::optional<APInt> getValue() const { return Value; } 2495ffd940aSRaphael Isemann 2505ffd940aSRaphael Isemann /// \returns the input buffer's string from which this variable's value was 251595f1a6aSKazu Hirata /// parsed, or std::nullopt if the value is not yet defined or was not parsed 252595f1a6aSKazu Hirata /// from the input buffer. For example, the value of @LINE is not parsed from 253595f1a6aSKazu Hirata /// the input buffer, and some numeric variables are parsed from the command 2545ffd940aSRaphael Isemann /// line instead. 25594081642SFangrui Song std::optional<StringRef> getStringValue() const { return StrValue; } 2565ffd940aSRaphael Isemann 2575ffd940aSRaphael Isemann /// Sets value of this numeric variable to \p NewValue, and sets the input 2585ffd940aSRaphael Isemann /// buffer string from which it was parsed to \p NewStrValue. See comments on 2591ca0cb71SKazu Hirata /// getStringValue for a discussion of when the latter can be std::nullopt. 260e15e969aSThomas Preud'homme void setValue(APInt NewValue, 26194081642SFangrui Song std::optional<StringRef> NewStrValue = std::nullopt) { 2625ffd940aSRaphael Isemann Value = NewValue; 2635ffd940aSRaphael Isemann StrValue = NewStrValue; 2645ffd940aSRaphael Isemann } 2655ffd940aSRaphael Isemann 2665ffd940aSRaphael Isemann /// Clears value of this numeric variable, regardless of whether it is 2675ffd940aSRaphael Isemann /// currently defined or not. 2685ffd940aSRaphael Isemann void clearValue() { 269aadaafacSKazu Hirata Value = std::nullopt; 270aadaafacSKazu Hirata StrValue = std::nullopt; 2715ffd940aSRaphael Isemann } 2725ffd940aSRaphael Isemann 273595f1a6aSKazu Hirata /// \returns the line number where this variable is defined, if any, or 274595f1a6aSKazu Hirata /// std::nullopt if defined before input is parsed. 27594081642SFangrui Song std::optional<size_t> getDefLineNumber() const { return DefLineNumber; } 2765ffd940aSRaphael Isemann }; 2775ffd940aSRaphael Isemann 2785ffd940aSRaphael Isemann /// Class representing the use of a numeric variable in the AST of an 2795ffd940aSRaphael Isemann /// expression. 2805ffd940aSRaphael Isemann class NumericVariableUse : public ExpressionAST { 2815ffd940aSRaphael Isemann private: 2825ffd940aSRaphael Isemann /// Pointer to the class instance for the variable this use is about. 2835ffd940aSRaphael Isemann NumericVariable *Variable; 2845ffd940aSRaphael Isemann 2855ffd940aSRaphael Isemann public: 2865ffd940aSRaphael Isemann NumericVariableUse(StringRef Name, NumericVariable *Variable) 2875ffd940aSRaphael Isemann : ExpressionAST(Name), Variable(Variable) {} 2885ffd940aSRaphael Isemann /// \returns the value of the variable referenced by this instance. 289e15e969aSThomas Preud'homme Expected<APInt> eval() const override; 2905ffd940aSRaphael Isemann 2915ffd940aSRaphael Isemann /// \returns implicit format of this numeric variable. 2925ffd940aSRaphael Isemann Expected<ExpressionFormat> 2935ffd940aSRaphael Isemann getImplicitFormat(const SourceMgr &SM) const override { 2945ffd940aSRaphael Isemann return Variable->getImplicitFormat(); 2955ffd940aSRaphael Isemann } 2965ffd940aSRaphael Isemann }; 2975ffd940aSRaphael Isemann 2985ffd940aSRaphael Isemann /// Type of functions evaluating a given binary operation. 299e15e969aSThomas Preud'homme using binop_eval_t = Expected<APInt> (*)(const APInt &, const APInt &, bool &); 3005ffd940aSRaphael Isemann 3015ffd940aSRaphael Isemann /// Class representing a single binary operation in the AST of an expression. 3025ffd940aSRaphael Isemann class BinaryOperation : public ExpressionAST { 3035ffd940aSRaphael Isemann private: 3045ffd940aSRaphael Isemann /// Left operand. 3055ffd940aSRaphael Isemann std::unique_ptr<ExpressionAST> LeftOperand; 3065ffd940aSRaphael Isemann 3075ffd940aSRaphael Isemann /// Right operand. 3085ffd940aSRaphael Isemann std::unique_ptr<ExpressionAST> RightOperand; 3095ffd940aSRaphael Isemann 3105ffd940aSRaphael Isemann /// Pointer to function that can evaluate this binary operation. 3115ffd940aSRaphael Isemann binop_eval_t EvalBinop; 3125ffd940aSRaphael Isemann 3135ffd940aSRaphael Isemann public: 3145ffd940aSRaphael Isemann BinaryOperation(StringRef ExpressionStr, binop_eval_t EvalBinop, 3155ffd940aSRaphael Isemann std::unique_ptr<ExpressionAST> LeftOp, 3165ffd940aSRaphael Isemann std::unique_ptr<ExpressionAST> RightOp) 3175ffd940aSRaphael Isemann : ExpressionAST(ExpressionStr), EvalBinop(EvalBinop) { 3185ffd940aSRaphael Isemann LeftOperand = std::move(LeftOp); 3195ffd940aSRaphael Isemann RightOperand = std::move(RightOp); 3205ffd940aSRaphael Isemann } 3215ffd940aSRaphael Isemann 3225ffd940aSRaphael Isemann /// Evaluates the value of the binary operation represented by this AST, 3235ffd940aSRaphael Isemann /// using EvalBinop on the result of recursively evaluating the operands. 3245ffd940aSRaphael Isemann /// \returns the expression value or an error if an undefined numeric 3255ffd940aSRaphael Isemann /// variable is used in one of the operands. 326e15e969aSThomas Preud'homme Expected<APInt> eval() const override; 3275ffd940aSRaphael Isemann 3285ffd940aSRaphael Isemann /// \returns the implicit format of this AST, if any, a diagnostic against 3295ffd940aSRaphael Isemann /// \p SM if the implicit formats of the AST's components conflict, or no 3305ffd940aSRaphael Isemann /// format if the AST has no implicit format (e.g. AST is made of a single 3315ffd940aSRaphael Isemann /// literal). 3325ffd940aSRaphael Isemann Expected<ExpressionFormat> 3335ffd940aSRaphael Isemann getImplicitFormat(const SourceMgr &SM) const override; 3345ffd940aSRaphael Isemann }; 3355ffd940aSRaphael Isemann 3365ffd940aSRaphael Isemann class FileCheckPatternContext; 3375ffd940aSRaphael Isemann 3385ffd940aSRaphael Isemann /// Class representing a substitution to perform in the RegExStr string. 3395ffd940aSRaphael Isemann class Substitution { 3405ffd940aSRaphael Isemann protected: 3415ffd940aSRaphael Isemann /// Pointer to a class instance holding, among other things, the table with 3425ffd940aSRaphael Isemann /// the values of live string variables at the start of any given CHECK line. 3435ffd940aSRaphael Isemann /// Used for substituting string variables with the text they were defined 3445ffd940aSRaphael Isemann /// as. Expressions are linked to the numeric variables they use at 3455ffd940aSRaphael Isemann /// parse time and directly access the value of the numeric variable to 3465ffd940aSRaphael Isemann /// evaluate their value. 3475ffd940aSRaphael Isemann FileCheckPatternContext *Context; 3485ffd940aSRaphael Isemann 3495ffd940aSRaphael Isemann /// The string that needs to be substituted for something else. For a 3505ffd940aSRaphael Isemann /// string variable this is its name, otherwise this is the whole expression. 3515ffd940aSRaphael Isemann StringRef FromStr; 3525ffd940aSRaphael Isemann 3535ffd940aSRaphael Isemann // Index in RegExStr of where to do the substitution. 3545ffd940aSRaphael Isemann size_t InsertIdx; 3555ffd940aSRaphael Isemann 3565ffd940aSRaphael Isemann public: 3575ffd940aSRaphael Isemann Substitution(FileCheckPatternContext *Context, StringRef VarName, 3585ffd940aSRaphael Isemann size_t InsertIdx) 3595ffd940aSRaphael Isemann : Context(Context), FromStr(VarName), InsertIdx(InsertIdx) {} 3605ffd940aSRaphael Isemann 3615ffd940aSRaphael Isemann virtual ~Substitution() = default; 3625ffd940aSRaphael Isemann 3635ffd940aSRaphael Isemann /// \returns the string to be substituted for something else. 3645ffd940aSRaphael Isemann StringRef getFromString() const { return FromStr; } 3655ffd940aSRaphael Isemann 3665ffd940aSRaphael Isemann /// \returns the index where the substitution is to be performed in RegExStr. 3675ffd940aSRaphael Isemann size_t getIndex() const { return InsertIdx; } 3685ffd940aSRaphael Isemann 3695ffd940aSRaphael Isemann /// \returns a string containing the result of the substitution represented 3705ffd940aSRaphael Isemann /// by this class instance or an error if substitution failed. 3715ffd940aSRaphael Isemann virtual Expected<std::string> getResult() const = 0; 3725ffd940aSRaphael Isemann }; 3735ffd940aSRaphael Isemann 3745ffd940aSRaphael Isemann class StringSubstitution : public Substitution { 3755ffd940aSRaphael Isemann public: 3765ffd940aSRaphael Isemann StringSubstitution(FileCheckPatternContext *Context, StringRef VarName, 3775ffd940aSRaphael Isemann size_t InsertIdx) 3785ffd940aSRaphael Isemann : Substitution(Context, VarName, InsertIdx) {} 3795ffd940aSRaphael Isemann 3805ffd940aSRaphael Isemann /// \returns the text that the string variable in this substitution matched 3815ffd940aSRaphael Isemann /// when defined, or an error if the variable is undefined. 3825ffd940aSRaphael Isemann Expected<std::string> getResult() const override; 3835ffd940aSRaphael Isemann }; 3845ffd940aSRaphael Isemann 3855ffd940aSRaphael Isemann class NumericSubstitution : public Substitution { 3865ffd940aSRaphael Isemann private: 3875ffd940aSRaphael Isemann /// Pointer to the class representing the expression whose value is to be 3885ffd940aSRaphael Isemann /// substituted. 3895ffd940aSRaphael Isemann std::unique_ptr<Expression> ExpressionPointer; 3905ffd940aSRaphael Isemann 3915ffd940aSRaphael Isemann public: 3925ffd940aSRaphael Isemann NumericSubstitution(FileCheckPatternContext *Context, StringRef ExpressionStr, 3935ffd940aSRaphael Isemann std::unique_ptr<Expression> ExpressionPointer, 3945ffd940aSRaphael Isemann size_t InsertIdx) 3955ffd940aSRaphael Isemann : Substitution(Context, ExpressionStr, InsertIdx), 3965ffd940aSRaphael Isemann ExpressionPointer(std::move(ExpressionPointer)) {} 3975ffd940aSRaphael Isemann 3985ffd940aSRaphael Isemann /// \returns a string containing the result of evaluating the expression in 3995ffd940aSRaphael Isemann /// this substitution, or an error if evaluation failed. 4005ffd940aSRaphael Isemann Expected<std::string> getResult() const override; 4015ffd940aSRaphael Isemann }; 4025ffd940aSRaphael Isemann 4035ffd940aSRaphael Isemann //===----------------------------------------------------------------------===// 4045ffd940aSRaphael Isemann // Pattern handling code. 4055ffd940aSRaphael Isemann //===----------------------------------------------------------------------===// 4065ffd940aSRaphael Isemann 4075ffd940aSRaphael Isemann /// Class holding the Pattern global state, shared by all patterns: tables 4085ffd940aSRaphael Isemann /// holding values of variables and whether they are defined or not at any 4095ffd940aSRaphael Isemann /// given time in the matching process. 4105ffd940aSRaphael Isemann class FileCheckPatternContext { 4115ffd940aSRaphael Isemann friend class Pattern; 4125ffd940aSRaphael Isemann 4135ffd940aSRaphael Isemann private: 4145ffd940aSRaphael Isemann /// When matching a given pattern, this holds the value of all the string 4155ffd940aSRaphael Isemann /// variables defined in previous patterns. In a pattern, only the last 4165ffd940aSRaphael Isemann /// definition for a given variable is recorded in this table. 4175ffd940aSRaphael Isemann /// Back-references are used for uses after any the other definition. 4185ffd940aSRaphael Isemann StringMap<StringRef> GlobalVariableTable; 4195ffd940aSRaphael Isemann 4205ffd940aSRaphael Isemann /// Map of all string variables defined so far. Used at parse time to detect 4215ffd940aSRaphael Isemann /// a name conflict between a numeric variable and a string variable when 4225ffd940aSRaphael Isemann /// the former is defined on a later line than the latter. 4235ffd940aSRaphael Isemann StringMap<bool> DefinedVariableTable; 4245ffd940aSRaphael Isemann 4255ffd940aSRaphael Isemann /// When matching a given pattern, this holds the pointers to the classes 4265ffd940aSRaphael Isemann /// representing the numeric variables defined in previous patterns. When 4275ffd940aSRaphael Isemann /// matching a pattern all definitions for that pattern are recorded in the 4285ffd940aSRaphael Isemann /// NumericVariableDefs table in the Pattern instance of that pattern. 4295ffd940aSRaphael Isemann StringMap<NumericVariable *> GlobalNumericVariableTable; 4305ffd940aSRaphael Isemann 4315ffd940aSRaphael Isemann /// Pointer to the class instance representing the @LINE pseudo variable for 4325ffd940aSRaphael Isemann /// easily updating its value. 4335ffd940aSRaphael Isemann NumericVariable *LineVariable = nullptr; 4345ffd940aSRaphael Isemann 4355ffd940aSRaphael Isemann /// Vector holding pointers to all parsed numeric variables. Used to 4365ffd940aSRaphael Isemann /// automatically free them once they are guaranteed to no longer be used. 4375ffd940aSRaphael Isemann std::vector<std::unique_ptr<NumericVariable>> NumericVariables; 4385ffd940aSRaphael Isemann 4395ffd940aSRaphael Isemann /// Vector holding pointers to all parsed expressions. Used to automatically 4405ffd940aSRaphael Isemann /// free the expressions once they are guaranteed to no longer be used. 4415ffd940aSRaphael Isemann std::vector<std::unique_ptr<Expression>> Expressions; 4425ffd940aSRaphael Isemann 4435ffd940aSRaphael Isemann /// Vector holding pointers to all substitutions. Used to automatically free 4445ffd940aSRaphael Isemann /// them once they are guaranteed to no longer be used. 4455ffd940aSRaphael Isemann std::vector<std::unique_ptr<Substitution>> Substitutions; 4465ffd940aSRaphael Isemann 4475ffd940aSRaphael Isemann public: 4485ffd940aSRaphael Isemann /// \returns the value of string variable \p VarName or an error if no such 4495ffd940aSRaphael Isemann /// variable has been defined. 4505ffd940aSRaphael Isemann Expected<StringRef> getPatternVarValue(StringRef VarName); 4515ffd940aSRaphael Isemann 4525ffd940aSRaphael Isemann /// Defines string and numeric variables from definitions given on the 4535ffd940aSRaphael Isemann /// command line, passed as a vector of [#]VAR=VAL strings in 4545ffd940aSRaphael Isemann /// \p CmdlineDefines. \returns an error list containing diagnostics against 4555ffd940aSRaphael Isemann /// \p SM for all definition parsing failures, if any, or Success otherwise. 4565ffd940aSRaphael Isemann Error defineCmdlineVariables(ArrayRef<StringRef> CmdlineDefines, 4575ffd940aSRaphael Isemann SourceMgr &SM); 4585ffd940aSRaphael Isemann 4595ffd940aSRaphael Isemann /// Create @LINE pseudo variable. Value is set when pattern are being 4605ffd940aSRaphael Isemann /// matched. 4615ffd940aSRaphael Isemann void createLineVariable(); 4625ffd940aSRaphael Isemann 4635ffd940aSRaphael Isemann /// Undefines local variables (variables whose name does not start with a '$' 4645ffd940aSRaphael Isemann /// sign), i.e. removes them from GlobalVariableTable and from 4655ffd940aSRaphael Isemann /// GlobalNumericVariableTable and also clears the value of numeric 4665ffd940aSRaphael Isemann /// variables. 4675ffd940aSRaphael Isemann void clearLocalVars(); 4685ffd940aSRaphael Isemann 4695ffd940aSRaphael Isemann private: 4705ffd940aSRaphael Isemann /// Makes a new numeric variable and registers it for destruction when the 4715ffd940aSRaphael Isemann /// context is destroyed. 4725ffd940aSRaphael Isemann template <class... Types> NumericVariable *makeNumericVariable(Types... args); 4735ffd940aSRaphael Isemann 4745ffd940aSRaphael Isemann /// Makes a new string substitution and registers it for destruction when the 4755ffd940aSRaphael Isemann /// context is destroyed. 4765ffd940aSRaphael Isemann Substitution *makeStringSubstitution(StringRef VarName, size_t InsertIdx); 4775ffd940aSRaphael Isemann 4785ffd940aSRaphael Isemann /// Makes a new numeric substitution and registers it for destruction when 4795ffd940aSRaphael Isemann /// the context is destroyed. 4805ffd940aSRaphael Isemann Substitution *makeNumericSubstitution(StringRef ExpressionStr, 4815ffd940aSRaphael Isemann std::unique_ptr<Expression> Expression, 4825ffd940aSRaphael Isemann size_t InsertIdx); 4835ffd940aSRaphael Isemann }; 4845ffd940aSRaphael Isemann 4855ffd940aSRaphael Isemann /// Class to represent an error holding a diagnostic with location information 4865ffd940aSRaphael Isemann /// used when printing it. 4875ffd940aSRaphael Isemann class ErrorDiagnostic : public ErrorInfo<ErrorDiagnostic> { 4885ffd940aSRaphael Isemann private: 4895ffd940aSRaphael Isemann SMDiagnostic Diagnostic; 490dd59c132SJoel E. Denny SMRange Range; 4915ffd940aSRaphael Isemann 4925ffd940aSRaphael Isemann public: 4935ffd940aSRaphael Isemann static char ID; 4945ffd940aSRaphael Isemann 495dd59c132SJoel E. Denny ErrorDiagnostic(SMDiagnostic &&Diag, SMRange Range) 496dd59c132SJoel E. Denny : Diagnostic(Diag), Range(Range) {} 4975ffd940aSRaphael Isemann 4985ffd940aSRaphael Isemann std::error_code convertToErrorCode() const override { 4995ffd940aSRaphael Isemann return inconvertibleErrorCode(); 5005ffd940aSRaphael Isemann } 5015ffd940aSRaphael Isemann 5025ffd940aSRaphael Isemann /// Print diagnostic associated with this error when printing the error. 5035ffd940aSRaphael Isemann void log(raw_ostream &OS) const override { Diagnostic.print(nullptr, OS); } 5045ffd940aSRaphael Isemann 505dd59c132SJoel E. Denny StringRef getMessage() const { return Diagnostic.getMessage(); } 506dd59c132SJoel E. Denny SMRange getRange() const { return Range; } 507dd59c132SJoel E. Denny 508dd59c132SJoel E. Denny static Error get(const SourceMgr &SM, SMLoc Loc, const Twine &ErrMsg, 509aadaafacSKazu Hirata SMRange Range = std::nullopt) { 5105ffd940aSRaphael Isemann return make_error<ErrorDiagnostic>( 511dd59c132SJoel E. Denny SM.GetMessage(Loc, SourceMgr::DK_Error, ErrMsg), Range); 5125ffd940aSRaphael Isemann } 5135ffd940aSRaphael Isemann 5145ffd940aSRaphael Isemann static Error get(const SourceMgr &SM, StringRef Buffer, const Twine &ErrMsg) { 515dd59c132SJoel E. Denny SMLoc Start = SMLoc::getFromPointer(Buffer.data()); 516dd59c132SJoel E. Denny SMLoc End = SMLoc::getFromPointer(Buffer.data() + Buffer.size()); 517dd59c132SJoel E. Denny return get(SM, Start, ErrMsg, SMRange(Start, End)); 5185ffd940aSRaphael Isemann } 5195ffd940aSRaphael Isemann }; 5205ffd940aSRaphael Isemann 5215ffd940aSRaphael Isemann class NotFoundError : public ErrorInfo<NotFoundError> { 5225ffd940aSRaphael Isemann public: 5235ffd940aSRaphael Isemann static char ID; 5245ffd940aSRaphael Isemann 5255ffd940aSRaphael Isemann std::error_code convertToErrorCode() const override { 5265ffd940aSRaphael Isemann return inconvertibleErrorCode(); 5275ffd940aSRaphael Isemann } 5285ffd940aSRaphael Isemann 5295ffd940aSRaphael Isemann /// Print diagnostic associated with this error when printing the error. 5305ffd940aSRaphael Isemann void log(raw_ostream &OS) const override { 5315ffd940aSRaphael Isemann OS << "String not found in input"; 5325ffd940aSRaphael Isemann } 5335ffd940aSRaphael Isemann }; 5345ffd940aSRaphael Isemann 535dd59c132SJoel E. Denny /// An error that has already been reported. 536dd59c132SJoel E. Denny /// 537dd59c132SJoel E. Denny /// This class is designed to support a function whose callers may need to know 538dd59c132SJoel E. Denny /// whether the function encountered and reported an error but never need to 539dd59c132SJoel E. Denny /// know the nature of that error. For example, the function has a return type 540dd59c132SJoel E. Denny /// of \c Error and always returns either \c ErrorReported or \c ErrorSuccess. 541dd59c132SJoel E. Denny /// That interface is similar to that of a function returning bool to indicate 542dd59c132SJoel E. Denny /// an error except, in the former case, (1) there is no confusion over polarity 543dd59c132SJoel E. Denny /// and (2) the caller must either check the result or explicitly ignore it with 544dd59c132SJoel E. Denny /// a call like \c consumeError. 545dd59c132SJoel E. Denny class ErrorReported final : public ErrorInfo<ErrorReported> { 546dd59c132SJoel E. Denny public: 547dd59c132SJoel E. Denny static char ID; 548dd59c132SJoel E. Denny 549dd59c132SJoel E. Denny std::error_code convertToErrorCode() const override { 550dd59c132SJoel E. Denny return inconvertibleErrorCode(); 551dd59c132SJoel E. Denny } 552dd59c132SJoel E. Denny 553dd59c132SJoel E. Denny /// Print diagnostic associated with this error when printing the error. 554dd59c132SJoel E. Denny void log(raw_ostream &OS) const override { 555dd59c132SJoel E. Denny OS << "error previously reported"; 556dd59c132SJoel E. Denny } 557dd59c132SJoel E. Denny 558dd59c132SJoel E. Denny static inline Error reportedOrSuccess(bool HasErrorReported) { 559dd59c132SJoel E. Denny if (HasErrorReported) 560dd59c132SJoel E. Denny return make_error<ErrorReported>(); 561dd59c132SJoel E. Denny return Error::success(); 562dd59c132SJoel E. Denny } 563dd59c132SJoel E. Denny }; 564dd59c132SJoel E. Denny 5655ffd940aSRaphael Isemann class Pattern { 5665ffd940aSRaphael Isemann SMLoc PatternLoc; 5675ffd940aSRaphael Isemann 5685ffd940aSRaphael Isemann /// A fixed string to match as the pattern or empty if this pattern requires 5695ffd940aSRaphael Isemann /// a regex match. 5705ffd940aSRaphael Isemann StringRef FixedStr; 5715ffd940aSRaphael Isemann 5725ffd940aSRaphael Isemann /// A regex string to match as the pattern or empty if this pattern requires 5735ffd940aSRaphael Isemann /// a fixed string to match. 5745ffd940aSRaphael Isemann std::string RegExStr; 5755ffd940aSRaphael Isemann 5765ffd940aSRaphael Isemann /// Entries in this vector represent a substitution of a string variable or 5775ffd940aSRaphael Isemann /// an expression in the RegExStr regex at match time. For example, in the 5785ffd940aSRaphael Isemann /// case of a CHECK directive with the pattern "foo[[bar]]baz[[#N+1]]", 5795ffd940aSRaphael Isemann /// RegExStr will contain "foobaz" and we'll get two entries in this vector 5805ffd940aSRaphael Isemann /// that tells us to insert the value of string variable "bar" at offset 3 5815ffd940aSRaphael Isemann /// and the value of expression "N+1" at offset 6. 5825ffd940aSRaphael Isemann std::vector<Substitution *> Substitutions; 5835ffd940aSRaphael Isemann 5845ffd940aSRaphael Isemann /// Maps names of string variables defined in a pattern to the number of 5855ffd940aSRaphael Isemann /// their parenthesis group in RegExStr capturing their last definition. 5865ffd940aSRaphael Isemann /// 5875ffd940aSRaphael Isemann /// E.g. for the pattern "foo[[bar:.*]]baz([[bar]][[QUUX]][[bar:.*]])", 5885ffd940aSRaphael Isemann /// RegExStr will be "foo(.*)baz(\1<quux value>(.*))" where <quux value> is 5895ffd940aSRaphael Isemann /// the value captured for QUUX on the earlier line where it was defined, and 5905ffd940aSRaphael Isemann /// VariableDefs will map "bar" to the third parenthesis group which captures 5915ffd940aSRaphael Isemann /// the second definition of "bar". 5925ffd940aSRaphael Isemann /// 5935ffd940aSRaphael Isemann /// Note: uses std::map rather than StringMap to be able to get the key when 5945ffd940aSRaphael Isemann /// iterating over values. 5955ffd940aSRaphael Isemann std::map<StringRef, unsigned> VariableDefs; 5965ffd940aSRaphael Isemann 5975ffd940aSRaphael Isemann /// Structure representing the definition of a numeric variable in a pattern. 5985ffd940aSRaphael Isemann /// It holds the pointer to the class instance holding the value and matching 5995ffd940aSRaphael Isemann /// format of the numeric variable whose value is being defined and the 6005ffd940aSRaphael Isemann /// number of the parenthesis group in RegExStr to capture that value. 6015ffd940aSRaphael Isemann struct NumericVariableMatch { 6025ffd940aSRaphael Isemann /// Pointer to class instance holding the value and matching format of the 6035ffd940aSRaphael Isemann /// numeric variable being defined. 6045ffd940aSRaphael Isemann NumericVariable *DefinedNumericVariable; 6055ffd940aSRaphael Isemann 6065ffd940aSRaphael Isemann /// Number of the parenthesis group in RegExStr that captures the value of 6075ffd940aSRaphael Isemann /// this numeric variable definition. 6085ffd940aSRaphael Isemann unsigned CaptureParenGroup; 6095ffd940aSRaphael Isemann }; 6105ffd940aSRaphael Isemann 6115ffd940aSRaphael Isemann /// Holds the number of the parenthesis group in RegExStr and pointer to the 6125ffd940aSRaphael Isemann /// corresponding NumericVariable class instance of all numeric variable 6135ffd940aSRaphael Isemann /// definitions. Used to set the matched value of all those variables. 6145ffd940aSRaphael Isemann StringMap<NumericVariableMatch> NumericVariableDefs; 6155ffd940aSRaphael Isemann 6165ffd940aSRaphael Isemann /// Pointer to a class instance holding the global state shared by all 6175ffd940aSRaphael Isemann /// patterns: 6185ffd940aSRaphael Isemann /// - separate tables with the values of live string and numeric variables 6195ffd940aSRaphael Isemann /// respectively at the start of any given CHECK line; 6205ffd940aSRaphael Isemann /// - table holding whether a string variable has been defined at any given 6215ffd940aSRaphael Isemann /// point during the parsing phase. 6225ffd940aSRaphael Isemann FileCheckPatternContext *Context; 6235ffd940aSRaphael Isemann 6245ffd940aSRaphael Isemann Check::FileCheckType CheckTy; 6255ffd940aSRaphael Isemann 626595f1a6aSKazu Hirata /// Line number for this CHECK pattern or std::nullopt if it is an implicit 627595f1a6aSKazu Hirata /// pattern. Used to determine whether a variable definition is made on an 628595f1a6aSKazu Hirata /// earlier line to the one with this CHECK. 62994081642SFangrui Song std::optional<size_t> LineNumber; 6305ffd940aSRaphael Isemann 6315ffd940aSRaphael Isemann /// Ignore case while matching if set to true. 6325ffd940aSRaphael Isemann bool IgnoreCase = false; 6335ffd940aSRaphael Isemann 6345ffd940aSRaphael Isemann public: 6355ffd940aSRaphael Isemann Pattern(Check::FileCheckType Ty, FileCheckPatternContext *Context, 63694081642SFangrui Song std::optional<size_t> Line = std::nullopt) 6375ffd940aSRaphael Isemann : Context(Context), CheckTy(Ty), LineNumber(Line) {} 6385ffd940aSRaphael Isemann 6395ffd940aSRaphael Isemann /// \returns the location in source code. 6405ffd940aSRaphael Isemann SMLoc getLoc() const { return PatternLoc; } 6415ffd940aSRaphael Isemann 6425ffd940aSRaphael Isemann /// \returns the pointer to the global state for all patterns in this 6435ffd940aSRaphael Isemann /// FileCheck instance. 6445ffd940aSRaphael Isemann FileCheckPatternContext *getContext() const { return Context; } 6455ffd940aSRaphael Isemann 6465ffd940aSRaphael Isemann /// \returns whether \p C is a valid first character for a variable name. 6475ffd940aSRaphael Isemann static bool isValidVarNameStart(char C); 6485ffd940aSRaphael Isemann 6495ffd940aSRaphael Isemann /// Parsing information about a variable. 6505ffd940aSRaphael Isemann struct VariableProperties { 6515ffd940aSRaphael Isemann StringRef Name; 6525ffd940aSRaphael Isemann bool IsPseudo; 6535ffd940aSRaphael Isemann }; 6545ffd940aSRaphael Isemann 6555ffd940aSRaphael Isemann /// Parses the string at the start of \p Str for a variable name. \returns 6565ffd940aSRaphael Isemann /// a VariableProperties structure holding the variable name and whether it 6575ffd940aSRaphael Isemann /// is the name of a pseudo variable, or an error holding a diagnostic 6585ffd940aSRaphael Isemann /// against \p SM if parsing fail. If parsing was successful, also strips 6595ffd940aSRaphael Isemann /// \p Str from the variable name. 6605ffd940aSRaphael Isemann static Expected<VariableProperties> parseVariable(StringRef &Str, 6615ffd940aSRaphael Isemann const SourceMgr &SM); 6625ffd940aSRaphael Isemann /// Parses \p Expr for a numeric substitution block at line \p LineNumber, 6635ffd940aSRaphael Isemann /// or before input is parsed if \p LineNumber is None. Parameter 6645ffd940aSRaphael Isemann /// \p IsLegacyLineExpr indicates whether \p Expr should be a legacy @LINE 6655ffd940aSRaphael Isemann /// expression and \p Context points to the class instance holding the live 6665ffd940aSRaphael Isemann /// string and numeric variables. \returns a pointer to the class instance 6675ffd940aSRaphael Isemann /// representing the expression whose value must be substitued, or an error 6685ffd940aSRaphael Isemann /// holding a diagnostic against \p SM if parsing fails. If substitution was 6695ffd940aSRaphael Isemann /// successful, sets \p DefinedNumericVariable to point to the class 6705ffd940aSRaphael Isemann /// representing the numeric variable defined in this numeric substitution 671595f1a6aSKazu Hirata /// block, or std::nullopt if this block does not define any variable. 6725ffd940aSRaphael Isemann static Expected<std::unique_ptr<Expression>> parseNumericSubstitutionBlock( 67394081642SFangrui Song StringRef Expr, std::optional<NumericVariable *> &DefinedNumericVariable, 67494081642SFangrui Song bool IsLegacyLineExpr, std::optional<size_t> LineNumber, 6755ffd940aSRaphael Isemann FileCheckPatternContext *Context, const SourceMgr &SM); 6765ffd940aSRaphael Isemann /// Parses the pattern in \p PatternStr and initializes this Pattern instance 6775ffd940aSRaphael Isemann /// accordingly. 6785ffd940aSRaphael Isemann /// 6795ffd940aSRaphael Isemann /// \p Prefix provides which prefix is being matched, \p Req describes the 6805ffd940aSRaphael Isemann /// global options that influence the parsing such as whitespace 6815ffd940aSRaphael Isemann /// canonicalization, \p SM provides the SourceMgr used for error reports. 6825ffd940aSRaphael Isemann /// \returns true in case of an error, false otherwise. 6835ffd940aSRaphael Isemann bool parsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM, 6845ffd940aSRaphael Isemann const FileCheckRequest &Req); 685dd59c132SJoel E. Denny struct Match { 686dd59c132SJoel E. Denny size_t Pos; 687dd59c132SJoel E. Denny size_t Len; 688dd59c132SJoel E. Denny }; 689dd59c132SJoel E. Denny struct MatchResult { 69094081642SFangrui Song std::optional<Match> TheMatch; 691dd59c132SJoel E. Denny Error TheError; 692dd59c132SJoel E. Denny MatchResult(size_t MatchPos, size_t MatchLen, Error E) 693dd59c132SJoel E. Denny : TheMatch(Match{MatchPos, MatchLen}), TheError(std::move(E)) {} 694dd59c132SJoel E. Denny MatchResult(Match M, Error E) : TheMatch(M), TheError(std::move(E)) {} 695dd59c132SJoel E. Denny MatchResult(Error E) : TheError(std::move(E)) {} 696dd59c132SJoel E. Denny }; 697dd59c132SJoel E. Denny /// Matches the pattern string against the input buffer \p Buffer. 6985ffd940aSRaphael Isemann /// 699dd59c132SJoel E. Denny /// \returns either (1) an error resulting in no match or (2) a match possibly 700dd59c132SJoel E. Denny /// with an error encountered while processing the match. 7015ffd940aSRaphael Isemann /// 7025ffd940aSRaphael Isemann /// The GlobalVariableTable StringMap in the FileCheckPatternContext class 7035ffd940aSRaphael Isemann /// instance provides the current values of FileCheck string variables and is 7045ffd940aSRaphael Isemann /// updated if this match defines new values. Likewise, the 7055ffd940aSRaphael Isemann /// GlobalNumericVariableTable StringMap in the same class provides the 7065ffd940aSRaphael Isemann /// current values of FileCheck numeric variables and is updated if this 7075ffd940aSRaphael Isemann /// match defines new numeric values. 708dd59c132SJoel E. Denny MatchResult match(StringRef Buffer, const SourceMgr &SM) const; 709fd941036SThomas Preud'homme /// Prints the value of successful substitutions. 7105ffd940aSRaphael Isemann void printSubstitutions(const SourceMgr &SM, StringRef Buffer, 7115ffd940aSRaphael Isemann SMRange MatchRange, FileCheckDiag::MatchType MatchTy, 7125ffd940aSRaphael Isemann std::vector<FileCheckDiag> *Diags) const; 7135ffd940aSRaphael Isemann void printFuzzyMatch(const SourceMgr &SM, StringRef Buffer, 7145ffd940aSRaphael Isemann std::vector<FileCheckDiag> *Diags) const; 7155ffd940aSRaphael Isemann 7165ffd940aSRaphael Isemann bool hasVariable() const { 7175ffd940aSRaphael Isemann return !(Substitutions.empty() && VariableDefs.empty()); 7185ffd940aSRaphael Isemann } 7195ffd940aSRaphael Isemann void printVariableDefs(const SourceMgr &SM, FileCheckDiag::MatchType MatchTy, 7205ffd940aSRaphael Isemann std::vector<FileCheckDiag> *Diags) const; 7215ffd940aSRaphael Isemann 7225ffd940aSRaphael Isemann Check::FileCheckType getCheckTy() const { return CheckTy; } 7235ffd940aSRaphael Isemann 7245ffd940aSRaphael Isemann int getCount() const { return CheckTy.getCount(); } 7255ffd940aSRaphael Isemann 7265ffd940aSRaphael Isemann private: 7275ffd940aSRaphael Isemann bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM); 7285ffd940aSRaphael Isemann void AddBackrefToRegEx(unsigned BackrefNum); 7295ffd940aSRaphael Isemann /// Computes an arbitrary estimate for the quality of matching this pattern 7305ffd940aSRaphael Isemann /// at the start of \p Buffer; a distance of zero should correspond to a 7315ffd940aSRaphael Isemann /// perfect match. 7325ffd940aSRaphael Isemann unsigned computeMatchDistance(StringRef Buffer) const; 7335ffd940aSRaphael Isemann /// Finds the closing sequence of a regex variable usage or definition. 7345ffd940aSRaphael Isemann /// 7355ffd940aSRaphael Isemann /// \p Str has to point in the beginning of the definition (right after the 7365ffd940aSRaphael Isemann /// opening sequence). \p SM holds the SourceMgr used for error reporting. 7375ffd940aSRaphael Isemann /// \returns the offset of the closing sequence within Str, or npos if it 7385ffd940aSRaphael Isemann /// was not found. 7395ffd940aSRaphael Isemann static size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM); 7405ffd940aSRaphael Isemann 7415ffd940aSRaphael Isemann /// Parses \p Expr for the name of a numeric variable to be defined at line 7425ffd940aSRaphael Isemann /// \p LineNumber, or before input is parsed if \p LineNumber is None. 7435ffd940aSRaphael Isemann /// \returns a pointer to the class instance representing that variable, 7445ffd940aSRaphael Isemann /// creating it if needed, or an error holding a diagnostic against \p SM 7455ffd940aSRaphael Isemann /// should defining such a variable be invalid. 7465ffd940aSRaphael Isemann static Expected<NumericVariable *> parseNumericVariableDefinition( 7475ffd940aSRaphael Isemann StringRef &Expr, FileCheckPatternContext *Context, 74894081642SFangrui Song std::optional<size_t> LineNumber, ExpressionFormat ImplicitFormat, 7495ffd940aSRaphael Isemann const SourceMgr &SM); 7505ffd940aSRaphael Isemann /// Parses \p Name as a (pseudo if \p IsPseudo is true) numeric variable use 7515ffd940aSRaphael Isemann /// at line \p LineNumber, or before input is parsed if \p LineNumber is 7525ffd940aSRaphael Isemann /// None. Parameter \p Context points to the class instance holding the live 7535ffd940aSRaphael Isemann /// string and numeric variables. \returns the pointer to the class instance 7545ffd940aSRaphael Isemann /// representing that variable if successful, or an error holding a 7555ffd940aSRaphael Isemann /// diagnostic against \p SM otherwise. 7565ffd940aSRaphael Isemann static Expected<std::unique_ptr<NumericVariableUse>> parseNumericVariableUse( 75794081642SFangrui Song StringRef Name, bool IsPseudo, std::optional<size_t> LineNumber, 7585ffd940aSRaphael Isemann FileCheckPatternContext *Context, const SourceMgr &SM); 7595ffd940aSRaphael Isemann enum class AllowedOperand { LineVar, LegacyLiteral, Any }; 7605ffd940aSRaphael Isemann /// Parses \p Expr for use of a numeric operand at line \p LineNumber, or 7615ffd940aSRaphael Isemann /// before input is parsed if \p LineNumber is None. Accepts literal values, 7625ffd940aSRaphael Isemann /// numeric variables and function calls, depending on the value of \p AO. 7635ffd940aSRaphael Isemann /// \p MaybeInvalidConstraint indicates whether the text being parsed could 7645ffd940aSRaphael Isemann /// be an invalid constraint. \p Context points to the class instance holding 7655ffd940aSRaphael Isemann /// the live string and numeric variables. \returns the class representing 7665ffd940aSRaphael Isemann /// that operand in the AST of the expression or an error holding a 7675ffd940aSRaphael Isemann /// diagnostic against \p SM otherwise. If \p Expr starts with a "(" this 7685ffd940aSRaphael Isemann /// function will attempt to parse a parenthesized expression. 7695ffd940aSRaphael Isemann static Expected<std::unique_ptr<ExpressionAST>> 7705ffd940aSRaphael Isemann parseNumericOperand(StringRef &Expr, AllowedOperand AO, bool ConstraintParsed, 77194081642SFangrui Song std::optional<size_t> LineNumber, 7725ffd940aSRaphael Isemann FileCheckPatternContext *Context, const SourceMgr &SM); 7735ffd940aSRaphael Isemann /// Parses and updates \p RemainingExpr for a binary operation at line 7745ffd940aSRaphael Isemann /// \p LineNumber, or before input is parsed if \p LineNumber is None. The 7755ffd940aSRaphael Isemann /// left operand of this binary operation is given in \p LeftOp and \p Expr 7765ffd940aSRaphael Isemann /// holds the string for the full expression, including the left operand. 7775ffd940aSRaphael Isemann /// Parameter \p IsLegacyLineExpr indicates whether we are parsing a legacy 7785ffd940aSRaphael Isemann /// @LINE expression. Parameter \p Context points to the class instance 7795ffd940aSRaphael Isemann /// holding the live string and numeric variables. \returns the class 7805ffd940aSRaphael Isemann /// representing the binary operation in the AST of the expression, or an 7815ffd940aSRaphael Isemann /// error holding a diagnostic against \p SM otherwise. 7825ffd940aSRaphael Isemann static Expected<std::unique_ptr<ExpressionAST>> 7835ffd940aSRaphael Isemann parseBinop(StringRef Expr, StringRef &RemainingExpr, 7845ffd940aSRaphael Isemann std::unique_ptr<ExpressionAST> LeftOp, bool IsLegacyLineExpr, 78594081642SFangrui Song std::optional<size_t> LineNumber, FileCheckPatternContext *Context, 7865ffd940aSRaphael Isemann const SourceMgr &SM); 7875ffd940aSRaphael Isemann 7885ffd940aSRaphael Isemann /// Parses a parenthesized expression inside \p Expr at line \p LineNumber, or 7895ffd940aSRaphael Isemann /// before input is parsed if \p LineNumber is None. \p Expr must start with 7905ffd940aSRaphael Isemann /// a '('. Accepts both literal values and numeric variables. Parameter \p 7915ffd940aSRaphael Isemann /// Context points to the class instance holding the live string and numeric 7925ffd940aSRaphael Isemann /// variables. \returns the class representing that operand in the AST of the 7935ffd940aSRaphael Isemann /// expression or an error holding a diagnostic against \p SM otherwise. 7945ffd940aSRaphael Isemann static Expected<std::unique_ptr<ExpressionAST>> 79594081642SFangrui Song parseParenExpr(StringRef &Expr, std::optional<size_t> LineNumber, 7965ffd940aSRaphael Isemann FileCheckPatternContext *Context, const SourceMgr &SM); 7975ffd940aSRaphael Isemann 7985ffd940aSRaphael Isemann /// Parses \p Expr for an argument list belonging to a call to function \p 7995ffd940aSRaphael Isemann /// FuncName at line \p LineNumber, or before input is parsed if \p LineNumber 8005ffd940aSRaphael Isemann /// is None. Parameter \p FuncLoc is the source location used for diagnostics. 8015ffd940aSRaphael Isemann /// Parameter \p Context points to the class instance holding the live string 8025ffd940aSRaphael Isemann /// and numeric variables. \returns the class representing that call in the 8035ffd940aSRaphael Isemann /// AST of the expression or an error holding a diagnostic against \p SM 8045ffd940aSRaphael Isemann /// otherwise. 8055ffd940aSRaphael Isemann static Expected<std::unique_ptr<ExpressionAST>> 8065ffd940aSRaphael Isemann parseCallExpr(StringRef &Expr, StringRef FuncName, 80794081642SFangrui Song std::optional<size_t> LineNumber, 80894081642SFangrui Song FileCheckPatternContext *Context, const SourceMgr &SM); 8095ffd940aSRaphael Isemann }; 8105ffd940aSRaphael Isemann 8115ffd940aSRaphael Isemann //===----------------------------------------------------------------------===// 8125ffd940aSRaphael Isemann // Check Strings. 8135ffd940aSRaphael Isemann //===----------------------------------------------------------------------===// 8145ffd940aSRaphael Isemann 8155ffd940aSRaphael Isemann /// A check that we found in the input file. 8165ffd940aSRaphael Isemann struct FileCheckString { 8175ffd940aSRaphael Isemann /// The pattern to match. 8185ffd940aSRaphael Isemann Pattern Pat; 8195ffd940aSRaphael Isemann 8205ffd940aSRaphael Isemann /// Which prefix name this check matched. 8215ffd940aSRaphael Isemann StringRef Prefix; 8225ffd940aSRaphael Isemann 8235ffd940aSRaphael Isemann /// The location in the match file that the check string was specified. 8245ffd940aSRaphael Isemann SMLoc Loc; 8255ffd940aSRaphael Isemann 826497a8604SVinayak Dev /// Hold the information about the DAG/NOT strings in the program, which are 827497a8604SVinayak Dev /// not explicitly stored otherwise. This allows for better and more accurate 828497a8604SVinayak Dev /// diagnostic messages. 829497a8604SVinayak Dev struct DagNotPrefixInfo { 830497a8604SVinayak Dev Pattern DagNotPat; 831497a8604SVinayak Dev StringRef DagNotPrefix; 832497a8604SVinayak Dev 833497a8604SVinayak Dev DagNotPrefixInfo(const Pattern &P, StringRef S) 834497a8604SVinayak Dev : DagNotPat(P), DagNotPrefix(S) {} 835497a8604SVinayak Dev }; 836497a8604SVinayak Dev 837497a8604SVinayak Dev /// Hold the DAG/NOT strings occurring in the input file. 838497a8604SVinayak Dev std::vector<DagNotPrefixInfo> DagNotStrings; 8395ffd940aSRaphael Isemann 840*d3d605b7SJay Foad FileCheckString(Pattern &&P, StringRef S, SMLoc L, 841*d3d605b7SJay Foad std::vector<DagNotPrefixInfo> &&D) 842*d3d605b7SJay Foad : Pat(std::move(P)), Prefix(S), Loc(L), DagNotStrings(std::move(D)) {} 8435ffd940aSRaphael Isemann 8445ffd940aSRaphael Isemann /// Matches check string and its "not strings" and/or "dag strings". 8455ffd940aSRaphael Isemann size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode, 8465ffd940aSRaphael Isemann size_t &MatchLen, FileCheckRequest &Req, 8475ffd940aSRaphael Isemann std::vector<FileCheckDiag> *Diags) const; 8485ffd940aSRaphael Isemann 8495ffd940aSRaphael Isemann /// Verifies that there is a single line in the given \p Buffer. Errors are 8505ffd940aSRaphael Isemann /// reported against \p SM. 8515ffd940aSRaphael Isemann bool CheckNext(const SourceMgr &SM, StringRef Buffer) const; 8525ffd940aSRaphael Isemann /// Verifies that there is no newline in the given \p Buffer. Errors are 8535ffd940aSRaphael Isemann /// reported against \p SM. 8545ffd940aSRaphael Isemann bool CheckSame(const SourceMgr &SM, StringRef Buffer) const; 8555ffd940aSRaphael Isemann /// Verifies that none of the strings in \p NotStrings are found in the given 8565ffd940aSRaphael Isemann /// \p Buffer. Errors are reported against \p SM and diagnostics recorded in 8575ffd940aSRaphael Isemann /// \p Diags according to the verbosity level set in \p Req. 8585ffd940aSRaphael Isemann bool CheckNot(const SourceMgr &SM, StringRef Buffer, 859497a8604SVinayak Dev const std::vector<const DagNotPrefixInfo *> &NotStrings, 8605ffd940aSRaphael Isemann const FileCheckRequest &Req, 8615ffd940aSRaphael Isemann std::vector<FileCheckDiag> *Diags) const; 8625ffd940aSRaphael Isemann /// Matches "dag strings" and their mixed "not strings". 8635ffd940aSRaphael Isemann size_t CheckDag(const SourceMgr &SM, StringRef Buffer, 864497a8604SVinayak Dev std::vector<const DagNotPrefixInfo *> &NotStrings, 8655ffd940aSRaphael Isemann const FileCheckRequest &Req, 8665ffd940aSRaphael Isemann std::vector<FileCheckDiag> *Diags) const; 8675ffd940aSRaphael Isemann }; 8685ffd940aSRaphael Isemann 8695ffd940aSRaphael Isemann } // namespace llvm 8705ffd940aSRaphael Isemann 8715ffd940aSRaphael Isemann #endif 872