diff --git a/clang/test/CodeGen/attr-noundef.cpp b/clang/test/CodeGen/attr-noundef.cpp
--- a/clang/test/CodeGen/attr-noundef.cpp
+++ b/clang/test/CodeGen/attr-noundef.cpp
@@ -15,10 +15,10 @@
 };
 Trivial ret_trivial() { return {}; }
 void pass_trivial(Trivial e) {}
-// CHECK-INTEL: [[DEFINE:define( dso_local)?]] i32 @{{.*}}ret_trivial
-// CHECK-AARCH: [[DEFINE:define( dso_local)?]] i32 @{{.*}}ret_trivial
-// CHECK-INTEL: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i32 %
-// CHECK-AARCH: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i64 %
+// CHECK-INTEL: [[DEF:define( dso_local)?]] i32 @{{.*}}ret_trivial
+// CHECK-AARCH: [[DEF:define( dso_local)?]] i32 @{{.*}}ret_trivial
+// CHECK-INTEL: [[DEF]] void @{{.*}}pass_trivial{{.*}}(i32 %
+// CHECK-AARCH: [[DEF]] void @{{.*}}pass_trivial{{.*}}(i64 %
 
 struct NoCopy {
   int a;
@@ -26,16 +26,16 @@
 };
 NoCopy ret_nocopy() { return {}; }
 void pass_nocopy(NoCopy e) {}
-// CHECK: [[DEFINE]] void @{{.*}}ret_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noalias sret({{[^)]+}}) align 4 %
-// CHECK: [[DEFINE]] void @{{.*}}pass_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noundef %
+// CHECK: [[DEF]] void @{{.*}}ret_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noalias sret({{[^)]+}}) align 4 %
+// CHECK: [[DEF]] void @{{.*}}pass_nocopy{{.*}}(%"struct.check_structs::NoCopy"* noundef %
 
 struct Huge {
   int a[1024];
 };
 Huge ret_huge() { return {}; }
 void pass_huge(Huge h) {}
-// CHECK: [[DEFINE]] void @{{.*}}ret_huge{{.*}}(%"struct.check_structs::Huge"* noalias sret({{[^)]+}}) align 4 %
-// CHECK: [[DEFINE]] void @{{.*}}pass_huge{{.*}}(%"struct.check_structs::Huge"* noundef
+// CHECK: [[DEF]] void @{{.*}}ret_huge{{.*}}(%"struct.check_structs::Huge"* noalias sret({{[^)]+}}) align 4 %
+// CHECK: [[DEF]] void @{{.*}}pass_huge{{.*}}(%"struct.check_structs::Huge"* noundef
 } // namespace check_structs
 
 //************ Passing unions by value
@@ -47,10 +47,10 @@
 };
 Trivial ret_trivial() { return {}; }
 void pass_trivial(Trivial e) {}
-// CHECK-INTEL: [[DEFINE]] i32 @{{.*}}ret_trivial
-// CHECK-AARCH: [[DEFINE]] i32 @{{.*}}ret_trivial
-// CHECK-INTEL: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i32 %
-// CHECK-AARCH: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i64 %
+// CHECK-INTEL: [[DEF]] i32 @{{.*}}ret_trivial
+// CHECK-AARCH: [[DEF]] i32 @{{.*}}ret_trivial
+// CHECK-INTEL: [[DEF]] void @{{.*}}pass_trivial{{.*}}(i32 %
+// CHECK-AARCH: [[DEF]] void @{{.*}}pass_trivial{{.*}}(i64 %
 
 union NoCopy {
   int a;
@@ -58,8 +58,8 @@
 };
 NoCopy ret_nocopy() { return {}; }
 void pass_nocopy(NoCopy e) {}
-// CHECK: [[DEFINE]] void @{{.*}}ret_nocopy{{.*}}(%"union.check_unions::NoCopy"* noalias sret({{[^)]+}}) align 4 %
-// CHECK: [[DEFINE]] void @{{.*}}pass_nocopy{{.*}}(%"union.check_unions::NoCopy"* noundef %
+// CHECK: [[DEF]] void @{{.*}}ret_nocopy{{.*}}(%"union.check_unions::NoCopy"* noalias sret({{[^)]+}}) align 4 %
+// CHECK: [[DEF]] void @{{.*}}pass_nocopy{{.*}}(%"union.check_unions::NoCopy"* noundef %
 } // namespace check_unions
 
 //************ Passing `this` pointers
@@ -100,9 +100,9 @@
 void pass_vec(i32x3 v) {
 }
 
-// CHECK: [[DEFINE]] noundef <3 x i32> @{{.*}}ret_vec{{.*}}()
-// CHECK-INTEL: [[DEFINE]] void @{{.*}}pass_vec{{.*}}(<3 x i32> noundef %
-// CHECK-AARCH: [[DEFINE]] void @{{.*}}pass_vec{{.*}}(<4 x i32> %
+// CHECK: [[DEF]] noundef <3 x i32> @{{.*}}ret_vec{{.*}}()
+// CHECK-INTEL: [[DEF]] void @{{.*}}pass_vec{{.*}}(<3 x i32> noundef %
+// CHECK-AARCH: [[DEF]] void @{{.*}}pass_vec{{.*}}(<4 x i32> %
 } // namespace check_vecs
 
 //************ Passing exotic types
@@ -145,23 +145,23 @@
 }
 
 // Pointers to arrays/functions are always noundef
-// CHECK: [[DEFINE]] noundef [32 x i32]* @{{.*}}ret_arrptr{{.*}}()
-// CHECK: [[DEFINE]] noundef i32 (i32)* @{{.*}}ret_fnptr{{.*}}()
+// CHECK: [[DEF]] noundef [32 x i32]* @{{.*}}ret_arrptr{{.*}}()
+// CHECK: [[DEF]] noundef i32 (i32)* @{{.*}}ret_fnptr{{.*}}()
 
 // Pointers to members are never noundef
-// CHECK: [[DEFINE]] i64 @{{.*}}ret_mdptr{{.*}}()
-// CHECK-INTEL: [[DEFINE]] { i64, i64 } @{{.*}}ret_mfptr{{.*}}()
-// CHECK-AARCH: [[DEFINE]] [2 x i64] @{{.*}}ret_mfptr{{.*}}()
+// CHECK: [[DEF]] i64 @{{.*}}ret_mdptr{{.*}}()
+// CHECK-INTEL: [[DEF]] { i64, i64 } @{{.*}}ret_mfptr{{.*}}()
+// CHECK-AARCH: [[DEF]] [2 x i64] @{{.*}}ret_mfptr{{.*}}()
 
 // nullptr_t is never noundef
-// CHECK: [[DEFINE]] i8* @{{.*}}ret_npt{{.*}}()
-// CHECK: [[DEFINE]] void @{{.*}}pass_npt{{.*}}(i8* %
+// CHECK: [[DEF]] i8* @{{.*}}ret_npt{{.*}}()
+// CHECK: [[DEF]] void @{{.*}}pass_npt{{.*}}(i8* %
 
 // TODO: for now, ExtInt is only noundef if it is sign/zero-extended
-// CHECK-INTEL: [[DEFINE]] noundef signext i3 @{{.*}}ret_BitInt{{.*}}()
-// CHECK-AARCH: [[DEFINE]] i3 @{{.*}}ret_BitInt{{.*}}()
-// CHECK-INTEL: [[DEFINE]] void @{{.*}}pass_BitInt{{.*}}(i3 noundef signext %
-// CHECK-AARCH: [[DEFINE]] void @{{.*}}pass_BitInt{{.*}}(i3 %
-// CHECK-INTEL: [[DEFINE]] void @{{.*}}pass_large_BitInt{{.*}}(i64 %{{.*}}, i64 %
-// CHECK-AARCH: [[DEFINE]] void @{{.*}}pass_large_BitInt{{.*}}(i127 %
+// CHECK-INTEL: [[DEF]] noundef signext i3 @{{.*}}ret_BitInt{{.*}}()
+// CHECK-AARCH: [[DEF]] i3 @{{.*}}ret_BitInt{{.*}}()
+// CHECK-INTEL: [[DEF]] void @{{.*}}pass_BitInt{{.*}}(i3 noundef signext %
+// CHECK-AARCH: [[DEF]] void @{{.*}}pass_BitInt{{.*}}(i3 %
+// CHECK-INTEL: [[DEF]] void @{{.*}}pass_large_BitInt{{.*}}(i64 %{{.*}}, i64 %
+// CHECK-AARCH: [[DEF]] void @{{.*}}pass_large_BitInt{{.*}}(i127 %
 } // namespace check_exotic
diff --git a/clang/test/CodeGen/indirect-noundef.cpp b/clang/test/CodeGen/indirect-noundef.cpp
--- a/clang/test/CodeGen/indirect-noundef.cpp
+++ b/clang/test/CodeGen/indirect-noundef.cpp
@@ -13,9 +13,9 @@
 // CHECK: @indirect_callee_union_ptr = [[GLOBAL]] i32 (i32)*
 union u1 (*indirect_callee_union_ptr)(union u1);
 
-// CHECK: [[DEFINE:define( dso_local)?]] noundef i32 @{{.*}}indirect_callee_int{{.*}}(i32 noundef %
+// CHECK: [[DEF:define( dso_local)?]] noundef i32 @{{.*}}indirect_callee_int{{.*}}(i32 noundef %
 int indirect_callee_int(int a) { return a; }
-// CHECK: [[DEFINE]] i32 @{{.*}}indirect_callee_union{{.*}}(i32 %
+// CHECK: [[DEF]] i32 @{{.*}}indirect_callee_union{{.*}}(i32 %
 union u1 indirect_callee_union(union u1 a) {
   return a;
 }
diff --git a/clang/test/Preprocessor/init.c b/clang/test/Preprocessor/init.c
--- a/clang/test/Preprocessor/init.c
+++ b/clang/test/Preprocessor/init.c
@@ -1396,13 +1396,13 @@
 // SPARC64-OBSD:#define __UINTMAX_C_SUFFIX__ ULL
 // SPARC64-OBSD:#define __UINTMAX_TYPE__ long long unsigned int
 //
-// RUN: %clang_cc1 -E -dM -ffreestanding -triple=x86_64-pc-kfreebsd-gnu < /dev/null | FileCheck -match-full-lines -check-prefix KFREEBSD-DEFINE %s
-// KFREEBSD-DEFINE:#define __FreeBSD_kernel__ 1
-// KFREEBSD-DEFINE:#define __GLIBC__ 1
+// RUN: %clang_cc1 -E -dM -ffreestanding -triple=x86_64-pc-kfreebsd-gnu < /dev/null | FileCheck -match-full-lines -check-prefix KFREEBSD-DEF %s
+// KFREEBSD-DEF:#define __FreeBSD_kernel__ 1
+// KFREEBSD-DEF:#define __GLIBC__ 1
 //
-// RUN: %clang_cc1 -E -dM -ffreestanding -triple=i686-pc-kfreebsd-gnu < /dev/null | FileCheck -match-full-lines -check-prefix KFREEBSDI686-DEFINE %s
-// KFREEBSDI686-DEFINE:#define __FreeBSD_kernel__ 1
-// KFREEBSDI686-DEFINE:#define __GLIBC__ 1
+// RUN: %clang_cc1 -E -dM -ffreestanding -triple=i686-pc-kfreebsd-gnu < /dev/null | FileCheck -match-full-lines -check-prefix KFREEBSDI686-DEF %s
+// KFREEBSDI686-DEF:#define __FreeBSD_kernel__ 1
+// KFREEBSDI686-DEF:#define __GLIBC__ 1
 //
 // RUN: %clang_cc1 -x c++ -triple i686-pc-linux-gnu -fobjc-runtime=gcc -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GNUSOURCE %s
 // RUN: %clang_cc1 -x c++ -triple sparc-rtems-elf -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GNUSOURCE %s
diff --git a/llvm/docs/CommandGuide/lit.rst b/llvm/docs/CommandGuide/lit.rst
--- a/llvm/docs/CommandGuide/lit.rst
+++ b/llvm/docs/CommandGuide/lit.rst
@@ -562,14 +562,6 @@
 further substitution patterns can be defined by each test module. See the
 modules :ref:`local-configuration-files`.
 
-By default, substitutions are expanded exactly once, so that if e.g. a
-substitution ``%build`` is defined in top of another substitution ``%cxx``,
-``%build`` will expand to ``%cxx`` textually, not to what ``%cxx`` expands to.
-However, if the ``recursiveExpansionLimit`` property of the ``TestingConfig``
-is set to a non-negative integer, substitutions will be expanded recursively
-until that limit is reached. It is an error if the limit is reached and
-expanding substitutions again would yield a different result.
-
 More detailed information on substitutions can be found in the
 :doc:`../TestingGuide`.
 
diff --git a/llvm/docs/TestingGuide.rst b/llvm/docs/TestingGuide.rst
--- a/llvm/docs/TestingGuide.rst
+++ b/llvm/docs/TestingGuide.rst
@@ -619,6 +619,15 @@
  ``%else %{<else branch>%}`` is optional and treated like ``%else %{%}``
  if not present.
 
+``%(line)``, ``%(line+<number>)``, ``%(line-<number>)``
+
+  The number of the line where this substitution is used, with an
+  optional integer offset.  These expand only if they appear
+  immediately in ``RUN:``, ``DEFINE:``, and ``REDEFINE:`` directives.
+  Occurrences in substitutions defined elsewhere are never expanded.
+  For example, this can be used in tests with multiple RUN lines,
+  which reference the test file's line numbers.
+
 **LLVM-specific substitutions:**
 
 ``%shlibext``
@@ -633,12 +642,6 @@
 
    Example: ``.exe`` (Windows), empty on Linux.
 
-``%(line)``, ``%(line+<number>)``, ``%(line-<number>)``
-   The number of the line where this substitution is used, with an optional
-   integer offset. This can be used in tests with multiple RUN lines, which
-   reference test file's line numbers.
-
-
 **Clang-specific substitutions:**
 
 ``%clang``
@@ -670,8 +673,199 @@
    output affects test results.  It's usually easy to tell: just look for
    redirection or piping of the ``FileCheck`` call's stdout or stderr.
 
-To add more substitutions, look at ``test/lit.cfg`` or ``lit.local.cfg``.
+.. _Test-specific substitutions:
+
+**Test-specific substitutions:**
+
+Additional substitutions can be defined as follows:
+
+- Lit configuration files (e.g., ``lit.cfg`` or ``lit.local.cfg``) can define
+  substitutions for all tests in a test directory.  They do so by extending the
+  substitution list, ``config.substitutions``.  Each item in the list is a tuple
+  consisting of a pattern and its replacement, which lit applies using python's
+  ``re.sub`` function.
+- To define substitutions within a single test file, lit supports the
+  ``DEFINE:`` and ``REDEFINE:`` directives, described in detail below.  So that
+  they have no effect on other test files, these directives modify a copy of the
+  substitution list that is produced by lit configuration files.
+
+For example, the following directives can be inserted into a test file to define
+``%{cflags}`` and ``%{fcflags}`` substitutions with empty initial values, which
+serve as the parameters of another newly defined ``%{check}`` substitution:
+
+.. code-block:: llvm
+
+    ; DEFINE: %{cflags} =
+    ; DEFINE: %{fcflags} =
+
+    ; DEFINE: %{check} =                                                  \
+    ; DEFINE:   %clang_cc1 -verify -fopenmp -fopenmp-version=51 %{cflags} \
+    ; DEFINE:              -emit-llvm -o - %s |                           \
+    ; DEFINE:     FileCheck %{fcflags} %s
+
+Alternatively, the above substitutions can be defined in a lit configuration
+file to be shared with other test files.  Either way, the test file can then
+specify directives like the following to redefine the parameter substitutions as
+desired before each use of ``%{check}`` in a ``RUN:`` line:
+
+.. code-block:: llvm
+
+    ; REDEFINE: %{cflags} = -triple x86_64-apple-darwin10.6.0 -fopenmp-simd
+    ; REDEFINE: %{fcflags} = -check-prefix=SIMD
+    ; RUN: %{check}
+
+    ; REDEFINE: %{cflags} = -triple x86_64-unknown-linux-gnu -fopenmp-simd
+    ; REDEFINE: %{fcflags} = -check-prefix=SIMD
+    ; RUN: %{check}
+
+    ; REDEFINE: %{cflags} = -triple x86_64-apple-darwin10.6.0
+    ; REDEFINE: %{fcflags} = -check-prefix=NO-SIMD
+    ; RUN: %{check}
+
+    ; REDEFINE: %{cflags} = -triple x86_64-unknown-linux-gnu
+    ; REDEFINE: %{fcflags} = -check-prefix=NO-SIMD
+    ; RUN: %{check}
+
+Besides providing initial values, the initial ``DEFINE:`` directives for the
+parameter substitutions in the above example serve a second purpose: they
+establish the substitution order so that both ``%{check}`` and its parameters
+expand as desired.  There's a simple way to remember the required definition
+order in a test file: define a substitution before any substitution that might
+refer to it.
+
+In general, substitution expansion behaves as follows:
+
+- Upon arriving at each ``RUN:`` line, lit expands all substitutions in that
+  ``RUN:`` line using their current values from the substitution list.  No
+  substitution expansion is performed immediately at ``DEFINE:`` and
+  ``REDEFINE:`` directives except ``%(line)``, ``%(line+<number>)``, and
+  ``%(line-<number>)``.
+- When expanding substitutions in a ``RUN:`` line, lit makes only one pass
+  through the substitution list by default.  In this case, a substitution must
+  have been inserted earlier in the substitution list than any substitution
+  appearing in its value in order for the latter to expand.  (For greater
+  flexibility, you can enable multiple passes through the substitution list by
+  setting `recursiveExpansionLimit`_ in a lit configuration file.)
+- While lit configuration files can insert anywhere in the substitution list,
+  the insertion behavior of the ``DEFINE:`` and ``REDEFINE:`` directives is
+  specified below and is designed specifically for the use case presented in the
+  example above.
+- Defining a substitution in terms of itself, whether directly or via other
+  substitutions, should be avoided.  It usually produces an infinitely recursive
+  definition that cannot be fully expanded.  It does *not* define the
+  substitution in terms of its previous value, even when using ``REDEFINE:``.
+
+The relationship between the ``DEFINE:`` and ``REDEFINE:`` directive is
+analogous to the relationship between a variable declaration and variable
+assignment in many programming languages:
+
+- ``DEFINE: %{name} = value``
+
+   This directive assigns the specified value to a new substitution whose
+   pattern is ``%{name}``, or it reports an error if there is already a
+   substitution whose pattern contains ``%{name}`` because that could produce
+   confusing expansions (e.g., a lit configuration file might define a
+   substitution with the pattern ``%{name}\[0\]``).  The new substitution is
+   inserted at the start of the substitution list so that it will expand first.
+   Thus, its value can contain any substitution previously defined, whether in
+   the same test file or in a lit configuration file, and both will expand.
+
+- ``REDEFINE: %{name} = value``
+
+   This directive assigns the specified value to an existing substitution whose
+   pattern is ``%{name}``, or it reports an error if there are no substitutions
+   with that pattern or if there are multiple substitutions whose patterns
+   contain ``%{name}``.  The substitution's current position in the substitution
+   list does not change so that expansion order relative to other existing
+   substitutions is preserved.
+
+The following properties apply to both the ``DEFINE:`` and ``REDEFINE:``
+directives:
+
+- **Substitution name**: In the directive, whitespace immediately before or
+  after ``%{name}`` is optional and discarded.  ``%{name}`` must start with
+  ``%{``, it must end with ``}``, and the rest must start with a letter or
+  underscore and contain only alphanumeric characters, hyphens, underscores, and
+  colons.  This syntax has a few advantages:
+
+    - It is impossible for ``%{name}`` to contain sequences that are special in
+      python's ``re.sub`` patterns.  Otherwise, attempting to specify
+      ``%{name}`` as a substitution pattern in a lit configuration file could
+      produce confusing expansions.
+    - The braces help avoid the possibility that another substitution's pattern
+      will match part of ``%{name}`` or vice-versa, producing confusing
+      expansions.  However, the patterns of substitutions defined by lit
+      configuration files and by lit itself are not restricted to this form, so
+      overlaps are still theoretically possible.
+
+- **Substitution value**: The value includes all text from the first
+  non-whitespace character after ``=`` to the last non-whitespace character.  If
+  there is no non-whitespace character after ``=``, the value is the empty
+  string.  Escape sequences that can appear in python ``re.sub`` replacement
+  strings are treated as plain text in the value.
+- **Line continuations**: If the last non-whitespace character on the line after
+  ``:`` is ``\``, then the next directive must use the same directive keyword
+  (e.g., ``DEFINE:``) , and it is an error if there is no additional directive.
+  That directive serves as a continuation.  That is, before following the rules
+  above to parse the text after ``:`` in either directive, lit joins that text
+  together to form a single directive, replaces the ``\`` with a single space,
+  and removes any other whitespace that is now adjacent to that space.  A
+  continuation can be continued in the same manner.  A continuation containing
+  only whitespace after its ``:`` is an error.
+
+.. _recursiveExpansionLimit:
+
+**recursiveExpansionLimit:**
+
+As described in the previous section, when expanding substitutions in a ``RUN:``
+line, lit makes only one pass through the substitution list by default.  Thus,
+if substitutions are not defined in the proper order, some will remain in the
+``RUN:`` line unexpanded.  For example, the following directives refer to
+``%{inner}`` within ``%{outer}`` but do not define ``%{inner}`` until after
+``%{outer}``:
+
+.. code-block:: llvm
+
+    ; By default, this definition order does not enable full expansion.
+
+    ; DEFINE: %{outer} = %{inner}
+    ; DEFINE: %{inner} = expanded
+
+    ; RUN: echo '%{outer}'
+
+``DEFINE:`` inserts substitutions at the start of the substitution list, so
+``%{inner}`` expands first but has no effect because the original ``RUN:`` line
+does not contain ``%{inner}``.  Next, ``%{outer}`` expands, and the output of
+the ``echo`` command becomes:
+
+.. code-block:: shell
+
+    %{inner}
+
+Of course, one way to fix this simple case is to reverse the definitions of
+``%{outer}`` and ``%{inner}``.  However, if a test has a complex set of
+substitutions that can all reference each other, there might not exist a
+sufficient substitution order.
+
+To address such use cases, lit configuration files support
+``config.recursiveExpansionLimit``, which can be set to a non-negative integer
+to specify the maximum number of passes through the substitution list.  Thus, in
+the above example, setting the limit to 2 would cause lit to make a second pass
+that expands ``%{inner}`` in the ``RUN:`` line, and the output from the ``echo``
+command when then be:
+
+.. code-block:: shell
+
+    expanded
+
+To improve performance, lit will stop making passes when it notices the ``RUN:``
+line has stopped changing.  In the above example, setting the limit higher than
+2 is thus harmless.
 
+To facilitate debugging, after reaching the limit, lit will make one extra pass
+and report an error if the ``RUN:`` line changes again.  In the above example,
+setting the limit to 1 will thus cause lit to report an error instead of
+producing incorrect output.
 
 Options
 -------
diff --git a/llvm/test/tools/llvm-cvtres/help.test b/llvm/test/tools/llvm-cvtres/help.test
--- a/llvm/test/tools/llvm-cvtres/help.test
+++ b/llvm/test/tools/llvm-cvtres/help.test
@@ -4,7 +4,7 @@
 ; HELP_TEST: 	  OVERVIEW: Resource Converter
 ; HELP_TEST-DAG:  USAGE: llvm-cvtres [options] file...
 ; HELP_TEST-DAG:  OPTIONS:
-; HELP_TEST-NEXT:   /DEFINE:symbol Not implemented
+; HELP_TEST-NEXT:   /{{DEFINE}}:symbol Not implemented
 ; HELP_TEST-NEXT:   /FOLDDUPS: Not implemented
 ; HELP_TEST-NEXT:   /HELP Display available options
 ; HELP_TEST-NEXT:   /MACHINE:{ARM|ARM64|EBC|IA64|X64|X86}
diff --git a/llvm/test/tools/yaml2obj/ELF/custom-null-section.yaml b/llvm/test/tools/yaml2obj/ELF/custom-null-section.yaml
--- a/llvm/test/tools/yaml2obj/ELF/custom-null-section.yaml
+++ b/llvm/test/tools/yaml2obj/ELF/custom-null-section.yaml
@@ -42,11 +42,11 @@
 ## Check we can redefine fields of the first SHT_NULL section.
 
 # RUN: yaml2obj --docnum=3 %s -o %t3
-# RUN: llvm-readelf --sections %t3 | FileCheck %s --check-prefix=REDEFINE
+# RUN: llvm-readelf --sections %t3 | FileCheck %s --check-prefix=REDEF
 
-# REDEFINE:      Section Headers:
-# REDEFINE-NEXT:  [Nr] Name Type Address          Off    Size   ES Flg Lk Inf Al
-# REDEFINE-NEXT:  [ 0] .foo NULL 0000000000000006 000000 000002 03   A 4   5  1
+# REDEF:      Section Headers:
+# REDEF-NEXT:  [Nr] Name Type Address          Off    Size   ES Flg Lk Inf Al
+# REDEF-NEXT:  [ 0] .foo NULL 0000000000000006 000000 000002 03   A 4   5  1
 
 --- !ELF
 FileHeader:
diff --git a/llvm/utils/lit/lit/TestRunner.py b/llvm/utils/lit/lit/TestRunner.py
--- a/llvm/utils/lit/lit/TestRunner.py
+++ b/llvm/utils/lit/lit/TestRunner.py
@@ -1218,6 +1218,203 @@
 def _caching_re_compile(r):
     return re.compile(r)
 
+class ExpandableScriptDirective(object):
+    """
+    Common interface for lit directives for which any lit substitutions must be
+    expanded to produce the shell script.  It includes directives (e.g., 'RUN:')
+    specifying shell commands that might have lit substitutions to be expanded.
+    It also includes lit directives (e.g., 'DEFINE:') that adjust substitutions.
+
+    start_line_number: The directive's starting line number.
+    end_line_number: The directive's ending line number, which is
+        start_line_number if the directive has no line continuations.
+    keyword: The keyword that specifies the directive.  For example, 'RUN:'.
+    """
+
+    def __init__(self, start_line_number, end_line_number, keyword):
+        # Input line number where the directive starts.
+        self.start_line_number = start_line_number
+        # Input line number where the directive ends.
+        self.end_line_number = end_line_number
+        # The keyword used to indicate the directive.
+        self.keyword = keyword
+
+    def add_continuation(self, line_number, keyword, line):
+        """
+        Add a continuation line to this directive and return True, or do nothing
+        and return False if the specified line is not a continuation for this
+        directive (e.g., previous line does not end in '\', or keywords do not
+        match).
+
+        line_number: The line number for the continuation line.
+        keyword: The keyword that specifies the continuation line.  For example,
+            'RUN:'.
+        line: The content of the continuation line after the keyword.
+        """
+        assert False, "expected method to be called on derived class"
+
+    def needs_continuation(self):
+        """
+        Does this directive require a continuation line?
+
+        '\' is documented as indicating a line continuation even if whitespace
+        separates it from the newline.  It looks like a line continuation, and
+        it would be confusing if it didn't behave as one.
+        """
+        assert False, "expected method to be called on derived class"
+
+    def get_location(self):
+        """
+        Get a phrase describing the line or range of lines so far included by
+        this directive and any line continuations.
+        """
+        if self.start_line_number == self.end_line_number:
+            return f'at line {self.start_line_number}'
+        return f'from line {self.start_line_number} to {self.end_line_number}'
+
+class CommandDirective(ExpandableScriptDirective):
+    """
+    A lit directive taking a shell command line.  For example,
+    'RUN: echo hello world'.
+
+    command: The content accumulated so far from the directive and its
+        continuation lines.
+    """
+
+    def __init__(self, start_line_number, end_line_number, keyword, line):
+        super().__init__(start_line_number, end_line_number, keyword)
+        self.command = line.rstrip()
+
+    def add_continuation(self, line_number, keyword, line):
+        if keyword != self.keyword or not self.needs_continuation():
+            return False
+        self.command = self.command[:-1] + line.rstrip()
+        self.end_line_number = line_number
+        return True
+
+    def needs_continuation(self):
+        # Trailing whitespace is stripped immediately when each line is added,
+        # so '\' is never hidden here.
+        return self.command[-1] == '\\'
+
+class SubstDirective(ExpandableScriptDirective):
+    """
+    A lit directive taking a substitution definition or redefinition.  For
+    example, 'DEFINE: %{name} = value'.
+
+    new_subst: True if this directive defines a new substitution.  False if it
+        redefines an existing substitution.
+    body: The unparsed content accumulated so far from the directive and its
+        continuation lines.
+    name: The substitution's name, or None if more continuation lines are still
+        required.
+    value: The substitution's value, or None if more continuation lines are
+        still required.
+    """
+
+    def __init__(self, start_line_number, end_line_number, keyword, new_subst,
+                 line):
+        super().__init__(start_line_number, end_line_number, keyword)
+        self.new_subst = new_subst
+        self.body = line
+        self.name = None
+        self.value = None
+        self._parse_body()
+
+    def add_continuation(self, line_number, keyword, line):
+        if keyword != self.keyword or not self.needs_continuation():
+            return False
+        if not line.strip():
+            raise ValueError("Substitution's continuation is empty")
+        # Append line.  Replace the '\' and any adjacent whitespace with a
+        # single space.
+        self.body = self.body.rstrip()[:-1].rstrip() + ' ' + line.lstrip()
+        self.end_line_number = line_number
+        self._parse_body()
+        return True
+
+    def needs_continuation(self):
+        return self.body.rstrip()[-1:] == '\\'
+
+    def _parse_body(self):
+        """
+        If no more line continuations are required, parse all the directive's
+        accumulated lines in order to identify the substitution's name and full
+        value, and raise an exception if invalid.
+        """
+        if self.needs_continuation():
+            return
+
+        # Extract the left-hand side and value, and discard any whitespace
+        # enclosing each.
+        parts = self.body.split('=', 1)
+        if len(parts) == 1:
+            raise ValueError("Substitution's definition does not contain '='")
+        self.name = parts[0].strip()
+        self.value = parts[1].strip()
+
+        # Check the substitution's name.
+        #
+        # Do not extend this to permit '.' or any sequence that's special in a
+        # python pattern.  We could escape that automatically for
+        # DEFINE/REDEFINE directives in test files.  However, lit configuration
+        # file authors would still have to remember to escape them manually in
+        # substitution names but not in values.  Moreover, the manually chosen
+        # and automatically chosen escape sequences would have to be consistent
+        # (e.g., '\.' vs. '[.]') in order for REDEFINE to successfully redefine
+        # a substitution previously defined by a lit configuration file.  All
+        # this seems too error prone and confusing to be worthwhile.  If you
+        # want your name to express structure, use ':' instead of '.'.
+        #
+        # Actually, '{' and '}' are special if they contain only digits possibly
+        # separated by a comma.  Requiring a leading letter avoids that.
+        if not re.fullmatch(r'%{[_a-zA-Z][-_:0-9a-zA-Z]*}', self.name):
+            raise ValueError(
+                f"Substitution name '{self.name}' is malformed as it must "
+                f"start with '%{{', it must end with '}}', and the rest must "
+                f"start with a letter or underscore and contain only "
+                f"alphanumeric characters, hyphens, underscores, and colons")
+
+    def adjust_substitutions(self, substitutions):
+        """
+        Modify the specified substitution list as specified by this directive.
+        """
+        assert not self.needs_continuation(), \
+               "expected directive continuations to be parsed before applying"
+        value_repl = self.value.replace('\\', '\\\\')
+        existing = [i for i, subst in enumerate(substitutions)
+                    if self.name in subst[0]]
+        existing_res = ''.join("\nExisting pattern: " + substitutions[i][0]
+                               for i in existing)
+        if self.new_subst:
+            if existing:
+                raise ValueError(
+                    f"Substitution whose pattern contains '{self.name}' is "
+                    f"already defined before '{self.keyword}' directive "
+                    f"{self.get_location()}"
+                    f"{existing_res}")
+            substitutions.insert(0, (self.name, value_repl))
+            return
+        if len(existing) > 1:
+            raise ValueError(
+                f"Multiple substitutions whose patterns contain '{self.name}' "
+                f"are defined before '{self.keyword}' directive "
+                f"{self.get_location()}"
+                f"{existing_res}")
+        if not existing:
+            raise ValueError(
+                f"No substitution for '{self.name}' is defined before "
+                f"'{self.keyword}' directive {self.get_location()}")
+        if substitutions[existing[0]][0] != self.name:
+            raise ValueError(
+                f"Existing substitution whose pattern contains '{self.name}' "
+                f"does not have the pattern specified by '{self.keyword}' "
+                f"directive {self.get_location()}\n"
+                f"Expected pattern: {self.name}"
+                f"{existing_res}")
+        substitutions[existing[0]] = (self.name, value_repl)
+
+
 def applySubstitutions(script, substitutions, conditions={},
                        recursion_limit=None):
     """
@@ -1363,8 +1560,20 @@
         return processed
 
     process = processLine if recursion_limit is None else processLineToFixedPoint
-    
-    return [unescapePercents(process(ln)) for ln in script]
+    output = []
+    for directive in script:
+        if isinstance(directive, SubstDirective):
+            directive.adjust_substitutions(substitutions)
+        else:
+            if isinstance(directive, CommandDirective):
+                line = directive.command
+            else:
+                # Can come from preamble_commands.
+                assert isinstance(directive, str)
+                line = directive
+            output.append(unescapePercents(process(line)))
+
+    return output
 
 
 class ParserKind(object):
@@ -1379,6 +1588,10 @@
         boolean expressions. Ex 'XFAIL:'
     INTEGER: A keyword taking a single integer. Ex 'ALLOW_RETRIES:'
     CUSTOM: A keyword with custom parsing semantics.
+    DEFINE: A keyword taking a new lit substitution definition. Ex
+        'DEFINE: %{name}=value'
+    REDEFINE: A keyword taking a lit substitution redefinition. Ex
+        'REDEFINE: %{name}=value'
     """
     TAG = 0
     COMMAND = 1
@@ -1386,6 +1599,8 @@
     BOOLEAN_EXPR = 3
     INTEGER = 4
     CUSTOM = 5
+    DEFINE = 6
+    REDEFINE = 7
 
     @staticmethod
     def allowedKeywordSuffixes(value):
@@ -1394,7 +1609,9 @@
                  ParserKind.LIST:         [':'],
                  ParserKind.BOOLEAN_EXPR: [':'],
                  ParserKind.INTEGER:      [':'],
-                 ParserKind.CUSTOM:       [':', '.']
+                 ParserKind.CUSTOM:       [':', '.'],
+                 ParserKind.DEFINE:       [':'],
+                 ParserKind.REDEFINE:     [':']
                } [value]
 
     @staticmethod
@@ -1404,7 +1621,9 @@
                  ParserKind.LIST:         'LIST',
                  ParserKind.BOOLEAN_EXPR: 'BOOLEAN_EXPR',
                  ParserKind.INTEGER:      'INTEGER',
-                 ParserKind.CUSTOM:       'CUSTOM'
+                 ParserKind.CUSTOM:       'CUSTOM',
+                 ParserKind.DEFINE:       'DEFINE',
+                 ParserKind.REDEFINE:     'REDEFINE'
                } [value]
 
 
@@ -1454,6 +1673,15 @@
             if parser is None:
                 raise ValueError("ParserKind.CUSTOM requires a custom parser")
             self.parser = parser
+        elif kind == ParserKind.DEFINE:
+            self.parser = lambda line_number, line, output: \
+                                 self._handleSubst(line_number, line, output,
+                                                   self.keyword, new_subst=True)
+        elif kind == ParserKind.REDEFINE:
+            self.parser = lambda line_number, line, output: \
+                                 self._handleSubst(line_number, line, output,
+                                                   self.keyword,
+                                                   new_subst=False)
         else:
             raise ValueError("Unknown kind '%s'" % kind)
 
@@ -1474,23 +1702,25 @@
         return (not line.strip() or output)
 
     @staticmethod
-    def _handleCommand(line_number, line, output, keyword):
-        """A helper for parsing COMMAND type keywords"""
-        # Trim trailing whitespace.
-        line = line.rstrip()
-        # Substitute line number expressions
+    def _substituteLineNumbers(line_number, line):
         line = re.sub(r'%\(line\)', str(line_number), line)
-
         def replace_line_number(match):
             if match.group(1) == '+':
                 return str(line_number + int(match.group(2)))
             if match.group(1) == '-':
                 return str(line_number - int(match.group(2)))
-        line = re.sub(r'%\(line *([\+-]) *(\d+)\)', replace_line_number, line)
-        # Collapse lines with trailing '\\'.
-        if output and output[-1][-1] == '\\':
-            output[-1] = output[-1][:-1] + line
-        else:
+        return re.sub(r'%\(line *([\+-]) *(\d+)\)', replace_line_number, line)
+
+    @classmethod
+    def _handleCommand(cls, line_number, line, output, keyword):
+        """A helper for parsing COMMAND type keywords"""
+        # Substitute line number expressions.
+        line = cls._substituteLineNumbers(line_number, line)
+
+        # Collapse lines with trailing '\\', or add line with line number to
+        # start a new pipeline.
+        if not output or not output[-1].add_continuation(line_number, keyword,
+                                                         line):
             if output is None:
                 output = []
             pdbg = "%dbg({keyword} at line {line_number})".format(
@@ -1501,7 +1731,8 @@
             line = "{pdbg} {real_command}".format(
                 pdbg=pdbg,
                 real_command=line)
-            output.append(line)
+            output.append(CommandDirective(line_number, line_number, keyword,
+                                           line))
         return output
 
     @staticmethod
@@ -1541,6 +1772,18 @@
                 BooleanExpression.evaluate(s, [])
         return output
 
+    @classmethod
+    def _handleSubst(cls, line_number, line, output, keyword, new_subst):
+        """A parser for DEFINE and REDEFINE type keywords"""
+        line = cls._substituteLineNumbers(line_number, line)
+        if output and output[-1].add_continuation(line_number, keyword, line):
+            return output
+        if output is None:
+            output = []
+        output.append(SubstDirective(line_number, line_number, keyword,
+                                     new_subst, line))
+        return output
+
 
 def _parseKeywords(sourcepath, additional_parsers=[],
                    require_script=True):
@@ -1548,8 +1791,8 @@
 
     Scan an LLVM/Clang style integrated test script and extract all the lines
     pertaining to a special parser. This includes 'RUN', 'XFAIL', 'REQUIRES',
-    'UNSUPPORTED' and 'ALLOW_RETRIES', as well as other specified custom
-    parsers.
+    'UNSUPPORTED', 'ALLOW_RETRIES', 'END', 'DEFINE', 'REDEFINE', as well as
+    other specified custom parsers.
 
     Returns a dictionary mapping each custom parser to its value after
     parsing the test.
@@ -1562,7 +1805,11 @@
         IntegratedTestKeywordParser('REQUIRES:', ParserKind.BOOLEAN_EXPR),
         IntegratedTestKeywordParser('UNSUPPORTED:', ParserKind.BOOLEAN_EXPR),
         IntegratedTestKeywordParser('ALLOW_RETRIES:', ParserKind.INTEGER),
-        IntegratedTestKeywordParser('END.', ParserKind.TAG)
+        IntegratedTestKeywordParser('END.', ParserKind.TAG),
+        IntegratedTestKeywordParser('DEFINE:', ParserKind.DEFINE,
+                                    initial_value=script),
+        IntegratedTestKeywordParser('REDEFINE:', ParserKind.REDEFINE,
+                                    initial_value=script)
     ]
     keyword_parsers = {p.keyword: p for p in builtin_parsers}
 
@@ -1586,12 +1833,21 @@
             break
 
     # Verify the script contains a run line.
-    if require_script and not script:
+    if require_script and not any(isinstance(directive, CommandDirective)
+                                  for directive in script):
         raise ValueError("Test has no 'RUN:' line")
 
-    # Check for unterminated run lines.
-    if script and script[-1][-1] == '\\':
-        raise ValueError("Test has unterminated 'RUN:' lines (with '\\')")
+    # Check for unterminated run or subst lines.
+    #
+    # If, after a line continuation for one kind of directive (e.g., 'RUN:',
+    # 'DEFINE:', 'REDEFINE:') in script, the next directive in script is a
+    # different kind, then the '\\' remains on the former, and we report it
+    # here.
+    for directive in script:
+        if directive.needs_continuation():
+            raise ValueError(f"Test has unterminated '{directive.keyword}' "
+                             f"directive (with '\\') "
+                             f"{directive.get_location()}")
 
     # Check boolean expressions for unterminated lines.
     for key in keyword_parsers:
@@ -1631,6 +1887,8 @@
     except ValueError as e:
         return lit.Test.Result(Test.UNRESOLVED, str(e))
     script = parsed['RUN:'] or []
+    assert parsed['DEFINE:'] == script
+    assert parsed['REDEFINE:'] == script
     test.xfails += parsed['XFAIL:'] or []
     test.requires += parsed['REQUIRES:'] or []
     test.unsupported += parsed['UNSUPPORTED:'] or []
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/before-name.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/before-name.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/before-name.txt
@@ -0,0 +1,7 @@
+# DEFINE: foo %{name}=value
+# RUN: echo %{name}
+
+#      CHECK: Substitution name 'foo %{name}' is malformed {{.*}}
+# CHECK-NEXT: in {{DEFINE}}: directive on test line [[#@LINE-4]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/between-name-equals.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/between-name-equals.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/between-name-equals.txt
@@ -0,0 +1,9 @@
+# ':' is treated like part of the name, so the name is bad.
+
+# DEFINE: %{name}:=value
+# RUN: echo %{name}
+
+#      CHECK: Substitution name '%{name}:' is malformed {{.*}}
+# CHECK-NEXT: in {{DEFINE}}: directive on test line [[#@LINE-4]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/braces-empty.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/braces-empty.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/braces-empty.txt
@@ -0,0 +1,7 @@
+# DEFINE: %{} = value
+# RUN: echo %{}
+
+#      CHECK: Substitution name '%{}' is malformed {{.*}}
+# CHECK-NEXT: in {{DEFINE}}: directive on test line [[#@LINE-4]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/braces-with-dot.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/braces-with-dot.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/braces-with-dot.txt
@@ -0,0 +1,12 @@
+# In python's re.sub patterns, '.' means any character.  If we permitted that
+# in a substitution name (and escaped it before recording it as a substitution),
+# it would be confusing if someone tried to use the same name in a lit
+# configuration file, where the pattern isn't escaped automatically.
+
+# DEFINE: %{foo.bar} = value
+# RUN: echo %{foo.bar}
+
+#      CHECK: Substitution name '%{foo.bar}' is malformed {{.*}}
+# CHECK-NEXT: in {{DEFINE}}: directive on test line [[#@LINE-4]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/braces-with-equals.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/braces-with-equals.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/braces-with-equals.txt
@@ -0,0 +1,9 @@
+# The first equals counts as the equals.
+
+# DEFINE: %{foo=bar} = value
+# RUN: echo %{foo=bar}
+
+#      CHECK: Substitution name '%{foo' is malformed {{.*}}
+# CHECK-NEXT: in {{DEFINE}}: directive on test line [[#@LINE-4]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/braces-with-newline.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/braces-with-newline.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/braces-with-newline.txt
@@ -0,0 +1,8 @@
+# DEFINE:%{foo\
+# DEFINE:bar} = value
+# RUN: echo %{foo bar}
+
+#      CHECK: Substitution name '%{foo bar}' is malformed {{.*}}
+# CHECK-NEXT: in {{DEFINE}}: directive on test line [[#@LINE-4]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/braces-with-number.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/braces-with-number.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/braces-with-number.txt
@@ -0,0 +1,12 @@
+# In python's re.sub patterns, '%{3}' means three '%%%'.  If we permitted that
+# as a substitution name (and escaped it before recording it as a
+# substitution), it would be confusing if someone tried to use the same name in
+# a lit configuration file, where the pattern isn't escaped automatically.
+
+# DEFINE: %{3} = value
+# RUN: echo %{3}
+
+#      CHECK: Substitution name '%{3}' is malformed {{.*}}
+# CHECK-NEXT: in {{DEFINE}}: directive on test line [[#@LINE-4]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/braces-with-ws.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/braces-with-ws.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/braces-with-ws.txt
@@ -0,0 +1,7 @@
+# DEFINE: %{foo bar} = value
+# RUN: echo %{foo bar}
+
+#      CHECK: Substitution name '%{foo bar}' is malformed {{.*}}
+# CHECK-NEXT: in {{DEFINE}}: directive on test line [[#@LINE-4]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/empty.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/empty.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/empty.txt
@@ -0,0 +1,7 @@
+# DEFINE:
+# RUN: echo Hello World
+
+#      CHECK: Substitution's definition does not contain '='
+# CHECK-NEXT: in {{DEFINE}}: directive on test line [[#@LINE-4]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/no-equals.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/no-equals.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/no-equals.txt
@@ -0,0 +1,7 @@
+# DEFINE: %{name}: value
+# RUN: echo %{name}
+
+#      CHECK: Substitution's definition does not contain '='
+# CHECK-NEXT: in {{DEFINE}}: directive on test line [[#@LINE-4]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/no-name.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/no-name.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/no-name.txt
@@ -0,0 +1,7 @@
+# DEFINE:=value
+# RUN: echo Hello World
+
+#      CHECK: Substitution name '' is malformed {{.*}}
+# CHECK-NEXT: in {{DEFINE}}: directive on test line [[#@LINE-4]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/ws-only.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/ws-only.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/assignment/ws-only.txt
@@ -0,0 +1,8 @@
+#        v~ whitespace intentional
+# DEFINE:  
+# RUN: echo Hello World
+
+#      CHECK: Substitution's definition does not contain '='
+# CHECK-NEXT: in {{DEFINE}}: directive on test line [[#@LINE-4]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/empty.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/empty.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/empty.txt
@@ -0,0 +1,10 @@
+# Surely an empty substitution continuation is an accident, so it's an error.
+
+# DEFINE: %{foo} = foo \
+# DEFINE:
+# RUN: echo '%{foo}'
+
+#      CHECK: Substitution's continuation is empty
+# CHECK-NEXT: in DEFINE: directive on test line [[#@LINE-4]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/end-in-double-backslash.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/end-in-double-backslash.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/end-in-double-backslash.txt
@@ -0,0 +1,11 @@
+# This seems like a way to end a value with a backslash, but it requires an
+# empty substitution continuation, which isn't permitted.
+
+# DEFINE: %{foo} = \\
+# DEFINE:
+# RUN: echo '%{foo}'
+
+#      CHECK: Substitution's continuation is empty
+# CHECK-NEXT: in {{DEFINE}}: directive on test line [[#@LINE-4]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-define-bad-redefine.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-define-bad-redefine.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-define-bad-redefine.txt
@@ -0,0 +1,13 @@
+# You cannot continue a DEFINE with a REDEFINE.  In this case, the REDEFINE
+# is wrong on its own because it's written as a continuation, so the bad
+# REDEFINE is reported.
+
+# DEFINE: %{foo}=echo \
+# REDEFINE: Hello World
+# DEFINE: too late to continue
+# RUN: %{foo}
+
+#      CHECK: Substitution's definition does not contain '='
+# CHECK-NEXT: in {{REDEFINE}}: directive on test line [[#@LINE-5]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-define-continuation.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-define-continuation.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-define-continuation.txt
@@ -0,0 +1,9 @@
+# Check a define's continuation line that is unterminated.
+
+# RUN: echo "Don't complain about no RUN lines."
+# DEFINE: %{foo} = foo \
+# DEFINE:          bar \
+
+# CHECK: Test has unterminated '{{DEFINE}}:' directive (with '\') from line [[#@LINE-3]] to [[#@LINE-2]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-define-redefine.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-define-redefine.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-define-redefine.txt
@@ -0,0 +1,13 @@
+# You cannot continue a DEFINE with a REDEFINE.  In this case, the REDEFINE
+# looks fine on its own, so the unterminated DEFINE is reported.
+
+# DEFINE: %{name}=x
+# DEFINE: %{value}=3
+# DEFINE: %{deceptive-continue}=echo \
+# REDEFINE: %{name}=%{value}
+# DEFINE: %{too-late-to-continue}=
+# RUN: %{deceptive-continue}
+
+# CHECK: Test has unterminated '{{DEFINE}}:' directive (with '\') at line [[#@LINE-5]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-define-run.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-define-run.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-define-run.txt
@@ -0,0 +1,9 @@
+# You cannot continue a DEFINE with a RUN.
+
+# DEFINE: %{foo}=echo \
+# RUN: %{foo}
+# DEFINE: %{too-late-to-continue}=
+
+# CHECK: Test has unterminated '{{DEFINE}}:' directive (with '\') at line [[#@LINE-4]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-define.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-define.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-define.txt
@@ -0,0 +1,8 @@
+# Simple case of unterminated define as last directive in the script.
+
+# RUN: echo "Don't complain about no RUN lines."
+# DEFINE: %{foo}=foo\
+
+# CHECK: Test has unterminated '{{DEFINE}}:' directive (with '\') at line [[#@LINE-2]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-redefine-bad-define.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-redefine-bad-define.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-redefine-bad-define.txt
@@ -0,0 +1,13 @@
+# You cannot continue a REDEFINE with a DEFINE.  In this case, the DEFINE is
+# wrong on its own because it's written as a continuation, so the bad DEFINE is
+# reported.
+
+# REDEFINE: %{global:what}=echo \
+# DEFINE: Hello World
+# REDEFINE: too late to continue
+# RUN: %{foo}
+
+#      CHECK: Substitution's definition does not contain '='
+# CHECK-NEXT: in {{DEFINE}}: directive on test line [[#@LINE-5]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-redefine-continuation.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-redefine-continuation.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-redefine-continuation.txt
@@ -0,0 +1,9 @@
+# Check a redefine's continuation line that is unterminated.
+
+# RUN: echo "Don't complain about no RUN lines."
+# REDEFINE: %{global:what} = foo \
+# REDEFINE:                  bar \
+
+# CHECK: Test has unterminated '{{REDEFINE}}:' directive (with '\') from line [[#@LINE-3]] to [[#@LINE-2]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-redefine-define.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-redefine-define.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-redefine-define.txt
@@ -0,0 +1,13 @@
+# You cannot continue a REDEFINE with a DEFINE.  In this case, the DEFINE
+# looks fine on its own, so the unterminated REDEFINE is reported.
+
+# DEFINE: %{name}=x
+# DEFINE: %{value}=3
+# REDEFINE: %{global:what}=echo \
+# DEFINE: %{name}=%{value}
+# REDEFINE: %{too-late-to-continue}=
+# RUN: %{deceptive-continue}
+
+# CHECK: Test has unterminated '{{REDEFINE}}:' directive (with '\') at line [[#@LINE-5]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-redefine-run.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-redefine-run.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-redefine-run.txt
@@ -0,0 +1,9 @@
+# You cannot continue a REDEFINE with a RUN.
+
+# REDEFINE: %{global:what}=echo \
+# RUN: %{global:what}
+# REDEFINE: %{too-late-to-continue}=
+
+# CHECK: Test has unterminated '{{REDEFINE}}:' directive (with '\') at line [[#@LINE-4]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-redefine.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-redefine.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-redefine.txt
@@ -0,0 +1,8 @@
+# Simple case of unterminated redefine as last directive in the script.
+
+# RUN: echo "Don't complain about no RUN lines."
+# REDEFINE: %{global:what}=foo\
+
+# CHECK: Test has unterminated '{{REDEFINE}}:' directive (with '\') at line [[#@LINE-2]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-run-define.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-run-define.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-run-define.txt
@@ -0,0 +1,9 @@
+# You cannot continue a RUN with a DEFINE.
+
+# RUN: echo \
+# DEFINE: %{foo}=bar
+# RUN: too late to continue
+
+# CHECK: Test has unterminated '{{RUN}}:' directive (with '\') at line [[#@LINE-4]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-run-redefine.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-run-redefine.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/unterminated-run-redefine.txt
@@ -0,0 +1,9 @@
+# You cannot continue a RUN with a REDEFINE.
+
+# RUN: echo Hello \
+# REDEFINE: %{global:what}=bar
+# RUN: too late to continue
+
+# CHECK: Test has unterminated '{{RUN}}:' directive (with '\') at line [[#@LINE-4]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/ws-only.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/ws-only.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/continuation/ws-only.txt
@@ -0,0 +1,11 @@
+# Surely an empty substitution continuation is an accident, so it's an error.
+
+# DEFINE: %{foo} = foo \
+# DEFINE:  
+#        ^~ whitespace intentional
+# RUN: echo '%{foo}'
+
+#      CHECK: Substitution's continuation is empty
+# CHECK-NEXT: in {{DEFINE}}: directive on test line [[#@LINE-5]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/define-already-by-config.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/define-already-by-config.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/define-already-by-config.txt
@@ -0,0 +1,8 @@
+# DEFINE: %{global:greeting}=Hello
+# RUN: %{global:echo}
+
+#      CHECK: ValueError: Substitution whose pattern contains '%{global:greeting}' is already defined before '{{DEFINE}}:' directive at line [[#@LINE-3]]
+# CHECK-NEXT: Existing pattern: %{global:greeting}
+#  CHECK-NOT: Existing pattern:
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/define-already-by-test.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/define-already-by-test.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/define-already-by-test.txt
@@ -0,0 +1,10 @@
+# DEFINE: %{foo}=bar
+# RUN: echo %{foo}
+# DEFINE: %{foo}=bar
+# RUN: echo %{foo}
+
+#      CHECK: ValueError: Substitution whose pattern contains '%{foo}' is already defined before '{{DEFINE}}:' directive at line [[#@LINE-3]]
+# CHECK-NEXT: Existing pattern: %{foo}
+#  CHECK-NOT: Existing pattern:
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/define-inside-pattern.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/define-inside-pattern.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/define-inside-pattern.txt
@@ -0,0 +1,8 @@
+# DEFINE: %{global:inside} = @
+# RUN: echo '<%{global:inside}>'
+
+#      CHECK: ValueError: Substitution whose pattern contains '%{global:inside}' is already defined before '{{DEFINE}}:' directive at line [[#@LINE-3]]
+# CHECK-NEXT: Existing pattern: <%{global:inside}>
+#  CHECK-NOT: Existing pattern:
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/define-multiple-exact.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/define-multiple-exact.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/define-multiple-exact.txt
@@ -0,0 +1,9 @@
+# DEFINE: %{global:multiple-exact} = @
+# RUN: echo '%{global:multiple-exact}'
+
+#      CHECK: ValueError: Substitution whose pattern contains '%{global:multiple-exact}' is already defined before '{{DEFINE}}:' directive at line [[#@LINE-3]]
+# CHECK-NEXT: Existing pattern: %{global:multiple-exact}
+# CHECK-NEXT: Existing pattern: %{global:multiple-exact}
+#  CHECK-NOT: Existing pattern:
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/define-multiple-once-exact.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/define-multiple-once-exact.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/define-multiple-once-exact.txt
@@ -0,0 +1,9 @@
+# DEFINE: %{global:multiple-once-exact} = @
+# RUN: echo '%{global:multiple-once-exact}'
+
+#      CHECK: ValueError: Substitution whose pattern contains '%{global:multiple-once-exact}' is already defined before '{{DEFINE}}:' directive at line [[#@LINE-3]]
+# CHECK-NEXT: Existing pattern: <%{global:multiple-once-exact}>
+# CHECK-NEXT: Existing pattern: %{global:multiple-once-exact}
+#  CHECK-NOT: Existing pattern:
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/define-prefixes-pattern.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/define-prefixes-pattern.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/define-prefixes-pattern.txt
@@ -0,0 +1,8 @@
+# DEFINE: %{global:prefix} = @
+# RUN: echo '%{global:prefix}(foo)'
+
+#      CHECK: ValueError: Substitution whose pattern contains '%{global:prefix}' is already defined before '{{DEFINE}}:' directive at line [[#@LINE-3]]
+# CHECK-NEXT: Existing pattern: %{global:prefix}\((.*)\)
+#  CHECK-NOT: Existing pattern:
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/define-suffixes-pattern.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/define-suffixes-pattern.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/define-suffixes-pattern.txt
@@ -0,0 +1,8 @@
+# DEFINE: %{global:suffix} = @
+# RUN: echo '@%{global:suffix}'
+
+#      CHECK: ValueError: Substitution whose pattern contains '%{global:suffix}' is already defined before '{{DEFINE}}:' directive at line [[#@LINE-3]]
+# CHECK-NEXT: Existing pattern: @%{global:suffix}
+#  CHECK-NOT: Existing pattern:
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/redefine-inside-pattern.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/redefine-inside-pattern.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/redefine-inside-pattern.txt
@@ -0,0 +1,9 @@
+# REDEFINE: %{global:inside} = @
+# RUN: echo '<%{global:inside}>'
+
+#      CHECK: ValueError: Existing substitution whose pattern contains '%{global:inside}' does not have the pattern specified by '{{REDEFINE}}:' directive at line [[#@LINE-3]]
+# CHECK-NEXT: Expected pattern: %{global:inside}
+# CHECK-NEXT: Existing pattern: <%{global:inside}>
+#  CHECK-NOT: Existing pattern:
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/redefine-multiple-exact.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/redefine-multiple-exact.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/redefine-multiple-exact.txt
@@ -0,0 +1,13 @@
+# It's impossible to multiply define a local substitution, but a lit config file
+# substitution can be multiply defined.  The trouble is we then don't know which
+# definition to redefine locally.
+
+# REDEFINE: %{global:multiple-exact}=foo
+# RUN: echo %{global:multiple-exact}
+
+#      CHECK: ValueError: Multiple substitutions whose patterns contain '%{global:multiple-exact}' are defined before '{{REDEFINE}}:' directive at line [[#@LINE-3]]
+# CHECK-NEXT: Existing pattern: %{global:multiple-exact}
+# CHECK-NEXT: Existing pattern: %{global:multiple-exact}
+#  CHECK-NOT: Existing pattern:
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/redefine-multiple-once-exact.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/redefine-multiple-once-exact.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/redefine-multiple-once-exact.txt
@@ -0,0 +1,12 @@
+# There's only one substitution whose pattern matches exactly, but there's
+# another partial match, and that can lead to confusing expansions.
+
+# REDEFINE: %{global:multiple-once-exact}=foo
+# RUN: echo %{global:multiple-once-exact}
+
+#      CHECK: ValueError: Multiple substitutions whose patterns contain '%{global:multiple-once-exact}' are defined before '{{REDEFINE}}:' directive at line [[#@LINE-3]]
+# CHECK-NEXT: Existing pattern: <%{global:multiple-once-exact}>
+# CHECK-NEXT: Existing pattern: %{global:multiple-once-exact}
+#  CHECK-NOT: Existing pattern:
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/redefine-none.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/redefine-none.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/redefine-none.txt
@@ -0,0 +1,7 @@
+# REDEFINE: %{local}=foo
+# RUN: echo %{local}
+
+#     CHECK: ValueError: No substitution for '%{local}' is defined before '{{REDEFINE}}:' directive at line [[#@LINE-3]]
+# CHECK-NOT: Existing pattern:
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/redefine-prefixes-pattern.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/redefine-prefixes-pattern.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/redefine-prefixes-pattern.txt
@@ -0,0 +1,9 @@
+# REDEFINE: %{global:prefix} = @
+# RUN: echo '%{global:prefix}(foo)'
+
+#      CHECK: ValueError: Existing substitution whose pattern contains '%{global:prefix}' does not have the pattern specified by '{{REDEFINE}}:' directive at line [[#@LINE-3]]
+# CHECK-NEXT: Expected pattern: %{global:prefix}
+# CHECK-NEXT: Existing pattern: %{global:prefix}\((.*)\)
+#  CHECK-NOT: Existing pattern:
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/redefine-suffixes-pattern.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/redefine-suffixes-pattern.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/defined-check/redefine-suffixes-pattern.txt
@@ -0,0 +1,9 @@
+# REDEFINE: %{global:suffix} = @
+# RUN: echo '@%{global:suffix}'
+
+#      CHECK: ValueError: Existing substitution whose pattern contains '%{global:suffix}' does not have the pattern specified by '{{REDEFINE}}:' directive at line [[#@LINE-3]]
+# CHECK-NEXT: Expected pattern: %{global:suffix}
+# CHECK-NEXT: Existing pattern: @%{global:suffix}
+#  CHECK-NOT: Existing pattern:
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/location-range.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/location-range.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/location-range.txt
@@ -0,0 +1,8 @@
+# DEFINE: %{foo}=Hello World
+# DEFINE: %{foo}=Hello \
+# DEFINE:   World
+# RUN: echo '%{foo}'
+
+# CHECK: ValueError: Substitution whose pattern contains '%{foo}' is already defined before '{{DEFINE}}:' directive from line [[#@LINE-4]] to [[#@LINE-3]]
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/errors/no-run.txt b/llvm/utils/lit/tests/Inputs/shtest-define/errors/no-run.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/errors/no-run.txt
@@ -0,0 +1,8 @@
+# DEFINE and REDEFINE are not sufficient.  There must be a RUN.
+
+# DEFINE: %{local:echo}=foo
+# REDEFINE: %{global:echo}=bar
+
+# CHECK: Test has no '{{RUN}}:' line
+
+# CHECK: Unresolved: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/examples/param-subst.txt b/llvm/utils/lit/tests/Inputs/shtest-define/examples/param-subst.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/examples/param-subst.txt
@@ -0,0 +1,34 @@
+; This example originally appeared in TestingGuide.rst except here we've added
+; echo to the clang/FileCheck command line to be executed.
+
+; DEFINE: %{cflags} =
+; DEFINE: %{fcflags} =
+
+; DEFINE: %{check} =                                                           \
+; DEFINE:   echo '                                                             \
+; DEFINE:   %clang_cc1 -verify -fopenmp -fopenmp-version=51 %{cflags}          \
+; DEFINE:              -emit-llvm -o - %s |                                    \
+; DEFINE:     FileCheck %{fcflags} %s                                          \
+; DEFINE:   '
+
+; REDEFINE: %{cflags} = -triple x86_64-apple-darwin10.6.0 -fopenmp-simd
+; REDEFINE: %{fcflags} = -check-prefix=SIMD
+; RUN: %{check}
+; CHECK: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -triple x86_64-apple-darwin10.6.0 -fopenmp-simd -emit-llvm -o - {{.*}} | FileCheck -check-prefix=SIMD {{.*}}
+
+; REDEFINE: %{cflags} = -triple x86_64-unknown-linux-gnu -fopenmp-simd
+; REDEFINE: %{fcflags} = -check-prefix=SIMD
+; RUN: %{check}
+; CHECK: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -triple x86_64-unknown-linux-gnu -fopenmp-simd -emit-llvm -o - {{.*}} | FileCheck -check-prefix=SIMD {{.*}}
+
+; REDEFINE: %{cflags} = -triple x86_64-apple-darwin10.6.0
+; REDEFINE: %{fcflags} = -check-prefix=NO-SIMD
+; RUN: %{check}
+; CHECK: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -triple x86_64-apple-darwin10.6.0 -emit-llvm -o - {{.*}} | FileCheck -check-prefix=NO-SIMD {{.*}}
+
+; REDEFINE: %{cflags} = -triple x86_64-unknown-linux-gnu
+; REDEFINE: %{fcflags} = -check-prefix=NO-SIMD
+; RUN: %{check}
+; CHECK: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -triple x86_64-unknown-linux-gnu -emit-llvm -o - {{.*}} | FileCheck -check-prefix=NO-SIMD {{.*}}
+
+; CHECK: Passed: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/expansion-order.txt b/llvm/utils/lit/tests/Inputs/shtest-define/expansion-order.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/expansion-order.txt
@@ -0,0 +1,41 @@
+# Redefine the %{global:greeting} parameter of %{global:echo} before using it.
+# The necessary expansion order was established in the test suite config
+# (%{global:echo} before %{global:greeting}), and redefining the parameter
+# doesn't change that expansion order.  That order would be reversed if
+# %{global:greeting} were handled as a new substitution, preventing full
+# expansion.
+#
+# REDEFINE: %{global:greeting}=Hello
+# RUN: %{global:echo}
+# CHECK: GLOBAL: Hello World
+
+# We can redefine the test suite config's substitutions multiple times.  Again,
+# the expansion order remains the same (%{global:echo} before %{global:greeting}
+# before %{global:what}) but would be reversed if these were handled as new
+# substitutions, preventing full expansion.
+#
+# REDEFINE: %{global:greeting}=Goodbye %{global:what}
+# REDEFINE: %{global:what}=Sleep
+# RUN: %{global:echo}
+# CHECK: GLOBAL: Goodbye Sleep Sleep
+
+# A new local substitution is prepended to the substitution list so that it can
+# depend on all substitutions that were defined previously, including those from
+# the test suite config.
+#
+# DEFINE: %{local:greeting}=Hey %{global:what}
+# DEFINE: %{local:echo}=echo "LOCAL: %{local:greeting} %{global:what}"
+# RUN: %{local:echo}
+# CHECK: LOCAL: Hey Sleep Sleep
+
+# As for substitutions from the test suite config, redefining local
+# substitutions should not change the expansion order.  Again, the expansion
+# order would be reversed if these were instead handled as new substitutions,
+# preventing full expansion.
+#
+# REDEFINE: %{local:greeting}=So Long %{global:what}
+# REDEFINE: %{global:what}=World
+# RUN: %{local:echo}
+# CHECK: LOCAL: So Long World World
+
+# CHECK: Passed: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/line-number-substitutions.txt b/llvm/utils/lit/tests/Inputs/shtest-define/line-number-substitutions.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/line-number-substitutions.txt
@@ -0,0 +1,32 @@
+# Does it work as expected directly in RUN lines?
+# RUN: echo %(line), %(line-1), %(line+2)
+# CHECK: [[#@LINE-1]], [[#@LINE-2]], [[#@LINE+1]]
+
+# %(line) substitutions refer to the original DEFINE/REDEFINE line not the RUN
+# line they eventually appear within.
+#
+# DEFINE: %{lines} = %(line)
+# RUN: echo '%{lines}'
+# CHECK: [[#@LINE-2]]
+#
+# REDEFINE: %{lines} = %(line),                                                \
+# REDEFINE:            %(line),                                                \
+# REDEFINE:            %(line)
+# RUN: echo '%{lines}'
+# CHECK: [[#@LINE-4]], [[#@LINE-3]], [[#@LINE-2]]
+
+# %(line+N) and %{line-N) should work too.
+#
+# DEFINE: %{lines-rel} = %(line+1),                                            \
+# DEFINE:                %(line),                                              \
+# DEFINE:                %(line-1)
+# RUN: echo '%{lines-rel}'
+# CHECK: [[#@LINE-3]], [[#@LINE-3]], [[#@LINE-3]]
+#
+# REDEFINE: %{lines-rel} = %(line+5),                                          \
+# REDEFINE:                %(line+0),                                          \
+# REDEFINE:                %(line-10)
+# RUN: echo '%{lines-rel}'
+# CHECK: [[#@LINE+1]], [[#@LINE-3]], [[#@LINE-12]]
+
+# CHECK: Passed: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/lit.cfg b/llvm/utils/lit/tests/Inputs/shtest-define/lit.cfg
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/lit.cfg
@@ -0,0 +1,47 @@
+import lit.formats
+config.name = 'shtest-define'
+config.suffixes = ['.txt']
+config.test_format = lit.formats.ShTest()
+config.test_source_root = None
+config.test_exec_root = None
+
+# When config.recursiveExpansionLimit is not specified, it's important to
+# prepend substitutions before substitutions they might now or later (upon a
+# redefinition) depend upon.  For example, %{global:greeting} and %{global:what}
+# act as parameters for %{global:echo}, so we make sure the latter expands
+# before the former.  Moreover, some tests redefine %{global:greeting} in terms
+# of %{global:what}, so we make sure the former expands before the latter.
+# If we always insert at the beginning of the substitution list (as DEFINE
+# does), then the rule is simple: define a substitution before you refer to it.
+config.substitutions.insert(0, ('%{global:what}', 'World'))
+config.substitutions.insert(0, ('%{global:greeting}', ''))
+config.substitutions.insert(0,
+    ('%{global:echo}', "echo GLOBAL: %{global:greeting} %{global:what}"))
+
+# The following substitution definitions are confusing and should be avoided.
+# We define them here so we can test that 'DEFINE:' and 'REDEFINE:' directives
+# guard against the confusion they cause.
+
+# Even though each of '%{global:inside}', '%{global:prefix}', and
+# '%{global:suffix}' is not already the exact pattern of a substitution,
+# 'DEFINE:' and 'REDEFINE:' will refuse to (re)define a substitution with that
+# pattern because it is a substring of one of the following substitution's
+# patterns.
+config.substitutions.insert(0, ('<%{global:inside}>', '<@>'))
+config.substitutions.insert(0, (r'%{global:prefix}\((.*)\)', r'@(\g<1>)'))
+config.substitutions.insert(0, ('@%{global:suffix}', '@@'))
+
+# These cannot be redefined by 'REDEFINE:', which doesn't know which one to
+# redefine.
+config.substitutions.insert(0, ('%{global:multiple-exact}', 'first'))
+config.substitutions.insert(0, ('%{global:multiple-exact}', 'second'))
+
+# Even though '%{global:multiple-once-exact}' is the exact pattern of only one
+# existing substitution, 'REDEFINE:' will refuse to redefine that substitution
+# because that string is a substring of another substitution's pattern.
+config.substitutions.insert(0, ('%{global:multiple-once-exact}', '@'))
+config.substitutions.insert(0, ('<%{global:multiple-once-exact}>', '<@>'))
+
+recur = lit_config.params.get('recur', None)
+if recur:
+  config.recursiveExpansionLimit = int(recur)
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/name-chars.txt b/llvm/utils/lit/tests/Inputs/shtest-define/name-chars.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/name-chars.txt
@@ -0,0 +1,25 @@
+# DEFINE: %{abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789} = ok
+# RUN: echo '%{abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789}'
+# CHECK: ok
+
+# DEFINE: %{FooBar} = ok at %(line)
+# RUN: echo '%{FooBar}'
+# CHECK: ok at [[#@LINE - 2]]
+
+# DEFINE: %{fooBar} = ok at %(line)
+# RUN: echo '%{fooBar}'
+# CHECK: ok at [[#@LINE - 2]]
+
+# DEFINE: %{foo-bar-} = ok at %(line)
+# RUN: echo '%{foo-bar-}'
+# CHECK: ok at [[#@LINE - 2]]
+
+# DEFINE: %{foo:bar:} = ok at %(line)
+# RUN: echo '%{foo:bar:}'
+# CHECK: ok at [[#@LINE - 2]]
+
+# DEFINE: %{_foo_bar_} = ok at %(line)
+# RUN: echo '%{_foo_bar_}'
+# CHECK: ok at [[#@LINE - 2]]
+
+# CHECK: Passed: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/recursiveExpansionLimit.txt b/llvm/utils/lit/tests/Inputs/shtest-define/recursiveExpansionLimit.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/recursiveExpansionLimit.txt
@@ -0,0 +1,12 @@
+# These are defined in the wrong order for non-recursive expansion: %{inner} is
+# defined after it's referenced.
+
+# DEFINE: %{outer}=%{inner}
+# DEFINE: %{inner}=expanded
+
+# RUN: echo '%{outer}'
+
+# CHECK-NON-RECUR:%{inner}
+# CHECK-RECUR:expanded
+
+# CHECK: Passed: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/shared-substs-0.txt b/llvm/utils/lit/tests/Inputs/shtest-define/shared-substs-0.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/shared-substs-0.txt
@@ -0,0 +1,22 @@
+# RUN: echo shared-substs-0.txt
+
+# Make sure we don't see modifications that other shared-substs-*.txt have made
+# to the test suite config's substitutions.
+#
+# RUN: %{global:echo}
+
+# Next, modify substs that would affect the above.  Verify they are set locally.
+#
+# REDEFINE: %{global:what}=LOCAL0:World
+# REDEFINE: %{global:greeting}=LOCAL0:Hello
+# REDEFINE: %{global:echo}=echo LOCAL0: %{global:greeting} %{global:what}
+# RUN: %{global:echo}
+
+# Finally, set a local that other shared-substs-*.txt also set to be sure
+# there's no redefinition complaint because they left it behind.  Verify it is
+# set locally.
+#
+# DEFINE: %{local:echo}=echo LOCAL0: subst
+# RUN: %{local:echo}
+
+# CHECK: Passed: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/shared-substs-1.txt b/llvm/utils/lit/tests/Inputs/shtest-define/shared-substs-1.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/shared-substs-1.txt
@@ -0,0 +1,22 @@
+# RUN: echo shared-substs-1.txt
+
+# Make sure we don't see modifications that other shared-substs-*.txt have made
+# to the test suite config's substitutions.
+#
+# RUN: %{global:echo}
+
+# Next, modify substs that would affect the above.  Verify they are set locally.
+#
+# REDEFINE: %{global:what}=LOCAL1:World
+# REDEFINE: %{global:greeting}=LOCAL1:Hello
+# REDEFINE: %{global:echo}=echo LOCAL1: %{global:greeting} %{global:what}
+# RUN: %{global:echo}
+
+# Finally, set a local that other shared-substs-*.txt also set to be sure
+# there's no redefinition complaint because they left it behind.  Verify it is
+# set locally.
+#
+# DEFINE: %{local:echo}=echo LOCAL1: subst
+# RUN: %{local:echo}
+
+# CHECK: Passed: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/value-equals.txt b/llvm/utils/lit/tests/Inputs/shtest-define/value-equals.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/value-equals.txt
@@ -0,0 +1,22 @@
+# After the initial '=', the value can contain '=' with no special meaning.
+
+# DEFINE: %{equals} = FileCheck -check-prefixes=FOO,BAR
+# RUN: echo '%{equals}'
+# CHECK: FileCheck -check-prefixes=FOO,BAR
+#
+# REDEFINE: %{equals} == == =
+# RUN: echo '%{equals}'
+# CHECK: = == =
+
+# DEFINE: %{continue-equals} = FileCheck -strict-whitespace -match-full-lines \
+# DEFINE:                      -check-prefixes=FOO,BAR
+# RUN: echo '%{continue-equals}'
+# CHECK: FileCheck -strict-whitespace -match-full-lines -check-prefixes=FOO,BAR
+#
+# REDEFINE: %{continue-equals} = FileCheck -input-file=test.txt                \
+# REDEFINE:                      -implicit-check-not=foobar                    \
+# REDEFINE:                      -check-prefixes=FOO,BAR
+# RUN: echo '%{continue-equals}'
+# CHECK: FileCheck -input-file=test.txt -implicit-check-not=foobar -check-prefixes=FOO,BAR
+
+# CHECK: Passed: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/value-escaped.txt b/llvm/utils/lit/tests/Inputs/shtest-define/value-escaped.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/value-escaped.txt
@@ -0,0 +1,13 @@
+# Escape sequences that can appear in python re.sub replacement strings have no
+# special meaning in the value.
+
+# DEFINE: %{escape} = \g<0>\n
+# RUN: echo '%{escape}'
+# CHECK: \g<0>\n
+
+# REDEFINE: %{escape} = \n                                                     \
+# REDEFINE:             \g<param>
+# RUN: echo '%{escape}'
+# CHECK: \n \g<param>
+
+# CHECK: Passed: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-define/ws-and-continuations.txt b/llvm/utils/lit/tests/Inputs/shtest-define/ws-and-continuations.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-define/ws-and-continuations.txt
@@ -0,0 +1,135 @@
+# Empty values are permitted and reasonable, especially when just establishing
+# expansion order.
+#
+# DEFINE: %{empty}=
+# RUN: echo "'%{empty}'"
+# CHECK:''
+#
+# REDEFINE: %{empty}=
+# RUN: echo "'%{empty}'"
+# CHECK:''
+
+# A value consisting only of whitespace is trimmed to the empty string.
+#
+#               v~~ intentional whitespace
+# DEFINE: %{ws}=   
+# RUN: echo "'%{ws}'"
+# CHECK:''
+#
+#                 v intentional whitespace
+# REDEFINE: %{ws}= 
+# RUN: echo "'%{ws}'"
+# CHECK:''
+
+# Whitespace is not required around the name or value.
+#
+# DEFINE:%{no-whitespace}=abc
+# RUN: echo "'%{no-whitespace}'"
+# CHECK:'abc'
+#
+# REDEFINE:%{no-whitespace}=HelloWorld
+# RUN: echo "'%{no-whitespace}'"
+# CHECK:'HelloWorld'
+
+# Whitespace is not required between substitutions in a value.
+#
+# DEFINE: %{adjacent0} = foo
+# DEFINE: %{adjacent1} = bar
+# DEFINE: %{has-adjacent-substs} = %{adjacent0}%{adjacent1}
+# RUN: echo "'%{has-adjacent-substs}'"
+# CHECK:'foobar'
+#
+# REDEFINE: %{has-adjacent-substs} = %{adjacent0}%{adjacent1}%{adjacent0}
+# RUN: echo "'%{has-adjacent-substs}'"
+# CHECK:'foobarfoo'
+
+# Exact whitespace is preserved within the value, but whitespace enclosing the
+# name or value is discarded.  ('%{' and '}' are part of the name, and
+# whitespace in between isn't permitted.)
+#
+#                                       v~~ intentional whitespace
+# DEFINE:   %{whitespace}  =  abc    def   
+# RUN: echo "'%{whitespace}'"
+# CHECK:'abc    def'
+#                                      v intentional whitespace
+# REDEFINE: %{whitespace} = Hello World 
+# RUN: echo "'%{whitespace}'"
+# CHECK:'Hello World'
+
+# Line continuations in the value are permitted and collapse whitespace.
+#
+# DEFINE: %{continue} = abc\
+# DEFINE:def \
+# DEFINE:ghi\
+# DEFINE: jkl \
+# DEFINE: mno  \
+# DEFINE:  pqr 
+#             ^ intentional whitespace
+# RUN: echo "'%{continue}'"
+# CHECK:'abc def ghi jkl mno pqr'
+#
+# REDEFINE: %{continue} =  abc  \
+# REDEFINE: def
+# RUN: echo "'%{continue}'"
+# CHECK:'abc def'
+
+# Whitespace at the end of the line after a '\' is ignored, and it's treated as
+# a line continuation.  Otherwise, the behavior would be hard to understand
+# because it looks like a line continuation.
+#
+#                                   v~~~~~~~~~~~ intentional whitespace
+# DEFINE: %{ws-after-continue}=foo \            
+# DEFINE: bar                      \ 
+#                                   ^ intentional whitespace
+# DEFINE: baz
+# RUN: echo "'%{ws-after-continue}'"
+# CHECK:'foo bar baz'
+#
+#                                     v intentional whitespace
+# REDEFINE: %{ws-after-continue}=foo \ 
+# REDEFINE: bar                      \            
+#                                     ^~~~~~~~~~~~ intentional whitespace
+# REDEFINE: baz
+# RUN: echo "'%{ws-after-continue}'"
+# CHECK:'foo bar baz'
+
+# A line continuation is recognized anywhere.  It should be used only where
+# whitespace is permitted because it reduces to a single space.
+#
+# Directives with at least one non-whitespace character (could be '\') are
+# permitted even if they contribute nothing to the value.  There might be no
+# practical use, but check that it behaves as expected.
+#
+# DEFINE:\
+# DEFINE:%{blank-lines}\
+# DEFINE:\
+# DEFINE:=\
+# DEFINE:\
+# DEFINE:a
+# RUN: echo "'%{blank-lines}'"
+# CHECK:'a'
+#
+# REDEFINE:                  \
+# REDEFINE: %{blank-lines}   \
+# REDEFINE:                  \
+# REDEFINE:                = \
+# REDEFINE:                  \
+# REDEFINE:      a           \
+# REDEFINE:                  \
+# REDEFINE:      b           \
+# REDEFINE:                  \
+# REDEFINE:      c
+# RUN: echo "'%{blank-lines}'"
+# CHECK:'a b c'
+
+# The fourth DEFINE line is deceptive because it looks like a new substitution,
+# but it's actually a continuation of the previous value.
+#
+# DEFINE: %{name}=x
+# DEFINE: %{value}=3
+# DEFINE: %{deceptive-continue}=echo \
+# DEFINE: %{name}=%{value}
+# RUN: %{deceptive-continue}
+# CHECK:x=3
+
+# CHECK:{{ *}}Passed: 1
diff --git a/llvm/utils/lit/tests/Inputs/shtest-shell/continuations.txt b/llvm/utils/lit/tests/Inputs/shtest-shell/continuations.txt
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/shtest-shell/continuations.txt
@@ -0,0 +1,17 @@
+RUN: echo 'foo' \
+RUN:      'bar' >> %t.out
+CHECK: foo bar
+
+RUN: echo 'foo' \
+RUN:      'bar' \
+RUN:      'baz' >> %t.out
+CHECK: foo bar baz
+
+#                 v~~ intentional whitespace
+RUN: echo 'foo'  \   
+RUN:      'bar'  \ 
+#                 ^ intentional whitespace
+RUN:      'baz' >> %t.out
+CHECK: foo bar baz
+
+RUN: FileCheck -match-full-lines -input-file=%t.out %s
diff --git a/llvm/utils/lit/tests/Inputs/testrunner-custom-parsers/test.txt b/llvm/utils/lit/tests/Inputs/testrunner-custom-parsers/test.txt
--- a/llvm/utils/lit/tests/Inputs/testrunner-custom-parsers/test.txt
+++ b/llvm/utils/lit/tests/Inputs/testrunner-custom-parsers/test.txt
@@ -18,5 +18,10 @@
 //
 // MY_BOOL_UNTERMINATED: a \
 //
+// MY_DEFINE: %{name} = value one
+//
+// MY_REDEFINE: %{name} = value \
+// MY_REDEFINE:           two
+//
 // END.
 // MY_LIST: five
diff --git a/llvm/utils/lit/tests/shtest-define.py b/llvm/utils/lit/tests/shtest-define.py
new file mode 100644
--- /dev/null
+++ b/llvm/utils/lit/tests/shtest-define.py
@@ -0,0 +1,167 @@
+# We're using DEFINE/REDEFINE to help us write tests for DEFINE/REDEFINE.
+
+# RUN: echo '-- Available Tests --' > %t.tests.actual.txt
+
+# DEFINE: %{my-inputs} = %{inputs}/shtest-define
+
+# DEFINE: %{test} =
+# DEFINE: %{lit-pre} =
+# DEFINE: %{lit-args} =
+# DEFINE: %{fc-args} =
+# DEFINE: %{run-test} =                                                        \
+# DEFINE:   %{lit-pre} %{lit} -va  %{lit-args} %{my-inputs}/%{test} 2>&1 |     \
+# DEFINE:     FileCheck -match-full-lines %{fc-args} %{my-inputs}/%{test}
+# DEFINE: %{record-test} =                                                     \
+# DEFINE:   echo '  shtest-define :: %{test}' >> %t.tests.actual.txt
+# DEFINE: %{run-and-record-test} = %{run-test} && %{record-test}
+
+# REDEFINE: %{lit-pre} = not
+#
+# REDEFINE: %{test} = errors/assignment/before-name.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/assignment/between-name-equals.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/assignment/braces-empty.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/assignment/braces-with-dot.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/assignment/braces-with-equals.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/assignment/braces-with-newline.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/assignment/braces-with-number.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/assignment/braces-with-ws.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/assignment/empty.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/assignment/no-equals.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/assignment/no-name.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/assignment/ws-only.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/continuation/empty.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/continuation/end-in-double-backslash.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/continuation/unterminated-define-bad-redefine.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/continuation/unterminated-define-continuation.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/continuation/unterminated-define-redefine.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/continuation/unterminated-define-run.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/continuation/unterminated-define.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/continuation/unterminated-redefine-bad-define.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/continuation/unterminated-redefine-continuation.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/continuation/unterminated-redefine-define.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/continuation/unterminated-redefine-run.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/continuation/unterminated-redefine.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/continuation/unterminated-run-define.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/continuation/unterminated-run-redefine.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/continuation/ws-only.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/defined-check/define-already-by-config.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/defined-check/define-already-by-test.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/defined-check/define-inside-pattern.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/defined-check/define-multiple-exact.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/defined-check/define-multiple-once-exact.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/defined-check/define-prefixes-pattern.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/defined-check/define-suffixes-pattern.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/defined-check/redefine-inside-pattern.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/defined-check/redefine-multiple-exact.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/defined-check/redefine-multiple-once-exact.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/defined-check/redefine-none.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/defined-check/redefine-prefixes-pattern.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/defined-check/redefine-suffixes-pattern.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/location-range.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{test} = errors/no-run.txt
+# RUN: %{run-and-record-test}
+#
+# REDEFINE: %{lit-pre} =
+
+# REDEFINE: %{test} = examples/param-subst.txt
+# RUN: %{run-and-record-test}
+
+# REDEFINE: %{test} = expansion-order.txt
+# RUN: %{run-and-record-test}
+
+# REDEFINE: %{test} = line-number-substitutions.txt
+# RUN: %{run-and-record-test}
+
+# REDEFINE: %{test} = name-chars.txt
+# RUN: %{run-and-record-test}
+
+# REDEFINE: %{test} = recursiveExpansionLimit.txt
+#
+# REDEFINE: %{fc-args} = -check-prefix=CHECK-NON-RECUR
+# RUN: %{run-test}
+#
+# REDEFINE: %{lit-args} = -Drecur=2
+# REDEFINE: %{fc-args} = -check-prefix=CHECK-RECUR
+# RUN: %{run-test}
+#
+# RUN: %{record-test}
+# REDEFINE: %{lit-args} =
+# REDEFINE: %{fc-args} =
+
+# Check that per-test changes to substitutions don't affect other tests in the
+# same LIT invocation.
+#
+# RUN: %{lit} -va %{my-inputs}/shared-substs-*.txt 2>&1 |                      \
+# RUN:   FileCheck -check-prefix=SHARED-SUBSTS -match-full-lines %s
+#
+# SHARED-SUBSTS: shared-substs-0.txt
+# SHARED-SUBSTS: GLOBAL: World
+# SHARED-SUBSTS: LOCAL0: LOCAL0:Hello LOCAL0:World
+# SHARED-SUBSTS: LOCAL0: subst
+#
+# SHARED-SUBSTS: shared-substs-1.txt
+# SHARED-SUBSTS: GLOBAL: World
+# SHARED-SUBSTS: LOCAL1: LOCAL1:Hello LOCAL1:World
+# SHARED-SUBSTS: LOCAL1: subst
+#
+# REDEFINE: %{test} = shared-substs-0.txt
+# RUN: %{record-test}
+# REDEFINE: %{test} = shared-substs-1.txt
+# RUN: %{record-test}
+
+# REDEFINE: %{test} = value-equals.txt
+# RUN: %{run-and-record-test}
+
+# REDEFINE: %{test} = value-escaped.txt
+# RUN: %{run-and-record-test}
+
+# REDEFINE: %{fc-args} = -strict-whitespace
+# REDEFINE: %{test} = ws-and-continuations.txt
+# RUN: %{run-and-record-test}
+# REDEFINE: %{fc-args} =
+
+# Make sure we didn't forget to run something.
+#
+# RUN: %{lit} --show-tests %{my-inputs} > %t.tests.expected.txt
+# RUN: diff -u %t.tests.expected.txt %t.tests.actual.txt
diff --git a/llvm/utils/lit/tests/shtest-keyword-parse-errors.py b/llvm/utils/lit/tests/shtest-keyword-parse-errors.py
--- a/llvm/utils/lit/tests/shtest-keyword-parse-errors.py
+++ b/llvm/utils/lit/tests/shtest-keyword-parse-errors.py
@@ -12,4 +12,4 @@
 # CHECK:       {{^}}Test has more than one ALLOW_RETRIES lines{{$}}
 
 # CHECK-LABEL: UNRESOLVED: shtest-keyword-parse-errors :: unterminated-run.txt
-# CHECK:       {{^}}Test has unterminated 'RUN:' lines (with '\'){{$}}
+# CHECK:       {{^}}Test has unterminated 'RUN:' directive (with '\') at line 1{{$}}
diff --git a/llvm/utils/lit/tests/shtest-shell.py b/llvm/utils/lit/tests/shtest-shell.py
--- a/llvm/utils/lit/tests/shtest-shell.py
+++ b/llvm/utils/lit/tests/shtest-shell.py
@@ -42,6 +42,8 @@
 # CHECK: error: command failed with exit status: 127
 # CHECK: ***
 
+# CHECK: PASS: shtest-shell :: continuations.txt
+
 # CHECK: PASS: shtest-shell :: dev-null.txt
 
 # CHECK: FAIL: shtest-shell :: diff-b.txt
diff --git a/llvm/utils/lit/tests/unit/TestRunner.py b/llvm/utils/lit/tests/unit/TestRunner.py
--- a/llvm/utils/lit/tests/unit/TestRunner.py
+++ b/llvm/utils/lit/tests/unit/TestRunner.py
@@ -62,7 +62,8 @@
             IntegratedTestKeywordParser("MY_RUN:", ParserKind.COMMAND),
             IntegratedTestKeywordParser("MY_CUSTOM:", ParserKind.CUSTOM,
                                         custom_parse),
-
+            IntegratedTestKeywordParser("MY_DEFINE:", ParserKind.DEFINE),
+            IntegratedTestKeywordParser("MY_REDEFINE:", ParserKind.REDEFINE),
         ]
 
     @staticmethod
@@ -105,8 +106,10 @@
         cmd_parser = self.get_parser(parsers, 'MY_RUN:')
         value = cmd_parser.getValue()
         self.assertEqual(len(value), 2)  # there are only two run lines
-        self.assertEqual(value[0].strip(), "%dbg(MY_RUN: at line 4)  baz")
-        self.assertEqual(value[1].strip(), "%dbg(MY_RUN: at line 7)  foo  bar")
+        self.assertEqual(value[0].command.strip(),
+                         "%dbg(MY_RUN: at line 4)  baz")
+        self.assertEqual(value[1].command.strip(),
+                         "%dbg(MY_RUN: at line 7)  foo  bar")
 
     def test_boolean(self):
         parsers = self.make_parsers()
@@ -164,6 +167,26 @@
         value = custom_parser.getValue()
         self.assertEqual(value, ['a', 'b', 'c'])
 
+    def test_defines(self):
+        parsers = self.make_parsers()
+        self.parse_test(parsers)
+        cmd_parser = self.get_parser(parsers, 'MY_DEFINE:')
+        value = cmd_parser.getValue()
+        self.assertEqual(len(value), 1) # there's only one MY_DEFINE directive
+        self.assertEqual(value[0].new_subst, True)
+        self.assertEqual(value[0].name, '%{name}')
+        self.assertEqual(value[0].value, 'value one')
+
+    def test_redefines(self):
+        parsers = self.make_parsers()
+        self.parse_test(parsers)
+        cmd_parser = self.get_parser(parsers, 'MY_REDEFINE:')
+        value = cmd_parser.getValue()
+        self.assertEqual(len(value), 1) # there's only one MY_REDEFINE directive
+        self.assertEqual(value[0].new_subst, False)
+        self.assertEqual(value[0].name, '%{name}')
+        self.assertEqual(value[0].value, 'value two')
+
     def test_bad_keywords(self):
         def custom_parse(line_number, line, output):
             return output