brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.2 KiB · 1fe048b Raw
292 lines · cpp
1// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -mconstructor-aliases -fclangir -emit-cir %s -o %t.cir2// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR3// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -mconstructor-aliases -fclangir -emit-llvm %s -o %t-cir.ll4// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM5// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -mconstructor-aliases -emit-llvm %s -o %t.ll6// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG7 8struct A {9  ~A();10};11 12void test_temporary_dtor() {13  A();14}15 16// CIR: cir.func dso_local @_Z19test_temporary_dtorv()17// CIR:   %[[ALLOCA:.*]] = cir.alloca !rec_A, !cir.ptr<!rec_A>, ["agg.tmp.ensured"]18// CIR:   cir.call @_ZN1AD1Ev(%[[ALLOCA]]) nothrow : (!cir.ptr<!rec_A>) -> ()19 20// LLVM: define dso_local void @_Z19test_temporary_dtorv(){{.*}}21// LLVM:   %[[ALLOCA:.*]] = alloca %struct.A, i64 1, align 122// LLVM:   call void @_ZN1AD1Ev(ptr %[[ALLOCA]])23 24// OGCG: define dso_local void @_Z19test_temporary_dtorv()25// OGCG:   %[[ALLOCA:.*]] = alloca %struct.A, align 126// OGCG:   call void @_ZN1AD1Ev(ptr {{.*}} %[[ALLOCA]])27 28struct B {29  int n;30  B(int n) : n(n) {}31  ~B() {}32};33 34bool make_temp(const B &) { return false; }35bool test_temp_or() { return make_temp(1) || make_temp(2); }36 37// CIR: cir.func{{.*}} @_Z12test_temp_orv()38// CIR:   cir.scope {39// CIR:     %[[REF_TMP0:.*]] = cir.alloca !rec_B, !cir.ptr<!rec_B>, ["ref.tmp0"]40// CIR:     %[[ONE:.*]] = cir.const #cir.int<1>41// CIR:     cir.call @_ZN1BC2Ei(%[[REF_TMP0]], %[[ONE]])42// CIR:     %[[MAKE_TEMP0:.*]] = cir.call @_Z9make_tempRK1B(%[[REF_TMP0]])43// CIR:     %[[TERNARY:.*]] = cir.ternary(%[[MAKE_TEMP0]], true {44// CIR:       %[[TRUE:.*]] = cir.const #true45// CIR:       cir.yield %[[TRUE]] : !cir.bool46// CIR:     }, false {47// CIR:       %[[REF_TMP1:.*]] = cir.alloca !rec_B, !cir.ptr<!rec_B>, ["ref.tmp1"]48// CIR:       %[[TWO:.*]] = cir.const #cir.int<2>49// CIR:       cir.call @_ZN1BC2Ei(%[[REF_TMP1]], %[[TWO]])50// CIR:       %[[MAKE_TEMP1:.*]] = cir.call @_Z9make_tempRK1B(%[[REF_TMP1]])51// CIR:       cir.call @_ZN1BD2Ev(%[[REF_TMP1]])52// CIR:       cir.yield %[[MAKE_TEMP1]] : !cir.bool53// CIR:     })54// CIR:     cir.store{{.*}} %[[TERNARY]], %[[RETVAL:.*]]55// CIR:     cir.call @_ZN1BD2Ev(%[[REF_TMP0]])56// CIR:   }57 58// LLVM: define{{.*}} i1 @_Z12test_temp_orv(){{.*}} {59// LLVM:   %[[REF_TMP0:.*]] = alloca %struct.B60// LLVM:   %[[REF_TMP1:.*]] = alloca %struct.B61// LLVM:   br label %[[LOR_BEGIN:.*]]62// LLVM: [[LOR_BEGIN]]:63// LLVM:   call void @_ZN1BC2Ei(ptr %[[REF_TMP0]], i32 1)64// LLVM:   %[[MAKE_TEMP0:.*]] = call i1 @_Z9make_tempRK1B(ptr %[[REF_TMP0]])65// LLVM:   br i1 %[[MAKE_TEMP0]], label %[[LHS_TRUE_BLOCK:.*]], label %[[LHS_FALSE_BLOCK:.*]]66// LLVM: [[LHS_TRUE_BLOCK]]:67// LLVM:   br label %[[RESULT_BLOCK:.*]]68// LLVM: [[LHS_FALSE_BLOCK]]:69// LLVM:   call void @_ZN1BC2Ei(ptr %[[REF_TMP1]], i32 2)70// LLVM:   %[[MAKE_TEMP1:.*]] = call i1 @_Z9make_tempRK1B(ptr %[[REF_TMP1]])71// LLVM:   call void @_ZN1BD2Ev(ptr %[[REF_TMP1]])72// LLVM:   br label %[[RESULT_BLOCK]]73// LLVM: [[RESULT_BLOCK]]:74// LLVM:   %[[RESULT:.*]] = phi i1 [ %[[MAKE_TEMP1]], %[[LHS_FALSE_BLOCK]] ], [ true, %[[LHS_TRUE_BLOCK]] ]75// LLVM:   br label %[[LOR_END:.*]]76// LLVM: [[LOR_END]]:77// LLVM:   call void @_ZN1BD2Ev(ptr %[[REF_TMP0]])78 79// OGCG: define {{.*}} i1 @_Z12test_temp_orv()80// OGCG: [[ENTRY:.*]]:81// OGCG:   %[[RETVAL:.*]] = alloca i182// OGCG:   %[[REF_TMP0:.*]] = alloca %struct.B83// OGCG:   %[[REF_TMP1:.*]] = alloca %struct.B84// OGCG:   %[[CLEANUP_COND:.*]] = alloca i185// OGCG:   call void @_ZN1BC2Ei(ptr {{.*}} %[[REF_TMP0]], i32 {{.*}} 1)86// OGCG:   %[[MAKE_TEMP0:.*]] = call {{.*}} i1 @_Z9make_tempRK1B(ptr {{.*}} %[[REF_TMP0]])87// OGCG:   store i1 false, ptr %cleanup.cond88// OGCG:   br i1 %[[MAKE_TEMP0]], label %[[LOR_END:.*]], label %[[LOR_RHS:.*]]89// OGCG: [[LOR_RHS]]:90// OGCG:   call void @_ZN1BC2Ei(ptr {{.*}} %[[REF_TMP1]], i32 {{.*}} 2)91// OGCG:   store i1 true, ptr %[[CLEANUP_COND]]92// OGCG:   %[[MAKE_TEMP1:.*]] = call {{.*}} i1 @_Z9make_tempRK1B(ptr {{.*}} %[[REF_TMP1]])93// OGCG:   br label %[[LOR_END]]94// OGCG: [[LOR_END]]:95// OGCG:    %[[PHI:.*]] = phi i1 [ true, %[[ENTRY]] ], [ %[[MAKE_TEMP1]], %[[LOR_RHS]] ]96// OGCG:   store i1 %[[PHI]], ptr %[[RETVAL]]97// OGCG:   %[[CLEANUP_IS_ACTIVE:.*]] = load i1, ptr %[[CLEANUP_COND]]98// OGCG:   br i1 %[[CLEANUP_IS_ACTIVE]], label %[[CLEANUP_ACTION:.*]], label %[[CLEANUP_DONE:.*]]99// OGCG: [[CLEANUP_ACTION]]:100// OGCG:   call void @_ZN1BD2Ev(ptr {{.*}} %[[REF_TMP1]])101// OGCG:   br label %[[CLEANUP_DONE]]102// OGCG: [[CLEANUP_DONE]]:103// OGCG:   call void @_ZN1BD2Ev(ptr {{.*}} %[[REF_TMP0]])104 105bool test_temp_and() { return make_temp(1) && make_temp(2); }106 107// CIR: cir.func{{.*}} @_Z13test_temp_andv()108// CIR:   cir.scope {109// CIR:     %[[REF_TMP0:.*]] = cir.alloca !rec_B, !cir.ptr<!rec_B>, ["ref.tmp0"]110// CIR:     %[[ONE:.*]] = cir.const #cir.int<1>111// CIR:     cir.call @_ZN1BC2Ei(%[[REF_TMP0]], %[[ONE]])112// CIR:     %[[MAKE_TEMP0:.*]] = cir.call @_Z9make_tempRK1B(%[[REF_TMP0]])113// CIR:     %[[TERNARY:.*]] = cir.ternary(%[[MAKE_TEMP0]], true {114// CIR:       %[[REF_TMP1:.*]] = cir.alloca !rec_B, !cir.ptr<!rec_B>, ["ref.tmp1"]115// CIR:       %[[TWO:.*]] = cir.const #cir.int<2>116// CIR:       cir.call @_ZN1BC2Ei(%[[REF_TMP1]], %[[TWO]])117// CIR:       %[[MAKE_TEMP1:.*]] = cir.call @_Z9make_tempRK1B(%[[REF_TMP1]])118// CIR:       cir.call @_ZN1BD2Ev(%[[REF_TMP1]])119// CIR:       cir.yield %[[MAKE_TEMP1]] : !cir.bool120// CIR:     }, false {121// CIR:       %[[FALSE:.*]] = cir.const #false122// CIR:       cir.yield %[[FALSE]] : !cir.bool123// CIR:     })124// CIR:     cir.store{{.*}} %[[TERNARY]], %[[RETVAL:.*]]125// CIR:     cir.call @_ZN1BD2Ev(%[[REF_TMP0]])126// CIR:   }127 128// LLVM: define{{.*}} i1 @_Z13test_temp_andv(){{.*}} {129// LLVM:   %[[REF_TMP0:.*]] = alloca %struct.B130// LLVM:   %[[REF_TMP1:.*]] = alloca %struct.B131// LLVM:   br label %[[LAND_BEGIN:.*]]132// LLVM: [[LAND_BEGIN]]:133// LLVM:   call void @_ZN1BC2Ei(ptr %[[REF_TMP0]], i32 1)134// LLVM:   %[[MAKE_TEMP0:.*]] = call i1 @_Z9make_tempRK1B(ptr %[[REF_TMP0]])135// LLVM:   br i1 %[[MAKE_TEMP0]], label %[[LHS_TRUE_BLOCK:.*]], label %[[LHS_FALSE_BLOCK:.*]]136// LLVM: [[LHS_TRUE_BLOCK]]:137// LLVM:   call void @_ZN1BC2Ei(ptr %[[REF_TMP1]], i32 2)138// LLVM:   %[[MAKE_TEMP1:.*]] = call i1 @_Z9make_tempRK1B(ptr %[[REF_TMP1]])139// LLVM:   call void @_ZN1BD2Ev(ptr %[[REF_TMP1]])140// LLVM:   br label %[[RESULT_BLOCK:.*]]141// LLVM: [[LHS_FALSE_BLOCK]]:142// LLVM:   br label %[[RESULT_BLOCK]]143// LLVM: [[RESULT_BLOCK]]:144// LLVM:   %[[RESULT:.*]] = phi i1 [ false, %[[LHS_FALSE_BLOCK]] ], [ %[[MAKE_TEMP1]], %[[LHS_TRUE_BLOCK]] ]145// LLVM:   br label %[[LAND_END:.*]]146// LLVM: [[LAND_END]]:147// LLVM:   call void @_ZN1BD2Ev(ptr %[[REF_TMP0]])148 149// OGCG: define {{.*}} i1 @_Z13test_temp_andv()150// OGCG: [[ENTRY:.*]]:151// OGCG:   %[[RETVAL:.*]] = alloca i1152// OGCG:   %[[REF_TMP0:.*]] = alloca %struct.B153// OGCG:   %[[REF_TMP1:.*]] = alloca %struct.B154// OGCG:   %[[CLEANUP_COND:.*]] = alloca i1155// OGCG:   call void @_ZN1BC2Ei(ptr {{.*}} %[[REF_TMP0]], i32 {{.*}} 1)156// OGCG:   %[[MAKE_TEMP0:.*]] = call {{.*}} i1 @_Z9make_tempRK1B(ptr {{.*}} %[[REF_TMP0]])157// OGCG:   store i1 false, ptr %cleanup.cond158// OGCG:   br i1 %[[MAKE_TEMP0]], label %[[LAND_RHS:.*]], label %[[LAND_END:.*]]159// OGCG: [[LAND_RHS]]:160// OGCG:   call void @_ZN1BC2Ei(ptr {{.*}} %[[REF_TMP1]], i32 {{.*}} 2)161// OGCG:   store i1 true, ptr %[[CLEANUP_COND]]162// OGCG:   %[[MAKE_TEMP1:.*]] = call {{.*}} i1 @_Z9make_tempRK1B(ptr {{.*}} %[[REF_TMP1]])163// OGCG:   br label %[[LAND_END]]164// OGCG: [[LAND_END]]:165// OGCG:   %[[PHI:.*]] = phi i1 [ false, %[[ENTRY]] ], [ %[[MAKE_TEMP1]], %[[LAND_RHS]] ]166// OGCG:   store i1 %[[PHI]], ptr %[[RETVAL]]167// OGCG:   %[[CLEANUP_IS_ACTIVE:.*]] = load i1, ptr %[[CLEANUP_COND]]168// OGCG:   br i1 %[[CLEANUP_IS_ACTIVE]], label %[[CLEANUP_ACTION:.*]], label %[[CLEANUP_DONE:.*]]169// OGCG: [[CLEANUP_ACTION]]:170// OGCG:   call void @_ZN1BD2Ev(ptr {{.*}} %[[REF_TMP1]])171// OGCG:   br label %[[CLEANUP_DONE]]172// OGCG: [[CLEANUP_DONE]]:173// OGCG:   call void @_ZN1BD2Ev(ptr {{.*}} %[[REF_TMP0]])174 175struct C {176  ~C();177};178 179struct D {180  int n;181  C c;182  ~D() {}183};184 185// CIR: cir.func {{.*}} @_ZN1DD2Ev186// CIR:   %[[C:.*]] = cir.get_member %{{.*}}[1] {name = "c"}187// CIR:   cir.call @_ZN1CD1Ev(%[[C]])188 189// LLVM: define {{.*}} void @_ZN1DD2Ev190// LLVM:   %[[C:.*]] = getelementptr %struct.D, ptr %{{.*}}, i32 0, i32 1191// LLVM:   call void @_ZN1CD1Ev(ptr %[[C]])192 193// This destructor is defined after the calling function in OGCG.194 195void test_nested_dtor() {196  D d;197}198 199// CIR: cir.func{{.*}} @_Z16test_nested_dtorv()200// CIR:   cir.call @_ZN1DD2Ev(%{{.*}})201 202// LLVM: define {{.*}} void @_Z16test_nested_dtorv(){{.*}}203// LLVM:   call void @_ZN1DD2Ev(ptr %{{.*}})204 205// OGCG: define {{.*}} void @_Z16test_nested_dtorv()206// OGCG:   call void @_ZN1DD2Ev(ptr {{.*}} %{{.*}})207 208// OGCG: define {{.*}} void @_ZN1DD2Ev209// OGCG:   %[[C:.*]] = getelementptr inbounds i8, ptr %{{.*}}, i64 4210// OGCG:   call void @_ZN1CD1Ev(ptr {{.*}} %[[C]])211 212struct E {213  ~E();214};215 216struct F : public E {217  int n;218  ~F() {}219};220 221// CIR: cir.func {{.*}} @_ZN1FD2Ev222// CIR:   %[[BASE_E:.*]] = cir.base_class_addr %{{.*}} : !cir.ptr<!rec_F> nonnull [0] -> !cir.ptr<!rec_E>223// CIR:   cir.call @_ZN1ED2Ev(%[[BASE_E]]) nothrow : (!cir.ptr<!rec_E>) -> ()224 225// Because E is at offset 0 in F, there is no getelementptr needed.226 227// LLVM: define {{.*}} void @_ZN1FD2Ev228// LLVM:   call void @_ZN1ED2Ev(ptr %{{.*}})229 230// This destructor is defined after the calling function in OGCG.231 232void test_base_dtor_call() {233  F f;234}235 236// CIR: cir.func {{.*}} @_Z19test_base_dtor_callv()237//   cir.call @_ZN1FD2Ev(%{{.*}}) nothrow : (!cir.ptr<!rec_F>) -> ()238 239// LLVM: define {{.*}} void @_Z19test_base_dtor_callv(){{.*}}240// LLVM:   call void @_ZN1FD2Ev(ptr %{{.*}})241 242// OGCG: define {{.*}} void @_Z19test_base_dtor_callv()243// OGCG:   call void @_ZN1FD2Ev(ptr {{.*}} %{{.*}})244 245// OGCG: define {{.*}} void @_ZN1FD2Ev246// OGCG:   call void @_ZN1ED2Ev(ptr {{.*}} %{{.*}})247 248struct VirtualBase {249  ~VirtualBase();250};251 252struct Derived : virtual VirtualBase {253  ~Derived() {}254};255 256void test_base_dtor_call_virtual_base() {257  Derived d;258}259 260// Derived D2 (base) destructor -- does not call VirtualBase destructor261 262// CIR:     cir.func {{.*}} @_ZN7DerivedD2Ev263// CIR-NOT:   cir.call{{.*}} @_ZN11VirtualBaseD2Ev264// CIR:       cir.return265 266// LLVM:     define {{.*}} void @_ZN7DerivedD2Ev267// LLVM-NOT:   call{{.*}} @_ZN11VirtualBaseD2Ev268// LLVM:       ret269 270// Derived D1 (complete) destructor -- does call VirtualBase destructor271 272// CIR: cir.func {{.*}} @_ZN7DerivedD1Ev273// CIR:   %[[THIS:.*]] = cir.load %{{.*}}274// CIR:   %[[VTT:.*]] = cir.vtt.address_point @_ZTT7Derived, offset = 0 -> !cir.ptr<!cir.ptr<!void>>275// CIR:   cir.call @_ZN7DerivedD2Ev(%[[THIS]], %[[VTT]])276// CIR:   %[[VIRTUAL_BASE:.*]] = cir.base_class_addr %[[THIS]] : !cir.ptr<!rec_Derived> nonnull [0] -> !cir.ptr<!rec_VirtualBase>277// CIR:   cir.call @_ZN11VirtualBaseD2Ev(%[[VIRTUAL_BASE]])278 279// LLVM: define {{.*}} void @_ZN7DerivedD1Ev280// LLVM:   call void @_ZN7DerivedD2Ev(ptr %{{.*}}, ptr @_ZTT7Derived)281// LLVM:   call void @_ZN11VirtualBaseD2Ev(ptr %{{.*}})282 283// OGCG emits these destructors in reverse order284 285// OGCG: define {{.*}} void @_ZN7DerivedD1Ev286// OGCG:   call void @_ZN7DerivedD2Ev(ptr {{.*}} %{{.*}}, ptr {{.*}} @_ZTT7Derived)287// OGCG:   call void @_ZN11VirtualBaseD2Ev(ptr {{.*}} %{{.*}})288 289// OGCG:     define {{.*}} void @_ZN7DerivedD2Ev290// OGCG-NOT:   call{{.*}} @_ZN11VirtualBaseD2Ev291// OGCG:       ret292