
This updates the array initialization loop to use a do..while loop rather than a fully serialized initialization. It also allows the initialization of destructed objects when exception handling is not enabled. Array initialization when exception handling is enabled remains unimplemented, but more precise messages are now emitted.
157 lines
7.8 KiB
C++
157 lines
7.8 KiB
C++
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-cir -mno-constructor-aliases %s -o %t.cir
|
|
// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
|
|
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -mno-constructor-aliases -o %t-cir.ll
|
|
// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
|
|
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -mno-constructor-aliases -o %t.ll
|
|
// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
|
|
|
|
void some_function() noexcept;
|
|
|
|
struct out_of_line_destructor {
|
|
int prevent_tail_padding_reuse;
|
|
~out_of_line_destructor();
|
|
};
|
|
|
|
out_of_line_destructor::~out_of_line_destructor() {
|
|
some_function();
|
|
}
|
|
|
|
// CIR: !rec_out_of_line_destructor = !cir.record<struct "out_of_line_destructor" {!s32i}>
|
|
|
|
// CIR: cir.func dso_local @_ZN22out_of_line_destructorD2Ev(%{{.+}}: !cir.ptr<!rec_out_of_line_destructor>
|
|
// CIR: cir.call @_Z13some_functionv() nothrow : () -> ()
|
|
// CIR: cir.return
|
|
|
|
// LLVM: define dso_local void @_ZN22out_of_line_destructorD2Ev(ptr %{{.+}})
|
|
// LLVM: call void @_Z13some_functionv()
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define dso_local void @_ZN22out_of_line_destructorD2Ev(ptr {{.*}}%{{.+}})
|
|
// OGCG: call void @_Z13some_functionv()
|
|
// OGCG: ret void
|
|
|
|
// CIR: cir.func dso_local @_ZN22out_of_line_destructorD1Ev(%{{.+}}: !cir.ptr<!rec_out_of_line_destructor>
|
|
// CIR: cir.call @_ZN22out_of_line_destructorD2Ev(%{{.*}}) nothrow : (!cir.ptr<!rec_out_of_line_destructor>)
|
|
// CIR: cir.return
|
|
|
|
// LLVM: define dso_local void @_ZN22out_of_line_destructorD1Ev(ptr %{{.+}})
|
|
// LLVM: call void @_ZN22out_of_line_destructorD2Ev
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define dso_local void @_ZN22out_of_line_destructorD1Ev(ptr {{.*}}%{{.+}})
|
|
// OGCG: call void @_ZN22out_of_line_destructorD2Ev
|
|
// OGCG: ret void
|
|
|
|
struct inline_destructor {
|
|
int prevent_tail_padding_reuse;
|
|
~inline_destructor() noexcept(false) {
|
|
some_function();
|
|
}
|
|
};
|
|
|
|
// This inline destructor is not odr-used in this TU.
|
|
// Make sure we don't emit a definition
|
|
|
|
// CIR-NOT: cir.func {{.*}}inline_destructor{{.*}}
|
|
// LLVM-NOT: define {{.*}}inline_destructor{{.*}}
|
|
// OGCG-NOT: define {{.*}}inline_destructor{{.*}}
|
|
|
|
struct array_element {~array_element();};
|
|
void test_array_destructor() {
|
|
array_element arr[5]{};
|
|
}
|
|
|
|
// CIR: cir.func dso_local @_Z21test_array_destructorv()
|
|
// CIR: %[[ARR:.*]] = cir.alloca !cir.array<!rec_array_element x 5>, !cir.ptr<!cir.array<!rec_array_element x 5>>, ["arr", init]
|
|
// CIR: %[[ARR_PTR:.*]] = cir.alloca !cir.ptr<!rec_array_element>, !cir.ptr<!cir.ptr<!rec_array_element>>, ["arrayinit.temp", init]
|
|
// CIR: %[[BEGIN:.*]] = cir.cast(array_to_ptrdecay, %[[ARR]] : !cir.ptr<!cir.array<!rec_array_element x 5>>)
|
|
// CIR: cir.store{{.*}} %[[BEGIN]], %[[ARR_PTR]]
|
|
// CIR: %[[FIVE:.*]] = cir.const #cir.int<5> : !s64i
|
|
// CIR: %[[ARR_END:.*]] = cir.ptr_stride(%[[BEGIN]] : !cir.ptr<!rec_array_element>, %[[FIVE]] : !s64i)
|
|
// CIR: cir.do {
|
|
// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]]
|
|
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i
|
|
// CIR: %[[ARR_NEXT:.*]] = cir.ptr_stride(%[[ARR_CUR]] : !cir.ptr<!rec_array_element>, %[[ONE]] : !s64i)
|
|
// CIR: cir.store{{.*}} %[[ARR_NEXT]], %[[ARR_PTR]] : !cir.ptr<!rec_array_element>, !cir.ptr<!cir.ptr<!rec_array_element>>
|
|
// CIR: cir.yield
|
|
// CIR: } while {
|
|
// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]]
|
|
// CIR: %[[CMP:.*]] = cir.cmp(ne, %[[ARR_CUR]], %[[ARR_END]])
|
|
// CIR: cir.condition(%[[CMP]])
|
|
// CIR: }
|
|
// CIR: %[[FOUR:.*]] = cir.const #cir.int<4> : !u64i
|
|
// CIR: %[[BEGIN:.*]] = cir.cast(array_to_ptrdecay, %[[ARR]] : !cir.ptr<!cir.array<!rec_array_element x 5>>)
|
|
// CIR: %[[END:.*]] = cir.ptr_stride(%[[BEGIN]] : !cir.ptr<!rec_array_element>, %[[FOUR]] : !u64i)
|
|
// CIR: %[[ARR_PTR:.*]] = cir.alloca !cir.ptr<!rec_array_element>, !cir.ptr<!cir.ptr<!rec_array_element>>, ["__array_idx"]
|
|
// CIR: cir.store %[[END]], %[[ARR_PTR]]
|
|
// CIR: cir.do {
|
|
// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]]
|
|
// CIR: cir.call @_ZN13array_elementD1Ev(%[[ARR_CUR]]) nothrow : (!cir.ptr<!rec_array_element>) -> ()
|
|
// CIR: %[[NEG_ONE:.*]] = cir.const #cir.int<-1> : !s64i
|
|
// CIR: %[[ARR_NEXT:.*]] = cir.ptr_stride(%[[ARR_CUR]] : !cir.ptr<!rec_array_element>, %[[NEG_ONE]] : !s64i)
|
|
// CIR: cir.store %[[ARR_NEXT]], %[[ARR_PTR]]
|
|
// CIR: cir.yield
|
|
// CIR: } while {
|
|
// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]]
|
|
// CIR: %[[CMP:.*]] = cir.cmp(ne, %[[ARR_CUR]], %[[BEGIN]])
|
|
// CIR: cir.condition(%[[CMP]])
|
|
// CIR: }
|
|
|
|
// LLVM: define{{.*}} void @_Z21test_array_destructorv()
|
|
// LLVM: %[[ARR:.*]] = alloca [5 x %struct.array_element]
|
|
// LLVM: %[[TMP:.*]] = alloca ptr
|
|
// LLVM: %[[ARR_PTR:.*]] = getelementptr %struct.array_element, ptr %[[ARR]], i32 0
|
|
// LLVM: store ptr %[[ARR_PTR]], ptr %[[TMP]]
|
|
// LLVM: %[[END_PTR:.*]] = getelementptr %struct.array_element, ptr %[[ARR_PTR]], i64 5
|
|
// LLVM: br label %[[INIT_LOOP_BODY:.*]]
|
|
// LLVM: [[INIT_LOOP_NEXT:.*]]:
|
|
// LLVM: %[[CUR:.*]] = load ptr, ptr %[[TMP]]
|
|
// LLVM: %[[CMP:.*]] = icmp ne ptr %[[CUR]], %[[END_PTR]]
|
|
// LLVM: br i1 %[[CMP]], label %[[INIT_LOOP_BODY]], label %[[INIT_LOOP_END:.*]]
|
|
// LLVM: [[INIT_LOOP_BODY]]:
|
|
// LLVM: %[[CUR:.*]] = load ptr, ptr %[[TMP]]
|
|
// LLVM: %[[NEXT:.*]] = getelementptr %struct.array_element, ptr %[[CUR]], i64 1
|
|
// LLVM: store ptr %[[NEXT]], ptr %[[TMP]]
|
|
// LLVM: br label %[[INIT_LOOP_NEXT:.*]]
|
|
// LLVM: [[INIT_LOOP_END]]:
|
|
// LLVM: %[[ARR_BEGIN:.*]] = getelementptr %struct.array_element, ptr %[[ARR]], i32 0
|
|
// LLVM: %[[ARR_END:.*]] = getelementptr %struct.array_element, ptr %[[ARR_BEGIN]], i64 4
|
|
// LLVM: %[[ARR_CUR:.*]] = alloca ptr
|
|
// LLVM: store ptr %[[ARR_END]], ptr %[[ARR_CUR]]
|
|
// LLVM: br label %[[DESTROY_LOOP_BODY:.*]]
|
|
// LLVM: [[DESTROY_LOOP_NEXT:.*]]:
|
|
// LLVM: %[[CUR:.*]] = load ptr, ptr %[[ARR_CUR]]
|
|
// LLVM: %[[CMP:.*]] = icmp ne ptr %[[CUR]], %[[ARR_BEGIN]]
|
|
// LLVM: br i1 %[[CMP]], label %[[DESTROY_LOOP_BODY]], label %[[DESTROY_LOOP_END:.*]]
|
|
// LLVM: [[DESTROY_LOOP_BODY]]:
|
|
// LLVM: %[[CUR:.*]] = load ptr, ptr %[[ARR_CUR]]
|
|
// LLVM: call void @_ZN13array_elementD1Ev(ptr %[[CUR]])
|
|
// LLVM: %[[PREV:.*]] = getelementptr %struct.array_element, ptr %[[CUR]], i64 -1
|
|
// LLVM: store ptr %[[PREV]], ptr %[[ARR_CUR]]
|
|
// LLVM: br label %[[DESTROY_LOOP_NEXT]]
|
|
// LLVM: [[DESTROY_LOOP_END]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z21test_array_destructorv()
|
|
// OGCG: entry:
|
|
// OGCG: %[[ARR:.*]] = alloca [5 x %struct.array_element]
|
|
// OGCG: %[[ARRAYINIT_END:.*]] = getelementptr inbounds %struct.array_element, ptr %[[ARR]], i64 5
|
|
// OGCG: br label %[[INIT_LOOP_BODY:.*]]
|
|
// OGCG: [[INIT_LOOP_BODY]]:
|
|
// OGCG: %[[CUR:.*]] = phi ptr [ %[[ARR]], %entry ], [ %[[NEXT:.*]], %[[INIT_LOOP_BODY]] ]
|
|
// OGCG: %[[NEXT]] = getelementptr inbounds %struct.array_element, ptr %[[CUR]], i64 1
|
|
// OGCG: %[[CMP:.*]] = icmp eq ptr %[[NEXT]], %[[ARRAYINIT_END]]
|
|
// OGCG: br i1 %[[CMP]], label %[[INIT_LOOP_END:.*]], label %[[INIT_LOOP_BODY]]
|
|
// OGCG: [[INIT_LOOP_END:.*]]:
|
|
// OGCG: %[[BEGIN:.*]] = getelementptr inbounds [5 x %struct.array_element], ptr %[[ARR]], i32 0, i32 0
|
|
// OGCG: %[[END:.*]] = getelementptr inbounds %struct.array_element, ptr %[[BEGIN]], i64 5
|
|
// OGCG: br label %[[DESTROY_LOOP_BODY:.*]]
|
|
// OGCG: [[DESTROY_LOOP_BODY:.*]]:
|
|
// OGCG: %[[CUR:.*]] = phi ptr [ %[[END]], %[[INIT_LOOP_END]] ], [ %[[PREV:.*]], %[[DESTROY_LOOP_BODY]] ]
|
|
// OGCG: %[[PREV]] = getelementptr inbounds %struct.array_element, ptr %[[CUR]], i64 -1
|
|
// OGCG: call void @_ZN13array_elementD1Ev(ptr {{.*}} %[[PREV]])
|
|
// OGCG: %[[CMP:.*]] = icmp eq ptr %[[PREV]], %[[BEGIN]]
|
|
// OGCG: br i1 %[[CMP]], label %[[DESTROY_LOOP_END:.*]], label %[[DESTROY_LOOP_BODY]]
|
|
// OGCG: [[DESTROY_LOOP_END:.*]]:
|
|
// OGCG: ret void
|