``CHECK-LABEL:`` directives cannot contain variable definitions or uses.
-FileCheck Pattern Matching Syntax
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+FileCheck Regex Matching Syntax
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
All FileCheck directives take a pattern to match.
For most uses of FileCheck, fixed string matching is perfectly sufficient. For
braces explicitly from the input, you can use something ugly like
``{{[{][{]}}`` as your pattern.
-FileCheck Pattern Expressions
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+FileCheck String Substitution Blocks
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It is often useful to match a pattern and then verify that it occurs again
-later in the file. For codegen tests, this can be useful to allow any register,
-but verify that that register is used consistently later. To do this,
-:program:`FileCheck` supports pattern expressions that allow pattern variables
-to be defined and substituted into patterns. Here is a simple example:
+later in the file. For codegen tests, this can be useful to allow any
+register, but verify that that register is used consistently later. To do
+this, :program:`FileCheck` supports string substitution blocks that allow
+string variables to be defined and substituted into patterns. Here is a simple
+example:
.. code-block:: llvm
; CHECK: andw {{.*}}[[REGISTER]]
The first check line matches a regex ``%[a-z]+`` and captures it into the
-variable ``REGISTER``. The second line verifies that whatever is in
-``REGISTER`` occurs later in the file after an "``andw``". :program:`FileCheck`
-variable references are always contained in ``[[ ]]`` pairs, and their names can
-be formed with the regex ``[a-zA-Z_][a-zA-Z0-9_]*``. If a colon follows the name,
-then it is a definition of the variable; otherwise, it is a use.
+string variable ``REGISTER``. The second line verifies that whatever is in
+``REGISTER`` occurs later in the file after an "``andw``". :program:`FileCheck`
+string substitution blocks are always contained in ``[[ ]]`` pairs, and string
+variable names can be formed with the regex ``[a-zA-Z_][a-zA-Z0-9_]*``. If a
+colon follows the name, then it is a definition of the variable; otherwise, it
+is a substitution.
-:program:`FileCheck` variables can be defined multiple times, and uses always
-get the latest value. Variables can also be used later on the same line they
-were defined on. For example:
+:program:`FileCheck` variables can be defined multiple times, and substitutions
+always get the latest value. Variables can also be substituted later on the
+same line they were defined on. For example:
.. code-block:: llvm
This makes it easier to ensure that individual tests are not affected
by variables set in preceding tests.
-FileCheck Numeric Variables and Expressions
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+FileCheck Numeric Substitution Blocks
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-:program:`FileCheck` also allows checking for numeric values that satisfy a
-numeric expression constraint based on numeric variables. This allows
-``CHECK:`` directives to verify a numeric relation between two numbers, such as
-the need for consecutive registers to be used.
+:program:`FileCheck` also supports numeric substitution blocks that allow
+checking for numeric values that satisfy a numeric expression constraint based
+on numeric variables. This allows ``CHECK:`` directives to verify a numeric
+relation between two numbers, such as the need for consecutive registers to be
+used.
-The syntax to check a numeric expression constraint is
-``[[#<NUMVAR><op><offset>]]`` where:
+The syntax of a numeric substitution block is ``[[#<NUMVAR><op><offset>]]``
+where:
* ``<NUMVAR>`` is the name of a numeric variable defined on the command line.
the numeric operation <op>. It must be present if ``<op>`` is present,
absent otherwise.
+Spaces are accepted before, after and between any of these elements.
+
+Unlike string substitution blocks, numeric substitution blocks only introduce
+numeric substitutions which substitute a numeric expression for its value.
For example:
.. code-block:: llvm
due to ``7`` being unequal to ``5 + 1``.
The ``--enable-var-scope`` option has the same effect on numeric variables as
-on pattern variables.
+on string variables.
FileCheck Pseudo Numeric Variables
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK-NEXT: {{^ ;}}
int a
-To support legacy uses of ``@LINE`` as a special pattern variable,
-:program:`FileCheck` also accepts the following uses of ``@LINE`` with pattern
-variable syntax: ``[[@LINE]]``, ``[[@LINE+<offset>]]`` and
+To support legacy uses of ``@LINE`` as a special string variable,
+:program:`FileCheck` also accepts the following uses of ``@LINE`` with string
+substitution block syntax: ``[[@LINE]]``, ``[[@LINE+<offset>]]`` and
``[[@LINE-<offset>]]`` without any spaces inside the brackets and where
``offset`` is an integer.
};
//===----------------------------------------------------------------------===//
-// Numeric expression handling code.
+// Numeric substitution handling code.
//===----------------------------------------------------------------------===//
/// Class representing a numeric variable with a given value in a numeric
class FileCheckPatternContext;
-/// Class representing a substitution to perform in the string to match.
-class FileCheckPatternSubstitution {
-private:
- /// Pointer to a class instance holding the table with the values of live
- /// pattern variables at the start of any given CHECK line. Used for
- /// substituting pattern variables (numeric variables have their value in the
- /// FileCheckNumExpr class instance pointed to by NumExpr).
+/// Class representing a substitution to perform in the RegExStr string.
+class FileCheckSubstitution {
+protected:
+ /// Pointer to a class instance holding, among other things, the table with
+ /// the values of live string variables at the start of any given CHECK line.
+ /// Used for substituting string variables with the text they were defined
+ /// as. Numeric expressions are linked to the numeric variables they use at
+ /// parse time and directly access the value of the numeric variable to
+ /// evaluate their value.
FileCheckPatternContext *Context;
/// Whether this represents a numeric expression substitution.
- bool IsNumExpr;
+ bool IsNumSubst;
/// The string that needs to be substituted for something else. For a
- /// pattern variable this is its name, otherwise this is the whole numeric
+ /// string variable this is its name, otherwise this is the whole numeric
/// expression.
StringRef FromStr;
/// If this is a numeric expression substitution, this is the pointer to the
- /// class representing that numeric expression.
+ /// class representing the numeric expression whose value is to be
+ /// substituted.
FileCheckNumExpr *NumExpr = nullptr;
// Index in RegExStr of where to do the substitution.
public:
/// Constructor for a pattern variable substitution.
- FileCheckPatternSubstitution(FileCheckPatternContext *Context,
- StringRef VarName, size_t InsertIdx)
- : Context(Context), IsNumExpr(false), FromStr(VarName),
+ FileCheckSubstitution(FileCheckPatternContext *Context,
+ StringRef VarName, size_t InsertIdx)
+ : Context(Context), IsNumSubst(false), FromStr(VarName),
InsertIdx(InsertIdx) {}
/// Constructor for a numeric expression substitution.
- FileCheckPatternSubstitution(FileCheckPatternContext *Context, StringRef Expr,
- FileCheckNumExpr *NumExpr, size_t InsertIdx)
- : Context(Context), IsNumExpr(true), FromStr(Expr), NumExpr(NumExpr),
+ FileCheckSubstitution(FileCheckPatternContext *Context, StringRef Expr,
+ FileCheckNumExpr *NumExpr, size_t InsertIdx)
+ : Context(Context), IsNumSubst(true), FromStr(Expr), NumExpr(NumExpr),
InsertIdx(InsertIdx) {}
/// \returns whether this is a numeric expression substitution.
- bool isNumExpr() const { return IsNumExpr; }
+ bool isNumSubst() const { return IsNumSubst; }
- /// \returns the string to be substituted.
+ /// \returns the string to be substituted for something else.
StringRef getFromString() const { return FromStr; }
- /// \returns the index where the substitution is to be performed.
+ /// \returns the index where the substitution is to be performed in RegExStr.
size_t getIndex() const { return InsertIdx; }
/// \returns the result of the substitution represented by this class
/// instance or None if substitution failed. Numeric expressions are
- /// substituted by their values. Pattern variables are simply replaced by the
+ /// substituted by their values. String variables are simply replaced by the
/// text their definition matched.
llvm::Optional<std::string> getResult() const;
friend class FileCheckPattern;
private:
- /// When matching a given pattern, this holds the value of all the FileCheck
- /// pattern variables defined in previous patterns. In a pattern, only the
- /// last definition for a given variable is recorded in this table.
+ /// When matching a given pattern, this holds the value of all the string
+ /// variables defined in previous patterns. In a pattern, only the last
+ /// definition for a given variable is recorded in this table.
/// Back-references are used for uses after any the other definition.
StringMap<StringRef> GlobalVariableTable;
- /// Map of all pattern variables defined so far. Used at parse time to detect
- /// a name conflict between a numeric variable and a pattern variable when
+ /// Map of all string variables defined so far. Used at parse time to detect
+ /// a name conflict between a numeric variable and a string variable when
/// the former is defined on a later line than the latter.
StringMap<bool> DefinedVariableTable;
std::vector<std::unique_ptr<FileCheckNumericVariable>> NumericVariables;
public:
- /// \returns the value of pattern variable \p VarName or None if no such
+ /// \returns the value of string variable \p VarName or None if no such
/// variable has been defined.
llvm::Optional<StringRef> getPatternVarValue(StringRef VarName);
- /// Defines pattern and numeric variables from definitions given on the
+ /// 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.
SourceMgr &SM);
/// Undefines local variables (variables whose name does not start with a '$'
- /// sign), i.e. removes them from GlobalVariableTable.
+ /// sign), i.e. removes them from GlobalVariableTable and from
+ /// GlobalNumericVariableTable and also clears the value of numeric
+ /// variables.
void clearLocalVars();
private:
/// a fixed string to match.
std::string RegExStr;
- /// Entries in this vector represent uses of a pattern variable or a numeric
- /// expression in the pattern that need to be substituted in the regexp
- /// pattern at match time, e.g. "foo[[bar]]baz[[#N+1]]". In this case, the
+ /// Entries in this vector represent a substitution of a string variable or a
+ /// numeric expression in the RegExStr regex at match time. For example, in
+ /// the case of a CHECK directive with the pattern "foo[[bar]]baz[[#N+1]]",
/// RegExStr will contain "foobaz" and we'll get two entries in this vector
- /// that tells us to insert the value of pattern variable "bar" at offset 3
- /// and the value of numeric expression "N+1" at offset 6. Uses are
- /// represented by a FileCheckPatternSubstitution class to abstract whether
- /// it is a pattern variable or a numeric expression.
- std::vector<FileCheckPatternSubstitution> Substitutions;
+ /// that tells us to insert the value of string variable "bar" at offset 3
+ /// and the value of numeric expression "N+1" at offset 6.
+ std::vector<FileCheckSubstitution> Substitutions;
- /// Maps names of pattern variables defined in a pattern to the parenthesized
+ /// Maps names of string variables defined in a pattern to the parenthesized
/// capture numbers of their last definition.
///
/// E.g. for the pattern "foo[[bar:.*]]baz[[bar]]quux[[bar:.*]]",
/// Pointer to a class instance holding the global state shared by all
/// patterns:
- /// - separate tables with the values of live pattern and numeric variables
+ /// - separate tables with the values of live string and numeric variables
/// respectively at the start of any given CHECK line;
- /// - table holding whether a pattern variable has been defined at any given
+ /// - table holding whether a string variable has been defined at any given
/// point during the parsing phase.
FileCheckPatternContext *Context;
/// character that is part of the variable name. Otherwise, only
/// \returns true.
static bool parseVariable(StringRef Str, bool &IsPseudo, unsigned &TrailIdx);
- /// Parses a numeric expression involving (pseudo if \p IsPseudo is true)
+ /// Parses a numeric substitution involving (pseudo if \p IsPseudo is true)
/// variable \p Name with the string corresponding to the operation being
/// performed in \p Trailer. \returns the class representing the numeric
- /// expression or nullptr if parsing fails in which case errors are reported
- /// on \p SM.
- FileCheckNumExpr *parseNumericExpression(StringRef Name, bool IsPseudo,
- StringRef Trailer,
- const SourceMgr &SM) const;
+ /// expression being substituted or nullptr if parsing fails, in which case
+ /// errors are reported on \p SM.
+ FileCheckNumExpr *parseNumericSubstitution(StringRef Name, bool IsPseudo,
+ StringRef Trailer,
+ const SourceMgr &SM) const;
/// Parses the pattern in \p PatternStr and initializes this FileCheckPattern
/// instance accordingly.
///
/// string.
///
/// The GlobalVariableTable StringMap in the FileCheckPatternContext class
- /// instance provides the current values of FileCheck pattern variables and
+ /// instance provides the current values of FileCheck string variables and
/// is updated if this match defines new values.
size_t match(StringRef Buffer, size_t &MatchLen) const;
/// Prints the value of successful substitutions or the name of the undefined
- /// pattern or numeric variable preventing such a successful substitution.
+ /// string or numeric variable preventing a successful substitution.
void printSubstitutions(const SourceMgr &SM, StringRef Buffer,
SMRange MatchRange = None) const;
void printFuzzyMatch(const SourceMgr &SM, StringRef Buffer,
return StringRef();
}
-llvm::Optional<std::string> FileCheckPatternSubstitution::getResult() const {
- if (IsNumExpr) {
+llvm::Optional<std::string> FileCheckSubstitution::getResult() const {
+ if (IsNumSubst) {
llvm::Optional<uint64_t> EvaluatedValue = NumExpr->eval();
if (!EvaluatedValue)
return llvm::None;
return Regex::escape(*VarVal);
}
-StringRef FileCheckPatternSubstitution::getUndefVarName() const {
- if (IsNumExpr)
+StringRef FileCheckSubstitution::getUndefVarName() const {
+ if (IsNumSubst)
// Although a use of an undefined numeric variable is detected at parse
// time, a numeric variable can be undefined later by ClearLocalVariables.
return NumExpr->getUndefVarName();
}
FileCheckNumExpr *
-FileCheckPattern::parseNumericExpression(StringRef Name, bool IsPseudo,
- StringRef Trailer,
- const SourceMgr &SM) const {
+FileCheckPattern::parseNumericSubstitution(StringRef Name, bool IsPseudo,
+ StringRef Trailer,
+ const SourceMgr &SM) const {
if (IsPseudo && !Name.equals("@LINE")) {
SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
"invalid pseudo numeric variable '" + Name + "'");
continue;
}
- // Pattern and numeric expression matches. Pattern expressions come in two
- // forms: [[foo:.*]] and [[foo]]. The former matches .* (or some other
- // regex) and assigns it to the FileCheck variable 'foo'. The latter
- // substitutes foo's value. Numeric expressions start with a '#' sign after
- // the double brackets and only have the substitution form. Both pattern
- // and numeric variables must satisfy the regular expression
+ // String and numeric substitution blocks. String substitution blocks come
+ // in two forms: [[foo:.*]] and [[foo]]. The former matches .* (or some
+ // other regex) and assigns it to the string variable 'foo'. The latter
+ // substitutes foo's value. Numeric substitution blocks start with a
+ // '#' sign after the double brackets and only have the substitution form.
+ // Both string and numeric variables must satisfy the regular expression
// "[a-zA-Z_][0-9a-zA-Z_]*" to be valid, as this helps catch some common
// errors.
if (PatternStr.startswith("[[")) {
// offset relative to the beginning of the match string.
size_t End = FindRegexVarEnd(UnparsedPatternStr, SM);
StringRef MatchStr = UnparsedPatternStr.substr(0, End);
- bool IsNumExpr = MatchStr.consume_front("#");
- const char *RefTypeStr =
- IsNumExpr ? "numeric expression" : "pattern variable";
+ bool IsNumBlock = MatchStr.consume_front("#");
if (End == StringRef::npos) {
- SM.PrintMessage(
- SMLoc::getFromPointer(PatternStr.data()), SourceMgr::DK_Error,
- Twine("Invalid ") + RefTypeStr + " reference, no ]] found");
+ SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
+ SourceMgr::DK_Error,
+ "Invalid substitution block, no ]] found");
return true;
}
- // Strip the subtitution we are parsing. End points to the start of the
- // "]]" closing the expression so account for it in computing the index
- // of the first unparsed character.
+ // Strip the substitution block we are parsing. End points to the start
+ // of the "]]" closing the expression so account for it in computing the
+ // index of the first unparsed character.
PatternStr = UnparsedPatternStr.substr(End + 2);
size_t VarEndIdx = MatchStr.find(":");
- if (IsNumExpr)
+ if (IsNumBlock)
MatchStr = MatchStr.ltrim(SpaceChars);
else {
size_t SpacePos = MatchStr.substr(0, VarEndIdx).find_first_of(" \t");
}
}
- // Get the regex name (e.g. "foo") and verify it is well formed.
+ // Get the variable name (e.g. "foo") and verify it is well formed.
bool IsPseudo;
unsigned TrailIdx;
if (parseVariable(MatchStr, IsPseudo, TrailIdx)) {
if (IsPseudo || !Trailer.consume_front(":")) {
SM.PrintMessage(SMLoc::getFromPointer(MatchStr.data()),
SourceMgr::DK_Error,
- "invalid name in pattern variable definition");
+ "invalid name in string variable definition");
return true;
}
- // Detect collisions between pattern and numeric variables when the
+ // Detect collisions between string and numeric variables when the
// former is created later than the latter.
if (Context->GlobalNumericVariableTable.find(Name) !=
Context->GlobalNumericVariableTable.end()) {
}
}
- if (IsNumExpr || (!IsVarDef && IsPseudo)) {
- NumExpr = parseNumericExpression(Name, IsPseudo, Trailer, SM);
+ if (IsNumBlock || (!IsVarDef && IsPseudo)) {
+ NumExpr = parseNumericSubstitution(Name, IsPseudo, Trailer, SM);
if (NumExpr == nullptr)
return true;
- IsNumExpr = true;
+ IsNumBlock = true;
}
- // Handle variable use: [[foo]] and [[#<foo expr>]].
+ // Handle substitutions: [[foo]] and [[#<foo expr>]].
if (!IsVarDef) {
- // Handle use of pattern variables that were defined earlier on the
- // same line by emitting a backreference.
- if (!IsNumExpr && VariableDefs.find(Name) != VariableDefs.end()) {
+ // Handle substitution of string variables that were defined earlier on
+ // the same line by emitting a backreference.
+ if (!IsNumBlock && VariableDefs.find(Name) != VariableDefs.end()) {
unsigned CaptureParen = VariableDefs[Name];
if (CaptureParen < 1 || CaptureParen > 9) {
SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
}
AddBackrefToRegEx(CaptureParen);
} else {
- // Handle use of pattern variables ([[<var>]]) defined in previous
- // CHECK pattern or use of a numeric expression.
- FileCheckPatternSubstitution Substitution =
- IsNumExpr ? FileCheckPatternSubstitution(Context, MatchStr,
- NumExpr, SubstInsertIdx)
- : FileCheckPatternSubstitution(Context, MatchStr,
- SubstInsertIdx);
+ // Handle substitution of string variables ([[<var>]]) defined in
+ // previous CHECK patterns, and substitution of numeric expressions.
+ FileCheckSubstitution Substitution =
+ IsNumBlock ? FileCheckSubstitution(Context, MatchStr, NumExpr,
+ SubstInsertIdx)
+ : FileCheckSubstitution(Context, MatchStr,
+ SubstInsertIdx);
Substitutions.push_back(Substitution);
}
continue;
}
- // Handle [[foo:.*]].
+ // Handle variable definitions: [[foo:.*]].
VariableDefs[Name] = CurParen;
RegExStr += '(';
++CurParen;
// Regex match.
- // If there are variable uses, we need to create a temporary string with the
+ // If there are substitutions, we need to create a temporary string with the
// actual value.
StringRef RegExToMatch = RegExStr;
std::string TmpStr;
TmpStr = RegExStr;
size_t InsertOffset = 0;
- // Substitute all pattern variables and numeric expressions whose value is
- // known just now. Use of pattern variables defined on the same line are
+ // Substitute all string variables and numeric expressions whose values are
+ // only now known. Use of string variables defined on the same line are
// handled by back-references.
for (const auto &Substitution : Substitutions) {
// Substitute and check for failure (e.g. use of undefined variable).
assert(!MatchInfo.empty() && "Didn't get any match");
StringRef FullMatch = MatchInfo[0];
- // If this defines any pattern variables, remember their values.
+ // If this defines any string variables, remember their values.
for (const auto &VariableDef : VariableDefs) {
assert(VariableDef.second < MatchInfo.size() && "Internal paren error");
Context->GlobalVariableTable[VariableDef.first] =
void FileCheckPattern::printSubstitutions(const SourceMgr &SM, StringRef Buffer,
SMRange MatchRange) const {
- // Print what we know about substitutions. This covers both uses of pattern
- // variables and numeric subsitutions.
+ // Print what we know about substitutions.
if (!Substitutions.empty()) {
for (const auto &Substitution : Substitutions) {
SmallString<256> Msg;
raw_svector_ostream OS(Msg);
- bool IsNumExpr = Substitution.isNumExpr();
+ bool IsNumSubst = Substitution.isNumSubst();
llvm::Optional<std::string> MatchedValue = Substitution.getResult();
// Substitution failed or is not known at match time, print the undefined
OS.write_escaped(UndefVarName) << "\"";
} else {
// Substitution succeeded. Print substituted value.
- if (IsNumExpr)
+ if (IsNumSubst)
OS << "with numeric expression \"";
else
- OS << "with variable \"";
+ OS << "with string variable \"";
OS.write_escaped(Substitution.getFromString()) << "\" equal to \"";
OS.write_escaped(*MatchedValue) << "\"";
}
continue;
}
- // Detect collisions between pattern and numeric variables when the
- // latter is created later than the former.
+ // Detect collisions between string and numeric variables when the latter
+ // is created later than the former.
if (DefinedVariableTable.find(CmdlineName) !=
DefinedVariableTable.end()) {
SM.PrintMessage(
SMLoc::getFromPointer(CmdlineName.data()), SourceMgr::DK_Error,
- "pattern variable with name '" + CmdlineName + "' already exists");
+ "string variable with name '" + CmdlineName + "' already exists");
ErrorFound = true;
continue;
}
// Record this variable definition.
GlobalNumericVariableTable[CmdlineName] = DefinedNumericVariable;
} else {
- // Pattern variable definition.
+ // String variable definition.
std::pair<StringRef, StringRef> CmdlineNameVal = CmdlineDef.split('=');
StringRef Name = CmdlineNameVal.first;
bool IsPseudo;
if (FileCheckPattern::parseVariable(Name, IsPseudo, TrailIdx) ||
IsPseudo || TrailIdx != Name.size() || Name.empty()) {
SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
- "invalid name in pattern variable definition '" + Name +
+ "invalid name in string variable definition '" + Name +
"'");
ErrorFound = true;
continue;
}
- // Detect collisions between pattern and numeric variables when the
- // former is created later than the latter.
+ // Detect collisions between string and numeric variables when the former
+ // is created later than the latter.
if (GlobalNumericVariableTable.find(Name) !=
GlobalNumericVariableTable.end()) {
SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
continue;
}
GlobalVariableTable.insert(CmdlineNameVal);
- // Mark the pattern variable as defined to detect collisions between
- // pattern and numeric variables in DefineCmdlineVariables when the
- // latter is created later than the former. We cannot reuse
- // GlobalVariableTable for that by populating it with an empty string
- // since we would then lose the ability to detect the use of an undefined
- // variable in Match().
+ // Mark the string variable as defined to detect collisions between
+ // string and numeric variables in DefineCmdlineVariables when the latter
+ // is created later than the former. We cannot reuse GlobalVariableTable
+ // for that by populating it with an empty string since we would then
+ // lose the ability to detect the use of an undefined variable in
+ // match().
DefinedVariableTable[Name] = true;
}
}
if (Var.first()[0] != '$')
LocalPatternVars.push_back(Var.first());
- // Numeric expression substitution reads the value of a variable directly,
- // not via GlobalNumericVariableTable. Therefore, we clear local variables by
- // clearing their value which will lead to a numeric expression substitution
- // failure. We also mark the variable for removal from
- // GlobalNumericVariableTable since this is what defineCmdlineVariables
- // checks to decide that no global variable has been defined.
+ // Numeric substitution reads the value of a variable directly, not via
+ // GlobalNumericVariableTable. Therefore, we clear local variables by
+ // clearing their value which will lead to a numeric substitution failure. We
+ // also mark the variable for removal from GlobalNumericVariableTable since
+ // this is what defineCmdlineVariables checks to decide that no global
+ // variable has been defined.
for (const auto &Var : GlobalNumericVariableTable)
if (Var.first()[0] != '$') {
Var.getValue()->clearValue();
23 arst CHECK: [[@LINE]] {{a}}rst
24
25 BAD1: [[@LINE:cant-have-regex]]
-26 ERR1: line-count.txt:[[#@LINE-1]]:12: error: invalid name in pattern variable definition
+26 ERR1: line-count.txt:[[#@LINE-1]]:12: error: invalid name in string variable definition
27
28 BAD2: [[ @LINE]]
29 ERR2: line-count.txt:[[#@LINE-1]]:12: error: unexpected whitespace
INVAL-OP-MSG-NEXT: {{I}}NVAL-OP-NEXT: VAR1*2: {{\[\[#VAR1\*2\]\]}}
INVAL-OP-MSG-NEXT: {{^ \^$}}
-; Name conflict between Numeric variable definition and pattern variable
+; Name conflict between Numeric variable definition and string variable
; definition
RUN: not FileCheck -D#VAR1=11 -D#NUMVAR=42 --check-prefixes CONFLICT,CONFLICT1 --input-file %s %s 2>&1 \
RUN: | FileCheck --strict-whitespace --check-prefix CLI-INPUT-PAT-CONFLICT %s
CLI-CLI-PAT-CONFLICT: Global defines:3:19: error: numeric variable with name 'NUMVAR' already exists
CLI-CLI-PAT-CONFLICT-NEXT: Global define #3: NUMVAR=foobar
CLI-CLI-PAT-CONFLICT-NEXT: {{^ \^$}}
-CLI-CLI-NUM-CONFLICT: Global defines:3:20: error: pattern variable with name 'PATVAR' already exists
+CLI-CLI-NUM-CONFLICT: Global defines:3:20: error: string variable with name 'PATVAR' already exists
CLI-CLI-NUM-CONFLICT-NEXT: Global define #3: #PATVAR=42
CLI-CLI-NUM-CONFLICT-NEXT: {{^ \^$}}
RUN: not FileCheck -D=10 --input-file %s %s 2>&1 \
RUN: | FileCheck %s --check-prefix ERRCLIVAR1
-ERRCLIVAR1: Missing pattern variable name in command-line definition '-D=10'
+ERRCLIVAR1: Missing variable name in command-line definition '-D=10'
; Missing variable name.
RUN: not FileCheck -D= --input-file %s %s 2>&1 \
RUN: | FileCheck %s --check-prefix ERRCLIVAR2
-ERRCLIVAR2: Missing pattern variable name in command-line definition '-D='
+ERRCLIVAR2: Missing variable name in command-line definition '-D='
; Invalid variable name: starts with a digit.
RUN: not FileCheck -D10VALUE=10 --input-file %s %s 2>&1 \
RUN: | FileCheck %s --strict-whitespace --check-prefix ERRCLIFMT
-ERRCLIFMT: Global defines:1:19: error: invalid name in pattern variable definition '10VALUE'
+ERRCLIFMT: Global defines:1:19: error: invalid name in string variable definition '10VALUE'
ERRCLIFMT-NEXT: Global define #1: 10VALUE=10
ERRCLIFMT-NEXT: {{^ \^$}}
RUN: not FileCheck -D@VALUE=10 --input-file %s %s 2>&1 \
RUN: | FileCheck %s --strict-whitespace --check-prefix ERRCLIPSEUDO
-ERRCLIPSEUDO: Global defines:1:19: error: invalid name in pattern variable definition '@VALUE'
+ERRCLIPSEUDO: Global defines:1:19: error: invalid name in string variable definition '@VALUE'
ERRCLIPSEUDO-NEXT: Global define #1: @VALUE=10
ERRCLIPSEUDO-NEXT: {{^ \^$}}
RUN: not FileCheck -D'VALUE + 2=10' --input-file %s %s 2>&1 \
RUN: | FileCheck %s --strict-whitespace --check-prefix ERRCLITRAIL
-ERRCLITRAIL: Global defines:1:19: error: invalid name in pattern variable definition 'VALUE + 2'
+ERRCLITRAIL: Global defines:1:19: error: invalid name in string variable definition 'VALUE + 2'
ERRCLITRAIL-NEXT: Global define #1: VALUE + 2=10
ERRCLITRAIL-NEXT: {{^ \^$}}
-; Test functionality of -D option: pattern variables are defined to the right
+; Test functionality of -D option: string variables are defined to the right
; value and CHECK directives using them match as expected given the value set.
-; Pattern variable correctly defined to a non-empty string.
+; String variable correctly defined to a non-empty string.
RUN: FileCheck -DVALUE=10 --input-file %s %s
RUN: not FileCheck -DVALUE=20 --input-file %s %s 2>&1 \
RUN: | FileCheck %s --check-prefix ERRMSG
ERRMSG: defines.txt:[[@LINE-3]]:8: error: CHECK: expected string not found in input
ERRMSG: defines.txt:1:1: note: scanning from here
-ERRMSG: defines.txt:1:1: note: with variable "VALUE" equal to "20"
+ERRMSG: defines.txt:1:1: note: with string variable "VALUE" equal to "20"
ERRMSG: defines.txt:[[@LINE-7]]:1: note: possible intended match here
NOT-ERRMSG: defines.txt:[[@LINE-7]]:10: error: {{NOT}}-NOT: excluded string found in input
NOT-ERRMSG: defines.txt:[[@LINE-10]]:1: note: found here
-NOT-ERRMSG: defines.txt:[[@LINE-11]]:1: note: with variable "VALUE" equal to "10"
+NOT-ERRMSG: defines.txt:[[@LINE-11]]:1: note: with string variable "VALUE" equal to "10"
-; Definition of pattern variable to an empty string.
+; Definition of string variable to an empty string.
RUN: FileCheck -DVALUE= --check-prefix EMPTY --input-file %s %s 2>&1
Empty value = @@
StringRef NameTrailerRef = bufferize(SM, NameTrailer);
StringRef VarNameRef = NameTrailerRef.substr(0, VarName.size());
StringRef TrailerRef = NameTrailerRef.substr(VarName.size());
- return P.parseNumericExpression(VarNameRef, IsPseudo, TrailerRef, SM) ==
+ return P.parseNumericSubstitution(VarNameRef, IsPseudo, TrailerRef, SM) ==
nullptr;
}
};
GlobalDefines.emplace_back(std::string("FOO=BAR"));
Context.defineCmdlineVariables(GlobalDefines, SM);
- // Substitution of undefined pattern variable fails.
- FileCheckPatternSubstitution PatternSubstitution =
- FileCheckPatternSubstitution(&Context, "VAR404", 42);
- EXPECT_FALSE(PatternSubstitution.getResult());
+ // Substitution of an undefined string variable fails.
+ FileCheckSubstitution Substitution =
+ FileCheckSubstitution(&Context, "VAR404", 42);
+ EXPECT_FALSE(Substitution.getResult());
// Substitutions of defined pseudo and non-pseudo numeric variables return
// the right value.
FileCheckNumericVariable NVar = FileCheckNumericVariable("@N", 10);
FileCheckNumExpr NumExprLine = FileCheckNumExpr(doAdd, &LineVar, 0);
FileCheckNumExpr NumExprN = FileCheckNumExpr(doAdd, &NVar, 3);
- FileCheckPatternSubstitution SubstitutionLine =
- FileCheckPatternSubstitution(&Context, "@LINE", &NumExprLine, 12);
- FileCheckPatternSubstitution SubstitutionN =
- FileCheckPatternSubstitution(&Context, "N", &NumExprN, 30);
+ FileCheckSubstitution SubstitutionLine =
+ FileCheckSubstitution(&Context, "@LINE", &NumExprLine, 12);
+ FileCheckSubstitution SubstitutionN =
+ FileCheckSubstitution(&Context, "N", &NumExprN, 30);
llvm::Optional<std::string> Value = SubstitutionLine.getResult();
EXPECT_TRUE(Value);
EXPECT_EQ("42", *Value);
EXPECT_TRUE(Value);
EXPECT_EQ("13", *Value);
- // Substitution of undefined numeric variable fails.
+ // Substitution of an undefined numeric variable fails.
LineVar.clearValue();
EXPECT_FALSE(SubstitutionLine.getResult());
NVar.clearValue();
EXPECT_FALSE(SubstitutionN.getResult());
- // Substitution of defined pattern variable returns the right value.
+ // Substitution of a defined string variable returns the right value.
FileCheckPattern P = FileCheckPattern(Check::CheckPlain, &Context);
- PatternSubstitution = FileCheckPatternSubstitution(&Context, "FOO", 42);
- Value = PatternSubstitution.getResult();
+ Substitution = FileCheckSubstitution(&Context, "FOO", 42);
+ Value = Substitution.getResult();
EXPECT_TRUE(Value);
EXPECT_EQ("BAR", *Value);
}
GlobalDefines.emplace_back(std::string("FOO=BAR"));
Context.defineCmdlineVariables(GlobalDefines, SM);
- // getUndefVarName() on a pattern variable substitution with an undefined
- // variable returns that variable.
- FileCheckPatternSubstitution Substitution =
- FileCheckPatternSubstitution(&Context, "VAR404", 42);
+ // getUndefVarName() on a string substitution with an undefined variable
+ // returns that variable.
+ FileCheckSubstitution Substitution =
+ FileCheckSubstitution(&Context, "VAR404", 42);
StringRef UndefVar = Substitution.getUndefVarName();
EXPECT_EQ("VAR404", UndefVar);
- // getUndefVarName() on a pattern variable substitution with a defined
- // variable returns an empty string.
- Substitution = FileCheckPatternSubstitution(&Context, "FOO", 42);
+ // getUndefVarName() on a string substitution with a defined variable returns
+ // an empty string.
+ Substitution = FileCheckSubstitution(&Context, "FOO", 42);
UndefVar = Substitution.getUndefVarName();
EXPECT_EQ("", UndefVar);
- // getUndefVarName() on a numeric expression substitution with a defined
- // variable returns an empty string.
+ // getUndefVarName() on a numeric substitution with a defined variable
+ // returns an empty string.
FileCheckNumericVariable LineVar = FileCheckNumericVariable("@LINE", 42);
FileCheckNumExpr NumExpr = FileCheckNumExpr(doAdd, &LineVar, 0);
- Substitution = FileCheckPatternSubstitution(&Context, "@LINE", &NumExpr, 12);
+ Substitution = FileCheckSubstitution(&Context, "@LINE", &NumExpr, 12);
UndefVar = Substitution.getUndefVarName();
EXPECT_EQ("", UndefVar);
- // getUndefVarName() on a numeric expression substitution with an undefined
- // variable returns that variable.
+ // getUndefVarName() on a numeric substitution with an undefined variable
+ // returns that variable.
LineVar.clearValue();
UndefVar = Substitution.getUndefVarName();
EXPECT_EQ("@LINE", UndefVar);
llvm::Optional<StringRef> LocalVar = Cxt.getPatternVarValue(LocalVarStr);
FileCheckPattern P = FileCheckPattern(Check::CheckPlain, &Cxt);
FileCheckNumExpr *NumExpr =
- P.parseNumericExpression(LocalNumVarRef, false /*IsPseudo*/, "", SM);
+ P.parseNumericSubstitution(LocalNumVarRef, false /*IsPseudo*/, "", SM);
llvm::Optional<StringRef> EmptyVar = Cxt.getPatternVarValue(EmptyVarStr);
llvm::Optional<StringRef> UnknownVar = Cxt.getPatternVarValue(UnknownVarStr);
EXPECT_TRUE(LocalVar);
EXPECT_FALSE(NumExpr->eval());
P = FileCheckPattern(Check::CheckPlain, &Cxt);
NumExpr =
- P.parseNumericExpression(LocalNumVarRef, false /*IsPseudo*/, "", SM);
+ P.parseNumericSubstitution(LocalNumVarRef, false /*IsPseudo*/, "", SM);
EXPECT_FALSE(NumExpr);
EmptyVar = Cxt.getPatternVarValue(EmptyVarStr);
EXPECT_FALSE(EmptyVar);
EXPECT_EQ(*GlobalVar, "BAR");
P = FileCheckPattern(Check::CheckPlain, &Cxt);
NumExpr =
- P.parseNumericExpression(GlobalNumVarRef, false /*IsPseudo*/, "", SM);
+ P.parseNumericSubstitution(GlobalNumVarRef, false /*IsPseudo*/, "", SM);
EXPECT_TRUE(NumExpr);
NumExprVal = NumExpr->eval();
EXPECT_TRUE(NumExprVal);
EXPECT_TRUE(GlobalVar);
P = FileCheckPattern(Check::CheckPlain, &Cxt);
NumExpr =
- P.parseNumericExpression(GlobalNumVarRef, false /*IsPseudo*/, "", SM);
+ P.parseNumericSubstitution(GlobalNumVarRef, false /*IsPseudo*/, "", SM);
EXPECT_TRUE(NumExpr);
NumExprVal = NumExpr->eval();
EXPECT_TRUE(NumExprVal);
continue;
}
if (EqIdx == 0) {
- errs() << "Missing pattern variable name in command-line definition '-D"
- << G << "'\n";
+ errs() << "Missing variable name in command-line definition '-D" << G
+ << "'\n";
GlobalDefineError = true;
continue;
}