From 28412d1800e391c5ba8e7607bb15c74b106d581b Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl@gmail.com>
Date: Wed, 21 Sep 2022 11:32:05 -0400
Subject: [PATCH] [lit] Implement DEFINE and REDEFINE directives

These directives define per-test lit substitutions.  The concept was
discussed at
<https://discourse.llvm.org/t/iterating-lit-run-lines/62596/10>.

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:

```
// DEFINE: %{cflags} =
// DEFINE: %{fcflags} =

// DEFINE: %{check} = %clang_cc1 %{cflags} -emit-llvm -o - %s | \
// DEFINE:            FileCheck %{fcflags} %s
```

The following directives then redefine the parameters before each use
of `%{check}`:

```
// REDEFINE: %{cflags} = -foo
// REDEFINE: %{fcflags} = -check-prefix=FOO
// RUN: %{check}

// REDEFINE: %{cflags} = -bar
// REDEFINE: %{fcflags} = -check-prefix=BAR
// RUN: %{check}
```

Of course, `%{check}` would typically be more elaborate, increasing
the benefit of the reuse.

One issue is that the strings `DEFINE:` and `REDEFINE:` already appear
in 5 tests.  This patch adjusts those tests not to use those strings.
Our prediction is that, in the vast majority of cases, if a test
author mistakenly uses one of those strings for another purpose, the
text appearing after the string will not happen to have the syntax
required for these directives.  Thus, the test author will discover
the mistake immediately when lit reports the syntax error.

This patch also expands the documentation on existing lit substitution
behavior.

Reviewed By: jhenderson, MaskRay, awarzynski

Differential Revision: https://reviews.llvm.org/D132513
---
 clang/test/CodeGen/attr-noundef.cpp     | 60 ++++++++++++-------------
 clang/test/CodeGen/indirect-noundef.cpp |  4 +-
 clang/test/Preprocessor/init.c          | 12 ++---
 3 files changed, 38 insertions(+), 38 deletions(-)

diff --git a/clang/test/CodeGen/attr-noundef.cpp b/clang/test/CodeGen/attr-noundef.cpp
index f0570a5390a2..ab167281817e 100644
--- a/clang/test/CodeGen/attr-noundef.cpp
+++ b/clang/test/CodeGen/attr-noundef.cpp
@@ -15,10 +15,10 @@ struct Trivial {
 };
 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 @@ struct NoCopy {
 };
 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 @@ union Trivial {
 };
 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 @@ union NoCopy {
 };
 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 @@ i32x3 ret_vec() {
 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 @@ void pass_large_BitInt(_BitInt(127) e) {
 }
 
 // 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
index 0f63daac044c..1d82aa60ad1e 100644
--- a/clang/test/CodeGen/indirect-noundef.cpp
+++ b/clang/test/CodeGen/indirect-noundef.cpp
@@ -13,9 +13,9 @@ int (*indirect_callee_int_ptr)(int);
 // 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
index 028f3448f8bd..8e3c87e7675f 100644
--- 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
