Skip to content

Commit c947dc7

Browse files
[CIR][CodeGen] Implement union cast (#867)
Currently the C style cast is not implemented/supported for unions. This PR adds support for union casts as done in `CGExprAgg.cpp`. I have also added an extra test in `union-init.c`.
1 parent 923264b commit c947dc7

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,22 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
980980
break;
981981
}
982982

983+
case CK_ToUnion: {
984+
// Evaluate even if the destination is ignored.
985+
if (Dest.isIgnored()) {
986+
CGF.buildAnyExpr(E->getSubExpr(), AggValueSlot::ignored(),
987+
/*ignoreResult=*/true);
988+
break;
989+
}
990+
991+
// GCC union extension
992+
QualType Ty = E->getSubExpr()->getType();
993+
Address CastPtr = Dest.getAddress().withElementType(CGF.ConvertType(Ty));
994+
buildInitializationToLValue(E->getSubExpr(),
995+
CGF.makeAddrLValue(CastPtr, Ty));
996+
break;
997+
}
998+
983999
case CK_LValueToRValue:
9841000
// If we're loading from a volatile type, force the destination
9851001
// into existence.

clang/test/CIR/CodeGen/union-init.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,19 @@ unsigned is_little(void) {
4545
// CHECK: cir.func @is_little
4646
// CHECK: %[[VAL_1:.*]] = cir.get_global @is_little.one : !cir.ptr<![[anon0]]>
4747
// CHECK: %[[VAL_2:.*]] = cir.cast(bitcast, %[[VAL_1]] : !cir.ptr<![[anon0]]>), !cir.ptr<![[anon1]]>
48-
// CHECK: %[[VAL_3:.*]] = cir.get_member %[[VAL_2]][1] {name = "c"} : !cir.ptr<![[anon1]]> -> !cir.ptr<!cir.array<!u8i x 4>>
48+
// CHECK: %[[VAL_3:.*]] = cir.get_member %[[VAL_2]][1] {name = "c"} : !cir.ptr<![[anon1]]> -> !cir.ptr<!cir.array<!u8i x 4>>
49+
50+
typedef union {
51+
int x;
52+
} U;
53+
54+
// CHECK: %[[VAL_0:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init] {alignment = 4 : i64}
55+
// CHECK: %[[VAL_1:.*]] = cir.alloca !ty_U, !cir.ptr<!ty_U>, ["u", init] {alignment = 4 : i64}
56+
// CHECK: cir.store %arg0, %[[VAL_0]] : !s32i, !cir.ptr<!s32i>
57+
// CHECK: %[[VAL_2:.*]] = cir.load %[[VAL_0]] : !cir.ptr<!s32i>, !s32i
58+
// CHECK: %[[VAL_3:.*]] = cir.cast(bitcast, %[[VAL_1]] : !cir.ptr<!ty_U>), !cir.ptr<!s32i>
59+
// CHECK: cir.store %[[VAL_2]], %[[VAL_3]] : !s32i, !cir.ptr<!s32i>
60+
61+
void union_cast(int x) {
62+
U u = (U) x;
63+
}

0 commit comments

Comments
 (0)