blob: d8ac4361bb5387ddd3857baf4839ebc05f7165f5 [file] [log] [blame] [edit]
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -fclangir -mconstructor-aliases -emit-cir %s -o %t.cir
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -fclangir -mconstructor-aliases -emit-llvm %s -o %t-cir.ll
// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -mconstructor-aliases -emit-llvm %s -o %t.ll
// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
typedef __typeof(sizeof(int)) size_t;
struct SizedDelete {
void operator delete(void*, size_t);
int member;
};
void test_sized_delete(SizedDelete *x) {
delete x;
}
// SizedDelete::operator delete(void*, unsigned long)
// CIR: cir.func private @_ZN11SizedDeletedlEPvm(!cir.ptr<!void>, !u64i)
// LLVM: declare void @_ZN11SizedDeletedlEPvm(ptr, i64)
// CIR: cir.func dso_local @_Z17test_sized_deleteP11SizedDelete
// CIR: %[[X:.*]] = cir.load{{.*}} %{{.*}}
// CIR: %[[X_CAST:.*]] = cir.cast bitcast %[[X]] : !cir.ptr<!rec_SizedDelete> -> !cir.ptr<!void>
// CIR: %[[OBJ_SIZE:.*]] = cir.const #cir.int<4> : !u64i
// CIR: cir.call @_ZN11SizedDeletedlEPvm(%[[X_CAST]], %[[OBJ_SIZE]]) nothrow : (!cir.ptr<!void>, !u64i) -> ()
// LLVM: define dso_local void @_Z17test_sized_deleteP11SizedDelete
// LLVM: %[[X:.*]] = load ptr, ptr %{{.*}}
// LLVM: call void @_ZN11SizedDeletedlEPvm(ptr %[[X]], i64 4)
// OGCG: define dso_local void @_Z17test_sized_deleteP11SizedDelete
// OGCG: %[[X:.*]] = load ptr, ptr %{{.*}}
// OGCG: %[[ISNULL:.*]] = icmp eq ptr %[[X]], null
// OGCG: br i1 %[[ISNULL]], label %{{.*}}, label %[[DELETE_NOTNULL:.*]]
// OGCG: [[DELETE_NOTNULL]]:
// OGCG: call void @_ZN11SizedDeletedlEPvm(ptr noundef %[[X]], i64 noundef 4)
// This function is declared below the call in OGCG.
// OGCG: declare void @_ZN11SizedDeletedlEPvm(ptr noundef, i64 noundef)
struct Contents {
~Contents() {}
};
struct Container {
Contents *contents;
~Container();
};
Container::~Container() { delete contents; }
// Contents::~Contents()
// CIR: cir.func comdat linkonce_odr @_ZN8ContentsD2Ev
// LLVM: define linkonce_odr void @_ZN8ContentsD2Ev
// operator delete(void*, unsigned long)
// CIR: cir.func private @_ZdlPvm(!cir.ptr<!void>, !u64i)
// LLVM: declare void @_ZdlPvm(ptr, i64)
// Container::~Container()
// CIR: cir.func dso_local @_ZN9ContainerD2Ev
// CIR: %[[THIS:.*]] = cir.load %{{.*}}
// CIR: %[[CONTENTS_PTR_ADDR:.*]] = cir.get_member %[[THIS]][0] {name = "contents"} : !cir.ptr<!rec_Container> -> !cir.ptr<!cir.ptr<!rec_Contents>>
// CIR: %[[CONTENTS_PTR:.*]] = cir.load{{.*}} %[[CONTENTS_PTR_ADDR]]
// CIR: cir.call @_ZN8ContentsD2Ev(%[[CONTENTS_PTR]]) nothrow : (!cir.ptr<!rec_Contents>) -> ()
// CIR: %[[CONTENTS_CAST:.*]] = cir.cast bitcast %[[CONTENTS_PTR]] : !cir.ptr<!rec_Contents> -> !cir.ptr<!void>
// CIR: %[[OBJ_SIZE:.*]] = cir.const #cir.int<1> : !u64i
// CIR: cir.call @_ZdlPvm(%[[CONTENTS_CAST]], %[[OBJ_SIZE]]) nothrow : (!cir.ptr<!void>, !u64i) -> ()
// LLVM: define dso_local void @_ZN9ContainerD2Ev
// LLVM: %[[THIS:.*]] = load ptr, ptr %{{.*}}
// LLVM: %[[CONTENTS_PTR_ADDR:.*]] = getelementptr %struct.Container, ptr %[[THIS]], i32 0, i32 0
// LLVM: %[[CONTENTS_PTR:.*]] = load ptr, ptr %[[CONTENTS_PTR_ADDR]]
// LLVM: call void @_ZN8ContentsD2Ev(ptr %[[CONTENTS_PTR]])
// LLVM: call void @_ZdlPvm(ptr %[[CONTENTS_PTR]], i64 1)
// OGCG: define dso_local void @_ZN9ContainerD2Ev
// OGCG: %[[THIS:.*]] = load ptr, ptr %{{.*}}
// OGCG: %[[CONTENTS:.*]] = getelementptr inbounds nuw %struct.Container, ptr %[[THIS]], i32 0, i32 0
// OGCG: %[[CONTENTS_PTR:.*]] = load ptr, ptr %[[CONTENTS]]
// OGCG: %[[ISNULL:.*]] = icmp eq ptr %[[CONTENTS_PTR]], null
// OGCG: br i1 %[[ISNULL]], label %{{.*}}, label %[[DELETE_NOTNULL:.*]]
// OGCG: [[DELETE_NOTNULL]]:
// OGCG: call void @_ZN8ContentsD2Ev(ptr noundef nonnull align 1 dereferenceable(1) %[[CONTENTS_PTR]])
// OGCG: call void @_ZdlPvm(ptr noundef %[[CONTENTS_PTR]], i64 noundef 1)
// These functions are declared/defined below the calls in OGCG.
// OGCG: define linkonce_odr void @_ZN8ContentsD2Ev
// OGCG: declare void @_ZdlPvm(ptr noundef, i64 noundef)
struct StructWithVirtualDestructor {
virtual ~StructWithVirtualDestructor();
};
void destroy(StructWithVirtualDestructor *x) {
delete x;
}
// CIR: cir.func {{.*}} @_Z7destroyP27StructWithVirtualDestructor(%[[X_ARG:.*]]: !cir.ptr<!rec_StructWithVirtualDestructor> {{.*}})
// CIR: %[[X_ADDR:.*]] = cir.alloca !cir.ptr<!rec_StructWithVirtualDestructor>
// CIR: cir.store %[[X_ARG]], %[[X_ADDR]]
// CIR: %[[X:.*]] = cir.load{{.*}} %[[X_ADDR]]
// CIR: %[[VTABLE_PTR:.*]] = cir.vtable.get_vptr %[[X]] : !cir.ptr<!rec_StructWithVirtualDestructor> -> !cir.ptr<!cir.vptr>
// CIR: %[[VTABLE:.*]] = cir.load{{.*}} %[[VTABLE_PTR]] : !cir.ptr<!cir.vptr>, !cir.vptr
// CIR: %[[DTOR_FN_ADDR_PTR:.*]] = cir.vtable.get_virtual_fn_addr %[[VTABLE]][1]
// CIR: %[[DTOR_FN_ADDR:.*]] = cir.load{{.*}} %[[DTOR_FN_ADDR_PTR]]
// CIR: cir.call %[[DTOR_FN_ADDR]](%[[X]])
// LLVM: define {{.*}} void @_Z7destroyP27StructWithVirtualDestructor(ptr %[[X_ARG:.*]])
// LLVM: %[[X_ADDR:.*]] = alloca ptr
// LLVM: store ptr %[[X_ARG]], ptr %[[X_ADDR]]
// LLVM: %[[X:.*]] = load ptr, ptr %[[X_ADDR]]
// LLVM: %[[VTABLE:.*]] = load ptr, ptr %[[X]]
// LLVM: %[[DTOR_FN_ADDR_PTR:.*]] = getelementptr inbounds ptr, ptr %[[VTABLE]], i32 1
// LLVM: %[[DTOR_FN_ADDR:.*]] = load ptr, ptr %[[DTOR_FN_ADDR_PTR]]
// LLVM: call void %[[DTOR_FN_ADDR]](ptr %[[X]])
// OGCG: define {{.*}} void @_Z7destroyP27StructWithVirtualDestructor(ptr {{.*}} %[[X_ARG:.*]])
// OGCG: %[[X_ADDR:.*]] = alloca ptr
// OGCG: store ptr %[[X_ARG]], ptr %[[X_ADDR]]
// OGCG: %[[X:.*]] = load ptr, ptr %[[X_ADDR]]
// OGCG: %[[ISNULL:.*]] = icmp eq ptr %[[X]], null
// OGCG: br i1 %[[ISNULL]], label %{{.*}}, label %[[DELETE_NOTNULL:.*]]
// OGCG: [[DELETE_NOTNULL]]:
// OGCG: %[[VTABLE:.*]] = load ptr, ptr %[[X]]
// OGCG: %[[DTOR_FN_ADDR_PTR:.*]] = getelementptr inbounds ptr, ptr %[[VTABLE]], i64 1
// OGCG: %[[DTOR_FN_ADDR:.*]] = load ptr, ptr %[[DTOR_FN_ADDR_PTR]]
// OGCG: call void %[[DTOR_FN_ADDR]](ptr {{.*}} %[[X]])