diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp b/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp index e6ae5289618d..3ad9d21eced9 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp @@ -95,7 +95,11 @@ void CIRGenBuilderTy::computeGlobalViewIndicesFromFlatOffset( unsigned AlignMask = Layout.getABITypeAlign(Elts[I]).value() - 1; if (RecordTy.getPacked()) AlignMask = 0; - Pos = (Pos + AlignMask) & ~AlignMask; + // Union's fields have the same offset, so no need to change Pos here, + // we just need to find EltSize that is greater then the required offset. + // The same is true for the similar union type check below + if (!RecordTy.isUnion()) + Pos = (Pos + AlignMask) & ~AlignMask; assert(Offset >= 0); if (Offset < Pos + EltSize) { Indices.push_back(I); @@ -103,7 +107,9 @@ void CIRGenBuilderTy::computeGlobalViewIndicesFromFlatOffset( Offset -= Pos; break; } - Pos += EltSize; + // No need to update Pos here, see the comment above. + if (!RecordTy.isUnion()) + Pos += EltSize; } } else { llvm_unreachable("unexpected type"); diff --git a/clang/test/CIR/CodeGen/union-array.c b/clang/test/CIR/CodeGen/union-array.c index 6b5fcb2c907e..27b6392bce2a 100644 --- a/clang/test/CIR/CodeGen/union-array.c +++ b/clang/test/CIR/CodeGen/union-array.c @@ -26,6 +26,7 @@ static U1 g = {5}; // LLVM: @g = internal global { i32 } { i32 5 } // FIXME: LLVM output should be: @g = internal global %union.U { i32 5 } +// LLVM: @g2 = global ptr getelementptr inbounds nuw (i8, ptr @g1, i64 24) void foo() { U arr[2] = {{.b = {1, 2}}, {.a = {1}}}; } @@ -37,3 +38,22 @@ void bar(void) { } // CIR: cir.global "private" internal dsolocal @g = #cir.const_record<{#cir.int<5> : !s32i}> : !rec_anon_struct // CIR: cir.const #cir.const_array<[#cir.global_view<@g> : !cir.ptr, #cir.global_view<@g> : !cir.ptr]> : !cir.array x 2> + +typedef struct { + long s0; + int s1; +} S_3; + +typedef union { + int f0; + S_3 f1; +} U2; + + +static U2 g1[3] = {{0x42},{0x42},{0x42}}; +int* g2 = &g1[1].f1.s1; +// CIR: cir.global external @g2 = #cir.global_view<@g1, [1, 1, 4]> : !cir.ptr + +void baz(void) { + (*g2) = 4; +}