Morris Hafner b5e5794534
[CIR] Implement Statement Expressions (#153677)
Depends on #153625

This patch adds support for statement expressions. It also changes
emitCompoundStmt and emitCompoundStmtWithoutScope to accept an Address
that the optional result is written to. This allows the creation of the
alloca ahead of the creation of the scope which saves us from hoisting
the alloca to its parent scope.
2025-08-19 10:11:15 +02:00

91 lines
3.0 KiB
C++

// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mconstructor-aliases -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mconstructor-aliases -fclangir -emit-llvm %s -o %t-cir.ll
// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mconstructor-aliases -emit-llvm %s -o %t.ll
// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG
class A {
public:
A(): x(0) {}
A(A &a) : x(a.x) {}
int x;
void Foo() {}
};
void test1() {
({
A a;
a;
}).Foo();
}
// CIR: cir.func dso_local @_Z5test1v()
// CIR: cir.scope {
// CIR: %[[REF_TMP0:.+]] = cir.alloca !rec_A, !cir.ptr<!rec_A>, ["ref.tmp0"]
// CIR: %[[TMP:.+]] = cir.alloca !rec_A, !cir.ptr<!rec_A>, ["tmp"]
// CIR: cir.scope {
// CIR: %[[A:.+]] = cir.alloca !rec_A, !cir.ptr<!rec_A>, ["a", init]
// CIR: cir.call @_ZN1AC2Ev(%[[A]]) : (!cir.ptr<!rec_A>) -> ()
// CIR: cir.call @_ZN1AC2ERS_(%[[REF_TMP0]], %[[A]]) : (!cir.ptr<!rec_A>, !cir.ptr<!rec_A>) -> ()
// CIR: }
// CIR: cir.call @_ZN1A3FooEv(%[[REF_TMP0]]) : (!cir.ptr<!rec_A>) -> ()
// CIR: }
// CIR: cir.return
// LLVM: define dso_local void @_Z5test1v()
// LLVM: %[[VAR1:.+]] = alloca %class.A, i64 1
// LLVM: %[[VAR2:.+]] = alloca %class.A, i64 1
// LLVM: %[[VAR3:.+]] = alloca %class.A, i64 1
// LLVM: br label %[[LBL4:.+]]
// LLVM: [[LBL4]]:
// LLVM: br label %[[LBL5:.+]]
// LLVM: [[LBL5]]:
// LLVM: call void @_ZN1AC2Ev(ptr %[[VAR3]])
// LLVM: call void @_ZN1AC2ERS_(ptr %[[VAR1]], ptr %[[VAR3]])
// LLVM: br label %[[LBL6:.+]]
// LLVM: [[LBL6]]:
// LLVM: call void @_ZN1A3FooEv(ptr %[[VAR1]])
// LLVM: br label %[[LBL7:.+]]
// LLVM: [[LBL7]]:
// LLVM: ret void
// OGCG: define dso_local void @_Z5test1v()
// OGCG: entry:
// OGCG: %[[REF_TMP:.+]] = alloca %class.A
// OGCG: %[[A:.+]] = alloca %class.A
// OGCG: call void @_ZN1AC2Ev(ptr {{.*}} %[[A]])
// OGCG: call void @_ZN1AC2ERS_(ptr {{.*}} %[[REF_TMP]], ptr {{.*}} %[[A]])
// OGCG: call void @_ZN1A3FooEv(ptr {{.*}} %[[REF_TMP]])
// OGCG: ret void
struct with_dtor {
~with_dtor();
};
void cleanup() {
({ with_dtor wd; });
}
// CIR: cir.func dso_local @_Z7cleanupv()
// CIR: cir.scope {
// CIR: %[[WD:.+]] = cir.alloca !rec_with_dtor, !cir.ptr<!rec_with_dtor>, ["wd"]
// CIR: cir.call @_ZN9with_dtorD1Ev(%[[WD]]) nothrow : (!cir.ptr<!rec_with_dtor>) -> ()
// CIR: }
// CIR: cir.return
// LLVM: define dso_local void @_Z7cleanupv()
// LLVM: %[[WD:.+]] = alloca %struct.with_dtor, i64 1
// LLVM: br label %[[LBL2:.+]]
// LLVM: [[LBL2]]:
// LLVM: call void @_ZN9with_dtorD1Ev(ptr %[[WD]])
// LLVM: br label %[[LBL3:.+]]
// LLVM: [[LBL3]]:
// LLVM: ret void
// OGCG: define dso_local void @_Z7cleanupv()
// OGCG: entry:
// OGCG: %[[WD:.+]] = alloca %struct.with_dtor
// OGCG: call void @_ZN9with_dtorD1Ev(ptr {{.*}} %[[WD]])
// OGCG: ret void