[FileCheck] Added --enable-var-scope option to enable scope for regex variables.

If `--enable-var-scope` is in effect, variables with names that
start with `$` are considered to be global. All other variables are
local. All local variables get undefined at the beginning of each
CHECK-LABEL block. Global variables are not affected by CHECK-LABEL.
This makes it easier to ensure that individual tests are not affected
by variables set in preceding tests.

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@297396 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Artem Belevich 2017-03-09 17:59:04 +00:00
parent ef87bd9051
commit bb9779aa2e
4 changed files with 88 additions and 21 deletions

View File

@ -77,6 +77,15 @@ OPTIONS
-verify``. With this option FileCheck will verify that input does not contain
warnings not covered by any ``CHECK:`` patterns.
.. option:: --enable-var-scope
Enables scope for regex variables.
Variables with names that start with ``$`` are considered global and
remain set throughout the file.
All other variables get undefined after each encountered ``CHECK-LABEL``.
.. option:: -version
Show the version number of this program.
@ -344,6 +353,9 @@ matched by the directive cannot also be matched by any other check present in
other unique identifiers. Conceptually, the presence of ``CHECK-LABEL`` divides
the input stream into separate blocks, each of which is processed independently,
preventing a ``CHECK:`` directive in one block matching a line in another block.
If ``--enable-var-scope`` is in effect, all local variables are cleared at the
beginning of the block.
For example,
.. code-block:: llvm
@ -436,6 +448,13 @@ were defined on. For example:
Can be useful if you want the operands of ``op`` to be the same register,
and don't care exactly which register it is.
If ``--enable-var-scope`` is in effect, variables with names that
start with ``$`` are considered to be global. All others variables are
local. All local variables get undefined at the beginning of each
CHECK-LABEL block. Global variables are not affected by CHECK-LABEL.
This makes it easier to ensure that individual tests are not affected
by variables set in preceding tests.
FileCheck Expressions
~~~~~~~~~~~~~~~~~~~~~

View File

@ -1,15 +1,15 @@
; RUN: FileCheck -input-file %s %s
2
3 aaa
4 bbb
5 ccc
6 CHECK: [[@LINE-3]] {{a}}aa
7 CHECK: [[@LINE-3]] {{b}}bb
8 CHECK: [[@LINE-3]] {{c}}cc
9 foobar
10 CHECK: [[@LINE-1]] {{foo}}bar
11
12 arst CHECK: [[@LINE]] {{a}}rst
13
; RUN: not FileCheck -check-prefix BAD -input-file %s %s
3
4 aaa
5 bbb
6 ccc
7 CHECK: [[@LINE-3]] {{a}}aa
8 CHECK: [[@LINE-3]] {{b}}bb
9 CHECK: [[@LINE-3]] {{c}}cc
10 foobar
11 CHECK: [[@LINE-1]] {{foo}}bar
12
13 arst CHECK: [[@LINE]] {{a}}rst
14
15 BAD: [[@LINE:cant-have-regex]]

View File

@ -0,0 +1,23 @@
// RUN: FileCheck -check-prefix CHECK -input-file %s %s
// RUN: FileCheck -check-prefixes CHECK,GLOBAL -input-file %s %s
// RUN: FileCheck -check-prefixes CHECK,LOCAL -input-file %s %s
// RUN: FileCheck -check-prefixes CHECK,GLOBAL --enable-var-scope -input-file %s %s
// RUN: not FileCheck -check-prefixes CHECK,LOCAL --enable-var-scope -input-file %s %s
local
global
; CHECK: [[LOCAL:loc.*]]
; CHECK: [[$GLOBAL:glo.*]]
local2
global2
; CHECK: [[LOCAL]]2
; CHECK: [[$GLOBAL]]2
barrier:
; CHECK-LABEL: barrier
local3
global3
; LOCAL: [[LOCAL]]3
; GLOBAL: [[$GLOBAL]]3

View File

@ -73,6 +73,12 @@ static cl::opt<bool> MatchFullLines(
"Allows leading and trailing whitespace if --strict-whitespace\n"
"is not also passed."));
static cl::opt<bool> EnableVarScope(
"enable-var-scope", cl::init(false),
cl::desc("Enables scope for regex variables. Variables with names that\n"
"do not start with '$' will be reset at the beginning of\n"
"each CHECK-LABEL block."));
typedef cl::list<std::string>::const_iterator prefix_iterator;
//===----------------------------------------------------------------------===//
@ -263,15 +269,19 @@ bool Pattern::ParsePattern(StringRef PatternStr, StringRef Prefix,
// is relaxed, more strict check is performed in \c EvaluateExpression.
bool IsExpression = false;
for (unsigned i = 0, e = Name.size(); i != e; ++i) {
if (i == 0 && Name[i] == '@') {
if (NameEnd != StringRef::npos) {
SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
SourceMgr::DK_Error,
"invalid name in named regex definition");
return true;
if (i == 0) {
if (Name[i] == '$') // Global vars start with '$'
continue;
if (Name[i] == '@') {
if (NameEnd != StringRef::npos) {
SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
SourceMgr::DK_Error,
"invalid name in named regex definition");
return true;
}
IsExpression = true;
continue;
}
IsExpression = true;
continue;
}
if (Name[i] != '_' && !isalnum(Name[i]) &&
(!IsExpression || (Name[i] != '+' && Name[i] != '-'))) {
@ -1262,6 +1272,18 @@ static void DumpCommandLine(int argc, char **argv) {
errs() << "\n";
}
// Remove local variables from \p VariableTable. Global variables
// (start with '$') are preserved.
static void ClearLocalVars(StringMap<StringRef> &VariableTable) {
SmallVector<StringRef, 16> LocalVars;
for (const auto &Var : VariableTable)
if (Var.first()[0] != '$')
LocalVars.push_back(Var.first());
for (const auto &Var : LocalVars)
VariableTable.erase(Var);
}
/// Check the input to FileCheck provided in the \p Buffer against the \p
/// CheckStrings read from the check file.
///
@ -1298,6 +1320,9 @@ bool CheckInput(SourceMgr &SM, StringRef Buffer,
++j;
}
if (EnableVarScope)
ClearLocalVars(VariableTable);
for (; i != j; ++i) {
const CheckString &CheckStr = CheckStrings[i];