[clang] [UBSAN] add null, alignment and array-bounds checks (PR #190739)

VASU SHARMA via cfe-commits cfe-commits at lists.llvm.org
Thu Apr 9 04:59:51 PDT 2026


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 <Vasu.Sharma2 at ibm.com>
Date: Tue, 7 Apr 2026 03:01:00 -0400
Subject: [PATCH 1/3] 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 <Vasu.Sharma2 at ibm.com>
Date: Tue, 7 Apr 2026 08:22:55 -0400
Subject: [PATCH 2/3] 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 <Vasu.Sharma2 at ibm.com>
Date: Thu, 9 Apr 2026 07:58:47 -0400
Subject: [PATCH 3/3] 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]};



More information about the cfe-commits mailing list