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