From bb9779aa2e56321365861cc02988265487469da1 Mon Sep 17 00:00:00 2001 From: Artem Belevich Date: Thu, 9 Mar 2017 17:59:04 +0000 Subject: [PATCH] [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 --- docs/CommandGuide/FileCheck.rst | 19 +++++++++++++++++++ test/FileCheck/line-count.txt | 26 +++++++++++++------------- test/FileCheck/regex-scope.txt | 23 +++++++++++++++++++++++ utils/FileCheck/FileCheck.cpp | 41 +++++++++++++++++++++++++++++++++-------- 4 files changed, 88 insertions(+), 21 deletions(-) create mode 100644 test/FileCheck/regex-scope.txt diff --git a/docs/CommandGuide/FileCheck.rst b/docs/CommandGuide/FileCheck.rst index 413b6f41b0c..8830c394b21 100644 --- a/docs/CommandGuide/FileCheck.rst +++ b/docs/CommandGuide/FileCheck.rst @@ -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 ~~~~~~~~~~~~~~~~~~~~~ diff --git a/test/FileCheck/line-count.txt b/test/FileCheck/line-count.txt index 6f91c2050bf..d39663e2dba 100644 --- a/test/FileCheck/line-count.txt +++ b/test/FileCheck/line-count.txt @@ -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]] diff --git a/test/FileCheck/regex-scope.txt b/test/FileCheck/regex-scope.txt new file mode 100644 index 00000000000..e77f3f6513a --- /dev/null +++ b/test/FileCheck/regex-scope.txt @@ -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 diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index 9e177574625..da1267f027d 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -73,6 +73,12 @@ static cl::opt MatchFullLines( "Allows leading and trailing whitespace if --strict-whitespace\n" "is not also passed.")); +static cl::opt 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::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 &VariableTable) { + SmallVector 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]; -- 2.11.0