Skip to content

Commit

Permalink
FileCheck: Return parse error w/ Error & Expected
Browse files Browse the repository at this point in the history
Summary:
Make use of Error and Expected to bubble up diagnostics and force
checking of errors in the callers.

Reviewers: jhenderson, jdenny, probinson, arichardson

Subscribers: hiraditya, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D63125

llvm-svn: 363900
  • Loading branch information
Thomas Preud'homme committed Jun 19, 2019
1 parent e24b34e commit baae41f
Show file tree
Hide file tree
Showing 5 changed files with 462 additions and 400 deletions.
176 changes: 115 additions & 61 deletions llvm/include/llvm/Support/FileCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,30 @@ class FileCheckNumericVariable {
/// Type of functions evaluating a given binary operation.
using binop_eval_t = uint64_t (*)(uint64_t, uint64_t);

/// Class to represent an undefined variable error which prints that variable's
/// name between quotes when printed.
class FileCheckUndefVarError : public ErrorInfo<FileCheckUndefVarError> {
private:
StringRef VarName;

public:
static char ID;

FileCheckUndefVarError(StringRef VarName) : VarName(VarName) {}

StringRef getVarName() const { return VarName; }

std::error_code convertToErrorCode() const override {
return inconvertibleErrorCode();
}

/// Print name of variable associated with this error.
void log(raw_ostream &OS) const override {
OS << "\"";
OS.write_escaped(VarName) << "\"";
}
};

/// Class representing a numeric expression consisting of either a single
/// numeric variable or a binary operation between a numeric variable and an
/// immediate.
Expand All @@ -107,13 +131,9 @@ class FileCheckNumExpr {
: LeftOp(OperandLeft), RightOp(OperandRight), EvalBinop(EvalBinop) {}

/// Evaluates the value of this numeric expression, using EvalBinop to
/// perform the binary operation it consists of. \returns None if the numeric
/// variable used is undefined, or the expression value otherwise.
Optional<uint64_t> eval() const;

/// \returns the name of the undefined variable used in this expression if
/// any or an empty string otherwise.
StringRef getUndefVarName() const;
/// perform the binary operation it consists of. \returns an error if the
/// numeric variable used is undefined, or the expression value otherwise.
Expected<uint64_t> eval() const;
};

class FileCheckPatternContext;
Expand Down Expand Up @@ -151,12 +171,8 @@ class FileCheckSubstitution {
size_t getIndex() const { return InsertIdx; }

/// \returns a string containing the result of the substitution represented
/// by this class instance or None if substitution failed.
virtual Optional<std::string> getResult() const = 0;

/// \returns the name of the variable used in this substitution if undefined,
/// or an empty string otherwise.
virtual StringRef getUndefVarName() const = 0;
/// by this class instance or an error if substitution failed.
virtual Expected<std::string> getResult() const = 0;
};

class FileCheckStringSubstitution : public FileCheckSubstitution {
Expand All @@ -166,12 +182,8 @@ class FileCheckStringSubstitution : public FileCheckSubstitution {
: FileCheckSubstitution(Context, VarName, InsertIdx) {}

/// \returns the text that the string variable in this substitution matched
/// when defined, or None if the variable is undefined.
Optional<std::string> getResult() const override;

/// \returns the name of the string variable used in this substitution if
/// undefined, or an empty string otherwise.
StringRef getUndefVarName() const override;
/// when defined, or an error if the variable is undefined.
Expected<std::string> getResult() const override;
};

class FileCheckNumericSubstitution : public FileCheckSubstitution {
Expand All @@ -186,12 +198,8 @@ class FileCheckNumericSubstitution : public FileCheckSubstitution {
: FileCheckSubstitution(Context, Expr, InsertIdx), NumExpr(NumExpr) {}

/// \returns a string containing the result of evaluating the numeric
/// expression in this substitution, or None if evaluation failed.
Optional<std::string> getResult() const override;

/// \returns the name of the numeric variable used in this substitution if
/// undefined, or an empty string otherwise.
StringRef getUndefVarName() const override;
/// expression in this substitution, or an error if evaluation failed.
Expected<std::string> getResult() const override;
};

//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -282,16 +290,16 @@ class FileCheckPatternContext {
std::vector<std::unique_ptr<FileCheckSubstitution>> Substitutions;

public:
/// \returns the value of string variable \p VarName or None if no such
/// \returns the value of string variable \p VarName or an error if no such
/// variable has been defined.
Optional<StringRef> getPatternVarValue(StringRef VarName);
Expected<StringRef> getPatternVarValue(StringRef VarName);

/// Defines string and numeric variables from definitions given on the
/// command line, passed as a vector of [#]VAR=VAL strings in
/// \p CmdlineDefines. Reports any error to \p SM and \returns whether an
/// error occured.
bool defineCmdlineVariables(std::vector<std::string> &CmdlineDefines,
SourceMgr &SM);
/// \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,
SourceMgr &SM);

/// Undefines local variables (variables whose name does not start with a '$'
/// sign), i.e. removes them from GlobalVariableTable and from
Expand Down Expand Up @@ -323,6 +331,48 @@ class FileCheckPatternContext {
size_t InsertIdx);
};

/// Class to represent an error holding a diagnostic with location information
/// used when printing it.
class FileCheckErrorDiagnostic : public ErrorInfo<FileCheckErrorDiagnostic> {
private:
SMDiagnostic Diagnostic;

public:
static char ID;

FileCheckErrorDiagnostic(SMDiagnostic &&Diag) : Diagnostic(Diag) {}

std::error_code convertToErrorCode() const override {
return inconvertibleErrorCode();
}

/// Print diagnostic associated with this error when printing the error.
void log(raw_ostream &OS) const override { Diagnostic.print(nullptr, OS); }

static Error get(const SourceMgr &SM, SMLoc Loc, const Twine &ErrMsg) {
return make_error<FileCheckErrorDiagnostic>(
SM.GetMessage(Loc, SourceMgr::DK_Error, ErrMsg));
}

static Error get(const SourceMgr &SM, StringRef Buffer, const Twine &ErrMsg) {
return get(SM, SMLoc::getFromPointer(Buffer.data()), ErrMsg);
}
};

class FileCheckNotFoundError : public ErrorInfo<FileCheckNotFoundError> {
public:
static char ID;

std::error_code convertToErrorCode() const override {
return inconvertibleErrorCode();
}

/// Print diagnostic associated with this error when printing the error.
void log(raw_ostream &OS) const override {
OS << "String not found in input";
}
};

class FileCheckPattern {
SMLoc PatternLoc;

Expand Down Expand Up @@ -403,27 +453,30 @@ class FileCheckPattern {

/// \returns whether \p C is a valid first character for a variable name.
static bool isValidVarNameStart(char C);
/// Parses the string at the start of \p Str for a variable name and \returns
/// whether the variable name is ill-formed. If parsing succeeded, sets
/// \p IsPseudo to indicate if it is a pseudo variable, sets \p Name to the
/// parsed variable name and strips \p Str from the variable name.
static bool parseVariable(StringRef &Str, StringRef &Name, bool &IsPseudo);
/// Parses \p Expr for the definition of a numeric variable, returning an
/// error if \p Context already holds a string variable with the same name.
/// \returns whether parsing fails, in which case errors are reported on
/// \p SM. Otherwise, sets \p Name to the name of the parsed numeric
/// variable.
static bool parseNumericVariableDefinition(StringRef &Expr, StringRef &Name,
FileCheckPatternContext *Context,
const SourceMgr &SM);
/// Parses the string at the start of \p Str for a variable name. \returns
/// an error holding a diagnostic against \p SM if parsing fail, or the
/// name of the variable otherwise. In the latter case, sets \p IsPseudo to
/// indicate if it is a pseudo variable and strips \p Str from the variable
/// name.
static Expected<StringRef> parseVariable(StringRef &Str, bool &IsPseudo,
const SourceMgr &SM);
/// Parses \p Expr for the name of a numeric variable to be defined. \returns
/// an error holding a diagnostic against \p SM should defining such a
/// variable be invalid, or Success otherwise. In the latter case, sets
/// \p Name to the name of the parsed numeric variable name.
static Error parseNumericVariableDefinition(StringRef &Expr, StringRef &Name,
FileCheckPatternContext *Context,
const SourceMgr &SM);
/// Parses \p Expr for a numeric substitution block. \returns the class
/// representing the AST of the numeric expression whose value must be
/// substituted, or nullptr if parsing fails, in which case errors are
/// reported on \p SM. Sets \p DefinedNumericVariable to point to the class
/// representing the numeric variable defined in this numeric substitution
/// block, or nullptr if this block does not define any variable.
FileCheckNumExpr *parseNumericSubstitutionBlock(
StringRef Expr, FileCheckNumericVariable *&DefinedNumericVariable,
/// substituted, 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.
Expected<FileCheckNumExpr *> parseNumericSubstitutionBlock(
StringRef Expr,
Optional<FileCheckNumericVariable *> &DefinedNumericVariable,
const SourceMgr &SM) const;
/// Parses the pattern in \p PatternStr and initializes this FileCheckPattern
/// instance accordingly.
Expand All @@ -436,17 +489,18 @@ class FileCheckPattern {
const FileCheckRequest &Req);
/// Matches the pattern string against the input buffer \p Buffer
///
/// \returns the position that is matched or npos if there is no match. If
/// there is a match, updates \p MatchLen with the size of the matched
/// string.
/// \returns the position that is matched or an error indicating why matching
/// failed. If there is a match, updates \p MatchLen with the size of the
/// matched string.
///
/// The GlobalVariableTable StringMap in the FileCheckPatternContext class
/// instance provides the current values of FileCheck string variables and
/// is updated if this match defines new values. Likewise, the
/// GlobalNumericVariableTable StringMap in the same class provides the
/// current values of FileCheck numeric variables and is updated if this
/// match defines new numeric values.
size_t match(StringRef Buffer, size_t &MatchLen, const SourceMgr &SM) const;
Expected<size_t> match(StringRef Buffer, size_t &MatchLen,
const SourceMgr &SM) const;
/// Prints the value of successful substitutions or the name of the undefined
/// string or numeric variable preventing a successful substitution.
void printSubstitutions(const SourceMgr &SM, StringRef Buffer,
Expand Down Expand Up @@ -478,15 +532,15 @@ class FileCheckPattern {
size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM);

/// Parses \p Expr for the use of a numeric variable. \returns the pointer to
/// the class instance representing that variable if successful, or nullptr
/// otherwise, in which case errors are reported on \p SM.
FileCheckNumericVariable *parseNumericVariableUse(StringRef &Expr,
const SourceMgr &SM) const;
/// the class instance representing that variable if successful, or an error
/// holding a diagnostic against \p SM otherwise.
Expected<FileCheckNumericVariable *>
parseNumericVariableUse(StringRef &Expr, const SourceMgr &SM) const;
/// Parses \p Expr for a binary operation.
/// \returns the class representing the binary operation of the numeric
/// expression, or nullptr if parsing fails, in which case errors are
/// reported on \p SM.
FileCheckNumExpr *parseBinop(StringRef &Expr, const SourceMgr &SM) const;
/// expression, or an error holding a diagnostic against \p SM otherwise.
Expected<FileCheckNumExpr *> parseBinop(StringRef &Expr,
const SourceMgr &SM) const;
};

//===----------------------------------------------------------------------===//
Expand Down
Loading

0 comments on commit baae41f

Please sign in to comment.