summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorMarco Antognini <marco.antognini@arm.com>2019-07-22 09:39:13 +0000
committerMarco Antognini <marco.antognini@arm.com>2019-07-22 09:39:13 +0000
commit88559637641e993895337e1047a0bd787fecc647 (patch)
tree639b057daba633db68b8fa4d34a957913786c64f /clang/test
parent6771a89fa01ffb1ea8702d7b07e259750ae62f1c (diff)
downloadbcm5719-llvm-88559637641e993895337e1047a0bd787fecc647.tar.gz
bcm5719-llvm-88559637641e993895337e1047a0bd787fecc647.zip
[OpenCL] Improve destructor support in C++ for OpenCL
This re-applies r366422 with a fix for Bug PR42665 and a new regression test. llvm-svn: 366670
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/CodeGenCXX/PR42665.cpp61
-rw-r--r--clang/test/CodeGenOpenCLCXX/addrspace-ctor.cl14
-rw-r--r--clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl59
3 files changed, 120 insertions, 14 deletions
diff --git a/clang/test/CodeGenCXX/PR42665.cpp b/clang/test/CodeGenCXX/PR42665.cpp
new file mode 100644
index 00000000000..4a460cfa107
--- /dev/null
+++ b/clang/test/CodeGenCXX/PR42665.cpp
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -std=c++17 -O0 %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -std=c++17 -O0 %s -o - | FileCheck %s
+
+// Minimal reproducer for PR42665.
+
+struct Foo {
+ Foo() = default;
+ virtual ~Foo() = default;
+};
+
+template <typename Deleter>
+struct Pair {
+ Foo first;
+ Deleter second;
+};
+
+template <typename Deleter>
+Pair(Foo, Deleter) -> Pair<Deleter>;
+
+template <typename T>
+void deleter(T& t) { t.~T(); }
+
+auto make_pair() {
+ return Pair{ Foo(), deleter<Foo> };
+}
+
+void foobar() {
+ auto p = make_pair();
+ auto& f = p.first;
+ auto& d = p.second;
+ d(f); // Invoke virtual destructor of Foo through d.
+} // p's destructor is invoked.
+
+// Regexes are used to handle both kind of mangling.
+//
+// CHECK-LABEL: define linkonce_odr{{( dso_local)?}} void @{{.*deleter.*Foo.*}}(%struct.Foo* dereferenceable({{[0-9]+}})
+// CHECK-SAME: [[T:%.*]])
+// CHECK: [[T_ADDR:%.*]] = alloca %struct.Foo*
+// CHECK: store %struct.Foo* [[T]], %struct.Foo** [[T_ADDR]]
+// CHECK: [[R0:%.*]] = load %struct.Foo*, %struct.Foo** [[T_ADDR]]
+// CHECK: [[R1:%.*]] = bitcast %struct.Foo* [[R0]] to [[TYPE:.*struct\.Foo.*]]***
+// CHECK: [[VTABLE:%.*]] = load [[TYPE]]**, [[TYPE]]*** [[R1]]
+// CHECK: [[VFUN:%.*]] = getelementptr inbounds [[TYPE]]*, [[TYPE]]** [[VTABLE]], i64 0
+// CHECK: [[DTOR:%.*]] = load [[TYPE]]*, [[TYPE]]** [[VFUN]]
+// CHECK: call {{(void|i8\*)}} [[DTOR]](%struct.Foo* [[R0]]
+//
+// CHECK-LABEL: define{{( dso_local)?}} void @{{.*foobar.*}}()
+// CHECK: [[P:%.*]] = alloca %struct.Pair
+// CHECK: [[F:%.*]] = alloca %struct.Foo*
+// CHECK: [[D:%.*]] = alloca [[TYPE:void \(%struct.Foo\*\)]]**
+// CHECK: call void @{{.*make_pair.*}}(%struct.Pair* sret [[P]])
+// CHECK: [[FIRST:%.*]] = getelementptr inbounds %struct.Pair, %struct.Pair* [[P]], i32 0, i32 0
+// CHECK: store %struct.Foo* [[FIRST]], %struct.Foo** [[F]]
+// CHECK: [[SECOND:%.*]] = getelementptr inbounds %struct.Pair, %struct.Pair* [[P]], i32 0, i32 1
+// CHECK: store void (%struct.Foo*)** [[SECOND]], [[TYPE]]*** [[D]]
+// CHECK: [[R0:%.*]] = load [[TYPE]]**, [[TYPE]]*** [[D]]
+// CHECK: [[R1:%.*]] = load [[TYPE]]*, [[TYPE]]** [[R0]]
+// CHECK: [[R2:%.*]] = load %struct.Foo*, %struct.Foo** [[F]]
+// CHECK: call void [[R1]](%struct.Foo* dereferenceable({{[0-9]+}}) [[R2]])
+// CHECK: call void @{{.*Pair.*Foo.*}}(%struct.Pair* [[P]])
+
diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-ctor.cl b/clang/test/CodeGenOpenCLCXX/addrspace-ctor.cl
deleted file mode 100644
index 42c2e6e9077..00000000000
--- a/clang/test/CodeGenOpenCLCXX/addrspace-ctor.cl
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s
-
-struct MyType {
- MyType(int i) : i(i) {}
- MyType(int i) __constant : i(i) {}
- int i;
-};
-
-//CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const1, i32 1)
-__constant MyType const1 = 1;
-//CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const2, i32 2)
-__constant MyType const2(2);
-//CHECK: call void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* addrspacecast (%struct.MyType addrspace(1)* @glob to %struct.MyType addrspace(4)*), i32 1)
-MyType glob(1);
diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl b/clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl
new file mode 100644
index 00000000000..21ba1ca251d
--- /dev/null
+++ b/clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s --check-prefix=CHECK-DEFINITIONS
+
+// This test ensures the proper address spaces and address space cast are used
+// for constructors, member functions and destructors.
+// See also atexit.cl and global_init.cl for other specific tests.
+
+// CHECK: %struct.MyType = type { i32 }
+struct MyType {
+ MyType(int i) : i(i) {}
+ MyType(int i) __constant : i(i) {}
+ ~MyType() {}
+ ~MyType() __constant {}
+ int bar() { return i + 2; }
+ int bar() __constant { return i + 1; }
+ int i;
+};
+
+// CHECK: @const1 = addrspace(2) global %struct.MyType zeroinitializer
+__constant MyType const1 = 1;
+// CHECK: @const2 = addrspace(2) global %struct.MyType zeroinitializer
+__constant MyType const2(2);
+// CHECK: @glob = addrspace(1) global %struct.MyType zeroinitializer
+MyType glob(1);
+
+// CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const1, i32 1)
+// CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const2, i32 2)
+// CHECK: call void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* addrspacecast (%struct.MyType addrspace(1)* @glob to %struct.MyType addrspace(4)*), i32 1)
+
+// CHECK-LABEL: define spir_kernel void @fooGlobal()
+kernel void fooGlobal() {
+ // CHECK: call i32 @_ZNU3AS46MyType3barEv(%struct.MyType addrspace(4)* addrspacecast (%struct.MyType addrspace(1)* @glob to %struct.MyType addrspace(4)*))
+ glob.bar();
+ // CHECK: call i32 @_ZNU3AS26MyType3barEv(%struct.MyType addrspace(2)* @const1)
+ const1.bar();
+ // CHECK: call void @_ZNU3AS26MyTypeD1Ev(%struct.MyType addrspace(2)* @const1)
+ const1.~MyType();
+}
+
+// CHECK-LABEL: define spir_kernel void @fooLocal()
+kernel void fooLocal() {
+ // CHECK: [[VAR:%.*]] = alloca %struct.MyType
+ // CHECK: [[REG:%.*]] = addrspacecast %struct.MyType* [[VAR]] to %struct.MyType addrspace(4)*
+ // CHECK: call void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* [[REG]], i32 3)
+ MyType myLocal(3);
+ // CHECK: [[REG:%.*]] = addrspacecast %struct.MyType* [[VAR]] to %struct.MyType addrspace(4)*
+ // CHECK: call i32 @_ZNU3AS46MyType3barEv(%struct.MyType addrspace(4)* [[REG]])
+ myLocal.bar();
+ // CHECK: [[REG:%.*]] = addrspacecast %struct.MyType* [[VAR]] to %struct.MyType addrspace(4)*
+ // CHECK: call void @_ZNU3AS46MyTypeD1Ev(%struct.MyType addrspace(4)* [[REG]])
+}
+
+// Ensure all members are defined for all the required address spaces.
+// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* %this, i32 %i)
+// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* %this, i32 %i)
+// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS26MyTypeD1Ev(%struct.MyType addrspace(2)* %this)
+// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS46MyTypeD1Ev(%struct.MyType addrspace(4)* %this)
+// CHECK-DEFINITIONS-DAG: define linkonce_odr i32 @_ZNU3AS26MyType3barEv(%struct.MyType addrspace(2)* %this)
+// CHECK-DEFINITIONS-DAG: define linkonce_odr i32 @_ZNU3AS46MyType3barEv(%struct.MyType addrspace(4)* %this)
OpenPOWER on IntegriCloud