diff --git a/clang/lib/CIR/CodeGen/CIRRecordLayoutBuilder.cpp b/clang/lib/CIR/CodeGen/CIRRecordLayoutBuilder.cpp index 2d3bdb522171..c4edbee33dea 100644 --- a/clang/lib/CIR/CodeGen/CIRRecordLayoutBuilder.cpp +++ b/clang/lib/CIR/CodeGen/CIRRecordLayoutBuilder.cpp @@ -364,7 +364,7 @@ void CIRRecordLowering::lowerUnion() { } // If we have no storage type just pad to the appropriate size and return. if (!StorageType) - llvm_unreachable("no-storage union NYI"); + return appendPaddingBytes(LayoutSize); // If our storage size was bigger than our required size (can happen in the // case of packed bitfields on Itanium) then just use an I8 array. if (LayoutSize < getSize(StorageType)) diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp index e34232af2d83..a1fa1f7067b0 100644 --- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp @@ -453,8 +453,9 @@ RecordType::computeUnionSize(const mlir::DataLayout &dataLayout) const { unsigned recordSize = 0; llvm::Align recordAlignment{1}; - auto largestMember = getLargestMember(dataLayout); - recordSize = dataLayout.getTypeSize(largestMember); + Type largestMember = getLargestMember(dataLayout); + if (largestMember) + recordSize = dataLayout.getTypeSize(largestMember); // If the union is padded, add the padding to the size. if (getPadded()) { @@ -517,7 +518,10 @@ RecordType::computeStructAlignment(const mlir::DataLayout &dataLayout) const { uint64_t RecordType::computeUnionAlignment(const mlir::DataLayout &dataLayout) const { - auto largestMember = getLargestMember(dataLayout); + Type largestMember = getLargestMember(dataLayout); + // use 1 byte alignment for empty union + if (!largestMember) + return 1; return dataLayout.getTypeABIAlignment(largestMember); } diff --git a/clang/test/CIR/CodeGen/union-empty.cpp b/clang/test/CIR/CodeGen/union-empty.cpp new file mode 100644 index 000000000000..9fab3134e190 --- /dev/null +++ b/clang/test/CIR/CodeGen/union-empty.cpp @@ -0,0 +1,22 @@ +// 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 -fclangir -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s --check-prefix=LLVM + +union EmptyUnion { + EmptyUnion() = default; +}; + +void f0() { + EmptyUnion e; +}; + +// CIR: !rec_EmptyUnion = !cir.record +// CIR: cir.func dso_local @_Z2f0v() +// CIR: %0 = cir.alloca !rec_EmptyUnion, !cir.ptr, ["e"] {alignment = 1 : i64} +// CIR: cir.return + +// LLVM: %union.EmptyUnion = type { i8 } +// LLVM: define dso_local void @_Z2f0v() +// LLVM: %1 = alloca %union.EmptyUnion, i64 1, align 1 +// LLVM: ret void