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