Skip to content

Conversation

@AmrDeveloper
Copy link
Member

Implement StmtExpr for ComplexType

@llvmbot llvmbot added clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project labels Dec 8, 2025
@llvmbot
Copy link
Member

llvmbot commented Dec 8, 2025

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clangir

Author: Amr Hesham (AmrDeveloper)

Changes

Implement StmtExpr for ComplexType


Full diff: https://github.com/llvm/llvm-project/pull/171196.diff

2 Files Affected:

  • (modified) clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp (+7-2)
  • (modified) clang/test/CIR/CodeGen/stmt-expr.cpp (+43)
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
index fe06f8cc2c430..d1124252e13cd 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
@@ -400,8 +400,13 @@ mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *e) {
 }
 
 mlir::Value ComplexExprEmitter::VisitStmtExpr(const StmtExpr *e) {
-  cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitExpr");
-  return {};
+  CIRGenFunction::StmtExprEvaluation eval(cgf);
+  Address retAlloca =
+      cgf.createMemTemp(e->getType(), cgf.getLoc(e->getSourceRange()));
+  (void)cgf.emitCompoundStmt(*e->getSubStmt(), &retAlloca);
+  assert(retAlloca.isValid() && "Expected complex return value");
+  return emitLoadOfLValue(cgf.makeAddrLValue(retAlloca, e->getType()),
+                          e->getExprLoc());
 }
 
 mlir::Value ComplexExprEmitter::emitComplexToComplexCast(mlir::Value val,
diff --git a/clang/test/CIR/CodeGen/stmt-expr.cpp b/clang/test/CIR/CodeGen/stmt-expr.cpp
index f65bf9b7e010f..b645b15087ec5 100644
--- a/clang/test/CIR/CodeGen/stmt-expr.cpp
+++ b/clang/test/CIR/CodeGen/stmt-expr.cpp
@@ -88,3 +88,46 @@ void cleanup() {
 // OGCG:   %[[WD:.+]] = alloca %struct.with_dtor
 // OGCG:   call void @_ZN9with_dtorD1Ev(ptr {{.*}} %[[WD]])
 // OGCG:   ret void
+
+void gnu_statement_extension() {
+  float b = __real__ ({float _Complex a; a;});
+}
+
+// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b", init]
+// CIR: %[[TMP_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["tmp"]
+// CIR: cir.scope {
+// CIR:   %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]
+// CIR:   %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
+// CIR:   cir.store {{.*}} %[[TMP_A]], %[[TMP_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
+// CIR: }
+// CIR: %[[TMP:.*]] = cir.load {{.*}} %[[TMP_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
+// CIR: %[[REAL:.*]] = cir.complex.real %[[TMP]] : !cir.complex<!cir.float> -> !cir.float
+// CIR: cir.store {{.*}} %[[REAL]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float>
+
+// LLVM:   %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4
+// LLVM:   %[[B_ADDR:.*]] = alloca float, i64 1, align 4
+// LLVM:   %[[TMP_ADDR:.*]] = alloca { float, float }, i64 1, align 4
+// LLVM:   br label %[[LABEL_1:.*]]
+// LLVM: [[LABEL_1]]:
+// LLVM:   %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4
+// LLVM:   store { float, float } %[[TMP_A]], ptr %[[TMP_ADDR]], align 4
+// LLVM:   br label %[[LABEL_2:.*]]
+// LLVM: [[LABEL_2]]:
+// LLVM:   %[[TMP:.*]] = load { float, float }, ptr %[[TMP_ADDR]], align 4
+// LLVM:   %[[REAL:.*]] = extractvalue { float, float } %[[TMP]], 0
+// LLVM:   store float %[[REAL]], ptr %[[B_ADDR]], align 4
+
+// OGCG: %[[B_ADDR:.*]] = alloca float, align 4
+// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4
+// OGCG: %[[TMP_ADDR:.*]] = alloca { float, float }, align 4
+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0
+// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4
+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1
+// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4
+// OGCG: %[[TMP_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[TMP_ADDR]], i32 0, i32 0
+// OGCG: %[[TMP_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[TMP_ADDR]], i32 0, i32 1
+// OGCG: store float %[[A_REAL]], ptr %[[TMP_REAL_PTR]], align 4
+// OGCG: store float %[[A_IMAG]], ptr %[[TMP_IMAG_PTR]], align 4
+// OGCG: %[[TMP_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[TMP_ADDR]], i32 0, i32 0
+// OGCG: %[[TMP_REAL:.*]] = load float, ptr %[[TMP_REAL_PTR]], align 4
+// OGCG: store float %[[TMP_REAL]], ptr %[[B_ADDR]], align 4

Copy link
Contributor

@andykaylor andykaylor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@AmrDeveloper AmrDeveloper merged commit a94f01a into llvm:main Dec 9, 2025
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants