[clang] 87789e2 - [CIR] Handle non-zero-initializable types in emitNullInitialization (#201654)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 23 10:47:28 PDT 2026
Author: adams381
Date: 2026-06-23T12:47:22-05:00
New Revision: 87789e236d9de4b8d688a0d7291c7390fc2c58b4
URL: https://github.com/llvm/llvm-project/commit/87789e236d9de4b8d688a0d7291c7390fc2c58b4
DIFF: https://github.com/llvm/llvm-project/commit/87789e236d9de4b8d688a0d7291c7390fc2c58b4.diff
LOG: [CIR] Handle non-zero-initializable types in emitNullInitialization (#201654)
Value-initializing an aggregate containing a pointer-to-data-member
(e.g. `new Inner()` where `Inner` has an `int Inner::*` field) crashed
with "type is not zero initializable" because `emitNullInitialization`
unconditionally called `errorNYI` for types where `isZeroInitializable`
returns false.
Member pointers use -1 as the null sentinel, so a plain zero store is
incorrect. Replace the `errorNYI` with `emitNullConstant`, which already
builds the correct per-field pattern (-1 for member-pointer fields, zero
elsewhere), and store the result. Types with virtual bases are still
guarded with `errorNYI` since `emitNullConstant` does not yet handle
them.
Added:
clang/test/CIR/CodeGen/member-pointer-null-init.cpp
Modified:
clang/lib/CIR/CodeGen/CIRGenFunction.cpp
Removed:
################################################################################
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index 4b020c96964a7..6606cf74c7dea 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -1385,7 +1385,15 @@ void CIRGenFunction::emitNullInitialization(mlir::Location loc, Address destPtr,
// TODO: there are other patterns besides zero that we can usefully memset,
// like -1, which happens to be the pattern used by member-pointers.
if (!cgm.getTypes().isZeroInitializable(ty)) {
- cgm.errorNYI(loc, "type is not zero initializable");
+ // Only the pointer-to-data-member case is tested here; emitNullConstant
+ // owns the NYIs for shapes it cannot build (virtual bases, non-zero-init
+ // arrays).
+ assert((ty->isMemberDataPointerType() || ty->isRecordType()) &&
+ "emitNullInitialization: only pointer-to-data-member (directly or "
+ "within a record) null initialization is implemented");
+ mlir::Value nullVal = cgm.emitNullConstant(ty, loc);
+ builder.createStore(loc, nullVal, destPtr);
+ return;
}
// In LLVM Codegen: otherwise, just memset the whole thing to zero using
diff --git a/clang/test/CIR/CodeGen/member-pointer-null-init.cpp b/clang/test/CIR/CodeGen/member-pointer-null-init.cpp
new file mode 100644
index 0000000000000..74ee344c6f407
--- /dev/null
+++ b/clang/test/CIR/CodeGen/member-pointer-null-init.cpp
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --check-prefix=LLVM,LLVMCIR --input-file=%t-cir.ll %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefix=LLVM,OGCG --input-file=%t.ll %s
+
+struct Inner {
+ int Inner::*p;
+};
+
+struct Outer {
+ Inner a;
+ int b;
+};
+
+// Value-init of a heap-allocated struct containing a pointer-to-data-member.
+// The member pointer is null (-1), so the stored constant must carry -1.
+
+// CIR-LABEL: cir.func {{.*}}@_Z8make_newv
+// CIR: [[NULL:%.*]] = cir.const #cir.const_record<{#cir.int<-1> : !s64i}> : !rec_Inner
+// CIR: cir.store align(8) [[NULL]], {{%.*}} : !rec_Inner, !cir.ptr<!rec_Inner>
+
+// LLVMCIR-LABEL: define {{.*}} ptr @_Z8make_newv
+// LLVMCIR: call {{.*}} @_Znwm
+// LLVMCIR: store %struct.Inner { i64 -1 }, ptr %{{.*}}, align 8
+
+// OGCG: @{{.*}} = private constant %struct.Inner { i64 -1 }
+// OGCG-LABEL: define {{.*}} ptr @_Z8make_newv
+// OGCG: call {{.*}} @llvm.memcpy{{.*}}i64 8
+
+Inner *make_new() { return new Inner(); }
+
+// Partial aggregate init: Inner subobject 'a' is value-initialized because
+// it has no designated initializer.
+
+// CIR-LABEL: cir.func {{.*}}@_Z11runtime_aggi
+// CIR: cir.const #cir.int<-1> : !s64i
+// CIR: cir.store align(8) {{%.*}}, {{%.*}} : !s64i
+
+// LLVM-LABEL: define {{.*}} void @_Z11runtime_aggi
+// LLVM: store i64 -1, ptr %{{.*}}, align 8
+
+void runtime_agg(int x) {
+ Outer o = {.b = x};
+ (void)o;
+}
More information about the cfe-commits
mailing list