diff options
Diffstat (limited to 'llvm/lib/Support/FileCheckImpl.h')
-rw-r--r-- | llvm/lib/Support/FileCheckImpl.h | 349 |
1 files changed, 284 insertions, 65 deletions
diff --git a/llvm/lib/Support/FileCheckImpl.h b/llvm/lib/Support/FileCheckImpl.h index dc07d22aefd83..6ca67ec2964c2 100644 --- a/llvm/lib/Support/FileCheckImpl.h +++ b/llvm/lib/Support/FileCheckImpl.h @@ -15,6 +15,7 @@ #ifndef LLVM_LIB_SUPPORT_FILECHECKIMPL_H #define LLVM_LIB_SUPPORT_FILECHECKIMPL_H +#include "llvm/Support/FileCheck.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" @@ -30,28 +31,175 @@ namespace llvm { // Numeric substitution handling code. //===----------------------------------------------------------------------===// +class ExpressionValue; + +/// Type representing the format an expression value should be textualized into +/// for matching. Used to represent both explicit format specifiers as well as +/// implicit format from using numeric variables. +struct ExpressionFormat { + enum class Kind { + /// Denote absence of format. Used for implicit format of literals and + /// empty expressions. + NoFormat, + /// Value is an unsigned integer and should be printed as a decimal number. + Unsigned, + /// Value is a signed integer and should be printed as a decimal number. + Signed, + /// Value should be printed as an uppercase hex number. + HexUpper, + /// Value should be printed as a lowercase hex number. + HexLower + }; + +private: + Kind Value; + +public: + /// Evaluates a format to true if it can be used in a match. + explicit operator bool() const { return Value != Kind::NoFormat; } + + /// Define format equality: formats are equal if neither is NoFormat and + /// their kinds are the same. + bool operator==(const ExpressionFormat &Other) const { + return Value != Kind::NoFormat && Value == Other.Value; + } + + bool operator!=(const ExpressionFormat &Other) const { + return !(*this == Other); + } + + bool operator==(Kind OtherValue) const { return Value == OtherValue; } + + bool operator!=(Kind OtherValue) const { return !(*this == OtherValue); } + + /// \returns the format specifier corresponding to this format as a string. + StringRef toString() const; + + ExpressionFormat() : Value(Kind::NoFormat){}; + explicit ExpressionFormat(Kind Value) : Value(Value){}; + + /// \returns a wildcard regular expression StringRef that matches any value + /// in the format represented by this instance, or an error if the format is + /// NoFormat. + Expected<StringRef> getWildcardRegex() const; + + /// \returns the string representation of \p Value in the format represented + /// by this instance, or an error if conversion to this format failed or the + /// format is NoFormat. + Expected<std::string> getMatchingString(ExpressionValue Value) const; + + /// \returns the value corresponding to string representation \p StrVal + /// according to the matching format represented by this instance or an error + /// with diagnostic against \p SM if \p StrVal does not correspond to a valid + /// and representable value. + Expected<ExpressionValue> valueFromStringRepr(StringRef StrVal, + const SourceMgr &SM) const; +}; + +/// Class to represent an overflow error that might result when manipulating a +/// value. +class OverflowError : public ErrorInfo<OverflowError> { +public: + static char ID; + + std::error_code convertToErrorCode() const override { + return std::make_error_code(std::errc::value_too_large); + } + + void log(raw_ostream &OS) const override { OS << "overflow error"; } +}; + +/// Class representing a numeric value. +class ExpressionValue { +private: + uint64_t Value; + bool Negative; + +public: + template <class T> + explicit ExpressionValue(T Val) : Value(Val), Negative(Val < 0) {} + + bool operator==(const ExpressionValue &Other) const { + return Value == Other.Value && isNegative() == Other.isNegative(); + } + + bool operator!=(const ExpressionValue &Other) const { + return !(*this == Other); + } + + /// Returns true if value is signed and negative, false otherwise. + bool isNegative() const { + assert((Value != 0 || !Negative) && "Unexpected negative zero!"); + return Negative; + } + + /// \returns the value as a signed integer or an error if the value is out of + /// range. + Expected<int64_t> getSignedValue() const; + + /// \returns the value as an unsigned integer or an error if the value is out + /// of range. + Expected<uint64_t> getUnsignedValue() const; + + /// \returns an unsigned ExpressionValue instance whose value is the absolute + /// value to this object's value. + ExpressionValue getAbsolute() const; +}; + +/// Performs operation and \returns its result or an error in case of failure, +/// such as if an overflow occurs. +Expected<ExpressionValue> operator+(const ExpressionValue &Lhs, + const ExpressionValue &Rhs); +Expected<ExpressionValue> operator-(const ExpressionValue &Lhs, + const ExpressionValue &Rhs); +Expected<ExpressionValue> operator*(const ExpressionValue &Lhs, + const ExpressionValue &Rhs); +Expected<ExpressionValue> operator/(const ExpressionValue &Lhs, + const ExpressionValue &Rhs); +Expected<ExpressionValue> max(const ExpressionValue &Lhs, + const ExpressionValue &Rhs); +Expected<ExpressionValue> min(const ExpressionValue &Lhs, + const ExpressionValue &Rhs); + /// Base class representing the AST of a given expression. class ExpressionAST { +private: + StringRef ExpressionStr; + public: + ExpressionAST(StringRef ExpressionStr) : ExpressionStr(ExpressionStr) {} + virtual ~ExpressionAST() = default; + StringRef getExpressionStr() const { return ExpressionStr; } + /// Evaluates and \returns the value of the expression represented by this /// AST or an error if evaluation fails. - virtual Expected<uint64_t> eval() const = 0; + virtual Expected<ExpressionValue> eval() const = 0; + + /// \returns either the implicit format of this AST, a diagnostic against + /// \p SM if implicit formats of the AST's components conflict, or NoFormat + /// if the AST has no implicit format (e.g. AST is made up of a single + /// literal). + virtual Expected<ExpressionFormat> + getImplicitFormat(const SourceMgr &SM) const { + return ExpressionFormat(); + } }; /// Class representing an unsigned literal in the AST of an expression. class ExpressionLiteral : public ExpressionAST { private: /// Actual value of the literal. - uint64_t Value; + ExpressionValue Value; public: - /// Constructs a literal with the specified value. - ExpressionLiteral(uint64_t Val) : Value(Val) {} + template <class T> + explicit ExpressionLiteral(StringRef ExpressionStr, T Val) + : ExpressionAST(ExpressionStr), Value(Val) {} /// \returns the literal's value. - Expected<uint64_t> eval() const override { return Value; } + Expected<ExpressionValue> eval() const override { return Value; } }; /// Class to represent an undefined variable error, which quotes that @@ -78,14 +226,40 @@ public: } }; +/// Class representing an expression and its matching format. +class Expression { +private: + /// Pointer to AST of the expression. + std::unique_ptr<ExpressionAST> AST; + + /// Format to use (e.g. hex upper case letters) when matching the value. + ExpressionFormat Format; + +public: + /// Generic constructor for an expression represented by the given \p AST and + /// whose matching format is \p Format. + Expression(std::unique_ptr<ExpressionAST> AST, ExpressionFormat Format) + : AST(std::move(AST)), Format(Format) {} + + /// \returns pointer to AST of the expression. Pointer is guaranteed to be + /// valid as long as this object is. + ExpressionAST *getAST() const { return AST.get(); } + + ExpressionFormat getFormat() const { return Format; } +}; + /// Class representing a numeric variable and its associated current value. class NumericVariable { private: /// Name of the numeric variable. StringRef Name; + /// Format to use for expressions using this variable without an explicit + /// format. + ExpressionFormat ImplicitFormat; + /// Value of numeric variable, if defined, or None otherwise. - Optional<uint64_t> Value; + Optional<ExpressionValue> Value; /// Line number where this variable is defined, or None if defined before /// input is parsed. Used to determine whether a variable is defined on the @@ -93,20 +267,25 @@ private: Optional<size_t> DefLineNumber; public: - /// Constructor for a variable \p Name defined at line \p DefLineNumber or - /// defined before input is parsed if \p DefLineNumber is None. - explicit NumericVariable(StringRef Name, + /// Constructor for a variable \p Name with implicit format \p ImplicitFormat + /// defined at line \p DefLineNumber or defined before input is parsed if + /// \p DefLineNumber is None. + explicit NumericVariable(StringRef Name, ExpressionFormat ImplicitFormat, Optional<size_t> DefLineNumber = None) - : Name(Name), DefLineNumber(DefLineNumber) {} + : Name(Name), ImplicitFormat(ImplicitFormat), + DefLineNumber(DefLineNumber) {} /// \returns name of this numeric variable. StringRef getName() const { return Name; } + /// \returns implicit format of this numeric variable. + ExpressionFormat getImplicitFormat() const { return ImplicitFormat; } + /// \returns this variable's value. - Optional<uint64_t> getValue() const { return Value; } + Optional<ExpressionValue> getValue() const { return Value; } /// Sets value of this numeric variable to \p NewValue. - void setValue(uint64_t NewValue) { Value = NewValue; } + void setValue(ExpressionValue NewValue) { Value = NewValue; } /// Clears value of this numeric variable, regardless of whether it is /// currently defined or not. @@ -121,22 +300,25 @@ public: /// expression. class NumericVariableUse : public ExpressionAST { private: - /// Name of the numeric variable. - StringRef Name; - /// Pointer to the class instance for the variable this use is about. NumericVariable *Variable; public: NumericVariableUse(StringRef Name, NumericVariable *Variable) - : Name(Name), Variable(Variable) {} - + : ExpressionAST(Name), Variable(Variable) {} /// \returns the value of the variable referenced by this instance. - Expected<uint64_t> eval() const override; + Expected<ExpressionValue> eval() const override; + + /// \returns implicit format of this numeric variable. + Expected<ExpressionFormat> + getImplicitFormat(const SourceMgr &SM) const override { + return Variable->getImplicitFormat(); + } }; /// Type of functions evaluating a given binary operation. -using binop_eval_t = uint64_t (*)(uint64_t, uint64_t); +using binop_eval_t = Expected<ExpressionValue> (*)(const ExpressionValue &, + const ExpressionValue &); /// Class representing a single binary operation in the AST of an expression. class BinaryOperation : public ExpressionAST { @@ -151,9 +333,10 @@ private: binop_eval_t EvalBinop; public: - BinaryOperation(binop_eval_t EvalBinop, std::unique_ptr<ExpressionAST> LeftOp, + BinaryOperation(StringRef ExpressionStr, binop_eval_t EvalBinop, + std::unique_ptr<ExpressionAST> LeftOp, std::unique_ptr<ExpressionAST> RightOp) - : EvalBinop(EvalBinop) { + : ExpressionAST(ExpressionStr), EvalBinop(EvalBinop) { LeftOperand = std::move(LeftOp); RightOperand = std::move(RightOp); } @@ -162,7 +345,14 @@ public: /// using EvalBinop on the result of recursively evaluating the operands. /// \returns the expression value or an error if an undefined numeric /// variable is used in one of the operands. - Expected<uint64_t> eval() const override; + Expected<ExpressionValue> eval() const override; + + /// \returns the implicit format of this AST, if any, a diagnostic against + /// \p SM if the implicit formats of the AST's components conflict, or no + /// format if the AST has no implicit format (e.g. AST is made of a single + /// literal). + Expected<ExpressionFormat> + getImplicitFormat(const SourceMgr &SM) const override; }; class FileCheckPatternContext; @@ -218,14 +408,14 @@ class NumericSubstitution : public Substitution { private: /// Pointer to the class representing the expression whose value is to be /// substituted. - std::unique_ptr<ExpressionAST> ExpressionASTPointer; + std::unique_ptr<Expression> ExpressionPointer; public: - NumericSubstitution(FileCheckPatternContext *Context, StringRef Expr, - std::unique_ptr<ExpressionAST> ExprAST, size_t InsertIdx) - : Substitution(Context, Expr, InsertIdx) { - ExpressionASTPointer = std::move(ExprAST); - } + NumericSubstitution(FileCheckPatternContext *Context, StringRef ExpressionStr, + std::unique_ptr<Expression> ExpressionPointer, + size_t InsertIdx) + : Substitution(Context, ExpressionStr, InsertIdx), + ExpressionPointer(std::move(ExpressionPointer)) {} /// \returns a string containing the result of evaluating the expression in /// this substitution, or an error if evaluation failed. @@ -236,8 +426,6 @@ public: // Pattern handling code. //===----------------------------------------------------------------------===// -struct FileCheckDiag; - /// Class holding the Pattern global state, shared by all patterns: tables /// holding values of variables and whether they are defined or not at any /// given time in the matching process. @@ -270,6 +458,10 @@ private: /// automatically free them once they are guaranteed to no longer be used. std::vector<std::unique_ptr<NumericVariable>> NumericVariables; + /// Vector holding pointers to all parsed expressions. Used to automatically + /// free the expressions once they are guaranteed to no longer be used. + std::vector<std::unique_ptr<Expression>> Expressions; + /// Vector holding pointers to all substitutions. Used to automatically free /// them once they are guaranteed to no longer be used. std::vector<std::unique_ptr<Substitution>> Substitutions; @@ -283,7 +475,7 @@ public: /// command line, passed as a vector of [#]VAR=VAL strings in /// \p CmdlineDefines. \returns an error list containing diagnostics against /// \p SM for all definition parsing failures, if any, or Success otherwise. - Error defineCmdlineVariables(std::vector<std::string> &CmdlineDefines, + Error defineCmdlineVariables(ArrayRef<StringRef> CmdlineDefines, SourceMgr &SM); /// Create @LINE pseudo variable. Value is set when pattern are being @@ -307,10 +499,9 @@ private: /// Makes a new numeric substitution and registers it for destruction when /// the context is destroyed. - Substitution * - makeNumericSubstitution(StringRef ExpressionStr, - std::unique_ptr<ExpressionAST> ExpressionAST, - size_t InsertIdx); + Substitution *makeNumericSubstitution(StringRef ExpressionStr, + std::unique_ptr<Expression> Expression, + size_t InsertIdx); }; /// Class to represent an error holding a diagnostic with location information @@ -388,12 +579,12 @@ class Pattern { std::map<StringRef, unsigned> VariableDefs; /// Structure representing the definition of a numeric variable in a pattern. - /// It holds the pointer to the class representing the numeric variable whose - /// value is being defined and the number of the parenthesis group in - /// RegExStr to capture that value. + /// It holds the pointer to the class instance holding the value and matching + /// format of the numeric variable whose value is being defined and the + /// number of the parenthesis group in RegExStr to capture that value. struct NumericVariableMatch { - /// Pointer to class representing the numeric variable whose value is being - /// defined. + /// Pointer to class instance holding the value and matching format of the + /// numeric variable being defined. NumericVariable *DefinedNumericVariable; /// Number of the parenthesis group in RegExStr that captures the value of @@ -457,12 +648,12 @@ public: /// \p IsLegacyLineExpr indicates whether \p Expr should be a legacy @LINE /// expression and \p Context points to the class instance holding the live /// string and numeric variables. \returns a pointer to the class instance - /// representing the AST of the expression whose value must be substitued, or - /// an error holding a diagnostic against \p SM if parsing fails. If - /// substitution was successful, sets \p DefinedNumericVariable to point to - /// the class representing the numeric variable defined in this numeric - /// substitution block, or None if this block does not define any variable. - static Expected<std::unique_ptr<ExpressionAST>> parseNumericSubstitutionBlock( + /// representing the expression whose value must be substitued, or an error + /// holding a diagnostic against \p SM if parsing fails. If substitution was + /// successful, sets \p DefinedNumericVariable to point to the class + /// representing the numeric variable defined in this numeric substitution + /// block, or None if this block does not define any variable. + static Expected<std::unique_ptr<Expression>> parseNumericSubstitutionBlock( StringRef Expr, Optional<NumericVariable *> &DefinedNumericVariable, bool IsLegacyLineExpr, Optional<size_t> LineNumber, FileCheckPatternContext *Context, const SourceMgr &SM); @@ -526,7 +717,8 @@ private: /// should defining such a variable be invalid. static Expected<NumericVariable *> parseNumericVariableDefinition( StringRef &Expr, FileCheckPatternContext *Context, - Optional<size_t> LineNumber, const SourceMgr &SM); + Optional<size_t> LineNumber, ExpressionFormat ImplicitFormat, + const SourceMgr &SM); /// Parses \p Name as a (pseudo if \p IsPseudo is true) numeric variable use /// at line \p LineNumber, or before input is parsed if \p LineNumber is /// None. Parameter \p Context points to the class instance holding the live @@ -536,29 +728,56 @@ private: static Expected<std::unique_ptr<NumericVariableUse>> parseNumericVariableUse( StringRef Name, bool IsPseudo, Optional<size_t> LineNumber, FileCheckPatternContext *Context, const SourceMgr &SM); - enum class AllowedOperand { LineVar, Literal, Any }; + enum class AllowedOperand { LineVar, LegacyLiteral, Any }; /// Parses \p Expr for use of a numeric operand at line \p LineNumber, or - /// before input is parsed if \p LineNumber is None. Accepts both literal - /// values and numeric variables, depending on the value of \p AO. Parameter - /// \p Context points to the class instance holding the live string and - /// numeric variables. \returns the class representing that operand in the - /// AST of the expression or an error holding a diagnostic against \p SM - /// otherwise. + /// before input is parsed if \p LineNumber is None. Accepts literal values, + /// numeric variables and function calls, depending on the value of \p AO. + /// \p MaybeInvalidConstraint indicates whether the text being parsed could + /// be an invalid constraint. \p Context points to the class instance holding + /// the live string and numeric variables. \returns the class representing + /// that operand in the AST of the expression or an error holding a + /// diagnostic against \p SM otherwise. If \p Expr starts with a "(" this + /// function will attempt to parse a parenthesized expression. static Expected<std::unique_ptr<ExpressionAST>> - parseNumericOperand(StringRef &Expr, AllowedOperand AO, + parseNumericOperand(StringRef &Expr, AllowedOperand AO, bool ConstraintParsed, Optional<size_t> LineNumber, FileCheckPatternContext *Context, const SourceMgr &SM); - /// Parses \p Expr for a binary operation at line \p LineNumber, or before - /// input is parsed if \p LineNumber is None. The left operand of this binary - /// operation is given in \p LeftOp and \p IsLegacyLineExpr indicates whether - /// we are parsing a legacy @LINE expression. Parameter \p Context points to - /// the class instance holding the live string and numeric variables. - /// \returns the class representing the binary operation in the AST of the - /// expression, or an error holding a diagnostic against \p SM otherwise. + /// Parses and updates \p RemainingExpr for a binary operation at line + /// \p LineNumber, or before input is parsed if \p LineNumber is None. The + /// left operand of this binary operation is given in \p LeftOp and \p Expr + /// holds the string for the full expression, including the left operand. + /// Parameter \p IsLegacyLineExpr indicates whether we are parsing a legacy + /// @LINE expression. Parameter \p Context points to the class instance + /// holding the live string and numeric variables. \returns the class + /// representing the binary operation in the AST of the expression, or an + /// error holding a diagnostic against \p SM otherwise. + static Expected<std::unique_ptr<ExpressionAST>> + parseBinop(StringRef Expr, StringRef &RemainingExpr, + std::unique_ptr<ExpressionAST> LeftOp, bool IsLegacyLineExpr, + Optional<size_t> LineNumber, FileCheckPatternContext *Context, + const SourceMgr &SM); + + /// Parses a parenthesized expression inside \p Expr at line \p LineNumber, or + /// before input is parsed if \p LineNumber is None. \p Expr must start with + /// a '('. Accepts both literal values and numeric variables. Parameter \p + /// Context points to the class instance holding the live string and numeric + /// variables. \returns the class representing that operand in the AST of the + /// expression or an error holding a diagnostic against \p SM otherwise. + static Expected<std::unique_ptr<ExpressionAST>> + parseParenExpr(StringRef &Expr, Optional<size_t> LineNumber, + FileCheckPatternContext *Context, const SourceMgr &SM); + + /// Parses \p Expr for an argument list belonging to a call to function \p + /// FuncName at line \p LineNumber, or before input is parsed if \p LineNumber + /// is None. Parameter \p FuncLoc is the source location used for diagnostics. + /// Parameter \p Context points to the class instance holding the live string + /// and numeric variables. \returns the class representing that call in the + /// AST of the expression or an error holding a diagnostic against \p SM + /// otherwise. static Expected<std::unique_ptr<ExpressionAST>> - parseBinop(StringRef &Expr, std::unique_ptr<ExpressionAST> LeftOp, - bool IsLegacyLineExpr, Optional<size_t> LineNumber, - FileCheckPatternContext *Context, const SourceMgr &SM); + parseCallExpr(StringRef &Expr, StringRef FuncName, + Optional<size_t> LineNumber, FileCheckPatternContext *Context, + const SourceMgr &SM); }; //===----------------------------------------------------------------------===// |