https://github.com/erichkeane updated 
https://github.com/llvm/llvm-project/pull/191485

>From f670a4f78a0515ad0b4a1558f5d14ad58bc94394 Mon Sep 17 00:00:00 2001
From: erichkeane <[email protected]>
Date: Fri, 10 Apr 2026 10:44:47 -0700
Subject: [PATCH 1/2] [[CIR]] Implement 'to-union' cast.

This ends up being pretty trivial/can only really happen in 2 ways, the
only useful way is via an extension.  This patch implements this.

This doesn't really affect anything as it is a pretty rarely used
feature and thus doesn't appear in the test suite I've seen, but I saw
it while investigating something else.
---
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp          |  5 ++-
 clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp | 13 ++++++
 clang/test/CIR/CodeGen/casts.c                | 44 +++++++++++++++++++
 3 files changed, 61 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/CIR/CodeGen/casts.c

diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index a306cc68dff8e..cd3e4671ac106 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -1498,9 +1498,11 @@ LValue CIRGenFunction::emitCastLValue(const CastExpr *e) 
{
   }
 
   // These are never l-values; just use the aggregate emission code.
+  case CK_ToUnion:
+    return emitAggExprToLValue(e);
+
   case CK_NonAtomicToAtomic:
   case CK_AtomicToNonAtomic:
-  case CK_ToUnion:
   case CK_ObjCObjectLValueCast:
   case CK_VectorSplat:
   case CK_ConstructorConversion:
@@ -1514,6 +1516,7 @@ LValue CIRGenFunction::emitCastLValue(const CastExpr *e) {
 
     return {};
   }
+
   case CK_AddressSpaceConversion: {
     LValue lv = emitLValue(e->getSubExpr());
     QualType destTy = getContext().getPointerType(e->getType());
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index ffce8a6bf86a7..c5c30bb5e8cea 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -273,6 +273,19 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
              "Implicit cast types must be compatible");
       Visit(e->getSubExpr());
       break;
+    case CK_ToUnion: {
+      if (dest.isIgnored()) {
+        cgf.emitAnyExpr(e->getSubExpr(), AggValueSlot::ignored(),
+                        /*ignoreResult=*/true);
+        break;
+      }
+      QualType ty = e->getSubExpr()->getType();
+      Address castPtr = dest.getAddress().withElementType(cgf.getBuilder(),
+                                                          cgf.convertType(ty));
+      emitInitializationToLValue(e->getSubExpr(),
+                                 cgf.makeAddrLValue(castPtr, ty));
+      break;
+    }
     default:
       cgf.cgm.errorNYI(e->getSourceRange(),
                        std::string("AggExprEmitter: VisitCastExpr: ") +
diff --git a/clang/test/CIR/CodeGen/casts.c b/clang/test/CIR/CodeGen/casts.c
new file mode 100644
index 0000000000000..cce29c49d2039
--- /dev/null
+++ b/clang/test/CIR/CodeGen/casts.c
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -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 -Wno-unused-value 
-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 -Wno-unused-value 
-emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+
+union Union { int i; float f; };
+
+float getF();
+
+void toUnion() {
+  // CIR-LABEL: toUnion()
+  // LLVM-LABEL: toUnion()
+  //
+  (void)(union Union) getF();
+  // CIR: %[[F_FUNC:.*]] = cir.get_global @getF : !cir.ptr<!cir.func<(...) -> 
!cir.float>>
+  // CIR:  %[[F_CAST:.*]] = cir.cast bitcast %[[F_FUNC]] : 
!cir.ptr<!cir.func<(...) -> !cir.float>> -> !cir.ptr<!cir.func<() -> 
!cir.float>>
+  // CIR: cir.call %[[F_CAST:.*]]() : (!cir.ptr<!cir.func<() -> !cir.float>>) 
-> !cir.float
+  // CIR: cir.return
+
+  // LLVM: call float @getF()
+  // LLVM: ret void
+}
+
+// GCC assign-from-cast extension:
+union Union toUnionAssign() {
+  // CIR-LABEL: toUnionAssign()
+  // LLVM-LABEL: toUnionAssign()
+  //
+  // CIR: %[[RET_ALLOCA:.*]] = cir.alloca !rec_Union, !cir.ptr<!rec_Union>, 
["__retval"]
+  // LLVM: %[[RET_ALLOCA:.*]] = alloca %union.Union
+  union Union u;
+  u = (union Union)42;
+  // CIR: %[[UNION_TO_INT:.*]] = cir.cast bitcast %[[RET_ALLOCA]] : 
!cir.ptr<!rec_Union> -> !cir.ptr<!s32i>
+  // CIR: %[[INT42:.*]] = cir.const #cir.int<42>
+  // CIR: cir.store align(4) %[[INT42]], %[[UNION_TO_INT]] : !s32i, 
!cir.ptr<!s32i>
+  // LLVM: store i32 42, ptr %[[RET_ALLOCA]]
+  return u;
+  // CIR: %[[LOAD:.*]] = cir.load %[[RET_ALLOCA]] : !cir.ptr<!rec_Union>, 
!rec_Union
+  // CIR: cir.return %[[LOAD]]
+  // LLVM: %[[LOAD:.*]] = load %union.Union, ptr %[[RET_ALLOCA]]
+  // LLVM: ret %union.Union %[[LOAD]]
+}

>From f6eb8aca9b5d831f4a334ccf4d884dc8ee42ca46 Mon Sep 17 00:00:00 2001
From: erichkeane <[email protected]>
Date: Mon, 13 Apr 2026 05:59:52 -0700
Subject: [PATCH 2/2] Move test

---
 clang/test/CIR/CodeGen/{casts.c => cast.c} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename clang/test/CIR/CodeGen/{casts.c => cast.c} (100%)

diff --git a/clang/test/CIR/CodeGen/casts.c b/clang/test/CIR/CodeGen/cast.c
similarity index 100%
rename from clang/test/CIR/CodeGen/casts.c
rename to clang/test/CIR/CodeGen/cast.c

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to