[CIR] ConstRecordBuilder check if attribute present before casting (#164575)
Fix the crash because in `ConstRecordBuilder::build` we cast to
TypedAttr then we check if it null, but in case that the result from
emitter is nullptr, that cast crash, In this PR I fixed the order to
check first if it not null, then casting to the TypedAttr
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index 8f05014..7de3dd0 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -627,10 +627,7 @@
}
bool ConstRecordBuilder::build(InitListExpr *ile, bool allowOverwrite) {
- RecordDecl *rd = ile->getType()
- ->castAs<clang::RecordType>()
- ->getDecl()
- ->getDefinitionOrSelf();
+ RecordDecl *rd = ile->getType()->castAsRecordDecl();
const ASTRecordLayout &layout = cgm.getASTContext().getASTRecordLayout(rd);
// Bail out if we have base classes. We could support these, but they only
@@ -686,17 +683,14 @@
return false;
}
- mlir::TypedAttr eltInit;
- if (init)
- eltInit = mlir::cast<mlir::TypedAttr>(
- emitter.tryEmitPrivateForMemory(init, field->getType()));
- else
- eltInit = mlir::cast<mlir::TypedAttr>(emitter.emitNullForMemory(
- cgm.getLoc(ile->getSourceRange()), field->getType()));
-
- if (!eltInit)
+ mlir::Attribute eltInitAttr =
+ init ? emitter.tryEmitPrivateForMemory(init, field->getType())
+ : emitter.emitNullForMemory(cgm.getLoc(ile->getSourceRange()),
+ field->getType());
+ if (!eltInitAttr)
return false;
+ mlir::TypedAttr eltInit = mlir::cast<mlir::TypedAttr>(eltInitAttr);
if (!field->isBitField()) {
// Handle non-bitfield members.
if (!appendField(field, layout.getFieldOffset(index), eltInit,
diff --git a/clang/test/CIR/CodeGen/struct-init.cpp b/clang/test/CIR/CodeGen/struct-init.cpp
index 63e13dd..7988619 100644
--- a/clang/test/CIR/CodeGen/struct-init.cpp
+++ b/clang/test/CIR/CodeGen/struct-init.cpp
@@ -40,6 +40,23 @@
// LLVM: @swdi = global %struct.StructWithDefaultInit { i32 2 }, align 4
// OGCG: @swdi = global %struct.StructWithDefaultInit { i32 2 }, align 4
+struct StructWithFieldInitFromConst {
+ int a : 10;
+ int b = a;
+};
+
+StructWithFieldInitFromConst swfifc = {};
+
+// CIR: cir.global external @swfifc = #cir.zero : !rec_anon_struct
+// LLVM: @swfifc = global { i8, i8, i32 } zeroinitializer, align 4
+// OGCG: @swfifc = global { i8, i8, i32 } zeroinitializer, align 4
+
+StructWithFieldInitFromConst swfifc2 = { 2 };
+
+// CIR: cir.global external @swfifc2 = #cir.const_record<{#cir.int<2> : !u8i, #cir.int<0> : !u8i, #cir.int<2> : !s32i}> : !rec_anon_struct
+// LLVM: @swfifc2 = global { i8, i8, i32 } { i8 2, i8 0, i32 2 }, align 4
+// OGCG: @swfifc2 = global { i8, i8, i32 } { i8 2, i8 0, i32 2 }, align 4
+
void init() {
S s1 = {1, 2, 3};
S s2 = {4, 5};