]> granicus.if.org Git - llvm/commitdiff
[FileCheck] Implement --ignore-case option.
authorKai Nacke <kai.nacke@redstar.de>
Thu, 10 Oct 2019 13:15:41 +0000 (13:15 +0000)
committerKai Nacke <kai.nacke@redstar.de>
Thu, 10 Oct 2019 13:15:41 +0000 (13:15 +0000)
The FileCheck utility is enhanced to support a `--ignore-case`
option. This is useful in cases where the output of Unix tools
differs in case (e.g. case not specified by Posix).

Reviewers: Bigcheese, jakehehrlich, rupprecht, espindola, alexshap, jhenderson, MaskRay

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@374339 91177308-0d34-0410-b5e6-96231b3b80d8

docs/CommandGuide/FileCheck.rst
include/llvm/Support/FileCheck.h
lib/Support/FileCheck.cpp
lib/Support/FileCheckImpl.h
test/FileCheck/check-ignore-case.txt [new file with mode: 0644]
utils/FileCheck/FileCheck.cpp

index e8b324d080dfa95c397ff71e7d21d1078ab37b2d..7d8ecaa7bfa6d8bda8467324295604928bee033d 100644 (file)
-FileCheck - Flexible pattern matching file verifier
-===================================================
-
-.. program:: FileCheck
-
-SYNOPSIS
---------
-
-:program:`FileCheck` *match-filename* [*--check-prefix=XXX*] [*--strict-whitespace*]
-
-DESCRIPTION
------------
-
-:program:`FileCheck` reads two files (one from standard input, and one
-specified on the command line) and uses one to verify the other.  This
-behavior is particularly useful for the testsuite, which wants to verify that
-the output of some tool (e.g. :program:`llc`) contains the expected information
-(for example, a movsd from esp or whatever is interesting).  This is similar to
-using :program:`grep`, but it is optimized for matching multiple different
-inputs in one file in a specific order.
-
-The ``match-filename`` file specifies the file that contains the patterns to
-match.  The file to verify is read from standard input unless the
-:option:`--input-file` option is used.
-
-OPTIONS
--------
-
-Options are parsed from the environment variable ``FILECHECK_OPTS``
-and from the command line.
-
-.. option:: -help
-
- Print a summary of command line options.
-
-.. option:: --check-prefix prefix
-
- FileCheck searches the contents of ``match-filename`` for patterns to
- match.  By default, these patterns are prefixed with "``CHECK:``".
- If you'd like to use a different prefix (e.g. because the same input
- file is checking multiple different tool or options), the
- :option:`--check-prefix` argument allows you to specify one or more
- prefixes to match. Multiple prefixes are useful for tests which might
- change for different run options, but most lines remain the same.
-
-.. option:: --check-prefixes prefix1,prefix2,...
-
- An alias of :option:`--check-prefix` that allows multiple prefixes to be
- specified as a comma separated list.
-
-.. option:: --input-file filename
-
-  File to check (defaults to stdin).
-
-.. option:: --match-full-lines
-
- By default, FileCheck allows matches of anywhere on a line. This
- option will require all positive matches to cover an entire
- line. Leading and trailing whitespace is ignored, unless
- :option:`--strict-whitespace` is also specified. (Note: negative
- matches from ``CHECK-NOT`` are not affected by this option!)
-
- Passing this option is equivalent to inserting ``{{^ *}}`` or
- ``{{^}}`` before, and ``{{ *$}}`` or ``{{$}}`` after every positive
- check pattern.
-
-.. option:: --strict-whitespace
-
- By default, FileCheck canonicalizes input horizontal whitespace (spaces and
- tabs) which causes it to ignore these differences (a space will match a tab).
- The :option:`--strict-whitespace` argument disables this behavior. End-of-line
- sequences are canonicalized to UNIX-style ``\n`` in all modes.
-
-.. option:: --implicit-check-not check-pattern
-
-  Adds implicit negative checks for the specified patterns between positive
-  checks. The option allows writing stricter tests without stuffing them with
-  ``CHECK-NOT``\ s.
-
-  For example, "``--implicit-check-not warning:``" can be useful when testing
-  diagnostic messages from tools that don't have an option similar to ``clang
-  -verify``. With this option FileCheck will verify that input does not contain
-  warnings not covered by any ``CHECK:`` patterns.
-
-.. option:: --dump-input <mode>
-
-  Dump input to stderr, adding annotations representing currently enabled
-  diagnostics.  Do this either 'always', on 'fail', or 'never'.  Specify 'help'
-  to explain the dump format and quit.
-
-.. option:: --dump-input-on-failure
-
-  When the check fails, dump all of the original input.  This option is
-  deprecated in favor of `--dump-input=fail`.
-
-.. 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:: -D<VAR=VALUE>
-
-  Sets a filecheck pattern variable ``VAR`` with value ``VALUE`` that can be
-  used in ``CHECK:`` lines.
-
-.. option:: -D#<NUMVAR>=<NUMERIC EXPRESSION>
-
-  Sets a filecheck numeric variable ``NUMVAR`` to the result of evaluating
-  ``<NUMERIC EXPRESSION>`` that can be used in ``CHECK:`` lines. See section
-  ``FileCheck Numeric Variables and Expressions`` for details on supported
-  numeric expressions.
-
-.. option:: -version
-
- Show the version number of this program.
-
-.. option:: -v
-
-  Print good directive pattern matches.  However, if ``-input-dump=fail`` or
-  ``-input-dump=always``, add those matches as input annotations instead.
-
-.. option:: -vv
-
-  Print information helpful in diagnosing internal FileCheck issues, such as
-  discarded overlapping ``CHECK-DAG:`` matches, implicit EOF pattern matches,
-  and ``CHECK-NOT:`` patterns that do not have matches.  Implies ``-v``.
-  However, if ``-input-dump=fail`` or ``-input-dump=always``, just add that
-  information as input annotations instead.
-
-.. option:: --allow-deprecated-dag-overlap
-
-  Enable overlapping among matches in a group of consecutive ``CHECK-DAG:``
-  directives.  This option is deprecated and is only provided for convenience
-  as old tests are migrated to the new non-overlapping ``CHECK-DAG:``
-  implementation.
-
-.. option:: --color
-
-  Use colors in output (autodetected by default).
-
-EXIT STATUS
------------
-
-If :program:`FileCheck` verifies that the file matches the expected contents,
-it exits with 0.  Otherwise, if not, or if an error occurs, it will exit with a
-non-zero value.
-
-TUTORIAL
---------
-
-FileCheck is typically used from LLVM regression tests, being invoked on the RUN
-line of the test.  A simple example of using FileCheck from a RUN line looks
-like this:
-
-.. code-block:: llvm
-
-   ; RUN: llvm-as < %s | llc -march=x86-64 | FileCheck %s
-
-This syntax says to pipe the current file ("``%s``") into ``llvm-as``, pipe
-that into ``llc``, then pipe the output of ``llc`` into ``FileCheck``.  This
-means that FileCheck will be verifying its standard input (the llc output)
-against the filename argument specified (the original ``.ll`` file specified by
-"``%s``").  To see how this works, let's look at the rest of the ``.ll`` file
-(after the RUN line):
-
-.. code-block:: llvm
-
-   define void @sub1(i32* %p, i32 %v) {
-   entry:
-   ; CHECK: sub1:
-   ; CHECK: subl
-           %0 = tail call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %p, i32 %v)
-           ret void
-   }
-
-   define void @inc4(i64* %p) {
-   entry:
-   ; CHECK: inc4:
-   ; CHECK: incq
-           %0 = tail call i64 @llvm.atomic.load.add.i64.p0i64(i64* %p, i64 1)
-           ret void
-   }
-
-Here you can see some "``CHECK:``" lines specified in comments.  Now you can
-see how the file is piped into ``llvm-as``, then ``llc``, and the machine code
-output is what we are verifying.  FileCheck checks the machine code output to
-verify that it matches what the "``CHECK:``" lines specify.
-
-The syntax of the "``CHECK:``" lines is very simple: they are fixed strings that
-must occur in order.  FileCheck defaults to ignoring horizontal whitespace
-differences (e.g. a space is allowed to match a tab) but otherwise, the contents
-of the "``CHECK:``" line is required to match some thing in the test file exactly.
-
-One nice thing about FileCheck (compared to grep) is that it allows merging
-test cases together into logical groups.  For example, because the test above
-is checking for the "``sub1:``" and "``inc4:``" labels, it will not match
-unless there is a "``subl``" in between those labels.  If it existed somewhere
-else in the file, that would not count: "``grep subl``" matches if "``subl``"
-exists anywhere in the file.
-
-The FileCheck -check-prefix option
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The FileCheck `-check-prefix` option allows multiple test
-configurations to be driven from one `.ll` file.  This is useful in many
-circumstances, for example, testing different architectural variants with
-:program:`llc`.  Here's a simple example:
-
-.. code-block:: llvm
-
-   ; RUN: llvm-as < %s | llc -mtriple=i686-apple-darwin9 -mattr=sse41 \
-   ; RUN:              | FileCheck %s -check-prefix=X32
-   ; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin9 -mattr=sse41 \
-   ; RUN:              | FileCheck %s -check-prefix=X64
-
-   define <4 x i32> @pinsrd_1(i32 %s, <4 x i32> %tmp) nounwind {
-           %tmp1 = insertelement <4 x i32>; %tmp, i32 %s, i32 1
-           ret <4 x i32> %tmp1
-   ; X32: pinsrd_1:
-   ; X32:    pinsrd $1, 4(%esp), %xmm0
-
-   ; X64: pinsrd_1:
-   ; X64:    pinsrd $1, %edi, %xmm0
-   }
-
-In this case, we're testing that we get the expected code generation with
-both 32-bit and 64-bit code generation.
-
-The "CHECK-NEXT:" directive
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Sometimes you want to match lines and would like to verify that matches
-happen on exactly consecutive lines with no other lines in between them.  In
-this case, you can use "``CHECK:``" and "``CHECK-NEXT:``" directives to specify
-this.  If you specified a custom check prefix, just use "``<PREFIX>-NEXT:``".
-For example, something like this works as you'd expect:
-
-.. code-block:: llvm
-
-   define void @t2(<2 x double>* %r, <2 x double>* %A, double %B) {
-       %tmp3 = load <2 x double>* %A, align 16
-       %tmp7 = insertelement <2 x double> undef, double %B, i32 0
-       %tmp9 = shufflevector <2 x double> %tmp3,
-                               <2 x double> %tmp7,
-                               <2 x i32> < i32 0, i32 2 >
-       store <2 x double> %tmp9, <2 x double>* %r, align 16
-       ret void
-
-   ; CHECK:          t2:
-   ; CHECK:            movl    8(%esp), %eax
-   ; CHECK-NEXT:       movapd  (%eax), %xmm0
-   ; CHECK-NEXT:       movhpd  12(%esp), %xmm0
-   ; CHECK-NEXT:       movl    4(%esp), %eax
-   ; CHECK-NEXT:       movapd  %xmm0, (%eax)
-   ; CHECK-NEXT:       ret
-   }
-
-"``CHECK-NEXT:``" directives reject the input unless there is exactly one
-newline between it and the previous directive.  A "``CHECK-NEXT:``" cannot be
-the first directive in a file.
-
-The "CHECK-SAME:" directive
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Sometimes you want to match lines and would like to verify that matches happen
-on the same line as the previous match.  In this case, you can use "``CHECK:``"
-and "``CHECK-SAME:``" directives to specify this.  If you specified a custom
-check prefix, just use "``<PREFIX>-SAME:``".
-
-"``CHECK-SAME:``" is particularly powerful in conjunction with "``CHECK-NOT:``"
-(described below).
-
-For example, the following works like you'd expect:
-
-.. code-block:: llvm
-
-   !0 = !DILocation(line: 5, scope: !1, inlinedAt: !2)
-
-   ; CHECK:       !DILocation(line: 5,
-   ; CHECK-NOT:               column:
-   ; CHECK-SAME:              scope: ![[SCOPE:[0-9]+]]
-
-"``CHECK-SAME:``" directives reject the input if there are any newlines between
-it and the previous directive.  A "``CHECK-SAME:``" cannot be the first
-directive in a file.
-
-The "CHECK-EMPTY:" directive
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-If you need to check that the next line has nothing on it, not even whitespace,
-you can use the "``CHECK-EMPTY:``" directive.
-
-.. code-block:: llvm
-
-   declare void @foo()
-
-   declare void @bar()
-   ; CHECK: foo
-   ; CHECK-EMPTY:
-   ; CHECK-NEXT: bar
-
-Just like "``CHECK-NEXT:``" the directive will fail if there is more than one
-newline before it finds the next blank line, and it cannot be the first
-directive in a file.
-
-The "CHECK-NOT:" directive
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The "``CHECK-NOT:``" directive is used to verify that a string doesn't occur
-between two matches (or before the first match, or after the last match).  For
-example, to verify that a load is removed by a transformation, a test like this
-can be used:
-
-.. code-block:: llvm
-
-   define i8 @coerce_offset0(i32 %V, i32* %P) {
-     store i32 %V, i32* %P
-
-     %P2 = bitcast i32* %P to i8*
-     %P3 = getelementptr i8* %P2, i32 2
-
-     %A = load i8* %P3
-     ret i8 %A
-   ; CHECK: @coerce_offset0
-   ; CHECK-NOT: load
-   ; CHECK: ret i8
-   }
-
-The "CHECK-COUNT:" directive
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-If you need to match multiple lines with the same pattern over and over again
-you can repeat a plain ``CHECK:`` as many times as needed. If that looks too
-boring you can instead use a counted check "``CHECK-COUNT-<num>:``", where
-``<num>`` is a positive decimal number. It will match the pattern exactly
-``<num>`` times, no more and no less. If you specified a custom check prefix,
-just use "``<PREFIX>-COUNT-<num>:``" for the same effect.
-Here is a simple example:
-
-.. code-block:: text
-
-   Loop at depth 1
-   Loop at depth 1
-   Loop at depth 1
-   Loop at depth 1
-     Loop at depth 2
-       Loop at depth 3
-
-   ; CHECK-COUNT-6: Loop at depth {{[0-9]+}}
-   ; CHECK-NOT:     Loop at depth {{[0-9]+}}
-
-The "CHECK-DAG:" directive
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-If it's necessary to match strings that don't occur in a strictly sequential
-order, "``CHECK-DAG:``" could be used to verify them between two matches (or
-before the first match, or after the last match). For example, clang emits
-vtable globals in reverse order. Using ``CHECK-DAG:``, we can keep the checks
-in the natural order:
-
-.. code-block:: c++
-
-    // RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
-
-    struct Foo { virtual void method(); };
-    Foo f;  // emit vtable
-    // CHECK-DAG: @_ZTV3Foo =
-
-    struct Bar { virtual void method(); };
-    Bar b;
-    // CHECK-DAG: @_ZTV3Bar =
-
-``CHECK-NOT:`` directives could be mixed with ``CHECK-DAG:`` directives to
-exclude strings between the surrounding ``CHECK-DAG:`` directives. As a result,
-the surrounding ``CHECK-DAG:`` directives cannot be reordered, i.e. all
-occurrences matching ``CHECK-DAG:`` before ``CHECK-NOT:`` must not fall behind
-occurrences matching ``CHECK-DAG:`` after ``CHECK-NOT:``. For example,
-
-.. code-block:: llvm
-
-   ; CHECK-DAG: BEFORE
-   ; CHECK-NOT: NOT
-   ; CHECK-DAG: AFTER
-
-This case will reject input strings where ``BEFORE`` occurs after ``AFTER``.
-
-With captured variables, ``CHECK-DAG:`` is able to match valid topological
-orderings of a DAG with edges from the definition of a variable to its use.
-It's useful, e.g., when your test cases need to match different output
-sequences from the instruction scheduler. For example,
-
-.. code-block:: llvm
-
-   ; CHECK-DAG: add [[REG1:r[0-9]+]], r1, r2
-   ; CHECK-DAG: add [[REG2:r[0-9]+]], r3, r4
-   ; CHECK:     mul r5, [[REG1]], [[REG2]]
-
-In this case, any order of that two ``add`` instructions will be allowed.
-
-If you are defining `and` using variables in the same ``CHECK-DAG:`` block,
-be aware that the definition rule can match `after` its use.
-
-So, for instance, the code below will pass:
-
-.. code-block:: text
-
-  ; CHECK-DAG: vmov.32 [[REG2:d[0-9]+]][0]
-  ; CHECK-DAG: vmov.32 [[REG2]][1]
-  vmov.32 d0[1]
-  vmov.32 d0[0]
-
-While this other code, will not:
-
-.. code-block:: text
-
-  ; CHECK-DAG: vmov.32 [[REG2:d[0-9]+]][0]
-  ; CHECK-DAG: vmov.32 [[REG2]][1]
-  vmov.32 d1[1]
-  vmov.32 d0[0]
-
-While this can be very useful, it's also dangerous, because in the case of
-register sequence, you must have a strong order (read before write, copy before
-use, etc). If the definition your test is looking for doesn't match (because
-of a bug in the compiler), it may match further away from the use, and mask
-real bugs away.
-
-In those cases, to enforce the order, use a non-DAG directive between DAG-blocks.
-
-A ``CHECK-DAG:`` directive skips matches that overlap the matches of any
-preceding ``CHECK-DAG:`` directives in the same ``CHECK-DAG:`` block.  Not only
-is this non-overlapping behavior consistent with other directives, but it's
-also necessary to handle sets of non-unique strings or patterns.  For example,
-the following directives look for unordered log entries for two tasks in a
-parallel program, such as the OpenMP runtime:
-
-.. code-block:: text
-
-    // CHECK-DAG: [[THREAD_ID:[0-9]+]]: task_begin
-    // CHECK-DAG: [[THREAD_ID]]: task_end
-    //
-    // CHECK-DAG: [[THREAD_ID:[0-9]+]]: task_begin
-    // CHECK-DAG: [[THREAD_ID]]: task_end
-
-The second pair of directives is guaranteed not to match the same log entries
-as the first pair even though the patterns are identical and even if the text
-of the log entries is identical because the thread ID manages to be reused.
-
-The "CHECK-LABEL:" directive
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Sometimes in a file containing multiple tests divided into logical blocks, one
-or more ``CHECK:`` directives may inadvertently succeed by matching lines in a
-later block. While an error will usually eventually be generated, the check
-flagged as causing the error may not actually bear any relationship to the
-actual source of the problem.
-
-In order to produce better error messages in these cases, the "``CHECK-LABEL:``"
-directive can be used. It is treated identically to a normal ``CHECK``
-directive except that FileCheck makes an additional assumption that a line
-matched by the directive cannot also be matched by any other check present in
-``match-filename``; this is intended to be used for lines containing labels or
-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
-
-  define %struct.C* @C_ctor_base(%struct.C* %this, i32 %x) {
-  entry:
-  ; CHECK-LABEL: C_ctor_base:
-  ; CHECK: mov [[SAVETHIS:r[0-9]+]], r0
-  ; CHECK: bl A_ctor_base
-  ; CHECK: mov r0, [[SAVETHIS]]
-    %0 = bitcast %struct.C* %this to %struct.A*
-    %call = tail call %struct.A* @A_ctor_base(%struct.A* %0)
-    %1 = bitcast %struct.C* %this to %struct.B*
-    %call2 = tail call %struct.B* @B_ctor_base(%struct.B* %1, i32 %x)
-    ret %struct.C* %this
-  }
-
-  define %struct.D* @D_ctor_base(%struct.D* %this, i32 %x) {
-  entry:
-  ; CHECK-LABEL: D_ctor_base:
-
-The use of ``CHECK-LABEL:`` directives in this case ensures that the three
-``CHECK:`` directives only accept lines corresponding to the body of the
-``@C_ctor_base`` function, even if the patterns match lines found later in
-the file. Furthermore, if one of these three ``CHECK:`` directives fail,
-FileCheck will recover by continuing to the next block, allowing multiple test
-failures to be detected in a single invocation.
-
-There is no requirement that ``CHECK-LABEL:`` directives contain strings that
-correspond to actual syntactic labels in a source or output language: they must
-simply uniquely match a single line in the file being verified.
-
-``CHECK-LABEL:`` directives cannot contain variable definitions or uses.
-
-FileCheck Regex Matching Syntax
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-All FileCheck directives take a pattern to match.
-For most uses of FileCheck, fixed string matching is perfectly sufficient.  For
-some things, a more flexible form of matching is desired.  To support this,
-FileCheck allows you to specify regular expressions in matching strings,
-surrounded by double braces: ``{{yourregex}}``. FileCheck implements a POSIX
-regular expression matcher; it supports Extended POSIX regular expressions
-(ERE). Because we want to use fixed string matching for a majority of what we
-do, FileCheck has been designed to support mixing and matching fixed string
-matching with regular expressions.  This allows you to write things like this:
-
-.. code-block:: llvm
-
-   ; CHECK: movhpd     {{[0-9]+}}(%esp), {{%xmm[0-7]}}
-
-In this case, any offset from the ESP register will be allowed, and any xmm
-register will be allowed.
-
-Because regular expressions are enclosed with double braces, they are
-visually distinct, and you don't need to use escape characters within the double
-braces like you would in C.  In the rare case that you want to match double
-braces explicitly from the input, you can use something ugly like
-``{{[}][}]}}`` as your pattern.  Or if you are using the repetition count
-syntax, for example ``[[:xdigit:]]{8}`` to match exactly 8 hex digits, you
-would need to add parentheses like this ``{{([[:xdigit:]]{8})}}`` to avoid
-confusion with FileCheck's closing double-brace.
-
-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 string substitution blocks that allow
-string variables to be defined and substituted into patterns.  Here is a simple
-example:
-
-.. code-block:: llvm
-
-   ; CHECK: test5:
-   ; CHECK:    notw    [[REGISTER:%[a-z]+]]
-   ; CHECK:    andw    {{.*}}[[REGISTER]]
-
-The first check line matches a regex ``%[a-z]+`` and captures it into the
-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 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
-
-    ; CHECK: op [[REG:r[0-9]+]], [[REG]]
-
-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 Numeric Substitution Blocks
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-:program:`FileCheck` also supports numeric substitution blocks that allow
-defining numeric variables and checking for numeric values that satisfy a
-numeric expression constraint based on those variables via a numeric
-substitution. 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 define a numeric variable is ``[[#<NUMVAR>:]]`` where
-``<NUMVAR>`` is the name of the numeric variable to define to the matching
-value.
-
-For example:
-
-.. code-block:: llvm
-
-    ; CHECK: mov r[[#REG:]], 42
-
-would match ``mov r5, 42`` and set ``REG`` to the value ``5``.
-
-The syntax of a numeric substitution is ``[[#<expr>]]`` where ``<expr>`` is an
-expression. An expression is recursively defined as:
-
-* a numeric operand, or
-* an expression followed by an operator and a numeric operand.
-
-A numeric operand is a previously defined numeric variable, or an integer
-literal. The supported operators are ``+`` and ``-``. Spaces are accepted
-before, after and between any of these elements.
-
-For example:
-
-.. code-block:: llvm
-
-    ; CHECK: load r[[#REG:]], [r0]
-    ; CHECK: load r[[#REG+1]], [r1]
-
-The above example would match the text:
-
-.. code-block:: gas
-
-    load r5, [r0]
-    load r6, [r1]
-
-but would not match the text:
-
-.. code-block:: gas
-
-    load r5, [r0]
-    load r7, [r1]
-
-due to ``7`` being unequal to ``5 + 1``.
-
-The syntax also supports an empty expression, equivalent to writing {{[0-9]+}},
-for cases where the input must contain a numeric value but the value itself
-does not matter:
-
-.. code-block:: gas
-
-    ; CHECK-NOT: mov r0, r[[#]]
-
-to check that a value is synthesized rather than moved around.
-
-A numeric variable can also be defined to the result of a numeric expression,
-in which case the numeric expression is checked and if verified the variable is
-assigned to the value. The unified syntax for both defining numeric variables
-and checking a numeric expression is thus ``[[#<NUMVAR>: <expr>]]`` with each
-element as described previously.
-
-The ``--enable-var-scope`` option has the same effect on numeric variables as
-on string variables.
-
-Important note: In its current implementation, an expression cannot use a
-numeric variable defined earlier in the same CHECK directive.
-
-FileCheck Pseudo Numeric Variables
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Sometimes there's a need to verify output that contains line numbers of the
-match file, e.g. when testing compiler diagnostics.  This introduces a certain
-fragility of the match file structure, as "``CHECK:``" lines contain absolute
-line numbers in the same file, which have to be updated whenever line numbers
-change due to text addition or deletion.
-
-To support this case, FileCheck expressions understand the ``@LINE`` pseudo
-numeric variable which evaluates to the line number of the CHECK pattern where
-it is found.
-
-This way match patterns can be put near the relevant test lines and include
-relative line number references, for example:
-
-.. code-block:: c++
-
-   // CHECK: test.cpp:[[# @LINE + 4]]:6: error: expected ';' after top level declarator
-   // CHECK-NEXT: {{^int a}}
-   // CHECK-NEXT: {{^     \^}}
-   // CHECK-NEXT: {{^     ;}}
-   int a
-
-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.
-
-Matching Newline Characters
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-To match newline characters in regular expressions the character class
-``[[:space:]]`` can be used. For example, the following pattern:
-
-.. code-block:: c++
-
-   // CHECK: DW_AT_location [DW_FORM_sec_offset] ([[DLOC:0x[0-9a-f]+]]){{[[:space:]].*}}"intd"
-
-matches output of the form (from llvm-dwarfdump):
-
-.. code-block:: text
-
-       DW_AT_location [DW_FORM_sec_offset]   (0x00000233)
-       DW_AT_name [DW_FORM_strp]  ( .debug_str[0x000000c9] = "intd")
-
-letting us set the :program:`FileCheck` variable ``DLOC`` to the desired value 
-``0x00000233``, extracted from the line immediately preceding "``intd``".
+FileCheck - Flexible pattern matching file verifier\r
+===================================================\r
+\r
+.. program:: FileCheck\r
+\r
+SYNOPSIS\r
+--------\r
+\r
+:program:`FileCheck` *match-filename* [*--check-prefix=XXX*] [*--strict-whitespace*]\r
+\r
+DESCRIPTION\r
+-----------\r
+\r
+:program:`FileCheck` reads two files (one from standard input, and one\r
+specified on the command line) and uses one to verify the other.  This\r
+behavior is particularly useful for the testsuite, which wants to verify that\r
+the output of some tool (e.g. :program:`llc`) contains the expected information\r
+(for example, a movsd from esp or whatever is interesting).  This is similar to\r
+using :program:`grep`, but it is optimized for matching multiple different\r
+inputs in one file in a specific order.\r
+\r
+The ``match-filename`` file specifies the file that contains the patterns to\r
+match.  The file to verify is read from standard input unless the\r
+:option:`--input-file` option is used.\r
+\r
+OPTIONS\r
+-------\r
+\r
+Options are parsed from the environment variable ``FILECHECK_OPTS``\r
+and from the command line.\r
+\r
+.. option:: -help\r
+\r
+ Print a summary of command line options.\r
+\r
+.. option:: --check-prefix prefix\r
+\r
+ FileCheck searches the contents of ``match-filename`` for patterns to\r
+ match.  By default, these patterns are prefixed with "``CHECK:``".\r
+ If you'd like to use a different prefix (e.g. because the same input\r
+ file is checking multiple different tool or options), the\r
+ :option:`--check-prefix` argument allows you to specify one or more\r
+ prefixes to match. Multiple prefixes are useful for tests which might\r
+ change for different run options, but most lines remain the same.\r
+\r
+.. option:: --check-prefixes prefix1,prefix2,...\r
+\r
+ An alias of :option:`--check-prefix` that allows multiple prefixes to be\r
+ specified as a comma separated list.\r
+\r
+.. option:: --input-file filename\r
+\r
+  File to check (defaults to stdin).\r
+\r
+.. option:: --match-full-lines\r
+\r
+ By default, FileCheck allows matches of anywhere on a line. This\r
+ option will require all positive matches to cover an entire\r
+ line. Leading and trailing whitespace is ignored, unless\r
+ :option:`--strict-whitespace` is also specified. (Note: negative\r
+ matches from ``CHECK-NOT`` are not affected by this option!)\r
+\r
+ Passing this option is equivalent to inserting ``{{^ *}}`` or\r
+ ``{{^}}`` before, and ``{{ *$}}`` or ``{{$}}`` after every positive\r
+ check pattern.\r
+\r
+.. option:: --strict-whitespace\r
+\r
+ By default, FileCheck canonicalizes input horizontal whitespace (spaces and\r
+ tabs) which causes it to ignore these differences (a space will match a tab).\r
+ The :option:`--strict-whitespace` argument disables this behavior. End-of-line\r
+ sequences are canonicalized to UNIX-style ``\n`` in all modes.\r
+\r
+.. option:: --ignore-case\r
+\r
+  By default, FileCheck uses case-sensitive matching. This option causes\r
+  FileCheck to use case-insensitive matching.\r
+\r
+.. option:: --implicit-check-not check-pattern\r
+\r
+  Adds implicit negative checks for the specified patterns between positive\r
+  checks. The option allows writing stricter tests without stuffing them with\r
+  ``CHECK-NOT``\ s.\r
+\r
+  For example, "``--implicit-check-not warning:``" can be useful when testing\r
+  diagnostic messages from tools that don't have an option similar to ``clang\r
+  -verify``. With this option FileCheck will verify that input does not contain\r
+  warnings not covered by any ``CHECK:`` patterns.\r
+\r
+.. option:: --dump-input <mode>\r
+\r
+  Dump input to stderr, adding annotations representing currently enabled\r
+  diagnostics.  Do this either 'always', on 'fail', or 'never'.  Specify 'help'\r
+  to explain the dump format and quit.\r
+\r
+.. option:: --dump-input-on-failure\r
+\r
+  When the check fails, dump all of the original input.  This option is\r
+  deprecated in favor of `--dump-input=fail`.\r
+\r
+.. option:: --enable-var-scope\r
+\r
+  Enables scope for regex variables.\r
+\r
+  Variables with names that start with ``$`` are considered global and\r
+  remain set throughout the file.\r
+\r
+  All other variables get undefined after each encountered ``CHECK-LABEL``.\r
+\r
+.. option:: -D<VAR=VALUE>\r
+\r
+  Sets a filecheck pattern variable ``VAR`` with value ``VALUE`` that can be\r
+  used in ``CHECK:`` lines.\r
+\r
+.. option:: -D#<NUMVAR>=<NUMERIC EXPRESSION>\r
+\r
+  Sets a filecheck numeric variable ``NUMVAR`` to the result of evaluating\r
+  ``<NUMERIC EXPRESSION>`` that can be used in ``CHECK:`` lines. See section\r
+  ``FileCheck Numeric Variables and Expressions`` for details on supported\r
+  numeric expressions.\r
+\r
+.. option:: -version\r
+\r
+ Show the version number of this program.\r
+\r
+.. option:: -v\r
+\r
+  Print good directive pattern matches.  However, if ``-input-dump=fail`` or\r
+  ``-input-dump=always``, add those matches as input annotations instead.\r
+\r
+.. option:: -vv\r
+\r
+  Print information helpful in diagnosing internal FileCheck issues, such as\r
+  discarded overlapping ``CHECK-DAG:`` matches, implicit EOF pattern matches,\r
+  and ``CHECK-NOT:`` patterns that do not have matches.  Implies ``-v``.\r
+  However, if ``-input-dump=fail`` or ``-input-dump=always``, just add that\r
+  information as input annotations instead.\r
+\r
+.. option:: --allow-deprecated-dag-overlap\r
+\r
+  Enable overlapping among matches in a group of consecutive ``CHECK-DAG:``\r
+  directives.  This option is deprecated and is only provided for convenience\r
+  as old tests are migrated to the new non-overlapping ``CHECK-DAG:``\r
+  implementation.\r
+\r
+.. option:: --color\r
+\r
+  Use colors in output (autodetected by default).\r
+\r
+EXIT STATUS\r
+-----------\r
+\r
+If :program:`FileCheck` verifies that the file matches the expected contents,\r
+it exits with 0.  Otherwise, if not, or if an error occurs, it will exit with a\r
+non-zero value.\r
+\r
+TUTORIAL\r
+--------\r
+\r
+FileCheck is typically used from LLVM regression tests, being invoked on the RUN\r
+line of the test.  A simple example of using FileCheck from a RUN line looks\r
+like this:\r
+\r
+.. code-block:: llvm\r
+\r
+   ; RUN: llvm-as < %s | llc -march=x86-64 | FileCheck %s\r
+\r
+This syntax says to pipe the current file ("``%s``") into ``llvm-as``, pipe\r
+that into ``llc``, then pipe the output of ``llc`` into ``FileCheck``.  This\r
+means that FileCheck will be verifying its standard input (the llc output)\r
+against the filename argument specified (the original ``.ll`` file specified by\r
+"``%s``").  To see how this works, let's look at the rest of the ``.ll`` file\r
+(after the RUN line):\r
+\r
+.. code-block:: llvm\r
+\r
+   define void @sub1(i32* %p, i32 %v) {\r
+   entry:\r
+   ; CHECK: sub1:\r
+   ; CHECK: subl\r
+           %0 = tail call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %p, i32 %v)\r
+           ret void\r
+   }\r
+\r
+   define void @inc4(i64* %p) {\r
+   entry:\r
+   ; CHECK: inc4:\r
+   ; CHECK: incq\r
+           %0 = tail call i64 @llvm.atomic.load.add.i64.p0i64(i64* %p, i64 1)\r
+           ret void\r
+   }\r
+\r
+Here you can see some "``CHECK:``" lines specified in comments.  Now you can\r
+see how the file is piped into ``llvm-as``, then ``llc``, and the machine code\r
+output is what we are verifying.  FileCheck checks the machine code output to\r
+verify that it matches what the "``CHECK:``" lines specify.\r
+\r
+The syntax of the "``CHECK:``" lines is very simple: they are fixed strings that\r
+must occur in order.  FileCheck defaults to ignoring horizontal whitespace\r
+differences (e.g. a space is allowed to match a tab) but otherwise, the contents\r
+of the "``CHECK:``" line is required to match some thing in the test file exactly.\r
+\r
+One nice thing about FileCheck (compared to grep) is that it allows merging\r
+test cases together into logical groups.  For example, because the test above\r
+is checking for the "``sub1:``" and "``inc4:``" labels, it will not match\r
+unless there is a "``subl``" in between those labels.  If it existed somewhere\r
+else in the file, that would not count: "``grep subl``" matches if "``subl``"\r
+exists anywhere in the file.\r
+\r
+The FileCheck -check-prefix option\r
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+\r
+The FileCheck `-check-prefix` option allows multiple test\r
+configurations to be driven from one `.ll` file.  This is useful in many\r
+circumstances, for example, testing different architectural variants with\r
+:program:`llc`.  Here's a simple example:\r
+\r
+.. code-block:: llvm\r
+\r
+   ; RUN: llvm-as < %s | llc -mtriple=i686-apple-darwin9 -mattr=sse41 \\r
+   ; RUN:              | FileCheck %s -check-prefix=X32\r
+   ; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin9 -mattr=sse41 \\r
+   ; RUN:              | FileCheck %s -check-prefix=X64\r
+\r
+   define <4 x i32> @pinsrd_1(i32 %s, <4 x i32> %tmp) nounwind {\r
+           %tmp1 = insertelement <4 x i32>; %tmp, i32 %s, i32 1\r
+           ret <4 x i32> %tmp1\r
+   ; X32: pinsrd_1:\r
+   ; X32:    pinsrd $1, 4(%esp), %xmm0\r
+\r
+   ; X64: pinsrd_1:\r
+   ; X64:    pinsrd $1, %edi, %xmm0\r
+   }\r
+\r
+In this case, we're testing that we get the expected code generation with\r
+both 32-bit and 64-bit code generation.\r
+\r
+The "CHECK-NEXT:" directive\r
+~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+\r
+Sometimes you want to match lines and would like to verify that matches\r
+happen on exactly consecutive lines with no other lines in between them.  In\r
+this case, you can use "``CHECK:``" and "``CHECK-NEXT:``" directives to specify\r
+this.  If you specified a custom check prefix, just use "``<PREFIX>-NEXT:``".\r
+For example, something like this works as you'd expect:\r
+\r
+.. code-block:: llvm\r
+\r
+   define void @t2(<2 x double>* %r, <2 x double>* %A, double %B) {\r
+       %tmp3 = load <2 x double>* %A, align 16\r
+       %tmp7 = insertelement <2 x double> undef, double %B, i32 0\r
+       %tmp9 = shufflevector <2 x double> %tmp3,\r
+                               <2 x double> %tmp7,\r
+                               <2 x i32> < i32 0, i32 2 >\r
+       store <2 x double> %tmp9, <2 x double>* %r, align 16\r
+       ret void\r
+\r
+   ; CHECK:          t2:\r
+   ; CHECK:            movl    8(%esp), %eax\r
+   ; CHECK-NEXT:       movapd  (%eax), %xmm0\r
+   ; CHECK-NEXT:       movhpd  12(%esp), %xmm0\r
+   ; CHECK-NEXT:       movl    4(%esp), %eax\r
+   ; CHECK-NEXT:       movapd  %xmm0, (%eax)\r
+   ; CHECK-NEXT:       ret\r
+   }\r
+\r
+"``CHECK-NEXT:``" directives reject the input unless there is exactly one\r
+newline between it and the previous directive.  A "``CHECK-NEXT:``" cannot be\r
+the first directive in a file.\r
+\r
+The "CHECK-SAME:" directive\r
+~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+\r
+Sometimes you want to match lines and would like to verify that matches happen\r
+on the same line as the previous match.  In this case, you can use "``CHECK:``"\r
+and "``CHECK-SAME:``" directives to specify this.  If you specified a custom\r
+check prefix, just use "``<PREFIX>-SAME:``".\r
+\r
+"``CHECK-SAME:``" is particularly powerful in conjunction with "``CHECK-NOT:``"\r
+(described below).\r
+\r
+For example, the following works like you'd expect:\r
+\r
+.. code-block:: llvm\r
+\r
+   !0 = !DILocation(line: 5, scope: !1, inlinedAt: !2)\r
+\r
+   ; CHECK:       !DILocation(line: 5,\r
+   ; CHECK-NOT:               column:\r
+   ; CHECK-SAME:              scope: ![[SCOPE:[0-9]+]]\r
+\r
+"``CHECK-SAME:``" directives reject the input if there are any newlines between\r
+it and the previous directive.  A "``CHECK-SAME:``" cannot be the first\r
+directive in a file.\r
+\r
+The "CHECK-EMPTY:" directive\r
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+\r
+If you need to check that the next line has nothing on it, not even whitespace,\r
+you can use the "``CHECK-EMPTY:``" directive.\r
+\r
+.. code-block:: llvm\r
+\r
+   declare void @foo()\r
+\r
+   declare void @bar()\r
+   ; CHECK: foo\r
+   ; CHECK-EMPTY:\r
+   ; CHECK-NEXT: bar\r
+\r
+Just like "``CHECK-NEXT:``" the directive will fail if there is more than one\r
+newline before it finds the next blank line, and it cannot be the first\r
+directive in a file.\r
+\r
+The "CHECK-NOT:" directive\r
+~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+\r
+The "``CHECK-NOT:``" directive is used to verify that a string doesn't occur\r
+between two matches (or before the first match, or after the last match).  For\r
+example, to verify that a load is removed by a transformation, a test like this\r
+can be used:\r
+\r
+.. code-block:: llvm\r
+\r
+   define i8 @coerce_offset0(i32 %V, i32* %P) {\r
+     store i32 %V, i32* %P\r
+\r
+     %P2 = bitcast i32* %P to i8*\r
+     %P3 = getelementptr i8* %P2, i32 2\r
+\r
+     %A = load i8* %P3\r
+     ret i8 %A\r
+   ; CHECK: @coerce_offset0\r
+   ; CHECK-NOT: load\r
+   ; CHECK: ret i8\r
+   }\r
+\r
+The "CHECK-COUNT:" directive\r
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+\r
+If you need to match multiple lines with the same pattern over and over again\r
+you can repeat a plain ``CHECK:`` as many times as needed. If that looks too\r
+boring you can instead use a counted check "``CHECK-COUNT-<num>:``", where\r
+``<num>`` is a positive decimal number. It will match the pattern exactly\r
+``<num>`` times, no more and no less. If you specified a custom check prefix,\r
+just use "``<PREFIX>-COUNT-<num>:``" for the same effect.\r
+Here is a simple example:\r
+\r
+.. code-block:: text\r
+\r
+   Loop at depth 1\r
+   Loop at depth 1\r
+   Loop at depth 1\r
+   Loop at depth 1\r
+     Loop at depth 2\r
+       Loop at depth 3\r
+\r
+   ; CHECK-COUNT-6: Loop at depth {{[0-9]+}}\r
+   ; CHECK-NOT:     Loop at depth {{[0-9]+}}\r
+\r
+The "CHECK-DAG:" directive\r
+~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+\r
+If it's necessary to match strings that don't occur in a strictly sequential\r
+order, "``CHECK-DAG:``" could be used to verify them between two matches (or\r
+before the first match, or after the last match). For example, clang emits\r
+vtable globals in reverse order. Using ``CHECK-DAG:``, we can keep the checks\r
+in the natural order:\r
+\r
+.. code-block:: c++\r
+\r
+    // RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s\r
+\r
+    struct Foo { virtual void method(); };\r
+    Foo f;  // emit vtable\r
+    // CHECK-DAG: @_ZTV3Foo =\r
+\r
+    struct Bar { virtual void method(); };\r
+    Bar b;\r
+    // CHECK-DAG: @_ZTV3Bar =\r
+\r
+``CHECK-NOT:`` directives could be mixed with ``CHECK-DAG:`` directives to\r
+exclude strings between the surrounding ``CHECK-DAG:`` directives. As a result,\r
+the surrounding ``CHECK-DAG:`` directives cannot be reordered, i.e. all\r
+occurrences matching ``CHECK-DAG:`` before ``CHECK-NOT:`` must not fall behind\r
+occurrences matching ``CHECK-DAG:`` after ``CHECK-NOT:``. For example,\r
+\r
+.. code-block:: llvm\r
+\r
+   ; CHECK-DAG: BEFORE\r
+   ; CHECK-NOT: NOT\r
+   ; CHECK-DAG: AFTER\r
+\r
+This case will reject input strings where ``BEFORE`` occurs after ``AFTER``.\r
+\r
+With captured variables, ``CHECK-DAG:`` is able to match valid topological\r
+orderings of a DAG with edges from the definition of a variable to its use.\r
+It's useful, e.g., when your test cases need to match different output\r
+sequences from the instruction scheduler. For example,\r
+\r
+.. code-block:: llvm\r
+\r
+   ; CHECK-DAG: add [[REG1:r[0-9]+]], r1, r2\r
+   ; CHECK-DAG: add [[REG2:r[0-9]+]], r3, r4\r
+   ; CHECK:     mul r5, [[REG1]], [[REG2]]\r
+\r
+In this case, any order of that two ``add`` instructions will be allowed.\r
+\r
+If you are defining `and` using variables in the same ``CHECK-DAG:`` block,\r
+be aware that the definition rule can match `after` its use.\r
+\r
+So, for instance, the code below will pass:\r
+\r
+.. code-block:: text\r
+\r
+  ; CHECK-DAG: vmov.32 [[REG2:d[0-9]+]][0]\r
+  ; CHECK-DAG: vmov.32 [[REG2]][1]\r
+  vmov.32 d0[1]\r
+  vmov.32 d0[0]\r
+\r
+While this other code, will not:\r
+\r
+.. code-block:: text\r
+\r
+  ; CHECK-DAG: vmov.32 [[REG2:d[0-9]+]][0]\r
+  ; CHECK-DAG: vmov.32 [[REG2]][1]\r
+  vmov.32 d1[1]\r
+  vmov.32 d0[0]\r
+\r
+While this can be very useful, it's also dangerous, because in the case of\r
+register sequence, you must have a strong order (read before write, copy before\r
+use, etc). If the definition your test is looking for doesn't match (because\r
+of a bug in the compiler), it may match further away from the use, and mask\r
+real bugs away.\r
+\r
+In those cases, to enforce the order, use a non-DAG directive between DAG-blocks.\r
+\r
+A ``CHECK-DAG:`` directive skips matches that overlap the matches of any\r
+preceding ``CHECK-DAG:`` directives in the same ``CHECK-DAG:`` block.  Not only\r
+is this non-overlapping behavior consistent with other directives, but it's\r
+also necessary to handle sets of non-unique strings or patterns.  For example,\r
+the following directives look for unordered log entries for two tasks in a\r
+parallel program, such as the OpenMP runtime:\r
+\r
+.. code-block:: text\r
+\r
+    // CHECK-DAG: [[THREAD_ID:[0-9]+]]: task_begin\r
+    // CHECK-DAG: [[THREAD_ID]]: task_end\r
+    //\r
+    // CHECK-DAG: [[THREAD_ID:[0-9]+]]: task_begin\r
+    // CHECK-DAG: [[THREAD_ID]]: task_end\r
+\r
+The second pair of directives is guaranteed not to match the same log entries\r
+as the first pair even though the patterns are identical and even if the text\r
+of the log entries is identical because the thread ID manages to be reused.\r
+\r
+The "CHECK-LABEL:" directive\r
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+\r
+Sometimes in a file containing multiple tests divided into logical blocks, one\r
+or more ``CHECK:`` directives may inadvertently succeed by matching lines in a\r
+later block. While an error will usually eventually be generated, the check\r
+flagged as causing the error may not actually bear any relationship to the\r
+actual source of the problem.\r
+\r
+In order to produce better error messages in these cases, the "``CHECK-LABEL:``"\r
+directive can be used. It is treated identically to a normal ``CHECK``\r
+directive except that FileCheck makes an additional assumption that a line\r
+matched by the directive cannot also be matched by any other check present in\r
+``match-filename``; this is intended to be used for lines containing labels or\r
+other unique identifiers. Conceptually, the presence of ``CHECK-LABEL`` divides\r
+the input stream into separate blocks, each of which is processed independently,\r
+preventing a ``CHECK:`` directive in one block matching a line in another block.\r
+If ``--enable-var-scope`` is in effect, all local variables are cleared at the\r
+beginning of the block.\r
+\r
+For example,\r
+\r
+.. code-block:: llvm\r
+\r
+  define %struct.C* @C_ctor_base(%struct.C* %this, i32 %x) {\r
+  entry:\r
+  ; CHECK-LABEL: C_ctor_base:\r
+  ; CHECK: mov [[SAVETHIS:r[0-9]+]], r0\r
+  ; CHECK: bl A_ctor_base\r
+  ; CHECK: mov r0, [[SAVETHIS]]\r
+    %0 = bitcast %struct.C* %this to %struct.A*\r
+    %call = tail call %struct.A* @A_ctor_base(%struct.A* %0)\r
+    %1 = bitcast %struct.C* %this to %struct.B*\r
+    %call2 = tail call %struct.B* @B_ctor_base(%struct.B* %1, i32 %x)\r
+    ret %struct.C* %this\r
+  }\r
+\r
+  define %struct.D* @D_ctor_base(%struct.D* %this, i32 %x) {\r
+  entry:\r
+  ; CHECK-LABEL: D_ctor_base:\r
+\r
+The use of ``CHECK-LABEL:`` directives in this case ensures that the three\r
+``CHECK:`` directives only accept lines corresponding to the body of the\r
+``@C_ctor_base`` function, even if the patterns match lines found later in\r
+the file. Furthermore, if one of these three ``CHECK:`` directives fail,\r
+FileCheck will recover by continuing to the next block, allowing multiple test\r
+failures to be detected in a single invocation.\r
+\r
+There is no requirement that ``CHECK-LABEL:`` directives contain strings that\r
+correspond to actual syntactic labels in a source or output language: they must\r
+simply uniquely match a single line in the file being verified.\r
+\r
+``CHECK-LABEL:`` directives cannot contain variable definitions or uses.\r
+\r
+FileCheck Regex Matching Syntax\r
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+\r
+All FileCheck directives take a pattern to match.\r
+For most uses of FileCheck, fixed string matching is perfectly sufficient.  For\r
+some things, a more flexible form of matching is desired.  To support this,\r
+FileCheck allows you to specify regular expressions in matching strings,\r
+surrounded by double braces: ``{{yourregex}}``. FileCheck implements a POSIX\r
+regular expression matcher; it supports Extended POSIX regular expressions\r
+(ERE). Because we want to use fixed string matching for a majority of what we\r
+do, FileCheck has been designed to support mixing and matching fixed string\r
+matching with regular expressions.  This allows you to write things like this:\r
+\r
+.. code-block:: llvm\r
+\r
+   ; CHECK: movhpd     {{[0-9]+}}(%esp), {{%xmm[0-7]}}\r
+\r
+In this case, any offset from the ESP register will be allowed, and any xmm\r
+register will be allowed.\r
+\r
+Because regular expressions are enclosed with double braces, they are\r
+visually distinct, and you don't need to use escape characters within the double\r
+braces like you would in C.  In the rare case that you want to match double\r
+braces explicitly from the input, you can use something ugly like\r
+``{{[}][}]}}`` as your pattern.  Or if you are using the repetition count\r
+syntax, for example ``[[:xdigit:]]{8}`` to match exactly 8 hex digits, you\r
+would need to add parentheses like this ``{{([[:xdigit:]]{8})}}`` to avoid\r
+confusion with FileCheck's closing double-brace.\r
+\r
+FileCheck String Substitution Blocks\r
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+\r
+It is often useful to match a pattern and then verify that it occurs again\r
+later in the file.  For codegen tests, this can be useful to allow any\r
+register, but verify that that register is used consistently later.  To do\r
+this, :program:`FileCheck` supports string substitution blocks that allow\r
+string variables to be defined and substituted into patterns.  Here is a simple\r
+example:\r
+\r
+.. code-block:: llvm\r
+\r
+   ; CHECK: test5:\r
+   ; CHECK:    notw    [[REGISTER:%[a-z]+]]\r
+   ; CHECK:    andw    {{.*}}[[REGISTER]]\r
+\r
+The first check line matches a regex ``%[a-z]+`` and captures it into the\r
+string variable ``REGISTER``.  The second line verifies that whatever is in\r
+``REGISTER`` occurs later in the file after an "``andw``". :program:`FileCheck`\r
+string substitution blocks are always contained in ``[[ ]]`` pairs, and string\r
+variable names can be formed with the regex ``[a-zA-Z_][a-zA-Z0-9_]*``.  If a\r
+colon follows the name, then it is a definition of the variable; otherwise, it\r
+is a substitution.\r
+\r
+:program:`FileCheck` variables can be defined multiple times, and substitutions\r
+always get the latest value.  Variables can also be substituted later on the\r
+same line they were defined on. For example:\r
+\r
+.. code-block:: llvm\r
+\r
+    ; CHECK: op [[REG:r[0-9]+]], [[REG]]\r
+\r
+Can be useful if you want the operands of ``op`` to be the same register,\r
+and don't care exactly which register it is.\r
+\r
+If ``--enable-var-scope`` is in effect, variables with names that\r
+start with ``$`` are considered to be global. All others variables are\r
+local.  All local variables get undefined at the beginning of each\r
+CHECK-LABEL block. Global variables are not affected by CHECK-LABEL.\r
+This makes it easier to ensure that individual tests are not affected\r
+by variables set in preceding tests.\r
+\r
+FileCheck Numeric Substitution Blocks\r
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+\r
+:program:`FileCheck` also supports numeric substitution blocks that allow\r
+defining numeric variables and checking for numeric values that satisfy a\r
+numeric expression constraint based on those variables via a numeric\r
+substitution. This allows ``CHECK:`` directives to verify a numeric relation\r
+between two numbers, such as the need for consecutive registers to be used.\r
+\r
+The syntax to define a numeric variable is ``[[#<NUMVAR>:]]`` where\r
+``<NUMVAR>`` is the name of the numeric variable to define to the matching\r
+value.\r
+\r
+For example:\r
+\r
+.. code-block:: llvm\r
+\r
+    ; CHECK: mov r[[#REG:]], 42\r
+\r
+would match ``mov r5, 42`` and set ``REG`` to the value ``5``.\r
+\r
+The syntax of a numeric substitution is ``[[#<expr>]]`` where ``<expr>`` is an\r
+expression. An expression is recursively defined as:\r
+\r
+* a numeric operand, or\r
+* an expression followed by an operator and a numeric operand.\r
+\r
+A numeric operand is a previously defined numeric variable, or an integer\r
+literal. The supported operators are ``+`` and ``-``. Spaces are accepted\r
+before, after and between any of these elements.\r
+\r
+For example:\r
+\r
+.. code-block:: llvm\r
+\r
+    ; CHECK: load r[[#REG:]], [r0]\r
+    ; CHECK: load r[[#REG+1]], [r1]\r
+\r
+The above example would match the text:\r
+\r
+.. code-block:: gas\r
+\r
+    load r5, [r0]\r
+    load r6, [r1]\r
+\r
+but would not match the text:\r
+\r
+.. code-block:: gas\r
+\r
+    load r5, [r0]\r
+    load r7, [r1]\r
+\r
+due to ``7`` being unequal to ``5 + 1``.\r
+\r
+The syntax also supports an empty expression, equivalent to writing {{[0-9]+}},\r
+for cases where the input must contain a numeric value but the value itself\r
+does not matter:\r
+\r
+.. code-block:: gas\r
+\r
+    ; CHECK-NOT: mov r0, r[[#]]\r
+\r
+to check that a value is synthesized rather than moved around.\r
+\r
+A numeric variable can also be defined to the result of a numeric expression,\r
+in which case the numeric expression is checked and if verified the variable is\r
+assigned to the value. The unified syntax for both defining numeric variables\r
+and checking a numeric expression is thus ``[[#<NUMVAR>: <expr>]]`` with each\r
+element as described previously.\r
+\r
+The ``--enable-var-scope`` option has the same effect on numeric variables as\r
+on string variables.\r
+\r
+Important note: In its current implementation, an expression cannot use a\r
+numeric variable defined earlier in the same CHECK directive.\r
+\r
+FileCheck Pseudo Numeric Variables\r
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+\r
+Sometimes there's a need to verify output that contains line numbers of the\r
+match file, e.g. when testing compiler diagnostics.  This introduces a certain\r
+fragility of the match file structure, as "``CHECK:``" lines contain absolute\r
+line numbers in the same file, which have to be updated whenever line numbers\r
+change due to text addition or deletion.\r
+\r
+To support this case, FileCheck expressions understand the ``@LINE`` pseudo\r
+numeric variable which evaluates to the line number of the CHECK pattern where\r
+it is found.\r
+\r
+This way match patterns can be put near the relevant test lines and include\r
+relative line number references, for example:\r
+\r
+.. code-block:: c++\r
+\r
+   // CHECK: test.cpp:[[# @LINE + 4]]:6: error: expected ';' after top level declarator\r
+   // CHECK-NEXT: {{^int a}}\r
+   // CHECK-NEXT: {{^     \^}}\r
+   // CHECK-NEXT: {{^     ;}}\r
+   int a\r
+\r
+To support legacy uses of ``@LINE`` as a special string variable,\r
+:program:`FileCheck` also accepts the following uses of ``@LINE`` with string\r
+substitution block syntax: ``[[@LINE]]``, ``[[@LINE+<offset>]]`` and\r
+``[[@LINE-<offset>]]`` without any spaces inside the brackets and where\r
+``offset`` is an integer.\r
+\r
+Matching Newline Characters\r
+~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+\r
+To match newline characters in regular expressions the character class\r
+``[[:space:]]`` can be used. For example, the following pattern:\r
+\r
+.. code-block:: c++\r
+\r
+   // CHECK: DW_AT_location [DW_FORM_sec_offset] ([[DLOC:0x[0-9a-f]+]]){{[[:space:]].*}}"intd"\r
+\r
+matches output of the form (from llvm-dwarfdump):\r
+\r
+.. code-block:: text\r
+\r
+       DW_AT_location [DW_FORM_sec_offset]   (0x00000233)\r
+       DW_AT_name [DW_FORM_strp]  ( .debug_str[0x000000c9] = "intd")\r
+\r
+letting us set the :program:`FileCheck` variable ``DLOC`` to the desired value \r
+``0x00000233``, extracted from the line immediately preceding "``intd``".\r
index 5c6585ed76f758727cfac83e287f09364394c10b..dc6dc7496af1fb03490e4e2fa783715014fb376b 100644 (file)
-//==-- llvm/Support/FileCheck.h ---------------------------*- C++ -*-==//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-/// \file This file has some utilities to use FileCheck as an API
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_SUPPORT_FILECHECK_H
-#define LLVM_SUPPORT_FILECHECK_H
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Regex.h"
-#include "llvm/Support/SourceMgr.h"
-#include <string>
-#include <vector>
-
-namespace llvm {
-
-/// Contains info about various FileCheck options.
-struct FileCheckRequest {
-  std::vector<std::string> CheckPrefixes;
-  bool NoCanonicalizeWhiteSpace = false;
-  std::vector<std::string> ImplicitCheckNot;
-  std::vector<std::string> GlobalDefines;
-  bool AllowEmptyInput = false;
-  bool MatchFullLines = false;
-  bool EnableVarScope = false;
-  bool AllowDeprecatedDagOverlap = false;
-  bool Verbose = false;
-  bool VerboseVerbose = false;
-};
-
-//===----------------------------------------------------------------------===//
-// Summary of a FileCheck diagnostic.
-//===----------------------------------------------------------------------===//
-
-namespace Check {
-
-enum FileCheckKind {
-  CheckNone = 0,
-  CheckPlain,
-  CheckNext,
-  CheckSame,
-  CheckNot,
-  CheckDAG,
-  CheckLabel,
-  CheckEmpty,
-
-  /// Indicates the pattern only matches the end of file. This is used for
-  /// trailing CHECK-NOTs.
-  CheckEOF,
-
-  /// Marks when parsing found a -NOT check combined with another CHECK suffix.
-  CheckBadNot,
-
-  /// Marks when parsing found a -COUNT directive with invalid count value.
-  CheckBadCount
-};
-
-class FileCheckType {
-  FileCheckKind Kind;
-  int Count; ///< optional Count for some checks
-
-public:
-  FileCheckType(FileCheckKind Kind = CheckNone) : Kind(Kind), Count(1) {}
-  FileCheckType(const FileCheckType &) = default;
-
-  operator FileCheckKind() const { return Kind; }
-
-  int getCount() const { return Count; }
-  FileCheckType &setCount(int C);
-
-  // \returns a description of \p Prefix.
-  std::string getDescription(StringRef Prefix) const;
-};
-} // namespace Check
-
-struct FileCheckDiag {
-  /// What is the FileCheck directive for this diagnostic?
-  Check::FileCheckType CheckTy;
-  /// Where is the FileCheck directive for this diagnostic?
-  unsigned CheckLine, CheckCol;
-  /// What type of match result does this diagnostic describe?
-  ///
-  /// A directive's supplied pattern is said to be either expected or excluded
-  /// depending on whether the pattern must have or must not have a match in
-  /// order for the directive to succeed.  For example, a CHECK directive's
-  /// pattern is expected, and a CHECK-NOT directive's pattern is excluded.
-  /// All match result types whose names end with "Excluded" are for excluded
-  /// patterns, and all others are for expected patterns.
-  ///
-  /// There might be more than one match result for a single pattern.  For
-  /// example, there might be several discarded matches
-  /// (MatchFoundButDiscarded) before either a good match
-  /// (MatchFoundAndExpected) or a failure to match (MatchNoneButExpected),
-  /// and there might be a fuzzy match (MatchFuzzy) after the latter.
-  enum MatchType {
-    /// Indicates a good match for an expected pattern.
-    MatchFoundAndExpected,
-    /// Indicates a match for an excluded pattern.
-    MatchFoundButExcluded,
-    /// Indicates a match for an expected pattern, but the match is on the
-    /// wrong line.
-    MatchFoundButWrongLine,
-    /// Indicates a discarded match for an expected pattern.
-    MatchFoundButDiscarded,
-    /// Indicates no match for an excluded pattern.
-    MatchNoneAndExcluded,
-    /// Indicates no match for an expected pattern, but this might follow good
-    /// matches when multiple matches are expected for the pattern, or it might
-    /// follow discarded matches for the pattern.
-    MatchNoneButExpected,
-    /// Indicates a fuzzy match that serves as a suggestion for the next
-    /// intended match for an expected pattern with too few or no good matches.
-    MatchFuzzy,
-  } MatchTy;
-  /// The search range if MatchTy is MatchNoneAndExcluded or
-  /// MatchNoneButExpected, or the match range otherwise.
-  unsigned InputStartLine;
-  unsigned InputStartCol;
-  unsigned InputEndLine;
-  unsigned InputEndCol;
-  FileCheckDiag(const SourceMgr &SM, const Check::FileCheckType &CheckTy,
-                SMLoc CheckLoc, MatchType MatchTy, SMRange InputRange);
-};
-
-class FileCheckPatternContext;
-struct FileCheckString;
-
-/// FileCheck class takes the request and exposes various methods that
-/// use information from the request.
-class FileCheck {
-  FileCheckRequest Req;
-  std::unique_ptr<FileCheckPatternContext> PatternContext;
-  // C++17 TODO: make this a plain std::vector.
-  std::unique_ptr<std::vector<FileCheckString>> CheckStrings;
-
-public:
-  explicit FileCheck(FileCheckRequest Req);
-  ~FileCheck();
-
-  // Combines the check prefixes into a single regex so that we can efficiently
-  // scan for any of the set.
-  //
-  // The semantics are that the longest-match wins which matches our regex
-  // library.
-  Regex buildCheckPrefixRegex();
-
-  /// Reads the check file from \p Buffer and records the expected strings it
-  /// contains. Errors are reported against \p SM.
-  ///
-  /// Only expected strings whose prefix is one of those listed in \p PrefixRE
-  /// are recorded. \returns true in case of an error, false otherwise.
-  bool readCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE);
-
-  bool ValidateCheckPrefixes();
-
-  /// Canonicalizes whitespaces in the file. Line endings are replaced with
-  /// UNIX-style '\n'.
-  StringRef CanonicalizeFile(MemoryBuffer &MB,
-                             SmallVectorImpl<char> &OutputBuffer);
-
-  /// Checks the input to FileCheck provided in the \p Buffer against the
-  /// expected strings read from the check file and record diagnostics emitted
-  /// in \p Diags. Errors are recorded against \p SM.
-  ///
-  /// \returns false if the input fails to satisfy the checks.
-  bool checkInput(SourceMgr &SM, StringRef Buffer,
-                  std::vector<FileCheckDiag> *Diags = nullptr);
-};
-
-} // namespace llvm
-
-#endif
+//==-- llvm/Support/FileCheck.h ---------------------------*- C++ -*-==//\r
+//\r
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.\r
+// See https://llvm.org/LICENSE.txt for license information.\r
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\r
+//\r
+//===----------------------------------------------------------------------===//\r
+//\r
+/// \file This file has some utilities to use FileCheck as an API\r
+//\r
+//===----------------------------------------------------------------------===//\r
+\r
+#ifndef LLVM_SUPPORT_FILECHECK_H\r
+#define LLVM_SUPPORT_FILECHECK_H\r
+\r
+#include "llvm/ADT/StringRef.h"\r
+#include "llvm/Support/MemoryBuffer.h"\r
+#include "llvm/Support/Regex.h"\r
+#include "llvm/Support/SourceMgr.h"\r
+#include <string>\r
+#include <vector>\r
+\r
+namespace llvm {\r
+\r
+/// Contains info about various FileCheck options.\r
+struct FileCheckRequest {\r
+  std::vector<std::string> CheckPrefixes;\r
+  bool NoCanonicalizeWhiteSpace = false;\r
+  std::vector<std::string> ImplicitCheckNot;\r
+  std::vector<std::string> GlobalDefines;\r
+  bool AllowEmptyInput = false;\r
+  bool MatchFullLines = false;\r
+  bool IgnoreCase = false;\r
+  bool EnableVarScope = false;\r
+  bool AllowDeprecatedDagOverlap = false;\r
+  bool Verbose = false;\r
+  bool VerboseVerbose = false;\r
+};\r
+\r
+//===----------------------------------------------------------------------===//\r
+// Summary of a FileCheck diagnostic.\r
+//===----------------------------------------------------------------------===//\r
+\r
+namespace Check {\r
+\r
+enum FileCheckKind {\r
+  CheckNone = 0,\r
+  CheckPlain,\r
+  CheckNext,\r
+  CheckSame,\r
+  CheckNot,\r
+  CheckDAG,\r
+  CheckLabel,\r
+  CheckEmpty,\r
+\r
+  /// Indicates the pattern only matches the end of file. This is used for\r
+  /// trailing CHECK-NOTs.\r
+  CheckEOF,\r
+\r
+  /// Marks when parsing found a -NOT check combined with another CHECK suffix.\r
+  CheckBadNot,\r
+\r
+  /// Marks when parsing found a -COUNT directive with invalid count value.\r
+  CheckBadCount\r
+};\r
+\r
+class FileCheckType {\r
+  FileCheckKind Kind;\r
+  int Count; ///< optional Count for some checks\r
+\r
+public:\r
+  FileCheckType(FileCheckKind Kind = CheckNone) : Kind(Kind), Count(1) {}\r
+  FileCheckType(const FileCheckType &) = default;\r
+\r
+  operator FileCheckKind() const { return Kind; }\r
+\r
+  int getCount() const { return Count; }\r
+  FileCheckType &setCount(int C);\r
+\r
+  // \returns a description of \p Prefix.\r
+  std::string getDescription(StringRef Prefix) const;\r
+};\r
+} // namespace Check\r
+\r
+struct FileCheckDiag {\r
+  /// What is the FileCheck directive for this diagnostic?\r
+  Check::FileCheckType CheckTy;\r
+  /// Where is the FileCheck directive for this diagnostic?\r
+  unsigned CheckLine, CheckCol;\r
+  /// What type of match result does this diagnostic describe?\r
+  ///\r
+  /// A directive's supplied pattern is said to be either expected or excluded\r
+  /// depending on whether the pattern must have or must not have a match in\r
+  /// order for the directive to succeed.  For example, a CHECK directive's\r
+  /// pattern is expected, and a CHECK-NOT directive's pattern is excluded.\r
+  /// All match result types whose names end with "Excluded" are for excluded\r
+  /// patterns, and all others are for expected patterns.\r
+  ///\r
+  /// There might be more than one match result for a single pattern.  For\r
+  /// example, there might be several discarded matches\r
+  /// (MatchFoundButDiscarded) before either a good match\r
+  /// (MatchFoundAndExpected) or a failure to match (MatchNoneButExpected),\r
+  /// and there might be a fuzzy match (MatchFuzzy) after the latter.\r
+  enum MatchType {\r
+    /// Indicates a good match for an expected pattern.\r
+    MatchFoundAndExpected,\r
+    /// Indicates a match for an excluded pattern.\r
+    MatchFoundButExcluded,\r
+    /// Indicates a match for an expected pattern, but the match is on the\r
+    /// wrong line.\r
+    MatchFoundButWrongLine,\r
+    /// Indicates a discarded match for an expected pattern.\r
+    MatchFoundButDiscarded,\r
+    /// Indicates no match for an excluded pattern.\r
+    MatchNoneAndExcluded,\r
+    /// Indicates no match for an expected pattern, but this might follow good\r
+    /// matches when multiple matches are expected for the pattern, or it might\r
+    /// follow discarded matches for the pattern.\r
+    MatchNoneButExpected,\r
+    /// Indicates a fuzzy match that serves as a suggestion for the next\r
+    /// intended match for an expected pattern with too few or no good matches.\r
+    MatchFuzzy,\r
+  } MatchTy;\r
+  /// The search range if MatchTy is MatchNoneAndExcluded or\r
+  /// MatchNoneButExpected, or the match range otherwise.\r
+  unsigned InputStartLine;\r
+  unsigned InputStartCol;\r
+  unsigned InputEndLine;\r
+  unsigned InputEndCol;\r
+  FileCheckDiag(const SourceMgr &SM, const Check::FileCheckType &CheckTy,\r
+                SMLoc CheckLoc, MatchType MatchTy, SMRange InputRange);\r
+};\r
+\r
+class FileCheckPatternContext;\r
+struct FileCheckString;\r
+\r
+/// FileCheck class takes the request and exposes various methods that\r
+/// use information from the request.\r
+class FileCheck {\r
+  FileCheckRequest Req;\r
+  std::unique_ptr<FileCheckPatternContext> PatternContext;\r
+  // C++17 TODO: make this a plain std::vector.\r
+  std::unique_ptr<std::vector<FileCheckString>> CheckStrings;\r
+\r
+public:\r
+  explicit FileCheck(FileCheckRequest Req);\r
+  ~FileCheck();\r
+\r
+  // Combines the check prefixes into a single regex so that we can efficiently\r
+  // scan for any of the set.\r
+  //\r
+  // The semantics are that the longest-match wins which matches our regex\r
+  // library.\r
+  Regex buildCheckPrefixRegex();\r
+\r
+  /// Reads the check file from \p Buffer and records the expected strings it\r
+  /// contains. Errors are reported against \p SM.\r
+  ///\r
+  /// Only expected strings whose prefix is one of those listed in \p PrefixRE\r
+  /// are recorded. \returns true in case of an error, false otherwise.\r
+  bool readCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE);\r
+\r
+  bool ValidateCheckPrefixes();\r
+\r
+  /// Canonicalizes whitespaces in the file. Line endings are replaced with\r
+  /// UNIX-style '\n'.\r
+  StringRef CanonicalizeFile(MemoryBuffer &MB,\r
+                             SmallVectorImpl<char> &OutputBuffer);\r
+\r
+  /// Checks the input to FileCheck provided in the \p Buffer against the\r
+  /// expected strings read from the check file and record diagnostics emitted\r
+  /// in \p Diags. Errors are recorded against \p SM.\r
+  ///\r
+  /// \returns false if the input fails to satisfy the checks.\r
+  bool checkInput(SourceMgr &SM, StringRef Buffer,\r
+                  std::vector<FileCheckDiag> *Diags = nullptr);\r
+};\r
+\r
+} // namespace llvm\r
+\r
+#endif\r
index c3f537b35243ec303165e5c9827f65215020d153..fb4bbba033b544c19f143c702aff9a6d359487ed 100644 (file)
-//===- FileCheck.cpp - Check that File's Contents match what is expected --===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// FileCheck does a line-by line check of a file that validates whether it
-// contains the expected content.  This is useful for regression tests etc.
-//
-// This file implements most of the API that will be used by the FileCheck utility
-// as well as various unittests.
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/FileCheck.h"
-#include "FileCheckImpl.h"
-#include "llvm/ADT/StringSet.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/FormatVariadic.h"
-#include <cstdint>
-#include <list>
-#include <tuple>
-#include <utility>
-
-using namespace llvm;
-
-Expected<uint64_t> FileCheckNumericVariableUse::eval() const {
-  Optional<uint64_t> Value = NumericVariable->getValue();
-  if (Value)
-    return *Value;
-
-  return make_error<FileCheckUndefVarError>(Name);
-}
-
-Expected<uint64_t> FileCheckASTBinop::eval() const {
-  Expected<uint64_t> LeftOp = LeftOperand->eval();
-  Expected<uint64_t> RightOp = RightOperand->eval();
-
-  // Bubble up any error (e.g. undefined variables) in the recursive
-  // evaluation.
-  if (!LeftOp || !RightOp) {
-    Error Err = Error::success();
-    if (!LeftOp)
-      Err = joinErrors(std::move(Err), LeftOp.takeError());
-    if (!RightOp)
-      Err = joinErrors(std::move(Err), RightOp.takeError());
-    return std::move(Err);
-  }
-
-  return EvalBinop(*LeftOp, *RightOp);
-}
-
-Expected<std::string> FileCheckNumericSubstitution::getResult() const {
-  Expected<uint64_t> EvaluatedValue = ExpressionAST->eval();
-  if (!EvaluatedValue)
-    return EvaluatedValue.takeError();
-  return utostr(*EvaluatedValue);
-}
-
-Expected<std::string> FileCheckStringSubstitution::getResult() const {
-  // Look up the value and escape it so that we can put it into the regex.
-  Expected<StringRef> VarVal = Context->getPatternVarValue(FromStr);
-  if (!VarVal)
-    return VarVal.takeError();
-  return Regex::escape(*VarVal);
-}
-
-bool FileCheckPattern::isValidVarNameStart(char C) {
-  return C == '_' || isalpha(C);
-}
-
-Expected<FileCheckPattern::VariableProperties>
-FileCheckPattern::parseVariable(StringRef &Str, const SourceMgr &SM) {
-  if (Str.empty())
-    return FileCheckErrorDiagnostic::get(SM, Str, "empty variable name");
-
-  bool ParsedOneChar = false;
-  unsigned I = 0;
-  bool IsPseudo = Str[0] == '@';
-
-  // Global vars start with '$'.
-  if (Str[0] == '$' || IsPseudo)
-    ++I;
-
-  for (unsigned E = Str.size(); I != E; ++I) {
-    if (!ParsedOneChar && !isValidVarNameStart(Str[I]))
-      return FileCheckErrorDiagnostic::get(SM, Str, "invalid variable name");
-
-    // Variable names are composed of alphanumeric characters and underscores.
-    if (Str[I] != '_' && !isalnum(Str[I]))
-      break;
-    ParsedOneChar = true;
-  }
-
-  StringRef Name = Str.take_front(I);
-  Str = Str.substr(I);
-  return VariableProperties {Name, IsPseudo};
-}
-
-// StringRef holding all characters considered as horizontal whitespaces by
-// FileCheck input canonicalization.
-constexpr StringLiteral SpaceChars = " \t";
-
-// Parsing helper function that strips the first character in S and returns it.
-static char popFront(StringRef &S) {
-  char C = S.front();
-  S = S.drop_front();
-  return C;
-}
-
-char FileCheckUndefVarError::ID = 0;
-char FileCheckErrorDiagnostic::ID = 0;
-char FileCheckNotFoundError::ID = 0;
-
-Expected<FileCheckNumericVariable *>
-FileCheckPattern::parseNumericVariableDefinition(
-    StringRef &Expr, FileCheckPatternContext *Context,
-    Optional<size_t> LineNumber, const SourceMgr &SM) {
-  Expected<VariableProperties> ParseVarResult = parseVariable(Expr, SM);
-  if (!ParseVarResult)
-    return ParseVarResult.takeError();
-  StringRef Name = ParseVarResult->Name;
-
-  if (ParseVarResult->IsPseudo)
-    return FileCheckErrorDiagnostic::get(
-        SM, Name, "definition of pseudo numeric variable unsupported");
-
-  // Detect collisions between string and numeric variables when the latter
-  // is created later than the former.
-  if (Context->DefinedVariableTable.find(Name) !=
-      Context->DefinedVariableTable.end())
-    return FileCheckErrorDiagnostic::get(
-        SM, Name, "string variable with name '" + Name + "' already exists");
-
-  Expr = Expr.ltrim(SpaceChars);
-  if (!Expr.empty())
-    return FileCheckErrorDiagnostic::get(
-        SM, Expr, "unexpected characters after numeric variable name");
-
-  FileCheckNumericVariable *DefinedNumericVariable;
-  auto VarTableIter = Context->GlobalNumericVariableTable.find(Name);
-  if (VarTableIter != Context->GlobalNumericVariableTable.end())
-    DefinedNumericVariable = VarTableIter->second;
-  else
-    DefinedNumericVariable = Context->makeNumericVariable(Name, LineNumber);
-
-  return DefinedNumericVariable;
-}
-
-Expected<std::unique_ptr<FileCheckNumericVariableUse>>
-FileCheckPattern::parseNumericVariableUse(StringRef Name, bool IsPseudo,
-                                          Optional<size_t> LineNumber,
-                                          FileCheckPatternContext *Context,
-                                          const SourceMgr &SM) {
-  if (IsPseudo && !Name.equals("@LINE"))
-    return FileCheckErrorDiagnostic::get(
-        SM, Name, "invalid pseudo numeric variable '" + Name + "'");
-
-  // Numeric variable definitions and uses are parsed in the order in which
-  // they appear in the CHECK patterns. For each definition, the pointer to the
-  // class instance of the corresponding numeric variable definition is stored
-  // in GlobalNumericVariableTable in parsePattern. Therefore, if the pointer
-  // we get below is null, it means no such variable was defined before. When
-  // that happens, we create a dummy variable so that parsing can continue. All
-  // uses of undefined variables, whether string or numeric, are then diagnosed
-  // in printSubstitutions() after failing to match.
-  auto VarTableIter = Context->GlobalNumericVariableTable.find(Name);
-  FileCheckNumericVariable *NumericVariable;
-  if (VarTableIter != Context->GlobalNumericVariableTable.end())
-    NumericVariable = VarTableIter->second;
-  else {
-    NumericVariable = Context->makeNumericVariable(Name);
-    Context->GlobalNumericVariableTable[Name] = NumericVariable;
-  }
-
-  Optional<size_t> DefLineNumber = NumericVariable->getDefLineNumber();
-  if (DefLineNumber && LineNumber && *DefLineNumber == *LineNumber)
-    return FileCheckErrorDiagnostic::get(
-        SM, Name,
-        "numeric variable '" + Name +
-            "' defined earlier in the same CHECK directive");
-
-  return std::make_unique<FileCheckNumericVariableUse>(Name, NumericVariable);
-}
-
-Expected<std::unique_ptr<FileCheckExpressionAST>>
-FileCheckPattern::parseNumericOperand(StringRef &Expr, AllowedOperand AO,
-                                      Optional<size_t> LineNumber,
-                                      FileCheckPatternContext *Context,
-                                      const SourceMgr &SM) {
-  if (AO == AllowedOperand::LineVar || AO == AllowedOperand::Any) {
-    // Try to parse as a numeric variable use.
-    Expected<FileCheckPattern::VariableProperties> ParseVarResult =
-        parseVariable(Expr, SM);
-    if (ParseVarResult)
-      return parseNumericVariableUse(ParseVarResult->Name,
-                                     ParseVarResult->IsPseudo, LineNumber,
-                                     Context, SM);
-    if (AO == AllowedOperand::LineVar)
-      return ParseVarResult.takeError();
-    // Ignore the error and retry parsing as a literal.
-    consumeError(ParseVarResult.takeError());
-  }
-
-  // Otherwise, parse it as a literal.
-  uint64_t LiteralValue;
-  if (!Expr.consumeInteger(/*Radix=*/10, LiteralValue))
-    return std::make_unique<FileCheckExpressionLiteral>(LiteralValue);
-
-  return FileCheckErrorDiagnostic::get(SM, Expr,
-                                       "invalid operand format '" + Expr + "'");
-}
-
-static uint64_t add(uint64_t LeftOp, uint64_t RightOp) {
-  return LeftOp + RightOp;
-}
-
-static uint64_t sub(uint64_t LeftOp, uint64_t RightOp) {
-  return LeftOp - RightOp;
-}
-
-Expected<std::unique_ptr<FileCheckExpressionAST>> FileCheckPattern::parseBinop(
-    StringRef &Expr, std::unique_ptr<FileCheckExpressionAST> LeftOp,
-    bool IsLegacyLineExpr, Optional<size_t> LineNumber,
-    FileCheckPatternContext *Context, const SourceMgr &SM) {
-  Expr = Expr.ltrim(SpaceChars);
-  if (Expr.empty())
-    return std::move(LeftOp);
-
-  // Check if this is a supported operation and select a function to perform
-  // it.
-  SMLoc OpLoc = SMLoc::getFromPointer(Expr.data());
-  char Operator = popFront(Expr);
-  binop_eval_t EvalBinop;
-  switch (Operator) {
-  case '+':
-    EvalBinop = add;
-    break;
-  case '-':
-    EvalBinop = sub;
-    break;
-  default:
-    return FileCheckErrorDiagnostic::get(
-        SM, OpLoc, Twine("unsupported operation '") + Twine(Operator) + "'");
-  }
-
-  // Parse right operand.
-  Expr = Expr.ltrim(SpaceChars);
-  if (Expr.empty())
-    return FileCheckErrorDiagnostic::get(SM, Expr,
-                                         "missing operand in expression");
-  // The second operand in a legacy @LINE expression is always a literal.
-  AllowedOperand AO =
-      IsLegacyLineExpr ? AllowedOperand::Literal : AllowedOperand::Any;
-  Expected<std::unique_ptr<FileCheckExpressionAST>> RightOpResult =
-      parseNumericOperand(Expr, AO, LineNumber, Context, SM);
-  if (!RightOpResult)
-    return RightOpResult;
-
-  Expr = Expr.ltrim(SpaceChars);
-  return std::make_unique<FileCheckASTBinop>(EvalBinop, std::move(LeftOp),
-                                              std::move(*RightOpResult));
-}
-
-Expected<std::unique_ptr<FileCheckExpressionAST>>
-FileCheckPattern::parseNumericSubstitutionBlock(
-    StringRef Expr,
-    Optional<FileCheckNumericVariable *> &DefinedNumericVariable,
-    bool IsLegacyLineExpr, Optional<size_t> LineNumber,
-    FileCheckPatternContext *Context, const SourceMgr &SM) {
-  std::unique_ptr<FileCheckExpressionAST> ExpressionAST = nullptr;
-  StringRef DefExpr = StringRef();
-  DefinedNumericVariable = None;
-  // Save variable definition expression if any.
-  size_t DefEnd = Expr.find(':');
-  if (DefEnd != StringRef::npos) {
-    DefExpr = Expr.substr(0, DefEnd);
-    Expr = Expr.substr(DefEnd + 1);
-  }
-
-  // Parse the expression itself.
-  Expr = Expr.ltrim(SpaceChars);
-  if (!Expr.empty()) {
-    // The first operand in a legacy @LINE expression is always the @LINE
-    // pseudo variable.
-    AllowedOperand AO =
-        IsLegacyLineExpr ? AllowedOperand::LineVar : AllowedOperand::Any;
-    Expected<std::unique_ptr<FileCheckExpressionAST>> ParseResult =
-        parseNumericOperand(Expr, AO, LineNumber, Context, SM);
-    while (ParseResult && !Expr.empty()) {
-      ParseResult = parseBinop(Expr, std::move(*ParseResult), IsLegacyLineExpr,
-                               LineNumber, Context, SM);
-      // Legacy @LINE expressions only allow 2 operands.
-      if (ParseResult && IsLegacyLineExpr && !Expr.empty())
-        return FileCheckErrorDiagnostic::get(
-            SM, Expr,
-            "unexpected characters at end of expression '" + Expr + "'");
-    }
-    if (!ParseResult)
-      return ParseResult;
-    ExpressionAST = std::move(*ParseResult);
-  }
-
-  // Parse the numeric variable definition.
-  if (DefEnd != StringRef::npos) {
-    DefExpr = DefExpr.ltrim(SpaceChars);
-    Expected<FileCheckNumericVariable *> ParseResult =
-        parseNumericVariableDefinition(DefExpr, Context, LineNumber, SM);
-
-    if (!ParseResult)
-      return ParseResult.takeError();
-    DefinedNumericVariable = *ParseResult;
-  }
-
-  return std::move(ExpressionAST);
-}
-
-bool FileCheckPattern::parsePattern(StringRef PatternStr, StringRef Prefix,
-                                    SourceMgr &SM,
-                                    const FileCheckRequest &Req) {
-  bool MatchFullLinesHere = Req.MatchFullLines && CheckTy != Check::CheckNot;
-
-  PatternLoc = SMLoc::getFromPointer(PatternStr.data());
-
-  if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines))
-    // Ignore trailing whitespace.
-    while (!PatternStr.empty() &&
-           (PatternStr.back() == ' ' || PatternStr.back() == '\t'))
-      PatternStr = PatternStr.substr(0, PatternStr.size() - 1);
-
-  // Check that there is something on the line.
-  if (PatternStr.empty() && CheckTy != Check::CheckEmpty) {
-    SM.PrintMessage(PatternLoc, SourceMgr::DK_Error,
-                    "found empty check string with prefix '" + Prefix + ":'");
-    return true;
-  }
-
-  if (!PatternStr.empty() && CheckTy == Check::CheckEmpty) {
-    SM.PrintMessage(
-        PatternLoc, SourceMgr::DK_Error,
-        "found non-empty check string for empty check with prefix '" + Prefix +
-            ":'");
-    return true;
-  }
-
-  if (CheckTy == Check::CheckEmpty) {
-    RegExStr = "(\n$)";
-    return false;
-  }
-
-  // Check to see if this is a fixed string, or if it has regex pieces.
-  if (!MatchFullLinesHere &&
-      (PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos &&
-                                 PatternStr.find("[[") == StringRef::npos))) {
-    FixedStr = PatternStr;
-    return false;
-  }
-
-  if (MatchFullLinesHere) {
-    RegExStr += '^';
-    if (!Req.NoCanonicalizeWhiteSpace)
-      RegExStr += " *";
-  }
-
-  // Paren value #0 is for the fully matched string.  Any new parenthesized
-  // values add from there.
-  unsigned CurParen = 1;
-
-  // Otherwise, there is at least one regex piece.  Build up the regex pattern
-  // by escaping scary characters in fixed strings, building up one big regex.
-  while (!PatternStr.empty()) {
-    // RegEx matches.
-    if (PatternStr.startswith("{{")) {
-      // This is the start of a regex match.  Scan for the }}.
-      size_t End = PatternStr.find("}}");
-      if (End == StringRef::npos) {
-        SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
-                        SourceMgr::DK_Error,
-                        "found start of regex string with no end '}}'");
-        return true;
-      }
-
-      // Enclose {{}} patterns in parens just like [[]] even though we're not
-      // capturing the result for any purpose.  This is required in case the
-      // expression contains an alternation like: CHECK:  abc{{x|z}}def.  We
-      // want this to turn into: "abc(x|z)def" not "abcx|zdef".
-      RegExStr += '(';
-      ++CurParen;
-
-      if (AddRegExToRegEx(PatternStr.substr(2, End - 2), CurParen, SM))
-        return true;
-      RegExStr += ')';
-
-      PatternStr = PatternStr.substr(End + 2);
-      continue;
-    }
-
-    // String and numeric substitution blocks. Pattern 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 recognize the same
-    // form as string ones, but start with a '#' sign after the double
-    // brackets. They also accept a combined form which sets a numeric variable
-    // to the evaluation of an expression. Both string and numeric variable
-    // names 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("[[")) {
-      StringRef UnparsedPatternStr = PatternStr.substr(2);
-      // Find the closing bracket pair ending the match.  End is going to be an
-      // offset relative to the beginning of the match string.
-      size_t End = FindRegexVarEnd(UnparsedPatternStr, SM);
-      StringRef MatchStr = UnparsedPatternStr.substr(0, End);
-      bool IsNumBlock = MatchStr.consume_front("#");
-
-      if (End == StringRef::npos) {
-        SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
-                        SourceMgr::DK_Error,
-                        "Invalid substitution block, no ]] found");
-        return true;
-      }
-      // 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);
-
-      bool IsDefinition = false;
-      bool SubstNeeded = false;
-      // Whether the substitution block is a legacy use of @LINE with string
-      // substitution block syntax.
-      bool IsLegacyLineExpr = false;
-      StringRef DefName;
-      StringRef SubstStr;
-      StringRef MatchRegexp;
-      size_t SubstInsertIdx = RegExStr.size();
-
-      // Parse string variable or legacy @LINE expression.
-      if (!IsNumBlock) {
-        size_t VarEndIdx = MatchStr.find(":");
-        size_t SpacePos = MatchStr.substr(0, VarEndIdx).find_first_of(" \t");
-        if (SpacePos != StringRef::npos) {
-          SM.PrintMessage(SMLoc::getFromPointer(MatchStr.data() + SpacePos),
-                          SourceMgr::DK_Error, "unexpected whitespace");
-          return true;
-        }
-
-        // Get the name (e.g. "foo") and verify it is well formed.
-        StringRef OrigMatchStr = MatchStr;
-        Expected<FileCheckPattern::VariableProperties> ParseVarResult =
-            parseVariable(MatchStr, SM);
-        if (!ParseVarResult) {
-          logAllUnhandledErrors(ParseVarResult.takeError(), errs());
-          return true;
-        }
-        StringRef Name = ParseVarResult->Name;
-        bool IsPseudo = ParseVarResult->IsPseudo;
-
-        IsDefinition = (VarEndIdx != StringRef::npos);
-        SubstNeeded = !IsDefinition;
-        if (IsDefinition) {
-          if ((IsPseudo || !MatchStr.consume_front(":"))) {
-            SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
-                            SourceMgr::DK_Error,
-                            "invalid name in string variable definition");
-            return true;
-          }
-
-          // Detect collisions between string and numeric variables when the
-          // former is created later than the latter.
-          if (Context->GlobalNumericVariableTable.find(Name) !=
-              Context->GlobalNumericVariableTable.end()) {
-            SM.PrintMessage(
-                SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
-                "numeric variable with name '" + Name + "' already exists");
-            return true;
-          }
-          DefName = Name;
-          MatchRegexp = MatchStr;
-        } else {
-          if (IsPseudo) {
-            MatchStr = OrigMatchStr;
-            IsLegacyLineExpr = IsNumBlock = true;
-          } else
-            SubstStr = Name;
-        }
-      }
-
-      // Parse numeric substitution block.
-      std::unique_ptr<FileCheckExpressionAST> ExpressionAST;
-      Optional<FileCheckNumericVariable *> DefinedNumericVariable;
-      if (IsNumBlock) {
-        Expected<std::unique_ptr<FileCheckExpressionAST>> ParseResult =
-            parseNumericSubstitutionBlock(MatchStr, DefinedNumericVariable,
-                                          IsLegacyLineExpr, LineNumber, Context,
-                                          SM);
-        if (!ParseResult) {
-          logAllUnhandledErrors(ParseResult.takeError(), errs());
-          return true;
-        }
-        ExpressionAST = std::move(*ParseResult);
-        SubstNeeded = ExpressionAST != nullptr;
-        if (DefinedNumericVariable) {
-          IsDefinition = true;
-          DefName = (*DefinedNumericVariable)->getName();
-        }
-        if (SubstNeeded)
-          SubstStr = MatchStr;
-        else
-          MatchRegexp = "[0-9]+";
-      }
-
-      // Handle variable definition: [[<def>:(...)]] and [[#(...)<def>:(...)]].
-      if (IsDefinition) {
-        RegExStr += '(';
-        ++SubstInsertIdx;
-
-        if (IsNumBlock) {
-          FileCheckNumericVariableMatch NumericVariableDefinition = {
-              *DefinedNumericVariable, CurParen};
-          NumericVariableDefs[DefName] = NumericVariableDefinition;
-          // This store is done here rather than in match() to allow
-          // parseNumericVariableUse() to get the pointer to the class instance
-          // of the right variable definition corresponding to a given numeric
-          // variable use.
-          Context->GlobalNumericVariableTable[DefName] =
-              *DefinedNumericVariable;
-        } else {
-          VariableDefs[DefName] = CurParen;
-          // Mark string variable as defined to detect collisions between
-          // string and numeric variables in parseNumericVariableUse() and
-          // defineCmdlineVariables() when the latter is created later than the
-          // former. We cannot reuse GlobalVariableTable for this by populating
-          // it with an empty string since we would then lose the ability to
-          // detect the use of an undefined variable in match().
-          Context->DefinedVariableTable[DefName] = true;
-        }
-
-        ++CurParen;
-      }
-
-      if (!MatchRegexp.empty() && AddRegExToRegEx(MatchRegexp, CurParen, SM))
-        return true;
-
-      if (IsDefinition)
-        RegExStr += ')';
-
-      // Handle substitutions: [[foo]] and [[#<foo expr>]].
-      if (SubstNeeded) {
-        // Handle substitution of string variables that were defined earlier on
-        // the same line by emitting a backreference. Expressions do not
-        // support substituting a numeric variable defined on the same line.
-        if (!IsNumBlock && VariableDefs.find(SubstStr) != VariableDefs.end()) {
-          unsigned CaptureParenGroup = VariableDefs[SubstStr];
-          if (CaptureParenGroup < 1 || CaptureParenGroup > 9) {
-            SM.PrintMessage(SMLoc::getFromPointer(SubstStr.data()),
-                            SourceMgr::DK_Error,
-                            "Can't back-reference more than 9 variables");
-            return true;
-          }
-          AddBackrefToRegEx(CaptureParenGroup);
-        } else {
-          // Handle substitution of string variables ([[<var>]]) defined in
-          // previous CHECK patterns, and substitution of expressions.
-          FileCheckSubstitution *Substitution =
-              IsNumBlock
-                  ? Context->makeNumericSubstitution(
-                        SubstStr, std::move(ExpressionAST), SubstInsertIdx)
-                  : Context->makeStringSubstitution(SubstStr, SubstInsertIdx);
-          Substitutions.push_back(Substitution);
-        }
-      }
-    }
-
-    // Handle fixed string matches.
-    // Find the end, which is the start of the next regex.
-    size_t FixedMatchEnd = PatternStr.find("{{");
-    FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[["));
-    RegExStr += Regex::escape(PatternStr.substr(0, FixedMatchEnd));
-    PatternStr = PatternStr.substr(FixedMatchEnd);
-  }
-
-  if (MatchFullLinesHere) {
-    if (!Req.NoCanonicalizeWhiteSpace)
-      RegExStr += " *";
-    RegExStr += '$';
-  }
-
-  return false;
-}
-
-bool FileCheckPattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM) {
-  Regex R(RS);
-  std::string Error;
-  if (!R.isValid(Error)) {
-    SM.PrintMessage(SMLoc::getFromPointer(RS.data()), SourceMgr::DK_Error,
-                    "invalid regex: " + Error);
-    return true;
-  }
-
-  RegExStr += RS.str();
-  CurParen += R.getNumMatches();
-  return false;
-}
-
-void FileCheckPattern::AddBackrefToRegEx(unsigned BackrefNum) {
-  assert(BackrefNum >= 1 && BackrefNum <= 9 && "Invalid backref number");
-  std::string Backref = std::string("\\") + std::string(1, '0' + BackrefNum);
-  RegExStr += Backref;
-}
-
-Expected<size_t> FileCheckPattern::match(StringRef Buffer, size_t &MatchLen,
-                                         const SourceMgr &SM) const {
-  // If this is the EOF pattern, match it immediately.
-  if (CheckTy == Check::CheckEOF) {
-    MatchLen = 0;
-    return Buffer.size();
-  }
-
-  // If this is a fixed string pattern, just match it now.
-  if (!FixedStr.empty()) {
-    MatchLen = FixedStr.size();
-    size_t Pos = Buffer.find(FixedStr);
-    if (Pos == StringRef::npos)
-      return make_error<FileCheckNotFoundError>();
-    return Pos;
-  }
-
-  // Regex match.
-
-  // If there are substitutions, we need to create a temporary string with the
-  // actual value.
-  StringRef RegExToMatch = RegExStr;
-  std::string TmpStr;
-  if (!Substitutions.empty()) {
-    TmpStr = RegExStr;
-    if (LineNumber)
-      Context->LineVariable->setValue(*LineNumber);
-
-    size_t InsertOffset = 0;
-    // Substitute all string variables and 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).
-      Expected<std::string> Value = Substitution->getResult();
-      if (!Value)
-        return Value.takeError();
-
-      // Plop it into the regex at the adjusted offset.
-      TmpStr.insert(TmpStr.begin() + Substitution->getIndex() + InsertOffset,
-                    Value->begin(), Value->end());
-      InsertOffset += Value->size();
-    }
-
-    // Match the newly constructed regex.
-    RegExToMatch = TmpStr;
-  }
-
-  SmallVector<StringRef, 4> MatchInfo;
-  if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo))
-    return make_error<FileCheckNotFoundError>();
-
-  // Successful regex match.
-  assert(!MatchInfo.empty() && "Didn't get any match");
-  StringRef FullMatch = MatchInfo[0];
-
-  // 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] =
-        MatchInfo[VariableDef.second];
-  }
-
-  // If this defines any numeric variables, remember their values.
-  for (const auto &NumericVariableDef : NumericVariableDefs) {
-    const FileCheckNumericVariableMatch &NumericVariableMatch =
-        NumericVariableDef.getValue();
-    unsigned CaptureParenGroup = NumericVariableMatch.CaptureParenGroup;
-    assert(CaptureParenGroup < MatchInfo.size() && "Internal paren error");
-    FileCheckNumericVariable *DefinedNumericVariable =
-        NumericVariableMatch.DefinedNumericVariable;
-
-    StringRef MatchedValue = MatchInfo[CaptureParenGroup];
-    uint64_t Val;
-    if (MatchedValue.getAsInteger(10, Val))
-      return FileCheckErrorDiagnostic::get(SM, MatchedValue,
-                                           "Unable to represent numeric value");
-    DefinedNumericVariable->setValue(Val);
-  }
-
-  // Like CHECK-NEXT, CHECK-EMPTY's match range is considered to start after
-  // the required preceding newline, which is consumed by the pattern in the
-  // case of CHECK-EMPTY but not CHECK-NEXT.
-  size_t MatchStartSkip = CheckTy == Check::CheckEmpty;
-  MatchLen = FullMatch.size() - MatchStartSkip;
-  return FullMatch.data() - Buffer.data() + MatchStartSkip;
-}
-
-unsigned FileCheckPattern::computeMatchDistance(StringRef Buffer) const {
-  // Just compute the number of matching characters. For regular expressions, we
-  // just compare against the regex itself and hope for the best.
-  //
-  // FIXME: One easy improvement here is have the regex lib generate a single
-  // example regular expression which matches, and use that as the example
-  // string.
-  StringRef ExampleString(FixedStr);
-  if (ExampleString.empty())
-    ExampleString = RegExStr;
-
-  // Only compare up to the first line in the buffer, or the string size.
-  StringRef BufferPrefix = Buffer.substr(0, ExampleString.size());
-  BufferPrefix = BufferPrefix.split('\n').first;
-  return BufferPrefix.edit_distance(ExampleString);
-}
-
-void FileCheckPattern::printSubstitutions(const SourceMgr &SM, StringRef Buffer,
-                                          SMRange MatchRange) const {
-  // Print what we know about substitutions.
-  if (!Substitutions.empty()) {
-    for (const auto &Substitution : Substitutions) {
-      SmallString<256> Msg;
-      raw_svector_ostream OS(Msg);
-      Expected<std::string> MatchedValue = Substitution->getResult();
-
-      // Substitution failed or is not known at match time, print the undefined
-      // variables it uses.
-      if (!MatchedValue) {
-        bool UndefSeen = false;
-        handleAllErrors(MatchedValue.takeError(),
-                        [](const FileCheckNotFoundError &E) {},
-                        // Handled in PrintNoMatch().
-                        [](const FileCheckErrorDiagnostic &E) {},
-                        [&](const FileCheckUndefVarError &E) {
-                          if (!UndefSeen) {
-                            OS << "uses undefined variable(s):";
-                            UndefSeen = true;
-                          }
-                          OS << " ";
-                          E.log(OS);
-                        });
-      } else {
-        // Substitution succeeded. Print substituted value.
-        OS << "with \"";
-        OS.write_escaped(Substitution->getFromString()) << "\" equal to \"";
-        OS.write_escaped(*MatchedValue) << "\"";
-      }
-
-      if (MatchRange.isValid())
-        SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note, OS.str(),
-                        {MatchRange});
-      else
-        SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
-                        SourceMgr::DK_Note, OS.str());
-    }
-  }
-}
-
-static SMRange ProcessMatchResult(FileCheckDiag::MatchType MatchTy,
-                                  const SourceMgr &SM, SMLoc Loc,
-                                  Check::FileCheckType CheckTy,
-                                  StringRef Buffer, size_t Pos, size_t Len,
-                                  std::vector<FileCheckDiag> *Diags,
-                                  bool AdjustPrevDiag = false) {
-  SMLoc Start = SMLoc::getFromPointer(Buffer.data() + Pos);
-  SMLoc End = SMLoc::getFromPointer(Buffer.data() + Pos + Len);
-  SMRange Range(Start, End);
-  if (Diags) {
-    if (AdjustPrevDiag)
-      Diags->rbegin()->MatchTy = MatchTy;
-    else
-      Diags->emplace_back(SM, CheckTy, Loc, MatchTy, Range);
-  }
-  return Range;
-}
-
-void FileCheckPattern::printFuzzyMatch(
-    const SourceMgr &SM, StringRef Buffer,
-    std::vector<FileCheckDiag> *Diags) const {
-  // Attempt to find the closest/best fuzzy match.  Usually an error happens
-  // because some string in the output didn't exactly match. In these cases, we
-  // would like to show the user a best guess at what "should have" matched, to
-  // save them having to actually check the input manually.
-  size_t NumLinesForward = 0;
-  size_t Best = StringRef::npos;
-  double BestQuality = 0;
-
-  // Use an arbitrary 4k limit on how far we will search.
-  for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) {
-    if (Buffer[i] == '\n')
-      ++NumLinesForward;
-
-    // Patterns have leading whitespace stripped, so skip whitespace when
-    // looking for something which looks like a pattern.
-    if (Buffer[i] == ' ' || Buffer[i] == '\t')
-      continue;
-
-    // Compute the "quality" of this match as an arbitrary combination of the
-    // match distance and the number of lines skipped to get to this match.
-    unsigned Distance = computeMatchDistance(Buffer.substr(i));
-    double Quality = Distance + (NumLinesForward / 100.);
-
-    if (Quality < BestQuality || Best == StringRef::npos) {
-      Best = i;
-      BestQuality = Quality;
-    }
-  }
-
-  // Print the "possible intended match here" line if we found something
-  // reasonable and not equal to what we showed in the "scanning from here"
-  // line.
-  if (Best && Best != StringRef::npos && BestQuality < 50) {
-    SMRange MatchRange =
-        ProcessMatchResult(FileCheckDiag::MatchFuzzy, SM, getLoc(),
-                           getCheckTy(), Buffer, Best, 0, Diags);
-    SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note,
-                    "possible intended match here");
-
-    // FIXME: If we wanted to be really friendly we would show why the match
-    // failed, as it can be hard to spot simple one character differences.
-  }
-}
-
-Expected<StringRef>
-FileCheckPatternContext::getPatternVarValue(StringRef VarName) {
-  auto VarIter = GlobalVariableTable.find(VarName);
-  if (VarIter == GlobalVariableTable.end())
-    return make_error<FileCheckUndefVarError>(VarName);
-
-  return VarIter->second;
-}
-
-template <class... Types>
-FileCheckNumericVariable *
-FileCheckPatternContext::makeNumericVariable(Types... args) {
-  NumericVariables.push_back(
-      std::make_unique<FileCheckNumericVariable>(args...));
-  return NumericVariables.back().get();
-}
-
-FileCheckSubstitution *
-FileCheckPatternContext::makeStringSubstitution(StringRef VarName,
-                                                size_t InsertIdx) {
-  Substitutions.push_back(
-      std::make_unique<FileCheckStringSubstitution>(this, VarName, InsertIdx));
-  return Substitutions.back().get();
-}
-
-FileCheckSubstitution *FileCheckPatternContext::makeNumericSubstitution(
-    StringRef ExpressionStr,
-    std::unique_ptr<FileCheckExpressionAST> ExpressionAST, size_t InsertIdx) {
-  Substitutions.push_back(std::make_unique<FileCheckNumericSubstitution>(
-      this, ExpressionStr, std::move(ExpressionAST), InsertIdx));
-  return Substitutions.back().get();
-}
-
-size_t FileCheckPattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) {
-  // Offset keeps track of the current offset within the input Str
-  size_t Offset = 0;
-  // [...] Nesting depth
-  size_t BracketDepth = 0;
-
-  while (!Str.empty()) {
-    if (Str.startswith("]]") && BracketDepth == 0)
-      return Offset;
-    if (Str[0] == '\\') {
-      // Backslash escapes the next char within regexes, so skip them both.
-      Str = Str.substr(2);
-      Offset += 2;
-    } else {
-      switch (Str[0]) {
-      default:
-        break;
-      case '[':
-        BracketDepth++;
-        break;
-      case ']':
-        if (BracketDepth == 0) {
-          SM.PrintMessage(SMLoc::getFromPointer(Str.data()),
-                          SourceMgr::DK_Error,
-                          "missing closing \"]\" for regex variable");
-          exit(1);
-        }
-        BracketDepth--;
-        break;
-      }
-      Str = Str.substr(1);
-      Offset++;
-    }
-  }
-
-  return StringRef::npos;
-}
-
-StringRef FileCheck::CanonicalizeFile(MemoryBuffer &MB,
-                                      SmallVectorImpl<char> &OutputBuffer) {
-  OutputBuffer.reserve(MB.getBufferSize());
-
-  for (const char *Ptr = MB.getBufferStart(), *End = MB.getBufferEnd();
-       Ptr != End; ++Ptr) {
-    // Eliminate trailing dosish \r.
-    if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') {
-      continue;
-    }
-
-    // If current char is not a horizontal whitespace or if horizontal
-    // whitespace canonicalization is disabled, dump it to output as is.
-    if (Req.NoCanonicalizeWhiteSpace || (*Ptr != ' ' && *Ptr != '\t')) {
-      OutputBuffer.push_back(*Ptr);
-      continue;
-    }
-
-    // Otherwise, add one space and advance over neighboring space.
-    OutputBuffer.push_back(' ');
-    while (Ptr + 1 != End && (Ptr[1] == ' ' || Ptr[1] == '\t'))
-      ++Ptr;
-  }
-
-  // Add a null byte and then return all but that byte.
-  OutputBuffer.push_back('\0');
-  return StringRef(OutputBuffer.data(), OutputBuffer.size() - 1);
-}
-
-FileCheckDiag::FileCheckDiag(const SourceMgr &SM,
-                             const Check::FileCheckType &CheckTy,
-                             SMLoc CheckLoc, MatchType MatchTy,
-                             SMRange InputRange)
-    : CheckTy(CheckTy), MatchTy(MatchTy) {
-  auto Start = SM.getLineAndColumn(InputRange.Start);
-  auto End = SM.getLineAndColumn(InputRange.End);
-  InputStartLine = Start.first;
-  InputStartCol = Start.second;
-  InputEndLine = End.first;
-  InputEndCol = End.second;
-  Start = SM.getLineAndColumn(CheckLoc);
-  CheckLine = Start.first;
-  CheckCol = Start.second;
-}
-
-static bool IsPartOfWord(char c) {
-  return (isalnum(c) || c == '-' || c == '_');
-}
-
-Check::FileCheckType &Check::FileCheckType::setCount(int C) {
-  assert(Count > 0 && "zero and negative counts are not supported");
-  assert((C == 1 || Kind == CheckPlain) &&
-         "count supported only for plain CHECK directives");
-  Count = C;
-  return *this;
-}
-
-std::string Check::FileCheckType::getDescription(StringRef Prefix) const {
-  switch (Kind) {
-  case Check::CheckNone:
-    return "invalid";
-  case Check::CheckPlain:
-    if (Count > 1)
-      return Prefix.str() + "-COUNT";
-    return Prefix;
-  case Check::CheckNext:
-    return Prefix.str() + "-NEXT";
-  case Check::CheckSame:
-    return Prefix.str() + "-SAME";
-  case Check::CheckNot:
-    return Prefix.str() + "-NOT";
-  case Check::CheckDAG:
-    return Prefix.str() + "-DAG";
-  case Check::CheckLabel:
-    return Prefix.str() + "-LABEL";
-  case Check::CheckEmpty:
-    return Prefix.str() + "-EMPTY";
-  case Check::CheckEOF:
-    return "implicit EOF";
-  case Check::CheckBadNot:
-    return "bad NOT";
-  case Check::CheckBadCount:
-    return "bad COUNT";
-  }
-  llvm_unreachable("unknown FileCheckType");
-}
-
-static std::pair<Check::FileCheckType, StringRef>
-FindCheckType(StringRef Buffer, StringRef Prefix) {
-  if (Buffer.size() <= Prefix.size())
-    return {Check::CheckNone, StringRef()};
-
-  char NextChar = Buffer[Prefix.size()];
-
-  StringRef Rest = Buffer.drop_front(Prefix.size() + 1);
-  // Verify that the : is present after the prefix.
-  if (NextChar == ':')
-    return {Check::CheckPlain, Rest};
-
-  if (NextChar != '-')
-    return {Check::CheckNone, StringRef()};
-
-  if (Rest.consume_front("COUNT-")) {
-    int64_t Count;
-    if (Rest.consumeInteger(10, Count))
-      // Error happened in parsing integer.
-      return {Check::CheckBadCount, Rest};
-    if (Count <= 0 || Count > INT32_MAX)
-      return {Check::CheckBadCount, Rest};
-    if (!Rest.consume_front(":"))
-      return {Check::CheckBadCount, Rest};
-    return {Check::FileCheckType(Check::CheckPlain).setCount(Count), Rest};
-  }
-
-  if (Rest.consume_front("NEXT:"))
-    return {Check::CheckNext, Rest};
-
-  if (Rest.consume_front("SAME:"))
-    return {Check::CheckSame, Rest};
-
-  if (Rest.consume_front("NOT:"))
-    return {Check::CheckNot, Rest};
-
-  if (Rest.consume_front("DAG:"))
-    return {Check::CheckDAG, Rest};
-
-  if (Rest.consume_front("LABEL:"))
-    return {Check::CheckLabel, Rest};
-
-  if (Rest.consume_front("EMPTY:"))
-    return {Check::CheckEmpty, Rest};
-
-  // You can't combine -NOT with another suffix.
-  if (Rest.startswith("DAG-NOT:") || Rest.startswith("NOT-DAG:") ||
-      Rest.startswith("NEXT-NOT:") || Rest.startswith("NOT-NEXT:") ||
-      Rest.startswith("SAME-NOT:") || Rest.startswith("NOT-SAME:") ||
-      Rest.startswith("EMPTY-NOT:") || Rest.startswith("NOT-EMPTY:"))
-    return {Check::CheckBadNot, Rest};
-
-  return {Check::CheckNone, Rest};
-}
-
-// From the given position, find the next character after the word.
-static size_t SkipWord(StringRef Str, size_t Loc) {
-  while (Loc < Str.size() && IsPartOfWord(Str[Loc]))
-    ++Loc;
-  return Loc;
-}
-
-/// Searches the buffer for the first prefix in the prefix regular expression.
-///
-/// This searches the buffer using the provided regular expression, however it
-/// enforces constraints beyond that:
-/// 1) The found prefix must not be a suffix of something that looks like
-///    a valid prefix.
-/// 2) The found prefix must be followed by a valid check type suffix using \c
-///    FindCheckType above.
-///
-/// \returns a pair of StringRefs into the Buffer, which combines:
-///   - the first match of the regular expression to satisfy these two is
-///   returned,
-///     otherwise an empty StringRef is returned to indicate failure.
-///   - buffer rewound to the location right after parsed suffix, for parsing
-///     to continue from
-///
-/// If this routine returns a valid prefix, it will also shrink \p Buffer to
-/// start at the beginning of the returned prefix, increment \p LineNumber for
-/// each new line consumed from \p Buffer, and set \p CheckTy to the type of
-/// check found by examining the suffix.
-///
-/// If no valid prefix is found, the state of Buffer, LineNumber, and CheckTy
-/// is unspecified.
-static std::pair<StringRef, StringRef>
-FindFirstMatchingPrefix(Regex &PrefixRE, StringRef &Buffer,
-                        unsigned &LineNumber, Check::FileCheckType &CheckTy) {
-  SmallVector<StringRef, 2> Matches;
-
-  while (!Buffer.empty()) {
-    // Find the first (longest) match using the RE.
-    if (!PrefixRE.match(Buffer, &Matches))
-      // No match at all, bail.
-      return {StringRef(), StringRef()};
-
-    StringRef Prefix = Matches[0];
-    Matches.clear();
-
-    assert(Prefix.data() >= Buffer.data() &&
-           Prefix.data() < Buffer.data() + Buffer.size() &&
-           "Prefix doesn't start inside of buffer!");
-    size_t Loc = Prefix.data() - Buffer.data();
-    StringRef Skipped = Buffer.substr(0, Loc);
-    Buffer = Buffer.drop_front(Loc);
-    LineNumber += Skipped.count('\n');
-
-    // Check that the matched prefix isn't a suffix of some other check-like
-    // word.
-    // FIXME: This is a very ad-hoc check. it would be better handled in some
-    // other way. Among other things it seems hard to distinguish between
-    // intentional and unintentional uses of this feature.
-    if (Skipped.empty() || !IsPartOfWord(Skipped.back())) {
-      // Now extract the type.
-      StringRef AfterSuffix;
-      std::tie(CheckTy, AfterSuffix) = FindCheckType(Buffer, Prefix);
-
-      // If we've found a valid check type for this prefix, we're done.
-      if (CheckTy != Check::CheckNone)
-        return {Prefix, AfterSuffix};
-    }
-
-    // If we didn't successfully find a prefix, we need to skip this invalid
-    // prefix and continue scanning. We directly skip the prefix that was
-    // matched and any additional parts of that check-like word.
-    Buffer = Buffer.drop_front(SkipWord(Buffer, Prefix.size()));
-  }
-
-  // We ran out of buffer while skipping partial matches so give up.
-  return {StringRef(), StringRef()};
-}
-
-void FileCheckPatternContext::createLineVariable() {
-  assert(!LineVariable && "@LINE pseudo numeric variable already created");
-  StringRef LineName = "@LINE";
-  LineVariable = makeNumericVariable(LineName);
-  GlobalNumericVariableTable[LineName] = LineVariable;
-}
-
-FileCheck::FileCheck(FileCheckRequest Req)
-    : Req(Req), PatternContext(std::make_unique<FileCheckPatternContext>()),
-      CheckStrings(std::make_unique<std::vector<FileCheckString>>()) {}
-
-FileCheck::~FileCheck() = default;
-
-bool FileCheck::readCheckFile(SourceMgr &SM, StringRef Buffer,
-                              Regex &PrefixRE) {
-  Error DefineError =
-      PatternContext->defineCmdlineVariables(Req.GlobalDefines, SM);
-  if (DefineError) {
-    logAllUnhandledErrors(std::move(DefineError), errs());
-    return true;
-  }
-
-  PatternContext->createLineVariable();
-
-  std::vector<FileCheckPattern> ImplicitNegativeChecks;
-  for (const auto &PatternString : Req.ImplicitCheckNot) {
-    // Create a buffer with fake command line content in order to display the
-    // command line option responsible for the specific implicit CHECK-NOT.
-    std::string Prefix = "-implicit-check-not='";
-    std::string Suffix = "'";
-    std::unique_ptr<MemoryBuffer> CmdLine = MemoryBuffer::getMemBufferCopy(
-        Prefix + PatternString + Suffix, "command line");
-
-    StringRef PatternInBuffer =
-        CmdLine->getBuffer().substr(Prefix.size(), PatternString.size());
-    SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc());
-
-    ImplicitNegativeChecks.push_back(
-        FileCheckPattern(Check::CheckNot, PatternContext.get()));
-    ImplicitNegativeChecks.back().parsePattern(PatternInBuffer,
-                                               "IMPLICIT-CHECK", SM, Req);
-  }
-
-  std::vector<FileCheckPattern> DagNotMatches = ImplicitNegativeChecks;
-
-  // LineNumber keeps track of the line on which CheckPrefix instances are
-  // found.
-  unsigned LineNumber = 1;
-
-  while (1) {
-    Check::FileCheckType CheckTy;
-
-    // See if a prefix occurs in the memory buffer.
-    StringRef UsedPrefix;
-    StringRef AfterSuffix;
-    std::tie(UsedPrefix, AfterSuffix) =
-        FindFirstMatchingPrefix(PrefixRE, Buffer, LineNumber, CheckTy);
-    if (UsedPrefix.empty())
-      break;
-    assert(UsedPrefix.data() == Buffer.data() &&
-           "Failed to move Buffer's start forward, or pointed prefix outside "
-           "of the buffer!");
-    assert(AfterSuffix.data() >= Buffer.data() &&
-           AfterSuffix.data() < Buffer.data() + Buffer.size() &&
-           "Parsing after suffix doesn't start inside of buffer!");
-
-    // Location to use for error messages.
-    const char *UsedPrefixStart = UsedPrefix.data();
-
-    // Skip the buffer to the end of parsed suffix (or just prefix, if no good
-    // suffix was processed).
-    Buffer = AfterSuffix.empty() ? Buffer.drop_front(UsedPrefix.size())
-                                 : AfterSuffix;
-
-    // Complain about useful-looking but unsupported suffixes.
-    if (CheckTy == Check::CheckBadNot) {
-      SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Error,
-                      "unsupported -NOT combo on prefix '" + UsedPrefix + "'");
-      return true;
-    }
-
-    // Complain about invalid count specification.
-    if (CheckTy == Check::CheckBadCount) {
-      SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Error,
-                      "invalid count in -COUNT specification on prefix '" +
-                          UsedPrefix + "'");
-      return true;
-    }
-
-    // Okay, we found the prefix, yay. Remember the rest of the line, but ignore
-    // leading whitespace.
-    if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines))
-      Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
-
-    // Scan ahead to the end of line.
-    size_t EOL = Buffer.find_first_of("\n\r");
-
-    // Remember the location of the start of the pattern, for diagnostics.
-    SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data());
-
-    // Parse the pattern.
-    FileCheckPattern P(CheckTy, PatternContext.get(), LineNumber);
-    if (P.parsePattern(Buffer.substr(0, EOL), UsedPrefix, SM, Req))
-      return true;
-
-    // Verify that CHECK-LABEL lines do not define or use variables
-    if ((CheckTy == Check::CheckLabel) && P.hasVariable()) {
-      SM.PrintMessage(
-          SMLoc::getFromPointer(UsedPrefixStart), SourceMgr::DK_Error,
-          "found '" + UsedPrefix + "-LABEL:'"
-                                   " with variable definition or use");
-      return true;
-    }
-
-    Buffer = Buffer.substr(EOL);
-
-    // Verify that CHECK-NEXT/SAME/EMPTY lines have at least one CHECK line before them.
-    if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame ||
-         CheckTy == Check::CheckEmpty) &&
-        CheckStrings->empty()) {
-      StringRef Type = CheckTy == Check::CheckNext
-                           ? "NEXT"
-                           : CheckTy == Check::CheckEmpty ? "EMPTY" : "SAME";
-      SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),
-                      SourceMgr::DK_Error,
-                      "found '" + UsedPrefix + "-" + Type +
-                          "' without previous '" + UsedPrefix + ": line");
-      return true;
-    }
-
-    // Handle CHECK-DAG/-NOT.
-    if (CheckTy == Check::CheckDAG || CheckTy == Check::CheckNot) {
-      DagNotMatches.push_back(P);
-      continue;
-    }
-
-    // Okay, add the string we captured to the output vector and move on.
-    CheckStrings->emplace_back(P, UsedPrefix, PatternLoc);
-    std::swap(DagNotMatches, CheckStrings->back().DagNotStrings);
-    DagNotMatches = ImplicitNegativeChecks;
-  }
-
-  // Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first
-  // prefix as a filler for the error message.
-  if (!DagNotMatches.empty()) {
-    CheckStrings->emplace_back(
-        FileCheckPattern(Check::CheckEOF, PatternContext.get(), LineNumber + 1),
-        *Req.CheckPrefixes.begin(), SMLoc::getFromPointer(Buffer.data()));
-    std::swap(DagNotMatches, CheckStrings->back().DagNotStrings);
-  }
-
-  if (CheckStrings->empty()) {
-    errs() << "error: no check strings found with prefix"
-           << (Req.CheckPrefixes.size() > 1 ? "es " : " ");
-    auto I = Req.CheckPrefixes.begin();
-    auto E = Req.CheckPrefixes.end();
-    if (I != E) {
-      errs() << "\'" << *I << ":'";
-      ++I;
-    }
-    for (; I != E; ++I)
-      errs() << ", \'" << *I << ":'";
-
-    errs() << '\n';
-    return true;
-  }
-
-  return false;
-}
-
-static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM,
-                       StringRef Prefix, SMLoc Loc, const FileCheckPattern &Pat,
-                       int MatchedCount, StringRef Buffer, size_t MatchPos,
-                       size_t MatchLen, const FileCheckRequest &Req,
-                       std::vector<FileCheckDiag> *Diags) {
-  bool PrintDiag = true;
-  if (ExpectedMatch) {
-    if (!Req.Verbose)
-      return;
-    if (!Req.VerboseVerbose && Pat.getCheckTy() == Check::CheckEOF)
-      return;
-    // Due to their verbosity, we don't print verbose diagnostics here if we're
-    // gathering them for a different rendering, but we always print other
-    // diagnostics.
-    PrintDiag = !Diags;
-  }
-  SMRange MatchRange = ProcessMatchResult(
-      ExpectedMatch ? FileCheckDiag::MatchFoundAndExpected
-                    : FileCheckDiag::MatchFoundButExcluded,
-      SM, Loc, Pat.getCheckTy(), Buffer, MatchPos, MatchLen, Diags);
-  if (!PrintDiag)
-    return;
-
-  std::string Message = formatv("{0}: {1} string found in input",
-                                Pat.getCheckTy().getDescription(Prefix),
-                                (ExpectedMatch ? "expected" : "excluded"))
-                            .str();
-  if (Pat.getCount() > 1)
-    Message += formatv(" ({0} out of {1})", MatchedCount, Pat.getCount()).str();
-
-  SM.PrintMessage(
-      Loc, ExpectedMatch ? SourceMgr::DK_Remark : SourceMgr::DK_Error, Message);
-  SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note, "found here",
-                  {MatchRange});
-  Pat.printSubstitutions(SM, Buffer, MatchRange);
-}
-
-static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM,
-                       const FileCheckString &CheckStr, int MatchedCount,
-                       StringRef Buffer, size_t MatchPos, size_t MatchLen,
-                       FileCheckRequest &Req,
-                       std::vector<FileCheckDiag> *Diags) {
-  PrintMatch(ExpectedMatch, SM, CheckStr.Prefix, CheckStr.Loc, CheckStr.Pat,
-             MatchedCount, Buffer, MatchPos, MatchLen, Req, Diags);
-}
-
-static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM,
-                         StringRef Prefix, SMLoc Loc,
-                         const FileCheckPattern &Pat, int MatchedCount,
-                         StringRef Buffer, bool VerboseVerbose,
-                         std::vector<FileCheckDiag> *Diags, Error MatchErrors) {
-  assert(MatchErrors && "Called on successful match");
-  bool PrintDiag = true;
-  if (!ExpectedMatch) {
-    if (!VerboseVerbose) {
-      consumeError(std::move(MatchErrors));
-      return;
-    }
-    // Due to their verbosity, we don't print verbose diagnostics here if we're
-    // gathering them for a different rendering, but we always print other
-    // diagnostics.
-    PrintDiag = !Diags;
-  }
-
-  // If the current position is at the end of a line, advance to the start of
-  // the next line.
-  Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));
-  SMRange SearchRange = ProcessMatchResult(
-      ExpectedMatch ? FileCheckDiag::MatchNoneButExpected
-                    : FileCheckDiag::MatchNoneAndExcluded,
-      SM, Loc, Pat.getCheckTy(), Buffer, 0, Buffer.size(), Diags);
-  if (!PrintDiag) {
-    consumeError(std::move(MatchErrors));
-    return;
-  }
-
-  MatchErrors =
-      handleErrors(std::move(MatchErrors),
-                   [](const FileCheckErrorDiagnostic &E) { E.log(errs()); });
-
-  // No problem matching the string per se.
-  if (!MatchErrors)
-    return;
-  consumeError(std::move(MatchErrors));
-
-  // Print "not found" diagnostic.
-  std::string Message = formatv("{0}: {1} string not found in input",
-                                Pat.getCheckTy().getDescription(Prefix),
-                                (ExpectedMatch ? "expected" : "excluded"))
-                            .str();
-  if (Pat.getCount() > 1)
-    Message += formatv(" ({0} out of {1})", MatchedCount, Pat.getCount()).str();
-  SM.PrintMessage(
-      Loc, ExpectedMatch ? SourceMgr::DK_Error : SourceMgr::DK_Remark, Message);
-
-  // Print the "scanning from here" line.
-  SM.PrintMessage(SearchRange.Start, SourceMgr::DK_Note, "scanning from here");
-
-  // Allow the pattern to print additional information if desired.
-  Pat.printSubstitutions(SM, Buffer);
-
-  if (ExpectedMatch)
-    Pat.printFuzzyMatch(SM, Buffer, Diags);
-}
-
-static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM,
-                         const FileCheckString &CheckStr, int MatchedCount,
-                         StringRef Buffer, bool VerboseVerbose,
-                         std::vector<FileCheckDiag> *Diags, Error MatchErrors) {
-  PrintNoMatch(ExpectedMatch, SM, CheckStr.Prefix, CheckStr.Loc, CheckStr.Pat,
-               MatchedCount, Buffer, VerboseVerbose, Diags,
-               std::move(MatchErrors));
-}
-
-/// Counts the number of newlines in the specified range.
-static unsigned CountNumNewlinesBetween(StringRef Range,
-                                        const char *&FirstNewLine) {
-  unsigned NumNewLines = 0;
-  while (1) {
-    // Scan for newline.
-    Range = Range.substr(Range.find_first_of("\n\r"));
-    if (Range.empty())
-      return NumNewLines;
-
-    ++NumNewLines;
-
-    // Handle \n\r and \r\n as a single newline.
-    if (Range.size() > 1 && (Range[1] == '\n' || Range[1] == '\r') &&
-        (Range[0] != Range[1]))
-      Range = Range.substr(1);
-    Range = Range.substr(1);
-
-    if (NumNewLines == 1)
-      FirstNewLine = Range.begin();
-  }
-}
-
-size_t FileCheckString::Check(const SourceMgr &SM, StringRef Buffer,
-                              bool IsLabelScanMode, size_t &MatchLen,
-                              FileCheckRequest &Req,
-                              std::vector<FileCheckDiag> *Diags) const {
-  size_t LastPos = 0;
-  std::vector<const FileCheckPattern *> NotStrings;
-
-  // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL
-  // bounds; we have not processed variable definitions within the bounded block
-  // yet so cannot handle any final CHECK-DAG yet; this is handled when going
-  // over the block again (including the last CHECK-LABEL) in normal mode.
-  if (!IsLabelScanMode) {
-    // Match "dag strings" (with mixed "not strings" if any).
-    LastPos = CheckDag(SM, Buffer, NotStrings, Req, Diags);
-    if (LastPos == StringRef::npos)
-      return StringRef::npos;
-  }
-
-  // Match itself from the last position after matching CHECK-DAG.
-  size_t LastMatchEnd = LastPos;
-  size_t FirstMatchPos = 0;
-  // Go match the pattern Count times. Majority of patterns only match with
-  // count 1 though.
-  assert(Pat.getCount() != 0 && "pattern count can not be zero");
-  for (int i = 1; i <= Pat.getCount(); i++) {
-    StringRef MatchBuffer = Buffer.substr(LastMatchEnd);
-    size_t CurrentMatchLen;
-    // get a match at current start point
-    Expected<size_t> MatchResult = Pat.match(MatchBuffer, CurrentMatchLen, SM);
-
-    // report
-    if (!MatchResult) {
-      PrintNoMatch(true, SM, *this, i, MatchBuffer, Req.VerboseVerbose, Diags,
-                   MatchResult.takeError());
-      return StringRef::npos;
-    }
-    size_t MatchPos = *MatchResult;
-    PrintMatch(true, SM, *this, i, MatchBuffer, MatchPos, CurrentMatchLen, Req,
-               Diags);
-    if (i == 1)
-      FirstMatchPos = LastPos + MatchPos;
-
-    // move start point after the match
-    LastMatchEnd += MatchPos + CurrentMatchLen;
-  }
-  // Full match len counts from first match pos.
-  MatchLen = LastMatchEnd - FirstMatchPos;
-
-  // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT
-  // or CHECK-NOT
-  if (!IsLabelScanMode) {
-    size_t MatchPos = FirstMatchPos - LastPos;
-    StringRef MatchBuffer = Buffer.substr(LastPos);
-    StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos);
-
-    // If this check is a "CHECK-NEXT", verify that the previous match was on
-    // the previous line (i.e. that there is one newline between them).
-    if (CheckNext(SM, SkippedRegion)) {
-      ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine, SM, Loc,
-                         Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen,
-                         Diags, Req.Verbose);
-      return StringRef::npos;
-    }
-
-    // If this check is a "CHECK-SAME", verify that the previous match was on
-    // the same line (i.e. that there is no newline between them).
-    if (CheckSame(SM, SkippedRegion)) {
-      ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine, SM, Loc,
-                         Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen,
-                         Diags, Req.Verbose);
-      return StringRef::npos;
-    }
-
-    // If this match had "not strings", verify that they don't exist in the
-    // skipped region.
-    if (CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
-      return StringRef::npos;
-  }
-
-  return FirstMatchPos;
-}
-
-bool FileCheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
-  if (Pat.getCheckTy() != Check::CheckNext &&
-      Pat.getCheckTy() != Check::CheckEmpty)
-    return false;
-
-  Twine CheckName =
-      Prefix +
-      Twine(Pat.getCheckTy() == Check::CheckEmpty ? "-EMPTY" : "-NEXT");
-
-  // Count the number of newlines between the previous match and this one.
-  const char *FirstNewLine = nullptr;
-  unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
-
-  if (NumNewLines == 0) {
-    SM.PrintMessage(Loc, SourceMgr::DK_Error,
-                    CheckName + ": is on the same line as previous match");
-    SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
-                    "'next' match was here");
-    SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
-                    "previous match ended here");
-    return true;
-  }
-
-  if (NumNewLines != 1) {
-    SM.PrintMessage(Loc, SourceMgr::DK_Error,
-                    CheckName +
-                        ": is not on the line after the previous match");
-    SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
-                    "'next' match was here");
-    SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
-                    "previous match ended here");
-    SM.PrintMessage(SMLoc::getFromPointer(FirstNewLine), SourceMgr::DK_Note,
-                    "non-matching line after previous match is here");
-    return true;
-  }
-
-  return false;
-}
-
-bool FileCheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const {
-  if (Pat.getCheckTy() != Check::CheckSame)
-    return false;
-
-  // Count the number of newlines between the previous match and this one.
-  const char *FirstNewLine = nullptr;
-  unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
-
-  if (NumNewLines != 0) {
-    SM.PrintMessage(Loc, SourceMgr::DK_Error,
-                    Prefix +
-                        "-SAME: is not on the same line as the previous match");
-    SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
-                    "'next' match was here");
-    SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
-                    "previous match ended here");
-    return true;
-  }
-
-  return false;
-}
-
-bool FileCheckString::CheckNot(
-    const SourceMgr &SM, StringRef Buffer,
-    const std::vector<const FileCheckPattern *> &NotStrings,
-    const FileCheckRequest &Req, std::vector<FileCheckDiag> *Diags) const {
-  for (const FileCheckPattern *Pat : NotStrings) {
-    assert((Pat->getCheckTy() == Check::CheckNot) && "Expect CHECK-NOT!");
-
-    size_t MatchLen = 0;
-    Expected<size_t> MatchResult = Pat->match(Buffer, MatchLen, SM);
-
-    if (!MatchResult) {
-      PrintNoMatch(false, SM, Prefix, Pat->getLoc(), *Pat, 1, Buffer,
-                   Req.VerboseVerbose, Diags, MatchResult.takeError());
-      continue;
-    }
-    size_t Pos = *MatchResult;
-
-    PrintMatch(false, SM, Prefix, Pat->getLoc(), *Pat, 1, Buffer, Pos, MatchLen,
-               Req, Diags);
-
-    return true;
-  }
-
-  return false;
-}
-
-size_t
-FileCheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
-                          std::vector<const FileCheckPattern *> &NotStrings,
-                          const FileCheckRequest &Req,
-                          std::vector<FileCheckDiag> *Diags) const {
-  if (DagNotStrings.empty())
-    return 0;
-
-  // The start of the search range.
-  size_t StartPos = 0;
-
-  struct MatchRange {
-    size_t Pos;
-    size_t End;
-  };
-  // A sorted list of ranges for non-overlapping CHECK-DAG matches.  Match
-  // ranges are erased from this list once they are no longer in the search
-  // range.
-  std::list<MatchRange> MatchRanges;
-
-  // We need PatItr and PatEnd later for detecting the end of a CHECK-DAG
-  // group, so we don't use a range-based for loop here.
-  for (auto PatItr = DagNotStrings.begin(), PatEnd = DagNotStrings.end();
-       PatItr != PatEnd; ++PatItr) {
-    const FileCheckPattern &Pat = *PatItr;
-    assert((Pat.getCheckTy() == Check::CheckDAG ||
-            Pat.getCheckTy() == Check::CheckNot) &&
-           "Invalid CHECK-DAG or CHECK-NOT!");
-
-    if (Pat.getCheckTy() == Check::CheckNot) {
-      NotStrings.push_back(&Pat);
-      continue;
-    }
-
-    assert((Pat.getCheckTy() == Check::CheckDAG) && "Expect CHECK-DAG!");
-
-    // CHECK-DAG always matches from the start.
-    size_t MatchLen = 0, MatchPos = StartPos;
-
-    // Search for a match that doesn't overlap a previous match in this
-    // CHECK-DAG group.
-    for (auto MI = MatchRanges.begin(), ME = MatchRanges.end(); true; ++MI) {
-      StringRef MatchBuffer = Buffer.substr(MatchPos);
-      Expected<size_t> MatchResult = Pat.match(MatchBuffer, MatchLen, SM);
-      // With a group of CHECK-DAGs, a single mismatching means the match on
-      // that group of CHECK-DAGs fails immediately.
-      if (!MatchResult) {
-        PrintNoMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, MatchBuffer,
-                     Req.VerboseVerbose, Diags, MatchResult.takeError());
-        return StringRef::npos;
-      }
-      size_t MatchPosBuf = *MatchResult;
-      // Re-calc it as the offset relative to the start of the original string.
-      MatchPos += MatchPosBuf;
-      if (Req.VerboseVerbose)
-        PrintMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, Buffer, MatchPos,
-                   MatchLen, Req, Diags);
-      MatchRange M{MatchPos, MatchPos + MatchLen};
-      if (Req.AllowDeprecatedDagOverlap) {
-        // We don't need to track all matches in this mode, so we just maintain
-        // one match range that encompasses the current CHECK-DAG group's
-        // matches.
-        if (MatchRanges.empty())
-          MatchRanges.insert(MatchRanges.end(), M);
-        else {
-          auto Block = MatchRanges.begin();
-          Block->Pos = std::min(Block->Pos, M.Pos);
-          Block->End = std::max(Block->End, M.End);
-        }
-        break;
-      }
-      // Iterate previous matches until overlapping match or insertion point.
-      bool Overlap = false;
-      for (; MI != ME; ++MI) {
-        if (M.Pos < MI->End) {
-          // !Overlap => New match has no overlap and is before this old match.
-          // Overlap => New match overlaps this old match.
-          Overlap = MI->Pos < M.End;
-          break;
-        }
-      }
-      if (!Overlap) {
-        // Insert non-overlapping match into list.
-        MatchRanges.insert(MI, M);
-        break;
-      }
-      if (Req.VerboseVerbose) {
-        // Due to their verbosity, we don't print verbose diagnostics here if
-        // we're gathering them for a different rendering, but we always print
-        // other diagnostics.
-        if (!Diags) {
-          SMLoc OldStart = SMLoc::getFromPointer(Buffer.data() + MI->Pos);
-          SMLoc OldEnd = SMLoc::getFromPointer(Buffer.data() + MI->End);
-          SMRange OldRange(OldStart, OldEnd);
-          SM.PrintMessage(OldStart, SourceMgr::DK_Note,
-                          "match discarded, overlaps earlier DAG match here",
-                          {OldRange});
-        } else
-          Diags->rbegin()->MatchTy = FileCheckDiag::MatchFoundButDiscarded;
-      }
-      MatchPos = MI->End;
-    }
-    if (!Req.VerboseVerbose)
-      PrintMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, Buffer, MatchPos,
-                 MatchLen, Req, Diags);
-
-    // Handle the end of a CHECK-DAG group.
-    if (std::next(PatItr) == PatEnd ||
-        std::next(PatItr)->getCheckTy() == Check::CheckNot) {
-      if (!NotStrings.empty()) {
-        // If there are CHECK-NOTs between two CHECK-DAGs or from CHECK to
-        // CHECK-DAG, verify that there are no 'not' strings occurred in that
-        // region.
-        StringRef SkippedRegion =
-            Buffer.slice(StartPos, MatchRanges.begin()->Pos);
-        if (CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))
-          return StringRef::npos;
-        // Clear "not strings".
-        NotStrings.clear();
-      }
-      // All subsequent CHECK-DAGs and CHECK-NOTs should be matched from the
-      // end of this CHECK-DAG group's match range.
-      StartPos = MatchRanges.rbegin()->End;
-      // Don't waste time checking for (impossible) overlaps before that.
-      MatchRanges.clear();
-    }
-  }
-
-  return StartPos;
-}
-
-// A check prefix must contain only alphanumeric, hyphens and underscores.
-static bool ValidateCheckPrefix(StringRef CheckPrefix) {
-  static const Regex Validator("^[a-zA-Z0-9_-]*$");
-  return Validator.match(CheckPrefix);
-}
-
-bool FileCheck::ValidateCheckPrefixes() {
-  StringSet<> PrefixSet;
-
-  for (StringRef Prefix : Req.CheckPrefixes) {
-    // Reject empty prefixes.
-    if (Prefix == "")
-      return false;
-
-    if (!PrefixSet.insert(Prefix).second)
-      return false;
-
-    if (!ValidateCheckPrefix(Prefix))
-      return false;
-  }
-
-  return true;
-}
-
-Regex FileCheck::buildCheckPrefixRegex() {
-  // I don't think there's a way to specify an initial value for cl::list,
-  // so if nothing was specified, add the default
-  if (Req.CheckPrefixes.empty())
-    Req.CheckPrefixes.push_back("CHECK");
-
-  // We already validated the contents of CheckPrefixes so just concatenate
-  // them as alternatives.
-  SmallString<32> PrefixRegexStr;
-  for (StringRef Prefix : Req.CheckPrefixes) {
-    if (Prefix != Req.CheckPrefixes.front())
-      PrefixRegexStr.push_back('|');
-
-    PrefixRegexStr.append(Prefix);
-  }
-
-  return Regex(PrefixRegexStr);
-}
-
-Error FileCheckPatternContext::defineCmdlineVariables(
-    std::vector<std::string> &CmdlineDefines, SourceMgr &SM) {
-  assert(GlobalVariableTable.empty() && GlobalNumericVariableTable.empty() &&
-         "Overriding defined variable with command-line variable definitions");
-
-  if (CmdlineDefines.empty())
-    return Error::success();
-
-  // Create a string representing the vector of command-line definitions. Each
-  // definition is on its own line and prefixed with a definition number to
-  // clarify which definition a given diagnostic corresponds to.
-  unsigned I = 0;
-  Error Errs = Error::success();
-  std::string CmdlineDefsDiag;
-  SmallVector<std::pair<size_t, size_t>, 4> CmdlineDefsIndices;
-  for (StringRef CmdlineDef : CmdlineDefines) {
-    std::string DefPrefix = ("Global define #" + Twine(++I) + ": ").str();
-    size_t EqIdx = CmdlineDef.find('=');
-    if (EqIdx == StringRef::npos) {
-      CmdlineDefsIndices.push_back(std::make_pair(CmdlineDefsDiag.size(), 0));
-      continue;
-    }
-    // Numeric variable definition.
-    if (CmdlineDef[0] == '#') {
-      // Append a copy of the command-line definition adapted to use the same
-      // format as in the input file to be able to reuse
-      // parseNumericSubstitutionBlock.
-      CmdlineDefsDiag += (DefPrefix + CmdlineDef + " (parsed as: [[").str();
-      std::string SubstitutionStr = CmdlineDef;
-      SubstitutionStr[EqIdx] = ':';
-      CmdlineDefsIndices.push_back(
-          std::make_pair(CmdlineDefsDiag.size(), SubstitutionStr.size()));
-      CmdlineDefsDiag += (SubstitutionStr + Twine("]])\n")).str();
-    } else {
-      CmdlineDefsDiag += DefPrefix;
-      CmdlineDefsIndices.push_back(
-          std::make_pair(CmdlineDefsDiag.size(), CmdlineDef.size()));
-      CmdlineDefsDiag += (CmdlineDef + "\n").str();
-    }
-  }
-
-  // Create a buffer with fake command line content in order to display
-  // parsing diagnostic with location information and point to the
-  // global definition with invalid syntax.
-  std::unique_ptr<MemoryBuffer> CmdLineDefsDiagBuffer =
-      MemoryBuffer::getMemBufferCopy(CmdlineDefsDiag, "Global defines");
-  StringRef CmdlineDefsDiagRef = CmdLineDefsDiagBuffer->getBuffer();
-  SM.AddNewSourceBuffer(std::move(CmdLineDefsDiagBuffer), SMLoc());
-
-  for (std::pair<size_t, size_t> CmdlineDefIndices : CmdlineDefsIndices) {
-    StringRef CmdlineDef = CmdlineDefsDiagRef.substr(CmdlineDefIndices.first,
-                                                     CmdlineDefIndices.second);
-    if (CmdlineDef.empty()) {
-      Errs = joinErrors(
-          std::move(Errs),
-          FileCheckErrorDiagnostic::get(
-              SM, CmdlineDef, "missing equal sign in global definition"));
-      continue;
-    }
-
-    // Numeric variable definition.
-    if (CmdlineDef[0] == '#') {
-      // Now parse the definition both to check that the syntax is correct and
-      // to create the necessary class instance.
-      StringRef CmdlineDefExpr = CmdlineDef.substr(1);
-      Optional<FileCheckNumericVariable *> DefinedNumericVariable;
-      Expected<std::unique_ptr<FileCheckExpressionAST>> ExpressionASTResult =
-          FileCheckPattern::parseNumericSubstitutionBlock(
-              CmdlineDefExpr, DefinedNumericVariable, false, None, this, SM);
-      if (!ExpressionASTResult) {
-        Errs = joinErrors(std::move(Errs), ExpressionASTResult.takeError());
-        continue;
-      }
-      std::unique_ptr<FileCheckExpressionAST> ExpressionAST =
-          std::move(*ExpressionASTResult);
-      // Now evaluate the expression whose value this variable should be set
-      // to, since the expression of a command-line variable definition should
-      // only use variables defined earlier on the command-line. If not, this
-      // is an error and we report it.
-      Expected<uint64_t> Value = ExpressionAST->eval();
-      if (!Value) {
-        Errs = joinErrors(std::move(Errs), Value.takeError());
-        continue;
-      }
-
-      assert(DefinedNumericVariable && "No variable defined");
-      (*DefinedNumericVariable)->setValue(*Value);
-
-      // Record this variable definition.
-      GlobalNumericVariableTable[(*DefinedNumericVariable)->getName()] =
-          *DefinedNumericVariable;
-    } else {
-      // String variable definition.
-      std::pair<StringRef, StringRef> CmdlineNameVal = CmdlineDef.split('=');
-      StringRef CmdlineName = CmdlineNameVal.first;
-      StringRef OrigCmdlineName = CmdlineName;
-      Expected<FileCheckPattern::VariableProperties> ParseVarResult =
-          FileCheckPattern::parseVariable(CmdlineName, SM);
-      if (!ParseVarResult) {
-        Errs = joinErrors(std::move(Errs), ParseVarResult.takeError());
-        continue;
-      }
-      // Check that CmdlineName does not denote a pseudo variable is only
-      // composed of the parsed numeric variable. This catches cases like
-      // "FOO+2" in a "FOO+2=10" definition.
-      if (ParseVarResult->IsPseudo || !CmdlineName.empty()) {
-        Errs = joinErrors(std::move(Errs),
-                          FileCheckErrorDiagnostic::get(
-                              SM, OrigCmdlineName,
-                              "invalid name in string variable definition '" +
-                                  OrigCmdlineName + "'"));
-        continue;
-      }
-      StringRef Name = ParseVarResult->Name;
-
-      // Detect collisions between string and numeric variables when the former
-      // is created later than the latter.
-      if (GlobalNumericVariableTable.find(Name) !=
-          GlobalNumericVariableTable.end()) {
-        Errs = joinErrors(std::move(Errs), FileCheckErrorDiagnostic::get(
-                                               SM, Name,
-                                               "numeric variable with name '" +
-                                                   Name + "' already exists"));
-        continue;
-      }
-      GlobalVariableTable.insert(CmdlineNameVal);
-      // 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 this 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;
-    }
-  }
-
-  return Errs;
-}
-
-void FileCheckPatternContext::clearLocalVars() {
-  SmallVector<StringRef, 16> LocalPatternVars, LocalNumericVars;
-  for (const StringMapEntry<StringRef> &Var : GlobalVariableTable)
-    if (Var.first()[0] != '$')
-      LocalPatternVars.push_back(Var.first());
-
-  // 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();
-      LocalNumericVars.push_back(Var.first());
-    }
-
-  for (const auto &Var : LocalPatternVars)
-    GlobalVariableTable.erase(Var);
-  for (const auto &Var : LocalNumericVars)
-    GlobalNumericVariableTable.erase(Var);
-}
-
-bool FileCheck::checkInput(SourceMgr &SM, StringRef Buffer,
-                           std::vector<FileCheckDiag> *Diags) {
-  bool ChecksFailed = false;
-
-  unsigned i = 0, j = 0, e = CheckStrings->size();
-  while (true) {
-    StringRef CheckRegion;
-    if (j == e) {
-      CheckRegion = Buffer;
-    } else {
-      const FileCheckString &CheckLabelStr = (*CheckStrings)[j];
-      if (CheckLabelStr.Pat.getCheckTy() != Check::CheckLabel) {
-        ++j;
-        continue;
-      }
-
-      // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG
-      size_t MatchLabelLen = 0;
-      size_t MatchLabelPos =
-          CheckLabelStr.Check(SM, Buffer, true, MatchLabelLen, Req, Diags);
-      if (MatchLabelPos == StringRef::npos)
-        // Immediately bail if CHECK-LABEL fails, nothing else we can do.
-        return false;
-
-      CheckRegion = Buffer.substr(0, MatchLabelPos + MatchLabelLen);
-      Buffer = Buffer.substr(MatchLabelPos + MatchLabelLen);
-      ++j;
-    }
-
-    // Do not clear the first region as it's the one before the first
-    // CHECK-LABEL and it would clear variables defined on the command-line
-    // before they get used.
-    if (i != 0 && Req.EnableVarScope)
-      PatternContext->clearLocalVars();
-
-    for (; i != j; ++i) {
-      const FileCheckString &CheckStr = (*CheckStrings)[i];
-
-      // Check each string within the scanned region, including a second check
-      // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG)
-      size_t MatchLen = 0;
-      size_t MatchPos =
-          CheckStr.Check(SM, CheckRegion, false, MatchLen, Req, Diags);
-
-      if (MatchPos == StringRef::npos) {
-        ChecksFailed = true;
-        i = j;
-        break;
-      }
-
-      CheckRegion = CheckRegion.substr(MatchPos + MatchLen);
-    }
-
-    if (j == e)
-      break;
-  }
-
-  // Success if no checks failed.
-  return !ChecksFailed;
-}
+//===- FileCheck.cpp - Check that File's Contents match what is expected --===//\r
+//\r
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.\r
+// See https://llvm.org/LICENSE.txt for license information.\r
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\r
+//\r
+//===----------------------------------------------------------------------===//\r
+//\r
+// FileCheck does a line-by line check of a file that validates whether it\r
+// contains the expected content.  This is useful for regression tests etc.\r
+//\r
+// This file implements most of the API that will be used by the FileCheck utility\r
+// as well as various unittests.\r
+//===----------------------------------------------------------------------===//\r
+\r
+#include "llvm/Support/FileCheck.h"\r
+#include "FileCheckImpl.h"\r
+#include "llvm/ADT/StringSet.h"\r
+#include "llvm/ADT/Twine.h"\r
+#include "llvm/Support/FormatVariadic.h"\r
+#include <cstdint>\r
+#include <list>\r
+#include <tuple>\r
+#include <utility>\r
+\r
+using namespace llvm;\r
+\r
+Expected<uint64_t> FileCheckNumericVariableUse::eval() const {\r
+  Optional<uint64_t> Value = NumericVariable->getValue();\r
+  if (Value)\r
+    return *Value;\r
+\r
+  return make_error<FileCheckUndefVarError>(Name);\r
+}\r
+\r
+Expected<uint64_t> FileCheckASTBinop::eval() const {\r
+  Expected<uint64_t> LeftOp = LeftOperand->eval();\r
+  Expected<uint64_t> RightOp = RightOperand->eval();\r
+\r
+  // Bubble up any error (e.g. undefined variables) in the recursive\r
+  // evaluation.\r
+  if (!LeftOp || !RightOp) {\r
+    Error Err = Error::success();\r
+    if (!LeftOp)\r
+      Err = joinErrors(std::move(Err), LeftOp.takeError());\r
+    if (!RightOp)\r
+      Err = joinErrors(std::move(Err), RightOp.takeError());\r
+    return std::move(Err);\r
+  }\r
+\r
+  return EvalBinop(*LeftOp, *RightOp);\r
+}\r
+\r
+Expected<std::string> FileCheckNumericSubstitution::getResult() const {\r
+  Expected<uint64_t> EvaluatedValue = ExpressionAST->eval();\r
+  if (!EvaluatedValue)\r
+    return EvaluatedValue.takeError();\r
+  return utostr(*EvaluatedValue);\r
+}\r
+\r
+Expected<std::string> FileCheckStringSubstitution::getResult() const {\r
+  // Look up the value and escape it so that we can put it into the regex.\r
+  Expected<StringRef> VarVal = Context->getPatternVarValue(FromStr);\r
+  if (!VarVal)\r
+    return VarVal.takeError();\r
+  return Regex::escape(*VarVal);\r
+}\r
+\r
+bool FileCheckPattern::isValidVarNameStart(char C) {\r
+  return C == '_' || isalpha(C);\r
+}\r
+\r
+Expected<FileCheckPattern::VariableProperties>\r
+FileCheckPattern::parseVariable(StringRef &Str, const SourceMgr &SM) {\r
+  if (Str.empty())\r
+    return FileCheckErrorDiagnostic::get(SM, Str, "empty variable name");\r
+\r
+  bool ParsedOneChar = false;\r
+  unsigned I = 0;\r
+  bool IsPseudo = Str[0] == '@';\r
+\r
+  // Global vars start with '$'.\r
+  if (Str[0] == '$' || IsPseudo)\r
+    ++I;\r
+\r
+  for (unsigned E = Str.size(); I != E; ++I) {\r
+    if (!ParsedOneChar && !isValidVarNameStart(Str[I]))\r
+      return FileCheckErrorDiagnostic::get(SM, Str, "invalid variable name");\r
+\r
+    // Variable names are composed of alphanumeric characters and underscores.\r
+    if (Str[I] != '_' && !isalnum(Str[I]))\r
+      break;\r
+    ParsedOneChar = true;\r
+  }\r
+\r
+  StringRef Name = Str.take_front(I);\r
+  Str = Str.substr(I);\r
+  return VariableProperties {Name, IsPseudo};\r
+}\r
+\r
+// StringRef holding all characters considered as horizontal whitespaces by\r
+// FileCheck input canonicalization.\r
+constexpr StringLiteral SpaceChars = " \t";\r
+\r
+// Parsing helper function that strips the first character in S and returns it.\r
+static char popFront(StringRef &S) {\r
+  char C = S.front();\r
+  S = S.drop_front();\r
+  return C;\r
+}\r
+\r
+char FileCheckUndefVarError::ID = 0;\r
+char FileCheckErrorDiagnostic::ID = 0;\r
+char FileCheckNotFoundError::ID = 0;\r
+\r
+Expected<FileCheckNumericVariable *>\r
+FileCheckPattern::parseNumericVariableDefinition(\r
+    StringRef &Expr, FileCheckPatternContext *Context,\r
+    Optional<size_t> LineNumber, const SourceMgr &SM) {\r
+  Expected<VariableProperties> ParseVarResult = parseVariable(Expr, SM);\r
+  if (!ParseVarResult)\r
+    return ParseVarResult.takeError();\r
+  StringRef Name = ParseVarResult->Name;\r
+\r
+  if (ParseVarResult->IsPseudo)\r
+    return FileCheckErrorDiagnostic::get(\r
+        SM, Name, "definition of pseudo numeric variable unsupported");\r
+\r
+  // Detect collisions between string and numeric variables when the latter\r
+  // is created later than the former.\r
+  if (Context->DefinedVariableTable.find(Name) !=\r
+      Context->DefinedVariableTable.end())\r
+    return FileCheckErrorDiagnostic::get(\r
+        SM, Name, "string variable with name '" + Name + "' already exists");\r
+\r
+  Expr = Expr.ltrim(SpaceChars);\r
+  if (!Expr.empty())\r
+    return FileCheckErrorDiagnostic::get(\r
+        SM, Expr, "unexpected characters after numeric variable name");\r
+\r
+  FileCheckNumericVariable *DefinedNumericVariable;\r
+  auto VarTableIter = Context->GlobalNumericVariableTable.find(Name);\r
+  if (VarTableIter != Context->GlobalNumericVariableTable.end())\r
+    DefinedNumericVariable = VarTableIter->second;\r
+  else\r
+    DefinedNumericVariable = Context->makeNumericVariable(Name, LineNumber);\r
+\r
+  return DefinedNumericVariable;\r
+}\r
+\r
+Expected<std::unique_ptr<FileCheckNumericVariableUse>>\r
+FileCheckPattern::parseNumericVariableUse(StringRef Name, bool IsPseudo,\r
+                                          Optional<size_t> LineNumber,\r
+                                          FileCheckPatternContext *Context,\r
+                                          const SourceMgr &SM) {\r
+  if (IsPseudo && !Name.equals("@LINE"))\r
+    return FileCheckErrorDiagnostic::get(\r
+        SM, Name, "invalid pseudo numeric variable '" + Name + "'");\r
+\r
+  // Numeric variable definitions and uses are parsed in the order in which\r
+  // they appear in the CHECK patterns. For each definition, the pointer to the\r
+  // class instance of the corresponding numeric variable definition is stored\r
+  // in GlobalNumericVariableTable in parsePattern. Therefore, if the pointer\r
+  // we get below is null, it means no such variable was defined before. When\r
+  // that happens, we create a dummy variable so that parsing can continue. All\r
+  // uses of undefined variables, whether string or numeric, are then diagnosed\r
+  // in printSubstitutions() after failing to match.\r
+  auto VarTableIter = Context->GlobalNumericVariableTable.find(Name);\r
+  FileCheckNumericVariable *NumericVariable;\r
+  if (VarTableIter != Context->GlobalNumericVariableTable.end())\r
+    NumericVariable = VarTableIter->second;\r
+  else {\r
+    NumericVariable = Context->makeNumericVariable(Name);\r
+    Context->GlobalNumericVariableTable[Name] = NumericVariable;\r
+  }\r
+\r
+  Optional<size_t> DefLineNumber = NumericVariable->getDefLineNumber();\r
+  if (DefLineNumber && LineNumber && *DefLineNumber == *LineNumber)\r
+    return FileCheckErrorDiagnostic::get(\r
+        SM, Name,\r
+        "numeric variable '" + Name +\r
+            "' defined earlier in the same CHECK directive");\r
+\r
+  return std::make_unique<FileCheckNumericVariableUse>(Name, NumericVariable);\r
+}\r
+\r
+Expected<std::unique_ptr<FileCheckExpressionAST>>\r
+FileCheckPattern::parseNumericOperand(StringRef &Expr, AllowedOperand AO,\r
+                                      Optional<size_t> LineNumber,\r
+                                      FileCheckPatternContext *Context,\r
+                                      const SourceMgr &SM) {\r
+  if (AO == AllowedOperand::LineVar || AO == AllowedOperand::Any) {\r
+    // Try to parse as a numeric variable use.\r
+    Expected<FileCheckPattern::VariableProperties> ParseVarResult =\r
+        parseVariable(Expr, SM);\r
+    if (ParseVarResult)\r
+      return parseNumericVariableUse(ParseVarResult->Name,\r
+                                     ParseVarResult->IsPseudo, LineNumber,\r
+                                     Context, SM);\r
+    if (AO == AllowedOperand::LineVar)\r
+      return ParseVarResult.takeError();\r
+    // Ignore the error and retry parsing as a literal.\r
+    consumeError(ParseVarResult.takeError());\r
+  }\r
+\r
+  // Otherwise, parse it as a literal.\r
+  uint64_t LiteralValue;\r
+  if (!Expr.consumeInteger(/*Radix=*/10, LiteralValue))\r
+    return std::make_unique<FileCheckExpressionLiteral>(LiteralValue);\r
+\r
+  return FileCheckErrorDiagnostic::get(SM, Expr,\r
+                                       "invalid operand format '" + Expr + "'");\r
+}\r
+\r
+static uint64_t add(uint64_t LeftOp, uint64_t RightOp) {\r
+  return LeftOp + RightOp;\r
+}\r
+\r
+static uint64_t sub(uint64_t LeftOp, uint64_t RightOp) {\r
+  return LeftOp - RightOp;\r
+}\r
+\r
+Expected<std::unique_ptr<FileCheckExpressionAST>> FileCheckPattern::parseBinop(\r
+    StringRef &Expr, std::unique_ptr<FileCheckExpressionAST> LeftOp,\r
+    bool IsLegacyLineExpr, Optional<size_t> LineNumber,\r
+    FileCheckPatternContext *Context, const SourceMgr &SM) {\r
+  Expr = Expr.ltrim(SpaceChars);\r
+  if (Expr.empty())\r
+    return std::move(LeftOp);\r
+\r
+  // Check if this is a supported operation and select a function to perform\r
+  // it.\r
+  SMLoc OpLoc = SMLoc::getFromPointer(Expr.data());\r
+  char Operator = popFront(Expr);\r
+  binop_eval_t EvalBinop;\r
+  switch (Operator) {\r
+  case '+':\r
+    EvalBinop = add;\r
+    break;\r
+  case '-':\r
+    EvalBinop = sub;\r
+    break;\r
+  default:\r
+    return FileCheckErrorDiagnostic::get(\r
+        SM, OpLoc, Twine("unsupported operation '") + Twine(Operator) + "'");\r
+  }\r
+\r
+  // Parse right operand.\r
+  Expr = Expr.ltrim(SpaceChars);\r
+  if (Expr.empty())\r
+    return FileCheckErrorDiagnostic::get(SM, Expr,\r
+                                         "missing operand in expression");\r
+  // The second operand in a legacy @LINE expression is always a literal.\r
+  AllowedOperand AO =\r
+      IsLegacyLineExpr ? AllowedOperand::Literal : AllowedOperand::Any;\r
+  Expected<std::unique_ptr<FileCheckExpressionAST>> RightOpResult =\r
+      parseNumericOperand(Expr, AO, LineNumber, Context, SM);\r
+  if (!RightOpResult)\r
+    return RightOpResult;\r
+\r
+  Expr = Expr.ltrim(SpaceChars);\r
+  return std::make_unique<FileCheckASTBinop>(EvalBinop, std::move(LeftOp),\r
+                                              std::move(*RightOpResult));\r
+}\r
+\r
+Expected<std::unique_ptr<FileCheckExpressionAST>>\r
+FileCheckPattern::parseNumericSubstitutionBlock(\r
+    StringRef Expr,\r
+    Optional<FileCheckNumericVariable *> &DefinedNumericVariable,\r
+    bool IsLegacyLineExpr, Optional<size_t> LineNumber,\r
+    FileCheckPatternContext *Context, const SourceMgr &SM) {\r
+  std::unique_ptr<FileCheckExpressionAST> ExpressionAST = nullptr;\r
+  StringRef DefExpr = StringRef();\r
+  DefinedNumericVariable = None;\r
+  // Save variable definition expression if any.\r
+  size_t DefEnd = Expr.find(':');\r
+  if (DefEnd != StringRef::npos) {\r
+    DefExpr = Expr.substr(0, DefEnd);\r
+    Expr = Expr.substr(DefEnd + 1);\r
+  }\r
+\r
+  // Parse the expression itself.\r
+  Expr = Expr.ltrim(SpaceChars);\r
+  if (!Expr.empty()) {\r
+    // The first operand in a legacy @LINE expression is always the @LINE\r
+    // pseudo variable.\r
+    AllowedOperand AO =\r
+        IsLegacyLineExpr ? AllowedOperand::LineVar : AllowedOperand::Any;\r
+    Expected<std::unique_ptr<FileCheckExpressionAST>> ParseResult =\r
+        parseNumericOperand(Expr, AO, LineNumber, Context, SM);\r
+    while (ParseResult && !Expr.empty()) {\r
+      ParseResult = parseBinop(Expr, std::move(*ParseResult), IsLegacyLineExpr,\r
+                               LineNumber, Context, SM);\r
+      // Legacy @LINE expressions only allow 2 operands.\r
+      if (ParseResult && IsLegacyLineExpr && !Expr.empty())\r
+        return FileCheckErrorDiagnostic::get(\r
+            SM, Expr,\r
+            "unexpected characters at end of expression '" + Expr + "'");\r
+    }\r
+    if (!ParseResult)\r
+      return ParseResult;\r
+    ExpressionAST = std::move(*ParseResult);\r
+  }\r
+\r
+  // Parse the numeric variable definition.\r
+  if (DefEnd != StringRef::npos) {\r
+    DefExpr = DefExpr.ltrim(SpaceChars);\r
+    Expected<FileCheckNumericVariable *> ParseResult =\r
+        parseNumericVariableDefinition(DefExpr, Context, LineNumber, SM);\r
+\r
+    if (!ParseResult)\r
+      return ParseResult.takeError();\r
+    DefinedNumericVariable = *ParseResult;\r
+  }\r
+\r
+  return std::move(ExpressionAST);\r
+}\r
+\r
+bool FileCheckPattern::parsePattern(StringRef PatternStr, StringRef Prefix,\r
+                                    SourceMgr &SM,\r
+                                    const FileCheckRequest &Req) {\r
+  bool MatchFullLinesHere = Req.MatchFullLines && CheckTy != Check::CheckNot;\r
+  IgnoreCase = Req.IgnoreCase;\r
+\r
+  PatternLoc = SMLoc::getFromPointer(PatternStr.data());\r
+\r
+  if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines))\r
+    // Ignore trailing whitespace.\r
+    while (!PatternStr.empty() &&\r
+           (PatternStr.back() == ' ' || PatternStr.back() == '\t'))\r
+      PatternStr = PatternStr.substr(0, PatternStr.size() - 1);\r
+\r
+  // Check that there is something on the line.\r
+  if (PatternStr.empty() && CheckTy != Check::CheckEmpty) {\r
+    SM.PrintMessage(PatternLoc, SourceMgr::DK_Error,\r
+                    "found empty check string with prefix '" + Prefix + ":'");\r
+    return true;\r
+  }\r
+\r
+  if (!PatternStr.empty() && CheckTy == Check::CheckEmpty) {\r
+    SM.PrintMessage(\r
+        PatternLoc, SourceMgr::DK_Error,\r
+        "found non-empty check string for empty check with prefix '" + Prefix +\r
+            ":'");\r
+    return true;\r
+  }\r
+\r
+  if (CheckTy == Check::CheckEmpty) {\r
+    RegExStr = "(\n$)";\r
+    return false;\r
+  }\r
+\r
+  // Check to see if this is a fixed string, or if it has regex pieces.\r
+  if (!MatchFullLinesHere &&\r
+      (PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos &&\r
+                                 PatternStr.find("[[") == StringRef::npos))) {\r
+    FixedStr = PatternStr;\r
+    return false;\r
+  }\r
+\r
+  if (MatchFullLinesHere) {\r
+    RegExStr += '^';\r
+    if (!Req.NoCanonicalizeWhiteSpace)\r
+      RegExStr += " *";\r
+  }\r
+\r
+  // Paren value #0 is for the fully matched string.  Any new parenthesized\r
+  // values add from there.\r
+  unsigned CurParen = 1;\r
+\r
+  // Otherwise, there is at least one regex piece.  Build up the regex pattern\r
+  // by escaping scary characters in fixed strings, building up one big regex.\r
+  while (!PatternStr.empty()) {\r
+    // RegEx matches.\r
+    if (PatternStr.startswith("{{")) {\r
+      // This is the start of a regex match.  Scan for the }}.\r
+      size_t End = PatternStr.find("}}");\r
+      if (End == StringRef::npos) {\r
+        SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),\r
+                        SourceMgr::DK_Error,\r
+                        "found start of regex string with no end '}}'");\r
+        return true;\r
+      }\r
+\r
+      // Enclose {{}} patterns in parens just like [[]] even though we're not\r
+      // capturing the result for any purpose.  This is required in case the\r
+      // expression contains an alternation like: CHECK:  abc{{x|z}}def.  We\r
+      // want this to turn into: "abc(x|z)def" not "abcx|zdef".\r
+      RegExStr += '(';\r
+      ++CurParen;\r
+\r
+      if (AddRegExToRegEx(PatternStr.substr(2, End - 2), CurParen, SM))\r
+        return true;\r
+      RegExStr += ')';\r
+\r
+      PatternStr = PatternStr.substr(End + 2);\r
+      continue;\r
+    }\r
+\r
+    // String and numeric substitution blocks. Pattern substitution blocks come\r
+    // in two forms: [[foo:.*]] and [[foo]]. The former matches .* (or some\r
+    // other regex) and assigns it to the string variable 'foo'. The latter\r
+    // substitutes foo's value. Numeric substitution blocks recognize the same\r
+    // form as string ones, but start with a '#' sign after the double\r
+    // brackets. They also accept a combined form which sets a numeric variable\r
+    // to the evaluation of an expression. Both string and numeric variable\r
+    // names must satisfy the regular expression "[a-zA-Z_][0-9a-zA-Z_]*" to be\r
+    // valid, as this helps catch some common errors.\r
+    if (PatternStr.startswith("[[")) {\r
+      StringRef UnparsedPatternStr = PatternStr.substr(2);\r
+      // Find the closing bracket pair ending the match.  End is going to be an\r
+      // offset relative to the beginning of the match string.\r
+      size_t End = FindRegexVarEnd(UnparsedPatternStr, SM);\r
+      StringRef MatchStr = UnparsedPatternStr.substr(0, End);\r
+      bool IsNumBlock = MatchStr.consume_front("#");\r
+\r
+      if (End == StringRef::npos) {\r
+        SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),\r
+                        SourceMgr::DK_Error,\r
+                        "Invalid substitution block, no ]] found");\r
+        return true;\r
+      }\r
+      // Strip the substitution block we are parsing. End points to the start\r
+      // of the "]]" closing the expression so account for it in computing the\r
+      // index of the first unparsed character.\r
+      PatternStr = UnparsedPatternStr.substr(End + 2);\r
+\r
+      bool IsDefinition = false;\r
+      bool SubstNeeded = false;\r
+      // Whether the substitution block is a legacy use of @LINE with string\r
+      // substitution block syntax.\r
+      bool IsLegacyLineExpr = false;\r
+      StringRef DefName;\r
+      StringRef SubstStr;\r
+      StringRef MatchRegexp;\r
+      size_t SubstInsertIdx = RegExStr.size();\r
+\r
+      // Parse string variable or legacy @LINE expression.\r
+      if (!IsNumBlock) {\r
+        size_t VarEndIdx = MatchStr.find(":");\r
+        size_t SpacePos = MatchStr.substr(0, VarEndIdx).find_first_of(" \t");\r
+        if (SpacePos != StringRef::npos) {\r
+          SM.PrintMessage(SMLoc::getFromPointer(MatchStr.data() + SpacePos),\r
+                          SourceMgr::DK_Error, "unexpected whitespace");\r
+          return true;\r
+        }\r
+\r
+        // Get the name (e.g. "foo") and verify it is well formed.\r
+        StringRef OrigMatchStr = MatchStr;\r
+        Expected<FileCheckPattern::VariableProperties> ParseVarResult =\r
+            parseVariable(MatchStr, SM);\r
+        if (!ParseVarResult) {\r
+          logAllUnhandledErrors(ParseVarResult.takeError(), errs());\r
+          return true;\r
+        }\r
+        StringRef Name = ParseVarResult->Name;\r
+        bool IsPseudo = ParseVarResult->IsPseudo;\r
+\r
+        IsDefinition = (VarEndIdx != StringRef::npos);\r
+        SubstNeeded = !IsDefinition;\r
+        if (IsDefinition) {\r
+          if ((IsPseudo || !MatchStr.consume_front(":"))) {\r
+            SM.PrintMessage(SMLoc::getFromPointer(Name.data()),\r
+                            SourceMgr::DK_Error,\r
+                            "invalid name in string variable definition");\r
+            return true;\r
+          }\r
+\r
+          // Detect collisions between string and numeric variables when the\r
+          // former is created later than the latter.\r
+          if (Context->GlobalNumericVariableTable.find(Name) !=\r
+              Context->GlobalNumericVariableTable.end()) {\r
+            SM.PrintMessage(\r
+                SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,\r
+                "numeric variable with name '" + Name + "' already exists");\r
+            return true;\r
+          }\r
+          DefName = Name;\r
+          MatchRegexp = MatchStr;\r
+        } else {\r
+          if (IsPseudo) {\r
+            MatchStr = OrigMatchStr;\r
+            IsLegacyLineExpr = IsNumBlock = true;\r
+          } else\r
+            SubstStr = Name;\r
+        }\r
+      }\r
+\r
+      // Parse numeric substitution block.\r
+      std::unique_ptr<FileCheckExpressionAST> ExpressionAST;\r
+      Optional<FileCheckNumericVariable *> DefinedNumericVariable;\r
+      if (IsNumBlock) {\r
+        Expected<std::unique_ptr<FileCheckExpressionAST>> ParseResult =\r
+            parseNumericSubstitutionBlock(MatchStr, DefinedNumericVariable,\r
+                                          IsLegacyLineExpr, LineNumber, Context,\r
+                                          SM);\r
+        if (!ParseResult) {\r
+          logAllUnhandledErrors(ParseResult.takeError(), errs());\r
+          return true;\r
+        }\r
+        ExpressionAST = std::move(*ParseResult);\r
+        SubstNeeded = ExpressionAST != nullptr;\r
+        if (DefinedNumericVariable) {\r
+          IsDefinition = true;\r
+          DefName = (*DefinedNumericVariable)->getName();\r
+        }\r
+        if (SubstNeeded)\r
+          SubstStr = MatchStr;\r
+        else\r
+          MatchRegexp = "[0-9]+";\r
+      }\r
+\r
+      // Handle variable definition: [[<def>:(...)]] and [[#(...)<def>:(...)]].\r
+      if (IsDefinition) {\r
+        RegExStr += '(';\r
+        ++SubstInsertIdx;\r
+\r
+        if (IsNumBlock) {\r
+          FileCheckNumericVariableMatch NumericVariableDefinition = {\r
+              *DefinedNumericVariable, CurParen};\r
+          NumericVariableDefs[DefName] = NumericVariableDefinition;\r
+          // This store is done here rather than in match() to allow\r
+          // parseNumericVariableUse() to get the pointer to the class instance\r
+          // of the right variable definition corresponding to a given numeric\r
+          // variable use.\r
+          Context->GlobalNumericVariableTable[DefName] =\r
+              *DefinedNumericVariable;\r
+        } else {\r
+          VariableDefs[DefName] = CurParen;\r
+          // Mark string variable as defined to detect collisions between\r
+          // string and numeric variables in parseNumericVariableUse() and\r
+          // defineCmdlineVariables() when the latter is created later than the\r
+          // former. We cannot reuse GlobalVariableTable for this by populating\r
+          // it with an empty string since we would then lose the ability to\r
+          // detect the use of an undefined variable in match().\r
+          Context->DefinedVariableTable[DefName] = true;\r
+        }\r
+\r
+        ++CurParen;\r
+      }\r
+\r
+      if (!MatchRegexp.empty() && AddRegExToRegEx(MatchRegexp, CurParen, SM))\r
+        return true;\r
+\r
+      if (IsDefinition)\r
+        RegExStr += ')';\r
+\r
+      // Handle substitutions: [[foo]] and [[#<foo expr>]].\r
+      if (SubstNeeded) {\r
+        // Handle substitution of string variables that were defined earlier on\r
+        // the same line by emitting a backreference. Expressions do not\r
+        // support substituting a numeric variable defined on the same line.\r
+        if (!IsNumBlock && VariableDefs.find(SubstStr) != VariableDefs.end()) {\r
+          unsigned CaptureParenGroup = VariableDefs[SubstStr];\r
+          if (CaptureParenGroup < 1 || CaptureParenGroup > 9) {\r
+            SM.PrintMessage(SMLoc::getFromPointer(SubstStr.data()),\r
+                            SourceMgr::DK_Error,\r
+                            "Can't back-reference more than 9 variables");\r
+            return true;\r
+          }\r
+          AddBackrefToRegEx(CaptureParenGroup);\r
+        } else {\r
+          // Handle substitution of string variables ([[<var>]]) defined in\r
+          // previous CHECK patterns, and substitution of expressions.\r
+          FileCheckSubstitution *Substitution =\r
+              IsNumBlock\r
+                  ? Context->makeNumericSubstitution(\r
+                        SubstStr, std::move(ExpressionAST), SubstInsertIdx)\r
+                  : Context->makeStringSubstitution(SubstStr, SubstInsertIdx);\r
+          Substitutions.push_back(Substitution);\r
+        }\r
+      }\r
+    }\r
+\r
+    // Handle fixed string matches.\r
+    // Find the end, which is the start of the next regex.\r
+    size_t FixedMatchEnd = PatternStr.find("{{");\r
+    FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[["));\r
+    RegExStr += Regex::escape(PatternStr.substr(0, FixedMatchEnd));\r
+    PatternStr = PatternStr.substr(FixedMatchEnd);\r
+  }\r
+\r
+  if (MatchFullLinesHere) {\r
+    if (!Req.NoCanonicalizeWhiteSpace)\r
+      RegExStr += " *";\r
+    RegExStr += '$';\r
+  }\r
+\r
+  return false;\r
+}\r
+\r
+bool FileCheckPattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM) {\r
+  Regex R(RS);\r
+  std::string Error;\r
+  if (!R.isValid(Error)) {\r
+    SM.PrintMessage(SMLoc::getFromPointer(RS.data()), SourceMgr::DK_Error,\r
+                    "invalid regex: " + Error);\r
+    return true;\r
+  }\r
+\r
+  RegExStr += RS.str();\r
+  CurParen += R.getNumMatches();\r
+  return false;\r
+}\r
+\r
+void FileCheckPattern::AddBackrefToRegEx(unsigned BackrefNum) {\r
+  assert(BackrefNum >= 1 && BackrefNum <= 9 && "Invalid backref number");\r
+  std::string Backref = std::string("\\") + std::string(1, '0' + BackrefNum);\r
+  RegExStr += Backref;\r
+}\r
+\r
+Expected<size_t> FileCheckPattern::match(StringRef Buffer, size_t &MatchLen,\r
+                                         const SourceMgr &SM) const {\r
+  // If this is the EOF pattern, match it immediately.\r
+  if (CheckTy == Check::CheckEOF) {\r
+    MatchLen = 0;\r
+    return Buffer.size();\r
+  }\r
+\r
+  // If this is a fixed string pattern, just match it now.\r
+  if (!FixedStr.empty()) {\r
+    MatchLen = FixedStr.size();\r
+    size_t Pos = IgnoreCase ? Buffer.find_lower(FixedStr)\r
+                            : Buffer.find(FixedStr);\r
+    if (Pos == StringRef::npos)\r
+      return make_error<FileCheckNotFoundError>();\r
+    return Pos;\r
+  }\r
+\r
+  // Regex match.\r
+\r
+  // If there are substitutions, we need to create a temporary string with the\r
+  // actual value.\r
+  StringRef RegExToMatch = RegExStr;\r
+  std::string TmpStr;\r
+  if (!Substitutions.empty()) {\r
+    TmpStr = RegExStr;\r
+    if (LineNumber)\r
+      Context->LineVariable->setValue(*LineNumber);\r
+\r
+    size_t InsertOffset = 0;\r
+    // Substitute all string variables and expressions whose values are only\r
+    // now known. Use of string variables defined on the same line are handled\r
+    // by back-references.\r
+    for (const auto &Substitution : Substitutions) {\r
+      // Substitute and check for failure (e.g. use of undefined variable).\r
+      Expected<std::string> Value = Substitution->getResult();\r
+      if (!Value)\r
+        return Value.takeError();\r
+\r
+      // Plop it into the regex at the adjusted offset.\r
+      TmpStr.insert(TmpStr.begin() + Substitution->getIndex() + InsertOffset,\r
+                    Value->begin(), Value->end());\r
+      InsertOffset += Value->size();\r
+    }\r
+\r
+    // Match the newly constructed regex.\r
+    RegExToMatch = TmpStr;\r
+  }\r
+\r
+  SmallVector<StringRef, 4> MatchInfo;\r
+  unsigned int Flags = Regex::Newline;\r
+  if (IgnoreCase)\r
+    Flags |= Regex::IgnoreCase;\r
+  if (!Regex(RegExToMatch, Flags).match(Buffer, &MatchInfo))\r
+    return make_error<FileCheckNotFoundError>();\r
+\r
+  // Successful regex match.\r
+  assert(!MatchInfo.empty() && "Didn't get any match");\r
+  StringRef FullMatch = MatchInfo[0];\r
+\r
+  // If this defines any string variables, remember their values.\r
+  for (const auto &VariableDef : VariableDefs) {\r
+    assert(VariableDef.second < MatchInfo.size() && "Internal paren error");\r
+    Context->GlobalVariableTable[VariableDef.first] =\r
+        MatchInfo[VariableDef.second];\r
+  }\r
+\r
+  // If this defines any numeric variables, remember their values.\r
+  for (const auto &NumericVariableDef : NumericVariableDefs) {\r
+    const FileCheckNumericVariableMatch &NumericVariableMatch =\r
+        NumericVariableDef.getValue();\r
+    unsigned CaptureParenGroup = NumericVariableMatch.CaptureParenGroup;\r
+    assert(CaptureParenGroup < MatchInfo.size() && "Internal paren error");\r
+    FileCheckNumericVariable *DefinedNumericVariable =\r
+        NumericVariableMatch.DefinedNumericVariable;\r
+\r
+    StringRef MatchedValue = MatchInfo[CaptureParenGroup];\r
+    uint64_t Val;\r
+    if (MatchedValue.getAsInteger(10, Val))\r
+      return FileCheckErrorDiagnostic::get(SM, MatchedValue,\r
+                                           "Unable to represent numeric value");\r
+    DefinedNumericVariable->setValue(Val);\r
+  }\r
+\r
+  // Like CHECK-NEXT, CHECK-EMPTY's match range is considered to start after\r
+  // the required preceding newline, which is consumed by the pattern in the\r
+  // case of CHECK-EMPTY but not CHECK-NEXT.\r
+  size_t MatchStartSkip = CheckTy == Check::CheckEmpty;\r
+  MatchLen = FullMatch.size() - MatchStartSkip;\r
+  return FullMatch.data() - Buffer.data() + MatchStartSkip;\r
+}\r
+\r
+unsigned FileCheckPattern::computeMatchDistance(StringRef Buffer) const {\r
+  // Just compute the number of matching characters. For regular expressions, we\r
+  // just compare against the regex itself and hope for the best.\r
+  //\r
+  // FIXME: One easy improvement here is have the regex lib generate a single\r
+  // example regular expression which matches, and use that as the example\r
+  // string.\r
+  StringRef ExampleString(FixedStr);\r
+  if (ExampleString.empty())\r
+    ExampleString = RegExStr;\r
+\r
+  // Only compare up to the first line in the buffer, or the string size.\r
+  StringRef BufferPrefix = Buffer.substr(0, ExampleString.size());\r
+  BufferPrefix = BufferPrefix.split('\n').first;\r
+  return BufferPrefix.edit_distance(ExampleString);\r
+}\r
+\r
+void FileCheckPattern::printSubstitutions(const SourceMgr &SM, StringRef Buffer,\r
+                                          SMRange MatchRange) const {\r
+  // Print what we know about substitutions.\r
+  if (!Substitutions.empty()) {\r
+    for (const auto &Substitution : Substitutions) {\r
+      SmallString<256> Msg;\r
+      raw_svector_ostream OS(Msg);\r
+      Expected<std::string> MatchedValue = Substitution->getResult();\r
+\r
+      // Substitution failed or is not known at match time, print the undefined\r
+      // variables it uses.\r
+      if (!MatchedValue) {\r
+        bool UndefSeen = false;\r
+        handleAllErrors(MatchedValue.takeError(),\r
+                        [](const FileCheckNotFoundError &E) {},\r
+                        // Handled in PrintNoMatch().\r
+                        [](const FileCheckErrorDiagnostic &E) {},\r
+                        [&](const FileCheckUndefVarError &E) {\r
+                          if (!UndefSeen) {\r
+                            OS << "uses undefined variable(s):";\r
+                            UndefSeen = true;\r
+                          }\r
+                          OS << " ";\r
+                          E.log(OS);\r
+                        });\r
+      } else {\r
+        // Substitution succeeded. Print substituted value.\r
+        OS << "with \"";\r
+        OS.write_escaped(Substitution->getFromString()) << "\" equal to \"";\r
+        OS.write_escaped(*MatchedValue) << "\"";\r
+      }\r
+\r
+      if (MatchRange.isValid())\r
+        SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note, OS.str(),\r
+                        {MatchRange});\r
+      else\r
+        SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),\r
+                        SourceMgr::DK_Note, OS.str());\r
+    }\r
+  }\r
+}\r
+\r
+static SMRange ProcessMatchResult(FileCheckDiag::MatchType MatchTy,\r
+                                  const SourceMgr &SM, SMLoc Loc,\r
+                                  Check::FileCheckType CheckTy,\r
+                                  StringRef Buffer, size_t Pos, size_t Len,\r
+                                  std::vector<FileCheckDiag> *Diags,\r
+                                  bool AdjustPrevDiag = false) {\r
+  SMLoc Start = SMLoc::getFromPointer(Buffer.data() + Pos);\r
+  SMLoc End = SMLoc::getFromPointer(Buffer.data() + Pos + Len);\r
+  SMRange Range(Start, End);\r
+  if (Diags) {\r
+    if (AdjustPrevDiag)\r
+      Diags->rbegin()->MatchTy = MatchTy;\r
+    else\r
+      Diags->emplace_back(SM, CheckTy, Loc, MatchTy, Range);\r
+  }\r
+  return Range;\r
+}\r
+\r
+void FileCheckPattern::printFuzzyMatch(\r
+    const SourceMgr &SM, StringRef Buffer,\r
+    std::vector<FileCheckDiag> *Diags) const {\r
+  // Attempt to find the closest/best fuzzy match.  Usually an error happens\r
+  // because some string in the output didn't exactly match. In these cases, we\r
+  // would like to show the user a best guess at what "should have" matched, to\r
+  // save them having to actually check the input manually.\r
+  size_t NumLinesForward = 0;\r
+  size_t Best = StringRef::npos;\r
+  double BestQuality = 0;\r
+\r
+  // Use an arbitrary 4k limit on how far we will search.\r
+  for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) {\r
+    if (Buffer[i] == '\n')\r
+      ++NumLinesForward;\r
+\r
+    // Patterns have leading whitespace stripped, so skip whitespace when\r
+    // looking for something which looks like a pattern.\r
+    if (Buffer[i] == ' ' || Buffer[i] == '\t')\r
+      continue;\r
+\r
+    // Compute the "quality" of this match as an arbitrary combination of the\r
+    // match distance and the number of lines skipped to get to this match.\r
+    unsigned Distance = computeMatchDistance(Buffer.substr(i));\r
+    double Quality = Distance + (NumLinesForward / 100.);\r
+\r
+    if (Quality < BestQuality || Best == StringRef::npos) {\r
+      Best = i;\r
+      BestQuality = Quality;\r
+    }\r
+  }\r
+\r
+  // Print the "possible intended match here" line if we found something\r
+  // reasonable and not equal to what we showed in the "scanning from here"\r
+  // line.\r
+  if (Best && Best != StringRef::npos && BestQuality < 50) {\r
+    SMRange MatchRange =\r
+        ProcessMatchResult(FileCheckDiag::MatchFuzzy, SM, getLoc(),\r
+                           getCheckTy(), Buffer, Best, 0, Diags);\r
+    SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note,\r
+                    "possible intended match here");\r
+\r
+    // FIXME: If we wanted to be really friendly we would show why the match\r
+    // failed, as it can be hard to spot simple one character differences.\r
+  }\r
+}\r
+\r
+Expected<StringRef>\r
+FileCheckPatternContext::getPatternVarValue(StringRef VarName) {\r
+  auto VarIter = GlobalVariableTable.find(VarName);\r
+  if (VarIter == GlobalVariableTable.end())\r
+    return make_error<FileCheckUndefVarError>(VarName);\r
+\r
+  return VarIter->second;\r
+}\r
+\r
+template <class... Types>\r
+FileCheckNumericVariable *\r
+FileCheckPatternContext::makeNumericVariable(Types... args) {\r
+  NumericVariables.push_back(\r
+      std::make_unique<FileCheckNumericVariable>(args...));\r
+  return NumericVariables.back().get();\r
+}\r
+\r
+FileCheckSubstitution *\r
+FileCheckPatternContext::makeStringSubstitution(StringRef VarName,\r
+                                                size_t InsertIdx) {\r
+  Substitutions.push_back(\r
+      std::make_unique<FileCheckStringSubstitution>(this, VarName, InsertIdx));\r
+  return Substitutions.back().get();\r
+}\r
+\r
+FileCheckSubstitution *FileCheckPatternContext::makeNumericSubstitution(\r
+    StringRef ExpressionStr,\r
+    std::unique_ptr<FileCheckExpressionAST> ExpressionAST, size_t InsertIdx) {\r
+  Substitutions.push_back(std::make_unique<FileCheckNumericSubstitution>(\r
+      this, ExpressionStr, std::move(ExpressionAST), InsertIdx));\r
+  return Substitutions.back().get();\r
+}\r
+\r
+size_t FileCheckPattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) {\r
+  // Offset keeps track of the current offset within the input Str\r
+  size_t Offset = 0;\r
+  // [...] Nesting depth\r
+  size_t BracketDepth = 0;\r
+\r
+  while (!Str.empty()) {\r
+    if (Str.startswith("]]") && BracketDepth == 0)\r
+      return Offset;\r
+    if (Str[0] == '\\') {\r
+      // Backslash escapes the next char within regexes, so skip them both.\r
+      Str = Str.substr(2);\r
+      Offset += 2;\r
+    } else {\r
+      switch (Str[0]) {\r
+      default:\r
+        break;\r
+      case '[':\r
+        BracketDepth++;\r
+        break;\r
+      case ']':\r
+        if (BracketDepth == 0) {\r
+          SM.PrintMessage(SMLoc::getFromPointer(Str.data()),\r
+                          SourceMgr::DK_Error,\r
+                          "missing closing \"]\" for regex variable");\r
+          exit(1);\r
+        }\r
+        BracketDepth--;\r
+        break;\r
+      }\r
+      Str = Str.substr(1);\r
+      Offset++;\r
+    }\r
+  }\r
+\r
+  return StringRef::npos;\r
+}\r
+\r
+StringRef FileCheck::CanonicalizeFile(MemoryBuffer &MB,\r
+                                      SmallVectorImpl<char> &OutputBuffer) {\r
+  OutputBuffer.reserve(MB.getBufferSize());\r
+\r
+  for (const char *Ptr = MB.getBufferStart(), *End = MB.getBufferEnd();\r
+       Ptr != End; ++Ptr) {\r
+    // Eliminate trailing dosish \r.\r
+    if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') {\r
+      continue;\r
+    }\r
+\r
+    // If current char is not a horizontal whitespace or if horizontal\r
+    // whitespace canonicalization is disabled, dump it to output as is.\r
+    if (Req.NoCanonicalizeWhiteSpace || (*Ptr != ' ' && *Ptr != '\t')) {\r
+      OutputBuffer.push_back(*Ptr);\r
+      continue;\r
+    }\r
+\r
+    // Otherwise, add one space and advance over neighboring space.\r
+    OutputBuffer.push_back(' ');\r
+    while (Ptr + 1 != End && (Ptr[1] == ' ' || Ptr[1] == '\t'))\r
+      ++Ptr;\r
+  }\r
+\r
+  // Add a null byte and then return all but that byte.\r
+  OutputBuffer.push_back('\0');\r
+  return StringRef(OutputBuffer.data(), OutputBuffer.size() - 1);\r
+}\r
+\r
+FileCheckDiag::FileCheckDiag(const SourceMgr &SM,\r
+                             const Check::FileCheckType &CheckTy,\r
+                             SMLoc CheckLoc, MatchType MatchTy,\r
+                             SMRange InputRange)\r
+    : CheckTy(CheckTy), MatchTy(MatchTy) {\r
+  auto Start = SM.getLineAndColumn(InputRange.Start);\r
+  auto End = SM.getLineAndColumn(InputRange.End);\r
+  InputStartLine = Start.first;\r
+  InputStartCol = Start.second;\r
+  InputEndLine = End.first;\r
+  InputEndCol = End.second;\r
+  Start = SM.getLineAndColumn(CheckLoc);\r
+  CheckLine = Start.first;\r
+  CheckCol = Start.second;\r
+}\r
+\r
+static bool IsPartOfWord(char c) {\r
+  return (isalnum(c) || c == '-' || c == '_');\r
+}\r
+\r
+Check::FileCheckType &Check::FileCheckType::setCount(int C) {\r
+  assert(Count > 0 && "zero and negative counts are not supported");\r
+  assert((C == 1 || Kind == CheckPlain) &&\r
+         "count supported only for plain CHECK directives");\r
+  Count = C;\r
+  return *this;\r
+}\r
+\r
+std::string Check::FileCheckType::getDescription(StringRef Prefix) const {\r
+  switch (Kind) {\r
+  case Check::CheckNone:\r
+    return "invalid";\r
+  case Check::CheckPlain:\r
+    if (Count > 1)\r
+      return Prefix.str() + "-COUNT";\r
+    return Prefix;\r
+  case Check::CheckNext:\r
+    return Prefix.str() + "-NEXT";\r
+  case Check::CheckSame:\r
+    return Prefix.str() + "-SAME";\r
+  case Check::CheckNot:\r
+    return Prefix.str() + "-NOT";\r
+  case Check::CheckDAG:\r
+    return Prefix.str() + "-DAG";\r
+  case Check::CheckLabel:\r
+    return Prefix.str() + "-LABEL";\r
+  case Check::CheckEmpty:\r
+    return Prefix.str() + "-EMPTY";\r
+  case Check::CheckEOF:\r
+    return "implicit EOF";\r
+  case Check::CheckBadNot:\r
+    return "bad NOT";\r
+  case Check::CheckBadCount:\r
+    return "bad COUNT";\r
+  }\r
+  llvm_unreachable("unknown FileCheckType");\r
+}\r
+\r
+static std::pair<Check::FileCheckType, StringRef>\r
+FindCheckType(StringRef Buffer, StringRef Prefix) {\r
+  if (Buffer.size() <= Prefix.size())\r
+    return {Check::CheckNone, StringRef()};\r
+\r
+  char NextChar = Buffer[Prefix.size()];\r
+\r
+  StringRef Rest = Buffer.drop_front(Prefix.size() + 1);\r
+  // Verify that the : is present after the prefix.\r
+  if (NextChar == ':')\r
+    return {Check::CheckPlain, Rest};\r
+\r
+  if (NextChar != '-')\r
+    return {Check::CheckNone, StringRef()};\r
+\r
+  if (Rest.consume_front("COUNT-")) {\r
+    int64_t Count;\r
+    if (Rest.consumeInteger(10, Count))\r
+      // Error happened in parsing integer.\r
+      return {Check::CheckBadCount, Rest};\r
+    if (Count <= 0 || Count > INT32_MAX)\r
+      return {Check::CheckBadCount, Rest};\r
+    if (!Rest.consume_front(":"))\r
+      return {Check::CheckBadCount, Rest};\r
+    return {Check::FileCheckType(Check::CheckPlain).setCount(Count), Rest};\r
+  }\r
+\r
+  if (Rest.consume_front("NEXT:"))\r
+    return {Check::CheckNext, Rest};\r
+\r
+  if (Rest.consume_front("SAME:"))\r
+    return {Check::CheckSame, Rest};\r
+\r
+  if (Rest.consume_front("NOT:"))\r
+    return {Check::CheckNot, Rest};\r
+\r
+  if (Rest.consume_front("DAG:"))\r
+    return {Check::CheckDAG, Rest};\r
+\r
+  if (Rest.consume_front("LABEL:"))\r
+    return {Check::CheckLabel, Rest};\r
+\r
+  if (Rest.consume_front("EMPTY:"))\r
+    return {Check::CheckEmpty, Rest};\r
+\r
+  // You can't combine -NOT with another suffix.\r
+  if (Rest.startswith("DAG-NOT:") || Rest.startswith("NOT-DAG:") ||\r
+      Rest.startswith("NEXT-NOT:") || Rest.startswith("NOT-NEXT:") ||\r
+      Rest.startswith("SAME-NOT:") || Rest.startswith("NOT-SAME:") ||\r
+      Rest.startswith("EMPTY-NOT:") || Rest.startswith("NOT-EMPTY:"))\r
+    return {Check::CheckBadNot, Rest};\r
+\r
+  return {Check::CheckNone, Rest};\r
+}\r
+\r
+// From the given position, find the next character after the word.\r
+static size_t SkipWord(StringRef Str, size_t Loc) {\r
+  while (Loc < Str.size() && IsPartOfWord(Str[Loc]))\r
+    ++Loc;\r
+  return Loc;\r
+}\r
+\r
+/// Searches the buffer for the first prefix in the prefix regular expression.\r
+///\r
+/// This searches the buffer using the provided regular expression, however it\r
+/// enforces constraints beyond that:\r
+/// 1) The found prefix must not be a suffix of something that looks like\r
+///    a valid prefix.\r
+/// 2) The found prefix must be followed by a valid check type suffix using \c\r
+///    FindCheckType above.\r
+///\r
+/// \returns a pair of StringRefs into the Buffer, which combines:\r
+///   - the first match of the regular expression to satisfy these two is\r
+///   returned,\r
+///     otherwise an empty StringRef is returned to indicate failure.\r
+///   - buffer rewound to the location right after parsed suffix, for parsing\r
+///     to continue from\r
+///\r
+/// If this routine returns a valid prefix, it will also shrink \p Buffer to\r
+/// start at the beginning of the returned prefix, increment \p LineNumber for\r
+/// each new line consumed from \p Buffer, and set \p CheckTy to the type of\r
+/// check found by examining the suffix.\r
+///\r
+/// If no valid prefix is found, the state of Buffer, LineNumber, and CheckTy\r
+/// is unspecified.\r
+static std::pair<StringRef, StringRef>\r
+FindFirstMatchingPrefix(Regex &PrefixRE, StringRef &Buffer,\r
+                        unsigned &LineNumber, Check::FileCheckType &CheckTy) {\r
+  SmallVector<StringRef, 2> Matches;\r
+\r
+  while (!Buffer.empty()) {\r
+    // Find the first (longest) match using the RE.\r
+    if (!PrefixRE.match(Buffer, &Matches))\r
+      // No match at all, bail.\r
+      return {StringRef(), StringRef()};\r
+\r
+    StringRef Prefix = Matches[0];\r
+    Matches.clear();\r
+\r
+    assert(Prefix.data() >= Buffer.data() &&\r
+           Prefix.data() < Buffer.data() + Buffer.size() &&\r
+           "Prefix doesn't start inside of buffer!");\r
+    size_t Loc = Prefix.data() - Buffer.data();\r
+    StringRef Skipped = Buffer.substr(0, Loc);\r
+    Buffer = Buffer.drop_front(Loc);\r
+    LineNumber += Skipped.count('\n');\r
+\r
+    // Check that the matched prefix isn't a suffix of some other check-like\r
+    // word.\r
+    // FIXME: This is a very ad-hoc check. it would be better handled in some\r
+    // other way. Among other things it seems hard to distinguish between\r
+    // intentional and unintentional uses of this feature.\r
+    if (Skipped.empty() || !IsPartOfWord(Skipped.back())) {\r
+      // Now extract the type.\r
+      StringRef AfterSuffix;\r
+      std::tie(CheckTy, AfterSuffix) = FindCheckType(Buffer, Prefix);\r
+\r
+      // If we've found a valid check type for this prefix, we're done.\r
+      if (CheckTy != Check::CheckNone)\r
+        return {Prefix, AfterSuffix};\r
+    }\r
+\r
+    // If we didn't successfully find a prefix, we need to skip this invalid\r
+    // prefix and continue scanning. We directly skip the prefix that was\r
+    // matched and any additional parts of that check-like word.\r
+    Buffer = Buffer.drop_front(SkipWord(Buffer, Prefix.size()));\r
+  }\r
+\r
+  // We ran out of buffer while skipping partial matches so give up.\r
+  return {StringRef(), StringRef()};\r
+}\r
+\r
+void FileCheckPatternContext::createLineVariable() {\r
+  assert(!LineVariable && "@LINE pseudo numeric variable already created");\r
+  StringRef LineName = "@LINE";\r
+  LineVariable = makeNumericVariable(LineName);\r
+  GlobalNumericVariableTable[LineName] = LineVariable;\r
+}\r
+\r
+FileCheck::FileCheck(FileCheckRequest Req)\r
+    : Req(Req), PatternContext(std::make_unique<FileCheckPatternContext>()),\r
+      CheckStrings(std::make_unique<std::vector<FileCheckString>>()) {}\r
+\r
+FileCheck::~FileCheck() = default;\r
+\r
+bool FileCheck::readCheckFile(SourceMgr &SM, StringRef Buffer,\r
+                              Regex &PrefixRE) {\r
+  Error DefineError =\r
+      PatternContext->defineCmdlineVariables(Req.GlobalDefines, SM);\r
+  if (DefineError) {\r
+    logAllUnhandledErrors(std::move(DefineError), errs());\r
+    return true;\r
+  }\r
+\r
+  PatternContext->createLineVariable();\r
+\r
+  std::vector<FileCheckPattern> ImplicitNegativeChecks;\r
+  for (const auto &PatternString : Req.ImplicitCheckNot) {\r
+    // Create a buffer with fake command line content in order to display the\r
+    // command line option responsible for the specific implicit CHECK-NOT.\r
+    std::string Prefix = "-implicit-check-not='";\r
+    std::string Suffix = "'";\r
+    std::unique_ptr<MemoryBuffer> CmdLine = MemoryBuffer::getMemBufferCopy(\r
+        Prefix + PatternString + Suffix, "command line");\r
+\r
+    StringRef PatternInBuffer =\r
+        CmdLine->getBuffer().substr(Prefix.size(), PatternString.size());\r
+    SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc());\r
+\r
+    ImplicitNegativeChecks.push_back(\r
+        FileCheckPattern(Check::CheckNot, PatternContext.get()));\r
+    ImplicitNegativeChecks.back().parsePattern(PatternInBuffer,\r
+                                               "IMPLICIT-CHECK", SM, Req);\r
+  }\r
+\r
+  std::vector<FileCheckPattern> DagNotMatches = ImplicitNegativeChecks;\r
+\r
+  // LineNumber keeps track of the line on which CheckPrefix instances are\r
+  // found.\r
+  unsigned LineNumber = 1;\r
+\r
+  while (1) {\r
+    Check::FileCheckType CheckTy;\r
+\r
+    // See if a prefix occurs in the memory buffer.\r
+    StringRef UsedPrefix;\r
+    StringRef AfterSuffix;\r
+    std::tie(UsedPrefix, AfterSuffix) =\r
+        FindFirstMatchingPrefix(PrefixRE, Buffer, LineNumber, CheckTy);\r
+    if (UsedPrefix.empty())\r
+      break;\r
+    assert(UsedPrefix.data() == Buffer.data() &&\r
+           "Failed to move Buffer's start forward, or pointed prefix outside "\r
+           "of the buffer!");\r
+    assert(AfterSuffix.data() >= Buffer.data() &&\r
+           AfterSuffix.data() < Buffer.data() + Buffer.size() &&\r
+           "Parsing after suffix doesn't start inside of buffer!");\r
+\r
+    // Location to use for error messages.\r
+    const char *UsedPrefixStart = UsedPrefix.data();\r
+\r
+    // Skip the buffer to the end of parsed suffix (or just prefix, if no good\r
+    // suffix was processed).\r
+    Buffer = AfterSuffix.empty() ? Buffer.drop_front(UsedPrefix.size())\r
+                                 : AfterSuffix;\r
+\r
+    // Complain about useful-looking but unsupported suffixes.\r
+    if (CheckTy == Check::CheckBadNot) {\r
+      SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Error,\r
+                      "unsupported -NOT combo on prefix '" + UsedPrefix + "'");\r
+      return true;\r
+    }\r
+\r
+    // Complain about invalid count specification.\r
+    if (CheckTy == Check::CheckBadCount) {\r
+      SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Error,\r
+                      "invalid count in -COUNT specification on prefix '" +\r
+                          UsedPrefix + "'");\r
+      return true;\r
+    }\r
+\r
+    // Okay, we found the prefix, yay. Remember the rest of the line, but ignore\r
+    // leading whitespace.\r
+    if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines))\r
+      Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));\r
+\r
+    // Scan ahead to the end of line.\r
+    size_t EOL = Buffer.find_first_of("\n\r");\r
+\r
+    // Remember the location of the start of the pattern, for diagnostics.\r
+    SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data());\r
+\r
+    // Parse the pattern.\r
+    FileCheckPattern P(CheckTy, PatternContext.get(), LineNumber);\r
+    if (P.parsePattern(Buffer.substr(0, EOL), UsedPrefix, SM, Req))\r
+      return true;\r
+\r
+    // Verify that CHECK-LABEL lines do not define or use variables\r
+    if ((CheckTy == Check::CheckLabel) && P.hasVariable()) {\r
+      SM.PrintMessage(\r
+          SMLoc::getFromPointer(UsedPrefixStart), SourceMgr::DK_Error,\r
+          "found '" + UsedPrefix + "-LABEL:'"\r
+                                   " with variable definition or use");\r
+      return true;\r
+    }\r
+\r
+    Buffer = Buffer.substr(EOL);\r
+\r
+    // Verify that CHECK-NEXT/SAME/EMPTY lines have at least one CHECK line before them.\r
+    if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame ||\r
+         CheckTy == Check::CheckEmpty) &&\r
+        CheckStrings->empty()) {\r
+      StringRef Type = CheckTy == Check::CheckNext\r
+                           ? "NEXT"\r
+                           : CheckTy == Check::CheckEmpty ? "EMPTY" : "SAME";\r
+      SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),\r
+                      SourceMgr::DK_Error,\r
+                      "found '" + UsedPrefix + "-" + Type +\r
+                          "' without previous '" + UsedPrefix + ": line");\r
+      return true;\r
+    }\r
+\r
+    // Handle CHECK-DAG/-NOT.\r
+    if (CheckTy == Check::CheckDAG || CheckTy == Check::CheckNot) {\r
+      DagNotMatches.push_back(P);\r
+      continue;\r
+    }\r
+\r
+    // Okay, add the string we captured to the output vector and move on.\r
+    CheckStrings->emplace_back(P, UsedPrefix, PatternLoc);\r
+    std::swap(DagNotMatches, CheckStrings->back().DagNotStrings);\r
+    DagNotMatches = ImplicitNegativeChecks;\r
+  }\r
+\r
+  // Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first\r
+  // prefix as a filler for the error message.\r
+  if (!DagNotMatches.empty()) {\r
+    CheckStrings->emplace_back(\r
+        FileCheckPattern(Check::CheckEOF, PatternContext.get(), LineNumber + 1),\r
+        *Req.CheckPrefixes.begin(), SMLoc::getFromPointer(Buffer.data()));\r
+    std::swap(DagNotMatches, CheckStrings->back().DagNotStrings);\r
+  }\r
+\r
+  if (CheckStrings->empty()) {\r
+    errs() << "error: no check strings found with prefix"\r
+           << (Req.CheckPrefixes.size() > 1 ? "es " : " ");\r
+    auto I = Req.CheckPrefixes.begin();\r
+    auto E = Req.CheckPrefixes.end();\r
+    if (I != E) {\r
+      errs() << "\'" << *I << ":'";\r
+      ++I;\r
+    }\r
+    for (; I != E; ++I)\r
+      errs() << ", \'" << *I << ":'";\r
+\r
+    errs() << '\n';\r
+    return true;\r
+  }\r
+\r
+  return false;\r
+}\r
+\r
+static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM,\r
+                       StringRef Prefix, SMLoc Loc, const FileCheckPattern &Pat,\r
+                       int MatchedCount, StringRef Buffer, size_t MatchPos,\r
+                       size_t MatchLen, const FileCheckRequest &Req,\r
+                       std::vector<FileCheckDiag> *Diags) {\r
+  bool PrintDiag = true;\r
+  if (ExpectedMatch) {\r
+    if (!Req.Verbose)\r
+      return;\r
+    if (!Req.VerboseVerbose && Pat.getCheckTy() == Check::CheckEOF)\r
+      return;\r
+    // Due to their verbosity, we don't print verbose diagnostics here if we're\r
+    // gathering them for a different rendering, but we always print other\r
+    // diagnostics.\r
+    PrintDiag = !Diags;\r
+  }\r
+  SMRange MatchRange = ProcessMatchResult(\r
+      ExpectedMatch ? FileCheckDiag::MatchFoundAndExpected\r
+                    : FileCheckDiag::MatchFoundButExcluded,\r
+      SM, Loc, Pat.getCheckTy(), Buffer, MatchPos, MatchLen, Diags);\r
+  if (!PrintDiag)\r
+    return;\r
+\r
+  std::string Message = formatv("{0}: {1} string found in input",\r
+                                Pat.getCheckTy().getDescription(Prefix),\r
+                                (ExpectedMatch ? "expected" : "excluded"))\r
+                            .str();\r
+  if (Pat.getCount() > 1)\r
+    Message += formatv(" ({0} out of {1})", MatchedCount, Pat.getCount()).str();\r
+\r
+  SM.PrintMessage(\r
+      Loc, ExpectedMatch ? SourceMgr::DK_Remark : SourceMgr::DK_Error, Message);\r
+  SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note, "found here",\r
+                  {MatchRange});\r
+  Pat.printSubstitutions(SM, Buffer, MatchRange);\r
+}\r
+\r
+static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM,\r
+                       const FileCheckString &CheckStr, int MatchedCount,\r
+                       StringRef Buffer, size_t MatchPos, size_t MatchLen,\r
+                       FileCheckRequest &Req,\r
+                       std::vector<FileCheckDiag> *Diags) {\r
+  PrintMatch(ExpectedMatch, SM, CheckStr.Prefix, CheckStr.Loc, CheckStr.Pat,\r
+             MatchedCount, Buffer, MatchPos, MatchLen, Req, Diags);\r
+}\r
+\r
+static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM,\r
+                         StringRef Prefix, SMLoc Loc,\r
+                         const FileCheckPattern &Pat, int MatchedCount,\r
+                         StringRef Buffer, bool VerboseVerbose,\r
+                         std::vector<FileCheckDiag> *Diags, Error MatchErrors) {\r
+  assert(MatchErrors && "Called on successful match");\r
+  bool PrintDiag = true;\r
+  if (!ExpectedMatch) {\r
+    if (!VerboseVerbose) {\r
+      consumeError(std::move(MatchErrors));\r
+      return;\r
+    }\r
+    // Due to their verbosity, we don't print verbose diagnostics here if we're\r
+    // gathering them for a different rendering, but we always print other\r
+    // diagnostics.\r
+    PrintDiag = !Diags;\r
+  }\r
+\r
+  // If the current position is at the end of a line, advance to the start of\r
+  // the next line.\r
+  Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));\r
+  SMRange SearchRange = ProcessMatchResult(\r
+      ExpectedMatch ? FileCheckDiag::MatchNoneButExpected\r
+                    : FileCheckDiag::MatchNoneAndExcluded,\r
+      SM, Loc, Pat.getCheckTy(), Buffer, 0, Buffer.size(), Diags);\r
+  if (!PrintDiag) {\r
+    consumeError(std::move(MatchErrors));\r
+    return;\r
+  }\r
+\r
+  MatchErrors =\r
+      handleErrors(std::move(MatchErrors),\r
+                   [](const FileCheckErrorDiagnostic &E) { E.log(errs()); });\r
+\r
+  // No problem matching the string per se.\r
+  if (!MatchErrors)\r
+    return;\r
+  consumeError(std::move(MatchErrors));\r
+\r
+  // Print "not found" diagnostic.\r
+  std::string Message = formatv("{0}: {1} string not found in input",\r
+                                Pat.getCheckTy().getDescription(Prefix),\r
+                                (ExpectedMatch ? "expected" : "excluded"))\r
+                            .str();\r
+  if (Pat.getCount() > 1)\r
+    Message += formatv(" ({0} out of {1})", MatchedCount, Pat.getCount()).str();\r
+  SM.PrintMessage(\r
+      Loc, ExpectedMatch ? SourceMgr::DK_Error : SourceMgr::DK_Remark, Message);\r
+\r
+  // Print the "scanning from here" line.\r
+  SM.PrintMessage(SearchRange.Start, SourceMgr::DK_Note, "scanning from here");\r
+\r
+  // Allow the pattern to print additional information if desired.\r
+  Pat.printSubstitutions(SM, Buffer);\r
+\r
+  if (ExpectedMatch)\r
+    Pat.printFuzzyMatch(SM, Buffer, Diags);\r
+}\r
+\r
+static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM,\r
+                         const FileCheckString &CheckStr, int MatchedCount,\r
+                         StringRef Buffer, bool VerboseVerbose,\r
+                         std::vector<FileCheckDiag> *Diags, Error MatchErrors) {\r
+  PrintNoMatch(ExpectedMatch, SM, CheckStr.Prefix, CheckStr.Loc, CheckStr.Pat,\r
+               MatchedCount, Buffer, VerboseVerbose, Diags,\r
+               std::move(MatchErrors));\r
+}\r
+\r
+/// Counts the number of newlines in the specified range.\r
+static unsigned CountNumNewlinesBetween(StringRef Range,\r
+                                        const char *&FirstNewLine) {\r
+  unsigned NumNewLines = 0;\r
+  while (1) {\r
+    // Scan for newline.\r
+    Range = Range.substr(Range.find_first_of("\n\r"));\r
+    if (Range.empty())\r
+      return NumNewLines;\r
+\r
+    ++NumNewLines;\r
+\r
+    // Handle \n\r and \r\n as a single newline.\r
+    if (Range.size() > 1 && (Range[1] == '\n' || Range[1] == '\r') &&\r
+        (Range[0] != Range[1]))\r
+      Range = Range.substr(1);\r
+    Range = Range.substr(1);\r
+\r
+    if (NumNewLines == 1)\r
+      FirstNewLine = Range.begin();\r
+  }\r
+}\r
+\r
+size_t FileCheckString::Check(const SourceMgr &SM, StringRef Buffer,\r
+                              bool IsLabelScanMode, size_t &MatchLen,\r
+                              FileCheckRequest &Req,\r
+                              std::vector<FileCheckDiag> *Diags) const {\r
+  size_t LastPos = 0;\r
+  std::vector<const FileCheckPattern *> NotStrings;\r
+\r
+  // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL\r
+  // bounds; we have not processed variable definitions within the bounded block\r
+  // yet so cannot handle any final CHECK-DAG yet; this is handled when going\r
+  // over the block again (including the last CHECK-LABEL) in normal mode.\r
+  if (!IsLabelScanMode) {\r
+    // Match "dag strings" (with mixed "not strings" if any).\r
+    LastPos = CheckDag(SM, Buffer, NotStrings, Req, Diags);\r
+    if (LastPos == StringRef::npos)\r
+      return StringRef::npos;\r
+  }\r
+\r
+  // Match itself from the last position after matching CHECK-DAG.\r
+  size_t LastMatchEnd = LastPos;\r
+  size_t FirstMatchPos = 0;\r
+  // Go match the pattern Count times. Majority of patterns only match with\r
+  // count 1 though.\r
+  assert(Pat.getCount() != 0 && "pattern count can not be zero");\r
+  for (int i = 1; i <= Pat.getCount(); i++) {\r
+    StringRef MatchBuffer = Buffer.substr(LastMatchEnd);\r
+    size_t CurrentMatchLen;\r
+    // get a match at current start point\r
+    Expected<size_t> MatchResult = Pat.match(MatchBuffer, CurrentMatchLen, SM);\r
+\r
+    // report\r
+    if (!MatchResult) {\r
+      PrintNoMatch(true, SM, *this, i, MatchBuffer, Req.VerboseVerbose, Diags,\r
+                   MatchResult.takeError());\r
+      return StringRef::npos;\r
+    }\r
+    size_t MatchPos = *MatchResult;\r
+    PrintMatch(true, SM, *this, i, MatchBuffer, MatchPos, CurrentMatchLen, Req,\r
+               Diags);\r
+    if (i == 1)\r
+      FirstMatchPos = LastPos + MatchPos;\r
+\r
+    // move start point after the match\r
+    LastMatchEnd += MatchPos + CurrentMatchLen;\r
+  }\r
+  // Full match len counts from first match pos.\r
+  MatchLen = LastMatchEnd - FirstMatchPos;\r
+\r
+  // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT\r
+  // or CHECK-NOT\r
+  if (!IsLabelScanMode) {\r
+    size_t MatchPos = FirstMatchPos - LastPos;\r
+    StringRef MatchBuffer = Buffer.substr(LastPos);\r
+    StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos);\r
+\r
+    // If this check is a "CHECK-NEXT", verify that the previous match was on\r
+    // the previous line (i.e. that there is one newline between them).\r
+    if (CheckNext(SM, SkippedRegion)) {\r
+      ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine, SM, Loc,\r
+                         Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen,\r
+                         Diags, Req.Verbose);\r
+      return StringRef::npos;\r
+    }\r
+\r
+    // If this check is a "CHECK-SAME", verify that the previous match was on\r
+    // the same line (i.e. that there is no newline between them).\r
+    if (CheckSame(SM, SkippedRegion)) {\r
+      ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine, SM, Loc,\r
+                         Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen,\r
+                         Diags, Req.Verbose);\r
+      return StringRef::npos;\r
+    }\r
+\r
+    // If this match had "not strings", verify that they don't exist in the\r
+    // skipped region.\r
+    if (CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))\r
+      return StringRef::npos;\r
+  }\r
+\r
+  return FirstMatchPos;\r
+}\r
+\r
+bool FileCheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {\r
+  if (Pat.getCheckTy() != Check::CheckNext &&\r
+      Pat.getCheckTy() != Check::CheckEmpty)\r
+    return false;\r
+\r
+  Twine CheckName =\r
+      Prefix +\r
+      Twine(Pat.getCheckTy() == Check::CheckEmpty ? "-EMPTY" : "-NEXT");\r
+\r
+  // Count the number of newlines between the previous match and this one.\r
+  const char *FirstNewLine = nullptr;\r
+  unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);\r
+\r
+  if (NumNewLines == 0) {\r
+    SM.PrintMessage(Loc, SourceMgr::DK_Error,\r
+                    CheckName + ": is on the same line as previous match");\r
+    SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,\r
+                    "'next' match was here");\r
+    SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,\r
+                    "previous match ended here");\r
+    return true;\r
+  }\r
+\r
+  if (NumNewLines != 1) {\r
+    SM.PrintMessage(Loc, SourceMgr::DK_Error,\r
+                    CheckName +\r
+                        ": is not on the line after the previous match");\r
+    SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,\r
+                    "'next' match was here");\r
+    SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,\r
+                    "previous match ended here");\r
+    SM.PrintMessage(SMLoc::getFromPointer(FirstNewLine), SourceMgr::DK_Note,\r
+                    "non-matching line after previous match is here");\r
+    return true;\r
+  }\r
+\r
+  return false;\r
+}\r
+\r
+bool FileCheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const {\r
+  if (Pat.getCheckTy() != Check::CheckSame)\r
+    return false;\r
+\r
+  // Count the number of newlines between the previous match and this one.\r
+  const char *FirstNewLine = nullptr;\r
+  unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);\r
+\r
+  if (NumNewLines != 0) {\r
+    SM.PrintMessage(Loc, SourceMgr::DK_Error,\r
+                    Prefix +\r
+                        "-SAME: is not on the same line as the previous match");\r
+    SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,\r
+                    "'next' match was here");\r
+    SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,\r
+                    "previous match ended here");\r
+    return true;\r
+  }\r
+\r
+  return false;\r
+}\r
+\r
+bool FileCheckString::CheckNot(\r
+    const SourceMgr &SM, StringRef Buffer,\r
+    const std::vector<const FileCheckPattern *> &NotStrings,\r
+    const FileCheckRequest &Req, std::vector<FileCheckDiag> *Diags) const {\r
+  for (const FileCheckPattern *Pat : NotStrings) {\r
+    assert((Pat->getCheckTy() == Check::CheckNot) && "Expect CHECK-NOT!");\r
+\r
+    size_t MatchLen = 0;\r
+    Expected<size_t> MatchResult = Pat->match(Buffer, MatchLen, SM);\r
+\r
+    if (!MatchResult) {\r
+      PrintNoMatch(false, SM, Prefix, Pat->getLoc(), *Pat, 1, Buffer,\r
+                   Req.VerboseVerbose, Diags, MatchResult.takeError());\r
+      continue;\r
+    }\r
+    size_t Pos = *MatchResult;\r
+\r
+    PrintMatch(false, SM, Prefix, Pat->getLoc(), *Pat, 1, Buffer, Pos, MatchLen,\r
+               Req, Diags);\r
+\r
+    return true;\r
+  }\r
+\r
+  return false;\r
+}\r
+\r
+size_t\r
+FileCheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,\r
+                          std::vector<const FileCheckPattern *> &NotStrings,\r
+                          const FileCheckRequest &Req,\r
+                          std::vector<FileCheckDiag> *Diags) const {\r
+  if (DagNotStrings.empty())\r
+    return 0;\r
+\r
+  // The start of the search range.\r
+  size_t StartPos = 0;\r
+\r
+  struct MatchRange {\r
+    size_t Pos;\r
+    size_t End;\r
+  };\r
+  // A sorted list of ranges for non-overlapping CHECK-DAG matches.  Match\r
+  // ranges are erased from this list once they are no longer in the search\r
+  // range.\r
+  std::list<MatchRange> MatchRanges;\r
+\r
+  // We need PatItr and PatEnd later for detecting the end of a CHECK-DAG\r
+  // group, so we don't use a range-based for loop here.\r
+  for (auto PatItr = DagNotStrings.begin(), PatEnd = DagNotStrings.end();\r
+       PatItr != PatEnd; ++PatItr) {\r
+    const FileCheckPattern &Pat = *PatItr;\r
+    assert((Pat.getCheckTy() == Check::CheckDAG ||\r
+            Pat.getCheckTy() == Check::CheckNot) &&\r
+           "Invalid CHECK-DAG or CHECK-NOT!");\r
+\r
+    if (Pat.getCheckTy() == Check::CheckNot) {\r
+      NotStrings.push_back(&Pat);\r
+      continue;\r
+    }\r
+\r
+    assert((Pat.getCheckTy() == Check::CheckDAG) && "Expect CHECK-DAG!");\r
+\r
+    // CHECK-DAG always matches from the start.\r
+    size_t MatchLen = 0, MatchPos = StartPos;\r
+\r
+    // Search for a match that doesn't overlap a previous match in this\r
+    // CHECK-DAG group.\r
+    for (auto MI = MatchRanges.begin(), ME = MatchRanges.end(); true; ++MI) {\r
+      StringRef MatchBuffer = Buffer.substr(MatchPos);\r
+      Expected<size_t> MatchResult = Pat.match(MatchBuffer, MatchLen, SM);\r
+      // With a group of CHECK-DAGs, a single mismatching means the match on\r
+      // that group of CHECK-DAGs fails immediately.\r
+      if (!MatchResult) {\r
+        PrintNoMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, MatchBuffer,\r
+                     Req.VerboseVerbose, Diags, MatchResult.takeError());\r
+        return StringRef::npos;\r
+      }\r
+      size_t MatchPosBuf = *MatchResult;\r
+      // Re-calc it as the offset relative to the start of the original string.\r
+      MatchPos += MatchPosBuf;\r
+      if (Req.VerboseVerbose)\r
+        PrintMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, Buffer, MatchPos,\r
+                   MatchLen, Req, Diags);\r
+      MatchRange M{MatchPos, MatchPos + MatchLen};\r
+      if (Req.AllowDeprecatedDagOverlap) {\r
+        // We don't need to track all matches in this mode, so we just maintain\r
+        // one match range that encompasses the current CHECK-DAG group's\r
+        // matches.\r
+        if (MatchRanges.empty())\r
+          MatchRanges.insert(MatchRanges.end(), M);\r
+        else {\r
+          auto Block = MatchRanges.begin();\r
+          Block->Pos = std::min(Block->Pos, M.Pos);\r
+          Block->End = std::max(Block->End, M.End);\r
+        }\r
+        break;\r
+      }\r
+      // Iterate previous matches until overlapping match or insertion point.\r
+      bool Overlap = false;\r
+      for (; MI != ME; ++MI) {\r
+        if (M.Pos < MI->End) {\r
+          // !Overlap => New match has no overlap and is before this old match.\r
+          // Overlap => New match overlaps this old match.\r
+          Overlap = MI->Pos < M.End;\r
+          break;\r
+        }\r
+      }\r
+      if (!Overlap) {\r
+        // Insert non-overlapping match into list.\r
+        MatchRanges.insert(MI, M);\r
+        break;\r
+      }\r
+      if (Req.VerboseVerbose) {\r
+        // Due to their verbosity, we don't print verbose diagnostics here if\r
+        // we're gathering them for a different rendering, but we always print\r
+        // other diagnostics.\r
+        if (!Diags) {\r
+          SMLoc OldStart = SMLoc::getFromPointer(Buffer.data() + MI->Pos);\r
+          SMLoc OldEnd = SMLoc::getFromPointer(Buffer.data() + MI->End);\r
+          SMRange OldRange(OldStart, OldEnd);\r
+          SM.PrintMessage(OldStart, SourceMgr::DK_Note,\r
+                          "match discarded, overlaps earlier DAG match here",\r
+                          {OldRange});\r
+        } else\r
+          Diags->rbegin()->MatchTy = FileCheckDiag::MatchFoundButDiscarded;\r
+      }\r
+      MatchPos = MI->End;\r
+    }\r
+    if (!Req.VerboseVerbose)\r
+      PrintMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, Buffer, MatchPos,\r
+                 MatchLen, Req, Diags);\r
+\r
+    // Handle the end of a CHECK-DAG group.\r
+    if (std::next(PatItr) == PatEnd ||\r
+        std::next(PatItr)->getCheckTy() == Check::CheckNot) {\r
+      if (!NotStrings.empty()) {\r
+        // If there are CHECK-NOTs between two CHECK-DAGs or from CHECK to\r
+        // CHECK-DAG, verify that there are no 'not' strings occurred in that\r
+        // region.\r
+        StringRef SkippedRegion =\r
+            Buffer.slice(StartPos, MatchRanges.begin()->Pos);\r
+        if (CheckNot(SM, SkippedRegion, NotStrings, Req, Diags))\r
+          return StringRef::npos;\r
+        // Clear "not strings".\r
+        NotStrings.clear();\r
+      }\r
+      // All subsequent CHECK-DAGs and CHECK-NOTs should be matched from the\r
+      // end of this CHECK-DAG group's match range.\r
+      StartPos = MatchRanges.rbegin()->End;\r
+      // Don't waste time checking for (impossible) overlaps before that.\r
+      MatchRanges.clear();\r
+    }\r
+  }\r
+\r
+  return StartPos;\r
+}\r
+\r
+// A check prefix must contain only alphanumeric, hyphens and underscores.\r
+static bool ValidateCheckPrefix(StringRef CheckPrefix) {\r
+  static const Regex Validator("^[a-zA-Z0-9_-]*$");\r
+  return Validator.match(CheckPrefix);\r
+}\r
+\r
+bool FileCheck::ValidateCheckPrefixes() {\r
+  StringSet<> PrefixSet;\r
+\r
+  for (StringRef Prefix : Req.CheckPrefixes) {\r
+    // Reject empty prefixes.\r
+    if (Prefix == "")\r
+      return false;\r
+\r
+    if (!PrefixSet.insert(Prefix).second)\r
+      return false;\r
+\r
+    if (!ValidateCheckPrefix(Prefix))\r
+      return false;\r
+  }\r
+\r
+  return true;\r
+}\r
+\r
+Regex FileCheck::buildCheckPrefixRegex() {\r
+  // I don't think there's a way to specify an initial value for cl::list,\r
+  // so if nothing was specified, add the default\r
+  if (Req.CheckPrefixes.empty())\r
+    Req.CheckPrefixes.push_back("CHECK");\r
+\r
+  // We already validated the contents of CheckPrefixes so just concatenate\r
+  // them as alternatives.\r
+  SmallString<32> PrefixRegexStr;\r
+  for (StringRef Prefix : Req.CheckPrefixes) {\r
+    if (Prefix != Req.CheckPrefixes.front())\r
+      PrefixRegexStr.push_back('|');\r
+\r
+    PrefixRegexStr.append(Prefix);\r
+  }\r
+\r
+  return Regex(PrefixRegexStr);\r
+}\r
+\r
+Error FileCheckPatternContext::defineCmdlineVariables(\r
+    std::vector<std::string> &CmdlineDefines, SourceMgr &SM) {\r
+  assert(GlobalVariableTable.empty() && GlobalNumericVariableTable.empty() &&\r
+         "Overriding defined variable with command-line variable definitions");\r
+\r
+  if (CmdlineDefines.empty())\r
+    return Error::success();\r
+\r
+  // Create a string representing the vector of command-line definitions. Each\r
+  // definition is on its own line and prefixed with a definition number to\r
+  // clarify which definition a given diagnostic corresponds to.\r
+  unsigned I = 0;\r
+  Error Errs = Error::success();\r
+  std::string CmdlineDefsDiag;\r
+  SmallVector<std::pair<size_t, size_t>, 4> CmdlineDefsIndices;\r
+  for (StringRef CmdlineDef : CmdlineDefines) {\r
+    std::string DefPrefix = ("Global define #" + Twine(++I) + ": ").str();\r
+    size_t EqIdx = CmdlineDef.find('=');\r
+    if (EqIdx == StringRef::npos) {\r
+      CmdlineDefsIndices.push_back(std::make_pair(CmdlineDefsDiag.size(), 0));\r
+      continue;\r
+    }\r
+    // Numeric variable definition.\r
+    if (CmdlineDef[0] == '#') {\r
+      // Append a copy of the command-line definition adapted to use the same\r
+      // format as in the input file to be able to reuse\r
+      // parseNumericSubstitutionBlock.\r
+      CmdlineDefsDiag += (DefPrefix + CmdlineDef + " (parsed as: [[").str();\r
+      std::string SubstitutionStr = CmdlineDef;\r
+      SubstitutionStr[EqIdx] = ':';\r
+      CmdlineDefsIndices.push_back(\r
+          std::make_pair(CmdlineDefsDiag.size(), SubstitutionStr.size()));\r
+      CmdlineDefsDiag += (SubstitutionStr + Twine("]])\n")).str();\r
+    } else {\r
+      CmdlineDefsDiag += DefPrefix;\r
+      CmdlineDefsIndices.push_back(\r
+          std::make_pair(CmdlineDefsDiag.size(), CmdlineDef.size()));\r
+      CmdlineDefsDiag += (CmdlineDef + "\n").str();\r
+    }\r
+  }\r
+\r
+  // Create a buffer with fake command line content in order to display\r
+  // parsing diagnostic with location information and point to the\r
+  // global definition with invalid syntax.\r
+  std::unique_ptr<MemoryBuffer> CmdLineDefsDiagBuffer =\r
+      MemoryBuffer::getMemBufferCopy(CmdlineDefsDiag, "Global defines");\r
+  StringRef CmdlineDefsDiagRef = CmdLineDefsDiagBuffer->getBuffer();\r
+  SM.AddNewSourceBuffer(std::move(CmdLineDefsDiagBuffer), SMLoc());\r
+\r
+  for (std::pair<size_t, size_t> CmdlineDefIndices : CmdlineDefsIndices) {\r
+    StringRef CmdlineDef = CmdlineDefsDiagRef.substr(CmdlineDefIndices.first,\r
+                                                     CmdlineDefIndices.second);\r
+    if (CmdlineDef.empty()) {\r
+      Errs = joinErrors(\r
+          std::move(Errs),\r
+          FileCheckErrorDiagnostic::get(\r
+              SM, CmdlineDef, "missing equal sign in global definition"));\r
+      continue;\r
+    }\r
+\r
+    // Numeric variable definition.\r
+    if (CmdlineDef[0] == '#') {\r
+      // Now parse the definition both to check that the syntax is correct and\r
+      // to create the necessary class instance.\r
+      StringRef CmdlineDefExpr = CmdlineDef.substr(1);\r
+      Optional<FileCheckNumericVariable *> DefinedNumericVariable;\r
+      Expected<std::unique_ptr<FileCheckExpressionAST>> ExpressionASTResult =\r
+          FileCheckPattern::parseNumericSubstitutionBlock(\r
+              CmdlineDefExpr, DefinedNumericVariable, false, None, this, SM);\r
+      if (!ExpressionASTResult) {\r
+        Errs = joinErrors(std::move(Errs), ExpressionASTResult.takeError());\r
+        continue;\r
+      }\r
+      std::unique_ptr<FileCheckExpressionAST> ExpressionAST =\r
+          std::move(*ExpressionASTResult);\r
+      // Now evaluate the expression whose value this variable should be set\r
+      // to, since the expression of a command-line variable definition should\r
+      // only use variables defined earlier on the command-line. If not, this\r
+      // is an error and we report it.\r
+      Expected<uint64_t> Value = ExpressionAST->eval();\r
+      if (!Value) {\r
+        Errs = joinErrors(std::move(Errs), Value.takeError());\r
+        continue;\r
+      }\r
+\r
+      assert(DefinedNumericVariable && "No variable defined");\r
+      (*DefinedNumericVariable)->setValue(*Value);\r
+\r
+      // Record this variable definition.\r
+      GlobalNumericVariableTable[(*DefinedNumericVariable)->getName()] =\r
+          *DefinedNumericVariable;\r
+    } else {\r
+      // String variable definition.\r
+      std::pair<StringRef, StringRef> CmdlineNameVal = CmdlineDef.split('=');\r
+      StringRef CmdlineName = CmdlineNameVal.first;\r
+      StringRef OrigCmdlineName = CmdlineName;\r
+      Expected<FileCheckPattern::VariableProperties> ParseVarResult =\r
+          FileCheckPattern::parseVariable(CmdlineName, SM);\r
+      if (!ParseVarResult) {\r
+        Errs = joinErrors(std::move(Errs), ParseVarResult.takeError());\r
+        continue;\r
+      }\r
+      // Check that CmdlineName does not denote a pseudo variable is only\r
+      // composed of the parsed numeric variable. This catches cases like\r
+      // "FOO+2" in a "FOO+2=10" definition.\r
+      if (ParseVarResult->IsPseudo || !CmdlineName.empty()) {\r
+        Errs = joinErrors(std::move(Errs),\r
+                          FileCheckErrorDiagnostic::get(\r
+                              SM, OrigCmdlineName,\r
+                              "invalid name in string variable definition '" +\r
+                                  OrigCmdlineName + "'"));\r
+        continue;\r
+      }\r
+      StringRef Name = ParseVarResult->Name;\r
+\r
+      // Detect collisions between string and numeric variables when the former\r
+      // is created later than the latter.\r
+      if (GlobalNumericVariableTable.find(Name) !=\r
+          GlobalNumericVariableTable.end()) {\r
+        Errs = joinErrors(std::move(Errs), FileCheckErrorDiagnostic::get(\r
+                                               SM, Name,\r
+                                               "numeric variable with name '" +\r
+                                                   Name + "' already exists"));\r
+        continue;\r
+      }\r
+      GlobalVariableTable.insert(CmdlineNameVal);\r
+      // Mark the string variable as defined to detect collisions between\r
+      // string and numeric variables in defineCmdlineVariables when the latter\r
+      // is created later than the former. We cannot reuse GlobalVariableTable\r
+      // for this by populating it with an empty string since we would then\r
+      // lose the ability to detect the use of an undefined variable in\r
+      // match().\r
+      DefinedVariableTable[Name] = true;\r
+    }\r
+  }\r
+\r
+  return Errs;\r
+}\r
+\r
+void FileCheckPatternContext::clearLocalVars() {\r
+  SmallVector<StringRef, 16> LocalPatternVars, LocalNumericVars;\r
+  for (const StringMapEntry<StringRef> &Var : GlobalVariableTable)\r
+    if (Var.first()[0] != '$')\r
+      LocalPatternVars.push_back(Var.first());\r
+\r
+  // Numeric substitution reads the value of a variable directly, not via\r
+  // GlobalNumericVariableTable. Therefore, we clear local variables by\r
+  // clearing their value which will lead to a numeric substitution failure. We\r
+  // also mark the variable for removal from GlobalNumericVariableTable since\r
+  // this is what defineCmdlineVariables checks to decide that no global\r
+  // variable has been defined.\r
+  for (const auto &Var : GlobalNumericVariableTable)\r
+    if (Var.first()[0] != '$') {\r
+      Var.getValue()->clearValue();\r
+      LocalNumericVars.push_back(Var.first());\r
+    }\r
+\r
+  for (const auto &Var : LocalPatternVars)\r
+    GlobalVariableTable.erase(Var);\r
+  for (const auto &Var : LocalNumericVars)\r
+    GlobalNumericVariableTable.erase(Var);\r
+}\r
+\r
+bool FileCheck::checkInput(SourceMgr &SM, StringRef Buffer,\r
+                           std::vector<FileCheckDiag> *Diags) {\r
+  bool ChecksFailed = false;\r
+\r
+  unsigned i = 0, j = 0, e = CheckStrings->size();\r
+  while (true) {\r
+    StringRef CheckRegion;\r
+    if (j == e) {\r
+      CheckRegion = Buffer;\r
+    } else {\r
+      const FileCheckString &CheckLabelStr = (*CheckStrings)[j];\r
+      if (CheckLabelStr.Pat.getCheckTy() != Check::CheckLabel) {\r
+        ++j;\r
+        continue;\r
+      }\r
+\r
+      // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG\r
+      size_t MatchLabelLen = 0;\r
+      size_t MatchLabelPos =\r
+          CheckLabelStr.Check(SM, Buffer, true, MatchLabelLen, Req, Diags);\r
+      if (MatchLabelPos == StringRef::npos)\r
+        // Immediately bail if CHECK-LABEL fails, nothing else we can do.\r
+        return false;\r
+\r
+      CheckRegion = Buffer.substr(0, MatchLabelPos + MatchLabelLen);\r
+      Buffer = Buffer.substr(MatchLabelPos + MatchLabelLen);\r
+      ++j;\r
+    }\r
+\r
+    // Do not clear the first region as it's the one before the first\r
+    // CHECK-LABEL and it would clear variables defined on the command-line\r
+    // before they get used.\r
+    if (i != 0 && Req.EnableVarScope)\r
+      PatternContext->clearLocalVars();\r
+\r
+    for (; i != j; ++i) {\r
+      const FileCheckString &CheckStr = (*CheckStrings)[i];\r
+\r
+      // Check each string within the scanned region, including a second check\r
+      // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG)\r
+      size_t MatchLen = 0;\r
+      size_t MatchPos =\r
+          CheckStr.Check(SM, CheckRegion, false, MatchLen, Req, Diags);\r
+\r
+      if (MatchPos == StringRef::npos) {\r
+        ChecksFailed = true;\r
+        i = j;\r
+        break;\r
+      }\r
+\r
+      CheckRegion = CheckRegion.substr(MatchPos + MatchLen);\r
+    }\r
+\r
+    if (j == e)\r
+      break;\r
+  }\r
+\r
+  // Success if no checks failed.\r
+  return !ChecksFailed;\r
+}\r
index 001b3589d5fdcb65bf21f9f003f3fb02b75f8b0f..6581612a8e44cbbf0ca6a2dfe73fa6c15ab30e0a 100644 (file)
-//===-- FileCheckImpl.h - Private FileCheck Interface ------------*- C++ -*-==//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the private interfaces of FileCheck. Its purpose is to
-// allow unit testing of FileCheck and to separate the interface from the
-// implementation. It is only meant to be used by FileCheck.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_LIB_SUPPORT_FILECHECKIMPL_H
-#define LLVM_LIB_SUPPORT_FILECHECKIMPL_H
-
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/SourceMgr.h"
-#include <map>
-#include <string>
-#include <vector>
-
-namespace llvm {
-
-//===----------------------------------------------------------------------===//
-// Numeric substitution handling code.
-//===----------------------------------------------------------------------===//
-
-/// Base class representing the AST of a given expression.
-class FileCheckExpressionAST {
-public:
-  virtual ~FileCheckExpressionAST() = default;
-
-  /// 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;
-};
-
-/// Class representing an unsigned literal in the AST of an expression.
-class FileCheckExpressionLiteral : public FileCheckExpressionAST {
-private:
-  /// Actual value of the literal.
-  uint64_t Value;
-
-public:
-  /// Constructs a literal with the specified value.
-  FileCheckExpressionLiteral(uint64_t Val) : Value(Val) {}
-
-  /// \returns the literal's value.
-  Expected<uint64_t> eval() const { return Value; }
-};
-
-/// Class to represent an undefined variable error, which quotes that
-/// variable's name 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 variable and its associated current value.
-class FileCheckNumericVariable {
-private:
-  /// Name of the numeric variable.
-  StringRef Name;
-
-  /// Value of numeric variable, if defined, or None otherwise.
-  Optional<uint64_t> 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
-  /// same line as a given use.
-  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 FileCheckNumericVariable(StringRef Name,
-                                    Optional<size_t> DefLineNumber = None)
-      : Name(Name), DefLineNumber(DefLineNumber) {}
-
-  /// \returns name of this numeric variable.
-  StringRef getName() const { return Name; }
-
-  /// \returns this variable's value.
-  Optional<uint64_t> getValue() const { return Value; }
-
-  /// Sets value of this numeric variable to \p NewValue.
-  void setValue(uint64_t NewValue) { Value = NewValue; }
-
-  /// Clears value of this numeric variable, regardless of whether it is
-  /// currently defined or not.
-  void clearValue() { Value = None; }
-
-  /// \returns the line number where this variable is defined, if any, or None
-  /// if defined before input is parsed.
-  Optional<size_t> getDefLineNumber() { return DefLineNumber; }
-};
-
-/// Class representing the use of a numeric variable in the AST of an
-/// expression.
-class FileCheckNumericVariableUse : public FileCheckExpressionAST {
-private:
-  /// Name of the numeric variable.
-  StringRef Name;
-
-  /// Pointer to the class instance for the variable this use is about.
-  FileCheckNumericVariable *NumericVariable;
-
-public:
-  FileCheckNumericVariableUse(StringRef Name,
-                              FileCheckNumericVariable *NumericVariable)
-      : Name(Name), NumericVariable(NumericVariable) {}
-
-  /// \returns the value of the variable referenced by this instance.
-  Expected<uint64_t> eval() const;
-};
-
-/// Type of functions evaluating a given binary operation.
-using binop_eval_t = uint64_t (*)(uint64_t, uint64_t);
-
-/// Class representing a single binary operation in the AST of an expression.
-class FileCheckASTBinop : public FileCheckExpressionAST {
-private:
-  /// Left operand.
-  std::unique_ptr<FileCheckExpressionAST> LeftOperand;
-
-  /// Right operand.
-  std::unique_ptr<FileCheckExpressionAST> RightOperand;
-
-  /// Pointer to function that can evaluate this binary operation.
-  binop_eval_t EvalBinop;
-
-public:
-  FileCheckASTBinop(binop_eval_t EvalBinop,
-                    std::unique_ptr<FileCheckExpressionAST> LeftOp,
-                    std::unique_ptr<FileCheckExpressionAST> RightOp)
-      : EvalBinop(EvalBinop) {
-    LeftOperand = std::move(LeftOp);
-    RightOperand = std::move(RightOp);
-  }
-
-  /// Evaluates the value of the binary operation represented by this AST,
-  /// 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;
-};
-
-class FileCheckPatternContext;
-
-/// 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. 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;
-
-  /// The string that needs to be substituted for something else. For a
-  /// string variable this is its name, otherwise this is the whole expression.
-  StringRef FromStr;
-
-  // Index in RegExStr of where to do the substitution.
-  size_t InsertIdx;
-
-public:
-  FileCheckSubstitution(FileCheckPatternContext *Context, StringRef VarName,
-                        size_t InsertIdx)
-      : Context(Context), FromStr(VarName), InsertIdx(InsertIdx) {}
-
-  virtual ~FileCheckSubstitution() = default;
-
-  /// \returns the string to be substituted for something else.
-  StringRef getFromString() const { return FromStr; }
-
-  /// \returns the index where the substitution is to be performed in RegExStr.
-  size_t getIndex() const { return InsertIdx; }
-
-  /// \returns a string containing the result of the substitution represented
-  /// by this class instance or an error if substitution failed.
-  virtual Expected<std::string> getResult() const = 0;
-};
-
-class FileCheckStringSubstitution : public FileCheckSubstitution {
-public:
-  FileCheckStringSubstitution(FileCheckPatternContext *Context,
-                              StringRef VarName, size_t InsertIdx)
-      : FileCheckSubstitution(Context, VarName, InsertIdx) {}
-
-  /// \returns the text that the string variable in this substitution matched
-  /// when defined, or an error if the variable is undefined.
-  Expected<std::string> getResult() const override;
-};
-
-class FileCheckNumericSubstitution : public FileCheckSubstitution {
-private:
-  /// Pointer to the class representing the expression whose value is to be
-  /// substituted.
-  std::unique_ptr<FileCheckExpressionAST> ExpressionAST;
-
-public:
-  FileCheckNumericSubstitution(FileCheckPatternContext *Context, StringRef Expr,
-                               std::unique_ptr<FileCheckExpressionAST> ExprAST,
-                               size_t InsertIdx)
-      : FileCheckSubstitution(Context, Expr, InsertIdx) {
-    ExpressionAST = std::move(ExprAST);
-  }
-
-  /// \returns a string containing the result of evaluating the expression in
-  /// this substitution, or an error if evaluation failed.
-  Expected<std::string> getResult() const override;
-};
-
-//===----------------------------------------------------------------------===//
-// Pattern handling code.
-//===----------------------------------------------------------------------===//
-
-struct FileCheckDiag;
-
-/// Class holding the FileCheckPattern 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.
-class FileCheckPatternContext {
-  friend class FileCheckPattern;
-
-private:
-  /// 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 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;
-
-  /// When matching a given pattern, this holds the pointers to the classes
-  /// representing the numeric variables defined in previous patterns. When
-  /// matching a pattern all definitions for that pattern are recorded in the
-  /// NumericVariableDefs table in the FileCheckPattern instance of that
-  /// pattern.
-  StringMap<FileCheckNumericVariable *> GlobalNumericVariableTable;
-
-  /// Pointer to the class instance representing the @LINE pseudo variable for
-  /// easily updating its value.
-  FileCheckNumericVariable *LineVariable = nullptr;
-
-  /// Vector holding pointers to all parsed numeric variables. Used to
-  /// automatically free them once they are guaranteed to no longer be used.
-  std::vector<std::unique_ptr<FileCheckNumericVariable>> NumericVariables;
-
-  /// 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<FileCheckSubstitution>> Substitutions;
-
-public:
-  /// \returns the value of string variable \p VarName or an error if no such
-  /// variable has been defined.
-  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. \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);
-
-  /// Create @LINE pseudo variable. Value is set when pattern are being
-  /// matched.
-  void createLineVariable();
-
-  /// Undefines local variables (variables whose name does not start with a '$'
-  /// sign), i.e. removes them from GlobalVariableTable and from
-  /// GlobalNumericVariableTable and also clears the value of numeric
-  /// variables.
-  void clearLocalVars();
-
-private:
-  /// Makes a new numeric variable and registers it for destruction when the
-  /// context is destroyed.
-  template <class... Types>
-  FileCheckNumericVariable *makeNumericVariable(Types... args);
-
-  /// Makes a new string substitution and registers it for destruction when the
-  /// context is destroyed.
-  FileCheckSubstitution *makeStringSubstitution(StringRef VarName,
-                                                size_t InsertIdx);
-
-  /// Makes a new numeric substitution and registers it for destruction when
-  /// the context is destroyed.
-  FileCheckSubstitution *
-  makeNumericSubstitution(StringRef ExpressionStr,
-                          std::unique_ptr<FileCheckExpressionAST> ExpressionAST,
-                          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;
-
-  /// A fixed string to match as the pattern or empty if this pattern requires
-  /// a regex match.
-  StringRef FixedStr;
-
-  /// A regex string to match as the pattern or empty if this pattern requires
-  /// a fixed string to match.
-  std::string RegExStr;
-
-  /// Entries in this vector represent a substitution of a string variable or
-  /// an 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 string variable "bar" at offset 3
-  /// and the value of expression "N+1" at offset 6.
-  std::vector<FileCheckSubstitution *> Substitutions;
-
-  /// Maps names of string variables defined in a pattern to the number of
-  /// their parenthesis group in RegExStr capturing their last definition.
-  ///
-  /// E.g. for the pattern "foo[[bar:.*]]baz([[bar]][[QUUX]][[bar:.*]])",
-  /// RegExStr will be "foo(.*)baz(\1<quux value>(.*))" where <quux value> is
-  /// the value captured for QUUX on the earlier line where it was defined, and
-  /// VariableDefs will map "bar" to the third parenthesis group which captures
-  /// the second definition of "bar".
-  ///
-  /// Note: uses std::map rather than StringMap to be able to get the key when
-  /// iterating over values.
-  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.
-  struct FileCheckNumericVariableMatch {
-    /// Pointer to class representing the numeric variable whose value is being
-    /// defined.
-    FileCheckNumericVariable *DefinedNumericVariable;
-
-    /// Number of the parenthesis group in RegExStr that captures the value of
-    /// this numeric variable definition.
-    unsigned CaptureParenGroup;
-  };
-
-  /// Holds the number of the parenthesis group in RegExStr and pointer to the
-  /// corresponding FileCheckNumericVariable class instance of all numeric
-  /// variable definitions. Used to set the matched value of all those
-  /// variables.
-  StringMap<FileCheckNumericVariableMatch> NumericVariableDefs;
-
-  /// Pointer to a class instance holding the global state shared by all
-  /// patterns:
-  /// - separate tables with the values of live string and numeric variables
-  ///   respectively at the start of any given CHECK line;
-  /// - table holding whether a string variable has been defined at any given
-  ///   point during the parsing phase.
-  FileCheckPatternContext *Context;
-
-  Check::FileCheckType CheckTy;
-
-  /// Line number for this CHECK pattern or None if it is an implicit pattern.
-  /// Used to determine whether a variable definition is made on an earlier
-  /// line to the one with this CHECK.
-  Optional<size_t> LineNumber;
-
-public:
-  FileCheckPattern(Check::FileCheckType Ty, FileCheckPatternContext *Context,
-                   Optional<size_t> Line = None)
-      : Context(Context), CheckTy(Ty), LineNumber(Line) {}
-
-  /// \returns the location in source code.
-  SMLoc getLoc() const { return PatternLoc; }
-
-  /// \returns the pointer to the global state for all patterns in this
-  /// FileCheck instance.
-  FileCheckPatternContext *getContext() const { return Context; }
-
-  /// \returns whether \p C is a valid first character for a variable name.
-  static bool isValidVarNameStart(char C);
-
-  /// Parsing information about a variable.
-  struct VariableProperties {
-    StringRef Name;
-    bool IsPseudo;
-  };
-
-  /// Parses the string at the start of \p Str for a variable name. \returns
-  /// a VariableProperties structure holding the variable name and whether it
-  /// is the name of a pseudo variable, or an error holding a diagnostic
-  /// against \p SM if parsing fail. If parsing was successful, also strips
-  /// \p Str from the variable name.
-  static Expected<VariableProperties> parseVariable(StringRef &Str,
-                                                    const SourceMgr &SM);
-  /// Parses \p Expr for a numeric substitution block at line \p LineNumber,
-  /// or before input is parsed if \p LineNumber is None. Parameter
-  /// \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<FileCheckExpressionAST>>
-  parseNumericSubstitutionBlock(
-      StringRef Expr,
-      Optional<FileCheckNumericVariable *> &DefinedNumericVariable,
-      bool IsLegacyLineExpr, Optional<size_t> LineNumber,
-      FileCheckPatternContext *Context, const SourceMgr &SM);
-  /// Parses the pattern in \p PatternStr and initializes this FileCheckPattern
-  /// instance accordingly.
-  ///
-  /// \p Prefix provides which prefix is being matched, \p Req describes the
-  /// global options that influence the parsing such as whitespace
-  /// canonicalization, \p SM provides the SourceMgr used for error reports.
-  /// \returns true in case of an error, false otherwise.
-  bool parsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM,
-                    const FileCheckRequest &Req);
-  /// Matches the pattern string against the input buffer \p Buffer
-  ///
-  /// \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.
-  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 variables preventing a successful substitution.
-  void printSubstitutions(const SourceMgr &SM, StringRef Buffer,
-                          SMRange MatchRange = None) const;
-  void printFuzzyMatch(const SourceMgr &SM, StringRef Buffer,
-                       std::vector<FileCheckDiag> *Diags) const;
-
-  bool hasVariable() const {
-    return !(Substitutions.empty() && VariableDefs.empty());
-  }
-
-  Check::FileCheckType getCheckTy() const { return CheckTy; }
-
-  int getCount() const { return CheckTy.getCount(); }
-
-private:
-  bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM);
-  void AddBackrefToRegEx(unsigned BackrefNum);
-  /// Computes an arbitrary estimate for the quality of matching this pattern
-  /// at the start of \p Buffer; a distance of zero should correspond to a
-  /// perfect match.
-  unsigned computeMatchDistance(StringRef Buffer) const;
-  /// Finds the closing sequence of a regex variable usage or definition.
-  ///
-  /// \p Str has to point in the beginning of the definition (right after the
-  /// opening sequence). \p SM holds the SourceMgr used for error repporting.
-  ///  \returns the offset of the closing sequence within Str, or npos if it
-  /// was not found.
-  size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM);
-
-  /// Parses \p Expr for the name of a numeric variable to be defined at line
-  /// \p LineNumber, or before input is parsed if \p LineNumber is None.
-  /// \returns a pointer to the class instance representing that variable,
-  /// creating it if needed, or an error holding a diagnostic against \p SM
-  /// should defining such a variable be invalid.
-  static Expected<FileCheckNumericVariable *> parseNumericVariableDefinition(
-      StringRef &Expr, FileCheckPatternContext *Context,
-      Optional<size_t> LineNumber, 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
-  /// string and numeric variables. \returns the pointer to the class instance
-  /// representing that variable if successful, or an error holding a
-  /// diagnostic against \p SM otherwise.
-  static Expected<std::unique_ptr<FileCheckNumericVariableUse>>
-  parseNumericVariableUse(StringRef Name, bool IsPseudo,
-                          Optional<size_t> LineNumber,
-                          FileCheckPatternContext *Context,
-                          const SourceMgr &SM);
-  enum class AllowedOperand { LineVar, Literal, 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.
-  static Expected<std::unique_ptr<FileCheckExpressionAST>>
-  parseNumericOperand(StringRef &Expr, AllowedOperand AO,
-                      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.
-  static Expected<std::unique_ptr<FileCheckExpressionAST>>
-  parseBinop(StringRef &Expr, std::unique_ptr<FileCheckExpressionAST> LeftOp,
-             bool IsLegacyLineExpr, Optional<size_t> LineNumber,
-             FileCheckPatternContext *Context, const SourceMgr &SM);
-};
-
-//===----------------------------------------------------------------------===//
-// Check Strings.
-//===----------------------------------------------------------------------===//
-
-/// A check that we found in the input file.
-struct FileCheckString {
-  /// The pattern to match.
-  FileCheckPattern Pat;
-
-  /// Which prefix name this check matched.
-  StringRef Prefix;
-
-  /// The location in the match file that the check string was specified.
-  SMLoc Loc;
-
-  /// All of the strings that are disallowed from occurring between this match
-  /// string and the previous one (or start of file).
-  std::vector<FileCheckPattern> DagNotStrings;
-
-  FileCheckString(const FileCheckPattern &P, StringRef S, SMLoc L)
-      : Pat(P), Prefix(S), Loc(L) {}
-
-  /// Matches check string and its "not strings" and/or "dag strings".
-  size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode,
-               size_t &MatchLen, FileCheckRequest &Req,
-               std::vector<FileCheckDiag> *Diags) const;
-
-  /// Verifies that there is a single line in the given \p Buffer. Errors are
-  /// reported against \p SM.
-  bool CheckNext(const SourceMgr &SM, StringRef Buffer) const;
-  /// Verifies that there is no newline in the given \p Buffer. Errors are
-  /// reported against \p SM.
-  bool CheckSame(const SourceMgr &SM, StringRef Buffer) const;
-  /// Verifies that none of the strings in \p NotStrings are found in the given
-  /// \p Buffer. Errors are reported against \p SM and diagnostics recorded in
-  /// \p Diags according to the verbosity level set in \p Req.
-  bool CheckNot(const SourceMgr &SM, StringRef Buffer,
-                const std::vector<const FileCheckPattern *> &NotStrings,
-                const FileCheckRequest &Req,
-                std::vector<FileCheckDiag> *Diags) const;
-  /// Matches "dag strings" and their mixed "not strings".
-  size_t CheckDag(const SourceMgr &SM, StringRef Buffer,
-                  std::vector<const FileCheckPattern *> &NotStrings,
-                  const FileCheckRequest &Req,
-                  std::vector<FileCheckDiag> *Diags) const;
-};
-
-} // namespace llvm
-
-#endif
+//===-- FileCheckImpl.h - Private FileCheck Interface ------------*- C++ -*-==//\r
+//\r
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.\r
+// See https://llvm.org/LICENSE.txt for license information.\r
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\r
+//\r
+//===----------------------------------------------------------------------===//\r
+//\r
+// This file defines the private interfaces of FileCheck. Its purpose is to\r
+// allow unit testing of FileCheck and to separate the interface from the\r
+// implementation. It is only meant to be used by FileCheck.\r
+//\r
+//===----------------------------------------------------------------------===//\r
+\r
+#ifndef LLVM_LIB_SUPPORT_FILECHECKIMPL_H\r
+#define LLVM_LIB_SUPPORT_FILECHECKIMPL_H\r
+\r
+#include "llvm/ADT/Optional.h"\r
+#include "llvm/ADT/StringMap.h"\r
+#include "llvm/ADT/StringRef.h"\r
+#include "llvm/Support/Error.h"\r
+#include "llvm/Support/SourceMgr.h"\r
+#include <map>\r
+#include <string>\r
+#include <vector>\r
+\r
+namespace llvm {\r
+\r
+//===----------------------------------------------------------------------===//\r
+// Numeric substitution handling code.\r
+//===----------------------------------------------------------------------===//\r
+\r
+/// Base class representing the AST of a given expression.\r
+class FileCheckExpressionAST {\r
+public:\r
+  virtual ~FileCheckExpressionAST() = default;\r
+\r
+  /// Evaluates and \returns the value of the expression represented by this\r
+  /// AST or an error if evaluation fails.\r
+  virtual Expected<uint64_t> eval() const = 0;\r
+};\r
+\r
+/// Class representing an unsigned literal in the AST of an expression.\r
+class FileCheckExpressionLiteral : public FileCheckExpressionAST {\r
+private:\r
+  /// Actual value of the literal.\r
+  uint64_t Value;\r
+\r
+public:\r
+  /// Constructs a literal with the specified value.\r
+  FileCheckExpressionLiteral(uint64_t Val) : Value(Val) {}\r
+\r
+  /// \returns the literal's value.\r
+  Expected<uint64_t> eval() const { return Value; }\r
+};\r
+\r
+/// Class to represent an undefined variable error, which quotes that\r
+/// variable's name when printed.\r
+class FileCheckUndefVarError : public ErrorInfo<FileCheckUndefVarError> {\r
+private:\r
+  StringRef VarName;\r
+\r
+public:\r
+  static char ID;\r
+\r
+  FileCheckUndefVarError(StringRef VarName) : VarName(VarName) {}\r
+\r
+  StringRef getVarName() const { return VarName; }\r
+\r
+  std::error_code convertToErrorCode() const override {\r
+    return inconvertibleErrorCode();\r
+  }\r
+\r
+  /// Print name of variable associated with this error.\r
+  void log(raw_ostream &OS) const override {\r
+    OS << "\"";\r
+    OS.write_escaped(VarName) << "\"";\r
+  }\r
+};\r
+\r
+/// Class representing a numeric variable and its associated current value.\r
+class FileCheckNumericVariable {\r
+private:\r
+  /// Name of the numeric variable.\r
+  StringRef Name;\r
+\r
+  /// Value of numeric variable, if defined, or None otherwise.\r
+  Optional<uint64_t> Value;\r
+\r
+  /// Line number where this variable is defined, or None if defined before\r
+  /// input is parsed. Used to determine whether a variable is defined on the\r
+  /// same line as a given use.\r
+  Optional<size_t> DefLineNumber;\r
+\r
+public:\r
+  /// Constructor for a variable \p Name defined at line \p DefLineNumber or\r
+  /// defined before input is parsed if \p DefLineNumber is None.\r
+  explicit FileCheckNumericVariable(StringRef Name,\r
+                                    Optional<size_t> DefLineNumber = None)\r
+      : Name(Name), DefLineNumber(DefLineNumber) {}\r
+\r
+  /// \returns name of this numeric variable.\r
+  StringRef getName() const { return Name; }\r
+\r
+  /// \returns this variable's value.\r
+  Optional<uint64_t> getValue() const { return Value; }\r
+\r
+  /// Sets value of this numeric variable to \p NewValue.\r
+  void setValue(uint64_t NewValue) { Value = NewValue; }\r
+\r
+  /// Clears value of this numeric variable, regardless of whether it is\r
+  /// currently defined or not.\r
+  void clearValue() { Value = None; }\r
+\r
+  /// \returns the line number where this variable is defined, if any, or None\r
+  /// if defined before input is parsed.\r
+  Optional<size_t> getDefLineNumber() { return DefLineNumber; }\r
+};\r
+\r
+/// Class representing the use of a numeric variable in the AST of an\r
+/// expression.\r
+class FileCheckNumericVariableUse : public FileCheckExpressionAST {\r
+private:\r
+  /// Name of the numeric variable.\r
+  StringRef Name;\r
+\r
+  /// Pointer to the class instance for the variable this use is about.\r
+  FileCheckNumericVariable *NumericVariable;\r
+\r
+public:\r
+  FileCheckNumericVariableUse(StringRef Name,\r
+                              FileCheckNumericVariable *NumericVariable)\r
+      : Name(Name), NumericVariable(NumericVariable) {}\r
+\r
+  /// \returns the value of the variable referenced by this instance.\r
+  Expected<uint64_t> eval() const;\r
+};\r
+\r
+/// Type of functions evaluating a given binary operation.\r
+using binop_eval_t = uint64_t (*)(uint64_t, uint64_t);\r
+\r
+/// Class representing a single binary operation in the AST of an expression.\r
+class FileCheckASTBinop : public FileCheckExpressionAST {\r
+private:\r
+  /// Left operand.\r
+  std::unique_ptr<FileCheckExpressionAST> LeftOperand;\r
+\r
+  /// Right operand.\r
+  std::unique_ptr<FileCheckExpressionAST> RightOperand;\r
+\r
+  /// Pointer to function that can evaluate this binary operation.\r
+  binop_eval_t EvalBinop;\r
+\r
+public:\r
+  FileCheckASTBinop(binop_eval_t EvalBinop,\r
+                    std::unique_ptr<FileCheckExpressionAST> LeftOp,\r
+                    std::unique_ptr<FileCheckExpressionAST> RightOp)\r
+      : EvalBinop(EvalBinop) {\r
+    LeftOperand = std::move(LeftOp);\r
+    RightOperand = std::move(RightOp);\r
+  }\r
+\r
+  /// Evaluates the value of the binary operation represented by this AST,\r
+  /// using EvalBinop on the result of recursively evaluating the operands.\r
+  /// \returns the expression value or an error if an undefined numeric\r
+  /// variable is used in one of the operands.\r
+  Expected<uint64_t> eval() const;\r
+};\r
+\r
+class FileCheckPatternContext;\r
+\r
+/// Class representing a substitution to perform in the RegExStr string.\r
+class FileCheckSubstitution {\r
+protected:\r
+  /// Pointer to a class instance holding, among other things, the table with\r
+  /// the values of live string variables at the start of any given CHECK line.\r
+  /// Used for substituting string variables with the text they were defined\r
+  /// as. Expressions are linked to the numeric variables they use at\r
+  /// parse time and directly access the value of the numeric variable to\r
+  /// evaluate their value.\r
+  FileCheckPatternContext *Context;\r
+\r
+  /// The string that needs to be substituted for something else. For a\r
+  /// string variable this is its name, otherwise this is the whole expression.\r
+  StringRef FromStr;\r
+\r
+  // Index in RegExStr of where to do the substitution.\r
+  size_t InsertIdx;\r
+\r
+public:\r
+  FileCheckSubstitution(FileCheckPatternContext *Context, StringRef VarName,\r
+                        size_t InsertIdx)\r
+      : Context(Context), FromStr(VarName), InsertIdx(InsertIdx) {}\r
+\r
+  virtual ~FileCheckSubstitution() = default;\r
+\r
+  /// \returns the string to be substituted for something else.\r
+  StringRef getFromString() const { return FromStr; }\r
+\r
+  /// \returns the index where the substitution is to be performed in RegExStr.\r
+  size_t getIndex() const { return InsertIdx; }\r
+\r
+  /// \returns a string containing the result of the substitution represented\r
+  /// by this class instance or an error if substitution failed.\r
+  virtual Expected<std::string> getResult() const = 0;\r
+};\r
+\r
+class FileCheckStringSubstitution : public FileCheckSubstitution {\r
+public:\r
+  FileCheckStringSubstitution(FileCheckPatternContext *Context,\r
+                              StringRef VarName, size_t InsertIdx)\r
+      : FileCheckSubstitution(Context, VarName, InsertIdx) {}\r
+\r
+  /// \returns the text that the string variable in this substitution matched\r
+  /// when defined, or an error if the variable is undefined.\r
+  Expected<std::string> getResult() const override;\r
+};\r
+\r
+class FileCheckNumericSubstitution : public FileCheckSubstitution {\r
+private:\r
+  /// Pointer to the class representing the expression whose value is to be\r
+  /// substituted.\r
+  std::unique_ptr<FileCheckExpressionAST> ExpressionAST;\r
+\r
+public:\r
+  FileCheckNumericSubstitution(FileCheckPatternContext *Context, StringRef Expr,\r
+                               std::unique_ptr<FileCheckExpressionAST> ExprAST,\r
+                               size_t InsertIdx)\r
+      : FileCheckSubstitution(Context, Expr, InsertIdx) {\r
+    ExpressionAST = std::move(ExprAST);\r
+  }\r
+\r
+  /// \returns a string containing the result of evaluating the expression in\r
+  /// this substitution, or an error if evaluation failed.\r
+  Expected<std::string> getResult() const override;\r
+};\r
+\r
+//===----------------------------------------------------------------------===//\r
+// Pattern handling code.\r
+//===----------------------------------------------------------------------===//\r
+\r
+struct FileCheckDiag;\r
+\r
+/// Class holding the FileCheckPattern global state, shared by all patterns:\r
+/// tables holding values of variables and whether they are defined or not at\r
+/// any given time in the matching process.\r
+class FileCheckPatternContext {\r
+  friend class FileCheckPattern;\r
+\r
+private:\r
+  /// When matching a given pattern, this holds the value of all the string\r
+  /// variables defined in previous patterns. In a pattern, only the last\r
+  /// definition for a given variable is recorded in this table.\r
+  /// Back-references are used for uses after any the other definition.\r
+  StringMap<StringRef> GlobalVariableTable;\r
+\r
+  /// Map of all string variables defined so far. Used at parse time to detect\r
+  /// a name conflict between a numeric variable and a string variable when\r
+  /// the former is defined on a later line than the latter.\r
+  StringMap<bool> DefinedVariableTable;\r
+\r
+  /// When matching a given pattern, this holds the pointers to the classes\r
+  /// representing the numeric variables defined in previous patterns. When\r
+  /// matching a pattern all definitions for that pattern are recorded in the\r
+  /// NumericVariableDefs table in the FileCheckPattern instance of that\r
+  /// pattern.\r
+  StringMap<FileCheckNumericVariable *> GlobalNumericVariableTable;\r
+\r
+  /// Pointer to the class instance representing the @LINE pseudo variable for\r
+  /// easily updating its value.\r
+  FileCheckNumericVariable *LineVariable = nullptr;\r
+\r
+  /// Vector holding pointers to all parsed numeric variables. Used to\r
+  /// automatically free them once they are guaranteed to no longer be used.\r
+  std::vector<std::unique_ptr<FileCheckNumericVariable>> NumericVariables;\r
+\r
+  /// Vector holding pointers to all substitutions. Used to automatically free\r
+  /// them once they are guaranteed to no longer be used.\r
+  std::vector<std::unique_ptr<FileCheckSubstitution>> Substitutions;\r
+\r
+public:\r
+  /// \returns the value of string variable \p VarName or an error if no such\r
+  /// variable has been defined.\r
+  Expected<StringRef> getPatternVarValue(StringRef VarName);\r
+\r
+  /// Defines string and numeric variables from definitions given on the\r
+  /// command line, passed as a vector of [#]VAR=VAL strings in\r
+  /// \p CmdlineDefines. \returns an error list containing diagnostics against\r
+  /// \p SM for all definition parsing failures, if any, or Success otherwise.\r
+  Error defineCmdlineVariables(std::vector<std::string> &CmdlineDefines,\r
+                               SourceMgr &SM);\r
+\r
+  /// Create @LINE pseudo variable. Value is set when pattern are being\r
+  /// matched.\r
+  void createLineVariable();\r
+\r
+  /// Undefines local variables (variables whose name does not start with a '$'\r
+  /// sign), i.e. removes them from GlobalVariableTable and from\r
+  /// GlobalNumericVariableTable and also clears the value of numeric\r
+  /// variables.\r
+  void clearLocalVars();\r
+\r
+private:\r
+  /// Makes a new numeric variable and registers it for destruction when the\r
+  /// context is destroyed.\r
+  template <class... Types>\r
+  FileCheckNumericVariable *makeNumericVariable(Types... args);\r
+\r
+  /// Makes a new string substitution and registers it for destruction when the\r
+  /// context is destroyed.\r
+  FileCheckSubstitution *makeStringSubstitution(StringRef VarName,\r
+                                                size_t InsertIdx);\r
+\r
+  /// Makes a new numeric substitution and registers it for destruction when\r
+  /// the context is destroyed.\r
+  FileCheckSubstitution *\r
+  makeNumericSubstitution(StringRef ExpressionStr,\r
+                          std::unique_ptr<FileCheckExpressionAST> ExpressionAST,\r
+                          size_t InsertIdx);\r
+};\r
+\r
+/// Class to represent an error holding a diagnostic with location information\r
+/// used when printing it.\r
+class FileCheckErrorDiagnostic : public ErrorInfo<FileCheckErrorDiagnostic> {\r
+private:\r
+  SMDiagnostic Diagnostic;\r
+\r
+public:\r
+  static char ID;\r
+\r
+  FileCheckErrorDiagnostic(SMDiagnostic &&Diag) : Diagnostic(Diag) {}\r
+\r
+  std::error_code convertToErrorCode() const override {\r
+    return inconvertibleErrorCode();\r
+  }\r
+\r
+  /// Print diagnostic associated with this error when printing the error.\r
+  void log(raw_ostream &OS) const override { Diagnostic.print(nullptr, OS); }\r
+\r
+  static Error get(const SourceMgr &SM, SMLoc Loc, const Twine &ErrMsg) {\r
+    return make_error<FileCheckErrorDiagnostic>(\r
+        SM.GetMessage(Loc, SourceMgr::DK_Error, ErrMsg));\r
+  }\r
+\r
+  static Error get(const SourceMgr &SM, StringRef Buffer, const Twine &ErrMsg) {\r
+    return get(SM, SMLoc::getFromPointer(Buffer.data()), ErrMsg);\r
+  }\r
+};\r
+\r
+class FileCheckNotFoundError : public ErrorInfo<FileCheckNotFoundError> {\r
+public:\r
+  static char ID;\r
+\r
+  std::error_code convertToErrorCode() const override {\r
+    return inconvertibleErrorCode();\r
+  }\r
+\r
+  /// Print diagnostic associated with this error when printing the error.\r
+  void log(raw_ostream &OS) const override {\r
+    OS << "String not found in input";\r
+  }\r
+};\r
+\r
+class FileCheckPattern {\r
+  SMLoc PatternLoc;\r
+\r
+  /// A fixed string to match as the pattern or empty if this pattern requires\r
+  /// a regex match.\r
+  StringRef FixedStr;\r
+\r
+  /// A regex string to match as the pattern or empty if this pattern requires\r
+  /// a fixed string to match.\r
+  std::string RegExStr;\r
+\r
+  /// Entries in this vector represent a substitution of a string variable or\r
+  /// an expression in the RegExStr regex at match time. For example, in the\r
+  /// case of a CHECK directive with the pattern "foo[[bar]]baz[[#N+1]]",\r
+  /// RegExStr will contain "foobaz" and we'll get two entries in this vector\r
+  /// that tells us to insert the value of string variable "bar" at offset 3\r
+  /// and the value of expression "N+1" at offset 6.\r
+  std::vector<FileCheckSubstitution *> Substitutions;\r
+\r
+  /// Maps names of string variables defined in a pattern to the number of\r
+  /// their parenthesis group in RegExStr capturing their last definition.\r
+  ///\r
+  /// E.g. for the pattern "foo[[bar:.*]]baz([[bar]][[QUUX]][[bar:.*]])",\r
+  /// RegExStr will be "foo(.*)baz(\1<quux value>(.*))" where <quux value> is\r
+  /// the value captured for QUUX on the earlier line where it was defined, and\r
+  /// VariableDefs will map "bar" to the third parenthesis group which captures\r
+  /// the second definition of "bar".\r
+  ///\r
+  /// Note: uses std::map rather than StringMap to be able to get the key when\r
+  /// iterating over values.\r
+  std::map<StringRef, unsigned> VariableDefs;\r
+\r
+  /// Structure representing the definition of a numeric variable in a pattern.\r
+  /// It holds the pointer to the class representing the numeric variable whose\r
+  /// value is being defined and the number of the parenthesis group in\r
+  /// RegExStr to capture that value.\r
+  struct FileCheckNumericVariableMatch {\r
+    /// Pointer to class representing the numeric variable whose value is being\r
+    /// defined.\r
+    FileCheckNumericVariable *DefinedNumericVariable;\r
+\r
+    /// Number of the parenthesis group in RegExStr that captures the value of\r
+    /// this numeric variable definition.\r
+    unsigned CaptureParenGroup;\r
+  };\r
+\r
+  /// Holds the number of the parenthesis group in RegExStr and pointer to the\r
+  /// corresponding FileCheckNumericVariable class instance of all numeric\r
+  /// variable definitions. Used to set the matched value of all those\r
+  /// variables.\r
+  StringMap<FileCheckNumericVariableMatch> NumericVariableDefs;\r
+\r
+  /// Pointer to a class instance holding the global state shared by all\r
+  /// patterns:\r
+  /// - separate tables with the values of live string and numeric variables\r
+  ///   respectively at the start of any given CHECK line;\r
+  /// - table holding whether a string variable has been defined at any given\r
+  ///   point during the parsing phase.\r
+  FileCheckPatternContext *Context;\r
+\r
+  Check::FileCheckType CheckTy;\r
+\r
+  /// Line number for this CHECK pattern or None if it is an implicit pattern.\r
+  /// Used to determine whether a variable definition is made on an earlier\r
+  /// line to the one with this CHECK.\r
+  Optional<size_t> LineNumber;\r
+\r
+  /// Ignore case while matching if set to true.\r
+  bool IgnoreCase = false;\r
+\r
+public:\r
+  FileCheckPattern(Check::FileCheckType Ty, FileCheckPatternContext *Context,\r
+                   Optional<size_t> Line = None)\r
+      : Context(Context), CheckTy(Ty), LineNumber(Line) {}\r
+\r
+  /// \returns the location in source code.\r
+  SMLoc getLoc() const { return PatternLoc; }\r
+\r
+  /// \returns the pointer to the global state for all patterns in this\r
+  /// FileCheck instance.\r
+  FileCheckPatternContext *getContext() const { return Context; }\r
+\r
+  /// \returns whether \p C is a valid first character for a variable name.\r
+  static bool isValidVarNameStart(char C);\r
+\r
+  /// Parsing information about a variable.\r
+  struct VariableProperties {\r
+    StringRef Name;\r
+    bool IsPseudo;\r
+  };\r
+\r
+  /// Parses the string at the start of \p Str for a variable name. \returns\r
+  /// a VariableProperties structure holding the variable name and whether it\r
+  /// is the name of a pseudo variable, or an error holding a diagnostic\r
+  /// against \p SM if parsing fail. If parsing was successful, also strips\r
+  /// \p Str from the variable name.\r
+  static Expected<VariableProperties> parseVariable(StringRef &Str,\r
+                                                    const SourceMgr &SM);\r
+  /// Parses \p Expr for a numeric substitution block at line \p LineNumber,\r
+  /// or before input is parsed if \p LineNumber is None. Parameter\r
+  /// \p IsLegacyLineExpr indicates whether \p Expr should be a legacy @LINE\r
+  /// expression and \p Context points to the class instance holding the live\r
+  /// string and numeric variables. \returns a pointer to the class instance\r
+  /// representing the AST of the expression whose value must be substitued, or\r
+  /// an error holding a diagnostic against \p SM if parsing fails. If\r
+  /// substitution was successful, sets \p DefinedNumericVariable to point to\r
+  /// the class representing the numeric variable defined in this numeric\r
+  /// substitution block, or None if this block does not define any variable.\r
+  static Expected<std::unique_ptr<FileCheckExpressionAST>>\r
+  parseNumericSubstitutionBlock(\r
+      StringRef Expr,\r
+      Optional<FileCheckNumericVariable *> &DefinedNumericVariable,\r
+      bool IsLegacyLineExpr, Optional<size_t> LineNumber,\r
+      FileCheckPatternContext *Context, const SourceMgr &SM);\r
+  /// Parses the pattern in \p PatternStr and initializes this FileCheckPattern\r
+  /// instance accordingly.\r
+  ///\r
+  /// \p Prefix provides which prefix is being matched, \p Req describes the\r
+  /// global options that influence the parsing such as whitespace\r
+  /// canonicalization, \p SM provides the SourceMgr used for error reports.\r
+  /// \returns true in case of an error, false otherwise.\r
+  bool parsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM,\r
+                    const FileCheckRequest &Req);\r
+  /// Matches the pattern string against the input buffer \p Buffer\r
+  ///\r
+  /// \returns the position that is matched or an error indicating why matching\r
+  /// failed. If there is a match, updates \p MatchLen with the size of the\r
+  /// matched string.\r
+  ///\r
+  /// The GlobalVariableTable StringMap in the FileCheckPatternContext class\r
+  /// instance provides the current values of FileCheck string variables and\r
+  /// is updated if this match defines new values. Likewise, the\r
+  /// GlobalNumericVariableTable StringMap in the same class provides the\r
+  /// current values of FileCheck numeric variables and is updated if this\r
+  /// match defines new numeric values.\r
+  Expected<size_t> match(StringRef Buffer, size_t &MatchLen,\r
+                         const SourceMgr &SM) const;\r
+  /// Prints the value of successful substitutions or the name of the undefined\r
+  /// string or numeric variables preventing a successful substitution.\r
+  void printSubstitutions(const SourceMgr &SM, StringRef Buffer,\r
+                          SMRange MatchRange = None) const;\r
+  void printFuzzyMatch(const SourceMgr &SM, StringRef Buffer,\r
+                       std::vector<FileCheckDiag> *Diags) const;\r
+\r
+  bool hasVariable() const {\r
+    return !(Substitutions.empty() && VariableDefs.empty());\r
+  }\r
+\r
+  Check::FileCheckType getCheckTy() const { return CheckTy; }\r
+\r
+  int getCount() const { return CheckTy.getCount(); }\r
+\r
+private:\r
+  bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM);\r
+  void AddBackrefToRegEx(unsigned BackrefNum);\r
+  /// Computes an arbitrary estimate for the quality of matching this pattern\r
+  /// at the start of \p Buffer; a distance of zero should correspond to a\r
+  /// perfect match.\r
+  unsigned computeMatchDistance(StringRef Buffer) const;\r
+  /// Finds the closing sequence of a regex variable usage or definition.\r
+  ///\r
+  /// \p Str has to point in the beginning of the definition (right after the\r
+  /// opening sequence). \p SM holds the SourceMgr used for error repporting.\r
+  ///  \returns the offset of the closing sequence within Str, or npos if it\r
+  /// was not found.\r
+  size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM);\r
+\r
+  /// Parses \p Expr for the name of a numeric variable to be defined at line\r
+  /// \p LineNumber, or before input is parsed if \p LineNumber is None.\r
+  /// \returns a pointer to the class instance representing that variable,\r
+  /// creating it if needed, or an error holding a diagnostic against \p SM\r
+  /// should defining such a variable be invalid.\r
+  static Expected<FileCheckNumericVariable *> parseNumericVariableDefinition(\r
+      StringRef &Expr, FileCheckPatternContext *Context,\r
+      Optional<size_t> LineNumber, const SourceMgr &SM);\r
+  /// Parses \p Name as a (pseudo if \p IsPseudo is true) numeric variable use\r
+  /// at line \p LineNumber, or before input is parsed if \p LineNumber is\r
+  /// None. Parameter \p Context points to the class instance holding the live\r
+  /// string and numeric variables. \returns the pointer to the class instance\r
+  /// representing that variable if successful, or an error holding a\r
+  /// diagnostic against \p SM otherwise.\r
+  static Expected<std::unique_ptr<FileCheckNumericVariableUse>>\r
+  parseNumericVariableUse(StringRef Name, bool IsPseudo,\r
+                          Optional<size_t> LineNumber,\r
+                          FileCheckPatternContext *Context,\r
+                          const SourceMgr &SM);\r
+  enum class AllowedOperand { LineVar, Literal, Any };\r
+  /// Parses \p Expr for use of a numeric operand at line \p LineNumber, or\r
+  /// before input is parsed if \p LineNumber is None. Accepts both literal\r
+  /// values and numeric variables, depending on the value of \p AO. Parameter\r
+  /// \p Context points to the class instance holding the live string and\r
+  /// numeric variables. \returns the class representing that operand in the\r
+  /// AST of the expression or an error holding a diagnostic against \p SM\r
+  /// otherwise.\r
+  static Expected<std::unique_ptr<FileCheckExpressionAST>>\r
+  parseNumericOperand(StringRef &Expr, AllowedOperand AO,\r
+                      Optional<size_t> LineNumber,\r
+                      FileCheckPatternContext *Context, const SourceMgr &SM);\r
+  /// Parses \p Expr for a binary operation at line \p LineNumber, or before\r
+  /// input is parsed if \p LineNumber is None. The left operand of this binary\r
+  /// operation is given in \p LeftOp and \p IsLegacyLineExpr indicates whether\r
+  /// we are parsing a legacy @LINE expression. Parameter \p Context points to\r
+  /// the class instance holding the live string and numeric variables.\r
+  /// \returns the class representing the binary operation in the AST of the\r
+  /// expression, or an error holding a diagnostic against \p SM otherwise.\r
+  static Expected<std::unique_ptr<FileCheckExpressionAST>>\r
+  parseBinop(StringRef &Expr, std::unique_ptr<FileCheckExpressionAST> LeftOp,\r
+             bool IsLegacyLineExpr, Optional<size_t> LineNumber,\r
+             FileCheckPatternContext *Context, const SourceMgr &SM);\r
+};\r
+\r
+//===----------------------------------------------------------------------===//\r
+// Check Strings.\r
+//===----------------------------------------------------------------------===//\r
+\r
+/// A check that we found in the input file.\r
+struct FileCheckString {\r
+  /// The pattern to match.\r
+  FileCheckPattern Pat;\r
+\r
+  /// Which prefix name this check matched.\r
+  StringRef Prefix;\r
+\r
+  /// The location in the match file that the check string was specified.\r
+  SMLoc Loc;\r
+\r
+  /// All of the strings that are disallowed from occurring between this match\r
+  /// string and the previous one (or start of file).\r
+  std::vector<FileCheckPattern> DagNotStrings;\r
+\r
+  FileCheckString(const FileCheckPattern &P, StringRef S, SMLoc L)\r
+      : Pat(P), Prefix(S), Loc(L) {}\r
+\r
+  /// Matches check string and its "not strings" and/or "dag strings".\r
+  size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode,\r
+               size_t &MatchLen, FileCheckRequest &Req,\r
+               std::vector<FileCheckDiag> *Diags) const;\r
+\r
+  /// Verifies that there is a single line in the given \p Buffer. Errors are\r
+  /// reported against \p SM.\r
+  bool CheckNext(const SourceMgr &SM, StringRef Buffer) const;\r
+  /// Verifies that there is no newline in the given \p Buffer. Errors are\r
+  /// reported against \p SM.\r
+  bool CheckSame(const SourceMgr &SM, StringRef Buffer) const;\r
+  /// Verifies that none of the strings in \p NotStrings are found in the given\r
+  /// \p Buffer. Errors are reported against \p SM and diagnostics recorded in\r
+  /// \p Diags according to the verbosity level set in \p Req.\r
+  bool CheckNot(const SourceMgr &SM, StringRef Buffer,\r
+                const std::vector<const FileCheckPattern *> &NotStrings,\r
+                const FileCheckRequest &Req,\r
+                std::vector<FileCheckDiag> *Diags) const;\r
+  /// Matches "dag strings" and their mixed "not strings".\r
+  size_t CheckDag(const SourceMgr &SM, StringRef Buffer,\r
+                  std::vector<const FileCheckPattern *> &NotStrings,\r
+                  const FileCheckRequest &Req,\r
+                  std::vector<FileCheckDiag> *Diags) const;\r
+};\r
+\r
+} // namespace llvm\r
+\r
+#endif\r
diff --git a/test/FileCheck/check-ignore-case.txt b/test/FileCheck/check-ignore-case.txt
new file mode 100644 (file)
index 0000000..8721c3f
--- /dev/null
@@ -0,0 +1,45 @@
+## Check that a full line is matched case insensitively.\r
+# RUN: FileCheck --ignore-case --match-full-lines --check-prefix=FULL --input-file=%s %s\r
+\r
+## Check that a regular expression matches case insensitively.\r
+# RUN: FileCheck --ignore-case --check-prefix=REGEX --input-file=%s %s\r
+\r
+## Check that a pattern from command line matches case insensitively.\r
+# RUN: FileCheck --ignore-case --check-prefix=PAT --DPATTERN="THIS is the" --input-file=%s %s\r
+\r
+## Check that COUNT and NEXT work case insensitively.\r
+# RUN: FileCheck --ignore-case --check-prefix=CNT --input-file=%s %s\r
+\r
+## Check that match on same line works case insensitively.\r
+# RUN: FileCheck --ignore-case --check-prefix=LINE --input-file=%s %s\r
+\r
+## Check that option --implicit-not works case insensitively.\r
+# RUN: sed '/^#/d' %s | FileCheck --implicit-check-not=sTrInG %s\r
+# RUN: sed '/^#/d' %s | not FileCheck --ignore-case --implicit-check-not=sTrInG %s 2>&1 | FileCheck --check-prefix=ERROR %s\r
+\r
+this is the STRING to be matched\r
+\r
+# FULL: tHis iS The String TO be matched\r
+# REGEX: s{{TRing}}\r
+# PAT: [[PATTERN]] string\r
+\r
+Loop 1\r
+lOop 2\r
+loOp 3\r
+looP 4\r
+loop 5\r
+LOOP 6\r
+BREAK\r
+\r
+# CNT-COUNT-6: LOop {{[0-9]}}\r
+# CNT-NOT: loop\r
+# CNT-NEXT: break\r
+\r
+One Line To Match\r
+\r
+# LINE: {{o}}ne line\r
+# LINE-SAME: {{t}}o match\r
+\r
+# ERROR: command line:1:{{[0-9]+]}}: error: CHECK-NOT: excluded string found in input\r
+# ERROR-NEXT: -implicit-check-not='sTrInG'\r
+# ERROR: note: found here\r
index 8718be28ac9978b7b88b58859aa1ee63c66a3e05..4d2cd1930d681d6d29c0ccf3cd5c87348e9a9dad 100644 (file)
-//===- FileCheck.cpp - Check that File's Contents match what is expected --===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// FileCheck does a line-by line check of a file that validates whether it
-// contains the expected content.  This is useful for regression tests etc.
-//
-// This program exits with an exit status of 2 on error, exit status of 0 if
-// the file matched the expected contents, and exit status of 1 if it did not
-// contain the expected contents.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/InitLLVM.h"
-#include "llvm/Support/Process.h"
-#include "llvm/Support/WithColor.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/FileCheck.h"
-#include <cmath>
-using namespace llvm;
-
-static cl::extrahelp FileCheckOptsEnv(
-    "\nOptions are parsed from the environment variable FILECHECK_OPTS and\n"
-    "from the command line.\n");
-
-static cl::opt<std::string>
-    CheckFilename(cl::Positional, cl::desc("<check-file>"), cl::Optional);
-
-static cl::opt<std::string>
-    InputFilename("input-file", cl::desc("File to check (defaults to stdin)"),
-                  cl::init("-"), cl::value_desc("filename"));
-
-static cl::list<std::string> CheckPrefixes(
-    "check-prefix",
-    cl::desc("Prefix to use from check file (defaults to 'CHECK')"));
-static cl::alias CheckPrefixesAlias(
-    "check-prefixes", cl::aliasopt(CheckPrefixes), cl::CommaSeparated,
-    cl::NotHidden,
-    cl::desc(
-        "Alias for -check-prefix permitting multiple comma separated values"));
-
-static cl::opt<bool> NoCanonicalizeWhiteSpace(
-    "strict-whitespace",
-    cl::desc("Do not treat all horizontal whitespace as equivalent"));
-
-static cl::list<std::string> ImplicitCheckNot(
-    "implicit-check-not",
-    cl::desc("Add an implicit negative check with this pattern to every\n"
-             "positive check. This can be used to ensure that no instances of\n"
-             "this pattern occur which are not matched by a positive pattern"),
-    cl::value_desc("pattern"));
-
-static cl::list<std::string>
-    GlobalDefines("D", cl::AlwaysPrefix,
-                  cl::desc("Define a variable to be used in capture patterns."),
-                  cl::value_desc("VAR=VALUE"));
-
-static cl::opt<bool> AllowEmptyInput(
-    "allow-empty", cl::init(false),
-    cl::desc("Allow the input file to be empty. This is useful when making\n"
-             "checks that some error message does not occur, for example."));
-
-static cl::opt<bool> MatchFullLines(
-    "match-full-lines", cl::init(false),
-    cl::desc("Require all positive matches to cover an entire input line.\n"
-             "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."));
-
-static cl::opt<bool> AllowDeprecatedDagOverlap(
-    "allow-deprecated-dag-overlap", cl::init(false),
-    cl::desc("Enable overlapping among matches in a group of consecutive\n"
-             "CHECK-DAG directives.  This option is deprecated and is only\n"
-             "provided for convenience as old tests are migrated to the new\n"
-             "non-overlapping CHECK-DAG implementation.\n"));
-
-static cl::opt<bool> Verbose(
-    "v", cl::init(false),
-    cl::desc("Print directive pattern matches, or add them to the input dump\n"
-             "if enabled.\n"));
-
-static cl::opt<bool> VerboseVerbose(
-    "vv", cl::init(false),
-    cl::desc("Print information helpful in diagnosing internal FileCheck\n"
-             "issues, or add it to the input dump if enabled.  Implies\n"
-             "-v.\n"));
-static const char * DumpInputEnv = "FILECHECK_DUMP_INPUT_ON_FAILURE";
-
-static cl::opt<bool> DumpInputOnFailure(
-    "dump-input-on-failure",
-    cl::init(std::getenv(DumpInputEnv) && *std::getenv(DumpInputEnv)),
-    cl::desc("Dump original input to stderr before failing.\n"
-             "The value can be also controlled using\n"
-             "FILECHECK_DUMP_INPUT_ON_FAILURE environment variable.\n"
-             "This option is deprecated in favor of -dump-input=fail.\n"));
-
-enum DumpInputValue {
-  DumpInputDefault,
-  DumpInputHelp,
-  DumpInputNever,
-  DumpInputFail,
-  DumpInputAlways
-};
-
-static cl::opt<DumpInputValue> DumpInput(
-    "dump-input", cl::init(DumpInputDefault),
-    cl::desc("Dump input to stderr, adding annotations representing\n"
-             " currently enabled diagnostics\n"),
-    cl::value_desc("mode"),
-    cl::values(clEnumValN(DumpInputHelp, "help",
-                          "Explain dump format and quit"),
-               clEnumValN(DumpInputNever, "never", "Never dump input"),
-               clEnumValN(DumpInputFail, "fail", "Dump input on failure"),
-               clEnumValN(DumpInputAlways, "always", "Always dump input")));
-
-typedef cl::list<std::string>::const_iterator prefix_iterator;
-
-
-
-
-
-
-
-static void DumpCommandLine(int argc, char **argv) {
-  errs() << "FileCheck command line: ";
-  for (int I = 0; I < argc; I++)
-    errs() << " " << argv[I];
-  errs() << "\n";
-}
-
-struct MarkerStyle {
-  /// The starting char (before tildes) for marking the line.
-  char Lead;
-  /// What color to use for this annotation.
-  raw_ostream::Colors Color;
-  /// A note to follow the marker, or empty string if none.
-  std::string Note;
-  MarkerStyle() {}
-  MarkerStyle(char Lead, raw_ostream::Colors Color,
-              const std::string &Note = "")
-      : Lead(Lead), Color(Color), Note(Note) {}
-};
-
-static MarkerStyle GetMarker(FileCheckDiag::MatchType MatchTy) {
-  switch (MatchTy) {
-  case FileCheckDiag::MatchFoundAndExpected:
-    return MarkerStyle('^', raw_ostream::GREEN);
-  case FileCheckDiag::MatchFoundButExcluded:
-    return MarkerStyle('!', raw_ostream::RED, "error: no match expected");
-  case FileCheckDiag::MatchFoundButWrongLine:
-    return MarkerStyle('!', raw_ostream::RED, "error: match on wrong line");
-  case FileCheckDiag::MatchFoundButDiscarded:
-    return MarkerStyle('!', raw_ostream::CYAN,
-                       "discard: overlaps earlier match");
-  case FileCheckDiag::MatchNoneAndExcluded:
-    return MarkerStyle('X', raw_ostream::GREEN);
-  case FileCheckDiag::MatchNoneButExpected:
-    return MarkerStyle('X', raw_ostream::RED, "error: no match found");
-  case FileCheckDiag::MatchFuzzy:
-    return MarkerStyle('?', raw_ostream::MAGENTA, "possible intended match");
-  }
-  llvm_unreachable_internal("unexpected match type");
-}
-
-static void DumpInputAnnotationHelp(raw_ostream &OS) {
-  OS << "The following description was requested by -dump-input=help to\n"
-     << "explain the input annotations printed by -dump-input=always and\n"
-     << "-dump-input=fail:\n\n";
-
-  // Labels for input lines.
-  OS << "  - ";
-  WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "L:";
-  OS << "     labels line number L of the input file\n";
-
-  // Labels for annotation lines.
-  OS << "  - ";
-  WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "T:L";
-  OS << "    labels the only match result for a pattern of type T from "
-     << "line L of\n"
-     << "           the check file\n";
-  OS << "  - ";
-  WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "T:L'N";
-  OS << "  labels the Nth match result for a pattern of type T from line "
-     << "L of\n"
-     << "           the check file\n";
-
-  // Markers on annotation lines.
-  OS << "  - ";
-  WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "^~~";
-  OS << "    marks good match (reported if -v)\n"
-     << "  - ";
-  WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "!~~";
-  OS << "    marks bad match, such as:\n"
-     << "           - CHECK-NEXT on same line as previous match (error)\n"
-     << "           - CHECK-NOT found (error)\n"
-     << "           - CHECK-DAG overlapping match (discarded, reported if "
-     << "-vv)\n"
-     << "  - ";
-  WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "X~~";
-  OS << "    marks search range when no match is found, such as:\n"
-     << "           - CHECK-NEXT not found (error)\n"
-     << "           - CHECK-NOT not found (success, reported if -vv)\n"
-     << "           - CHECK-DAG not found after discarded matches (error)\n"
-     << "  - ";
-  WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "?";
-  OS << "      marks fuzzy match when no match is found\n";
-
-  // Colors.
-  OS << "  - colors ";
-  WithColor(OS, raw_ostream::GREEN, true) << "success";
-  OS << ", ";
-  WithColor(OS, raw_ostream::RED, true) << "error";
-  OS << ", ";
-  WithColor(OS, raw_ostream::MAGENTA, true) << "fuzzy match";
-  OS << ", ";
-  WithColor(OS, raw_ostream::CYAN, true, false) << "discarded match";
-  OS << ", ";
-  WithColor(OS, raw_ostream::CYAN, true, true) << "unmatched input";
-  OS << "\n\n"
-     << "If you are not seeing color above or in input dumps, try: -color\n";
-}
-
-/// An annotation for a single input line.
-struct InputAnnotation {
-  /// The check file line (one-origin indexing) where the directive that
-  /// produced this annotation is located.
-  unsigned CheckLine;
-  /// The index of the match result for this check.
-  unsigned CheckDiagIndex;
-  /// The label for this annotation.
-  std::string Label;
-  /// What input line (one-origin indexing) this annotation marks.  This might
-  /// be different from the starting line of the original diagnostic if this is
-  /// a non-initial fragment of a diagnostic that has been broken across
-  /// multiple lines.
-  unsigned InputLine;
-  /// The column range (one-origin indexing, open end) in which to to mark the
-  /// input line.  If InputEndCol is UINT_MAX, treat it as the last column
-  /// before the newline.
-  unsigned InputStartCol, InputEndCol;
-  /// The marker to use.
-  MarkerStyle Marker;
-  /// Whether this annotation represents a good match for an expected pattern.
-  bool FoundAndExpectedMatch;
-};
-
-/// Get an abbreviation for the check type.
-std::string GetCheckTypeAbbreviation(Check::FileCheckType Ty) {
-  switch (Ty) {
-  case Check::CheckPlain:
-    if (Ty.getCount() > 1)
-      return "count";
-    return "check";
-  case Check::CheckNext:
-    return "next";
-  case Check::CheckSame:
-    return "same";
-  case Check::CheckNot:
-    return "not";
-  case Check::CheckDAG:
-    return "dag";
-  case Check::CheckLabel:
-    return "label";
-  case Check::CheckEmpty:
-    return "empty";
-  case Check::CheckEOF:
-    return "eof";
-  case Check::CheckBadNot:
-    return "bad-not";
-  case Check::CheckBadCount:
-    return "bad-count";
-  case Check::CheckNone:
-    llvm_unreachable("invalid FileCheckType");
-  }
-  llvm_unreachable("unknown FileCheckType");
-}
-
-static void BuildInputAnnotations(const std::vector<FileCheckDiag> &Diags,
-                                  std::vector<InputAnnotation> &Annotations,
-                                  unsigned &LabelWidth) {
-  // How many diagnostics has the current check seen so far?
-  unsigned CheckDiagCount = 0;
-  // What's the widest label?
-  LabelWidth = 0;
-  for (auto DiagItr = Diags.begin(), DiagEnd = Diags.end(); DiagItr != DiagEnd;
-       ++DiagItr) {
-    InputAnnotation A;
-
-    // Build label, which uniquely identifies this check result.
-    A.CheckLine = DiagItr->CheckLine;
-    llvm::raw_string_ostream Label(A.Label);
-    Label << GetCheckTypeAbbreviation(DiagItr->CheckTy) << ":"
-          << DiagItr->CheckLine;
-    A.CheckDiagIndex = UINT_MAX;
-    auto DiagNext = std::next(DiagItr);
-    if (DiagNext != DiagEnd && DiagItr->CheckTy == DiagNext->CheckTy &&
-        DiagItr->CheckLine == DiagNext->CheckLine)
-      A.CheckDiagIndex = CheckDiagCount++;
-    else if (CheckDiagCount) {
-      A.CheckDiagIndex = CheckDiagCount;
-      CheckDiagCount = 0;
-    }
-    if (A.CheckDiagIndex != UINT_MAX)
-      Label << "'" << A.CheckDiagIndex;
-    else
-      A.CheckDiagIndex = 0;
-    Label.flush();
-    LabelWidth = std::max((std::string::size_type)LabelWidth, A.Label.size());
-
-    A.Marker = GetMarker(DiagItr->MatchTy);
-    A.FoundAndExpectedMatch =
-        DiagItr->MatchTy == FileCheckDiag::MatchFoundAndExpected;
-
-    // Compute the mark location, and break annotation into multiple
-    // annotations if it spans multiple lines.
-    A.InputLine = DiagItr->InputStartLine;
-    A.InputStartCol = DiagItr->InputStartCol;
-    if (DiagItr->InputStartLine == DiagItr->InputEndLine) {
-      // Sometimes ranges are empty in order to indicate a specific point, but
-      // that would mean nothing would be marked, so adjust the range to
-      // include the following character.
-      A.InputEndCol =
-          std::max(DiagItr->InputStartCol + 1, DiagItr->InputEndCol);
-      Annotations.push_back(A);
-    } else {
-      assert(DiagItr->InputStartLine < DiagItr->InputEndLine &&
-             "expected input range not to be inverted");
-      A.InputEndCol = UINT_MAX;
-      Annotations.push_back(A);
-      for (unsigned L = DiagItr->InputStartLine + 1, E = DiagItr->InputEndLine;
-           L <= E; ++L) {
-        // If a range ends before the first column on a line, then it has no
-        // characters on that line, so there's nothing to render.
-        if (DiagItr->InputEndCol == 1 && L == E)
-          break;
-        InputAnnotation B;
-        B.CheckLine = A.CheckLine;
-        B.CheckDiagIndex = A.CheckDiagIndex;
-        B.Label = A.Label;
-        B.InputLine = L;
-        B.Marker = A.Marker;
-        B.Marker.Lead = '~';
-        B.Marker.Note = "";
-        B.InputStartCol = 1;
-        if (L != E)
-          B.InputEndCol = UINT_MAX;
-        else
-          B.InputEndCol = DiagItr->InputEndCol;
-        B.FoundAndExpectedMatch = A.FoundAndExpectedMatch;
-        Annotations.push_back(B);
-      }
-    }
-  }
-}
-
-static void DumpAnnotatedInput(raw_ostream &OS, const FileCheckRequest &Req,
-                               StringRef InputFileText,
-                               std::vector<InputAnnotation> &Annotations,
-                               unsigned LabelWidth) {
-  OS << "Full input was:\n<<<<<<\n";
-
-  // Sort annotations.
-  //
-  // First, sort in the order of input lines to make it easier to find relevant
-  // annotations while iterating input lines in the implementation below.
-  // FileCheck diagnostics are not always reported and recorded in the order of
-  // input lines due to, for example, CHECK-DAG and CHECK-NOT.
-  //
-  // Second, for annotations for the same input line, sort in the order of the
-  // FileCheck directive's line in the check file (where there's at most one
-  // directive per line) and then by the index of the match result for that
-  // directive.  The rationale of this choice is that, for any input line, this
-  // sort establishes a total order of annotations that, with respect to match
-  // results, is consistent across multiple lines, thus making match results
-  // easier to track from one line to the next when they span multiple lines.
-  std::sort(Annotations.begin(), Annotations.end(),
-            [](const InputAnnotation &A, const InputAnnotation &B) {
-              if (A.InputLine != B.InputLine)
-                return A.InputLine < B.InputLine;
-              if (A.CheckLine != B.CheckLine)
-                return A.CheckLine < B.CheckLine;
-              // FIXME: Sometimes CHECK-LABEL reports its match twice with
-              // other diagnostics in between, and then diag index incrementing
-              // fails to work properly, and then this assert fails.  We should
-              // suppress one of those diagnostics or do a better job of
-              // computing this index.  For now, we just produce a redundant
-              // CHECK-LABEL annotation.
-              // assert(A.CheckDiagIndex != B.CheckDiagIndex &&
-              //        "expected diagnostic indices to be unique within a "
-              //        " check line");
-              return A.CheckDiagIndex < B.CheckDiagIndex;
-            });
-
-  // Compute the width of the label column.
-  const unsigned char *InputFilePtr = InputFileText.bytes_begin(),
-                      *InputFileEnd = InputFileText.bytes_end();
-  unsigned LineCount = InputFileText.count('\n');
-  if (InputFileEnd[-1] != '\n')
-    ++LineCount;
-  unsigned LineNoWidth = std::log10(LineCount) + 1;
-  // +3 below adds spaces (1) to the left of the (right-aligned) line numbers
-  // on input lines and (2) to the right of the (left-aligned) labels on
-  // annotation lines so that input lines and annotation lines are more
-  // visually distinct.  For example, the spaces on the annotation lines ensure
-  // that input line numbers and check directive line numbers never align
-  // horizontally.  Those line numbers might not even be for the same file.
-  // One space would be enough to achieve that, but more makes it even easier
-  // to see.
-  LabelWidth = std::max(LabelWidth, LineNoWidth) + 3;
-
-  // Print annotated input lines.
-  auto AnnotationItr = Annotations.begin(), AnnotationEnd = Annotations.end();
-  for (unsigned Line = 1;
-       InputFilePtr != InputFileEnd || AnnotationItr != AnnotationEnd;
-       ++Line) {
-    const unsigned char *InputFileLine = InputFilePtr;
-
-    // Print right-aligned line number.
-    WithColor(OS, raw_ostream::BLACK, true)
-        << format_decimal(Line, LabelWidth) << ": ";
-
-    // For the case where -v and colors are enabled, find the annotations for
-    // good matches for expected patterns in order to highlight everything
-    // else in the line.  There are no such annotations if -v is disabled.
-    std::vector<InputAnnotation> FoundAndExpectedMatches;
-    if (Req.Verbose && WithColor(OS).colorsEnabled()) {
-      for (auto I = AnnotationItr; I != AnnotationEnd && I->InputLine == Line;
-           ++I) {
-        if (I->FoundAndExpectedMatch)
-          FoundAndExpectedMatches.push_back(*I);
-      }
-    }
-
-    // Print numbered line with highlighting where there are no matches for
-    // expected patterns.
-    bool Newline = false;
-    {
-      WithColor COS(OS);
-      bool InMatch = false;
-      if (Req.Verbose)
-        COS.changeColor(raw_ostream::CYAN, true, true);
-      for (unsigned Col = 1; InputFilePtr != InputFileEnd && !Newline; ++Col) {
-        bool WasInMatch = InMatch;
-        InMatch = false;
-        for (auto M : FoundAndExpectedMatches) {
-          if (M.InputStartCol <= Col && Col < M.InputEndCol) {
-            InMatch = true;
-            break;
-          }
-        }
-        if (!WasInMatch && InMatch)
-          COS.resetColor();
-        else if (WasInMatch && !InMatch)
-          COS.changeColor(raw_ostream::CYAN, true, true);
-        if (*InputFilePtr == '\n')
-          Newline = true;
-        else
-          COS << *InputFilePtr;
-        ++InputFilePtr;
-      }
-    }
-    OS << '\n';
-    unsigned InputLineWidth = InputFilePtr - InputFileLine - Newline;
-
-    // Print any annotations.
-    while (AnnotationItr != AnnotationEnd &&
-           AnnotationItr->InputLine == Line) {
-      WithColor COS(OS, AnnotationItr->Marker.Color, true);
-      // The two spaces below are where the ": " appears on input lines.
-      COS << left_justify(AnnotationItr->Label, LabelWidth) << "  ";
-      unsigned Col;
-      for (Col = 1; Col < AnnotationItr->InputStartCol; ++Col)
-        COS << ' ';
-      COS << AnnotationItr->Marker.Lead;
-      // If InputEndCol=UINT_MAX, stop at InputLineWidth.
-      for (++Col; Col < AnnotationItr->InputEndCol && Col <= InputLineWidth;
-           ++Col)
-        COS << '~';
-      const std::string &Note = AnnotationItr->Marker.Note;
-      if (!Note.empty()) {
-        // Put the note at the end of the input line.  If we were to instead
-        // put the note right after the marker, subsequent annotations for the
-        // same input line might appear to mark this note instead of the input
-        // line.
-        for (; Col <= InputLineWidth; ++Col)
-          COS << ' ';
-        COS << ' ' << Note;
-      }
-      COS << '\n';
-      ++AnnotationItr;
-    }
-  }
-
-  OS << ">>>>>>\n";
-}
-
-int main(int argc, char **argv) {
-  // Enable use of ANSI color codes because FileCheck is using them to
-  // highlight text.
-  llvm::sys::Process::UseANSIEscapeCodes(true);
-
-  InitLLVM X(argc, argv);
-  cl::ParseCommandLineOptions(argc, argv, /*Overview*/ "", /*Errs*/ nullptr,
-                              "FILECHECK_OPTS");
-  if (DumpInput == DumpInputHelp) {
-    DumpInputAnnotationHelp(outs());
-    return 0;
-  }
-  if (CheckFilename.empty()) {
-    errs() << "<check-file> not specified\n";
-    return 2;
-  }
-
-  FileCheckRequest Req;
-  for (auto Prefix : CheckPrefixes)
-    Req.CheckPrefixes.push_back(Prefix);
-
-  for (auto CheckNot : ImplicitCheckNot)
-    Req.ImplicitCheckNot.push_back(CheckNot);
-
-  bool GlobalDefineError = false;
-  for (auto G : GlobalDefines) {
-    size_t EqIdx = G.find('=');
-    if (EqIdx == std::string::npos) {
-      errs() << "Missing equal sign in command-line definition '-D" << G
-             << "'\n";
-      GlobalDefineError = true;
-      continue;
-    }
-    if (EqIdx == 0) {
-      errs() << "Missing variable name in command-line definition '-D" << G
-             << "'\n";
-      GlobalDefineError = true;
-      continue;
-    }
-    Req.GlobalDefines.push_back(G);
-  }
-  if (GlobalDefineError)
-    return 2;
-
-  Req.AllowEmptyInput = AllowEmptyInput;
-  Req.EnableVarScope = EnableVarScope;
-  Req.AllowDeprecatedDagOverlap = AllowDeprecatedDagOverlap;
-  Req.Verbose = Verbose;
-  Req.VerboseVerbose = VerboseVerbose;
-  Req.NoCanonicalizeWhiteSpace = NoCanonicalizeWhiteSpace;
-  Req.MatchFullLines = MatchFullLines;
-
-  if (VerboseVerbose)
-    Req.Verbose = true;
-
-  FileCheck FC(Req);
-  if (!FC.ValidateCheckPrefixes()) {
-    errs() << "Supplied check-prefix is invalid! Prefixes must be unique and "
-              "start with a letter and contain only alphanumeric characters, "
-              "hyphens and underscores\n";
-    return 2;
-  }
-
-  Regex PrefixRE = FC.buildCheckPrefixRegex();
-  std::string REError;
-  if (!PrefixRE.isValid(REError)) {
-    errs() << "Unable to combine check-prefix strings into a prefix regular "
-              "expression! This is likely a bug in FileCheck's verification of "
-              "the check-prefix strings. Regular expression parsing failed "
-              "with the following error: "
-           << REError << "\n";
-    return 2;
-  }
-
-  SourceMgr SM;
-
-  // Read the expected strings from the check file.
-  ErrorOr<std::unique_ptr<MemoryBuffer>> CheckFileOrErr =
-      MemoryBuffer::getFileOrSTDIN(CheckFilename);
-  if (std::error_code EC = CheckFileOrErr.getError()) {
-    errs() << "Could not open check file '" << CheckFilename
-           << "': " << EC.message() << '\n';
-    return 2;
-  }
-  MemoryBuffer &CheckFile = *CheckFileOrErr.get();
-
-  SmallString<4096> CheckFileBuffer;
-  StringRef CheckFileText = FC.CanonicalizeFile(CheckFile, CheckFileBuffer);
-
-  SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(
-                            CheckFileText, CheckFile.getBufferIdentifier()),
-                        SMLoc());
-
-  if (FC.readCheckFile(SM, CheckFileText, PrefixRE))
-    return 2;
-
-  // Open the file to check and add it to SourceMgr.
-  ErrorOr<std::unique_ptr<MemoryBuffer>> InputFileOrErr =
-      MemoryBuffer::getFileOrSTDIN(InputFilename);
-  if (std::error_code EC = InputFileOrErr.getError()) {
-    errs() << "Could not open input file '" << InputFilename
-           << "': " << EC.message() << '\n';
-    return 2;
-  }
-  MemoryBuffer &InputFile = *InputFileOrErr.get();
-
-  if (InputFile.getBufferSize() == 0 && !AllowEmptyInput) {
-    errs() << "FileCheck error: '" << InputFilename << "' is empty.\n";
-    DumpCommandLine(argc, argv);
-    return 2;
-  }
-
-  SmallString<4096> InputFileBuffer;
-  StringRef InputFileText = FC.CanonicalizeFile(InputFile, InputFileBuffer);
-
-  SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(
-                            InputFileText, InputFile.getBufferIdentifier()),
-                        SMLoc());
-
-  if (DumpInput == DumpInputDefault)
-    DumpInput = DumpInputOnFailure ? DumpInputFail : DumpInputNever;
-
-  std::vector<FileCheckDiag> Diags;
-  int ExitCode = FC.checkInput(SM, InputFileText,
-                               DumpInput == DumpInputNever ? nullptr : &Diags)
-                     ? EXIT_SUCCESS
-                     : 1;
-  if (DumpInput == DumpInputAlways ||
-      (ExitCode == 1 && DumpInput == DumpInputFail)) {
-    errs() << "\n"
-           << "Input file: "
-           << (InputFilename == "-" ? "<stdin>" : InputFilename.getValue())
-           << "\n"
-           << "Check file: " << CheckFilename << "\n"
-           << "\n"
-           << "-dump-input=help describes the format of the following dump.\n"
-           << "\n";
-    std::vector<InputAnnotation> Annotations;
-    unsigned LabelWidth;
-    BuildInputAnnotations(Diags, Annotations, LabelWidth);
-    DumpAnnotatedInput(errs(), Req, InputFileText, Annotations, LabelWidth);
-  }
-
-  return ExitCode;
-}
+//===- FileCheck.cpp - Check that File's Contents match what is expected --===//\r
+//\r
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.\r
+// See https://llvm.org/LICENSE.txt for license information.\r
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\r
+//\r
+//===----------------------------------------------------------------------===//\r
+//\r
+// FileCheck does a line-by line check of a file that validates whether it\r
+// contains the expected content.  This is useful for regression tests etc.\r
+//\r
+// This program exits with an exit status of 2 on error, exit status of 0 if\r
+// the file matched the expected contents, and exit status of 1 if it did not\r
+// contain the expected contents.\r
+//\r
+//===----------------------------------------------------------------------===//\r
+\r
+#include "llvm/Support/CommandLine.h"\r
+#include "llvm/Support/InitLLVM.h"\r
+#include "llvm/Support/Process.h"\r
+#include "llvm/Support/WithColor.h"\r
+#include "llvm/Support/raw_ostream.h"\r
+#include "llvm/Support/FileCheck.h"\r
+#include <cmath>\r
+using namespace llvm;\r
+\r
+static cl::extrahelp FileCheckOptsEnv(\r
+    "\nOptions are parsed from the environment variable FILECHECK_OPTS and\n"\r
+    "from the command line.\n");\r
+\r
+static cl::opt<std::string>\r
+    CheckFilename(cl::Positional, cl::desc("<check-file>"), cl::Optional);\r
+\r
+static cl::opt<std::string>\r
+    InputFilename("input-file", cl::desc("File to check (defaults to stdin)"),\r
+                  cl::init("-"), cl::value_desc("filename"));\r
+\r
+static cl::list<std::string> CheckPrefixes(\r
+    "check-prefix",\r
+    cl::desc("Prefix to use from check file (defaults to 'CHECK')"));\r
+static cl::alias CheckPrefixesAlias(\r
+    "check-prefixes", cl::aliasopt(CheckPrefixes), cl::CommaSeparated,\r
+    cl::NotHidden,\r
+    cl::desc(\r
+        "Alias for -check-prefix permitting multiple comma separated values"));\r
+\r
+static cl::opt<bool> NoCanonicalizeWhiteSpace(\r
+    "strict-whitespace",\r
+    cl::desc("Do not treat all horizontal whitespace as equivalent"));\r
+\r
+static cl::opt<bool> IgnoreCase(\r
+    "ignore-case",\r
+    cl::desc("Use case-insensitive matching"));\r
+\r
+static cl::list<std::string> ImplicitCheckNot(\r
+    "implicit-check-not",\r
+    cl::desc("Add an implicit negative check with this pattern to every\n"\r
+             "positive check. This can be used to ensure that no instances of\n"\r
+             "this pattern occur which are not matched by a positive pattern"),\r
+    cl::value_desc("pattern"));\r
+\r
+static cl::list<std::string>\r
+    GlobalDefines("D", cl::AlwaysPrefix,\r
+                  cl::desc("Define a variable to be used in capture patterns."),\r
+                  cl::value_desc("VAR=VALUE"));\r
+\r
+static cl::opt<bool> AllowEmptyInput(\r
+    "allow-empty", cl::init(false),\r
+    cl::desc("Allow the input file to be empty. This is useful when making\n"\r
+             "checks that some error message does not occur, for example."));\r
+\r
+static cl::opt<bool> MatchFullLines(\r
+    "match-full-lines", cl::init(false),\r
+    cl::desc("Require all positive matches to cover an entire input line.\n"\r
+             "Allows leading and trailing whitespace if --strict-whitespace\n"\r
+             "is not also passed."));\r
+\r
+static cl::opt<bool> EnableVarScope(\r
+    "enable-var-scope", cl::init(false),\r
+    cl::desc("Enables scope for regex variables. Variables with names that\n"\r
+             "do not start with '$' will be reset at the beginning of\n"\r
+             "each CHECK-LABEL block."));\r
+\r
+static cl::opt<bool> AllowDeprecatedDagOverlap(\r
+    "allow-deprecated-dag-overlap", cl::init(false),\r
+    cl::desc("Enable overlapping among matches in a group of consecutive\n"\r
+             "CHECK-DAG directives.  This option is deprecated and is only\n"\r
+             "provided for convenience as old tests are migrated to the new\n"\r
+             "non-overlapping CHECK-DAG implementation.\n"));\r
+\r
+static cl::opt<bool> Verbose(\r
+    "v", cl::init(false),\r
+    cl::desc("Print directive pattern matches, or add them to the input dump\n"\r
+             "if enabled.\n"));\r
+\r
+static cl::opt<bool> VerboseVerbose(\r
+    "vv", cl::init(false),\r
+    cl::desc("Print information helpful in diagnosing internal FileCheck\n"\r
+             "issues, or add it to the input dump if enabled.  Implies\n"\r
+             "-v.\n"));\r
+static const char * DumpInputEnv = "FILECHECK_DUMP_INPUT_ON_FAILURE";\r
+\r
+static cl::opt<bool> DumpInputOnFailure(\r
+    "dump-input-on-failure",\r
+    cl::init(std::getenv(DumpInputEnv) && *std::getenv(DumpInputEnv)),\r
+    cl::desc("Dump original input to stderr before failing.\n"\r
+             "The value can be also controlled using\n"\r
+             "FILECHECK_DUMP_INPUT_ON_FAILURE environment variable.\n"\r
+             "This option is deprecated in favor of -dump-input=fail.\n"));\r
+\r
+enum DumpInputValue {\r
+  DumpInputDefault,\r
+  DumpInputHelp,\r
+  DumpInputNever,\r
+  DumpInputFail,\r
+  DumpInputAlways\r
+};\r
+\r
+static cl::opt<DumpInputValue> DumpInput(\r
+    "dump-input", cl::init(DumpInputDefault),\r
+    cl::desc("Dump input to stderr, adding annotations representing\n"\r
+             " currently enabled diagnostics\n"),\r
+    cl::value_desc("mode"),\r
+    cl::values(clEnumValN(DumpInputHelp, "help",\r
+                          "Explain dump format and quit"),\r
+               clEnumValN(DumpInputNever, "never", "Never dump input"),\r
+               clEnumValN(DumpInputFail, "fail", "Dump input on failure"),\r
+               clEnumValN(DumpInputAlways, "always", "Always dump input")));\r
+\r
+typedef cl::list<std::string>::const_iterator prefix_iterator;\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+static void DumpCommandLine(int argc, char **argv) {\r
+  errs() << "FileCheck command line: ";\r
+  for (int I = 0; I < argc; I++)\r
+    errs() << " " << argv[I];\r
+  errs() << "\n";\r
+}\r
+\r
+struct MarkerStyle {\r
+  /// The starting char (before tildes) for marking the line.\r
+  char Lead;\r
+  /// What color to use for this annotation.\r
+  raw_ostream::Colors Color;\r
+  /// A note to follow the marker, or empty string if none.\r
+  std::string Note;\r
+  MarkerStyle() {}\r
+  MarkerStyle(char Lead, raw_ostream::Colors Color,\r
+              const std::string &Note = "")\r
+      : Lead(Lead), Color(Color), Note(Note) {}\r
+};\r
+\r
+static MarkerStyle GetMarker(FileCheckDiag::MatchType MatchTy) {\r
+  switch (MatchTy) {\r
+  case FileCheckDiag::MatchFoundAndExpected:\r
+    return MarkerStyle('^', raw_ostream::GREEN);\r
+  case FileCheckDiag::MatchFoundButExcluded:\r
+    return MarkerStyle('!', raw_ostream::RED, "error: no match expected");\r
+  case FileCheckDiag::MatchFoundButWrongLine:\r
+    return MarkerStyle('!', raw_ostream::RED, "error: match on wrong line");\r
+  case FileCheckDiag::MatchFoundButDiscarded:\r
+    return MarkerStyle('!', raw_ostream::CYAN,\r
+                       "discard: overlaps earlier match");\r
+  case FileCheckDiag::MatchNoneAndExcluded:\r
+    return MarkerStyle('X', raw_ostream::GREEN);\r
+  case FileCheckDiag::MatchNoneButExpected:\r
+    return MarkerStyle('X', raw_ostream::RED, "error: no match found");\r
+  case FileCheckDiag::MatchFuzzy:\r
+    return MarkerStyle('?', raw_ostream::MAGENTA, "possible intended match");\r
+  }\r
+  llvm_unreachable_internal("unexpected match type");\r
+}\r
+\r
+static void DumpInputAnnotationHelp(raw_ostream &OS) {\r
+  OS << "The following description was requested by -dump-input=help to\n"\r
+     << "explain the input annotations printed by -dump-input=always and\n"\r
+     << "-dump-input=fail:\n\n";\r
+\r
+  // Labels for input lines.\r
+  OS << "  - ";\r
+  WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "L:";\r
+  OS << "     labels line number L of the input file\n";\r
+\r
+  // Labels for annotation lines.\r
+  OS << "  - ";\r
+  WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "T:L";\r
+  OS << "    labels the only match result for a pattern of type T from "\r
+     << "line L of\n"\r
+     << "           the check file\n";\r
+  OS << "  - ";\r
+  WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "T:L'N";\r
+  OS << "  labels the Nth match result for a pattern of type T from line "\r
+     << "L of\n"\r
+     << "           the check file\n";\r
+\r
+  // Markers on annotation lines.\r
+  OS << "  - ";\r
+  WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "^~~";\r
+  OS << "    marks good match (reported if -v)\n"\r
+     << "  - ";\r
+  WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "!~~";\r
+  OS << "    marks bad match, such as:\n"\r
+     << "           - CHECK-NEXT on same line as previous match (error)\n"\r
+     << "           - CHECK-NOT found (error)\n"\r
+     << "           - CHECK-DAG overlapping match (discarded, reported if "\r
+     << "-vv)\n"\r
+     << "  - ";\r
+  WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "X~~";\r
+  OS << "    marks search range when no match is found, such as:\n"\r
+     << "           - CHECK-NEXT not found (error)\n"\r
+     << "           - CHECK-NOT not found (success, reported if -vv)\n"\r
+     << "           - CHECK-DAG not found after discarded matches (error)\n"\r
+     << "  - ";\r
+  WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "?";\r
+  OS << "      marks fuzzy match when no match is found\n";\r
+\r
+  // Colors.\r
+  OS << "  - colors ";\r
+  WithColor(OS, raw_ostream::GREEN, true) << "success";\r
+  OS << ", ";\r
+  WithColor(OS, raw_ostream::RED, true) << "error";\r
+  OS << ", ";\r
+  WithColor(OS, raw_ostream::MAGENTA, true) << "fuzzy match";\r
+  OS << ", ";\r
+  WithColor(OS, raw_ostream::CYAN, true, false) << "discarded match";\r
+  OS << ", ";\r
+  WithColor(OS, raw_ostream::CYAN, true, true) << "unmatched input";\r
+  OS << "\n\n"\r
+     << "If you are not seeing color above or in input dumps, try: -color\n";\r
+}\r
+\r
+/// An annotation for a single input line.\r
+struct InputAnnotation {\r
+  /// The check file line (one-origin indexing) where the directive that\r
+  /// produced this annotation is located.\r
+  unsigned CheckLine;\r
+  /// The index of the match result for this check.\r
+  unsigned CheckDiagIndex;\r
+  /// The label for this annotation.\r
+  std::string Label;\r
+  /// What input line (one-origin indexing) this annotation marks.  This might\r
+  /// be different from the starting line of the original diagnostic if this is\r
+  /// a non-initial fragment of a diagnostic that has been broken across\r
+  /// multiple lines.\r
+  unsigned InputLine;\r
+  /// The column range (one-origin indexing, open end) in which to to mark the\r
+  /// input line.  If InputEndCol is UINT_MAX, treat it as the last column\r
+  /// before the newline.\r
+  unsigned InputStartCol, InputEndCol;\r
+  /// The marker to use.\r
+  MarkerStyle Marker;\r
+  /// Whether this annotation represents a good match for an expected pattern.\r
+  bool FoundAndExpectedMatch;\r
+};\r
+\r
+/// Get an abbreviation for the check type.\r
+std::string GetCheckTypeAbbreviation(Check::FileCheckType Ty) {\r
+  switch (Ty) {\r
+  case Check::CheckPlain:\r
+    if (Ty.getCount() > 1)\r
+      return "count";\r
+    return "check";\r
+  case Check::CheckNext:\r
+    return "next";\r
+  case Check::CheckSame:\r
+    return "same";\r
+  case Check::CheckNot:\r
+    return "not";\r
+  case Check::CheckDAG:\r
+    return "dag";\r
+  case Check::CheckLabel:\r
+    return "label";\r
+  case Check::CheckEmpty:\r
+    return "empty";\r
+  case Check::CheckEOF:\r
+    return "eof";\r
+  case Check::CheckBadNot:\r
+    return "bad-not";\r
+  case Check::CheckBadCount:\r
+    return "bad-count";\r
+  case Check::CheckNone:\r
+    llvm_unreachable("invalid FileCheckType");\r
+  }\r
+  llvm_unreachable("unknown FileCheckType");\r
+}\r
+\r
+static void BuildInputAnnotations(const std::vector<FileCheckDiag> &Diags,\r
+                                  std::vector<InputAnnotation> &Annotations,\r
+                                  unsigned &LabelWidth) {\r
+  // How many diagnostics has the current check seen so far?\r
+  unsigned CheckDiagCount = 0;\r
+  // What's the widest label?\r
+  LabelWidth = 0;\r
+  for (auto DiagItr = Diags.begin(), DiagEnd = Diags.end(); DiagItr != DiagEnd;\r
+       ++DiagItr) {\r
+    InputAnnotation A;\r
+\r
+    // Build label, which uniquely identifies this check result.\r
+    A.CheckLine = DiagItr->CheckLine;\r
+    llvm::raw_string_ostream Label(A.Label);\r
+    Label << GetCheckTypeAbbreviation(DiagItr->CheckTy) << ":"\r
+          << DiagItr->CheckLine;\r
+    A.CheckDiagIndex = UINT_MAX;\r
+    auto DiagNext = std::next(DiagItr);\r
+    if (DiagNext != DiagEnd && DiagItr->CheckTy == DiagNext->CheckTy &&\r
+        DiagItr->CheckLine == DiagNext->CheckLine)\r
+      A.CheckDiagIndex = CheckDiagCount++;\r
+    else if (CheckDiagCount) {\r
+      A.CheckDiagIndex = CheckDiagCount;\r
+      CheckDiagCount = 0;\r
+    }\r
+    if (A.CheckDiagIndex != UINT_MAX)\r
+      Label << "'" << A.CheckDiagIndex;\r
+    else\r
+      A.CheckDiagIndex = 0;\r
+    Label.flush();\r
+    LabelWidth = std::max((std::string::size_type)LabelWidth, A.Label.size());\r
+\r
+    A.Marker = GetMarker(DiagItr->MatchTy);\r
+    A.FoundAndExpectedMatch =\r
+        DiagItr->MatchTy == FileCheckDiag::MatchFoundAndExpected;\r
+\r
+    // Compute the mark location, and break annotation into multiple\r
+    // annotations if it spans multiple lines.\r
+    A.InputLine = DiagItr->InputStartLine;\r
+    A.InputStartCol = DiagItr->InputStartCol;\r
+    if (DiagItr->InputStartLine == DiagItr->InputEndLine) {\r
+      // Sometimes ranges are empty in order to indicate a specific point, but\r
+      // that would mean nothing would be marked, so adjust the range to\r
+      // include the following character.\r
+      A.InputEndCol =\r
+          std::max(DiagItr->InputStartCol + 1, DiagItr->InputEndCol);\r
+      Annotations.push_back(A);\r
+    } else {\r
+      assert(DiagItr->InputStartLine < DiagItr->InputEndLine &&\r
+             "expected input range not to be inverted");\r
+      A.InputEndCol = UINT_MAX;\r
+      Annotations.push_back(A);\r
+      for (unsigned L = DiagItr->InputStartLine + 1, E = DiagItr->InputEndLine;\r
+           L <= E; ++L) {\r
+        // If a range ends before the first column on a line, then it has no\r
+        // characters on that line, so there's nothing to render.\r
+        if (DiagItr->InputEndCol == 1 && L == E)\r
+          break;\r
+        InputAnnotation B;\r
+        B.CheckLine = A.CheckLine;\r
+        B.CheckDiagIndex = A.CheckDiagIndex;\r
+        B.Label = A.Label;\r
+        B.InputLine = L;\r
+        B.Marker = A.Marker;\r
+        B.Marker.Lead = '~';\r
+        B.Marker.Note = "";\r
+        B.InputStartCol = 1;\r
+        if (L != E)\r
+          B.InputEndCol = UINT_MAX;\r
+        else\r
+          B.InputEndCol = DiagItr->InputEndCol;\r
+        B.FoundAndExpectedMatch = A.FoundAndExpectedMatch;\r
+        Annotations.push_back(B);\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+static void DumpAnnotatedInput(raw_ostream &OS, const FileCheckRequest &Req,\r
+                               StringRef InputFileText,\r
+                               std::vector<InputAnnotation> &Annotations,\r
+                               unsigned LabelWidth) {\r
+  OS << "Full input was:\n<<<<<<\n";\r
+\r
+  // Sort annotations.\r
+  //\r
+  // First, sort in the order of input lines to make it easier to find relevant\r
+  // annotations while iterating input lines in the implementation below.\r
+  // FileCheck diagnostics are not always reported and recorded in the order of\r
+  // input lines due to, for example, CHECK-DAG and CHECK-NOT.\r
+  //\r
+  // Second, for annotations for the same input line, sort in the order of the\r
+  // FileCheck directive's line in the check file (where there's at most one\r
+  // directive per line) and then by the index of the match result for that\r
+  // directive.  The rationale of this choice is that, for any input line, this\r
+  // sort establishes a total order of annotations that, with respect to match\r
+  // results, is consistent across multiple lines, thus making match results\r
+  // easier to track from one line to the next when they span multiple lines.\r
+  std::sort(Annotations.begin(), Annotations.end(),\r
+            [](const InputAnnotation &A, const InputAnnotation &B) {\r
+              if (A.InputLine != B.InputLine)\r
+                return A.InputLine < B.InputLine;\r
+              if (A.CheckLine != B.CheckLine)\r
+                return A.CheckLine < B.CheckLine;\r
+              // FIXME: Sometimes CHECK-LABEL reports its match twice with\r
+              // other diagnostics in between, and then diag index incrementing\r
+              // fails to work properly, and then this assert fails.  We should\r
+              // suppress one of those diagnostics or do a better job of\r
+              // computing this index.  For now, we just produce a redundant\r
+              // CHECK-LABEL annotation.\r
+              // assert(A.CheckDiagIndex != B.CheckDiagIndex &&\r
+              //        "expected diagnostic indices to be unique within a "\r
+              //        " check line");\r
+              return A.CheckDiagIndex < B.CheckDiagIndex;\r
+            });\r
+\r
+  // Compute the width of the label column.\r
+  const unsigned char *InputFilePtr = InputFileText.bytes_begin(),\r
+                      *InputFileEnd = InputFileText.bytes_end();\r
+  unsigned LineCount = InputFileText.count('\n');\r
+  if (InputFileEnd[-1] != '\n')\r
+    ++LineCount;\r
+  unsigned LineNoWidth = std::log10(LineCount) + 1;\r
+  // +3 below adds spaces (1) to the left of the (right-aligned) line numbers\r
+  // on input lines and (2) to the right of the (left-aligned) labels on\r
+  // annotation lines so that input lines and annotation lines are more\r
+  // visually distinct.  For example, the spaces on the annotation lines ensure\r
+  // that input line numbers and check directive line numbers never align\r
+  // horizontally.  Those line numbers might not even be for the same file.\r
+  // One space would be enough to achieve that, but more makes it even easier\r
+  // to see.\r
+  LabelWidth = std::max(LabelWidth, LineNoWidth) + 3;\r
+\r
+  // Print annotated input lines.\r
+  auto AnnotationItr = Annotations.begin(), AnnotationEnd = Annotations.end();\r
+  for (unsigned Line = 1;\r
+       InputFilePtr != InputFileEnd || AnnotationItr != AnnotationEnd;\r
+       ++Line) {\r
+    const unsigned char *InputFileLine = InputFilePtr;\r
+\r
+    // Print right-aligned line number.\r
+    WithColor(OS, raw_ostream::BLACK, true)\r
+        << format_decimal(Line, LabelWidth) << ": ";\r
+\r
+    // For the case where -v and colors are enabled, find the annotations for\r
+    // good matches for expected patterns in order to highlight everything\r
+    // else in the line.  There are no such annotations if -v is disabled.\r
+    std::vector<InputAnnotation> FoundAndExpectedMatches;\r
+    if (Req.Verbose && WithColor(OS).colorsEnabled()) {\r
+      for (auto I = AnnotationItr; I != AnnotationEnd && I->InputLine == Line;\r
+           ++I) {\r
+        if (I->FoundAndExpectedMatch)\r
+          FoundAndExpectedMatches.push_back(*I);\r
+      }\r
+    }\r
+\r
+    // Print numbered line with highlighting where there are no matches for\r
+    // expected patterns.\r
+    bool Newline = false;\r
+    {\r
+      WithColor COS(OS);\r
+      bool InMatch = false;\r
+      if (Req.Verbose)\r
+        COS.changeColor(raw_ostream::CYAN, true, true);\r
+      for (unsigned Col = 1; InputFilePtr != InputFileEnd && !Newline; ++Col) {\r
+        bool WasInMatch = InMatch;\r
+        InMatch = false;\r
+        for (auto M : FoundAndExpectedMatches) {\r
+          if (M.InputStartCol <= Col && Col < M.InputEndCol) {\r
+            InMatch = true;\r
+            break;\r
+          }\r
+        }\r
+        if (!WasInMatch && InMatch)\r
+          COS.resetColor();\r
+        else if (WasInMatch && !InMatch)\r
+          COS.changeColor(raw_ostream::CYAN, true, true);\r
+        if (*InputFilePtr == '\n')\r
+          Newline = true;\r
+        else\r
+          COS << *InputFilePtr;\r
+        ++InputFilePtr;\r
+      }\r
+    }\r
+    OS << '\n';\r
+    unsigned InputLineWidth = InputFilePtr - InputFileLine - Newline;\r
+\r
+    // Print any annotations.\r
+    while (AnnotationItr != AnnotationEnd &&\r
+           AnnotationItr->InputLine == Line) {\r
+      WithColor COS(OS, AnnotationItr->Marker.Color, true);\r
+      // The two spaces below are where the ": " appears on input lines.\r
+      COS << left_justify(AnnotationItr->Label, LabelWidth) << "  ";\r
+      unsigned Col;\r
+      for (Col = 1; Col < AnnotationItr->InputStartCol; ++Col)\r
+        COS << ' ';\r
+      COS << AnnotationItr->Marker.Lead;\r
+      // If InputEndCol=UINT_MAX, stop at InputLineWidth.\r
+      for (++Col; Col < AnnotationItr->InputEndCol && Col <= InputLineWidth;\r
+           ++Col)\r
+        COS << '~';\r
+      const std::string &Note = AnnotationItr->Marker.Note;\r
+      if (!Note.empty()) {\r
+        // Put the note at the end of the input line.  If we were to instead\r
+        // put the note right after the marker, subsequent annotations for the\r
+        // same input line might appear to mark this note instead of the input\r
+        // line.\r
+        for (; Col <= InputLineWidth; ++Col)\r
+          COS << ' ';\r
+        COS << ' ' << Note;\r
+      }\r
+      COS << '\n';\r
+      ++AnnotationItr;\r
+    }\r
+  }\r
+\r
+  OS << ">>>>>>\n";\r
+}\r
+\r
+int main(int argc, char **argv) {\r
+  // Enable use of ANSI color codes because FileCheck is using them to\r
+  // highlight text.\r
+  llvm::sys::Process::UseANSIEscapeCodes(true);\r
+\r
+  InitLLVM X(argc, argv);\r
+  cl::ParseCommandLineOptions(argc, argv, /*Overview*/ "", /*Errs*/ nullptr,\r
+                              "FILECHECK_OPTS");\r
+  if (DumpInput == DumpInputHelp) {\r
+    DumpInputAnnotationHelp(outs());\r
+    return 0;\r
+  }\r
+  if (CheckFilename.empty()) {\r
+    errs() << "<check-file> not specified\n";\r
+    return 2;\r
+  }\r
+\r
+  FileCheckRequest Req;\r
+  for (auto Prefix : CheckPrefixes)\r
+    Req.CheckPrefixes.push_back(Prefix);\r
+\r
+  for (auto CheckNot : ImplicitCheckNot)\r
+    Req.ImplicitCheckNot.push_back(CheckNot);\r
+\r
+  bool GlobalDefineError = false;\r
+  for (auto G : GlobalDefines) {\r
+    size_t EqIdx = G.find('=');\r
+    if (EqIdx == std::string::npos) {\r
+      errs() << "Missing equal sign in command-line definition '-D" << G\r
+             << "'\n";\r
+      GlobalDefineError = true;\r
+      continue;\r
+    }\r
+    if (EqIdx == 0) {\r
+      errs() << "Missing variable name in command-line definition '-D" << G\r
+             << "'\n";\r
+      GlobalDefineError = true;\r
+      continue;\r
+    }\r
+    Req.GlobalDefines.push_back(G);\r
+  }\r
+  if (GlobalDefineError)\r
+    return 2;\r
+\r
+  Req.AllowEmptyInput = AllowEmptyInput;\r
+  Req.EnableVarScope = EnableVarScope;\r
+  Req.AllowDeprecatedDagOverlap = AllowDeprecatedDagOverlap;\r
+  Req.Verbose = Verbose;\r
+  Req.VerboseVerbose = VerboseVerbose;\r
+  Req.NoCanonicalizeWhiteSpace = NoCanonicalizeWhiteSpace;\r
+  Req.MatchFullLines = MatchFullLines;\r
+  Req.IgnoreCase = IgnoreCase;\r
+\r
+  if (VerboseVerbose)\r
+    Req.Verbose = true;\r
+\r
+  FileCheck FC(Req);\r
+  if (!FC.ValidateCheckPrefixes()) {\r
+    errs() << "Supplied check-prefix is invalid! Prefixes must be unique and "\r
+              "start with a letter and contain only alphanumeric characters, "\r
+              "hyphens and underscores\n";\r
+    return 2;\r
+  }\r
+\r
+  Regex PrefixRE = FC.buildCheckPrefixRegex();\r
+  std::string REError;\r
+  if (!PrefixRE.isValid(REError)) {\r
+    errs() << "Unable to combine check-prefix strings into a prefix regular "\r
+              "expression! This is likely a bug in FileCheck's verification of "\r
+              "the check-prefix strings. Regular expression parsing failed "\r
+              "with the following error: "\r
+           << REError << "\n";\r
+    return 2;\r
+  }\r
+\r
+  SourceMgr SM;\r
+\r
+  // Read the expected strings from the check file.\r
+  ErrorOr<std::unique_ptr<MemoryBuffer>> CheckFileOrErr =\r
+      MemoryBuffer::getFileOrSTDIN(CheckFilename);\r
+  if (std::error_code EC = CheckFileOrErr.getError()) {\r
+    errs() << "Could not open check file '" << CheckFilename\r
+           << "': " << EC.message() << '\n';\r
+    return 2;\r
+  }\r
+  MemoryBuffer &CheckFile = *CheckFileOrErr.get();\r
+\r
+  SmallString<4096> CheckFileBuffer;\r
+  StringRef CheckFileText = FC.CanonicalizeFile(CheckFile, CheckFileBuffer);\r
+\r
+  SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(\r
+                            CheckFileText, CheckFile.getBufferIdentifier()),\r
+                        SMLoc());\r
+\r
+  if (FC.readCheckFile(SM, CheckFileText, PrefixRE))\r
+    return 2;\r
+\r
+  // Open the file to check and add it to SourceMgr.\r
+  ErrorOr<std::unique_ptr<MemoryBuffer>> InputFileOrErr =\r
+      MemoryBuffer::getFileOrSTDIN(InputFilename);\r
+  if (std::error_code EC = InputFileOrErr.getError()) {\r
+    errs() << "Could not open input file '" << InputFilename\r
+           << "': " << EC.message() << '\n';\r
+    return 2;\r
+  }\r
+  MemoryBuffer &InputFile = *InputFileOrErr.get();\r
+\r
+  if (InputFile.getBufferSize() == 0 && !AllowEmptyInput) {\r
+    errs() << "FileCheck error: '" << InputFilename << "' is empty.\n";\r
+    DumpCommandLine(argc, argv);\r
+    return 2;\r
+  }\r
+\r
+  SmallString<4096> InputFileBuffer;\r
+  StringRef InputFileText = FC.CanonicalizeFile(InputFile, InputFileBuffer);\r
+\r
+  SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(\r
+                            InputFileText, InputFile.getBufferIdentifier()),\r
+                        SMLoc());\r
+\r
+  if (DumpInput == DumpInputDefault)\r
+    DumpInput = DumpInputOnFailure ? DumpInputFail : DumpInputNever;\r
+\r
+  std::vector<FileCheckDiag> Diags;\r
+  int ExitCode = FC.checkInput(SM, InputFileText,\r
+                               DumpInput == DumpInputNever ? nullptr : &Diags)\r
+                     ? EXIT_SUCCESS\r
+                     : 1;\r
+  if (DumpInput == DumpInputAlways ||\r
+      (ExitCode == 1 && DumpInput == DumpInputFail)) {\r
+    errs() << "\n"\r
+           << "Input file: "\r
+           << (InputFilename == "-" ? "<stdin>" : InputFilename.getValue())\r
+           << "\n"\r
+           << "Check file: " << CheckFilename << "\n"\r
+           << "\n"\r
+           << "-dump-input=help describes the format of the following dump.\n"\r
+           << "\n";\r
+    std::vector<InputAnnotation> Annotations;\r
+    unsigned LabelWidth;\r
+    BuildInputAnnotations(Diags, Annotations, LabelWidth);\r
+    DumpAnnotatedInput(errs(), Req, InputFileText, Annotations, LabelWidth);\r
+  }\r
+\r
+  return ExitCode;\r
+}\r