| // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fexceptions -fcxx-exceptions -fclangir -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 -fexceptions -fcxx-exceptions -fclangir -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 -fexceptions -fcxx-exceptions -emit-llvm %s -o %t.ll |
| // RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s |
| |
| struct S { |
| S(); |
| S(int); |
| S(const S &); |
| ~S(); |
| int x; |
| }; |
| |
| void capture_one(S s) { |
| auto lam = [s]() {}; |
| } |
| |
| // CIR-LABEL: @_Z11capture_one1S |
| // CIR: %[[LAM:.*]] = cir.alloca !rec_anon{{.*}}, {{.*}} ["lam", init] |
| // CIR: %[[FIELD:.*]] = cir.get_member %[[LAM]][0] {name = "s"} |
| // CIR: cir.call @_ZN1SC1ERKS_(%[[FIELD]], |
| // CIR: cir.cleanup.scope { |
| // CIR: cir.yield |
| // CIR: } cleanup all { |
| // CIR: cir.call @_ZZ11capture_one1SEN3$_0D1Ev(%[[LAM]]){{.*}} |
| // CIR: cir.yield |
| // CIR: } |
| |
| // LLVM-LABEL: define internal void @"_ZZ11capture_one1SEN3$_0D2Ev"( |
| // LLVM: %[[THIS1:.*]] = load ptr, ptr |
| // LLVM: %[[FIELD1:.*]] = getelementptr inbounds nuw %[[LAM_TY_1:.*]], ptr %[[THIS1]], i32 0, i32 0 |
| // LLVM: call void @_ZN1SD1Ev(ptr {{.*}} %[[FIELD1]]) |
| // LLVM: ret void |
| |
| // LLVM-LABEL: define dso_local void @_Z11capture_one1S( |
| // LLVM: %[[S_ALLOCA:.*]] = alloca %struct.S |
| // LLVM: %[[LAM1:.*]] = alloca %[[LAM_TY_1]] |
| // LLVM: %[[F1:.*]] = getelementptr inbounds nuw %[[LAM_TY_1]], ptr %[[LAM1]], i32 0, i32 0 |
| // LLVM: call void @_ZN1SC1ERKS_(ptr {{.*}} %[[F1]], ptr {{.*}} %[[S_ALLOCA]]) |
| // LLVM: call void @"_ZZ11capture_one1SEN3$_0D1Ev"(ptr {{.*}} %[[LAM1]]) |
| // LLVM: ret void |
| |
| // OGCG-LABEL: define dso_local void @_Z11capture_one1S( |
| // OGCG: %[[LAM1:.*]] = alloca %[[LAM_TY_1:.*]], align 4 |
| // OGCG: %[[FIELD1:.*]] = getelementptr inbounds nuw %[[LAM_TY_1]], ptr %[[LAM1]], i32 0, i32 0 |
| // OGCG: call void @_ZN1SC1ERKS_(ptr {{.*}} %[[FIELD1]], ptr {{.*}} %s) |
| // OGCG: call void @"_ZZ11capture_one1SEN3$_0D1Ev"(ptr {{.*}} %[[LAM1]]) |
| // OGCG: ret void |
| |
| void capture_two(S a, S b) { |
| auto lam = [a, b]() {}; |
| } |
| |
| // CIR-LABEL: @_Z11capture_two1SS_ |
| // CIR: %[[LAM2:.*]] = cir.alloca !rec_anon{{.*}}, {{.*}} ["lam", init] |
| // CIR: %[[FA:.*]] = cir.get_member %[[LAM2]][0] {name = "a"} |
| // CIR: cir.call @_ZN1SC1ERKS_(%[[FA]], |
| // CIR: cir.cleanup.scope { |
| // CIR: %[[FB:.*]] = cir.get_member %[[LAM2]][1] {name = "b"} |
| // CIR: cir.call @_ZN1SC1ERKS_(%[[FB]], |
| // CIR: cir.yield |
| // CIR: } cleanup eh { |
| // CIR: cir.call @_ZN1SD1Ev(%[[FA]]){{.*}} |
| // CIR: cir.yield |
| // CIR: } |
| // CIR: cir.cleanup.scope { |
| // CIR: cir.yield |
| // CIR: } cleanup all { |
| // CIR: cir.call @_ZZ11capture_two1SS_EN3$_0D1Ev(%[[LAM2]]){{.*}} |
| // CIR: cir.yield |
| // CIR: } |
| |
| // LLVM-LABEL: define internal void @"_ZZ11capture_two1SS_EN3$_0D2Ev"( |
| // LLVM: %[[THIS2:.*]] = load ptr, ptr |
| // LLVM: %[[FB_D:.*]] = getelementptr inbounds nuw %[[LAM_TY_2:.*]], ptr %[[THIS2]], i32 0, i32 1 |
| // LLVM: call void @_ZN1SD1Ev(ptr {{.*}} %[[FB_D]]) |
| // LLVM: %[[FA_D:.*]] = getelementptr inbounds nuw %[[LAM_TY_2]], ptr %[[THIS2]], i32 0, i32 0 |
| // LLVM: call void @_ZN1SD1Ev(ptr {{.*}} %[[FA_D]]) |
| // LLVM: ret void |
| |
| // LLVM-LABEL: define dso_local void @_Z11capture_two1SS_(%struct.S {{.*}}, %struct.S {{.*}}) #{{.*}} personality ptr @__gxx_personality_v0 { |
| // LLVM: %[[A_ALLOCA:.*]] = alloca %struct.S |
| // LLVM: %[[B_ALLOCA:.*]] = alloca %struct.S |
| // LLVM: %[[LAM2:.*]] = alloca %[[LAM_TY_2]] |
| // LLVM: %[[FA:.*]] = getelementptr inbounds nuw %[[LAM_TY_2]], ptr %[[LAM2]], i32 0, i32 0 |
| // LLVM: call void @_ZN1SC1ERKS_(ptr {{.*}} %[[FA]], ptr {{.*}} %[[A_ALLOCA]]) |
| // LLVM: %[[FB:.*]] = getelementptr inbounds nuw %[[LAM_TY_2]], ptr %[[LAM2]], i32 0, i32 1 |
| // LLVM: invoke void @_ZN1SC1ERKS_(ptr {{.*}} %[[FB]], ptr {{.*}} %[[B_ALLOCA]]) |
| // LLVM: to label %{{.*}} unwind label %{{.*}} |
| // LLVM: call void @"_ZZ11capture_two1SS_EN3$_0D1Ev"(ptr {{.*}} %[[LAM2]]) |
| // LLVM: ret void |
| |
| // OGCG-LABEL: define dso_local void @_Z11capture_two1SS_(ptr noundef %a, ptr noundef %b){{.*}}personality ptr @__gxx_personality_v0 |
| // OGCG: %[[LAM2:.*]] = alloca %[[LAM_TY_2:.*]], align 4 |
| // OGCG: %[[FA:.*]] = getelementptr inbounds nuw %[[LAM_TY_2]], ptr %[[LAM2]], i32 0, i32 0 |
| // OGCG: call void @_ZN1SC1ERKS_(ptr {{.*}} %[[FA]], ptr {{.*}} %a) |
| // OGCG: %[[FB:.*]] = getelementptr inbounds nuw %[[LAM_TY_2]], ptr %[[LAM2]], i32 0, i32 1 |
| // OGCG: invoke void @_ZN1SC1ERKS_(ptr {{.*}} %[[FB]], ptr {{.*}} %b) |
| // OGCG: to label %{{.*}} unwind label %{{.*}} |
| // OGCG: call void @"_ZZ11capture_two1SS_EN3$_0D1Ev"(ptr {{.*}} %[[LAM2]]) |
| // OGCG: ret void |
| |
| void capture_mixed(int n, S s) { |
| auto lam = [n, s]() {}; |
| } |
| |
| // CIR-LABEL: @_Z13capture_mixedi1S |
| // CIR: %[[LAM3:.*]] = cir.alloca !rec_anon{{.*}}, {{.*}} ["lam", init] |
| // CIR: %[[FN:.*]] = cir.get_member %[[LAM3]][0] {name = "n"} |
| // CIR: cir.load |
| // CIR: cir.store |
| // CIR: %[[FS:.*]] = cir.get_member %[[LAM3]][1] {name = "s"} |
| // CIR: cir.call @_ZN1SC1ERKS_(%[[FS]], |
| // CIR: cir.cleanup.scope { |
| // CIR: cir.yield |
| // CIR: } cleanup all { |
| // CIR: cir.call @_ZZ13capture_mixedi1SEN3$_0D1Ev(%[[LAM3]]){{.*}} |
| // CIR: cir.yield |
| // CIR: } |
| |
| // LLVM-LABEL: define internal void @"_ZZ13capture_mixedi1SEN3$_0D2Ev"( |
| // LLVM: %[[THIS3:.*]] = load ptr, ptr |
| // LLVM: %[[FS_D:.*]] = getelementptr inbounds nuw %[[LAM_TY_3:.*]], ptr %[[THIS3]], i32 0, i32 1 |
| // LLVM: call void @_ZN1SD1Ev(ptr {{.*}} %[[FS_D]]) |
| // LLVM: ret void |
| |
| // LLVM-LABEL: define dso_local void @_Z13capture_mixedi1S( |
| // LLVM: %[[N_ALLOCA:.*]] = alloca i32 |
| // LLVM: %[[S_ALLOCA2:.*]] = alloca %struct.S |
| // LLVM: %[[LAM3:.*]] = alloca %[[LAM_TY_3]] |
| // LLVM: %[[FN:.*]] = getelementptr inbounds nuw %[[LAM_TY_3]], ptr %[[LAM3]], i32 0, i32 0 |
| // LLVM: %[[NVAL:.*]] = load i32, ptr %[[N_ALLOCA]] |
| // LLVM: store i32 %[[NVAL]], ptr %[[FN]] |
| // LLVM: %[[FS:.*]] = getelementptr inbounds nuw %[[LAM_TY_3]], ptr %[[LAM3]], i32 0, i32 1 |
| // LLVM: call void @_ZN1SC1ERKS_(ptr {{.*}} %[[FS]], ptr {{.*}} %[[S_ALLOCA2]]) |
| // LLVM: call void @"_ZZ13capture_mixedi1SEN3$_0D1Ev"(ptr {{.*}} %[[LAM3]]) |
| // LLVM: ret void |
| |
| // OGCG-LABEL: define dso_local void @_Z13capture_mixedi1S( |
| // OGCG: %[[LAM3:.*]] = alloca %[[LAM_TY_3:.*]], align 4 |
| // OGCG: %[[FN:.*]] = getelementptr inbounds nuw %[[LAM_TY_3]], ptr %[[LAM3]], i32 0, i32 0 |
| // OGCG: %[[NVAL:.*]] = load i32, ptr %n.addr |
| // OGCG: store i32 %[[NVAL]], ptr %[[FN]] |
| // OGCG: %[[FS:.*]] = getelementptr inbounds nuw %[[LAM_TY_3]], ptr %[[LAM3]], i32 0, i32 1 |
| // OGCG: call void @_ZN1SC1ERKS_(ptr {{.*}} %[[FS]], ptr {{.*}} %s) |
| // OGCG: call void @"_ZZ13capture_mixedi1SEN3$_0D1Ev"(ptr {{.*}} %[[LAM3]]) |
| // OGCG: ret void |
| |
| void capture_local() { |
| S s; |
| auto lam = [s]() {}; |
| } |
| |
| // CIR-LABEL: @_Z13capture_localv |
| // CIR: %[[S4:.*]] = cir.alloca !rec_S, {{.*}} ["s", init] |
| // CIR: %[[LAM4:.*]] = cir.alloca !rec_anon{{.*}}, {{.*}} ["lam", init] |
| // CIR: cir.call @_ZN1SC1Ev(%[[S4]]) |
| // CIR: cir.cleanup.scope { |
| // CIR: %[[FL:.*]] = cir.get_member %[[LAM4]][0] {name = "s"} |
| // CIR: cir.call @_ZN1SC1ERKS_(%[[FL]], |
| // CIR: cir.cleanup.scope { |
| // CIR: cir.yield |
| // CIR: } cleanup all { |
| // CIR: cir.call @_ZZ13capture_localvEN3$_0D1Ev(%[[LAM4]]){{.*}} |
| // CIR: cir.yield |
| // CIR: } |
| // CIR: cir.yield |
| // CIR: } cleanup all { |
| // CIR: cir.call @_ZN1SD1Ev(%[[S4]]){{.*}} |
| // CIR: cir.yield |
| // CIR: } |
| |
| // LLVM-LABEL: define internal void @"_ZZ13capture_localvEN3$_0D2Ev"( |
| // LLVM: %[[THIS4:.*]] = load ptr, ptr |
| // LLVM: %[[FL_D:.*]] = getelementptr inbounds nuw %[[LAM_TY_4:.*]], ptr %[[THIS4]], i32 0, i32 0 |
| // LLVM: call void @_ZN1SD1Ev(ptr {{.*}} %[[FL_D]]) |
| // LLVM: ret void |
| |
| // LLVM-LABEL: define dso_local void @_Z13capture_localv(){{.*}} personality ptr @__gxx_personality_v0 |
| // LLVM: %[[S_LOCAL:.*]] = alloca %struct.S |
| // LLVM: %[[LAM4:.*]] = alloca %[[LAM_TY_4]] |
| // LLVM: call void @_ZN1SC1Ev(ptr {{.*}} %[[S_LOCAL]]) |
| // LLVM: %[[FL:.*]] = getelementptr inbounds nuw %[[LAM_TY_4]], ptr %[[LAM4]], i32 0, i32 0 |
| // LLVM: invoke void @_ZN1SC1ERKS_(ptr {{.*}} %[[FL]], ptr {{.*}} %[[S_LOCAL]]) |
| // LLVM: to label %{{.*}} unwind label %{{.*}} |
| // LLVM: call void @"_ZZ13capture_localvEN3$_0D1Ev"(ptr {{.*}} %[[LAM4]]) |
| // LLVM: call void @_ZN1SD1Ev(ptr {{.*}} %[[S_LOCAL]]) |
| // LLVM: ret void |
| |
| // OGCG-LABEL: define dso_local void @_Z13capture_localv(){{.*}} personality ptr @__gxx_personality_v0 |
| // OGCG: %[[S_LOCAL:.*]] = alloca %struct.S |
| // OGCG: %[[LAM4:.*]] = alloca %[[LAM_TY_4:.*]], align 4 |
| // OGCG: call void @_ZN1SC1Ev(ptr {{.*}} %[[S_LOCAL]]) |
| // OGCG: %[[FL:.*]] = getelementptr inbounds nuw %[[LAM_TY_4]], ptr %[[LAM4]], i32 0, i32 0 |
| // OGCG: invoke void @_ZN1SC1ERKS_(ptr {{.*}} %[[FL]], ptr {{.*}} %[[S_LOCAL]]) |
| // OGCG: to label %{{.*}} unwind label %{{.*}} |
| // OGCG: call void @"_ZZ13capture_localvEN3$_0D1Ev"(ptr {{.*}} %[[LAM4]]) |
| // OGCG: call void @_ZN1SD1Ev(ptr {{.*}} %[[S_LOCAL]]) |
| // OGCG: ret void |
| |
| // This test uses a GNU statement expression inside a lambda init-capture to |
| // exercise the case where a cleanup is deactivated while its body region |
| // contains a non-yield exit (cir.return). The cleanup for capture 'a' must |
| // fire on the early return path but be skipped on normal fallthrough. CIR |
| // handles this by guarding the cleanup with an active flag that is set to true |
| // when the cleanup is pushed and false at the deactivation point. |
| void stmt_expr_return(bool cond) { |
| auto lam = [a = S(0), b = S(({ |
| if (cond) return; |
| 42; |
| }))]() {}; |
| } |
| |
| // CIR-LABEL: @_Z16stmt_expr_returnb |
| // CIR: %[[LAM5:.*]] = cir.alloca !rec_anon{{.*}}, {{.*}} ["lam", init] |
| // CIR: %[[ACTIVE:.*]] = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, ["cleanup.isactive"] |
| // CIR: %[[FA5:.*]] = cir.get_member %[[LAM5]][0] {name = "a"} |
| // CIR: cir.call @_ZN1SC1Ei(%[[FA5]], |
| // CIR: %[[TRUE:.*]] = cir.const #true |
| // CIR: cir.store %[[TRUE]], %[[ACTIVE]] |
| // CIR: cir.cleanup.scope { |
| // CIR: %[[FB5:.*]] = cir.get_member %[[LAM5]][1] {name = "b"} |
| // CIR: cir.if |
| // CIR: cir.return |
| // CIR: cir.call @_ZN1SC1Ei(%[[FB5]], |
| // CIR: %[[FALSE:.*]] = cir.const #false |
| // CIR: cir.store %[[FALSE]], %[[ACTIVE]] |
| // CIR: cir.yield |
| // CIR: } cleanup all { |
| // CIR: %[[FLAG:.*]] = cir.load{{.*}} %[[ACTIVE]] |
| // CIR: cir.if %[[FLAG]] { |
| // CIR: cir.call @_ZN1SD1Ev(%[[FA5]]){{.*}} |
| // CIR: } |
| // CIR: cir.yield |
| // CIR: } |
| // CIR: cir.cleanup.scope { |
| // CIR: cir.yield |
| // CIR: } cleanup all { |
| // CIR: cir.call @_ZZ16stmt_expr_returnbEN3$_0D1Ev(%[[LAM5]]){{.*}} |
| // CIR: cir.yield |
| // CIR: } |
| |
| // LLVM-LABEL: define internal void @"_ZZ16stmt_expr_returnbEN3$_0D2Ev"( |
| // LLVM: %[[THIS5:.*]] = load ptr, ptr |
| // LLVM: %[[FB5_D:.*]] = getelementptr inbounds nuw %[[LAM_TY_5:.*]], ptr %[[THIS5]], i32 0, i32 1 |
| // LLVM: call void @_ZN1SD1Ev(ptr {{.*}} %[[FB5_D]]) |
| // LLVM: %[[FA5_D:.*]] = getelementptr inbounds nuw %[[LAM_TY_5]], ptr %[[THIS5]], i32 0, i32 0 |
| // LLVM: call void @_ZN1SD1Ev(ptr {{.*}} %[[FA5_D]]) |
| // LLVM: ret void |
| |
| // LLVM-LABEL: define dso_local void @_Z16stmt_expr_returnb({{.*}}) {{.*}} personality ptr @__gxx_personality_v0 { |
| // LLVM: %[[LAM5:.*]] = alloca %[[LAM_TY_5]] |
| // LLVM: %[[ACTIVE_ALLOCA:.*]] = alloca i8 |
| // LLVM: %[[FA5:.*]] = getelementptr inbounds nuw %[[LAM_TY_5]], ptr %[[LAM5]], i32 0, i32 0 |
| // LLVM: call void @_ZN1SC1Ei(ptr {{.*}} %[[FA5]], i32 {{.*}} 0) |
| // LLVM: store i8 1, ptr %[[ACTIVE_ALLOCA]] |
| // LLVM: %[[FB5:.*]] = getelementptr inbounds nuw %[[LAM_TY_5]], ptr %[[LAM5]], i32 0, i32 1 |
| // LLVM: br i1 %{{.*}}, |
| // The early return path — the active flag is still true, so the cleanup fires. |
| // LLVM: invoke void @_ZN1SC1Ei(ptr {{.*}} %[[FB5]], |
| // LLVM: to label %{{.*}} unwind label %{{.*}} |
| // LLVM: store i8 0, ptr %[[ACTIVE_ALLOCA]] |
| // The active flag is checked and the cleanup conditionally fires. |
| // LLVM: call void @_ZN1SD1Ev(ptr {{.*}} %[[FA5]]) |
| // LLVM: ret void |
| // Normal fallthrough path completes with the lambda destructor. |
| // LLVM: call void @"_ZZ16stmt_expr_returnbEN3$_0D1Ev"(ptr {{.*}} %[[LAM5]]) |
| // LLVM: ret void |
| |
| // OGCG-LABEL: define dso_local void @_Z16stmt_expr_returnb(i1 noundef zeroext %cond){{.*}} personality ptr @__gxx_personality_v0 |
| // OGCG: %[[LAM5:.*]] = alloca %[[LAM_TY_5:.*]], align 4 |
| // OGCG: %[[FA5:.*]] = getelementptr inbounds nuw %[[LAM_TY_5]], ptr %[[LAM5]], i32 0, i32 0 |
| // OGCG: call void @_ZN1SC1Ei(ptr {{.*}} %[[FA5]], i32 {{.*}} 0) |
| // OGCG: %[[FB5:.*]] = getelementptr inbounds nuw %[[LAM_TY_5]], ptr %[[LAM5]], i32 0, i32 1 |
| // OGCG: br i1 %{{.*}}, |
| // The early return path correctly destroys capture 'a' in classic codegen. |
| // OGCG: call void @_ZN1SD1Ev(ptr {{.*}} %[[FA5]]) |
| // OGCG: invoke void @_ZN1SC1Ei(ptr {{.*}} %[[FB5]], |
| // OGCG: to label %{{.*}} unwind label %{{.*}} |
| // OGCG: call void @"_ZZ16stmt_expr_returnbEN3$_0D1Ev"(ptr {{.*}} %[[LAM5]]) |
| // OGCG: ret void |
| |
| // The D2 destructors are emitted after all other functions in OGCG. |
| |
| // OGCG-LABEL: define internal void @"_ZZ11capture_one1SEN3$_0D2Ev"( |
| // OGCG: %[[THIS1:.*]] = load ptr, ptr %this.addr |
| // OGCG: %[[FIELD1_D:.*]] = getelementptr inbounds nuw %[[LAM_TY_1]], ptr %[[THIS1]], i32 0, i32 0 |
| // OGCG: call void @_ZN1SD1Ev(ptr {{.*}} %[[FIELD1_D]]) |
| // OGCG: ret void |
| |
| // OGCG-LABEL: define internal void @"_ZZ11capture_two1SS_EN3$_0D2Ev"( |
| // OGCG: %[[THIS2:.*]] = load ptr, ptr %this.addr |
| // OGCG: %[[FB_D:.*]] = getelementptr inbounds nuw %[[LAM_TY_2]], ptr %[[THIS2]], i32 0, i32 1 |
| // OGCG: call void @_ZN1SD1Ev(ptr {{.*}} %[[FB_D]]) |
| // OGCG: %[[FA_D:.*]] = getelementptr inbounds nuw %[[LAM_TY_2]], ptr %[[THIS2]], i32 0, i32 0 |
| // OGCG: call void @_ZN1SD1Ev(ptr {{.*}} %[[FA_D]]) |
| // OGCG: ret void |
| |
| // OGCG-LABEL: define internal void @"_ZZ13capture_mixedi1SEN3$_0D2Ev"( |
| // OGCG: %[[THIS3:.*]] = load ptr, ptr %this.addr |
| // OGCG: %[[FS_D:.*]] = getelementptr inbounds nuw %[[LAM_TY_3]], ptr %[[THIS3]], i32 0, i32 1 |
| // OGCG: call void @_ZN1SD1Ev(ptr {{.*}} %[[FS_D]]) |
| // OGCG: ret void |
| |
| // OGCG-LABEL: define internal void @"_ZZ13capture_localvEN3$_0D2Ev"( |
| // OGCG: %[[THIS4:.*]] = load ptr, ptr %this.addr |
| // OGCG: %[[FL_D:.*]] = getelementptr inbounds nuw %[[LAM_TY_4]], ptr %[[THIS4]], i32 0, i32 0 |
| // OGCG: call void @_ZN1SD1Ev(ptr {{.*}} %[[FL_D]]) |
| // OGCG: ret void |
| |
| // OGCG-LABEL: define internal void @"_ZZ16stmt_expr_returnbEN3$_0D2Ev"( |
| // OGCG: %[[THIS5:.*]] = load ptr, ptr %this.addr |
| // OGCG: %[[FB5_D:.*]] = getelementptr inbounds nuw %[[LAM_TY_5]], ptr %[[THIS5]], i32 0, i32 1 |
| // OGCG: call void @_ZN1SD1Ev(ptr {{.*}} %[[FB5_D]]) |
| // OGCG: %[[FA5_D:.*]] = getelementptr inbounds nuw %[[LAM_TY_5]], ptr %[[THIS5]], i32 0, i32 0 |
| // OGCG: call void @_ZN1SD1Ev(ptr {{.*}} %[[FA5_D]]) |
| // OGCG: ret void |