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 %{%}`` is optional and treated like ``%else %{%}`` if not present. +``%(line)``, ``%(line+)``, ``%(line-)`` + + 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+)``, ``%(line-)`` - 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+)``, and + ``%(line-)``. +- 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 +# RUN: echo '%{escape}' +# CHECK: \n \g + +# 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