https://github.com/vasu-the-sharma updated 
https://github.com/llvm/llvm-project/pull/176210

>From c3c8b0bf9ce0c27378aecd28c95c929ba34bf237 Mon Sep 17 00:00:00 2001
From: vasu-ibm <[email protected]>
Date: Thu, 15 Jan 2026 13:11:53 -0500
Subject: [PATCH 1/3] add coverage for null and alignment checks

---
 .../test/CodeGen/ubsan-aggregate-null-align.c | 507 ++++++++++++++++++
 1 file changed, 507 insertions(+)
 create mode 100644 clang/test/CodeGen/ubsan-aggregate-null-align.c

diff --git a/clang/test/CodeGen/ubsan-aggregate-null-align.c 
b/clang/test/CodeGen/ubsan-aggregate-null-align.c
new file mode 100644
index 0000000000000..da87f7bece163
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-aggregate-null-align.c
@@ -0,0 +1,507 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm 
-fsanitize=null,alignment -std=c11 -O0 %s -o %t.c.ll && FileCheck %s 
--check-prefixes=C,SHARED < %t.c.ll
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm 
-fsanitize=null,alignment -std=c++17 -x c++ -O0 %s -o %t.cxx.ll && FileCheck %s 
--check-prefixes=CXX,SHARED < %t.cxx.ll
+
+struct Small { int x; };
+struct Container { struct Small inner; };
+struct SmallWrapper { struct Small a; };
+
+extern void variadic_func(int, ...);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ============================================================================
+// TYPE VARIANT: plain
+// ============================================================================
+
+// --- OPERAND FORM: arr[idx] ---
+
+// SHARED-LABEL: define {{[^@]*}}@test_assign_plain_arr_idx
+// SHARED: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_assign_plain_arr_idx(struct Small *dest, 
struct Small arr[]) {
+  *dest = arr[0];
+}
+
+// SHARED-LABEL: define {{[^@]*}}@test_init_plain_arr_idx
+// SHARED: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_init_plain_arr_idx(struct Small arr[]) {
+  struct Small a = arr[0];
+}
+
+// SHARED-LABEL: define {{[^@]*}}@test_init_list_plain_arr_idx
+// SHARED: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_init_list_plain_arr_idx(struct Small 
arr[]) {
+  struct Small a[] = {arr[0]};
+}
+
+// SHARED-LABEL: define {{[^@]*}}@test_init_list_designate_plain_arr_idx
+// SHARED: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_init_list_designate_plain_arr_idx(struct 
Small arr[]) {
+  struct Small a[] = {[0] = arr[0]};
+}
+
+// SHARED-LABEL: define {{[^@]*}}@test_variadic_plain_arr_idx
+__attribute__((noinline)) void test_variadic_plain_arr_idx(struct Small arr[]) 
{
+  variadic_func(0, arr[0]);
+}
+
+// SHARED-LABEL: define {{[^@]*}}@test_nested_member_plain_arr_idx
+// SHARED: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_nested_member_plain_arr_idx(struct 
Container *c, struct Small arr[]) {
+  c->inner = arr[0];
+}
+
+// --- OPERAND FORM: *ap ---
+
+// SHARED-LABEL: define {{[^@]*}}@test_assign_plain_deref_ptr
+// SHARED: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_assign_plain_deref_ptr(struct Small *dest, 
struct Small *ap) {
+  *dest = *ap;
+}
+
+// SHARED-LABEL: define {{[^@]*}}@test_init_plain_deref_ptr
+// SHARED: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_init_plain_deref_ptr(struct Small *ap) {
+  struct Small a = *ap;
+}
+
+// SHARED-LABEL: define {{[^@]*}}@test_init_list_plain_deref_ptr
+// SHARED: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_init_list_plain_deref_ptr(struct Small 
*ap) {
+  struct Small a[] = {*ap};
+}
+
+// SHARED-LABEL: define {{[^@]*}}@test_init_list_designate_plain_deref_ptr
+// SHARED: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_init_list_designate_plain_deref_ptr(struct 
Small *ap) {
+  struct Small a[] = {[0] = *ap};
+}
+
+// SHARED-LABEL: define {{[^@]*}}@test_variadic_plain_deref_ptr
+__attribute__((noinline)) void test_variadic_plain_deref_ptr(struct Small *ap) 
{
+  variadic_func(0, *ap);
+}
+
+// SHARED-LABEL: define {{[^@]*}}@test_nested_member_plain_deref_ptr
+// SHARED: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_nested_member_plain_deref_ptr(struct 
Container *c, struct Small *ap) {
+  c->inner = *ap;
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+// ============================================================================
+// TYPE VARIANT: atomic (C only)
+// ============================================================================
+
+#ifndef __cplusplus
+
+// --- OPERAND FORM: arr[idx] ---
+
+// C-LABEL: define {{[^@]*}}@test_assign_atomic_arr_idx
+// C: call void @__ubsan_handle_type_mismatch_v1_abort
+__attribute__((noinline)) void test_assign_atomic_arr_idx(struct Small *dest, 
_Atomic(struct Small) arr[]) {
+  *dest = arr[0];
+}
+
+// C-LABEL: define {{[^@]*}}@test_init_atomic_arr_idx
+// C: call void @__ubsan_handle_type_mismatch_v1_abort
+__attribute__((noinline)) void test_init_atomic_arr_idx(_Atomic(struct Small) 
arr[]) {
+  struct Small a = arr[0];
+}
+
+// C-LABEL: define {{[^@]*}}@test_init_list_atomic_arr_idx
+// C: call void @__ubsan_handle_type_mismatch_v1_abort
+__attribute__((noinline)) void test_init_list_atomic_arr_idx(_Atomic(struct 
Small) arr[]) {
+  struct Small a[] = {arr[0]};
+}
+
+// C-LABEL: define {{[^@]*}}@test_init_list_designate_atomic_arr_idx
+// C: call void @__ubsan_handle_type_mismatch_v1_abort
+__attribute__((noinline)) void 
test_init_list_designate_atomic_arr_idx(_Atomic(struct Small) arr[]) {
+  struct Small a[] = {[0] = arr[0]};
+}
+
+// C-LABEL: define {{[^@]*}}@test_variadic_atomic_arr_idx
+__attribute__((noinline)) void test_variadic_atomic_arr_idx(_Atomic(struct 
Small) arr[]) {
+  variadic_func(0, arr[0]);
+}
+
+// C-LABEL: define {{[^@]*}}@test_nested_member_atomic_arr_idx
+// C: call void @__ubsan_handle_type_mismatch_v1_abort
+__attribute__((noinline)) void test_nested_member_atomic_arr_idx(struct 
Container *c, _Atomic(struct Small) arr[]) {
+  c->inner = arr[0];
+}
+
+// C-LABEL: define {{[^@]*}}@test_lvalue_to_rvalue_atomic_arr_idx
+// C: call void @__ubsan_handle_type_mismatch_v1_abort
+__attribute__((noinline)) void 
test_lvalue_to_rvalue_atomic_arr_idx(_Atomic(struct Small) arr[]) {
+  (void)arr[0];
+}
+
+// --- OPERAND FORM: *ap ---
+
+// C-LABEL: define {{[^@]*}}@test_assign_atomic_deref_ptr
+// C: call void @__ubsan_handle_type_mismatch_v1_abort
+__attribute__((noinline)) void test_assign_atomic_deref_ptr(struct Small 
*dest, _Atomic(struct Small) *ap) {
+  *dest = *ap;
+}
+
+// C-LABEL: define {{[^@]*}}@test_init_atomic_deref_ptr
+// C: call void @__ubsan_handle_type_mismatch_v1_abort
+__attribute__((noinline)) void test_init_atomic_deref_ptr(_Atomic(struct 
Small) *ap) {
+  struct Small a = *ap;
+}
+
+// C-LABEL: define {{[^@]*}}@test_init_list_atomic_deref_ptr
+// C: call void @__ubsan_handle_type_mismatch_v1_abort
+__attribute__((noinline)) void test_init_list_atomic_deref_ptr(_Atomic(struct 
Small) *ap) {
+  struct Small a[] = {*ap};
+}
+
+// C-LABEL: define {{[^@]*}}@test_init_list_designate_atomic_deref_ptr
+// C: call void @__ubsan_handle_type_mismatch_v1_abort
+__attribute__((noinline)) void 
test_init_list_designate_atomic_deref_ptr(_Atomic(struct Small) *ap) {
+  struct Small a[] = {[0] = *ap};
+}
+
+// C-LABEL: define {{[^@]*}}@test_variadic_atomic_deref_ptr
+__attribute__((noinline)) void test_variadic_atomic_deref_ptr(_Atomic(struct 
Small) *ap) {
+  variadic_func(0, *ap);
+}
+
+// C-LABEL: define {{[^@]*}}@test_nested_member_atomic_deref_ptr
+// C: call void @__ubsan_handle_type_mismatch_v1_abort
+__attribute__((noinline)) void test_nested_member_atomic_deref_ptr(struct 
Container *c, _Atomic(struct Small) *ap) {
+  c->inner = *ap;
+}
+
+// C-LABEL: define {{[^@]*}}@test_lvalue_to_rvalue_atomic_deref_ptr
+// C: call void @__ubsan_handle_type_mismatch_v1_abort
+__attribute__((noinline)) void 
test_lvalue_to_rvalue_atomic_deref_ptr(_Atomic(struct Small) *ap) {
+  (void)*ap;
+}
+
+#endif // !__cplusplus
+
+// ============================================================================
+// TYPE VARIANT: volatile (C only)
+// ============================================================================
+
+#ifndef __cplusplus
+
+// --- OPERAND FORM: arr[idx] ---
+
+// C-LABEL: define {{[^@]*}}@test_assign_volatile_arr_idx
+// C: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_assign_volatile_arr_idx(struct Small 
*dest, volatile struct Small arr[]) {
+  *dest = arr[0];
+}
+
+// C-LABEL: define {{[^@]*}}@test_init_volatile_arr_idx
+// C: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_init_volatile_arr_idx(volatile struct 
Small arr[]) {
+  struct Small a = arr[0];
+}
+
+// C-LABEL: define {{[^@]*}}@test_init_list_volatile_arr_idx
+// C: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_init_list_volatile_arr_idx(volatile struct 
Small arr[]) {
+  struct Small a[] = {arr[0]};
+}
+
+// C-LABEL: define {{[^@]*}}@test_init_list_designate_volatile_arr_idx
+// C: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void 
test_init_list_designate_volatile_arr_idx(volatile struct Small arr[]) {
+  struct Small a[] = {[0] = arr[0]};
+}
+
+// C-LABEL: define {{[^@]*}}@test_variadic_volatile_arr_idx
+__attribute__((noinline)) void test_variadic_volatile_arr_idx(volatile struct 
Small arr[]) {
+  variadic_func(0, arr[0]);
+}
+
+// C-LABEL: define {{[^@]*}}@test_nested_member_volatile_arr_idx
+// C: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_nested_member_volatile_arr_idx(struct 
Container *c, volatile struct Small arr[]) {
+  c->inner = arr[0];
+}
+
+// C-LABEL: define {{[^@]*}}@test_lvalue_to_rvalue_volatile_arr_idx
+// C: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_lvalue_to_rvalue_volatile_arr_idx(volatile 
struct Small arr[]) {
+  (void)arr[0];
+}
+
+// --- OPERAND FORM: *ap ---
+
+// C-LABEL: define {{[^@]*}}@test_assign_volatile_deref_ptr
+// C: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_assign_volatile_deref_ptr(struct Small 
*dest, volatile struct Small *ap) {
+  *dest = *ap;
+}
+
+// C-LABEL: define {{[^@]*}}@test_init_volatile_deref_ptr
+// C: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_init_volatile_deref_ptr(volatile struct 
Small *ap) {
+  struct Small a = *ap;
+}
+
+// C-LABEL: define {{[^@]*}}@test_init_list_volatile_deref_ptr
+// C: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_init_list_volatile_deref_ptr(volatile 
struct Small *ap) {
+  struct Small a[] = {*ap};
+}
+
+// C-LABEL: define {{[^@]*}}@test_init_list_designate_volatile_deref_ptr
+// C: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void 
test_init_list_designate_volatile_deref_ptr(volatile struct Small *ap) {
+  struct Small a[] = {[0] = *ap};
+}
+
+// C-LABEL: define {{[^@]*}}@test_variadic_volatile_deref_ptr
+__attribute__((noinline)) void test_variadic_volatile_deref_ptr(volatile 
struct Small *ap) {
+  variadic_func(0, *ap);
+}
+
+// C-LABEL: define {{[^@]*}}@test_nested_member_volatile_deref_ptr
+// C: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_nested_member_volatile_deref_ptr(struct 
Container *c, volatile struct Small *ap) {
+  c->inner = *ap;
+}
+
+// C-LABEL: define {{[^@]*}}@test_lvalue_to_rvalue_volatile_deref_ptr
+// C: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void 
test_lvalue_to_rvalue_volatile_deref_ptr(volatile struct Small *ap) {
+  (void)*ap;
+}
+
+#endif // !__cplusplus
+
+// ============================================================================
+// C++ ONLY: Additional initialization and operation forms
+// ============================================================================
+
+#ifdef __cplusplus
+
+extern "C" {
+
+// --- OPERAND FORM: arr[idx] with plain type ---
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_init_direct_plain_arr_idx
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_init_direct_plain_arr_idx(struct Small 
arr[]) {
+  struct Small a(arr[0]);
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_init_brace_plain_arr_idx
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_init_brace_plain_arr_idx(struct Small 
arr[]) {
+  struct Small a{arr[0]};
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_init_copy_list_plain_arr_idx
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_init_copy_list_plain_arr_idx(struct 
Small arr[]) {
+  struct Small a = {arr[0]};
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_new_direct_plain_arr_idx
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_new_direct_plain_arr_idx(struct Small 
arr[]) {
+  struct Small *a = new struct Small(arr[0]);
+  delete a;
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_new_brace_plain_arr_idx
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_new_brace_plain_arr_idx(struct Small 
arr[]) {
+  struct Small *a = new struct Small{arr[0]};
+  delete a;
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_functional_cast_plain_arr_idx
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_functional_cast_plain_arr_idx(struct 
Small arr[]) {
+  (void)Small(arr[0]);
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_functional_cast_brace_plain_arr_idx
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void 
test_cxx_functional_cast_brace_plain_arr_idx(struct Small arr[]) {
+  (void)Small{arr[0]};
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_static_cast_plain_arr_idx
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_static_cast_plain_arr_idx(struct Small 
arr[]) {
+  (void)static_cast<struct Small>(arr[0]);
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_c_cast_plain_arr_idx
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_c_cast_plain_arr_idx(struct Small 
arr[]) {
+  (void)(struct Small)(arr[0]);
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_member_init_plain_arr_idx
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_member_init_plain_arr_idx(struct Small 
arr[]) {
+  (void)new SmallWrapper{arr[0]};
+}
+
+// --- OPERAND FORM: *ap with plain type ---
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_init_direct_plain_deref_ptr
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_init_direct_plain_deref_ptr(struct 
Small *ap) {
+  struct Small a(*ap);
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_init_brace_plain_deref_ptr
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_init_brace_plain_deref_ptr(struct 
Small *ap) {
+  struct Small a{*ap};
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_init_copy_list_plain_deref_ptr
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_init_copy_list_plain_deref_ptr(struct 
Small *ap) {
+  struct Small a = {*ap};
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_new_direct_plain_deref_ptr
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_new_direct_plain_deref_ptr(struct 
Small *ap) {
+  struct Small *a = new struct Small(*ap);
+  delete a;
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_new_brace_plain_deref_ptr
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_new_brace_plain_deref_ptr(struct Small 
*ap) {
+  struct Small *a = new struct Small{*ap};
+  delete a;
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_functional_cast_plain_deref_ptr
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_functional_cast_plain_deref_ptr(struct 
Small *ap) {
+  (void)Small(*ap);
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_functional_cast_brace_plain_deref_ptr
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void 
test_cxx_functional_cast_brace_plain_deref_ptr(struct Small *ap) {
+  (void)Small{*ap};
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_static_cast_plain_deref_ptr
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_static_cast_plain_deref_ptr(struct 
Small *ap) {
+  (void)static_cast<struct Small>(*ap);
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_c_cast_plain_deref_ptr
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_c_cast_plain_deref_ptr(struct Small 
*ap) {
+  (void)(struct Small)(*ap);
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_member_init_plain_deref_ptr
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_member_init_plain_deref_ptr(struct 
Small *ap) {
+  (void)new SmallWrapper{*ap};
+}
+
+// --- VARIADIC with plain type ---
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_variadic_plain_arr_idx
+__attribute__((noinline)) void test_cxx_variadic_plain_arr_idx(struct Small 
arr[]) {
+  variadic_func(0, arr[0]);
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_variadic_plain_deref_ptr
+__attribute__((noinline)) void test_cxx_variadic_plain_deref_ptr(struct Small 
*ap) {
+  variadic_func(0, *ap);
+}
+
+// --- Explicit operator= calls ---
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_operator_assign_lhs_arr_idx
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_operator_assign_lhs_arr_idx(struct 
Small *dest, struct Small arr[]) {
+  dest->operator=(arr[0]);
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_operator_assign_lhs_deref_ptr
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_operator_assign_lhs_deref_ptr(struct 
Small *dest, struct Small *ap) {
+  dest->operator=(*ap);
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_operator_assign_obj_arr_idx
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_operator_assign_obj_arr_idx(struct 
Small arr[]) {
+  struct Small a;
+  a.operator=(arr[0]);
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_operator_assign_obj_deref_ptr
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_operator_assign_obj_deref_ptr(struct 
Small *ap) {
+  struct Small a;
+  a.operator=(*ap);
+}
+
+} // extern "C"
+
+// --- Virtual base initialization (cannot be extern "C") ---
+// Use a simple struct to ensure memcpy is used for the copy
+
+struct VirtualBaseSimple {
+  int x;
+};
+
+struct DerivedVirtualArrSimple : virtual VirtualBaseSimple {
+  __attribute__((noinline)) DerivedVirtualArrSimple(VirtualBaseSimple arr[]) : 
VirtualBaseSimple(arr[0]) {}
+};
+
+struct DerivedVirtualPtrSimple : virtual VirtualBaseSimple {
+  __attribute__((noinline)) DerivedVirtualPtrSimple(VirtualBaseSimple *ap) : 
VirtualBaseSimple(*ap) {}
+};
+
+// Force instantiation of constructors
+// The constructors are emitted inline after their first use, so we check them
+// in the order they appear: ArrSimple constructor, then wrapper for Ptr, then 
PtrSimple constructor
+
+extern "C" {
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_virtual_base_init_arr_idx
+__attribute__((noinline)) void 
test_cxx_virtual_base_init_arr_idx(VirtualBaseSimple arr[]) {
+  DerivedVirtualArrSimple d(arr);
+}
+
+}
+
+// Check the first constructor (DerivedVirtualArrSimple) - emitted after 
test_cxx_virtual_base_init_arr_idx
+// CXX-LABEL: define 
{{[^@]*}}@_ZN23DerivedVirtualArrSimpleC1EP17VirtualBaseSimple
+// CXX: call void @llvm.memcpy.p0.p0.i64
+
+extern "C" {
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_virtual_base_init_deref_ptr
+__attribute__((noinline)) void 
test_cxx_virtual_base_init_deref_ptr(VirtualBaseSimple *ap) {
+  DerivedVirtualPtrSimple d(ap);
+}
+
+}
+
+// Check the second constructor (DerivedVirtualPtrSimple) - emitted after 
test_cxx_virtual_base_init_deref_ptr
+// CXX-LABEL: define 
{{[^@]*}}@_ZN23DerivedVirtualPtrSimpleC1EP17VirtualBaseSimple
+// CXX: call void @llvm.memcpy.p0.p0.i64
+
+#endif // __cplusplus

>From 704d9c60efab711d0b7c05674d5caa35777fbf5d Mon Sep 17 00:00:00 2001
From: vasu-ibm <[email protected]>
Date: Mon, 19 Jan 2026 02:57:29 -0500
Subject: [PATCH 2/3] update ubsan-aggregate-null-align

---
 .../test/CodeGen/ubsan-aggregate-null-align.c | 28 +++++++++++--------
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/clang/test/CodeGen/ubsan-aggregate-null-align.c 
b/clang/test/CodeGen/ubsan-aggregate-null-align.c
index da87f7bece163..a49ea2c08e3e9 100644
--- a/clang/test/CodeGen/ubsan-aggregate-null-align.c
+++ b/clang/test/CodeGen/ubsan-aggregate-null-align.c
@@ -95,6 +95,8 @@ __attribute__((noinline)) void 
test_nested_member_plain_deref_ptr(struct Contain
 
 // ============================================================================
 // TYPE VARIANT: atomic (C only)
+// NOTE: Atomic struct operations use atomic load/store instructions and do not
+// go through EmitAggregateCopy, so UBSAN null/alignment checks are not 
emitted.
 // ============================================================================
 
 #ifndef __cplusplus
@@ -102,42 +104,43 @@ __attribute__((noinline)) void 
test_nested_member_plain_deref_ptr(struct Contain
 // --- OPERAND FORM: arr[idx] ---
 
 // C-LABEL: define {{[^@]*}}@test_assign_atomic_arr_idx
-// C: call void @__ubsan_handle_type_mismatch_v1_abort
+// C: load atomic i32
 __attribute__((noinline)) void test_assign_atomic_arr_idx(struct Small *dest, 
_Atomic(struct Small) arr[]) {
   *dest = arr[0];
 }
 
 // C-LABEL: define {{[^@]*}}@test_init_atomic_arr_idx
-// C: call void @__ubsan_handle_type_mismatch_v1_abort
+// C: load atomic i32
 __attribute__((noinline)) void test_init_atomic_arr_idx(_Atomic(struct Small) 
arr[]) {
   struct Small a = arr[0];
 }
 
 // C-LABEL: define {{[^@]*}}@test_init_list_atomic_arr_idx
-// C: call void @__ubsan_handle_type_mismatch_v1_abort
+// C: load atomic i32
 __attribute__((noinline)) void test_init_list_atomic_arr_idx(_Atomic(struct 
Small) arr[]) {
   struct Small a[] = {arr[0]};
 }
 
 // C-LABEL: define {{[^@]*}}@test_init_list_designate_atomic_arr_idx
-// C: call void @__ubsan_handle_type_mismatch_v1_abort
+// C: load atomic i32
 __attribute__((noinline)) void 
test_init_list_designate_atomic_arr_idx(_Atomic(struct Small) arr[]) {
   struct Small a[] = {[0] = arr[0]};
 }
 
 // C-LABEL: define {{[^@]*}}@test_variadic_atomic_arr_idx
+// C: load atomic i32
 __attribute__((noinline)) void test_variadic_atomic_arr_idx(_Atomic(struct 
Small) arr[]) {
   variadic_func(0, arr[0]);
 }
 
 // C-LABEL: define {{[^@]*}}@test_nested_member_atomic_arr_idx
-// C: call void @__ubsan_handle_type_mismatch_v1_abort
+// C: load atomic i32
 __attribute__((noinline)) void test_nested_member_atomic_arr_idx(struct 
Container *c, _Atomic(struct Small) arr[]) {
   c->inner = arr[0];
 }
 
 // C-LABEL: define {{[^@]*}}@test_lvalue_to_rvalue_atomic_arr_idx
-// C: call void @__ubsan_handle_type_mismatch_v1_abort
+// C: load atomic i32
 __attribute__((noinline)) void 
test_lvalue_to_rvalue_atomic_arr_idx(_Atomic(struct Small) arr[]) {
   (void)arr[0];
 }
@@ -145,42 +148,43 @@ __attribute__((noinline)) void 
test_lvalue_to_rvalue_atomic_arr_idx(_Atomic(stru
 // --- OPERAND FORM: *ap ---
 
 // C-LABEL: define {{[^@]*}}@test_assign_atomic_deref_ptr
-// C: call void @__ubsan_handle_type_mismatch_v1_abort
+// C: load atomic i32
 __attribute__((noinline)) void test_assign_atomic_deref_ptr(struct Small 
*dest, _Atomic(struct Small) *ap) {
   *dest = *ap;
 }
 
 // C-LABEL: define {{[^@]*}}@test_init_atomic_deref_ptr
-// C: call void @__ubsan_handle_type_mismatch_v1_abort
+// C: load atomic i32
 __attribute__((noinline)) void test_init_atomic_deref_ptr(_Atomic(struct 
Small) *ap) {
   struct Small a = *ap;
 }
 
 // C-LABEL: define {{[^@]*}}@test_init_list_atomic_deref_ptr
-// C: call void @__ubsan_handle_type_mismatch_v1_abort
+// C: load atomic i32
 __attribute__((noinline)) void test_init_list_atomic_deref_ptr(_Atomic(struct 
Small) *ap) {
   struct Small a[] = {*ap};
 }
 
 // C-LABEL: define {{[^@]*}}@test_init_list_designate_atomic_deref_ptr
-// C: call void @__ubsan_handle_type_mismatch_v1_abort
+// C: load atomic i32
 __attribute__((noinline)) void 
test_init_list_designate_atomic_deref_ptr(_Atomic(struct Small) *ap) {
   struct Small a[] = {[0] = *ap};
 }
 
 // C-LABEL: define {{[^@]*}}@test_variadic_atomic_deref_ptr
+// C: load atomic i32
 __attribute__((noinline)) void test_variadic_atomic_deref_ptr(_Atomic(struct 
Small) *ap) {
   variadic_func(0, *ap);
 }
 
 // C-LABEL: define {{[^@]*}}@test_nested_member_atomic_deref_ptr
-// C: call void @__ubsan_handle_type_mismatch_v1_abort
+// C: load atomic i32
 __attribute__((noinline)) void test_nested_member_atomic_deref_ptr(struct 
Container *c, _Atomic(struct Small) *ap) {
   c->inner = *ap;
 }
 
 // C-LABEL: define {{[^@]*}}@test_lvalue_to_rvalue_atomic_deref_ptr
-// C: call void @__ubsan_handle_type_mismatch_v1_abort
+// C: load atomic i32
 __attribute__((noinline)) void 
test_lvalue_to_rvalue_atomic_deref_ptr(_Atomic(struct Small) *ap) {
   (void)*ap;
 }

>From 4abb7d001d11ccae998f626da9e8515d41ad8a09 Mon Sep 17 00:00:00 2001
From: vasu-ibm <[email protected]>
Date: Tue, 3 Feb 2026 02:55:18 -0500
Subject: [PATCH 3/3] add arrays bounds check

---
 .../test/CodeGen/ubsan-aggregate-null-align.c | 205 +++++++++++++-----
 1 file changed, 151 insertions(+), 54 deletions(-)

diff --git a/clang/test/CodeGen/ubsan-aggregate-null-align.c 
b/clang/test/CodeGen/ubsan-aggregate-null-align.c
index a49ea2c08e3e9..706ac3d4d6055 100644
--- a/clang/test/CodeGen/ubsan-aggregate-null-align.c
+++ b/clang/test/CodeGen/ubsan-aggregate-null-align.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm 
-fsanitize=null,alignment -std=c11 -O0 %s -o %t.c.ll && FileCheck %s 
--check-prefixes=C,SHARED < %t.c.ll
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm 
-fsanitize=null,alignment -std=c++17 -x c++ -O0 %s -o %t.cxx.ll && FileCheck %s 
--check-prefixes=CXX,SHARED < %t.cxx.ll
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm 
-fsanitize=null,alignment,bounds -std=c11 -O0 %s -o %t.c.ll && FileCheck %s 
--check-prefixes=C,SHARED < %t.c.ll
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm 
-fsanitize=null,alignment,bounds -std=c++17 -x c++ -O0 %s -o %t.cxx.ll && 
FileCheck %s --check-prefixes=CXX,SHARED < %t.cxx.ll
 
 struct Small { int x; };
 struct Container { struct Small inner; };
@@ -19,36 +19,30 @@ extern "C" {
 
 // SHARED-LABEL: define {{[^@]*}}@test_assign_plain_arr_idx
 // SHARED: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_assign_plain_arr_idx(struct Small *dest, 
struct Small arr[]) {
+__attribute__((noinline)) void test_assign_plain_arr_idx(struct Small *dest, 
struct Small arr[4]) {
   *dest = arr[0];
 }
 
 // SHARED-LABEL: define {{[^@]*}}@test_init_plain_arr_idx
 // SHARED: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_init_plain_arr_idx(struct Small arr[]) {
+__attribute__((noinline)) void test_init_plain_arr_idx(struct Small arr[4]) {
   struct Small a = arr[0];
 }
 
 // SHARED-LABEL: define {{[^@]*}}@test_init_list_plain_arr_idx
 // SHARED: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_init_list_plain_arr_idx(struct Small 
arr[]) {
+__attribute__((noinline)) void test_init_list_plain_arr_idx(struct Small 
arr[4]) {
   struct Small a[] = {arr[0]};
 }
 
-// SHARED-LABEL: define {{[^@]*}}@test_init_list_designate_plain_arr_idx
-// SHARED: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_init_list_designate_plain_arr_idx(struct 
Small arr[]) {
-  struct Small a[] = {[0] = arr[0]};
-}
-
 // SHARED-LABEL: define {{[^@]*}}@test_variadic_plain_arr_idx
-__attribute__((noinline)) void test_variadic_plain_arr_idx(struct Small arr[]) 
{
+__attribute__((noinline)) void test_variadic_plain_arr_idx(struct Small 
arr[4]) {
   variadic_func(0, arr[0]);
 }
 
 // SHARED-LABEL: define {{[^@]*}}@test_nested_member_plain_arr_idx
 // SHARED: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_nested_member_plain_arr_idx(struct 
Container *c, struct Small arr[]) {
+__attribute__((noinline)) void test_nested_member_plain_arr_idx(struct 
Container *c, struct Small arr[4]) {
   c->inner = arr[0];
 }
 
@@ -72,12 +66,6 @@ __attribute__((noinline)) void 
test_init_list_plain_deref_ptr(struct Small *ap)
   struct Small a[] = {*ap};
 }
 
-// SHARED-LABEL: define {{[^@]*}}@test_init_list_designate_plain_deref_ptr
-// SHARED: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_init_list_designate_plain_deref_ptr(struct 
Small *ap) {
-  struct Small a[] = {[0] = *ap};
-}
-
 // SHARED-LABEL: define {{[^@]*}}@test_variadic_plain_deref_ptr
 __attribute__((noinline)) void test_variadic_plain_deref_ptr(struct Small *ap) 
{
   variadic_func(0, *ap);
@@ -89,14 +77,92 @@ __attribute__((noinline)) void 
test_nested_member_plain_deref_ptr(struct Contain
   c->inner = *ap;
 }
 
+// ============================================================================
+// ARRAY BOUNDS CHECKING
+// Tests for array out-of-bounds access, including past-the-end pointer cases.
+// Currently, bounds checking triggers for invalid indices but the planned fix
+// will also trigger when indexing generates a past-the-end pointer.
+// ============================================================================
+
+// --- In-bounds access (index 0 of array[4]) - should NOT trigger bounds 
error ---
+
+// SHARED-LABEL: define {{[^@]*}}@test_bounds_inbounds_idx0
+// SHARED: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_bounds_inbounds_idx0(struct Small *dest, 
struct Small arr[4]) {
+  *dest = arr[0];
+}
+
+// --- In-bounds access (index 3, last valid element of array[4]) ---
+
+// SHARED-LABEL: define {{[^@]*}}@test_bounds_inbounds_idx3
+// SHARED: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_bounds_inbounds_idx3(struct Small *dest, 
struct Small arr[4]) {
+  *dest = arr[3];
+}
+
+// --- Out-of-bounds access (index 4, past-the-end of array[4]) ---
+// This generates the past-the-end pointer. Currently no bounds check is 
emitted
+// for this case; the planned fix will add checking for past-the-end access.
+
+// SHARED-LABEL: define {{[^@]*}}@test_bounds_oob_past_end
+// SHARED: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_bounds_oob_past_end(struct Small *dest, 
struct Small arr[4]) {
+  *dest = arr[4];
+}
+
+// --- Out-of-bounds access (index 5, clearly beyond array[4]) ---
+
+// SHARED-LABEL: define {{[^@]*}}@test_bounds_oob_beyond
+// SHARED: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_bounds_oob_beyond(struct Small *dest, 
struct Small arr[4]) {
+  *dest = arr[5];
+}
+
+// --- Dynamic index bounds checking ---
+
+// SHARED-LABEL: define {{[^@]*}}@test_bounds_dynamic_idx
+// SHARED: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_bounds_dynamic_idx(struct Small *dest, 
struct Small arr[4], int idx) {
+  *dest = arr[idx];
+}
+
+// --- Bounds checking with initialization ---
+
+// SHARED-LABEL: define {{[^@]*}}@test_bounds_init_past_end
+// SHARED: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_bounds_init_past_end(struct Small arr[4]) {
+  struct Small a = arr[4];
+}
+
+// --- Bounds checking with nested member assignment ---
+
+// SHARED-LABEL: define {{[^@]*}}@test_bounds_nested_past_end
+// SHARED: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_bounds_nested_past_end(struct Container 
*c, struct Small arr[4]) {
+  c->inner = arr[4];
+}
+
+// --- Bounds checking in initializer list ---
+
+// SHARED-LABEL: define {{[^@]*}}@test_bounds_init_list_past_end
+// SHARED: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_bounds_init_list_past_end(struct Small 
arr[4]) {
+  struct Small a[] = {arr[4]};
+}
+
+// --- Bounds checking with variadic function ---
+
+// SHARED-LABEL: define {{[^@]*}}@test_bounds_variadic_past_end
+__attribute__((noinline)) void test_bounds_variadic_past_end(struct Small 
arr[4]) {
+  variadic_func(0, arr[4]);
+}
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
 
 // ============================================================================
 // TYPE VARIANT: atomic (C only)
-// NOTE: Atomic struct operations use atomic load/store instructions and do not
-// go through EmitAggregateCopy, so UBSAN null/alignment checks are not 
emitted.
 // ============================================================================
 
 #ifndef __cplusplus
@@ -105,43 +171,43 @@ __attribute__((noinline)) void 
test_nested_member_plain_deref_ptr(struct Contain
 
 // C-LABEL: define {{[^@]*}}@test_assign_atomic_arr_idx
 // C: load atomic i32
-__attribute__((noinline)) void test_assign_atomic_arr_idx(struct Small *dest, 
_Atomic(struct Small) arr[]) {
+__attribute__((noinline)) void test_assign_atomic_arr_idx(struct Small *dest, 
_Atomic(struct Small) arr[4]) {
   *dest = arr[0];
 }
 
 // C-LABEL: define {{[^@]*}}@test_init_atomic_arr_idx
 // C: load atomic i32
-__attribute__((noinline)) void test_init_atomic_arr_idx(_Atomic(struct Small) 
arr[]) {
+__attribute__((noinline)) void test_init_atomic_arr_idx(_Atomic(struct Small) 
arr[4]) {
   struct Small a = arr[0];
 }
 
 // C-LABEL: define {{[^@]*}}@test_init_list_atomic_arr_idx
 // C: load atomic i32
-__attribute__((noinline)) void test_init_list_atomic_arr_idx(_Atomic(struct 
Small) arr[]) {
+__attribute__((noinline)) void test_init_list_atomic_arr_idx(_Atomic(struct 
Small) arr[4]) {
   struct Small a[] = {arr[0]};
 }
 
 // C-LABEL: define {{[^@]*}}@test_init_list_designate_atomic_arr_idx
 // C: load atomic i32
-__attribute__((noinline)) void 
test_init_list_designate_atomic_arr_idx(_Atomic(struct Small) arr[]) {
+__attribute__((noinline)) void 
test_init_list_designate_atomic_arr_idx(_Atomic(struct Small) arr[4]) {
   struct Small a[] = {[0] = arr[0]};
 }
 
 // C-LABEL: define {{[^@]*}}@test_variadic_atomic_arr_idx
 // C: load atomic i32
-__attribute__((noinline)) void test_variadic_atomic_arr_idx(_Atomic(struct 
Small) arr[]) {
+__attribute__((noinline)) void test_variadic_atomic_arr_idx(_Atomic(struct 
Small) arr[4]) {
   variadic_func(0, arr[0]);
 }
 
 // C-LABEL: define {{[^@]*}}@test_nested_member_atomic_arr_idx
 // C: load atomic i32
-__attribute__((noinline)) void test_nested_member_atomic_arr_idx(struct 
Container *c, _Atomic(struct Small) arr[]) {
+__attribute__((noinline)) void test_nested_member_atomic_arr_idx(struct 
Container *c, _Atomic(struct Small) arr[4]) {
   c->inner = arr[0];
 }
 
 // C-LABEL: define {{[^@]*}}@test_lvalue_to_rvalue_atomic_arr_idx
 // C: load atomic i32
-__attribute__((noinline)) void 
test_lvalue_to_rvalue_atomic_arr_idx(_Atomic(struct Small) arr[]) {
+__attribute__((noinline)) void 
test_lvalue_to_rvalue_atomic_arr_idx(_Atomic(struct Small) arr[4]) {
   (void)arr[0];
 }
 
@@ -189,54 +255,50 @@ __attribute__((noinline)) void 
test_lvalue_to_rvalue_atomic_deref_ptr(_Atomic(st
   (void)*ap;
 }
 
-#endif // !__cplusplus
-
 // ============================================================================
 // TYPE VARIANT: volatile (C only)
 // ============================================================================
 
-#ifndef __cplusplus
-
 // --- OPERAND FORM: arr[idx] ---
 
 // C-LABEL: define {{[^@]*}}@test_assign_volatile_arr_idx
 // C: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_assign_volatile_arr_idx(struct Small 
*dest, volatile struct Small arr[]) {
+__attribute__((noinline)) void test_assign_volatile_arr_idx(struct Small 
*dest, volatile struct Small arr[4]) {
   *dest = arr[0];
 }
 
 // C-LABEL: define {{[^@]*}}@test_init_volatile_arr_idx
 // C: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_init_volatile_arr_idx(volatile struct 
Small arr[]) {
+__attribute__((noinline)) void test_init_volatile_arr_idx(volatile struct 
Small arr[4]) {
   struct Small a = arr[0];
 }
 
 // C-LABEL: define {{[^@]*}}@test_init_list_volatile_arr_idx
 // C: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_init_list_volatile_arr_idx(volatile struct 
Small arr[]) {
+__attribute__((noinline)) void test_init_list_volatile_arr_idx(volatile struct 
Small arr[4]) {
   struct Small a[] = {arr[0]};
 }
 
 // C-LABEL: define {{[^@]*}}@test_init_list_designate_volatile_arr_idx
 // C: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void 
test_init_list_designate_volatile_arr_idx(volatile struct Small arr[]) {
+__attribute__((noinline)) void 
test_init_list_designate_volatile_arr_idx(volatile struct Small arr[4]) {
   struct Small a[] = {[0] = arr[0]};
 }
 
 // C-LABEL: define {{[^@]*}}@test_variadic_volatile_arr_idx
-__attribute__((noinline)) void test_variadic_volatile_arr_idx(volatile struct 
Small arr[]) {
+__attribute__((noinline)) void test_variadic_volatile_arr_idx(volatile struct 
Small arr[4]) {
   variadic_func(0, arr[0]);
 }
 
 // C-LABEL: define {{[^@]*}}@test_nested_member_volatile_arr_idx
 // C: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_nested_member_volatile_arr_idx(struct 
Container *c, volatile struct Small arr[]) {
+__attribute__((noinline)) void test_nested_member_volatile_arr_idx(struct 
Container *c, volatile struct Small arr[4]) {
   c->inner = arr[0];
 }
 
 // C-LABEL: define {{[^@]*}}@test_lvalue_to_rvalue_volatile_arr_idx
 // C: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_lvalue_to_rvalue_volatile_arr_idx(volatile 
struct Small arr[]) {
+__attribute__((noinline)) void test_lvalue_to_rvalue_volatile_arr_idx(volatile 
struct Small arr[4]) {
   (void)arr[0];
 }
 
@@ -283,6 +345,20 @@ __attribute__((noinline)) void 
test_lvalue_to_rvalue_volatile_deref_ptr(volatile
   (void)*ap;
 }
 
+// --- Designated initializers (C only) ---
+
+// C-LABEL: define {{[^@]*}}@test_init_list_designate_plain_arr_idx
+// C: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_init_list_designate_plain_arr_idx(struct 
Small arr[4]) {
+  struct Small a[] = {[0] = arr[0]};
+}
+
+// C-LABEL: define {{[^@]*}}@test_init_list_designate_plain_deref_ptr
+// C: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_init_list_designate_plain_deref_ptr(struct 
Small *ap) {
+  struct Small a[] = {[0] = *ap};
+}
+
 #endif // !__cplusplus
 
 // ============================================================================
@@ -297,63 +373,63 @@ extern "C" {
 
 // CXX-LABEL: define {{[^@]*}}@test_cxx_init_direct_plain_arr_idx
 // CXX: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_cxx_init_direct_plain_arr_idx(struct Small 
arr[]) {
+__attribute__((noinline)) void test_cxx_init_direct_plain_arr_idx(struct Small 
arr[4]) {
   struct Small a(arr[0]);
 }
 
 // CXX-LABEL: define {{[^@]*}}@test_cxx_init_brace_plain_arr_idx
 // CXX: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_cxx_init_brace_plain_arr_idx(struct Small 
arr[]) {
+__attribute__((noinline)) void test_cxx_init_brace_plain_arr_idx(struct Small 
arr[4]) {
   struct Small a{arr[0]};
 }
 
 // CXX-LABEL: define {{[^@]*}}@test_cxx_init_copy_list_plain_arr_idx
 // CXX: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_cxx_init_copy_list_plain_arr_idx(struct 
Small arr[]) {
+__attribute__((noinline)) void test_cxx_init_copy_list_plain_arr_idx(struct 
Small arr[4]) {
   struct Small a = {arr[0]};
 }
 
 // CXX-LABEL: define {{[^@]*}}@test_cxx_new_direct_plain_arr_idx
 // CXX: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_cxx_new_direct_plain_arr_idx(struct Small 
arr[]) {
+__attribute__((noinline)) void test_cxx_new_direct_plain_arr_idx(struct Small 
arr[4]) {
   struct Small *a = new struct Small(arr[0]);
   delete a;
 }
 
 // CXX-LABEL: define {{[^@]*}}@test_cxx_new_brace_plain_arr_idx
 // CXX: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_cxx_new_brace_plain_arr_idx(struct Small 
arr[]) {
+__attribute__((noinline)) void test_cxx_new_brace_plain_arr_idx(struct Small 
arr[4]) {
   struct Small *a = new struct Small{arr[0]};
   delete a;
 }
 
 // CXX-LABEL: define {{[^@]*}}@test_cxx_functional_cast_plain_arr_idx
 // CXX: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_cxx_functional_cast_plain_arr_idx(struct 
Small arr[]) {
+__attribute__((noinline)) void test_cxx_functional_cast_plain_arr_idx(struct 
Small arr[4]) {
   (void)Small(arr[0]);
 }
 
 // CXX-LABEL: define {{[^@]*}}@test_cxx_functional_cast_brace_plain_arr_idx
 // CXX: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void 
test_cxx_functional_cast_brace_plain_arr_idx(struct Small arr[]) {
+__attribute__((noinline)) void 
test_cxx_functional_cast_brace_plain_arr_idx(struct Small arr[4]) {
   (void)Small{arr[0]};
 }
 
 // CXX-LABEL: define {{[^@]*}}@test_cxx_static_cast_plain_arr_idx
 // CXX: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_cxx_static_cast_plain_arr_idx(struct Small 
arr[]) {
+__attribute__((noinline)) void test_cxx_static_cast_plain_arr_idx(struct Small 
arr[4]) {
   (void)static_cast<struct Small>(arr[0]);
 }
 
 // CXX-LABEL: define {{[^@]*}}@test_cxx_c_cast_plain_arr_idx
 // CXX: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_cxx_c_cast_plain_arr_idx(struct Small 
arr[]) {
+__attribute__((noinline)) void test_cxx_c_cast_plain_arr_idx(struct Small 
arr[4]) {
   (void)(struct Small)(arr[0]);
 }
 
 // CXX-LABEL: define {{[^@]*}}@test_cxx_member_init_plain_arr_idx
 // CXX: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_cxx_member_init_plain_arr_idx(struct Small 
arr[]) {
+__attribute__((noinline)) void test_cxx_member_init_plain_arr_idx(struct Small 
arr[4]) {
   (void)new SmallWrapper{arr[0]};
 }
 
@@ -424,7 +500,7 @@ __attribute__((noinline)) void 
test_cxx_member_init_plain_deref_ptr(struct Small
 // --- VARIADIC with plain type ---
 
 // CXX-LABEL: define {{[^@]*}}@test_cxx_variadic_plain_arr_idx
-__attribute__((noinline)) void test_cxx_variadic_plain_arr_idx(struct Small 
arr[]) {
+__attribute__((noinline)) void test_cxx_variadic_plain_arr_idx(struct Small 
arr[4]) {
   variadic_func(0, arr[0]);
 }
 
@@ -437,7 +513,7 @@ __attribute__((noinline)) void 
test_cxx_variadic_plain_deref_ptr(struct Small *a
 
 // CXX-LABEL: define {{[^@]*}}@test_cxx_operator_assign_lhs_arr_idx
 // CXX: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_cxx_operator_assign_lhs_arr_idx(struct 
Small *dest, struct Small arr[]) {
+__attribute__((noinline)) void test_cxx_operator_assign_lhs_arr_idx(struct 
Small *dest, struct Small arr[4]) {
   dest->operator=(arr[0]);
 }
 
@@ -449,7 +525,7 @@ __attribute__((noinline)) void 
test_cxx_operator_assign_lhs_deref_ptr(struct Sma
 
 // CXX-LABEL: define {{[^@]*}}@test_cxx_operator_assign_obj_arr_idx
 // CXX: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_cxx_operator_assign_obj_arr_idx(struct 
Small arr[]) {
+__attribute__((noinline)) void test_cxx_operator_assign_obj_arr_idx(struct 
Small arr[4]) {
   struct Small a;
   a.operator=(arr[0]);
 }
@@ -461,6 +537,27 @@ __attribute__((noinline)) void 
test_cxx_operator_assign_obj_deref_ptr(struct Sma
   a.operator=(*ap);
 }
 
+// --- C++ bounds checking with past-the-end access ---
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_bounds_init_direct_past_end
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_bounds_init_direct_past_end(struct 
Small arr[4]) {
+  struct Small a(arr[4]);
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_bounds_init_brace_past_end
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_bounds_init_brace_past_end(struct 
Small arr[4]) {
+  struct Small a{arr[4]};
+}
+
+// CXX-LABEL: define {{[^@]*}}@test_cxx_bounds_new_past_end
+// CXX: call void @llvm.memcpy.p0.p0.i64
+__attribute__((noinline)) void test_cxx_bounds_new_past_end(struct Small 
arr[4]) {
+  struct Small *a = new struct Small(arr[4]);
+  delete a;
+}
+
 } // extern "C"
 
 // --- Virtual base initialization (cannot be extern "C") ---
@@ -471,7 +568,7 @@ struct VirtualBaseSimple {
 };
 
 struct DerivedVirtualArrSimple : virtual VirtualBaseSimple {
-  __attribute__((noinline)) DerivedVirtualArrSimple(VirtualBaseSimple arr[]) : 
VirtualBaseSimple(arr[0]) {}
+  __attribute__((noinline)) DerivedVirtualArrSimple(VirtualBaseSimple arr[4]) 
: VirtualBaseSimple(arr[0]) {}
 };
 
 struct DerivedVirtualPtrSimple : virtual VirtualBaseSimple {
@@ -485,7 +582,7 @@ struct DerivedVirtualPtrSimple : virtual VirtualBaseSimple {
 extern "C" {
 
 // CXX-LABEL: define {{[^@]*}}@test_cxx_virtual_base_init_arr_idx
-__attribute__((noinline)) void 
test_cxx_virtual_base_init_arr_idx(VirtualBaseSimple arr[]) {
+__attribute__((noinline)) void 
test_cxx_virtual_base_init_arr_idx(VirtualBaseSimple arr[4]) {
   DerivedVirtualArrSimple d(arr);
 }
 

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to