@@ -874,3 +874,161 @@ _Complex float test_complex_cond_cleanup(bool b, _Complex float x) {
874874// OGCG: [[DTOR]]:
875875// OGCG: call void @_ZN5CplxDD1Ev(ptr {{.*}} %[[TMP]])
876876// OGCG: br label %[[DONE]]
877+
878+ struct LE {
879+ LE (int );
880+ ~LE ();
881+ };
882+
883+ void test_lifetime_ext_cond_ref (bool c) {
884+ const LE &r = c ? LE (1 ) : LE (2 );
885+ }
886+ // CIR-LABEL: @_Z26test_lifetime_ext_cond_refb
887+ // CIR: %[[TMP:.*]] = cir.alloca !rec_LE, !cir.ptr<!rec_LE>, ["ref.tmp0"]
888+ // CIR: %[[R:.*]] = cir.alloca !cir.ptr<!rec_LE>, !cir.ptr<!cir.ptr<!rec_LE>>, ["r", init, const]
889+ // CIR: %[[SPILL:.*]] = cir.alloca !cir.ptr<!rec_LE>, !cir.ptr<!cir.ptr<!rec_LE>>, ["tmp.exprcleanup"]
890+ // CIR: cir.if %{{.*}} {
891+ // CIR: cir.call @_ZN2LEC1Ei(%[[TMP]], %{{.*}})
892+ // CIR: } else {
893+ // CIR: cir.call @_ZN2LEC1Ei(%[[TMP]], %{{.*}})
894+ // CIR: }
895+ // CIR: cir.store {{.*}} %[[TMP]], %[[SPILL]]
896+ // CIR: cir.cleanup.scope {
897+ // CIR: %[[RELOAD:.*]] = cir.load {{.*}} %[[SPILL]] : !cir.ptr<!cir.ptr<!rec_LE>>, !cir.ptr<!rec_LE>
898+ // CIR: cir.store {{.*}} %[[RELOAD]], %[[R]]
899+ // CIR: cir.yield
900+ // CIR: } cleanup normal {
901+ // CIR: cir.call @_ZN2LED1Ev(%[[TMP]]) nothrow
902+ // CIR: cir.yield
903+ // CIR: }
904+ // CIR: cir.return
905+
906+ // LLVM-LABEL: define dso_local void @_Z26test_lifetime_ext_cond_refb(
907+ // LLVM: %[[TMP:.*]] = alloca %struct.LE
908+ // LLVM: %[[R:.*]] = alloca ptr
909+ // LLVM: %[[SPILL:.*]] = alloca ptr
910+ // LLVM: br i1 %{{.*}}, label %[[TRUE:.*]], label %[[FALSE:.*]]
911+ // LLVM: [[TRUE]]:
912+ // LLVM: call void @_ZN2LEC1Ei(ptr {{.*}} %[[TMP]], i32 {{.*}} 1)
913+ // LLVM: [[FALSE]]:
914+ // LLVM: call void @_ZN2LEC1Ei(ptr {{.*}} %[[TMP]], i32 {{.*}} 2)
915+ // LLVM: store ptr %[[TMP]], ptr %[[SPILL]]
916+ // LLVM: %[[RELOAD:.*]] = load ptr, ptr %[[SPILL]]
917+ // LLVM: store ptr %[[RELOAD]], ptr %[[R]]
918+ // LLVM: call void @_ZN2LED1Ev(ptr {{.*}} %[[TMP]])
919+ // LLVM: ret void
920+
921+ // OGCG-LABEL: define dso_local void @_Z26test_lifetime_ext_cond_refb(
922+ // OGCG: %[[R:.*]] = alloca ptr
923+ // OGCG: %[[TMP:.*]] = alloca %struct.LE
924+ // OGCG: br i1 %{{.*}}, label %[[TRUE:.*]], label %[[FALSE:.*]]
925+ // OGCG: [[TRUE]]:
926+ // OGCG: call void @_ZN2LEC1Ei(ptr {{.*}} %[[TMP]], i32 {{.*}} 1)
927+ // OGCG: [[FALSE]]:
928+ // OGCG: call void @_ZN2LEC1Ei(ptr {{.*}} %[[TMP]], i32 {{.*}} 2)
929+ // OGCG: store ptr %[[TMP]], ptr %[[R]]
930+ // OGCG: call void @_ZN2LED1Ev(ptr {{.*}} %[[TMP]])
931+ // OGCG: ret void
932+
933+ void test_combined_cleanups (bool c) {
934+ const LE &r = LE ((S ().get (), c ? B ().get () : 0 ));
935+ }
936+ // CIR-LABEL: @_Z22test_combined_cleanupsb
937+ // CIR: %[[TMP_LE:.*]] = cir.alloca !rec_LE, !cir.ptr<!rec_LE>, ["ref.tmp0"]
938+ // CIR: %[[R:.*]] = cir.alloca !cir.ptr<!rec_LE>, !cir.ptr<!cir.ptr<!rec_LE>>, ["r", init, const]
939+ // CIR: %[[TMP_S:.*]] = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["ref.tmp1"]
940+ // CIR: %[[TMP_B:.*]] = cir.alloca !rec_B, !cir.ptr<!rec_B>, ["ref.tmp2"]
941+ // CIR: %[[ACT_B:.*]] = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, ["cleanup.cond"]
942+ // CIR: %[[SPILL:.*]] = cir.alloca !cir.ptr<!rec_LE>, !cir.ptr<!cir.ptr<!rec_LE>>, ["tmp.exprcleanup"]
943+ // CIR: cir.cleanup.scope {
944+ // CIR: cir.call @_ZN1SC1Ev(%[[TMP_S]])
945+ // CIR: cir.cleanup.scope {
946+ // CIR: cir.call @_ZN1S3getEv(%[[TMP_S]])
947+ // CIR: cir.store {{.*}}, %[[ACT_B]]
948+ // CIR: %{{.*}} = cir.ternary({{.*}}, true {
949+ // CIR: cir.call @_ZN1BC1Ev(%[[TMP_B]])
950+ // CIR: cir.store {{.*}}, %[[ACT_B]]
951+ // CIR: cir.call @_ZN1B3getEv(%[[TMP_B]])
952+ // CIR: }, false {
953+ // CIR: })
954+ // CIR: cir.call @_ZN2LEC1Ei(%[[TMP_LE]], %{{.*}})
955+ // CIR: cir.store {{.*}} %[[TMP_LE]], %[[SPILL]]
956+ // CIR: cir.yield
957+ // CIR: } cleanup normal {
958+ // CIR: cir.call @_ZN1SD1Ev(%[[TMP_S]]) nothrow
959+ // CIR: cir.yield
960+ // CIR: }
961+ // CIR: cir.yield
962+ // CIR: } cleanup normal {
963+ // CIR: %[[FLAG:.*]] = cir.load {{.*}} %[[ACT_B]]
964+ // CIR: cir.if %[[FLAG]] {
965+ // CIR: cir.call @_ZN1BD1Ev(%[[TMP_B]]) nothrow
966+ // CIR: }
967+ // CIR: cir.yield
968+ // CIR: }
969+ // CIR: cir.cleanup.scope {
970+ // CIR: %[[RELOAD:.*]] = cir.load {{.*}} %[[SPILL]]
971+ // CIR: cir.store {{.*}} %[[RELOAD]], %[[R]]
972+ // CIR: cir.yield
973+ // CIR: } cleanup normal {
974+ // CIR: cir.call @_ZN2LED1Ev(%[[TMP_LE]]) nothrow
975+ // CIR: cir.yield
976+ // CIR: }
977+ // CIR: cir.return
978+
979+ // LLVM-LABEL: define dso_local void @_Z22test_combined_cleanupsb(
980+ // LLVM: %[[TMP_LE:.*]] = alloca %struct.LE
981+ // LLVM: %[[R:.*]] = alloca ptr
982+ // LLVM: %[[TMP_S:.*]] = alloca %struct.S
983+ // LLVM: %[[TMP_B:.*]] = alloca %struct.B
984+ // LLVM: %[[ACT_B:.*]] = alloca i8
985+ // LLVM: %[[SPILL:.*]] = alloca ptr
986+ // LLVM: call void @_ZN1SC1Ev(ptr {{.*}} %[[TMP_S]])
987+ // LLVM: call {{.*}} i32 @_ZN1S3getEv(ptr {{.*}} %[[TMP_S]])
988+ // LLVM: store i8 0, ptr %[[ACT_B]]
989+ // LLVM: br i1 %{{.*}}, label %[[T:.*]], label %[[F:.*]]
990+ // LLVM: [[T]]:
991+ // LLVM: call void @_ZN1BC1Ev(ptr {{.*}} %[[TMP_B]])
992+ // LLVM: store i8 1, ptr %[[ACT_B]]
993+ // LLVM: call {{.*}} i32 @_ZN1B3getEv(ptr {{.*}} %[[TMP_B]])
994+ // LLVM: [[F]]:
995+ // LLVM: phi i32 [ 0, %[[F]] ], [ %{{.*}}, %[[T]] ]
996+ // LLVM: call void @_ZN2LEC1Ei(ptr {{.*}} %[[TMP_LE]], i32 {{.*}})
997+ // LLVM: store ptr %[[TMP_LE]], ptr %[[SPILL]]
998+ // LLVM: call void @_ZN1SD1Ev(ptr {{.*}} %[[TMP_S]])
999+ // LLVM: %[[FLAG_BYTE:.*]] = load i8, ptr %[[ACT_B]]
1000+ // LLVM: %[[FLAG:.*]] = trunc i8 %[[FLAG_BYTE]] to i1
1001+ // LLVM: br i1 %[[FLAG]], label %[[B_DTOR:.*]], label %[[B_DONE:.*]]
1002+ // LLVM: [[B_DTOR]]:
1003+ // LLVM: call void @_ZN1BD1Ev(ptr {{.*}} %[[TMP_B]])
1004+ // LLVM: [[B_DONE]]:
1005+ // LLVM: %[[RELOAD:.*]] = load ptr, ptr %[[SPILL]]
1006+ // LLVM: store ptr %[[RELOAD]], ptr %[[R]]
1007+ // LLVM: call void @_ZN2LED1Ev(ptr {{.*}} %[[TMP_LE]])
1008+ // LLVM: ret void
1009+
1010+ // OGCG-LABEL: define dso_local void @_Z22test_combined_cleanupsb(
1011+ // OGCG: %[[R:.*]] = alloca ptr
1012+ // OGCG: %[[TMP_LE:.*]] = alloca %struct.LE
1013+ // OGCG: %[[TMP_S:.*]] = alloca %struct.S
1014+ // OGCG: %[[TMP_B:.*]] = alloca %struct.B
1015+ // OGCG: %[[ACT_B:.*]] = alloca i1
1016+ // OGCG: call void @_ZN1SC1Ev(ptr {{.*}} %[[TMP_S]])
1017+ // OGCG: call {{.*}} i32 @_ZN1S3getEv(ptr {{.*}} %[[TMP_S]])
1018+ // OGCG: store i1 false, ptr %[[ACT_B]]
1019+ // OGCG: br i1 %{{.*}}, label %[[T:.*]], label %[[F:.*]]
1020+ // OGCG: [[T]]:
1021+ // OGCG: call void @_ZN1BC1Ev(ptr {{.*}} %[[TMP_B]])
1022+ // OGCG: store i1 true, ptr %[[ACT_B]]
1023+ // OGCG: call {{.*}} i32 @_ZN1B3getEv(ptr {{.*}} %[[TMP_B]])
1024+ // OGCG: [[F]]:
1025+ // OGCG: phi i32
1026+ // OGCG: call void @_ZN2LEC1Ei(ptr {{.*}} %[[TMP_LE]], i32 {{.*}})
1027+ // OGCG: br i1 %{{.*}}, label %[[B_DTOR:.*]], label %[[B_DONE:.*]]
1028+ // OGCG: [[B_DTOR]]:
1029+ // OGCG: call void @_ZN1BD1Ev(ptr {{.*}} %[[TMP_B]])
1030+ // OGCG: [[B_DONE]]:
1031+ // OGCG: call void @_ZN1SD1Ev(ptr {{.*}} %[[TMP_S]])
1032+ // OGCG: store ptr %[[TMP_LE]], ptr %[[R]]
1033+ // OGCG: call void @_ZN2LED1Ev(ptr {{.*}} %[[TMP_LE]])
1034+ // OGCG: ret void
0 commit comments