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

>From 07d7cae1b4e663ad53860ea6fe1eda66f74c41ae Mon Sep 17 00:00:00 2001
From: vasu-ibm <[email protected]>
Date: Tue, 7 Apr 2026 03:01:00 -0400
Subject: [PATCH 1/7] add null, alignment, and array-bounds checks

---
 clang/lib/CodeGen/CGClass.cpp                 |  2 +-
 clang/lib/CodeGen/CGExprAgg.cpp               |  2 +-
 clang/lib/CodeGen/CGExprCXX.cpp               |  2 +-
 .../test/CodeGen/ubsan-aggregate-null-align.c | 90 +++++++++----------
 4 files changed, 48 insertions(+), 48 deletions(-)

diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index c0482fb13ec79..de11e8bca43f1 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -2282,7 +2282,7 @@ void CodeGenFunction::EmitCXXConstructorCall(
     assert(E->getNumArgs() == 1 && "unexpected argcount for trivial ctor");
 
     const Expr *Arg = E->getArg(0);
-    LValue Src = EmitLValue(Arg);
+    LValue Src = EmitCheckedLValue(Arg, TCK_Load);
     CanQualType DestTy = getContext().getCanonicalTagType(D->getParent());
     LValue Dest = MakeAddrLValue(This, DestTy);
     EmitAggregateCopyCtor(Dest, Src, ThisAVS.mayOverlap());
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 3a4291719da74..2d6e183e85aee 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -246,7 +246,7 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
 /// represents a value lvalue, this method emits the address of the lvalue,
 /// then loads the result into DestPtr.
 void AggExprEmitter::EmitAggLoadOfLValue(const Expr *E) {
-  LValue LV = CGF.EmitLValue(E);
+  LValue LV = CGF.EmitCheckedLValue(E, CodeGenFunction::TCK_Load);
 
   // If the type of the l-value is atomic, then do an atomic load.
   if (LV.getType()->isAtomicType() || CGF.LValueIsSuitableForInlineAtomic(LV)) 
{
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 82300c3ede183..e98015cb8fabb 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -267,7 +267,7 @@ RValue 
CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
   if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(CE)) {
     if (OCE->isAssignmentOp()) {
       if (TrivialAssignment) {
-        TrivialAssignmentRHS = EmitLValue(CE->getArg(1));
+        TrivialAssignmentRHS = EmitCheckedLValue(CE->getArg(1), TCK_Load);
       } else {
         RtlArgs = &RtlArgStorage;
         EmitCallArgs(*RtlArgs, MD->getType()->castAs<FunctionProtoType>(),
diff --git a/clang/test/CodeGen/ubsan-aggregate-null-align.c 
b/clang/test/CodeGen/ubsan-aggregate-null-align.c
index 1e2b60d7bde14..310ec0b8bf86d 100644
--- a/clang/test/CodeGen/ubsan-aggregate-null-align.c
+++ b/clang/test/CodeGen/ubsan-aggregate-null-align.c
@@ -1,10 +1,9 @@
 // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm 
-fsanitize=null,alignment,array-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,array-bounds -std=c++17 -x c++ -O0 %s -o %t.cxx.ll && 
FileCheck %s --check-prefixes=CXX,SHARED < %t.cxx.ll
 
-// Precommit test for null, alignment, and array-bounds checks on aggregates.
-// This test documents current behavior: memcpy is called but source operand 
is not checked
-// for null/alignment (unlike scalar types). Array bounds checks exist for 
local
-// arrays but not for past-the-end pointer accesses via parameters.
+// Test for null, alignment, and array-bounds checks on aggregates.
+// Verifies that the source operand is checked for null/alignment before 
memcpy.
+// Array bounds checks exist for local arrays.
 
 struct Small { int x; };
 struct Container { struct Small inner; };
@@ -18,8 +17,8 @@ extern "C" {
 // SHARED-LABEL: define {{[^@]*}}@test_assign_plain_arr_idx
 // SHARED: [[ARR:%.*]] = load ptr, ptr %arr.addr
 // SHARED: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], 
i64 0
-// SHARED-NOT: call void @__ubsan_handle_type_mismatch_v1_abort
-// SHARED-NOT: icmp ne ptr [[SRC]], null
+// SHARED: icmp ne ptr [[SRC]], null
+// SHARED: call void @__ubsan_handle_type_mismatch
 // SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_assign_plain_arr_idx(struct Small *dest, 
struct Small arr[4]) {
   *dest = arr[0];
@@ -28,8 +27,8 @@ __attribute__((noinline)) void 
test_assign_plain_arr_idx(struct Small *dest, str
 // SHARED-LABEL: define {{[^@]*}}@test_init_plain_arr_idx
 // SHARED: [[ARR:%.*]] = load ptr, ptr %arr.addr
 // SHARED: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], 
i64 0
-// SHARED-NOT: call void @__ubsan_handle_type_mismatch_v1_abort
-// SHARED-NOT: icmp ne ptr [[SRC]], null
+// SHARED: icmp ne ptr [[SRC]], null
+// SHARED: call void @__ubsan_handle_type_mismatch
 // SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_init_plain_arr_idx(struct Small arr[4]) {
   struct Small a = arr[0];
@@ -38,15 +37,15 @@ __attribute__((noinline)) void 
test_init_plain_arr_idx(struct Small arr[4]) {
 // SHARED-LABEL: define {{[^@]*}}@test_init_list_plain_arr_idx
 // SHARED: [[ARR:%.*]] = load ptr, ptr %arr.addr
 // SHARED: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], 
i64 0
-// SHARED-NOT: call void @__ubsan_handle_type_mismatch_v1_abort
-// SHARED-NOT: icmp ne ptr [[SRC]], null
+// SHARED: icmp ne ptr [[SRC]], null
+// SHARED: call void @__ubsan_handle_type_mismatch
 // SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_init_list_plain_arr_idx(struct Small 
arr[4]) {
   struct Small a[] = {arr[0]};
 }
 
 // SHARED-LABEL: define {{[^@]*}}@test_nested_member_plain_arr_idx
-// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort
+// SHARED: __ubsan_handle_type_mismatch
 // SHARED: call void @llvm.memcpy.p0.p0.i64
 __attribute__((noinline)) void test_nested_member_plain_arr_idx(struct 
Container *c, struct Small arr[4]) {
   c->inner = arr[0];
@@ -56,8 +55,8 @@ __attribute__((noinline)) void 
test_nested_member_plain_arr_idx(struct Container
 
 // SHARED-LABEL: define {{[^@]*}}@test_assign_plain_deref_ptr
 // SHARED: [[SRC:%.*]] = load ptr, ptr %ap.addr
-// SHARED-NOT: call void @__ubsan_handle_type_mismatch_v1_abort
-// SHARED-NOT: icmp ne ptr [[SRC]], null
+// SHARED: icmp ne ptr [[SRC]], null
+// SHARED: call void @__ubsan_handle_type_mismatch
 // SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_assign_plain_deref_ptr(struct Small *dest, 
struct Small *ap) {
   *dest = *ap;
@@ -65,8 +64,8 @@ __attribute__((noinline)) void 
test_assign_plain_deref_ptr(struct Small *dest, s
 
 // SHARED-LABEL: define {{[^@]*}}@test_init_plain_deref_ptr
 // SHARED: [[SRC:%.*]] = load ptr, ptr %ap.addr
-// SHARED-NOT: call void @__ubsan_handle_type_mismatch_v1_abort
-// SHARED-NOT: icmp ne ptr [[SRC]], null
+// SHARED: icmp ne ptr [[SRC]], null
+// SHARED: call void @__ubsan_handle_type_mismatch
 // SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_init_plain_deref_ptr(struct Small *ap) {
   struct Small a = *ap;
@@ -74,15 +73,15 @@ __attribute__((noinline)) void 
test_init_plain_deref_ptr(struct Small *ap) {
 
 // SHARED-LABEL: define {{[^@]*}}@test_init_list_plain_deref_ptr
 // SHARED: [[SRC:%.*]] = load ptr, ptr %ap.addr
-// SHARED-NOT: call void @__ubsan_handle_type_mismatch_v1_abort
-// SHARED-NOT: icmp ne ptr [[SRC]], null
+// SHARED: icmp ne ptr [[SRC]], null
+// SHARED: call void @__ubsan_handle_type_mismatch
 // SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_init_list_plain_deref_ptr(struct Small 
*ap) {
   struct Small a[] = {*ap};
 }
 
 // SHARED-LABEL: define {{[^@]*}}@test_nested_member_plain_deref_ptr
-// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort
+// SHARED: __ubsan_handle_type_mismatch
 // 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;
@@ -91,7 +90,8 @@ __attribute__((noinline)) void 
test_nested_member_plain_deref_ptr(struct Contain
 // Misaligned aggregate access
 
 // SHARED-LABEL: define {{[^@]*}}@test_misaligned_access
-// SHARED-NOT: call void @__ubsan_handle_type_mismatch_v1_abort
+// SHARED: icmp ne ptr
+// SHARED: call void @__ubsan_handle_type_mismatch
 // SHARED: call void @llvm.memcpy
 __attribute__((noinline)) void test_misaligned_access(struct Small *dest, char 
*buf) {
   struct Small *p = (struct Small *)(buf + 1);  // Misaligned
@@ -101,8 +101,8 @@ __attribute__((noinline)) void 
test_misaligned_access(struct Small *dest, char *
 // Array bounds: out-of-bounds on local array
 
 // SHARED-LABEL: define {{[^@]*}}@test_local_array_oob
-// SHARED: call void @__ubsan_handle_out_of_bounds_abort
-// SHARED-NOT: call void @__ubsan_handle_type_mismatch_v1_abort
+// SHARED: call void @__ubsan_handle_out_of_bounds
+// SHARED: call void @__ubsan_handle_type_mismatch
 // SHARED: call void @llvm.memcpy.p0.p0.i64
 __attribute__((noinline)) void test_local_array_oob(struct Small *dest) {
   struct Small arr[4];
@@ -114,9 +114,9 @@ __attribute__((noinline)) void test_local_array_oob(struct 
Small *dest) {
 // SHARED-LABEL: define {{[^@]*}}@test_past_the_end_arr_idx
 // SHARED: [[ARR:%.*]] = load ptr, ptr %arr.addr
 // SHARED: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], 
i64 4
-// SHARED-NOT: call void @__ubsan_handle_out_of_bounds_abort
-// SHARED-NOT: call void @__ubsan_handle_type_mismatch_v1_abort
-// SHARED-NOT: icmp ne ptr [[SRC]], null
+// SHARED-NOT: __ubsan_handle_out_of_bounds
+// SHARED: icmp ne ptr [[SRC]], null
+// SHARED: call void @__ubsan_handle_type_mismatch
 // SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_past_the_end_arr_idx(struct Small *dest, 
struct Small arr[4]) {
   *dest = arr[4];
@@ -125,9 +125,9 @@ __attribute__((noinline)) void 
test_past_the_end_arr_idx(struct Small *dest, str
 // SHARED-LABEL: define {{[^@]*}}@test_past_the_end_init
 // SHARED: [[ARR:%.*]] = load ptr, ptr %arr.addr
 // SHARED: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], 
i64 4
-// SHARED-NOT: call void @__ubsan_handle_out_of_bounds_abort
-// SHARED-NOT: call void @__ubsan_handle_type_mismatch_v1_abort
-// SHARED-NOT: icmp ne ptr [[SRC]], null
+// SHARED-NOT: __ubsan_handle_out_of_bounds
+// SHARED: icmp ne ptr [[SRC]], null
+// SHARED: call void @__ubsan_handle_type_mismatch
 // SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_past_the_end_init(struct Small arr[4]) {
   struct Small a = arr[4];
@@ -143,8 +143,8 @@ __attribute__((noinline)) void 
test_past_the_end_init(struct Small arr[4]) {
 
 // C-LABEL: define {{[^@]*}}@test_assign_atomic_deref_ptr
 // C: [[SRC:%.*]] = load ptr, ptr %ap.addr
-// C-NOT: call void @__ubsan_handle_type_mismatch_v1_abort
-// C-NOT: icmp ne ptr [[SRC]], null
+// C: icmp ne ptr [[SRC]], null
+// C: call void @__ubsan_handle_type_mismatch
 // C: load atomic i32, ptr [[SRC]] seq_cst
 __attribute__((noinline)) void test_assign_atomic_deref_ptr(struct Small 
*dest, _Atomic(struct Small) *ap) {
   *dest = *ap;
@@ -161,8 +161,8 @@ extern "C" {
 // CXX-LABEL: define {{[^@]*}}@test_cxx_init_direct_plain_arr_idx
 // CXX: [[ARR:%.*]] = load ptr, ptr %arr.addr
 // CXX: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], i64 0
-// CXX-NOT: call void @__ubsan_handle_type_mismatch_v1_abort
-// CXX-NOT: icmp ne ptr [[SRC]], null
+// CXX: icmp ne ptr [[SRC]], null
+// CXX: call void @__ubsan_handle_type_mismatch
 // CXX: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_cxx_init_direct_plain_arr_idx(struct Small 
arr[4]) {
   struct Small a(arr[0]);
@@ -171,8 +171,8 @@ __attribute__((noinline)) void 
test_cxx_init_direct_plain_arr_idx(struct Small a
 // CXX-LABEL: define {{[^@]*}}@test_cxx_init_brace_plain_arr_idx
 // CXX: [[ARR:%.*]] = load ptr, ptr %arr.addr
 // CXX: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], i64 0
-// CXX-NOT: call void @__ubsan_handle_type_mismatch_v1_abort
-// CXX-NOT: icmp ne ptr [[SRC]], null
+// CXX: icmp ne ptr [[SRC]], null
+// CXX: call void @__ubsan_handle_type_mismatch
 // CXX: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_cxx_init_brace_plain_arr_idx(struct Small 
arr[4]) {
   struct Small a{arr[0]};
@@ -180,8 +180,8 @@ __attribute__((noinline)) void 
test_cxx_init_brace_plain_arr_idx(struct Small ar
 
 // CXX-LABEL: define {{[^@]*}}@test_cxx_init_direct_plain_deref_ptr
 // CXX: [[SRC:%.*]] = load ptr, ptr %ap.addr
-// CXX-NOT: call void @__ubsan_handle_type_mismatch_v1_abort
-// CXX-NOT: icmp ne ptr [[SRC]], null
+// CXX: icmp ne ptr [[SRC]], null
+// CXX: call void @__ubsan_handle_type_mismatch
 // CXX: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_cxx_init_direct_plain_deref_ptr(struct 
Small *ap) {
   struct Small a(*ap);
@@ -189,8 +189,8 @@ __attribute__((noinline)) void 
test_cxx_init_direct_plain_deref_ptr(struct Small
 
 // CXX-LABEL: define {{[^@]*}}@test_cxx_init_brace_plain_deref_ptr
 // CXX: [[SRC:%.*]] = load ptr, ptr %ap.addr
-// CXX-NOT: call void @__ubsan_handle_type_mismatch_v1_abort
-// CXX-NOT: icmp ne ptr [[SRC]], null
+// CXX: icmp ne ptr [[SRC]], null
+// CXX: call void @__ubsan_handle_type_mismatch
 // CXX: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_cxx_init_brace_plain_deref_ptr(struct 
Small *ap) {
   struct Small a{*ap};
@@ -198,8 +198,8 @@ __attribute__((noinline)) void 
test_cxx_init_brace_plain_deref_ptr(struct Small
 
 // CXX-LABEL: define {{[^@]*}}@test_cxx_new_direct_plain_deref_ptr
 // CXX: [[SRC:%.*]] = load ptr, ptr %ap.addr
-// CXX-NOT: call void @__ubsan_handle_type_mismatch_v1_abort
-// CXX-NOT: icmp ne ptr [[SRC]], null
+// CXX: icmp ne ptr [[SRC]], null
+// CXX: call void @__ubsan_handle_type_mismatch
 // CXX: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_cxx_new_direct_plain_deref_ptr(struct 
Small *ap) {
   struct Small *a = new struct Small(*ap);
@@ -211,9 +211,9 @@ __attribute__((noinline)) void 
test_cxx_new_direct_plain_deref_ptr(struct Small
 // CXX-LABEL: define {{[^@]*}}@test_cxx_past_the_end_direct
 // CXX: [[ARR:%.*]] = load ptr, ptr %arr.addr
 // CXX: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], i64 4
-// CXX-NOT: call void @__ubsan_handle_out_of_bounds_abort
-// CXX-NOT: call void @__ubsan_handle_type_mismatch_v1_abort
-// CXX-NOT: icmp ne ptr [[SRC]], null
+// CXX-NOT: __ubsan_handle_out_of_bounds
+// CXX: icmp ne ptr [[SRC]], null
+// CXX: call void @__ubsan_handle_type_mismatch
 // CXX: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_cxx_past_the_end_direct(struct Small 
arr[4]) {
   struct Small a(arr[4]);
@@ -222,9 +222,9 @@ __attribute__((noinline)) void 
test_cxx_past_the_end_direct(struct Small arr[4])
 // CXX-LABEL: define {{[^@]*}}@test_cxx_past_the_end_brace
 // CXX: [[ARR:%.*]] = load ptr, ptr %arr.addr
 // CXX: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], i64 4
-// CXX-NOT: call void @__ubsan_handle_out_of_bounds_abort
-// CXX-NOT: call void @__ubsan_handle_type_mismatch_v1_abort
-// CXX-NOT: icmp ne ptr [[SRC]], null
+// CXX-NOT: __ubsan_handle_out_of_bounds
+// CXX: icmp ne ptr [[SRC]], null
+// CXX: call void @__ubsan_handle_type_mismatch
 // CXX: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_cxx_past_the_end_brace(struct Small 
arr[4]) {
   struct Small a{arr[4]};

>From cdd05859ebba55636d5042ac7b898529998d9405 Mon Sep 17 00:00:00 2001
From: vasu-ibm <[email protected]>
Date: Tue, 7 Apr 2026 08:22:55 -0400
Subject: [PATCH 2/7] update ubsan-new-checks.cpp to expect new alignment check

---
 clang/test/CodeGenCXX/ubsan-new-checks.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang/test/CodeGenCXX/ubsan-new-checks.cpp 
b/clang/test/CodeGenCXX/ubsan-new-checks.cpp
index 60edd323648ab..adc54ccbb00b7 100644
--- a/clang/test/CodeGenCXX/ubsan-new-checks.cpp
+++ b/clang/test/CodeGenCXX/ubsan-new-checks.cpp
@@ -140,7 +140,8 @@ S5 *func_15(const S5 *ptr) {
   // CHECK-LABEL: define {{.*}} @_Z7func_15PK2S5
   // CHECK:       and i64 %{{.*}}, 31, !nosanitize
   // CHECK:       icmp eq i64 %{{.*}}, 0, !nosanitize
-  // CHECK-NOT:   and i64
+  // CHECK:       and i64 %{{.*}}, 31, !nosanitize
+  // CHECK:       icmp eq i64 %{{.*}}, 0, !nosanitize
   // CHECK:       ret ptr
   return new S5(*ptr);
 }

>From a5f9291e9739bd64634cbca16b65ca291ac90ef6 Mon Sep 17 00:00:00 2001
From: vasu-ibm <[email protected]>
Date: Thu, 9 Apr 2026 07:58:47 -0400
Subject: [PATCH 3/7] update FileCheck patterns and comments

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

diff --git a/clang/test/CodeGen/ubsan-aggregate-null-align.c 
b/clang/test/CodeGen/ubsan-aggregate-null-align.c
index 310ec0b8bf86d..c652a3729fe95 100644
--- a/clang/test/CodeGen/ubsan-aggregate-null-align.c
+++ b/clang/test/CodeGen/ubsan-aggregate-null-align.c
@@ -18,7 +18,7 @@ extern "C" {
 // SHARED: [[ARR:%.*]] = load ptr, ptr %arr.addr
 // SHARED: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], 
i64 0
 // SHARED: icmp ne ptr [[SRC]], null
-// SHARED: call void @__ubsan_handle_type_mismatch
+// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
 // SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_assign_plain_arr_idx(struct Small *dest, 
struct Small arr[4]) {
   *dest = arr[0];
@@ -28,7 +28,7 @@ __attribute__((noinline)) void 
test_assign_plain_arr_idx(struct Small *dest, str
 // SHARED: [[ARR:%.*]] = load ptr, ptr %arr.addr
 // SHARED: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], 
i64 0
 // SHARED: icmp ne ptr [[SRC]], null
-// SHARED: call void @__ubsan_handle_type_mismatch
+// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
 // SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_init_plain_arr_idx(struct Small arr[4]) {
   struct Small a = arr[0];
@@ -38,14 +38,16 @@ __attribute__((noinline)) void 
test_init_plain_arr_idx(struct Small arr[4]) {
 // SHARED: [[ARR:%.*]] = load ptr, ptr %arr.addr
 // SHARED: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], 
i64 0
 // SHARED: icmp ne ptr [[SRC]], null
-// SHARED: call void @__ubsan_handle_type_mismatch
+// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
 // SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_init_list_plain_arr_idx(struct Small 
arr[4]) {
   struct Small a[] = {arr[0]};
 }
 
+// Two ubsan calls: one for destination (c), one for source (arr[0])
 // SHARED-LABEL: define {{[^@]*}}@test_nested_member_plain_arr_idx
-// SHARED: __ubsan_handle_type_mismatch
+// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
+// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
 // SHARED: call void @llvm.memcpy.p0.p0.i64
 __attribute__((noinline)) void test_nested_member_plain_arr_idx(struct 
Container *c, struct Small arr[4]) {
   c->inner = arr[0];
@@ -56,7 +58,7 @@ __attribute__((noinline)) void 
test_nested_member_plain_arr_idx(struct Container
 // SHARED-LABEL: define {{[^@]*}}@test_assign_plain_deref_ptr
 // SHARED: [[SRC:%.*]] = load ptr, ptr %ap.addr
 // SHARED: icmp ne ptr [[SRC]], null
-// SHARED: call void @__ubsan_handle_type_mismatch
+// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
 // SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_assign_plain_deref_ptr(struct Small *dest, 
struct Small *ap) {
   *dest = *ap;
@@ -65,7 +67,7 @@ __attribute__((noinline)) void 
test_assign_plain_deref_ptr(struct Small *dest, s
 // SHARED-LABEL: define {{[^@]*}}@test_init_plain_deref_ptr
 // SHARED: [[SRC:%.*]] = load ptr, ptr %ap.addr
 // SHARED: icmp ne ptr [[SRC]], null
-// SHARED: call void @__ubsan_handle_type_mismatch
+// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
 // SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_init_plain_deref_ptr(struct Small *ap) {
   struct Small a = *ap;
@@ -74,14 +76,16 @@ __attribute__((noinline)) void 
test_init_plain_deref_ptr(struct Small *ap) {
 // SHARED-LABEL: define {{[^@]*}}@test_init_list_plain_deref_ptr
 // SHARED: [[SRC:%.*]] = load ptr, ptr %ap.addr
 // SHARED: icmp ne ptr [[SRC]], null
-// SHARED: call void @__ubsan_handle_type_mismatch
+// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
 // SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_init_list_plain_deref_ptr(struct Small 
*ap) {
   struct Small a[] = {*ap};
 }
 
+// Two ubsan calls: one for destination (c), one for source (*ap)
 // SHARED-LABEL: define {{[^@]*}}@test_nested_member_plain_deref_ptr
-// SHARED: __ubsan_handle_type_mismatch
+// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
+// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
 // 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;
@@ -91,7 +95,7 @@ __attribute__((noinline)) void 
test_nested_member_plain_deref_ptr(struct Contain
 
 // SHARED-LABEL: define {{[^@]*}}@test_misaligned_access
 // SHARED: icmp ne ptr
-// SHARED: call void @__ubsan_handle_type_mismatch
+// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
 // SHARED: call void @llvm.memcpy
 __attribute__((noinline)) void test_misaligned_access(struct Small *dest, char 
*buf) {
   struct Small *p = (struct Small *)(buf + 1);  // Misaligned
@@ -101,8 +105,8 @@ __attribute__((noinline)) void 
test_misaligned_access(struct Small *dest, char *
 // Array bounds: out-of-bounds on local array
 
 // SHARED-LABEL: define {{[^@]*}}@test_local_array_oob
-// SHARED: call void @__ubsan_handle_out_of_bounds
-// SHARED: call void @__ubsan_handle_type_mismatch
+// SHARED: call void @__ubsan_handle_out_of_bounds_abort(
+// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
 // SHARED: call void @llvm.memcpy.p0.p0.i64
 __attribute__((noinline)) void test_local_array_oob(struct Small *dest) {
   struct Small arr[4];
@@ -114,9 +118,9 @@ __attribute__((noinline)) void test_local_array_oob(struct 
Small *dest) {
 // SHARED-LABEL: define {{[^@]*}}@test_past_the_end_arr_idx
 // SHARED: [[ARR:%.*]] = load ptr, ptr %arr.addr
 // SHARED: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], 
i64 4
-// SHARED-NOT: __ubsan_handle_out_of_bounds
+// SHARED-NOT: call void @__ubsan_handle_out_of_bounds_abort(
 // SHARED: icmp ne ptr [[SRC]], null
-// SHARED: call void @__ubsan_handle_type_mismatch
+// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
 // SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_past_the_end_arr_idx(struct Small *dest, 
struct Small arr[4]) {
   *dest = arr[4];
@@ -125,9 +129,9 @@ __attribute__((noinline)) void 
test_past_the_end_arr_idx(struct Small *dest, str
 // SHARED-LABEL: define {{[^@]*}}@test_past_the_end_init
 // SHARED: [[ARR:%.*]] = load ptr, ptr %arr.addr
 // SHARED: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], 
i64 4
-// SHARED-NOT: __ubsan_handle_out_of_bounds
+// SHARED-NOT: call void @__ubsan_handle_out_of_bounds_abort(
 // SHARED: icmp ne ptr [[SRC]], null
-// SHARED: call void @__ubsan_handle_type_mismatch
+// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
 // SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_past_the_end_init(struct Small arr[4]) {
   struct Small a = arr[4];
@@ -144,7 +148,7 @@ __attribute__((noinline)) void 
test_past_the_end_init(struct Small arr[4]) {
 // C-LABEL: define {{[^@]*}}@test_assign_atomic_deref_ptr
 // C: [[SRC:%.*]] = load ptr, ptr %ap.addr
 // C: icmp ne ptr [[SRC]], null
-// C: call void @__ubsan_handle_type_mismatch
+// C: call void @__ubsan_handle_type_mismatch_v1_abort(
 // C: load atomic i32, ptr [[SRC]] seq_cst
 __attribute__((noinline)) void test_assign_atomic_deref_ptr(struct Small 
*dest, _Atomic(struct Small) *ap) {
   *dest = *ap;
@@ -162,7 +166,7 @@ extern "C" {
 // CXX: [[ARR:%.*]] = load ptr, ptr %arr.addr
 // CXX: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], i64 0
 // CXX: icmp ne ptr [[SRC]], null
-// CXX: call void @__ubsan_handle_type_mismatch
+// CXX: call void @__ubsan_handle_type_mismatch_v1_abort(
 // CXX: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_cxx_init_direct_plain_arr_idx(struct Small 
arr[4]) {
   struct Small a(arr[0]);
@@ -172,7 +176,7 @@ __attribute__((noinline)) void 
test_cxx_init_direct_plain_arr_idx(struct Small a
 // CXX: [[ARR:%.*]] = load ptr, ptr %arr.addr
 // CXX: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], i64 0
 // CXX: icmp ne ptr [[SRC]], null
-// CXX: call void @__ubsan_handle_type_mismatch
+// CXX: call void @__ubsan_handle_type_mismatch_v1_abort(
 // CXX: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_cxx_init_brace_plain_arr_idx(struct Small 
arr[4]) {
   struct Small a{arr[0]};
@@ -181,7 +185,7 @@ __attribute__((noinline)) void 
test_cxx_init_brace_plain_arr_idx(struct Small ar
 // CXX-LABEL: define {{[^@]*}}@test_cxx_init_direct_plain_deref_ptr
 // CXX: [[SRC:%.*]] = load ptr, ptr %ap.addr
 // CXX: icmp ne ptr [[SRC]], null
-// CXX: call void @__ubsan_handle_type_mismatch
+// CXX: call void @__ubsan_handle_type_mismatch_v1_abort(
 // CXX: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_cxx_init_direct_plain_deref_ptr(struct 
Small *ap) {
   struct Small a(*ap);
@@ -190,7 +194,7 @@ __attribute__((noinline)) void 
test_cxx_init_direct_plain_deref_ptr(struct Small
 // CXX-LABEL: define {{[^@]*}}@test_cxx_init_brace_plain_deref_ptr
 // CXX: [[SRC:%.*]] = load ptr, ptr %ap.addr
 // CXX: icmp ne ptr [[SRC]], null
-// CXX: call void @__ubsan_handle_type_mismatch
+// CXX: call void @__ubsan_handle_type_mismatch_v1_abort(
 // CXX: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_cxx_init_brace_plain_deref_ptr(struct 
Small *ap) {
   struct Small a{*ap};
@@ -199,7 +203,7 @@ __attribute__((noinline)) void 
test_cxx_init_brace_plain_deref_ptr(struct Small
 // CXX-LABEL: define {{[^@]*}}@test_cxx_new_direct_plain_deref_ptr
 // CXX: [[SRC:%.*]] = load ptr, ptr %ap.addr
 // CXX: icmp ne ptr [[SRC]], null
-// CXX: call void @__ubsan_handle_type_mismatch
+// CXX: call void @__ubsan_handle_type_mismatch_v1_abort(
 // CXX: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_cxx_new_direct_plain_deref_ptr(struct 
Small *ap) {
   struct Small *a = new struct Small(*ap);
@@ -211,9 +215,9 @@ __attribute__((noinline)) void 
test_cxx_new_direct_plain_deref_ptr(struct Small
 // CXX-LABEL: define {{[^@]*}}@test_cxx_past_the_end_direct
 // CXX: [[ARR:%.*]] = load ptr, ptr %arr.addr
 // CXX: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], i64 4
-// CXX-NOT: __ubsan_handle_out_of_bounds
+// CXX-NOT: call void @__ubsan_handle_out_of_bounds_abort(
 // CXX: icmp ne ptr [[SRC]], null
-// CXX: call void @__ubsan_handle_type_mismatch
+// CXX: call void @__ubsan_handle_type_mismatch_v1_abort(
 // CXX: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_cxx_past_the_end_direct(struct Small 
arr[4]) {
   struct Small a(arr[4]);
@@ -222,9 +226,9 @@ __attribute__((noinline)) void 
test_cxx_past_the_end_direct(struct Small arr[4])
 // CXX-LABEL: define {{[^@]*}}@test_cxx_past_the_end_brace
 // CXX: [[ARR:%.*]] = load ptr, ptr %arr.addr
 // CXX: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], i64 4
-// CXX-NOT: __ubsan_handle_out_of_bounds
+// CXX-NOT: call void @__ubsan_handle_out_of_bounds_abort(
 // CXX: icmp ne ptr [[SRC]], null
-// CXX: call void @__ubsan_handle_type_mismatch
+// CXX: call void @__ubsan_handle_type_mismatch_v1_abort(
 // CXX: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
 __attribute__((noinline)) void test_cxx_past_the_end_brace(struct Small 
arr[4]) {
   struct Small a{arr[4]};

>From 9972f63b9611a014c22a1322024c90da8ca0b23f Mon Sep 17 00:00:00 2001
From: vasu-ibm <[email protected]>
Date: Tue, 14 Apr 2026 04:59:07 -0400
Subject: [PATCH 4/7] add null/alignment checks for aggregate copy LHS/RHS

---
 clang/lib/CodeGen/CGExprAgg.cpp               |   2 +-
 .../test/CodeGen/ubsan-aggregate-null-align.c | 347 +++++++-----------
 2 files changed, 133 insertions(+), 216 deletions(-)

diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 2d6e183e85aee..1668d22be5adc 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -1337,7 +1337,7 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator 
*E) {
     return;
   }
 
-  LValue LHS = CGF.EmitLValue(E->getLHS());
+  LValue LHS = CGF.EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store);
 
   // If we have an atomic type, evaluate into the destination and then
   // do an atomic copy.
diff --git a/clang/test/CodeGen/ubsan-aggregate-null-align.c 
b/clang/test/CodeGen/ubsan-aggregate-null-align.c
index c652a3729fe95..4d1edb7d7af42 100644
--- a/clang/test/CodeGen/ubsan-aggregate-null-align.c
+++ b/clang/test/CodeGen/ubsan-aggregate-null-align.c
@@ -1,239 +1,156 @@
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm 
-fsanitize=null,alignment,array-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,array-bounds -std=c++17 -x c++ -O0 %s -o %t.cxx.ll && 
FileCheck %s --check-prefixes=CXX,SHARED < %t.cxx.ll
-
-// Test for null, alignment, and array-bounds checks on aggregates.
-// Verifies that the source operand is checked for null/alignment before 
memcpy.
-// Array bounds checks exist for local arrays.
-
-struct Small { int x; };
-struct Container { struct Small inner; };
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm 
-fsanitize=null,alignment,array-bounds -std=c11 -O0 %s -o %t.c.ll && FileCheck 
%s --check-prefixes=CHECK,C < %t.c.ll
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm 
-fsanitize=null,alignment,array-bounds -std=c++17 -x c++ -O0 %s -o %t.cxx.ll && 
FileCheck %s --check-prefixes=CHECK,CXX < %t.cxx.ll
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm 
-fsanitize=null,alignment,array-bounds -std=c11 -O0 -DUSE_UNION %s -o 
%t.union.ll && FileCheck %s --check-prefixes=CHECK,C < %t.union.ll
+
+#ifdef USE_UNION
+union Agg { int x; };
+#define AGG union Agg
+#else
+struct Agg { int x; };
+#define AGG struct Agg
+#endif
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-// Plain type - arr[idx] operand form (known bounds)
-
-// SHARED-LABEL: define {{[^@]*}}@test_assign_plain_arr_idx
-// SHARED: [[ARR:%.*]] = load ptr, ptr %arr.addr
-// SHARED: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], 
i64 0
-// SHARED: icmp ne ptr [[SRC]], null
-// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
-// SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
-__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: [[ARR:%.*]] = load ptr, ptr %arr.addr
-// SHARED: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], 
i64 0
-// SHARED: icmp ne ptr [[SRC]], null
-// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
-// SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
-__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: [[ARR:%.*]] = load ptr, ptr %arr.addr
-// SHARED: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], 
i64 0
-// SHARED: icmp ne ptr [[SRC]], null
-// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
-// SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
-__attribute__((noinline)) void test_init_list_plain_arr_idx(struct Small 
arr[4]) {
-  struct Small a[] = {arr[0]};
-}
-
-// Two ubsan calls: one for destination (c), one for source (arr[0])
-// SHARED-LABEL: define {{[^@]*}}@test_nested_member_plain_arr_idx
-// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
-// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
-// SHARED: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_nested_member_plain_arr_idx(struct 
Container *c, struct Small arr[4]) {
-  c->inner = arr[0];
-}
-
-// Plain type - *ap operand form
-
-// SHARED-LABEL: define {{[^@]*}}@test_assign_plain_deref_ptr
-// SHARED: [[SRC:%.*]] = load ptr, ptr %ap.addr
-// SHARED: icmp ne ptr [[SRC]], null
-// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
-// SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
-__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: [[SRC:%.*]] = load ptr, ptr %ap.addr
-// SHARED: icmp ne ptr [[SRC]], null
-// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
-// SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
-__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: [[SRC:%.*]] = load ptr, ptr %ap.addr
-// SHARED: icmp ne ptr [[SRC]], null
-// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
-// SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
-__attribute__((noinline)) void test_init_list_plain_deref_ptr(struct Small 
*ap) {
-  struct Small a[] = {*ap};
-}
-
-// Two ubsan calls: one for destination (c), one for source (*ap)
-// SHARED-LABEL: define {{[^@]*}}@test_nested_member_plain_deref_ptr
-// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
-// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
-// 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;
-}
-
-// Misaligned aggregate access
-
-// SHARED-LABEL: define {{[^@]*}}@test_misaligned_access
-// SHARED: icmp ne ptr
-// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
-// SHARED: call void @llvm.memcpy
-__attribute__((noinline)) void test_misaligned_access(struct Small *dest, char 
*buf) {
-  struct Small *p = (struct Small *)(buf + 1);  // Misaligned
-  *dest = *p;
-}
-
-// Array bounds: out-of-bounds on local array
-
-// SHARED-LABEL: define {{[^@]*}}@test_local_array_oob
-// SHARED: call void @__ubsan_handle_out_of_bounds_abort(
-// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
-// SHARED: call void @llvm.memcpy.p0.p0.i64
-__attribute__((noinline)) void test_local_array_oob(struct Small *dest) {
-  struct Small arr[4];
-  *dest = arr[5];
-}
-
-// Array bounds: past-the-end via parameter
-
-// SHARED-LABEL: define {{[^@]*}}@test_past_the_end_arr_idx
-// SHARED: [[ARR:%.*]] = load ptr, ptr %arr.addr
-// SHARED: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], 
i64 4
-// SHARED-NOT: call void @__ubsan_handle_out_of_bounds_abort(
-// SHARED: icmp ne ptr [[SRC]], null
-// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
-// SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
-__attribute__((noinline)) void test_past_the_end_arr_idx(struct Small *dest, 
struct Small arr[4]) {
-  *dest = arr[4];
-}
-
-// SHARED-LABEL: define {{[^@]*}}@test_past_the_end_init
-// SHARED: [[ARR:%.*]] = load ptr, ptr %arr.addr
-// SHARED: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], 
i64 4
-// SHARED-NOT: call void @__ubsan_handle_out_of_bounds_abort(
-// SHARED: icmp ne ptr [[SRC]], null
-// SHARED: call void @__ubsan_handle_type_mismatch_v1_abort(
-// SHARED: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
-__attribute__((noinline)) void test_past_the_end_init(struct Small arr[4]) {
-  struct Small a = arr[4];
+// LHS checks - C only
+
+// C-LABEL: define {{.*}}@test_lhs_ptr(
+// C: [[DEST:%.*]] = load ptr, ptr %dest.addr
+// C-NEXT: [[CMP:%.*]] = icmp ne ptr [[DEST]], null, !nosanitize
+// C-NEXT: [[INT:%.*]] = ptrtoint ptr [[DEST]] to i64, !nosanitize
+// C-NEXT: [[AND:%.*]] = and i64 [[INT]], 3, !nosanitize
+// C-NEXT: [[ALIGN:%.*]] = icmp eq i64 [[AND]], 0, !nosanitize
+// C-NEXT: [[OK:%.*]] = and i1 [[CMP]], [[ALIGN]], !nosanitize
+// C-NEXT: br i1 [[OK]], label %cont, label %handler.type_mismatch
+// C: handler.type_mismatch:
+// C-NEXT: call void @__ubsan_handle_type_mismatch_v1_abort
+// C: call void @llvm.memcpy
+void test_lhs_ptr(AGG *dest) {
+  AGG local = {0};
+  *dest = local;
+}
+
+// C-LABEL: define {{.*}}@test_lhs_array(
+// C: [[ARR:%.*]] = load ptr, ptr %arr.addr
+// C-NEXT: [[DEST:%.*]] = getelementptr inbounds %{{(struct|union)}}.Agg, ptr 
[[ARR]], i64 0
+// C-NEXT: [[CMP:%.*]] = icmp ne ptr [[DEST]], null, !nosanitize
+// C: handler.type_mismatch:
+// C-NEXT: call void @__ubsan_handle_type_mismatch_v1_abort
+// C: call void @llvm.memcpy
+void test_lhs_array(AGG arr[4]) {
+  AGG local = {0};
+  arr[0] = local;
+}
+
+// RHS checks - both C and C++
+
+// CHECK-LABEL: define {{.*}}@test_rhs_ptr(
+// CHECK: [[SRC:%.*]] = load ptr, ptr %src.addr
+// CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[SRC]], null, !nosanitize
+// CHECK-NEXT: [[INT:%.*]] = ptrtoint ptr [[SRC]] to i64, !nosanitize
+// CHECK-NEXT: [[AND:%.*]] = and i64 [[INT]], 3, !nosanitize
+// CHECK-NEXT: [[ALIGN:%.*]] = icmp eq i64 [[AND]], 0, !nosanitize
+// CHECK-NEXT: [[OK:%.*]] = and i1 [[CMP]], [[ALIGN]], !nosanitize
+// CHECK-NEXT: br i1 [[OK]], label %cont, label %handler.type_mismatch
+// CHECK: handler.type_mismatch:
+// CHECK-NEXT: call void @__ubsan_handle_type_mismatch_v1_abort
+// CHECK: cont:
+// CHECK-NEXT: call void @llvm.memcpy
+void test_rhs_ptr(AGG *src) {
+  AGG local;
+  local = *src;
+  (void)local;
+}
+
+// CHECK-LABEL: define {{.*}}@test_rhs_array(
+// CHECK: [[ARR:%.*]] = load ptr, ptr %arr.addr
+// CHECK-NEXT: [[SRC:%.*]] = getelementptr inbounds %{{(struct|union)}}.Agg, 
ptr [[ARR]], i64 0
+// CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[SRC]], null, !nosanitize
+// CHECK: handler.type_mismatch:
+// CHECK-NEXT: call void @__ubsan_handle_type_mismatch_v1_abort
+// CHECK: call void @llvm.memcpy
+void test_rhs_array(AGG arr[4]) {
+  AGG local;
+  local = arr[0];
+  (void)local;
+}
+
+// RHS cases - handler call only
+
+// CHECK-LABEL: define {{.*}}@test_init_from_ptr(
+// CHECK: handler.type_mismatch:
+// CHECK-NEXT: call void @__ubsan_handle_type_mismatch_v1_abort
+// CHECK: call void @llvm.memcpy
+void test_init_from_ptr(AGG *src) {
+  AGG local = *src;
+  (void)local;
+}
+
+// CHECK-LABEL: define {{.*}}@test_init_from_array(
+// CHECK: handler.type_mismatch:
+// CHECK-NEXT: call void @__ubsan_handle_type_mismatch_v1_abort
+// CHECK: call void @llvm.memcpy
+void test_init_from_array(AGG arr[4]) {
+  AGG local = arr[0];
+  (void)local;
+}
+
+// Array bounds - out-of-bounds access
+
+// CHECK-LABEL: define {{.*}}@test_oob_rhs(
+// CHECK: br i1 {{(true|false)}}, label %cont, label %handler.out_of_bounds
+// CHECK: handler.out_of_bounds:
+// CHECK-NEXT: call void @__ubsan_handle_out_of_bounds_abort
+// CHECK: handler.type_mismatch:
+// CHECK-NEXT: call void @__ubsan_handle_type_mismatch_v1_abort
+// CHECK: call void @llvm.memcpy
+void test_oob_rhs(void) {
+  AGG arr[4];
+  AGG local;
+  local = arr[4];
+  (void)local;
 }
 
 #ifdef __cplusplus
-} // extern "C"
-#endif
-
-// Atomic type (C only)
-
-#ifndef __cplusplus
-
-// C-LABEL: define {{[^@]*}}@test_assign_atomic_deref_ptr
-// C: [[SRC:%.*]] = load ptr, ptr %ap.addr
-// C: icmp ne ptr [[SRC]], null
-// C: call void @__ubsan_handle_type_mismatch_v1_abort(
-// C: load atomic i32, ptr [[SRC]] seq_cst
-__attribute__((noinline)) void test_assign_atomic_deref_ptr(struct Small 
*dest, _Atomic(struct Small) *ap) {
-  *dest = *ap;
 }
+#endif
 
-#endif // !__cplusplus
 
-// C++ only
+// C++ - handler call only
 
 #ifdef __cplusplus
 
 extern "C" {
 
-// CXX-LABEL: define {{[^@]*}}@test_cxx_init_direct_plain_arr_idx
-// CXX: [[ARR:%.*]] = load ptr, ptr %arr.addr
-// CXX: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], i64 0
-// CXX: icmp ne ptr [[SRC]], null
-// CXX: call void @__ubsan_handle_type_mismatch_v1_abort(
-// CXX: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
-__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: [[ARR:%.*]] = load ptr, ptr %arr.addr
-// CXX: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], i64 0
-// CXX: icmp ne ptr [[SRC]], null
-// CXX: call void @__ubsan_handle_type_mismatch_v1_abort(
-// CXX: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
-__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_direct_plain_deref_ptr
-// CXX: [[SRC:%.*]] = load ptr, ptr %ap.addr
-// CXX: icmp ne ptr [[SRC]], null
-// CXX: call void @__ubsan_handle_type_mismatch_v1_abort(
-// CXX: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
-__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: [[SRC:%.*]] = load ptr, ptr %ap.addr
-// CXX: icmp ne ptr [[SRC]], null
-// CXX: call void @__ubsan_handle_type_mismatch_v1_abort(
-// CXX: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
-__attribute__((noinline)) void test_cxx_init_brace_plain_deref_ptr(struct 
Small *ap) {
-  struct Small a{*ap};
+// CXX-LABEL: define {{.*}}@test_cxx_direct_init(
+// CXX: handler.type_mismatch:
+// CXX-NEXT: call void @__ubsan_handle_type_mismatch_v1_abort
+// CXX: call void @llvm.memcpy
+void test_cxx_direct_init(AGG *src) {
+  AGG local(*src);
+  (void)local;
 }
 
-// CXX-LABEL: define {{[^@]*}}@test_cxx_new_direct_plain_deref_ptr
-// CXX: [[SRC:%.*]] = load ptr, ptr %ap.addr
-// CXX: icmp ne ptr [[SRC]], null
-// CXX: call void @__ubsan_handle_type_mismatch_v1_abort(
-// CXX: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
-__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_brace_init(
+// CXX: handler.type_mismatch:
+// CXX-NEXT: call void @__ubsan_handle_type_mismatch_v1_abort
+// CXX: call void @llvm.memcpy
+void test_cxx_brace_init(AGG *src) {
+  AGG local{*src};
+  (void)local;
 }
 
-// C++ past-the-end tests
-
-// CXX-LABEL: define {{[^@]*}}@test_cxx_past_the_end_direct
-// CXX: [[ARR:%.*]] = load ptr, ptr %arr.addr
-// CXX: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], i64 4
-// CXX-NOT: call void @__ubsan_handle_out_of_bounds_abort(
-// CXX: icmp ne ptr [[SRC]], null
-// CXX: call void @__ubsan_handle_type_mismatch_v1_abort(
-// CXX: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
-__attribute__((noinline)) void test_cxx_past_the_end_direct(struct Small 
arr[4]) {
-  struct Small a(arr[4]);
+// CXX-LABEL: define {{.*}}@test_cxx_new(
+// CXX: handler.type_mismatch:
+// CXX-NEXT: call void @__ubsan_handle_type_mismatch_v1_abort
+// CXX: call void @llvm.memcpy
+void test_cxx_new(AGG *src) {
+  AGG *p = new AGG(*src);
+  delete p;
 }
 
-// CXX-LABEL: define {{[^@]*}}@test_cxx_past_the_end_brace
-// CXX: [[ARR:%.*]] = load ptr, ptr %arr.addr
-// CXX: [[SRC:%.*]] = getelementptr inbounds %struct.Small, ptr [[ARR]], i64 4
-// CXX-NOT: call void @__ubsan_handle_out_of_bounds_abort(
-// CXX: icmp ne ptr [[SRC]], null
-// CXX: call void @__ubsan_handle_type_mismatch_v1_abort(
-// CXX: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.*}}, ptr align 4 
[[SRC]], i64 4, i1 false)
-__attribute__((noinline)) void test_cxx_past_the_end_brace(struct Small 
arr[4]) {
-  struct Small a{arr[4]};
 }
 
-} // extern "C"
-
-#endif // __cplusplus
+#endif

>From fa88d481a2cd63811b1ca1a389fd9b519b4d8627 Mon Sep 17 00:00:00 2001
From: vasu-ibm <[email protected]>
Date: Tue, 21 Apr 2026 02:49:21 -0400
Subject: [PATCH 5/7] update ubsan-new-checks.cpp

---
 clang/test/CodeGenCXX/ubsan-new-checks.cpp | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/clang/test/CodeGenCXX/ubsan-new-checks.cpp 
b/clang/test/CodeGenCXX/ubsan-new-checks.cpp
index adc54ccbb00b7..9adc0840801b9 100644
--- a/clang/test/CodeGenCXX/ubsan-new-checks.cpp
+++ b/clang/test/CodeGenCXX/ubsan-new-checks.cpp
@@ -136,12 +136,12 @@ S4 *func_14() {
   return new S4;
 }
 
-S5 *func_15(const S5 *ptr) {
-  // CHECK-LABEL: define {{.*}} @_Z7func_15PK2S5
-  // CHECK:       and i64 %{{.*}}, 31, !nosanitize
-  // CHECK:       icmp eq i64 %{{.*}}, 0, !nosanitize
+S5 *func_15() {
+  // CHECK-LABEL: define {{.*}} @_Z7func_15v
   // CHECK:       and i64 %{{.*}}, 31, !nosanitize
   // CHECK:       icmp eq i64 %{{.*}}, 0, !nosanitize
+  // CHECK-NOT:   and i64
   // CHECK:       ret ptr
-  return new S5(*ptr);
+  S5 local = {};
+  return new S5(local);
 }

>From 58d4075b756f35214b4d6f64d89a9ea3e23e0e1f Mon Sep 17 00:00:00 2001
From: vasu-ibm <[email protected]>
Date: Wed, 22 Apr 2026 03:44:20 -0400
Subject: [PATCH 6/7] resolve review comments

---
 .../test/CodeGen/ubsan-aggregate-null-align.c | 44 +++++++++++++------
 1 file changed, 30 insertions(+), 14 deletions(-)

diff --git a/clang/test/CodeGen/ubsan-aggregate-null-align.c 
b/clang/test/CodeGen/ubsan-aggregate-null-align.c
index 4d1edb7d7af42..d5b6de3f456c0 100644
--- a/clang/test/CodeGen/ubsan-aggregate-null-align.c
+++ b/clang/test/CodeGen/ubsan-aggregate-null-align.c
@@ -1,6 +1,7 @@
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm 
-fsanitize=null,alignment,array-bounds -std=c11 -O0 %s -o %t.c.ll && FileCheck 
%s --check-prefixes=CHECK,C < %t.c.ll
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm 
-fsanitize=null,alignment,array-bounds -std=c++17 -x c++ -O0 %s -o %t.cxx.ll && 
FileCheck %s --check-prefixes=CHECK,CXX < %t.cxx.ll
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm 
-fsanitize=null,alignment,array-bounds -std=c11 -O0 -DUSE_UNION %s -o 
%t.union.ll && FileCheck %s --check-prefixes=CHECK,C < %t.union.ll
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm 
-fsanitize=null,alignment,array-bounds -std=c11 -O0 %s -o - | FileCheck %s 
--check-prefixes=CHECK,C
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm 
-fsanitize=null,alignment,array-bounds -std=c++17 -x c++ -O0 %s -o - | 
FileCheck %s --check-prefixes=CHECK,CXX
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm 
-fsanitize=null,alignment,array-bounds -std=c11 -O0 -DUSE_UNION %s -o - | 
FileCheck %s --check-prefixes=CHECK,C
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm 
-fsanitize=null,alignment,array-bounds -std=c++17 -x c++ -O0 -DUSE_UNION %s -o 
- | FileCheck %s --check-prefixes=CHECK,CXX
 
 #ifdef USE_UNION
 union Agg { int x; };
@@ -16,7 +17,7 @@ extern "C" {
 
 // LHS checks - C only
 
-// C-LABEL: define {{.*}}@test_lhs_ptr(
+// C-LABEL: define {{.*}}@test_lhs_ptrcheck_deref(
 // C: [[DEST:%.*]] = load ptr, ptr %dest.addr
 // C-NEXT: [[CMP:%.*]] = icmp ne ptr [[DEST]], null, !nosanitize
 // C-NEXT: [[INT:%.*]] = ptrtoint ptr [[DEST]] to i64, !nosanitize
@@ -27,26 +28,26 @@ extern "C" {
 // C: handler.type_mismatch:
 // C-NEXT: call void @__ubsan_handle_type_mismatch_v1_abort
 // C: call void @llvm.memcpy
-void test_lhs_ptr(AGG *dest) {
+void test_lhs_ptrcheck_deref(AGG *dest) {
   AGG local = {0};
   *dest = local;
 }
 
-// C-LABEL: define {{.*}}@test_lhs_array(
+// C-LABEL: define {{.*}}@test_lhs_ptrcheck_subscript(
 // C: [[ARR:%.*]] = load ptr, ptr %arr.addr
 // C-NEXT: [[DEST:%.*]] = getelementptr inbounds %{{(struct|union)}}.Agg, ptr 
[[ARR]], i64 0
 // C-NEXT: [[CMP:%.*]] = icmp ne ptr [[DEST]], null, !nosanitize
 // C: handler.type_mismatch:
 // C-NEXT: call void @__ubsan_handle_type_mismatch_v1_abort
 // C: call void @llvm.memcpy
-void test_lhs_array(AGG arr[4]) {
+void test_lhs_ptrcheck_subscript(AGG arr[4]) {
   AGG local = {0};
   arr[0] = local;
 }
 
 // RHS checks - both C and C++
 
-// CHECK-LABEL: define {{.*}}@test_rhs_ptr(
+// CHECK-LABEL: define {{.*}}@test_rhs_ptrcheck_deref(
 // CHECK: [[SRC:%.*]] = load ptr, ptr %src.addr
 // CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[SRC]], null, !nosanitize
 // CHECK-NEXT: [[INT:%.*]] = ptrtoint ptr [[SRC]] to i64, !nosanitize
@@ -58,20 +59,20 @@ void test_lhs_array(AGG arr[4]) {
 // CHECK-NEXT: call void @__ubsan_handle_type_mismatch_v1_abort
 // CHECK: cont:
 // CHECK-NEXT: call void @llvm.memcpy
-void test_rhs_ptr(AGG *src) {
+void test_rhs_ptrcheck_deref(AGG *src) {
   AGG local;
   local = *src;
   (void)local;
 }
 
-// CHECK-LABEL: define {{.*}}@test_rhs_array(
+// CHECK-LABEL: define {{.*}}@test_rhs_ptrcheck_subscript(
 // CHECK: [[ARR:%.*]] = load ptr, ptr %arr.addr
 // CHECK-NEXT: [[SRC:%.*]] = getelementptr inbounds %{{(struct|union)}}.Agg, 
ptr [[ARR]], i64 0
 // CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[SRC]], null, !nosanitize
 // CHECK: handler.type_mismatch:
 // CHECK-NEXT: call void @__ubsan_handle_type_mismatch_v1_abort
 // CHECK: call void @llvm.memcpy
-void test_rhs_array(AGG arr[4]) {
+void test_rhs_ptrcheck_subscript(AGG arr[4]) {
   AGG local;
   local = arr[0];
   (void)local;
@@ -97,7 +98,7 @@ void test_init_from_array(AGG arr[4]) {
   (void)local;
 }
 
-// Array bounds - out-of-bounds access
+// Array bounds - out-of-bounds access (RHS)
 
 // CHECK-LABEL: define {{.*}}@test_oob_rhs(
 // CHECK: br i1 {{(true|false)}}, label %cont, label %handler.out_of_bounds
@@ -113,12 +114,27 @@ void test_oob_rhs(void) {
   (void)local;
 }
 
+// Array bounds - out-of-bounds access (LHS)
+
+// C-LABEL: define {{.*}}@test_oob_lhs(
+// C: br i1 {{(true|false)}}, label %cont, label %handler.out_of_bounds
+// C: handler.out_of_bounds:
+// C-NEXT: call void @__ubsan_handle_out_of_bounds_abort
+// C: handler.type_mismatch:
+// C-NEXT: call void @__ubsan_handle_type_mismatch_v1_abort
+// C: call void @llvm.memcpy
+void test_oob_lhs(void) {
+  AGG arr[4];
+  AGG local = {0};
+  arr[4] = local;
+  (void)arr;
+}
+
 #ifdef __cplusplus
 }
 #endif
 
-
-// C++ - handler call only
+// C++ RHS cases - handler call only
 
 #ifdef __cplusplus
 

>From 24ab5af544afeb925012102ffe0f34da72338681 Mon Sep 17 00:00:00 2001
From: vasu-ibm <[email protected]>
Date: Wed, 6 May 2026 02:50:25 -0400
Subject: [PATCH 7/7] add C++ checks for test_oob_lhs

---
 clang/test/CodeGen/ubsan-aggregate-null-align.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/clang/test/CodeGen/ubsan-aggregate-null-align.c 
b/clang/test/CodeGen/ubsan-aggregate-null-align.c
index d5b6de3f456c0..579adb3f1c9ea 100644
--- a/clang/test/CodeGen/ubsan-aggregate-null-align.c
+++ b/clang/test/CodeGen/ubsan-aggregate-null-align.c
@@ -116,13 +116,13 @@ void test_oob_rhs(void) {
 
 // Array bounds - out-of-bounds access (LHS)
 
-// C-LABEL: define {{.*}}@test_oob_lhs(
-// C: br i1 {{(true|false)}}, label %cont, label %handler.out_of_bounds
-// C: handler.out_of_bounds:
-// C-NEXT: call void @__ubsan_handle_out_of_bounds_abort
+// CHECK-LABEL: define {{.*}}@test_oob_lhs(
+// CHECK: br i1 {{(true|false)}}, label %cont, label %handler.out_of_bounds
+// CHECK: handler.out_of_bounds:
+// CHECK-NEXT: call void @__ubsan_handle_out_of_bounds_abort
 // C: handler.type_mismatch:
 // C-NEXT: call void @__ubsan_handle_type_mismatch_v1_abort
-// C: call void @llvm.memcpy
+// CHECK: call void @llvm.memcpy
 void test_oob_lhs(void) {
   AGG arr[4];
   AGG local = {0};

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

Reply via email to