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 185ffd940aSRaphael Isemann #include "llvm/ADT/Optional.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> 255ffd940aSRaphael Isemann #include <string> 265ffd940aSRaphael Isemann #include <vector> 275ffd940aSRaphael Isemann 285ffd940aSRaphael Isemann namespace llvm { 295ffd940aSRaphael Isemann 305ffd940aSRaphael Isemann //===----------------------------------------------------------------------===// 315ffd940aSRaphael Isemann // Numeric substitution handling code. 325ffd940aSRaphael Isemann //===----------------------------------------------------------------------===// 335ffd940aSRaphael Isemann 345ffd940aSRaphael Isemann class ExpressionValue; 355ffd940aSRaphael Isemann 365ffd940aSRaphael Isemann /// Type representing the format an expression value should be textualized into 375ffd940aSRaphael Isemann /// for matching. Used to represent both explicit format specifiers as well as 385ffd940aSRaphael Isemann /// implicit format from using numeric variables. 395ffd940aSRaphael Isemann struct ExpressionFormat { 405ffd940aSRaphael Isemann enum class Kind { 415ffd940aSRaphael Isemann /// Denote absence of format. Used for implicit format of literals and 425ffd940aSRaphael Isemann /// empty expressions. 435ffd940aSRaphael Isemann NoFormat, 445ffd940aSRaphael Isemann /// Value is an unsigned integer and should be printed as a decimal number. 455ffd940aSRaphael Isemann Unsigned, 465ffd940aSRaphael Isemann /// Value is a signed integer and should be printed as a decimal number. 475ffd940aSRaphael Isemann Signed, 485ffd940aSRaphael Isemann /// Value should be printed as an uppercase hex number. 495ffd940aSRaphael Isemann HexUpper, 505ffd940aSRaphael Isemann /// Value should be printed as a lowercase hex number. 515ffd940aSRaphael Isemann HexLower 525ffd940aSRaphael Isemann }; 535ffd940aSRaphael Isemann 545ffd940aSRaphael Isemann private: 555ffd940aSRaphael Isemann Kind Value; 565ffd940aSRaphael Isemann unsigned Precision = 0; 57f9e2a62cSThomas Preud'homme /// printf-like "alternate form" selected. 58f9e2a62cSThomas Preud'homme bool AlternateForm = false; 595ffd940aSRaphael Isemann 605ffd940aSRaphael Isemann public: 615ffd940aSRaphael Isemann /// Evaluates a format to true if it can be used in a match. 625ffd940aSRaphael Isemann explicit operator bool() const { return Value != Kind::NoFormat; } 635ffd940aSRaphael Isemann 645ffd940aSRaphael Isemann /// Define format equality: formats are equal if neither is NoFormat and 655ffd940aSRaphael Isemann /// their kinds and precision are the same. 665ffd940aSRaphael Isemann bool operator==(const ExpressionFormat &Other) const { 675ffd940aSRaphael Isemann return Value != Kind::NoFormat && Value == Other.Value && 68f9e2a62cSThomas Preud'homme Precision == Other.Precision && AlternateForm == Other.AlternateForm; 695ffd940aSRaphael Isemann } 705ffd940aSRaphael Isemann 715ffd940aSRaphael Isemann bool operator!=(const ExpressionFormat &Other) const { 725ffd940aSRaphael Isemann return !(*this == Other); 735ffd940aSRaphael Isemann } 745ffd940aSRaphael Isemann 755ffd940aSRaphael Isemann bool operator==(Kind OtherValue) const { return Value == OtherValue; } 765ffd940aSRaphael Isemann 775ffd940aSRaphael Isemann bool operator!=(Kind OtherValue) const { return !(*this == OtherValue); } 785ffd940aSRaphael Isemann 795ffd940aSRaphael Isemann /// \returns the format specifier corresponding to this format as a string. 805ffd940aSRaphael Isemann StringRef toString() const; 815ffd940aSRaphael Isemann ExpressionFormatExpressionFormat825ffd940aSRaphael Isemann ExpressionFormat() : Value(Kind::NoFormat){}; ExpressionFormatExpressionFormat835ffd940aSRaphael Isemann explicit ExpressionFormat(Kind Value) : Value(Value), Precision(0){}; ExpressionFormatExpressionFormat845ffd940aSRaphael Isemann explicit ExpressionFormat(Kind Value, unsigned Precision) 855ffd940aSRaphael Isemann : Value(Value), Precision(Precision){}; ExpressionFormatExpressionFormat86f9e2a62cSThomas Preud'homme explicit ExpressionFormat(Kind Value, unsigned Precision, bool AlternateForm) 87f9e2a62cSThomas Preud'homme : Value(Value), Precision(Precision), AlternateForm(AlternateForm){}; 885ffd940aSRaphael Isemann 895ffd940aSRaphael Isemann /// \returns a wildcard regular expression string that matches any value in 905ffd940aSRaphael Isemann /// the format represented by this instance and no other value, or an error 915ffd940aSRaphael Isemann /// if the format is NoFormat. 925ffd940aSRaphael Isemann Expected<std::string> getWildcardRegex() const; 935ffd940aSRaphael Isemann 945ffd940aSRaphael Isemann /// \returns the string representation of \p Value in the format represented 955ffd940aSRaphael Isemann /// by this instance, or an error if conversion to this format failed or the 965ffd940aSRaphael Isemann /// format is NoFormat. 975ffd940aSRaphael Isemann Expected<std::string> getMatchingString(ExpressionValue Value) const; 985ffd940aSRaphael Isemann 995ffd940aSRaphael Isemann /// \returns the value corresponding to string representation \p StrVal 1005ffd940aSRaphael Isemann /// according to the matching format represented by this instance or an error 1015ffd940aSRaphael Isemann /// with diagnostic against \p SM if \p StrVal does not correspond to a valid 1025ffd940aSRaphael Isemann /// and representable value. 1035ffd940aSRaphael Isemann Expected<ExpressionValue> valueFromStringRepr(StringRef StrVal, 1045ffd940aSRaphael Isemann const SourceMgr &SM) const; 1055ffd940aSRaphael Isemann }; 1065ffd940aSRaphael Isemann 1075ffd940aSRaphael Isemann /// Class to represent an overflow error that might result when manipulating a 1085ffd940aSRaphael Isemann /// value. 1095ffd940aSRaphael Isemann class OverflowError : public ErrorInfo<OverflowError> { 1105ffd940aSRaphael Isemann public: 1115ffd940aSRaphael Isemann static char ID; 1125ffd940aSRaphael Isemann convertToErrorCode()1135ffd940aSRaphael Isemann std::error_code convertToErrorCode() const override { 1145ffd940aSRaphael Isemann return std::make_error_code(std::errc::value_too_large); 1155ffd940aSRaphael Isemann } 1165ffd940aSRaphael Isemann log(raw_ostream & OS)1175ffd940aSRaphael Isemann void log(raw_ostream &OS) const override { OS << "overflow error"; } 1185ffd940aSRaphael Isemann }; 1195ffd940aSRaphael Isemann 1205ffd940aSRaphael Isemann /// Class representing a numeric value. 1215ffd940aSRaphael Isemann class ExpressionValue { 1225ffd940aSRaphael Isemann private: 1235ffd940aSRaphael Isemann uint64_t Value; 1245ffd940aSRaphael Isemann bool Negative; 1255ffd940aSRaphael Isemann 1265ffd940aSRaphael Isemann public: 1275ffd940aSRaphael Isemann template <class T> ExpressionValue(T Val)1285ffd940aSRaphael Isemann explicit ExpressionValue(T Val) : Value(Val), Negative(Val < 0) {} 1295ffd940aSRaphael Isemann 1305ffd940aSRaphael Isemann bool operator==(const ExpressionValue &Other) const { 1315ffd940aSRaphael Isemann return Value == Other.Value && isNegative() == Other.isNegative(); 1325ffd940aSRaphael Isemann } 1335ffd940aSRaphael Isemann 1345ffd940aSRaphael Isemann bool operator!=(const ExpressionValue &Other) const { 1355ffd940aSRaphael Isemann return !(*this == Other); 1365ffd940aSRaphael Isemann } 1375ffd940aSRaphael Isemann 1385ffd940aSRaphael Isemann /// Returns true if value is signed and negative, false otherwise. isNegative()1395ffd940aSRaphael Isemann bool isNegative() const { 1405ffd940aSRaphael Isemann assert((Value != 0 || !Negative) && "Unexpected negative zero!"); 1415ffd940aSRaphael Isemann return Negative; 1425ffd940aSRaphael Isemann } 1435ffd940aSRaphael Isemann 1445ffd940aSRaphael Isemann /// \returns the value as a signed integer or an error if the value is out of 1455ffd940aSRaphael Isemann /// range. 1465ffd940aSRaphael Isemann Expected<int64_t> getSignedValue() const; 1475ffd940aSRaphael Isemann 1485ffd940aSRaphael Isemann /// \returns the value as an unsigned integer or an error if the value is out 1495ffd940aSRaphael Isemann /// of range. 1505ffd940aSRaphael Isemann Expected<uint64_t> getUnsignedValue() const; 1515ffd940aSRaphael Isemann 1525ffd940aSRaphael Isemann /// \returns an unsigned ExpressionValue instance whose value is the absolute 1535ffd940aSRaphael Isemann /// value to this object's value. 1545ffd940aSRaphael Isemann ExpressionValue getAbsolute() const; 1555ffd940aSRaphael Isemann }; 1565ffd940aSRaphael Isemann 1575ffd940aSRaphael Isemann /// Performs operation and \returns its result or an error in case of failure, 1585ffd940aSRaphael Isemann /// such as if an overflow occurs. 1595ffd940aSRaphael Isemann Expected<ExpressionValue> operator+(const ExpressionValue &Lhs, 1605ffd940aSRaphael Isemann const ExpressionValue &Rhs); 1615ffd940aSRaphael Isemann Expected<ExpressionValue> operator-(const ExpressionValue &Lhs, 1625ffd940aSRaphael Isemann const ExpressionValue &Rhs); 1635ffd940aSRaphael Isemann Expected<ExpressionValue> operator*(const ExpressionValue &Lhs, 1645ffd940aSRaphael Isemann const ExpressionValue &Rhs); 1655ffd940aSRaphael Isemann Expected<ExpressionValue> operator/(const ExpressionValue &Lhs, 1665ffd940aSRaphael Isemann const ExpressionValue &Rhs); 1675ffd940aSRaphael Isemann Expected<ExpressionValue> max(const ExpressionValue &Lhs, 1685ffd940aSRaphael Isemann const ExpressionValue &Rhs); 1695ffd940aSRaphael Isemann Expected<ExpressionValue> min(const ExpressionValue &Lhs, 1705ffd940aSRaphael Isemann const ExpressionValue &Rhs); 1715ffd940aSRaphael Isemann 1725ffd940aSRaphael Isemann /// Base class representing the AST of a given expression. 1735ffd940aSRaphael Isemann class ExpressionAST { 1745ffd940aSRaphael Isemann private: 1755ffd940aSRaphael Isemann StringRef ExpressionStr; 1765ffd940aSRaphael Isemann 1775ffd940aSRaphael Isemann public: ExpressionAST(StringRef ExpressionStr)1785ffd940aSRaphael Isemann ExpressionAST(StringRef ExpressionStr) : ExpressionStr(ExpressionStr) {} 1795ffd940aSRaphael Isemann 1805ffd940aSRaphael Isemann virtual ~ExpressionAST() = default; 1815ffd940aSRaphael Isemann getExpressionStr()1825ffd940aSRaphael Isemann StringRef getExpressionStr() const { return ExpressionStr; } 1835ffd940aSRaphael Isemann 1845ffd940aSRaphael Isemann /// Evaluates and \returns the value of the expression represented by this 1855ffd940aSRaphael Isemann /// AST or an error if evaluation fails. 1865ffd940aSRaphael Isemann virtual Expected<ExpressionValue> eval() const = 0; 1875ffd940aSRaphael Isemann 1885ffd940aSRaphael Isemann /// \returns either the implicit format of this AST, a diagnostic against 1895ffd940aSRaphael Isemann /// \p SM if implicit formats of the AST's components conflict, or NoFormat 1905ffd940aSRaphael Isemann /// if the AST has no implicit format (e.g. AST is made up of a single 1915ffd940aSRaphael Isemann /// literal). 1925ffd940aSRaphael Isemann virtual Expected<ExpressionFormat> getImplicitFormat(const SourceMgr & SM)1935ffd940aSRaphael Isemann getImplicitFormat(const SourceMgr &SM) const { 1945ffd940aSRaphael Isemann return ExpressionFormat(); 1955ffd940aSRaphael Isemann } 1965ffd940aSRaphael Isemann }; 1975ffd940aSRaphael Isemann 1985ffd940aSRaphael Isemann /// Class representing an unsigned literal in the AST of an expression. 1995ffd940aSRaphael Isemann class ExpressionLiteral : public ExpressionAST { 2005ffd940aSRaphael Isemann private: 2015ffd940aSRaphael Isemann /// Actual value of the literal. 2025ffd940aSRaphael Isemann ExpressionValue Value; 2035ffd940aSRaphael Isemann 2045ffd940aSRaphael Isemann public: 2055ffd940aSRaphael Isemann template <class T> ExpressionLiteral(StringRef ExpressionStr,T Val)2065ffd940aSRaphael Isemann explicit ExpressionLiteral(StringRef ExpressionStr, T Val) 2075ffd940aSRaphael Isemann : ExpressionAST(ExpressionStr), Value(Val) {} 2085ffd940aSRaphael Isemann 2095ffd940aSRaphael Isemann /// \returns the literal's value. eval()2105ffd940aSRaphael Isemann Expected<ExpressionValue> eval() const override { return Value; } 2115ffd940aSRaphael Isemann }; 2125ffd940aSRaphael Isemann 2135ffd940aSRaphael Isemann /// Class to represent an undefined variable error, which quotes that 2145ffd940aSRaphael Isemann /// variable's name when printed. 2155ffd940aSRaphael Isemann class UndefVarError : public ErrorInfo<UndefVarError> { 2165ffd940aSRaphael Isemann private: 2175ffd940aSRaphael Isemann StringRef VarName; 2185ffd940aSRaphael Isemann 2195ffd940aSRaphael Isemann public: 2205ffd940aSRaphael Isemann static char ID; 2215ffd940aSRaphael Isemann UndefVarError(StringRef VarName)2225ffd940aSRaphael Isemann UndefVarError(StringRef VarName) : VarName(VarName) {} 2235ffd940aSRaphael Isemann getVarName()2245ffd940aSRaphael Isemann StringRef getVarName() const { return VarName; } 2255ffd940aSRaphael Isemann convertToErrorCode()2265ffd940aSRaphael Isemann std::error_code convertToErrorCode() const override { 2275ffd940aSRaphael Isemann return inconvertibleErrorCode(); 2285ffd940aSRaphael Isemann } 2295ffd940aSRaphael Isemann 2305ffd940aSRaphael Isemann /// Print name of variable associated with this error. log(raw_ostream & OS)2315ffd940aSRaphael Isemann void log(raw_ostream &OS) const override { 232*fd941036SThomas Preud'homme OS << "undefined variable: " << VarName; 2335ffd940aSRaphael Isemann } 2345ffd940aSRaphael Isemann }; 2355ffd940aSRaphael Isemann 2365ffd940aSRaphael Isemann /// Class representing an expression and its matching format. 2375ffd940aSRaphael Isemann class Expression { 2385ffd940aSRaphael Isemann private: 2395ffd940aSRaphael Isemann /// Pointer to AST of the expression. 2405ffd940aSRaphael Isemann std::unique_ptr<ExpressionAST> AST; 2415ffd940aSRaphael Isemann 2425ffd940aSRaphael Isemann /// Format to use (e.g. hex upper case letters) when matching the value. 2435ffd940aSRaphael Isemann ExpressionFormat Format; 2445ffd940aSRaphael Isemann 2455ffd940aSRaphael Isemann public: 2465ffd940aSRaphael Isemann /// Generic constructor for an expression represented by the given \p AST and 2475ffd940aSRaphael Isemann /// whose matching format is \p Format. Expression(std::unique_ptr<ExpressionAST> AST,ExpressionFormat Format)2485ffd940aSRaphael Isemann Expression(std::unique_ptr<ExpressionAST> AST, ExpressionFormat Format) 2495ffd940aSRaphael Isemann : AST(std::move(AST)), Format(Format) {} 2505ffd940aSRaphael Isemann 2515ffd940aSRaphael Isemann /// \returns pointer to AST of the expression. Pointer is guaranteed to be 2525ffd940aSRaphael Isemann /// valid as long as this object is. getAST()2535ffd940aSRaphael Isemann ExpressionAST *getAST() const { return AST.get(); } 2545ffd940aSRaphael Isemann getFormat()2555ffd940aSRaphael Isemann ExpressionFormat getFormat() const { return Format; } 2565ffd940aSRaphael Isemann }; 2575ffd940aSRaphael Isemann 2585ffd940aSRaphael Isemann /// Class representing a numeric variable and its associated current value. 2595ffd940aSRaphael Isemann class NumericVariable { 2605ffd940aSRaphael Isemann private: 2615ffd940aSRaphael Isemann /// Name of the numeric variable. 2625ffd940aSRaphael Isemann StringRef Name; 2635ffd940aSRaphael Isemann 2645ffd940aSRaphael Isemann /// Format to use for expressions using this variable without an explicit 2655ffd940aSRaphael Isemann /// format. 2665ffd940aSRaphael Isemann ExpressionFormat ImplicitFormat; 2675ffd940aSRaphael Isemann 2685ffd940aSRaphael Isemann /// Value of numeric variable, if defined, or None otherwise. 2695ffd940aSRaphael Isemann Optional<ExpressionValue> Value; 2705ffd940aSRaphael Isemann 2715ffd940aSRaphael Isemann /// The input buffer's string from which Value was parsed, or None. See 2725ffd940aSRaphael Isemann /// comments on getStringValue for a discussion of the None case. 2735ffd940aSRaphael Isemann Optional<StringRef> StrValue; 2745ffd940aSRaphael Isemann 2755ffd940aSRaphael Isemann /// Line number where this variable is defined, or None if defined before 2765ffd940aSRaphael Isemann /// input is parsed. Used to determine whether a variable is defined on the 2775ffd940aSRaphael Isemann /// same line as a given use. 2785ffd940aSRaphael Isemann Optional<size_t> DefLineNumber; 2795ffd940aSRaphael Isemann 2805ffd940aSRaphael Isemann public: 2815ffd940aSRaphael Isemann /// Constructor for a variable \p Name with implicit format \p ImplicitFormat 2825ffd940aSRaphael Isemann /// defined at line \p DefLineNumber or defined before input is parsed if 2835ffd940aSRaphael Isemann /// \p DefLineNumber is None. 2845ffd940aSRaphael Isemann explicit NumericVariable(StringRef Name, ExpressionFormat ImplicitFormat, 2855ffd940aSRaphael Isemann Optional<size_t> DefLineNumber = None) Name(Name)2865ffd940aSRaphael Isemann : Name(Name), ImplicitFormat(ImplicitFormat), 2875ffd940aSRaphael Isemann DefLineNumber(DefLineNumber) {} 2885ffd940aSRaphael Isemann 2895ffd940aSRaphael Isemann /// \returns name of this numeric variable. getName()2905ffd940aSRaphael Isemann StringRef getName() const { return Name; } 2915ffd940aSRaphael Isemann 2925ffd940aSRaphael Isemann /// \returns implicit format of this numeric variable. getImplicitFormat()2935ffd940aSRaphael Isemann ExpressionFormat getImplicitFormat() const { return ImplicitFormat; } 2945ffd940aSRaphael Isemann 2955ffd940aSRaphael Isemann /// \returns this variable's value. getValue()2965ffd940aSRaphael Isemann Optional<ExpressionValue> getValue() const { return Value; } 2975ffd940aSRaphael Isemann 2985ffd940aSRaphael Isemann /// \returns the input buffer's string from which this variable's value was 2995ffd940aSRaphael Isemann /// parsed, or None if the value is not yet defined or was not parsed from the 3005ffd940aSRaphael Isemann /// input buffer. For example, the value of @LINE is not parsed from the 3015ffd940aSRaphael Isemann /// input buffer, and some numeric variables are parsed from the command 3025ffd940aSRaphael Isemann /// line instead. getStringValue()3035ffd940aSRaphael Isemann Optional<StringRef> getStringValue() const { return StrValue; } 3045ffd940aSRaphael Isemann 3055ffd940aSRaphael Isemann /// Sets value of this numeric variable to \p NewValue, and sets the input 3065ffd940aSRaphael Isemann /// buffer string from which it was parsed to \p NewStrValue. See comments on 3075ffd940aSRaphael Isemann /// getStringValue for a discussion of when the latter can be None. 3085ffd940aSRaphael Isemann void setValue(ExpressionValue NewValue, 3095ffd940aSRaphael Isemann Optional<StringRef> NewStrValue = None) { 3105ffd940aSRaphael Isemann Value = NewValue; 3115ffd940aSRaphael Isemann StrValue = NewStrValue; 3125ffd940aSRaphael Isemann } 3135ffd940aSRaphael Isemann 3145ffd940aSRaphael Isemann /// Clears value of this numeric variable, regardless of whether it is 3155ffd940aSRaphael Isemann /// currently defined or not. clearValue()3165ffd940aSRaphael Isemann void clearValue() { 3175ffd940aSRaphael Isemann Value = None; 3185ffd940aSRaphael Isemann StrValue = None; 3195ffd940aSRaphael Isemann } 3205ffd940aSRaphael Isemann 3215ffd940aSRaphael Isemann /// \returns the line number where this variable is defined, if any, or None 3225ffd940aSRaphael Isemann /// if defined before input is parsed. getDefLineNumber()3235ffd940aSRaphael Isemann Optional<size_t> getDefLineNumber() const { return DefLineNumber; } 3245ffd940aSRaphael Isemann }; 3255ffd940aSRaphael Isemann 3265ffd940aSRaphael Isemann /// Class representing the use of a numeric variable in the AST of an 3275ffd940aSRaphael Isemann /// expression. 3285ffd940aSRaphael Isemann class NumericVariableUse : public ExpressionAST { 3295ffd940aSRaphael Isemann private: 3305ffd940aSRaphael Isemann /// Pointer to the class instance for the variable this use is about. 3315ffd940aSRaphael Isemann NumericVariable *Variable; 3325ffd940aSRaphael Isemann 3335ffd940aSRaphael Isemann public: NumericVariableUse(StringRef Name,NumericVariable * Variable)3345ffd940aSRaphael Isemann NumericVariableUse(StringRef Name, NumericVariable *Variable) 3355ffd940aSRaphael Isemann : ExpressionAST(Name), Variable(Variable) {} 3365ffd940aSRaphael Isemann /// \returns the value of the variable referenced by this instance. 3375ffd940aSRaphael Isemann Expected<ExpressionValue> eval() const override; 3385ffd940aSRaphael Isemann 3395ffd940aSRaphael Isemann /// \returns implicit format of this numeric variable. 3405ffd940aSRaphael Isemann Expected<ExpressionFormat> getImplicitFormat(const SourceMgr & SM)3415ffd940aSRaphael Isemann getImplicitFormat(const SourceMgr &SM) const override { 3425ffd940aSRaphael Isemann return Variable->getImplicitFormat(); 3435ffd940aSRaphael Isemann } 3445ffd940aSRaphael Isemann }; 3455ffd940aSRaphael Isemann 3465ffd940aSRaphael Isemann /// Type of functions evaluating a given binary operation. 3475ffd940aSRaphael Isemann using binop_eval_t = Expected<ExpressionValue> (*)(const ExpressionValue &, 3485ffd940aSRaphael Isemann const ExpressionValue &); 3495ffd940aSRaphael Isemann 3505ffd940aSRaphael Isemann /// Class representing a single binary operation in the AST of an expression. 3515ffd940aSRaphael Isemann class BinaryOperation : public ExpressionAST { 3525ffd940aSRaphael Isemann private: 3535ffd940aSRaphael Isemann /// Left operand. 3545ffd940aSRaphael Isemann std::unique_ptr<ExpressionAST> LeftOperand; 3555ffd940aSRaphael Isemann 3565ffd940aSRaphael Isemann /// Right operand. 3575ffd940aSRaphael Isemann std::unique_ptr<ExpressionAST> RightOperand; 3585ffd940aSRaphael Isemann 3595ffd940aSRaphael Isemann /// Pointer to function that can evaluate this binary operation. 3605ffd940aSRaphael Isemann binop_eval_t EvalBinop; 3615ffd940aSRaphael Isemann 3625ffd940aSRaphael Isemann public: BinaryOperation(StringRef ExpressionStr,binop_eval_t EvalBinop,std::unique_ptr<ExpressionAST> LeftOp,std::unique_ptr<ExpressionAST> RightOp)3635ffd940aSRaphael Isemann BinaryOperation(StringRef ExpressionStr, binop_eval_t EvalBinop, 3645ffd940aSRaphael Isemann std::unique_ptr<ExpressionAST> LeftOp, 3655ffd940aSRaphael Isemann std::unique_ptr<ExpressionAST> RightOp) 3665ffd940aSRaphael Isemann : ExpressionAST(ExpressionStr), EvalBinop(EvalBinop) { 3675ffd940aSRaphael Isemann LeftOperand = std::move(LeftOp); 3685ffd940aSRaphael Isemann RightOperand = std::move(RightOp); 3695ffd940aSRaphael Isemann } 3705ffd940aSRaphael Isemann 3715ffd940aSRaphael Isemann /// Evaluates the value of the binary operation represented by this AST, 3725ffd940aSRaphael Isemann /// using EvalBinop on the result of recursively evaluating the operands. 3735ffd940aSRaphael Isemann /// \returns the expression value or an error if an undefined numeric 3745ffd940aSRaphael Isemann /// variable is used in one of the operands. 3755ffd940aSRaphael Isemann Expected<ExpressionValue> eval() const override; 3765ffd940aSRaphael Isemann 3775ffd940aSRaphael Isemann /// \returns the implicit format of this AST, if any, a diagnostic against 3785ffd940aSRaphael Isemann /// \p SM if the implicit formats of the AST's components conflict, or no 3795ffd940aSRaphael Isemann /// format if the AST has no implicit format (e.g. AST is made of a single 3805ffd940aSRaphael Isemann /// literal). 3815ffd940aSRaphael Isemann Expected<ExpressionFormat> 3825ffd940aSRaphael Isemann getImplicitFormat(const SourceMgr &SM) const override; 3835ffd940aSRaphael Isemann }; 3845ffd940aSRaphael Isemann 3855ffd940aSRaphael Isemann class FileCheckPatternContext; 3865ffd940aSRaphael Isemann 3875ffd940aSRaphael Isemann /// Class representing a substitution to perform in the RegExStr string. 3885ffd940aSRaphael Isemann class Substitution { 3895ffd940aSRaphael Isemann protected: 3905ffd940aSRaphael Isemann /// Pointer to a class instance holding, among other things, the table with 3915ffd940aSRaphael Isemann /// the values of live string variables at the start of any given CHECK line. 3925ffd940aSRaphael Isemann /// Used for substituting string variables with the text they were defined 3935ffd940aSRaphael Isemann /// as. Expressions are linked to the numeric variables they use at 3945ffd940aSRaphael Isemann /// parse time and directly access the value of the numeric variable to 3955ffd940aSRaphael Isemann /// evaluate their value. 3965ffd940aSRaphael Isemann FileCheckPatternContext *Context; 3975ffd940aSRaphael Isemann 3985ffd940aSRaphael Isemann /// The string that needs to be substituted for something else. For a 3995ffd940aSRaphael Isemann /// string variable this is its name, otherwise this is the whole expression. 4005ffd940aSRaphael Isemann StringRef FromStr; 4015ffd940aSRaphael Isemann 4025ffd940aSRaphael Isemann // Index in RegExStr of where to do the substitution. 4035ffd940aSRaphael Isemann size_t InsertIdx; 4045ffd940aSRaphael Isemann 4055ffd940aSRaphael Isemann public: Substitution(FileCheckPatternContext * Context,StringRef VarName,size_t InsertIdx)4065ffd940aSRaphael Isemann Substitution(FileCheckPatternContext *Context, StringRef VarName, 4075ffd940aSRaphael Isemann size_t InsertIdx) 4085ffd940aSRaphael Isemann : Context(Context), FromStr(VarName), InsertIdx(InsertIdx) {} 4095ffd940aSRaphael Isemann 4105ffd940aSRaphael Isemann virtual ~Substitution() = default; 4115ffd940aSRaphael Isemann 4125ffd940aSRaphael Isemann /// \returns the string to be substituted for something else. getFromString()4135ffd940aSRaphael Isemann StringRef getFromString() const { return FromStr; } 4145ffd940aSRaphael Isemann 4155ffd940aSRaphael Isemann /// \returns the index where the substitution is to be performed in RegExStr. getIndex()4165ffd940aSRaphael Isemann size_t getIndex() const { return InsertIdx; } 4175ffd940aSRaphael Isemann 4185ffd940aSRaphael Isemann /// \returns a string containing the result of the substitution represented 4195ffd940aSRaphael Isemann /// by this class instance or an error if substitution failed. 4205ffd940aSRaphael Isemann virtual Expected<std::string> getResult() const = 0; 4215ffd940aSRaphael Isemann }; 4225ffd940aSRaphael Isemann 4235ffd940aSRaphael Isemann class StringSubstitution : public Substitution { 4245ffd940aSRaphael Isemann public: StringSubstitution(FileCheckPatternContext * Context,StringRef VarName,size_t InsertIdx)4255ffd940aSRaphael Isemann StringSubstitution(FileCheckPatternContext *Context, StringRef VarName, 4265ffd940aSRaphael Isemann size_t InsertIdx) 4275ffd940aSRaphael Isemann : Substitution(Context, VarName, InsertIdx) {} 4285ffd940aSRaphael Isemann 4295ffd940aSRaphael Isemann /// \returns the text that the string variable in this substitution matched 4305ffd940aSRaphael Isemann /// when defined, or an error if the variable is undefined. 4315ffd940aSRaphael Isemann Expected<std::string> getResult() const override; 4325ffd940aSRaphael Isemann }; 4335ffd940aSRaphael Isemann 4345ffd940aSRaphael Isemann class NumericSubstitution : public Substitution { 4355ffd940aSRaphael Isemann private: 4365ffd940aSRaphael Isemann /// Pointer to the class representing the expression whose value is to be 4375ffd940aSRaphael Isemann /// substituted. 4385ffd940aSRaphael Isemann std::unique_ptr<Expression> ExpressionPointer; 4395ffd940aSRaphael Isemann 4405ffd940aSRaphael Isemann public: NumericSubstitution(FileCheckPatternContext * Context,StringRef ExpressionStr,std::unique_ptr<Expression> ExpressionPointer,size_t InsertIdx)4415ffd940aSRaphael Isemann NumericSubstitution(FileCheckPatternContext *Context, StringRef ExpressionStr, 4425ffd940aSRaphael Isemann std::unique_ptr<Expression> ExpressionPointer, 4435ffd940aSRaphael Isemann size_t InsertIdx) 4445ffd940aSRaphael Isemann : Substitution(Context, ExpressionStr, InsertIdx), 4455ffd940aSRaphael Isemann ExpressionPointer(std::move(ExpressionPointer)) {} 4465ffd940aSRaphael Isemann 4475ffd940aSRaphael Isemann /// \returns a string containing the result of evaluating the expression in 4485ffd940aSRaphael Isemann /// this substitution, or an error if evaluation failed. 4495ffd940aSRaphael Isemann Expected<std::string> getResult() const override; 4505ffd940aSRaphael Isemann }; 4515ffd940aSRaphael Isemann 4525ffd940aSRaphael Isemann //===----------------------------------------------------------------------===// 4535ffd940aSRaphael Isemann // Pattern handling code. 4545ffd940aSRaphael Isemann //===----------------------------------------------------------------------===// 4555ffd940aSRaphael Isemann 4565ffd940aSRaphael Isemann /// Class holding the Pattern global state, shared by all patterns: tables 4575ffd940aSRaphael Isemann /// holding values of variables and whether they are defined or not at any 4585ffd940aSRaphael Isemann /// given time in the matching process. 4595ffd940aSRaphael Isemann class FileCheckPatternContext { 4605ffd940aSRaphael Isemann friend class Pattern; 4615ffd940aSRaphael Isemann 4625ffd940aSRaphael Isemann private: 4635ffd940aSRaphael Isemann /// When matching a given pattern, this holds the value of all the string 4645ffd940aSRaphael Isemann /// variables defined in previous patterns. In a pattern, only the last 4655ffd940aSRaphael Isemann /// definition for a given variable is recorded in this table. 4665ffd940aSRaphael Isemann /// Back-references are used for uses after any the other definition. 4675ffd940aSRaphael Isemann StringMap<StringRef> GlobalVariableTable; 4685ffd940aSRaphael Isemann 4695ffd940aSRaphael Isemann /// Map of all string variables defined so far. Used at parse time to detect 4705ffd940aSRaphael Isemann /// a name conflict between a numeric variable and a string variable when 4715ffd940aSRaphael Isemann /// the former is defined on a later line than the latter. 4725ffd940aSRaphael Isemann StringMap<bool> DefinedVariableTable; 4735ffd940aSRaphael Isemann 4745ffd940aSRaphael Isemann /// When matching a given pattern, this holds the pointers to the classes 4755ffd940aSRaphael Isemann /// representing the numeric variables defined in previous patterns. When 4765ffd940aSRaphael Isemann /// matching a pattern all definitions for that pattern are recorded in the 4775ffd940aSRaphael Isemann /// NumericVariableDefs table in the Pattern instance of that pattern. 4785ffd940aSRaphael Isemann StringMap<NumericVariable *> GlobalNumericVariableTable; 4795ffd940aSRaphael Isemann 4805ffd940aSRaphael Isemann /// Pointer to the class instance representing the @LINE pseudo variable for 4815ffd940aSRaphael Isemann /// easily updating its value. 4825ffd940aSRaphael Isemann NumericVariable *LineVariable = nullptr; 4835ffd940aSRaphael Isemann 4845ffd940aSRaphael Isemann /// Vector holding pointers to all parsed numeric variables. Used to 4855ffd940aSRaphael Isemann /// automatically free them once they are guaranteed to no longer be used. 4865ffd940aSRaphael Isemann std::vector<std::unique_ptr<NumericVariable>> NumericVariables; 4875ffd940aSRaphael Isemann 4885ffd940aSRaphael Isemann /// Vector holding pointers to all parsed expressions. Used to automatically 4895ffd940aSRaphael Isemann /// free the expressions once they are guaranteed to no longer be used. 4905ffd940aSRaphael Isemann std::vector<std::unique_ptr<Expression>> Expressions; 4915ffd940aSRaphael Isemann 4925ffd940aSRaphael Isemann /// Vector holding pointers to all substitutions. Used to automatically free 4935ffd940aSRaphael Isemann /// them once they are guaranteed to no longer be used. 4945ffd940aSRaphael Isemann std::vector<std::unique_ptr<Substitution>> Substitutions; 4955ffd940aSRaphael Isemann 4965ffd940aSRaphael Isemann public: 4975ffd940aSRaphael Isemann /// \returns the value of string variable \p VarName or an error if no such 4985ffd940aSRaphael Isemann /// variable has been defined. 4995ffd940aSRaphael Isemann Expected<StringRef> getPatternVarValue(StringRef VarName); 5005ffd940aSRaphael Isemann 5015ffd940aSRaphael Isemann /// Defines string and numeric variables from definitions given on the 5025ffd940aSRaphael Isemann /// command line, passed as a vector of [#]VAR=VAL strings in 5035ffd940aSRaphael Isemann /// \p CmdlineDefines. \returns an error list containing diagnostics against 5045ffd940aSRaphael Isemann /// \p SM for all definition parsing failures, if any, or Success otherwise. 5055ffd940aSRaphael Isemann Error defineCmdlineVariables(ArrayRef<StringRef> CmdlineDefines, 5065ffd940aSRaphael Isemann SourceMgr &SM); 5075ffd940aSRaphael Isemann 5085ffd940aSRaphael Isemann /// Create @LINE pseudo variable. Value is set when pattern are being 5095ffd940aSRaphael Isemann /// matched. 5105ffd940aSRaphael Isemann void createLineVariable(); 5115ffd940aSRaphael Isemann 5125ffd940aSRaphael Isemann /// Undefines local variables (variables whose name does not start with a '$' 5135ffd940aSRaphael Isemann /// sign), i.e. removes them from GlobalVariableTable and from 5145ffd940aSRaphael Isemann /// GlobalNumericVariableTable and also clears the value of numeric 5155ffd940aSRaphael Isemann /// variables. 5165ffd940aSRaphael Isemann void clearLocalVars(); 5175ffd940aSRaphael Isemann 5185ffd940aSRaphael Isemann private: 5195ffd940aSRaphael Isemann /// Makes a new numeric variable and registers it for destruction when the 5205ffd940aSRaphael Isemann /// context is destroyed. 5215ffd940aSRaphael Isemann template <class... Types> NumericVariable *makeNumericVariable(Types... args); 5225ffd940aSRaphael Isemann 5235ffd940aSRaphael Isemann /// Makes a new string substitution and registers it for destruction when the 5245ffd940aSRaphael Isemann /// context is destroyed. 5255ffd940aSRaphael Isemann Substitution *makeStringSubstitution(StringRef VarName, size_t InsertIdx); 5265ffd940aSRaphael Isemann 5275ffd940aSRaphael Isemann /// Makes a new numeric substitution and registers it for destruction when 5285ffd940aSRaphael Isemann /// the context is destroyed. 5295ffd940aSRaphael Isemann Substitution *makeNumericSubstitution(StringRef ExpressionStr, 5305ffd940aSRaphael Isemann std::unique_ptr<Expression> Expression, 5315ffd940aSRaphael Isemann size_t InsertIdx); 5325ffd940aSRaphael Isemann }; 5335ffd940aSRaphael Isemann 5345ffd940aSRaphael Isemann /// Class to represent an error holding a diagnostic with location information 5355ffd940aSRaphael Isemann /// used when printing it. 5365ffd940aSRaphael Isemann class ErrorDiagnostic : public ErrorInfo<ErrorDiagnostic> { 5375ffd940aSRaphael Isemann private: 5385ffd940aSRaphael Isemann SMDiagnostic Diagnostic; 539dd59c132SJoel E. Denny SMRange Range; 5405ffd940aSRaphael Isemann 5415ffd940aSRaphael Isemann public: 5425ffd940aSRaphael Isemann static char ID; 5435ffd940aSRaphael Isemann ErrorDiagnostic(SMDiagnostic && Diag,SMRange Range)544dd59c132SJoel E. Denny ErrorDiagnostic(SMDiagnostic &&Diag, SMRange Range) 545dd59c132SJoel E. Denny : Diagnostic(Diag), Range(Range) {} 5465ffd940aSRaphael Isemann convertToErrorCode()5475ffd940aSRaphael Isemann std::error_code convertToErrorCode() const override { 5485ffd940aSRaphael Isemann return inconvertibleErrorCode(); 5495ffd940aSRaphael Isemann } 5505ffd940aSRaphael Isemann 5515ffd940aSRaphael Isemann /// Print diagnostic associated with this error when printing the error. log(raw_ostream & OS)5525ffd940aSRaphael Isemann void log(raw_ostream &OS) const override { Diagnostic.print(nullptr, OS); } 5535ffd940aSRaphael Isemann getMessage()554dd59c132SJoel E. Denny StringRef getMessage() const { return Diagnostic.getMessage(); } getRange()555dd59c132SJoel E. Denny SMRange getRange() const { return Range; } 556dd59c132SJoel E. Denny 557dd59c132SJoel E. Denny static Error get(const SourceMgr &SM, SMLoc Loc, const Twine &ErrMsg, 558dd59c132SJoel E. Denny SMRange Range = None) { 5595ffd940aSRaphael Isemann return make_error<ErrorDiagnostic>( 560dd59c132SJoel E. Denny SM.GetMessage(Loc, SourceMgr::DK_Error, ErrMsg), Range); 5615ffd940aSRaphael Isemann } 5625ffd940aSRaphael Isemann get(const SourceMgr & SM,StringRef Buffer,const Twine & ErrMsg)5635ffd940aSRaphael Isemann static Error get(const SourceMgr &SM, StringRef Buffer, const Twine &ErrMsg) { 564dd59c132SJoel E. Denny SMLoc Start = SMLoc::getFromPointer(Buffer.data()); 565dd59c132SJoel E. Denny SMLoc End = SMLoc::getFromPointer(Buffer.data() + Buffer.size()); 566dd59c132SJoel E. Denny return get(SM, Start, ErrMsg, SMRange(Start, End)); 5675ffd940aSRaphael Isemann } 5685ffd940aSRaphael Isemann }; 5695ffd940aSRaphael Isemann 5705ffd940aSRaphael Isemann class NotFoundError : public ErrorInfo<NotFoundError> { 5715ffd940aSRaphael Isemann public: 5725ffd940aSRaphael Isemann static char ID; 5735ffd940aSRaphael Isemann convertToErrorCode()5745ffd940aSRaphael Isemann std::error_code convertToErrorCode() const override { 5755ffd940aSRaphael Isemann return inconvertibleErrorCode(); 5765ffd940aSRaphael Isemann } 5775ffd940aSRaphael Isemann 5785ffd940aSRaphael Isemann /// Print diagnostic associated with this error when printing the error. log(raw_ostream & OS)5795ffd940aSRaphael Isemann void log(raw_ostream &OS) const override { 5805ffd940aSRaphael Isemann OS << "String not found in input"; 5815ffd940aSRaphael Isemann } 5825ffd940aSRaphael Isemann }; 5835ffd940aSRaphael Isemann 584dd59c132SJoel E. Denny /// An error that has already been reported. 585dd59c132SJoel E. Denny /// 586dd59c132SJoel E. Denny /// This class is designed to support a function whose callers may need to know 587dd59c132SJoel E. Denny /// whether the function encountered and reported an error but never need to 588dd59c132SJoel E. Denny /// know the nature of that error. For example, the function has a return type 589dd59c132SJoel E. Denny /// of \c Error and always returns either \c ErrorReported or \c ErrorSuccess. 590dd59c132SJoel E. Denny /// That interface is similar to that of a function returning bool to indicate 591dd59c132SJoel E. Denny /// an error except, in the former case, (1) there is no confusion over polarity 592dd59c132SJoel E. Denny /// and (2) the caller must either check the result or explicitly ignore it with 593dd59c132SJoel E. Denny /// a call like \c consumeError. 594dd59c132SJoel E. Denny class ErrorReported final : public ErrorInfo<ErrorReported> { 595dd59c132SJoel E. Denny public: 596dd59c132SJoel E. Denny static char ID; 597dd59c132SJoel E. Denny convertToErrorCode()598dd59c132SJoel E. Denny std::error_code convertToErrorCode() const override { 599dd59c132SJoel E. Denny return inconvertibleErrorCode(); 600dd59c132SJoel E. Denny } 601dd59c132SJoel E. Denny 602dd59c132SJoel E. Denny /// Print diagnostic associated with this error when printing the error. log(raw_ostream & OS)603dd59c132SJoel E. Denny void log(raw_ostream &OS) const override { 604dd59c132SJoel E. Denny OS << "error previously reported"; 605dd59c132SJoel E. Denny } 606dd59c132SJoel E. Denny reportedOrSuccess(bool HasErrorReported)607dd59c132SJoel E. Denny static inline Error reportedOrSuccess(bool HasErrorReported) { 608dd59c132SJoel E. Denny if (HasErrorReported) 609dd59c132SJoel E. Denny return make_error<ErrorReported>(); 610dd59c132SJoel E. Denny return Error::success(); 611dd59c132SJoel E. Denny } 612dd59c132SJoel E. Denny }; 613dd59c132SJoel E. Denny 6145ffd940aSRaphael Isemann class Pattern { 6155ffd940aSRaphael Isemann SMLoc PatternLoc; 6165ffd940aSRaphael Isemann 6175ffd940aSRaphael Isemann /// A fixed string to match as the pattern or empty if this pattern requires 6185ffd940aSRaphael Isemann /// a regex match. 6195ffd940aSRaphael Isemann StringRef FixedStr; 6205ffd940aSRaphael Isemann 6215ffd940aSRaphael Isemann /// A regex string to match as the pattern or empty if this pattern requires 6225ffd940aSRaphael Isemann /// a fixed string to match. 6235ffd940aSRaphael Isemann std::string RegExStr; 6245ffd940aSRaphael Isemann 6255ffd940aSRaphael Isemann /// Entries in this vector represent a substitution of a string variable or 6265ffd940aSRaphael Isemann /// an expression in the RegExStr regex at match time. For example, in the 6275ffd940aSRaphael Isemann /// case of a CHECK directive with the pattern "foo[[bar]]baz[[#N+1]]", 6285ffd940aSRaphael Isemann /// RegExStr will contain "foobaz" and we'll get two entries in this vector 6295ffd940aSRaphael Isemann /// that tells us to insert the value of string variable "bar" at offset 3 6305ffd940aSRaphael Isemann /// and the value of expression "N+1" at offset 6. 6315ffd940aSRaphael Isemann std::vector<Substitution *> Substitutions; 6325ffd940aSRaphael Isemann 6335ffd940aSRaphael Isemann /// Maps names of string variables defined in a pattern to the number of 6345ffd940aSRaphael Isemann /// their parenthesis group in RegExStr capturing their last definition. 6355ffd940aSRaphael Isemann /// 6365ffd940aSRaphael Isemann /// E.g. for the pattern "foo[[bar:.*]]baz([[bar]][[QUUX]][[bar:.*]])", 6375ffd940aSRaphael Isemann /// RegExStr will be "foo(.*)baz(\1<quux value>(.*))" where <quux value> is 6385ffd940aSRaphael Isemann /// the value captured for QUUX on the earlier line where it was defined, and 6395ffd940aSRaphael Isemann /// VariableDefs will map "bar" to the third parenthesis group which captures 6405ffd940aSRaphael Isemann /// the second definition of "bar". 6415ffd940aSRaphael Isemann /// 6425ffd940aSRaphael Isemann /// Note: uses std::map rather than StringMap to be able to get the key when 6435ffd940aSRaphael Isemann /// iterating over values. 6445ffd940aSRaphael Isemann std::map<StringRef, unsigned> VariableDefs; 6455ffd940aSRaphael Isemann 6465ffd940aSRaphael Isemann /// Structure representing the definition of a numeric variable in a pattern. 6475ffd940aSRaphael Isemann /// It holds the pointer to the class instance holding the value and matching 6485ffd940aSRaphael Isemann /// format of the numeric variable whose value is being defined and the 6495ffd940aSRaphael Isemann /// number of the parenthesis group in RegExStr to capture that value. 6505ffd940aSRaphael Isemann struct NumericVariableMatch { 6515ffd940aSRaphael Isemann /// Pointer to class instance holding the value and matching format of the 6525ffd940aSRaphael Isemann /// numeric variable being defined. 6535ffd940aSRaphael Isemann NumericVariable *DefinedNumericVariable; 6545ffd940aSRaphael Isemann 6555ffd940aSRaphael Isemann /// Number of the parenthesis group in RegExStr that captures the value of 6565ffd940aSRaphael Isemann /// this numeric variable definition. 6575ffd940aSRaphael Isemann unsigned CaptureParenGroup; 6585ffd940aSRaphael Isemann }; 6595ffd940aSRaphael Isemann 6605ffd940aSRaphael Isemann /// Holds the number of the parenthesis group in RegExStr and pointer to the 6615ffd940aSRaphael Isemann /// corresponding NumericVariable class instance of all numeric variable 6625ffd940aSRaphael Isemann /// definitions. Used to set the matched value of all those variables. 6635ffd940aSRaphael Isemann StringMap<NumericVariableMatch> NumericVariableDefs; 6645ffd940aSRaphael Isemann 6655ffd940aSRaphael Isemann /// Pointer to a class instance holding the global state shared by all 6665ffd940aSRaphael Isemann /// patterns: 6675ffd940aSRaphael Isemann /// - separate tables with the values of live string and numeric variables 6685ffd940aSRaphael Isemann /// respectively at the start of any given CHECK line; 6695ffd940aSRaphael Isemann /// - table holding whether a string variable has been defined at any given 6705ffd940aSRaphael Isemann /// point during the parsing phase. 6715ffd940aSRaphael Isemann FileCheckPatternContext *Context; 6725ffd940aSRaphael Isemann 6735ffd940aSRaphael Isemann Check::FileCheckType CheckTy; 6745ffd940aSRaphael Isemann 6755ffd940aSRaphael Isemann /// Line number for this CHECK pattern or None if it is an implicit pattern. 6765ffd940aSRaphael Isemann /// Used to determine whether a variable definition is made on an earlier 6775ffd940aSRaphael Isemann /// line to the one with this CHECK. 6785ffd940aSRaphael Isemann Optional<size_t> LineNumber; 6795ffd940aSRaphael Isemann 6805ffd940aSRaphael Isemann /// Ignore case while matching if set to true. 6815ffd940aSRaphael Isemann bool IgnoreCase = false; 6825ffd940aSRaphael Isemann 6835ffd940aSRaphael Isemann public: 6845ffd940aSRaphael Isemann Pattern(Check::FileCheckType Ty, FileCheckPatternContext *Context, 6855ffd940aSRaphael Isemann Optional<size_t> Line = None) Context(Context)6865ffd940aSRaphael Isemann : Context(Context), CheckTy(Ty), LineNumber(Line) {} 6875ffd940aSRaphael Isemann 6885ffd940aSRaphael Isemann /// \returns the location in source code. getLoc()6895ffd940aSRaphael Isemann SMLoc getLoc() const { return PatternLoc; } 6905ffd940aSRaphael Isemann 6915ffd940aSRaphael Isemann /// \returns the pointer to the global state for all patterns in this 6925ffd940aSRaphael Isemann /// FileCheck instance. getContext()6935ffd940aSRaphael Isemann FileCheckPatternContext *getContext() const { return Context; } 6945ffd940aSRaphael Isemann 6955ffd940aSRaphael Isemann /// \returns whether \p C is a valid first character for a variable name. 6965ffd940aSRaphael Isemann static bool isValidVarNameStart(char C); 6975ffd940aSRaphael Isemann 6985ffd940aSRaphael Isemann /// Parsing information about a variable. 6995ffd940aSRaphael Isemann struct VariableProperties { 7005ffd940aSRaphael Isemann StringRef Name; 7015ffd940aSRaphael Isemann bool IsPseudo; 7025ffd940aSRaphael Isemann }; 7035ffd940aSRaphael Isemann 7045ffd940aSRaphael Isemann /// Parses the string at the start of \p Str for a variable name. \returns 7055ffd940aSRaphael Isemann /// a VariableProperties structure holding the variable name and whether it 7065ffd940aSRaphael Isemann /// is the name of a pseudo variable, or an error holding a diagnostic 7075ffd940aSRaphael Isemann /// against \p SM if parsing fail. If parsing was successful, also strips 7085ffd940aSRaphael Isemann /// \p Str from the variable name. 7095ffd940aSRaphael Isemann static Expected<VariableProperties> parseVariable(StringRef &Str, 7105ffd940aSRaphael Isemann const SourceMgr &SM); 7115ffd940aSRaphael Isemann /// Parses \p Expr for a numeric substitution block at line \p LineNumber, 7125ffd940aSRaphael Isemann /// or before input is parsed if \p LineNumber is None. Parameter 7135ffd940aSRaphael Isemann /// \p IsLegacyLineExpr indicates whether \p Expr should be a legacy @LINE 7145ffd940aSRaphael Isemann /// expression and \p Context points to the class instance holding the live 7155ffd940aSRaphael Isemann /// string and numeric variables. \returns a pointer to the class instance 7165ffd940aSRaphael Isemann /// representing the expression whose value must be substitued, or an error 7175ffd940aSRaphael Isemann /// holding a diagnostic against \p SM if parsing fails. If substitution was 7185ffd940aSRaphael Isemann /// successful, sets \p DefinedNumericVariable to point to the class 7195ffd940aSRaphael Isemann /// representing the numeric variable defined in this numeric substitution 7205ffd940aSRaphael Isemann /// block, or None if this block does not define any variable. 7215ffd940aSRaphael Isemann static Expected<std::unique_ptr<Expression>> parseNumericSubstitutionBlock( 7225ffd940aSRaphael Isemann StringRef Expr, Optional<NumericVariable *> &DefinedNumericVariable, 7235ffd940aSRaphael Isemann bool IsLegacyLineExpr, Optional<size_t> LineNumber, 7245ffd940aSRaphael Isemann FileCheckPatternContext *Context, const SourceMgr &SM); 7255ffd940aSRaphael Isemann /// Parses the pattern in \p PatternStr and initializes this Pattern instance 7265ffd940aSRaphael Isemann /// accordingly. 7275ffd940aSRaphael Isemann /// 7285ffd940aSRaphael Isemann /// \p Prefix provides which prefix is being matched, \p Req describes the 7295ffd940aSRaphael Isemann /// global options that influence the parsing such as whitespace 7305ffd940aSRaphael Isemann /// canonicalization, \p SM provides the SourceMgr used for error reports. 7315ffd940aSRaphael Isemann /// \returns true in case of an error, false otherwise. 7325ffd940aSRaphael Isemann bool parsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM, 7335ffd940aSRaphael Isemann const FileCheckRequest &Req); 734dd59c132SJoel E. Denny struct Match { 735dd59c132SJoel E. Denny size_t Pos; 736dd59c132SJoel E. Denny size_t Len; 737dd59c132SJoel E. Denny }; 738dd59c132SJoel E. Denny struct MatchResult { 739dd59c132SJoel E. Denny Optional<Match> TheMatch; 740dd59c132SJoel E. Denny Error TheError; MatchResultMatchResult741dd59c132SJoel E. Denny MatchResult(size_t MatchPos, size_t MatchLen, Error E) 742dd59c132SJoel E. Denny : TheMatch(Match{MatchPos, MatchLen}), TheError(std::move(E)) {} MatchResultMatchResult743dd59c132SJoel E. Denny MatchResult(Match M, Error E) : TheMatch(M), TheError(std::move(E)) {} MatchResultMatchResult744dd59c132SJoel E. Denny MatchResult(Error E) : TheError(std::move(E)) {} 745dd59c132SJoel E. Denny }; 746dd59c132SJoel E. Denny /// Matches the pattern string against the input buffer \p Buffer. 7475ffd940aSRaphael Isemann /// 748dd59c132SJoel E. Denny /// \returns either (1) an error resulting in no match or (2) a match possibly 749dd59c132SJoel E. Denny /// with an error encountered while processing the match. 7505ffd940aSRaphael Isemann /// 7515ffd940aSRaphael Isemann /// The GlobalVariableTable StringMap in the FileCheckPatternContext class 7525ffd940aSRaphael Isemann /// instance provides the current values of FileCheck string variables and is 7535ffd940aSRaphael Isemann /// updated if this match defines new values. Likewise, the 7545ffd940aSRaphael Isemann /// GlobalNumericVariableTable StringMap in the same class provides the 7555ffd940aSRaphael Isemann /// current values of FileCheck numeric variables and is updated if this 7565ffd940aSRaphael Isemann /// match defines new numeric values. 757dd59c132SJoel E. Denny MatchResult match(StringRef Buffer, const SourceMgr &SM) const; 758*fd941036SThomas Preud'homme /// Prints the value of successful substitutions. 7595ffd940aSRaphael Isemann void printSubstitutions(const SourceMgr &SM, StringRef Buffer, 7605ffd940aSRaphael Isemann SMRange MatchRange, FileCheckDiag::MatchType MatchTy, 7615ffd940aSRaphael Isemann std::vector<FileCheckDiag> *Diags) const; 7625ffd940aSRaphael Isemann void printFuzzyMatch(const SourceMgr &SM, StringRef Buffer, 7635ffd940aSRaphael Isemann std::vector<FileCheckDiag> *Diags) const; 7645ffd940aSRaphael Isemann hasVariable()7655ffd940aSRaphael Isemann bool hasVariable() const { 7665ffd940aSRaphael Isemann return !(Substitutions.empty() && VariableDefs.empty()); 7675ffd940aSRaphael Isemann } 7685ffd940aSRaphael Isemann void printVariableDefs(const SourceMgr &SM, FileCheckDiag::MatchType MatchTy, 7695ffd940aSRaphael Isemann std::vector<FileCheckDiag> *Diags) const; 7705ffd940aSRaphael Isemann getCheckTy()7715ffd940aSRaphael Isemann Check::FileCheckType getCheckTy() const { return CheckTy; } 7725ffd940aSRaphael Isemann getCount()7735ffd940aSRaphael Isemann int getCount() const { return CheckTy.getCount(); } 7745ffd940aSRaphael Isemann 7755ffd940aSRaphael Isemann private: 7765ffd940aSRaphael Isemann bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM); 7775ffd940aSRaphael Isemann void AddBackrefToRegEx(unsigned BackrefNum); 7785ffd940aSRaphael Isemann /// Computes an arbitrary estimate for the quality of matching this pattern 7795ffd940aSRaphael Isemann /// at the start of \p Buffer; a distance of zero should correspond to a 7805ffd940aSRaphael Isemann /// perfect match. 7815ffd940aSRaphael Isemann unsigned computeMatchDistance(StringRef Buffer) const; 7825ffd940aSRaphael Isemann /// Finds the closing sequence of a regex variable usage or definition. 7835ffd940aSRaphael Isemann /// 7845ffd940aSRaphael Isemann /// \p Str has to point in the beginning of the definition (right after the 7855ffd940aSRaphael Isemann /// opening sequence). \p SM holds the SourceMgr used for error reporting. 7865ffd940aSRaphael Isemann /// \returns the offset of the closing sequence within Str, or npos if it 7875ffd940aSRaphael Isemann /// was not found. 7885ffd940aSRaphael Isemann static size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM); 7895ffd940aSRaphael Isemann 7905ffd940aSRaphael Isemann /// Parses \p Expr for the name of a numeric variable to be defined at line 7915ffd940aSRaphael Isemann /// \p LineNumber, or before input is parsed if \p LineNumber is None. 7925ffd940aSRaphael Isemann /// \returns a pointer to the class instance representing that variable, 7935ffd940aSRaphael Isemann /// creating it if needed, or an error holding a diagnostic against \p SM 7945ffd940aSRaphael Isemann /// should defining such a variable be invalid. 7955ffd940aSRaphael Isemann static Expected<NumericVariable *> parseNumericVariableDefinition( 7965ffd940aSRaphael Isemann StringRef &Expr, FileCheckPatternContext *Context, 7975ffd940aSRaphael Isemann Optional<size_t> LineNumber, ExpressionFormat ImplicitFormat, 7985ffd940aSRaphael Isemann const SourceMgr &SM); 7995ffd940aSRaphael Isemann /// Parses \p Name as a (pseudo if \p IsPseudo is true) numeric variable use 8005ffd940aSRaphael Isemann /// at line \p LineNumber, or before input is parsed if \p LineNumber is 8015ffd940aSRaphael Isemann /// None. Parameter \p Context points to the class instance holding the live 8025ffd940aSRaphael Isemann /// string and numeric variables. \returns the pointer to the class instance 8035ffd940aSRaphael Isemann /// representing that variable if successful, or an error holding a 8045ffd940aSRaphael Isemann /// diagnostic against \p SM otherwise. 8055ffd940aSRaphael Isemann static Expected<std::unique_ptr<NumericVariableUse>> parseNumericVariableUse( 8065ffd940aSRaphael Isemann StringRef Name, bool IsPseudo, Optional<size_t> LineNumber, 8075ffd940aSRaphael Isemann FileCheckPatternContext *Context, const SourceMgr &SM); 8085ffd940aSRaphael Isemann enum class AllowedOperand { LineVar, LegacyLiteral, Any }; 8095ffd940aSRaphael Isemann /// Parses \p Expr for use of a numeric operand at line \p LineNumber, or 8105ffd940aSRaphael Isemann /// before input is parsed if \p LineNumber is None. Accepts literal values, 8115ffd940aSRaphael Isemann /// numeric variables and function calls, depending on the value of \p AO. 8125ffd940aSRaphael Isemann /// \p MaybeInvalidConstraint indicates whether the text being parsed could 8135ffd940aSRaphael Isemann /// be an invalid constraint. \p Context points to the class instance holding 8145ffd940aSRaphael Isemann /// the live string and numeric variables. \returns the class representing 8155ffd940aSRaphael Isemann /// that operand in the AST of the expression or an error holding a 8165ffd940aSRaphael Isemann /// diagnostic against \p SM otherwise. If \p Expr starts with a "(" this 8175ffd940aSRaphael Isemann /// function will attempt to parse a parenthesized expression. 8185ffd940aSRaphael Isemann static Expected<std::unique_ptr<ExpressionAST>> 8195ffd940aSRaphael Isemann parseNumericOperand(StringRef &Expr, AllowedOperand AO, bool ConstraintParsed, 8205ffd940aSRaphael Isemann Optional<size_t> LineNumber, 8215ffd940aSRaphael Isemann FileCheckPatternContext *Context, const SourceMgr &SM); 8225ffd940aSRaphael Isemann /// Parses and updates \p RemainingExpr for a binary operation at line 8235ffd940aSRaphael Isemann /// \p LineNumber, or before input is parsed if \p LineNumber is None. The 8245ffd940aSRaphael Isemann /// left operand of this binary operation is given in \p LeftOp and \p Expr 8255ffd940aSRaphael Isemann /// holds the string for the full expression, including the left operand. 8265ffd940aSRaphael Isemann /// Parameter \p IsLegacyLineExpr indicates whether we are parsing a legacy 8275ffd940aSRaphael Isemann /// @LINE expression. Parameter \p Context points to the class instance 8285ffd940aSRaphael Isemann /// holding the live string and numeric variables. \returns the class 8295ffd940aSRaphael Isemann /// representing the binary operation in the AST of the expression, or an 8305ffd940aSRaphael Isemann /// error holding a diagnostic against \p SM otherwise. 8315ffd940aSRaphael Isemann static Expected<std::unique_ptr<ExpressionAST>> 8325ffd940aSRaphael Isemann parseBinop(StringRef Expr, StringRef &RemainingExpr, 8335ffd940aSRaphael Isemann std::unique_ptr<ExpressionAST> LeftOp, bool IsLegacyLineExpr, 8345ffd940aSRaphael Isemann Optional<size_t> LineNumber, FileCheckPatternContext *Context, 8355ffd940aSRaphael Isemann const SourceMgr &SM); 8365ffd940aSRaphael Isemann 8375ffd940aSRaphael Isemann /// Parses a parenthesized expression inside \p Expr at line \p LineNumber, or 8385ffd940aSRaphael Isemann /// before input is parsed if \p LineNumber is None. \p Expr must start with 8395ffd940aSRaphael Isemann /// a '('. Accepts both literal values and numeric variables. Parameter \p 8405ffd940aSRaphael Isemann /// Context points to the class instance holding the live string and numeric 8415ffd940aSRaphael Isemann /// variables. \returns the class representing that operand in the AST of the 8425ffd940aSRaphael Isemann /// expression or an error holding a diagnostic against \p SM otherwise. 8435ffd940aSRaphael Isemann static Expected<std::unique_ptr<ExpressionAST>> 8445ffd940aSRaphael Isemann parseParenExpr(StringRef &Expr, Optional<size_t> LineNumber, 8455ffd940aSRaphael Isemann FileCheckPatternContext *Context, const SourceMgr &SM); 8465ffd940aSRaphael Isemann 8475ffd940aSRaphael Isemann /// Parses \p Expr for an argument list belonging to a call to function \p 8485ffd940aSRaphael Isemann /// FuncName at line \p LineNumber, or before input is parsed if \p LineNumber 8495ffd940aSRaphael Isemann /// is None. Parameter \p FuncLoc is the source location used for diagnostics. 8505ffd940aSRaphael Isemann /// Parameter \p Context points to the class instance holding the live string 8515ffd940aSRaphael Isemann /// and numeric variables. \returns the class representing that call in the 8525ffd940aSRaphael Isemann /// AST of the expression or an error holding a diagnostic against \p SM 8535ffd940aSRaphael Isemann /// otherwise. 8545ffd940aSRaphael Isemann static Expected<std::unique_ptr<ExpressionAST>> 8555ffd940aSRaphael Isemann parseCallExpr(StringRef &Expr, StringRef FuncName, 8565ffd940aSRaphael Isemann Optional<size_t> LineNumber, FileCheckPatternContext *Context, 8575ffd940aSRaphael Isemann const SourceMgr &SM); 8585ffd940aSRaphael Isemann }; 8595ffd940aSRaphael Isemann 8605ffd940aSRaphael Isemann //===----------------------------------------------------------------------===// 8615ffd940aSRaphael Isemann // Check Strings. 8625ffd940aSRaphael Isemann //===----------------------------------------------------------------------===// 8635ffd940aSRaphael Isemann 8645ffd940aSRaphael Isemann /// A check that we found in the input file. 8655ffd940aSRaphael Isemann struct FileCheckString { 8665ffd940aSRaphael Isemann /// The pattern to match. 8675ffd940aSRaphael Isemann Pattern Pat; 8685ffd940aSRaphael Isemann 8695ffd940aSRaphael Isemann /// Which prefix name this check matched. 8705ffd940aSRaphael Isemann StringRef Prefix; 8715ffd940aSRaphael Isemann 8725ffd940aSRaphael Isemann /// The location in the match file that the check string was specified. 8735ffd940aSRaphael Isemann SMLoc Loc; 8745ffd940aSRaphael Isemann 8755ffd940aSRaphael Isemann /// All of the strings that are disallowed from occurring between this match 8765ffd940aSRaphael Isemann /// string and the previous one (or start of file). 8775ffd940aSRaphael Isemann std::vector<Pattern> DagNotStrings; 8785ffd940aSRaphael Isemann FileCheckStringFileCheckString8795ffd940aSRaphael Isemann FileCheckString(const Pattern &P, StringRef S, SMLoc L) 8805ffd940aSRaphael Isemann : Pat(P), Prefix(S), Loc(L) {} 8815ffd940aSRaphael Isemann 8825ffd940aSRaphael Isemann /// Matches check string and its "not strings" and/or "dag strings". 8835ffd940aSRaphael Isemann size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode, 8845ffd940aSRaphael Isemann size_t &MatchLen, FileCheckRequest &Req, 8855ffd940aSRaphael Isemann std::vector<FileCheckDiag> *Diags) const; 8865ffd940aSRaphael Isemann 8875ffd940aSRaphael Isemann /// Verifies that there is a single line in the given \p Buffer. Errors are 8885ffd940aSRaphael Isemann /// reported against \p SM. 8895ffd940aSRaphael Isemann bool CheckNext(const SourceMgr &SM, StringRef Buffer) const; 8905ffd940aSRaphael Isemann /// Verifies that there is no newline in the given \p Buffer. Errors are 8915ffd940aSRaphael Isemann /// reported against \p SM. 8925ffd940aSRaphael Isemann bool CheckSame(const SourceMgr &SM, StringRef Buffer) const; 8935ffd940aSRaphael Isemann /// Verifies that none of the strings in \p NotStrings are found in the given 8945ffd940aSRaphael Isemann /// \p Buffer. Errors are reported against \p SM and diagnostics recorded in 8955ffd940aSRaphael Isemann /// \p Diags according to the verbosity level set in \p Req. 8965ffd940aSRaphael Isemann bool CheckNot(const SourceMgr &SM, StringRef Buffer, 8975ffd940aSRaphael Isemann const std::vector<const Pattern *> &NotStrings, 8985ffd940aSRaphael Isemann const FileCheckRequest &Req, 8995ffd940aSRaphael Isemann std::vector<FileCheckDiag> *Diags) const; 9005ffd940aSRaphael Isemann /// Matches "dag strings" and their mixed "not strings". 9015ffd940aSRaphael Isemann size_t CheckDag(const SourceMgr &SM, StringRef Buffer, 9025ffd940aSRaphael Isemann std::vector<const Pattern *> &NotStrings, 9035ffd940aSRaphael Isemann const FileCheckRequest &Req, 9045ffd940aSRaphael Isemann std::vector<FileCheckDiag> *Diags) const; 9055ffd940aSRaphael Isemann }; 9065ffd940aSRaphael Isemann 9075ffd940aSRaphael Isemann } // namespace llvm 9085ffd940aSRaphael Isemann 9095ffd940aSRaphael Isemann #endif 910