[clang] [CodeGen] Fix -fsanitize=array-bounds for __sized_by / _or_null pointers (PR #213795)
Dan Liew via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 9 01:20:29 PDT 2026
https://github.com/delcypher updated https://github.com/llvm/llvm-project/pull/213795
>From 7b004a29fdb8d6b43168a06ae86bbbae072a089e Mon Sep 17 00:00:00 2001
From: Dan Liew <dliew at apple.com>
Date: Fri, 31 Jul 2026 15:50:22 -0700
Subject: [PATCH 1/3] [CodeGen] Fix -fsanitize=array-bounds for __sized_by /
_or_null pointers
`EmitCountedByBoundsChecking()` assumed a CountAttributedType is always
a __counted_by pointer. That isn't true; there are four versions of the
attribute:
* `__counted_by`: Already handled correctly.
* `__counted_by_or_null`: Incorrectly handled.
* `__sized_by`: Incorrectly handled.
* `__sized_by_or_null`: Incorrectly handled.
In particular:
* __sized_by / __sized_by_or_null: the loaded bound is a byte count, but the
element index was compared against it directly, so an access was only
flagged once the index exceeded the byte count -- missing out-of-bounds
accesses for a pointee larger than one byte. Convert the loaded byte count
into an element count by dividing it by the element size (`bound /
sizeof(element)`) so the check can compare the (element) index directly.
`counted_by` already counts elements and is unchanged; a void (or otherwise
zero-/unknown-sized) pointee uses the GNU convention of element size 1, i.e.
no conversion. Signed division is used for a signed count field so a negative
byte count stays non-positive and is still rejected by the negative-bounds
guard in EmitBoundsCheckImpl (unsigned division would turn it into a large
positive count).
* __counted_by_or_null / __sized_by_or_null: a null pointer describes no
accessible memory, but the null case was ignored, so an access through a
null pointer with a non-zero count was not trapped. Treat the bound as 0
when the pointer is null.
Both adjustments are applied to the loaded bound in
EmitCountedByBoundsChecking before it is handed to EmitBoundsCheckImpl;
the bounds-checking machinery and the runtime handler are left unchanged
and continue to work in terms of the element index. Plain `__counted_by`
and the general array-bounds path are unaffected.
I did try an alternative implementation where the comparison was done
in terms of bytes, but this had several disadvantages:
* It was less correct. Because the element-count implementation uses
truncating division, a `__sized_by()` whose size is not a multiple of the
pointee size rounds the bound down, so an access to a partially in-bounds
object is caught. A byte-level check would instead only verify that the
first byte of the object is in bounds, which would allow accessing a
partially in-bounds object.
* When benchmarking (small microbenchmarks), it appeared that the
division implementation was faster.
* It required changes in `CodeGenFunction::EmitBoundsCheckImpl` as well,
which made the change more invasive.
Assisted-by: Claude Code
rdar://184139694
---
clang/lib/CodeGen/CGExpr.cpp | 35 +
.../attr-counted-by-or-null-for-pointers.c | 389 +++++++---
.../test/CodeGen/attr-sized-by-for-pointers.c | 535 +++++++++++--
.../attr-sized-by-or-null-for-pointers.c | 714 ++++++++++++++----
4 files changed, 1327 insertions(+), 346 deletions(-)
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 1ca649afb197a..afe2dd8e79848 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -5011,6 +5011,41 @@ void CodeGenFunction::EmitCountedByBoundsChecking(
BoundsVal = Builder.CreateAlignedLoad(BoundsType, BoundsVal, getIntAlign(),
".counted_by.load");
+ const auto *CAT = FD->getType()->getAs<CountAttributedType>();
+
+ // For the '_or_null' variants a null pointer describes no accessible
+ // memory, so treat the bound as 0 when the pointer is null; any access then
+ // traps.
+ if (CAT->isOrNull()) {
+ llvm::Value *Ptr = EmitScalarExpr(ME);
+ llvm::Value *IsNull = Builder.CreateIsNull(Ptr);
+ BoundsVal = Builder.CreateSelect(
+ IsNull, llvm::ConstantInt::get(BoundsType, 0), BoundsVal);
+ }
+
+ // For '__sized_by' the loaded bound is a byte count. Convert it to an
+ // element count by dividing by the element size so the check can compare
+ // the (element) index directly. '__counted_by' already counts elements, and
+ // a void (or otherwise zero-/unknown-sized) pointee uses the GNU convention
+ // of element size 1; both need no conversion. Use signed division for a
+ // signed count field so a negative byte count stays non-positive and is
+ // still rejected by the negative-bounds guard in EmitBoundsCheckImpl
+ // (unsigned division would turn it into a large positive count).
+ if (CAT->isCountInBytes()) {
+ QualType ElemTy = ArrayType->getPointeeType();
+ if (!ElemTy.isNull() && !ElemTy->isIncompleteType() &&
+ !ElemTy->isFunctionType()) {
+ CharUnits ElemSize = getContext().getTypeSizeInChars(ElemTy);
+ if (ElemSize > CharUnits::One()) {
+ llvm::Value *ElemSizeV = llvm::ConstantInt::get(
+ BoundsVal->getType(), ElemSize.getQuantity());
+ BoundsVal = CountFD->getType()->isSignedIntegerOrEnumerationType()
+ ? Builder.CreateSDiv(BoundsVal, ElemSizeV)
+ : Builder.CreateUDiv(BoundsVal, ElemSizeV);
+ }
+ }
+ }
+
// Now emit the bounds checking.
EmitBoundsCheckImpl(ArrayExpr, ArrayType, IndexVal, IndexType, BoundsVal,
CountFD->getType(), Accessed);
diff --git a/clang/test/CodeGen/attr-counted-by-or-null-for-pointers.c b/clang/test/CodeGen/attr-counted-by-or-null-for-pointers.c
index 56b52fae804d2..4648ca21239e6 100644
--- a/clang/test/CodeGen/attr-counted-by-or-null-for-pointers.c
+++ b/clang/test/CodeGen/attr-counted-by-or-null-for-pointers.c
@@ -31,11 +31,182 @@ struct annotated_ptr {
int ptr_count;
};
-// SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 17179869177) i64 @test_bdos_of_pointer(
-// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_store_subscript(
+// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 0, i32 [[DOTCOUNTED_BY_LOAD]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ult i32 [[INDEX]], [[TMP2]], !nosanitize [[META12:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP2]], 0, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT15:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13:![0-9]+]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
+// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 [[TMP6]]) #[[ATTR5:[0-9]+]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR: [[CONT15]]:
+// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA14:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: ret void
+//
+// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_store_subscript(
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: ret void
+//
+// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_store_subscript(
+// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6:![0-9]+]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITHOUT-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12:![0-9]+]]
+// SANITIZE-WITHOUT-ATTR-NEXT: ret void
+//
+// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_store_subscript(
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6:![0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12:![0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
+//
+void test_store_subscript(struct annotated_ptr *p, int index, struct foo *value) {
+ p->buf[index] = value;
+}
+
+// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_store_subscript_through_cast(
+// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 0, i32 [[DOTCOUNTED_BY_LOAD]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ult i32 [[INDEX]], [[TMP2]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP2]], 0, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT15:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
+// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 [[TMP6]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR: [[CONT15]]:
+// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA14]]
+// SANITIZE-WITH-ATTR-NEXT: ret void
+//
+// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_store_subscript_through_cast(
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// NO-SANITIZE-WITH-ATTR-NEXT: ret void
+//
+// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_store_subscript_through_cast(
+// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITHOUT-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// SANITIZE-WITHOUT-ATTR-NEXT: ret void
+//
+// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_store_subscript_through_cast(
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
+//
+void test_store_subscript_through_cast(struct annotated_ptr *p, int index, struct foo *value) {
+ ((struct foo **)((char *)p->buf))[index] = value;
+}
+
+// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_store_subscript_through_deref_of_addressof(
+// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 0, i32 [[DOTCOUNTED_BY_LOAD]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ule i32 [[INDEX]], [[TMP2]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP2]], 0, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT15:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
+// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 [[TMP6]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR: [[CONT15]]:
+// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA14]]
+// SANITIZE-WITH-ATTR-NEXT: ret void
+//
+// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_store_subscript_through_deref_of_addressof(
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// NO-SANITIZE-WITH-ATTR-NEXT: ret void
+//
+// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_store_subscript_through_deref_of_addressof(
+// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITHOUT-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// SANITIZE-WITHOUT-ATTR-NEXT: ret void
+//
+// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_store_subscript_through_deref_of_addressof(
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
+//
+void test_store_subscript_through_deref_of_addressof(struct annotated_ptr *p, int index, struct foo *value) {
+ *&*&*&p->buf[index] = value;
+}
+
+// SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 17179869177) i64 @test_bdos_of_pointer(
+// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[COUNTED_BY_LOAD]] to i64
@@ -46,10 +217,10 @@ struct annotated_ptr {
// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP4]]
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 17179869177) i64 @test_bdos_of_pointer(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[COUNTED_BY_LOAD]] to i64
@@ -60,12 +231,12 @@ struct annotated_ptr {
// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP4]]
//
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_pointer(
-// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_pointer(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -88,7 +259,7 @@ size_t test_bdos_of_pointer(struct annotated_ptr *p) {
// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP4]]
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 17179869177) i64 @test_bdos_of_pointer_through_cast(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
@@ -107,7 +278,7 @@ size_t test_bdos_of_pointer(struct annotated_ptr *p) {
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_pointer_through_cast(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -118,31 +289,32 @@ size_t test_bdos_of_pointer_through_cast(struct annotated_ptr *p, int index) {
// SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 34359738361) i64 @test_bdos_of_element_address(
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
-// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 4
-// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp ule i32 [[INDEX]], [[DOTCOUNTED_BY_LOAD]], !nosanitize [[META12:![0-9]+]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[DOTCOUNTED_BY_LOAD]], 0, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]], !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13:![0-9]+]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 0, i32 [[DOTCOUNTED_BY_LOAD]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ule i32 [[INDEX]], [[TMP2]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP2]], 0, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT13:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
-// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 [[TMP3]]) #[[ATTR5:[0-9]+]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB6:[0-9]+]], i64 [[TMP6]]) #[[ATTR5]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR: [[CONT8]]:
-// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
-// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = zext nneg i32 [[DOTCOUNTED_BY_LOAD]] to i64
+// SANITIZE-WITH-ATTR: [[CONT13]]:
+// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[DOTCOUNTED_BY_LOAD]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
-// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp eq ptr [[TMP4]], null
-// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = shl nuw nsw i64 [[COUNT]], 3
-// SANITIZE-WITH-ATTR-NEXT: [[ARRAY_SIZE:%.*]] = select i1 [[TMP5]], i64 0, i64 [[TMP6]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = shl nsw i64 [[COUNT]], 3
+// SANITIZE-WITH-ATTR-NEXT: [[ARRAY_SIZE:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP7]]
// SANITIZE-WITH-ATTR-NEXT: [[INDEX_SIZE:%.*]] = shl nuw nsw i64 [[IDXPROM]], 3
// SANITIZE-WITH-ATTR-NEXT: [[RESULT:%.*]] = sub nsw i64 [[ARRAY_SIZE]], [[INDEX_SIZE]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = tail call i64 @llvm.smax.i64(i64 [[RESULT]], i64 0)
-// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP7]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = tail call i64 @llvm.smax.i64(i64 [[RESULT]], i64 0)
+// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP8]]
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -34359738360, 34359738361) i64 @test_bdos_of_element_address(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
@@ -167,7 +339,7 @@ size_t test_bdos_of_pointer_through_cast(struct annotated_ptr *p, int index) {
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_element_address(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -178,21 +350,25 @@ size_t test_bdos_of_element_address(struct annotated_ptr *p, int index) {
// SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test_bdos_of_subscript_through_cast(
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
-// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp ult i32 [[INDEX]], [[DOTCOUNTED_BY_LOAD]], !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[DOTCOUNTED_BY_LOAD]], 0, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]], !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 0, i32 [[DOTCOUNTED_BY_LOAD]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ult i32 [[INDEX]], [[TMP2]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP2]], 0, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT15:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
-// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 [[TMP3]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB7:[0-9]+]], i64 [[TMP6]]) #[[ATTR5]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR: [[CONT10]]:
+// SANITIZE-WITH-ATTR: [[CONT15]]:
// SANITIZE-WITH-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test_bdos_of_subscript_through_cast(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 -1
//
@@ -202,7 +378,7 @@ size_t test_bdos_of_element_address(struct annotated_ptr *p, int index) {
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_subscript_through_cast(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -218,7 +394,7 @@ struct pr151236_struct {
// SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 262137) i64 @test_bdos_of_short_count_field(
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA14:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA16:![0-9]+]]
// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i16, ptr [[COUNTED_BY_GEP]], align 8
// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i16 [[COUNTED_BY_LOAD]] to i64
@@ -230,9 +406,9 @@ struct pr151236_struct {
// SANITIZE-WITH-ATTR-NEXT: ret i64 [[ADD]]
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 262137) i64 @test_bdos_of_short_count_field(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR1]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA12:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA14:![0-9]+]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i16, ptr [[COUNTED_BY_GEP]], align 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i16 [[COUNTED_BY_LOAD]] to i64
@@ -249,7 +425,7 @@ struct pr151236_struct {
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -2
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local range(i64 0, -1) i64 @test_bdos_of_short_count_field(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR1]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -2
//
@@ -260,7 +436,7 @@ size_t test_bdos_of_short_count_field(struct pr151236_struct *p) {
// SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 262137) i64 @test_bdos_of_short_count_field_through_cast(
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA14]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA16]]
// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i16, ptr [[COUNTED_BY_GEP]], align 8
// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i16 [[COUNTED_BY_LOAD]] to i64
@@ -272,9 +448,9 @@ size_t test_bdos_of_short_count_field(struct pr151236_struct *p) {
// SANITIZE-WITH-ATTR-NEXT: ret i64 [[ADD]]
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 262137) i64 @test_bdos_of_short_count_field_through_cast(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR1]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA12]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA14]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i16, ptr [[COUNTED_BY_GEP]], align 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i16 [[COUNTED_BY_LOAD]] to i64
@@ -291,7 +467,7 @@ size_t test_bdos_of_short_count_field(struct pr151236_struct *p) {
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -2
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local range(i64 0, -1) i64 @test_bdos_of_short_count_field_through_cast(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR1]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -2
//
@@ -319,7 +495,7 @@ void take_ptr_with_size(void *p __attribute__((pass_dynamic_object_size(0))));
// SANITIZE-WITH-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i64 @test_bdos_of_volatile_pointer(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readnone captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readnone captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 -1
//
@@ -329,7 +505,7 @@ void take_ptr_with_size(void *p __attribute__((pass_dynamic_object_size(0))));
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i64 @test_bdos_of_volatile_pointer(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readnone captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readnone captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -345,7 +521,7 @@ size_t test_bdos_of_volatile_pointer(struct annotated_volatile_ptr *p) {
// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_pointer(
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA18:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20:![0-9]+]]
// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[COUNTED_BY_LOAD]] to i64
@@ -357,9 +533,9 @@ size_t test_bdos_of_volatile_pointer(struct annotated_volatile_ptr *p) {
// SANITIZE-WITH-ATTR-NEXT: ret void
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_pointer(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA16:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA18:![0-9]+]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[COUNTED_BY_LOAD]] to i64
@@ -367,21 +543,21 @@ size_t test_bdos_of_volatile_pointer(struct annotated_volatile_ptr *p) {
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = shl nsw i64 [[COUNT]], 2
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = tail call i64 @llvm.smax.i64(i64 [[TMP2]], i64 0)
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP3]]
-// NO-SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef [[TMP4]]) #[[ATTR6:[0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef [[TMP4]]) #[[ATTR7:[0-9]+]]
// NO-SANITIZE-WITH-ATTR-NEXT: ret void
//
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_pointer(
// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
-// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA6:![0-9]+]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA14:![0-9]+]]
// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef -1) #[[ATTR3:[0-9]+]]
// SANITIZE-WITHOUT-ATTR-NEXT: ret void
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_pointer(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
-// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA6:![0-9]+]]
-// NO-SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef -1) #[[ATTR5:[0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA14:![0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef -1) #[[ATTR6:[0-9]+]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
//
void test_pass_dynamic_object_size_of_pointer(struct annotated_volatile_ptr *p) {
@@ -394,40 +570,43 @@ void test_pass_dynamic_object_size_of_pointer(struct annotated_volatile_ptr *p)
// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_element_address(
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA18]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20]]
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
-// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ule i32 [[INDEX]], [[DOTCOUNTED_BY_LOAD]], !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[DOTCOUNTED_BY_LOAD]], 0, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]], !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label %[[CONT9:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP1]], null
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 0, i32 [[DOTCOUNTED_BY_LOAD]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ule i32 [[INDEX]], [[TMP3]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[TMP3]], 0, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT12:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
-// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB6:[0-9]+]], i64 [[TMP4]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB9:[0-9]+]], i64 [[TMP7]]) #[[ATTR5]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR: [[CONT9]]:
-// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = zext nneg i32 [[DOTCOUNTED_BY_LOAD]] to i64
+// SANITIZE-WITH-ATTR: [[CONT12]]:
+// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[DOTCOUNTED_BY_LOAD]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDXPROM]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA18]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = icmp eq ptr [[TMP5]], null
-// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = shl nuw nsw i64 [[COUNT]], 2
-// SANITIZE-WITH-ATTR-NEXT: [[ARRAY_SIZE:%.*]] = select i1 [[TMP6]], i64 0, i64 [[TMP7]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP9:%.*]] = icmp eq ptr [[TMP8]], null
+// SANITIZE-WITH-ATTR-NEXT: [[TMP10:%.*]] = shl nsw i64 [[COUNT]], 2
+// SANITIZE-WITH-ATTR-NEXT: [[ARRAY_SIZE:%.*]] = select i1 [[TMP9]], i64 0, i64 [[TMP10]]
// SANITIZE-WITH-ATTR-NEXT: [[RESULT:%.*]] = sub nsw i64 [[ARRAY_SIZE]], [[IDXPROM]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = tail call i64 @llvm.smax.i64(i64 [[RESULT]], i64 0)
-// SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef [[TMP8]]) #[[ATTR6]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP11:%.*]] = tail call i64 @llvm.smax.i64(i64 [[RESULT]], i64 0)
+// SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef [[TMP11]]) #[[ATTR6]]
// SANITIZE-WITH-ATTR-NEXT: ret void
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_element_address(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR3]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR4]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA16]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA18]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDXPROM]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[COUNTED_BY_LOAD]] to i64
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA16]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA18]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP1]], null
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = shl nsw i64 [[COUNT]], 2
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAY_SIZE:%.*]] = select i1 [[TMP2]], i64 0, i64 [[TMP3]]
@@ -436,25 +615,25 @@ void test_pass_dynamic_object_size_of_pointer(struct annotated_volatile_ptr *p)
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[INDEX]], -1
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = select i1 [[TMP6]], i64 [[RESULT]], i64 0
-// NO-SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef [[TMP7]]) #[[ATTR6]]
+// NO-SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef [[TMP7]]) #[[ATTR7]]
// NO-SANITIZE-WITH-ATTR-NEXT: ret void
//
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_element_address(
// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
-// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA6]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA14]]
// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDXPROM]]
// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef -1) #[[ATTR3]]
// SANITIZE-WITHOUT-ATTR-NEXT: ret void
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_element_address(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR3]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR4]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
-// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA6]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA14]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDXPROM]]
-// NO-SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef -1) #[[ATTR5]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef -1) #[[ATTR6]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
//
void test_pass_dynamic_object_size_of_element_address(struct annotated_volatile_ptr *p, int index) {
@@ -472,12 +651,14 @@ void test_pass_dynamic_object_size_of_element_address(struct annotated_volatile_
// SANITIZE-WITH-ATTR: [[META11]] = !{!"any pointer", [[META4]], i64 0}
// SANITIZE-WITH-ATTR: [[META12]] = !{}
// SANITIZE-WITH-ATTR: [[PROF13]] = !{!"branch_weights", i32 1048575, i32 1}
-// SANITIZE-WITH-ATTR: [[INTPTR_TBAA14]] = !{[[META15:![0-9]+]], [[META16:![0-9]+]], i64 0}
-// SANITIZE-WITH-ATTR: [[META15]] = !{!"pr151236_struct", [[META16]], i64 0, [[META17:![0-9]+]], i64 8}
-// SANITIZE-WITH-ATTR: [[META16]] = !{!"p1 int", [[META11]], i64 0}
-// SANITIZE-WITH-ATTR: [[META17]] = !{!"short", [[META4]], i64 0}
-// SANITIZE-WITH-ATTR: [[INTPTR_TBAA18]] = !{[[META19:![0-9]+]], [[META16]], i64 0}
-// SANITIZE-WITH-ATTR: [[META19]] = !{!"annotated_volatile_ptr", [[META16]], i64 0, [[META3]], i64 8}
+// SANITIZE-WITH-ATTR: [[_ZTS3FOOPTR_TBAA14]] = !{[[META15:![0-9]+]], [[META15]], i64 0}
+// SANITIZE-WITH-ATTR: [[META15]] = !{!"p1 _ZTS3foo", [[META11]], i64 0}
+// SANITIZE-WITH-ATTR: [[INTPTR_TBAA16]] = !{[[META17:![0-9]+]], [[META18:![0-9]+]], i64 0}
+// SANITIZE-WITH-ATTR: [[META17]] = !{!"pr151236_struct", [[META18]], i64 0, [[META19:![0-9]+]], i64 8}
+// SANITIZE-WITH-ATTR: [[META18]] = !{!"p1 int", [[META11]], i64 0}
+// SANITIZE-WITH-ATTR: [[META19]] = !{!"short", [[META4]], i64 0}
+// SANITIZE-WITH-ATTR: [[INTPTR_TBAA20]] = !{[[META21:![0-9]+]], [[META18]], i64 0}
+// SANITIZE-WITH-ATTR: [[META21]] = !{!"annotated_volatile_ptr", [[META18]], i64 0, [[META3]], i64 8}
//.
// NO-SANITIZE-WITH-ATTR: [[META3:![0-9]+]] = !{!"int", [[META4:![0-9]+]], i64 0}
// NO-SANITIZE-WITH-ATTR: [[META4]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}
@@ -488,26 +669,42 @@ void test_pass_dynamic_object_size_of_element_address(struct annotated_volatile_
// NO-SANITIZE-WITH-ATTR: [[META9]] = !{!"p2 _ZTS3foo", [[META10:![0-9]+]], i64 0}
// NO-SANITIZE-WITH-ATTR: [[META10]] = !{!"any p2 pointer", [[META11:![0-9]+]], i64 0}
// NO-SANITIZE-WITH-ATTR: [[META11]] = !{!"any pointer", [[META4]], i64 0}
-// NO-SANITIZE-WITH-ATTR: [[INTPTR_TBAA12]] = !{[[META13:![0-9]+]], [[META14:![0-9]+]], i64 0}
-// NO-SANITIZE-WITH-ATTR: [[META13]] = !{!"pr151236_struct", [[META14]], i64 0, [[META15:![0-9]+]], i64 8}
-// NO-SANITIZE-WITH-ATTR: [[META14]] = !{!"p1 int", [[META11]], i64 0}
-// NO-SANITIZE-WITH-ATTR: [[META15]] = !{!"short", [[META4]], i64 0}
-// NO-SANITIZE-WITH-ATTR: [[INTPTR_TBAA16]] = !{[[META17:![0-9]+]], [[META14]], i64 0}
-// NO-SANITIZE-WITH-ATTR: [[META17]] = !{!"annotated_volatile_ptr", [[META14]], i64 0, [[META3]], i64 8}
+// NO-SANITIZE-WITH-ATTR: [[_ZTS3FOOPTR_TBAA12]] = !{[[META13:![0-9]+]], [[META13]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[META13]] = !{!"p1 _ZTS3foo", [[META11]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[INTPTR_TBAA14]] = !{[[META15:![0-9]+]], [[META16:![0-9]+]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[META15]] = !{!"pr151236_struct", [[META16]], i64 0, [[META17:![0-9]+]], i64 8}
+// NO-SANITIZE-WITH-ATTR: [[META16]] = !{!"p1 int", [[META11]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[META17]] = !{!"short", [[META4]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[INTPTR_TBAA18]] = !{[[META19:![0-9]+]], [[META16]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[META19]] = !{!"annotated_volatile_ptr", [[META16]], i64 0, [[META3]], i64 8}
//.
// SANITIZE-WITHOUT-ATTR: [[META3:![0-9]+]] = !{!"int", [[META4:![0-9]+]], i64 0}
// SANITIZE-WITHOUT-ATTR: [[META4]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}
// SANITIZE-WITHOUT-ATTR: [[META5]] = !{!"Simple C/C++ TBAA"}
-// SANITIZE-WITHOUT-ATTR: [[INTPTR_TBAA6]] = !{[[META7:![0-9]+]], [[META8:![0-9]+]], i64 0}
-// SANITIZE-WITHOUT-ATTR: [[META7]] = !{!"annotated_volatile_ptr", [[META8]], i64 0, [[META3]], i64 8}
-// SANITIZE-WITHOUT-ATTR: [[META8]] = !{!"p1 int", [[META9:![0-9]+]], i64 0}
-// SANITIZE-WITHOUT-ATTR: [[META9]] = !{!"any pointer", [[META4]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[_ZTS3FOOPTR_TBAA6]] = !{[[META7:![0-9]+]], [[META9:![0-9]+]], i64 8}
+// SANITIZE-WITHOUT-ATTR: [[META7]] = !{!"annotated_ptr", [[META8:![0-9]+]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
+// SANITIZE-WITHOUT-ATTR: [[META8]] = !{!"long", [[META4]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[META9]] = !{!"p2 _ZTS3foo", [[META10:![0-9]+]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[META10]] = !{!"any p2 pointer", [[META11:![0-9]+]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[META11]] = !{!"any pointer", [[META4]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[_ZTS3FOOPTR_TBAA12]] = !{[[META13:![0-9]+]], [[META13]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[META13]] = !{!"p1 _ZTS3foo", [[META11]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[INTPTR_TBAA14]] = !{[[META15:![0-9]+]], [[META16:![0-9]+]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[META15]] = !{!"annotated_volatile_ptr", [[META16]], i64 0, [[META3]], i64 8}
+// SANITIZE-WITHOUT-ATTR: [[META16]] = !{!"p1 int", [[META11]], i64 0}
//.
// NO-SANITIZE-WITHOUT-ATTR: [[META3:![0-9]+]] = !{!"int", [[META4:![0-9]+]], i64 0}
// NO-SANITIZE-WITHOUT-ATTR: [[META4]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}
// NO-SANITIZE-WITHOUT-ATTR: [[META5]] = !{!"Simple C/C++ TBAA"}
-// NO-SANITIZE-WITHOUT-ATTR: [[INTPTR_TBAA6]] = !{[[META7:![0-9]+]], [[META8:![0-9]+]], i64 0}
-// NO-SANITIZE-WITHOUT-ATTR: [[META7]] = !{!"annotated_volatile_ptr", [[META8]], i64 0, [[META3]], i64 8}
-// NO-SANITIZE-WITHOUT-ATTR: [[META8]] = !{!"p1 int", [[META9:![0-9]+]], i64 0}
-// NO-SANITIZE-WITHOUT-ATTR: [[META9]] = !{!"any pointer", [[META4]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[_ZTS3FOOPTR_TBAA6]] = !{[[META7:![0-9]+]], [[META9:![0-9]+]], i64 8}
+// NO-SANITIZE-WITHOUT-ATTR: [[META7]] = !{!"annotated_ptr", [[META8:![0-9]+]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
+// NO-SANITIZE-WITHOUT-ATTR: [[META8]] = !{!"long", [[META4]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[META9]] = !{!"p2 _ZTS3foo", [[META10:![0-9]+]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[META10]] = !{!"any p2 pointer", [[META11:![0-9]+]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[META11]] = !{!"any pointer", [[META4]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[_ZTS3FOOPTR_TBAA12]] = !{[[META13:![0-9]+]], [[META13]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[META13]] = !{!"p1 _ZTS3foo", [[META11]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[INTPTR_TBAA14]] = !{[[META15:![0-9]+]], [[META16:![0-9]+]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[META15]] = !{!"annotated_volatile_ptr", [[META16]], i64 0, [[META3]], i64 8}
+// NO-SANITIZE-WITHOUT-ATTR: [[META16]] = !{!"p1 int", [[META11]], i64 0}
//.
diff --git a/clang/test/CodeGen/attr-sized-by-for-pointers.c b/clang/test/CodeGen/attr-sized-by-for-pointers.c
index 8bf77bcf71ca5..ec42d54d10360 100644
--- a/clang/test/CodeGen/attr-sized-by-for-pointers.c
+++ b/clang/test/CodeGen/attr-sized-by-for-pointers.c
@@ -19,6 +19,314 @@
typedef long unsigned int size_t;
struct foo { size_t field; };
+struct annotated_ptr {
+ unsigned long flags;
+ struct foo **buf __sized_by(ptr_count);
+ int ptr_count;
+};
+
+// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_store_subscript(
+// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = sdiv i32 [[DOTCOUNTED_BY_LOAD]], 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ult i32 [[INDEX]], [[TMP0]], !nosanitize [[META6:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[DOTCOUNTED_BY_LOAD]], 7
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7:![0-9]+]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 [[TMP4]]) #[[ATTR5:[0-9]+]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR: [[CONT10]]:
+// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA8:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP5]], i64 [[IDXPROM]]
+// SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA14:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: ret void
+//
+// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_store_subscript(
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: ret void
+//
+// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_store_subscript(
+// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6:![0-9]+]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITHOUT-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12:![0-9]+]]
+// SANITIZE-WITHOUT-ATTR-NEXT: ret void
+//
+// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_store_subscript(
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6:![0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12:![0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
+//
+void test_store_subscript(struct annotated_ptr *p, int index, struct foo *value) {
+ p->buf[index] = value;
+}
+
+// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_store_subscript_through_cast(
+// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = sdiv i32 [[DOTCOUNTED_BY_LOAD]], 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ult i32 [[INDEX]], [[TMP0]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[DOTCOUNTED_BY_LOAD]], 7
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 [[TMP4]]) #[[ATTR5]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR: [[CONT10]]:
+// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA8]]
+// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP5]], i64 [[IDXPROM]]
+// SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA14]]
+// SANITIZE-WITH-ATTR-NEXT: ret void
+//
+// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_store_subscript_through_cast(
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// NO-SANITIZE-WITH-ATTR-NEXT: ret void
+//
+// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_store_subscript_through_cast(
+// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITHOUT-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// SANITIZE-WITHOUT-ATTR-NEXT: ret void
+//
+// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_store_subscript_through_cast(
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
+//
+void test_store_subscript_through_cast(struct annotated_ptr *p, int index, struct foo *value) {
+ ((struct foo **)((char *)p->buf))[index] = value;
+}
+
+// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_store_subscript_through_deref_of_addressof(
+// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = sdiv i32 [[DOTCOUNTED_BY_LOAD]], 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ule i32 [[INDEX]], [[TMP0]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[DOTCOUNTED_BY_LOAD]], 7
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 [[TMP4]]) #[[ATTR5]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR: [[CONT10]]:
+// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA8]]
+// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP5]], i64 [[IDXPROM]]
+// SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA14]]
+// SANITIZE-WITH-ATTR-NEXT: ret void
+//
+// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_store_subscript_through_deref_of_addressof(
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// NO-SANITIZE-WITH-ATTR-NEXT: ret void
+//
+// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_store_subscript_through_deref_of_addressof(
+// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITHOUT-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// SANITIZE-WITHOUT-ATTR-NEXT: ret void
+//
+// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_store_subscript_through_deref_of_addressof(
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
+//
+void test_store_subscript_through_deref_of_addressof(struct annotated_ptr *p, int index, struct foo *value) {
+ *&*&*&p->buf[index] = value;
+}
+
+struct three_byte_pointee {
+ char data[3];
+};
+
+// With an unsigned count field the byte->element conversion 'bound /
+// sizeof(element)' is an unsigned division. A non-power-of-two element size
+// cannot be folded to a shift, so it stays a real 'udiv' (contrast
+// test_load_subscript_pow2_unsigned_count, where a power-of-two element lets
+// 'udiv' become a shift). This also exercises the floor-truncation: a bound that
+// is not a whole multiple of the element size rounds down to the number of
+// complete elements.
+struct annotated_sized_ptr_odd_pointee {
+ unsigned long flags;
+ struct three_byte_pointee *buf __sized_by(byte_count);
+ unsigned byte_count;
+};
+
+// SANITIZE-WITH-ATTR-LABEL: define dso_local signext i8 @test_load_subscript_odd_pointee(
+// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = udiv i32 [[DOTCOUNTED_BY_LOAD]], 3
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ult i32 [[INDEX]], [[TMP0]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label %[[CONT15:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB7:[0-9]+]], i64 [[TMP2]]) #[[ATTR5]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR: [[CONT15]]:
+// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS18THREE_BYTE_POINTEEPTR_TBAA16:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x i8], ptr [[TMP3]], i64 [[IDXPROM]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa [[CHAR_TBAA19:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: ret i8 [[TMP4]]
+//
+// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local signext i8 @test_load_subscript_odd_pointee(
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS18THREE_BYTE_POINTEEPTR_TBAA14:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa [[CHAR_TBAA17:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: ret i8 [[TMP1]]
+//
+// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local signext i8 @test_load_subscript_odd_pointee(
+// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS18THREE_BYTE_POINTEEPTR_TBAA14:![0-9]+]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa [[CHAR_TBAA17:![0-9]+]]
+// SANITIZE-WITHOUT-ATTR-NEXT: ret i8 [[TMP1]]
+//
+// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local signext i8 @test_load_subscript_odd_pointee(
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS18THREE_BYTE_POINTEEPTR_TBAA14:![0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa [[CHAR_TBAA17:![0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i8 [[TMP1]]
+//
+char test_load_subscript_odd_pointee(struct annotated_sized_ptr_odd_pointee *p, int index) {
+ return p->buf[index].data[0];
+}
+
+// An unsigned count field makes the byte->element conversion an unsigned
+// division; for a power-of-two element size 'udiv' folds to a shift ('lshr').
+// Being unsigned there is also no negative-bounds guard (contrast the signed
+// count tests above).
+struct annotated_sized_ptr_pow2_unsigned_count {
+ unsigned long flags;
+ struct foo **buf __sized_by(byte_count);
+ unsigned byte_count;
+};
+
+// SANITIZE-WITH-ATTR-LABEL: define dso_local ptr @test_load_subscript_pow2_unsigned_count(
+// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = lshr i32 [[DOTCOUNTED_BY_LOAD]], 3
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ult i32 [[INDEX]], [[TMP0]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB9:[0-9]+]], i64 [[TMP2]]) #[[ATTR5]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR: [[CONT10]]:
+// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA20:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP3]], i64 [[IDXPROM]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA14]]
+// SANITIZE-WITH-ATTR-NEXT: ret ptr [[TMP4]]
+//
+// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local ptr @test_load_subscript_pow2_unsigned_count(
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA18:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// NO-SANITIZE-WITH-ATTR-NEXT: ret ptr [[TMP1]]
+//
+// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local ptr @test_load_subscript_pow2_unsigned_count(
+// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA18:![0-9]+]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// SANITIZE-WITHOUT-ATTR-NEXT: ret ptr [[TMP1]]
+//
+// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local ptr @test_load_subscript_pow2_unsigned_count(
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA18:![0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret ptr [[TMP1]]
+//
+struct foo *test_load_subscript_pow2_unsigned_count(struct annotated_sized_ptr_pow2_unsigned_count *p, int index) {
+ return p->buf[index];
+}
struct annotated_sized_ptr {
unsigned long flags;
@@ -27,7 +335,7 @@ struct annotated_sized_ptr {
};
// SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 2147483648) i64 @test_bdos_of_pointer(
-// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 4
@@ -36,7 +344,7 @@ struct annotated_sized_ptr {
// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP0]]
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 2147483648) i64 @test_bdos_of_pointer(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 4
@@ -45,12 +353,12 @@ struct annotated_sized_ptr {
// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP0]]
//
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_pointer(
-// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_pointer(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -63,13 +371,13 @@ size_t test_bdos_of_pointer(struct annotated_sized_ptr *p) {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 4
-// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp ule i32 [[INDEX]], [[DOTCOUNTED_BY_LOAD]], !nosanitize [[META6:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp ule i32 [[INDEX]], [[DOTCOUNTED_BY_LOAD]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[DOTCOUNTED_BY_LOAD]], 0, !nosanitize [[META6]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]], !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7:![0-9]+]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 [[TMP3]]) #[[ATTR5:[0-9]+]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB11:[0-9]+]], i64 [[TMP3]]) #[[ATTR5]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[CONT8]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
@@ -78,7 +386,7 @@ size_t test_bdos_of_pointer(struct annotated_sized_ptr *p) {
// SANITIZE-WITH-ATTR-NEXT: ret i64 [[RESULT]]
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -4294967295, 4294967296) i64 @test_bdos_of_element_address(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
@@ -97,7 +405,7 @@ size_t test_bdos_of_pointer(struct annotated_sized_ptr *p) {
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_element_address(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -110,19 +418,20 @@ size_t test_bdos_of_element_address(struct annotated_sized_ptr *p, int index) {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
-// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp ult i32 [[INDEX]], [[DOTCOUNTED_BY_LOAD]], !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[DOTCOUNTED_BY_LOAD]], 0, !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]], !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = sdiv i32 [[DOTCOUNTED_BY_LOAD]], 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ult i32 [[INDEX]], [[TMP0]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[DOTCOUNTED_BY_LOAD]], 7
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
-// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 [[TMP3]]) #[[ATTR5]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB12:[0-9]+]], i64 [[TMP4]]) #[[ATTR5]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[CONT10]]:
// SANITIZE-WITH-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test_bdos_of_subscript_through_cast(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 -1
//
@@ -132,7 +441,7 @@ size_t test_bdos_of_element_address(struct annotated_sized_ptr *p, int index) {
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_subscript_through_cast(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -160,7 +469,7 @@ struct annotated_sized_ptr_non_byte_sized_pointee {
// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP0]]
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 2147483648) i64 @test_bdos_of_pointer_multibyte_pointee(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 4
@@ -174,7 +483,7 @@ struct annotated_sized_ptr_non_byte_sized_pointee {
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_pointer_multibyte_pointee(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -182,29 +491,33 @@ size_t test_bdos_of_pointer_multibyte_pointee(struct annotated_sized_ptr_non_byt
return __bdos(p->buf); // byte_count, not byte_count * sizeof(struct foo)
}
-// SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 19327352832) i64 @test_bdos_of_element_address_multibyte_pointee(
+// SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -17179869168, 19327352832) i64 @test_bdos_of_element_address_multibyte_pointee(
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 4
-// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp ule i32 [[INDEX]], [[DOTCOUNTED_BY_LOAD]], !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[DOTCOUNTED_BY_LOAD]], 0, !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]], !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = sdiv i32 [[DOTCOUNTED_BY_LOAD]], 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ule i32 [[INDEX]], [[TMP0]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[DOTCOUNTED_BY_LOAD]], 7
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
-// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB6:[0-9]+]], i64 [[TMP3]]) #[[ATTR5]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB14:[0-9]+]], i64 [[TMP4]]) #[[ATTR5]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[CONT8]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = zext nneg i32 [[DOTCOUNTED_BY_LOAD]] to i64
-// SANITIZE-WITH-ATTR-NEXT: [[INDEX_SIZE:%.*]] = shl nuw nsw i64 [[IDXPROM]], 3
+// SANITIZE-WITH-ATTR-NEXT: [[INDEX_SIZE:%.*]] = shl nsw i64 [[IDXPROM]], 3
// SANITIZE-WITH-ATTR-NEXT: [[RESULT:%.*]] = sub nsw i64 [[COUNT]], [[INDEX_SIZE]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = tail call i64 @llvm.smax.i64(i64 [[RESULT]], i64 0)
-// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP4]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i64 [[RESULT]], -1
+// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = icmp sgt i32 [[INDEX]], -1
+// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = and i1 [[TMP6]], [[TMP5]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = select i1 [[TMP7]], i64 [[RESULT]], i64 0
+// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP8]]
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -19327352824, 19327352832) i64 @test_bdos_of_element_address_multibyte_pointee(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
@@ -224,7 +537,7 @@ size_t test_bdos_of_pointer_multibyte_pointee(struct annotated_sized_ptr_non_byt
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_element_address_multibyte_pointee(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -254,7 +567,7 @@ struct annotated_sized_ptr_incomplete {
// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP0]]
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 2147483648) i64 @test_bdos_of_pointer_incomplete_pointee(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 4
@@ -268,7 +581,7 @@ struct annotated_sized_ptr_incomplete {
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_pointer_incomplete_pointee(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -287,7 +600,7 @@ size_t test_bdos_of_pointer_incomplete_pointee(struct annotated_sized_ptr_incomp
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB8:[0-9]+]], i64 [[TMP3]]) #[[ATTR5]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB16:[0-9]+]], i64 [[TMP3]]) #[[ATTR5]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[CONT8]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
@@ -296,7 +609,7 @@ size_t test_bdos_of_pointer_incomplete_pointee(struct annotated_sized_ptr_incomp
// SANITIZE-WITH-ATTR-NEXT: ret i64 [[RESULT]]
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -4294967295, 4294967296) i64 @test_bdos_of_element_address_incomplete_pointee(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
@@ -315,7 +628,7 @@ size_t test_bdos_of_pointer_incomplete_pointee(struct annotated_sized_ptr_incomp
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_element_address_incomplete_pointee(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -343,7 +656,7 @@ void take_ptr_with_size(void *p __attribute__((pass_dynamic_object_size(0))));
// SANITIZE-WITH-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i64 @test_bdos_of_volatile_pointer(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readnone captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readnone captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 -1
//
@@ -353,7 +666,7 @@ void take_ptr_with_size(void *p __attribute__((pass_dynamic_object_size(0))));
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i64 @test_bdos_of_volatile_pointer(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readnone captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readnone captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -369,7 +682,7 @@ size_t test_bdos_of_volatile_pointer(struct annotated_volatile_ptr *p) {
// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_pointer(
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA8:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA22:![0-9]+]]
// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = tail call i32 @llvm.smax.i32(i32 [[COUNTED_BY_LOAD]], i32 0)
@@ -378,28 +691,28 @@ size_t test_bdos_of_volatile_pointer(struct annotated_volatile_ptr *p) {
// SANITIZE-WITH-ATTR-NEXT: ret void
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_pointer(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA6:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20:![0-9]+]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = tail call i32 @llvm.smax.i32(i32 [[COUNTED_BY_LOAD]], i32 0)
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = zext nneg i32 [[NARROW]] to i64
-// NO-SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef [[TMP1]]) #[[ATTR6:[0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef [[TMP1]]) #[[ATTR7:[0-9]+]]
// NO-SANITIZE-WITH-ATTR-NEXT: ret void
//
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_pointer(
// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
-// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA6:![0-9]+]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20:![0-9]+]]
// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef -1) #[[ATTR3:[0-9]+]]
// SANITIZE-WITHOUT-ATTR-NEXT: ret void
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_pointer(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
-// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA6:![0-9]+]]
-// NO-SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef -1) #[[ATTR5:[0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20:![0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef -1) #[[ATTR6:[0-9]+]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
//
void test_pass_dynamic_object_size_of_pointer(struct annotated_volatile_ptr *p) {
@@ -411,7 +724,7 @@ void test_pass_dynamic_object_size_of_pointer(struct annotated_volatile_ptr *p)
// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_element_address(
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA8]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA22]]
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ule i32 [[INDEX]], [[DOTCOUNTED_BY_LOAD]], !nosanitize [[META6]]
@@ -420,7 +733,7 @@ void test_pass_dynamic_object_size_of_pointer(struct annotated_volatile_ptr *p)
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label %[[CONT6:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB9:[0-9]+]], i64 [[TMP4]]) #[[ATTR5]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB17:[0-9]+]], i64 [[TMP4]]) #[[ATTR5]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[CONT6]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
@@ -431,9 +744,9 @@ void test_pass_dynamic_object_size_of_pointer(struct annotated_volatile_ptr *p)
// SANITIZE-WITH-ATTR-NEXT: ret void
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_element_address(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR3]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR4]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA6]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDXPROM]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
@@ -444,25 +757,25 @@ void test_pass_dynamic_object_size_of_pointer(struct annotated_volatile_ptr *p)
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[INDEX]], -1
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = select i1 [[TMP3]], i64 [[RESULT]], i64 0
-// NO-SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef [[TMP4]]) #[[ATTR6]]
+// NO-SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef [[TMP4]]) #[[ATTR7]]
// NO-SANITIZE-WITH-ATTR-NEXT: ret void
//
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_element_address(
// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
-// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA6]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20]]
// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDXPROM]]
// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef -1) #[[ATTR3]]
// SANITIZE-WITHOUT-ATTR-NEXT: ret void
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_element_address(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR3]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR4]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
-// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA6]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDXPROM]]
-// NO-SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef -1) #[[ATTR5]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef -1) #[[ATTR6]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
//
void test_pass_dynamic_object_size_of_element_address(struct annotated_volatile_ptr *p, int index) {
@@ -471,29 +784,33 @@ void test_pass_dynamic_object_size_of_element_address(struct annotated_volatile_
// __bdos of '&((cast) ptr->buf)[idx]': the byte count is scaled by the cast
// element size (here 4), not the void* size.
-// SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 10737418240) i64 @test_bdos_of_element_address_through_widening_cast(
+// SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -8589934584, 10737418240) i64 @test_bdos_of_element_address_through_widening_cast(
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 4
-// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp ule i32 [[INDEX]], [[DOTCOUNTED_BY_LOAD]], !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[DOTCOUNTED_BY_LOAD]], 0, !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]], !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = sdiv i32 [[DOTCOUNTED_BY_LOAD]], 4
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ule i32 [[INDEX]], [[TMP0]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[DOTCOUNTED_BY_LOAD]], 3
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
-// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB11:[0-9]+]], i64 [[TMP3]]) #[[ATTR5]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB19:[0-9]+]], i64 [[TMP4]]) #[[ATTR5]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[CONT8]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = zext nneg i32 [[DOTCOUNTED_BY_LOAD]] to i64
-// SANITIZE-WITH-ATTR-NEXT: [[INDEX_SIZE:%.*]] = shl nuw nsw i64 [[IDXPROM]], 2
+// SANITIZE-WITH-ATTR-NEXT: [[INDEX_SIZE:%.*]] = shl nsw i64 [[IDXPROM]], 2
// SANITIZE-WITH-ATTR-NEXT: [[RESULT:%.*]] = sub nsw i64 [[COUNT]], [[INDEX_SIZE]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = tail call i64 @llvm.smax.i64(i64 [[RESULT]], i64 0)
-// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP4]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i64 [[RESULT]], -1
+// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = icmp sgt i32 [[INDEX]], -1
+// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = and i1 [[TMP6]], [[TMP5]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = select i1 [[TMP7]], i64 [[RESULT]], i64 0
+// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP8]]
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -10737418236, 10737418240) i64 @test_bdos_of_element_address_through_widening_cast(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
@@ -513,7 +830,7 @@ void test_pass_dynamic_object_size_of_element_address(struct annotated_volatile_
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_element_address_through_widening_cast(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -526,32 +843,84 @@ size_t test_bdos_of_element_address_through_widening_cast(struct annotated_sized
// SANITIZE-WITH-ATTR: [[META5]] = !{!"Simple C/C++ TBAA"}
// SANITIZE-WITH-ATTR: [[META6]] = !{}
// SANITIZE-WITH-ATTR: [[PROF7]] = !{!"branch_weights", i32 1048575, i32 1}
-// SANITIZE-WITH-ATTR: [[INTPTR_TBAA8]] = !{[[META9:![0-9]+]], [[META10:![0-9]+]], i64 0}
-// SANITIZE-WITH-ATTR: [[META9]] = !{!"annotated_volatile_ptr", [[META10]], i64 0, [[META3]], i64 8}
-// SANITIZE-WITH-ATTR: [[META10]] = !{!"p1 int", [[META11:![0-9]+]], i64 0}
-// SANITIZE-WITH-ATTR: [[META11]] = !{!"any pointer", [[META4]], i64 0}
+// SANITIZE-WITH-ATTR: [[_ZTS3FOOPTR_TBAA8]] = !{[[META9:![0-9]+]], [[META11:![0-9]+]], i64 8}
+// SANITIZE-WITH-ATTR: [[META9]] = !{!"annotated_ptr", [[META10:![0-9]+]], i64 0, [[META11]], i64 8, [[META3]], i64 16}
+// SANITIZE-WITH-ATTR: [[META10]] = !{!"long", [[META4]], i64 0}
+// SANITIZE-WITH-ATTR: [[META11]] = !{!"p2 _ZTS3foo", [[META12:![0-9]+]], i64 0}
+// SANITIZE-WITH-ATTR: [[META12]] = !{!"any p2 pointer", [[META13:![0-9]+]], i64 0}
+// SANITIZE-WITH-ATTR: [[META13]] = !{!"any pointer", [[META4]], i64 0}
+// SANITIZE-WITH-ATTR: [[_ZTS3FOOPTR_TBAA14]] = !{[[META15:![0-9]+]], [[META15]], i64 0}
+// SANITIZE-WITH-ATTR: [[META15]] = !{!"p1 _ZTS3foo", [[META13]], i64 0}
+// SANITIZE-WITH-ATTR: [[_ZTS18THREE_BYTE_POINTEEPTR_TBAA16]] = !{[[META17:![0-9]+]], [[META18:![0-9]+]], i64 8}
+// SANITIZE-WITH-ATTR: [[META17]] = !{!"annotated_sized_ptr_odd_pointee", [[META10]], i64 0, [[META18]], i64 8, [[META3]], i64 16}
+// SANITIZE-WITH-ATTR: [[META18]] = !{!"p1 _ZTS18three_byte_pointee", [[META13]], i64 0}
+// SANITIZE-WITH-ATTR: [[CHAR_TBAA19]] = !{[[META4]], [[META4]], i64 0}
+// SANITIZE-WITH-ATTR: [[_ZTS3FOOPTR_TBAA20]] = !{[[META21:![0-9]+]], [[META11]], i64 8}
+// SANITIZE-WITH-ATTR: [[META21]] = !{!"annotated_sized_ptr_pow2_unsigned_count", [[META10]], i64 0, [[META11]], i64 8, [[META3]], i64 16}
+// SANITIZE-WITH-ATTR: [[INTPTR_TBAA22]] = !{[[META23:![0-9]+]], [[META24:![0-9]+]], i64 0}
+// SANITIZE-WITH-ATTR: [[META23]] = !{!"annotated_volatile_ptr", [[META24]], i64 0, [[META3]], i64 8}
+// SANITIZE-WITH-ATTR: [[META24]] = !{!"p1 int", [[META13]], i64 0}
//.
// NO-SANITIZE-WITH-ATTR: [[META3:![0-9]+]] = !{!"int", [[META4:![0-9]+]], i64 0}
// NO-SANITIZE-WITH-ATTR: [[META4]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}
// NO-SANITIZE-WITH-ATTR: [[META5]] = !{!"Simple C/C++ TBAA"}
-// NO-SANITIZE-WITH-ATTR: [[INTPTR_TBAA6]] = !{[[META7:![0-9]+]], [[META8:![0-9]+]], i64 0}
-// NO-SANITIZE-WITH-ATTR: [[META7]] = !{!"annotated_volatile_ptr", [[META8]], i64 0, [[META3]], i64 8}
-// NO-SANITIZE-WITH-ATTR: [[META8]] = !{!"p1 int", [[META9:![0-9]+]], i64 0}
-// NO-SANITIZE-WITH-ATTR: [[META9]] = !{!"any pointer", [[META4]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[_ZTS3FOOPTR_TBAA6]] = !{[[META7:![0-9]+]], [[META9:![0-9]+]], i64 8}
+// NO-SANITIZE-WITH-ATTR: [[META7]] = !{!"annotated_ptr", [[META8:![0-9]+]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
+// NO-SANITIZE-WITH-ATTR: [[META8]] = !{!"long", [[META4]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[META9]] = !{!"p2 _ZTS3foo", [[META10:![0-9]+]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[META10]] = !{!"any p2 pointer", [[META11:![0-9]+]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[META11]] = !{!"any pointer", [[META4]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[_ZTS3FOOPTR_TBAA12]] = !{[[META13:![0-9]+]], [[META13]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[META13]] = !{!"p1 _ZTS3foo", [[META11]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[_ZTS18THREE_BYTE_POINTEEPTR_TBAA14]] = !{[[META15:![0-9]+]], [[META16:![0-9]+]], i64 8}
+// NO-SANITIZE-WITH-ATTR: [[META15]] = !{!"annotated_sized_ptr_odd_pointee", [[META8]], i64 0, [[META16]], i64 8, [[META3]], i64 16}
+// NO-SANITIZE-WITH-ATTR: [[META16]] = !{!"p1 _ZTS18three_byte_pointee", [[META11]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[CHAR_TBAA17]] = !{[[META4]], [[META4]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[_ZTS3FOOPTR_TBAA18]] = !{[[META19:![0-9]+]], [[META9]], i64 8}
+// NO-SANITIZE-WITH-ATTR: [[META19]] = !{!"annotated_sized_ptr_pow2_unsigned_count", [[META8]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
+// NO-SANITIZE-WITH-ATTR: [[INTPTR_TBAA20]] = !{[[META21:![0-9]+]], [[META22:![0-9]+]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[META21]] = !{!"annotated_volatile_ptr", [[META22]], i64 0, [[META3]], i64 8}
+// NO-SANITIZE-WITH-ATTR: [[META22]] = !{!"p1 int", [[META11]], i64 0}
//.
// SANITIZE-WITHOUT-ATTR: [[META3:![0-9]+]] = !{!"int", [[META4:![0-9]+]], i64 0}
// SANITIZE-WITHOUT-ATTR: [[META4]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}
// SANITIZE-WITHOUT-ATTR: [[META5]] = !{!"Simple C/C++ TBAA"}
-// SANITIZE-WITHOUT-ATTR: [[INTPTR_TBAA6]] = !{[[META7:![0-9]+]], [[META8:![0-9]+]], i64 0}
-// SANITIZE-WITHOUT-ATTR: [[META7]] = !{!"annotated_volatile_ptr", [[META8]], i64 0, [[META3]], i64 8}
-// SANITIZE-WITHOUT-ATTR: [[META8]] = !{!"p1 int", [[META9:![0-9]+]], i64 0}
-// SANITIZE-WITHOUT-ATTR: [[META9]] = !{!"any pointer", [[META4]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[_ZTS3FOOPTR_TBAA6]] = !{[[META7:![0-9]+]], [[META9:![0-9]+]], i64 8}
+// SANITIZE-WITHOUT-ATTR: [[META7]] = !{!"annotated_ptr", [[META8:![0-9]+]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
+// SANITIZE-WITHOUT-ATTR: [[META8]] = !{!"long", [[META4]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[META9]] = !{!"p2 _ZTS3foo", [[META10:![0-9]+]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[META10]] = !{!"any p2 pointer", [[META11:![0-9]+]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[META11]] = !{!"any pointer", [[META4]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[_ZTS3FOOPTR_TBAA12]] = !{[[META13:![0-9]+]], [[META13]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[META13]] = !{!"p1 _ZTS3foo", [[META11]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[_ZTS18THREE_BYTE_POINTEEPTR_TBAA14]] = !{[[META15:![0-9]+]], [[META16:![0-9]+]], i64 8}
+// SANITIZE-WITHOUT-ATTR: [[META15]] = !{!"annotated_sized_ptr_odd_pointee", [[META8]], i64 0, [[META16]], i64 8, [[META3]], i64 16}
+// SANITIZE-WITHOUT-ATTR: [[META16]] = !{!"p1 _ZTS18three_byte_pointee", [[META11]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[CHAR_TBAA17]] = !{[[META4]], [[META4]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[_ZTS3FOOPTR_TBAA18]] = !{[[META19:![0-9]+]], [[META9]], i64 8}
+// SANITIZE-WITHOUT-ATTR: [[META19]] = !{!"annotated_sized_ptr_pow2_unsigned_count", [[META8]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
+// SANITIZE-WITHOUT-ATTR: [[INTPTR_TBAA20]] = !{[[META21:![0-9]+]], [[META22:![0-9]+]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[META21]] = !{!"annotated_volatile_ptr", [[META22]], i64 0, [[META3]], i64 8}
+// SANITIZE-WITHOUT-ATTR: [[META22]] = !{!"p1 int", [[META11]], i64 0}
//.
// NO-SANITIZE-WITHOUT-ATTR: [[META3:![0-9]+]] = !{!"int", [[META4:![0-9]+]], i64 0}
// NO-SANITIZE-WITHOUT-ATTR: [[META4]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}
// NO-SANITIZE-WITHOUT-ATTR: [[META5]] = !{!"Simple C/C++ TBAA"}
-// NO-SANITIZE-WITHOUT-ATTR: [[INTPTR_TBAA6]] = !{[[META7:![0-9]+]], [[META8:![0-9]+]], i64 0}
-// NO-SANITIZE-WITHOUT-ATTR: [[META7]] = !{!"annotated_volatile_ptr", [[META8]], i64 0, [[META3]], i64 8}
-// NO-SANITIZE-WITHOUT-ATTR: [[META8]] = !{!"p1 int", [[META9:![0-9]+]], i64 0}
-// NO-SANITIZE-WITHOUT-ATTR: [[META9]] = !{!"any pointer", [[META4]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[_ZTS3FOOPTR_TBAA6]] = !{[[META7:![0-9]+]], [[META9:![0-9]+]], i64 8}
+// NO-SANITIZE-WITHOUT-ATTR: [[META7]] = !{!"annotated_ptr", [[META8:![0-9]+]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
+// NO-SANITIZE-WITHOUT-ATTR: [[META8]] = !{!"long", [[META4]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[META9]] = !{!"p2 _ZTS3foo", [[META10:![0-9]+]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[META10]] = !{!"any p2 pointer", [[META11:![0-9]+]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[META11]] = !{!"any pointer", [[META4]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[_ZTS3FOOPTR_TBAA12]] = !{[[META13:![0-9]+]], [[META13]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[META13]] = !{!"p1 _ZTS3foo", [[META11]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[_ZTS18THREE_BYTE_POINTEEPTR_TBAA14]] = !{[[META15:![0-9]+]], [[META16:![0-9]+]], i64 8}
+// NO-SANITIZE-WITHOUT-ATTR: [[META15]] = !{!"annotated_sized_ptr_odd_pointee", [[META8]], i64 0, [[META16]], i64 8, [[META3]], i64 16}
+// NO-SANITIZE-WITHOUT-ATTR: [[META16]] = !{!"p1 _ZTS18three_byte_pointee", [[META11]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[CHAR_TBAA17]] = !{[[META4]], [[META4]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[_ZTS3FOOPTR_TBAA18]] = !{[[META19:![0-9]+]], [[META9]], i64 8}
+// NO-SANITIZE-WITHOUT-ATTR: [[META19]] = !{!"annotated_sized_ptr_pow2_unsigned_count", [[META8]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
+// NO-SANITIZE-WITHOUT-ATTR: [[INTPTR_TBAA20]] = !{[[META21:![0-9]+]], [[META22:![0-9]+]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[META21]] = !{!"annotated_volatile_ptr", [[META22]], i64 0, [[META3]], i64 8}
+// NO-SANITIZE-WITHOUT-ATTR: [[META22]] = !{!"p1 int", [[META11]], i64 0}
//.
diff --git a/clang/test/CodeGen/attr-sized-by-or-null-for-pointers.c b/clang/test/CodeGen/attr-sized-by-or-null-for-pointers.c
index 61ca39b37d5f2..132d0bbbf61c4 100644
--- a/clang/test/CodeGen/attr-sized-by-or-null-for-pointers.c
+++ b/clang/test/CodeGen/attr-sized-by-or-null-for-pointers.c
@@ -25,6 +25,324 @@
typedef long unsigned int size_t;
struct foo { size_t field; };
+struct annotated_ptr {
+ unsigned long flags;
+ struct foo **buf __sized_by_or_null(ptr_count);
+ int ptr_count;
+};
+
+// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_store_subscript(
+// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = sdiv i32 [[DOTCOUNTED_BY_LOAD]], 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 0, i32 [[TMP2]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ult i32 [[INDEX]], [[TMP3]], !nosanitize [[META12:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[TMP3]], 0, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT15:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13:![0-9]+]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
+// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 [[TMP7]]) #[[ATTR5:[0-9]+]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR: [[CONT15]]:
+// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA14:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: ret void
+//
+// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_store_subscript(
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: ret void
+//
+// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_store_subscript(
+// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6:![0-9]+]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITHOUT-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12:![0-9]+]]
+// SANITIZE-WITHOUT-ATTR-NEXT: ret void
+//
+// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_store_subscript(
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6:![0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12:![0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
+//
+void test_store_subscript(struct annotated_ptr *p, int index, struct foo *value) {
+ p->buf[index] = value;
+}
+
+// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_store_subscript_through_cast(
+// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = sdiv i32 [[DOTCOUNTED_BY_LOAD]], 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 0, i32 [[TMP2]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ult i32 [[INDEX]], [[TMP3]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[TMP3]], 0, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT15:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
+// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 [[TMP7]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR: [[CONT15]]:
+// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA14]]
+// SANITIZE-WITH-ATTR-NEXT: ret void
+//
+// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_store_subscript_through_cast(
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// NO-SANITIZE-WITH-ATTR-NEXT: ret void
+//
+// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_store_subscript_through_cast(
+// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITHOUT-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// SANITIZE-WITHOUT-ATTR-NEXT: ret void
+//
+// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_store_subscript_through_cast(
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
+//
+void test_store_subscript_through_cast(struct annotated_ptr *p, int index, struct foo *value) {
+ ((struct foo **)((char *)p->buf))[index] = value;
+}
+
+// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_store_subscript_through_deref_of_addressof(
+// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = sdiv i32 [[DOTCOUNTED_BY_LOAD]], 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 0, i32 [[TMP2]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ule i32 [[INDEX]], [[TMP3]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[TMP3]], 0, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT15:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
+// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 [[TMP7]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR: [[CONT15]]:
+// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA14]]
+// SANITIZE-WITH-ATTR-NEXT: ret void
+//
+// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_store_subscript_through_deref_of_addressof(
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// NO-SANITIZE-WITH-ATTR-NEXT: ret void
+//
+// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_store_subscript_through_deref_of_addressof(
+// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITHOUT-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// SANITIZE-WITHOUT-ATTR-NEXT: ret void
+//
+// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_store_subscript_through_deref_of_addressof(
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]], ptr noundef [[VALUE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA6]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
+//
+void test_store_subscript_through_deref_of_addressof(struct annotated_ptr *p, int index, struct foo *value) {
+ *&*&*&p->buf[index] = value;
+}
+
+struct three_byte_pointee {
+ char data[3];
+};
+
+// With an unsigned count field the byte->element conversion 'bound /
+// sizeof(element)' is an unsigned division. A non-power-of-two element size
+// cannot be folded to a shift, so it stays a real 'udiv' (contrast
+// test_load_subscript_pow2_unsigned_count, where a power-of-two element lets
+// 'udiv' become a shift). This also exercises the floor-truncation: a bound that
+// is not a whole multiple of the element size rounds down to the number of
+// complete elements.
+struct annotated_sized_ptr_odd_pointee {
+ unsigned long flags;
+ struct three_byte_pointee *buf __sized_by_or_null(byte_count);
+ unsigned byte_count;
+};
+
+// SANITIZE-WITH-ATTR-LABEL: define dso_local signext i8 @test_load_subscript_odd_pointee(
+// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS18THREE_BYTE_POINTEEPTR_TBAA16:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ne ptr [[TMP0]], null
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = udiv i32 [[DOTCOUNTED_BY_LOAD]], 3
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ugt i32 [[TMP2]], [[INDEX]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], i1 [[TMP3]], i1 false
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP4]], label %[[CONT20:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB7:[0-9]+]], i64 [[TMP5]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR: [[CONT20]]:
+// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa [[CHAR_TBAA19:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: ret i8 [[TMP6]]
+//
+// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local signext i8 @test_load_subscript_odd_pointee(
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS18THREE_BYTE_POINTEEPTR_TBAA14:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa [[CHAR_TBAA17:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: ret i8 [[TMP1]]
+//
+// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local signext i8 @test_load_subscript_odd_pointee(
+// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS18THREE_BYTE_POINTEEPTR_TBAA14:![0-9]+]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa [[CHAR_TBAA17:![0-9]+]]
+// SANITIZE-WITHOUT-ATTR-NEXT: ret i8 [[TMP1]]
+//
+// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local signext i8 @test_load_subscript_odd_pointee(
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS18THREE_BYTE_POINTEEPTR_TBAA14:![0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa [[CHAR_TBAA17:![0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i8 [[TMP1]]
+//
+char test_load_subscript_odd_pointee(struct annotated_sized_ptr_odd_pointee *p, int index) {
+ return p->buf[index].data[0];
+}
+
+// An unsigned count field makes the byte->element conversion an unsigned
+// division; for a power-of-two element size 'udiv' folds to a shift ('lshr').
+// Being unsigned there is also no negative-bounds guard (contrast the signed
+// count tests above). The null pointer is still forced to a zero bound.
+struct annotated_sized_ptr_pow2_unsigned_count {
+ unsigned long flags;
+ struct foo **buf __sized_by_or_null(byte_count);
+ unsigned byte_count;
+};
+
+// SANITIZE-WITH-ATTR-LABEL: define dso_local ptr @test_load_subscript_pow2_unsigned_count(
+// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA20:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ne ptr [[TMP0]], null
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = lshr i32 [[DOTCOUNTED_BY_LOAD]], 3
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ugt i32 [[TMP2]], [[INDEX]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], i1 [[TMP3]], i1 false
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP4]], label %[[CONT15:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB9:[0-9]+]], i64 [[TMP5]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR: [[CONT15]]:
+// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA14]]
+// SANITIZE-WITH-ATTR-NEXT: ret ptr [[TMP6]]
+//
+// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local ptr @test_load_subscript_pow2_unsigned_count(
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA18:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// NO-SANITIZE-WITH-ATTR-NEXT: ret ptr [[TMP1]]
+//
+// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local ptr @test_load_subscript_pow2_unsigned_count(
+// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA18:![0-9]+]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// SANITIZE-WITHOUT-ATTR-NEXT: ret ptr [[TMP1]]
+//
+// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local ptr @test_load_subscript_pow2_unsigned_count(
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA18:![0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret ptr [[TMP1]]
+//
+struct foo *test_load_subscript_pow2_unsigned_count(struct annotated_sized_ptr_pow2_unsigned_count *p, int index) {
+ return p->buf[index];
+}
struct annotated_sized_ptr {
unsigned long flags;
@@ -33,10 +351,10 @@ struct annotated_sized_ptr {
};
// SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 2147483648) i64 @test_bdos_of_pointer(
-// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[ANYPTR_TBAA6:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[ANYPTR_TBAA22:![0-9]+]]
// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
@@ -46,10 +364,10 @@ struct annotated_sized_ptr {
// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP4]]
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 2147483648) i64 @test_bdos_of_pointer(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[ANYPTR_TBAA6:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[ANYPTR_TBAA20:![0-9]+]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
@@ -59,12 +377,12 @@ struct annotated_sized_ptr {
// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP4]]
//
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_pointer(
-// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_pointer(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -75,32 +393,33 @@ size_t test_bdos_of_pointer(struct annotated_sized_ptr *p) {
// SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 4294967296) i64 @test_bdos_of_element_address(
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[ANYPTR_TBAA22]]
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
-// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 4
-// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp ule i32 [[INDEX]], [[DOTCOUNTED_BY_LOAD]], !nosanitize [[META10:![0-9]+]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[DOTCOUNTED_BY_LOAD]], 0, !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]], !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF11:![0-9]+]], !nosanitize [[META10]]
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 0, i32 [[DOTCOUNTED_BY_LOAD]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ule i32 [[INDEX]], [[TMP2]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP2]], 0, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT13:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
-// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 [[TMP3]]) #[[ATTR5:[0-9]+]], !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR: [[CONT8]]:
-// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[ANYPTR_TBAA6]]
-// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = zext nneg i32 [[DOTCOUNTED_BY_LOAD]] to i64
+// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB11:[0-9]+]], i64 [[TMP6]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR: [[CONT13]]:
+// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[DOTCOUNTED_BY_LOAD]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
-// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp eq ptr [[TMP4]], null
-// SANITIZE-WITH-ATTR-NEXT: [[COUNT_OR_NULL:%.*]] = select i1 [[TMP5]], i64 0, i64 [[COUNT]]
+// SANITIZE-WITH-ATTR-NEXT: [[COUNT_OR_NULL:%.*]] = select i1 [[TMP1]], i64 0, i64 [[COUNT]]
// SANITIZE-WITH-ATTR-NEXT: [[RESULT:%.*]] = sub nsw i64 [[COUNT_OR_NULL]], [[IDXPROM]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = tail call i64 @llvm.smax.i64(i64 [[RESULT]], i64 0)
-// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP6]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = tail call i64 @llvm.smax.i64(i64 [[RESULT]], i64 0)
+// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP7]]
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -4294967295, 4294967296) i64 @test_bdos_of_element_address(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[ANYPTR_TBAA6]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[ANYPTR_TBAA20]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
@@ -120,7 +439,7 @@ size_t test_bdos_of_pointer(struct annotated_sized_ptr *p) {
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_element_address(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -131,21 +450,26 @@ size_t test_bdos_of_element_address(struct annotated_sized_ptr *p, int index) {
// SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test_bdos_of_subscript_through_cast(
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[ANYPTR_TBAA22]]
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
-// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp ult i32 [[INDEX]], [[DOTCOUNTED_BY_LOAD]], !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[DOTCOUNTED_BY_LOAD]], 0, !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]], !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF11]], !nosanitize [[META10]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = sdiv i32 [[DOTCOUNTED_BY_LOAD]], 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 0, i32 [[TMP2]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ult i32 [[INDEX]], [[TMP3]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[TMP3]], 0, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT15:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
-// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 [[TMP3]]) #[[ATTR5]], !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR: [[CONT10]]:
+// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB12:[0-9]+]], i64 [[TMP7]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR: [[CONT15]]:
// SANITIZE-WITH-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test_bdos_of_subscript_through_cast(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 -1
//
@@ -155,7 +479,7 @@ size_t test_bdos_of_element_address(struct annotated_sized_ptr *p, int index) {
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_subscript_through_cast(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -178,7 +502,7 @@ struct annotated_sized_ptr_non_byte_sized_pointee {
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA24:![0-9]+]]
// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
@@ -188,10 +512,10 @@ struct annotated_sized_ptr_non_byte_sized_pointee {
// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP4]]
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 2147483648) i64 @test_bdos_of_pointer_multibyte_pointee(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA10:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA22:![0-9]+]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
@@ -206,7 +530,7 @@ struct annotated_sized_ptr_non_byte_sized_pointee {
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_pointer_multibyte_pointee(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -217,33 +541,35 @@ size_t test_bdos_of_pointer_multibyte_pointee(struct annotated_sized_ptr_non_byt
// SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 19327352832) i64 @test_bdos_of_element_address_multibyte_pointee(
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA24]]
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
-// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 4
-// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp ule i32 [[INDEX]], [[DOTCOUNTED_BY_LOAD]], !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[DOTCOUNTED_BY_LOAD]], 0, !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]], !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF11]], !nosanitize [[META10]]
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = sdiv i32 [[DOTCOUNTED_BY_LOAD]], 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 0, i32 [[TMP2]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ule i32 [[INDEX]], [[TMP3]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[TMP3]], 0, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT13:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
-// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB6:[0-9]+]], i64 [[TMP3]]) #[[ATTR5]], !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR: [[CONT8]]:
-// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA12]]
-// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = zext nneg i32 [[DOTCOUNTED_BY_LOAD]] to i64
+// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB14:[0-9]+]], i64 [[TMP7]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR: [[CONT13]]:
+// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[DOTCOUNTED_BY_LOAD]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
-// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp eq ptr [[TMP4]], null
-// SANITIZE-WITH-ATTR-NEXT: [[COUNT_OR_NULL:%.*]] = select i1 [[TMP5]], i64 0, i64 [[COUNT]]
+// SANITIZE-WITH-ATTR-NEXT: [[COUNT_OR_NULL:%.*]] = select i1 [[TMP1]], i64 0, i64 [[COUNT]]
// SANITIZE-WITH-ATTR-NEXT: [[INDEX_SIZE:%.*]] = shl nuw nsw i64 [[IDXPROM]], 3
// SANITIZE-WITH-ATTR-NEXT: [[RESULT:%.*]] = sub nsw i64 [[COUNT_OR_NULL]], [[INDEX_SIZE]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = tail call i64 @llvm.smax.i64(i64 [[RESULT]], i64 0)
-// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP6]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = tail call i64 @llvm.smax.i64(i64 [[RESULT]], i64 0)
+// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP8]]
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -19327352824, 19327352832) i64 @test_bdos_of_element_address_multibyte_pointee(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA10]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA22]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
@@ -264,7 +590,7 @@ size_t test_bdos_of_pointer_multibyte_pointee(struct annotated_sized_ptr_non_byt
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_element_address_multibyte_pointee(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -288,7 +614,7 @@ struct annotated_sized_ptr_incomplete {
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS13INCOMPLETE_TYPTR_TBAA15:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS13INCOMPLETE_TYPTR_TBAA26:![0-9]+]]
// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
@@ -298,10 +624,10 @@ struct annotated_sized_ptr_incomplete {
// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP4]]
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 2147483648) i64 @test_bdos_of_pointer_incomplete_pointee(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS13INCOMPLETE_TYPTR_TBAA13:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS13INCOMPLETE_TYPTR_TBAA24:![0-9]+]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
@@ -316,7 +642,7 @@ struct annotated_sized_ptr_incomplete {
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_pointer_incomplete_pointee(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -327,32 +653,33 @@ size_t test_bdos_of_pointer_incomplete_pointee(struct annotated_sized_ptr_incomp
// SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 4294967296) i64 @test_bdos_of_element_address_incomplete_pointee(
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS13INCOMPLETE_TYPTR_TBAA26]]
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
-// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 4
-// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp ule i32 [[INDEX]], [[DOTCOUNTED_BY_LOAD]], !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[DOTCOUNTED_BY_LOAD]], 0, !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]], !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF11]], !nosanitize [[META10]]
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 0, i32 [[DOTCOUNTED_BY_LOAD]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ule i32 [[INDEX]], [[TMP2]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP2]], 0, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT13:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
-// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB8:[0-9]+]], i64 [[TMP3]]) #[[ATTR5]], !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR: [[CONT8]]:
-// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS13INCOMPLETE_TYPTR_TBAA15]]
-// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = zext nneg i32 [[DOTCOUNTED_BY_LOAD]] to i64
+// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB16:[0-9]+]], i64 [[TMP6]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR: [[CONT13]]:
+// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[DOTCOUNTED_BY_LOAD]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
-// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp eq ptr [[TMP4]], null
-// SANITIZE-WITH-ATTR-NEXT: [[COUNT_OR_NULL:%.*]] = select i1 [[TMP5]], i64 0, i64 [[COUNT]]
+// SANITIZE-WITH-ATTR-NEXT: [[COUNT_OR_NULL:%.*]] = select i1 [[TMP1]], i64 0, i64 [[COUNT]]
// SANITIZE-WITH-ATTR-NEXT: [[RESULT:%.*]] = sub nsw i64 [[COUNT_OR_NULL]], [[IDXPROM]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = tail call i64 @llvm.smax.i64(i64 [[RESULT]], i64 0)
-// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP6]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = tail call i64 @llvm.smax.i64(i64 [[RESULT]], i64 0)
+// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP7]]
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -4294967295, 4294967296) i64 @test_bdos_of_element_address_incomplete_pointee(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS13INCOMPLETE_TYPTR_TBAA13]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS13INCOMPLETE_TYPTR_TBAA24]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
@@ -372,7 +699,7 @@ size_t test_bdos_of_pointer_incomplete_pointee(struct annotated_sized_ptr_incomp
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_element_address_incomplete_pointee(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -400,7 +727,7 @@ void take_ptr_with_size(void *p __attribute__((pass_dynamic_object_size(0))));
// SANITIZE-WITH-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i64 @test_bdos_of_volatile_pointer(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readnone captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readnone captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 -1
//
@@ -410,7 +737,7 @@ void take_ptr_with_size(void *p __attribute__((pass_dynamic_object_size(0))));
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i64 @test_bdos_of_volatile_pointer(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readnone captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readnone captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -426,7 +753,7 @@ size_t test_bdos_of_volatile_pointer(struct annotated_volatile_ptr *p) {
// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_pointer(
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA18:![0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA29:![0-9]+]]
// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
@@ -437,30 +764,30 @@ size_t test_bdos_of_volatile_pointer(struct annotated_volatile_ptr *p) {
// SANITIZE-WITH-ATTR-NEXT: ret void
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_pointer(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA16:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA27:![0-9]+]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = tail call i32 @llvm.smax.i32(i32 [[COUNTED_BY_LOAD]], i32 0)
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext nneg i32 [[TMP2]] to i64
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP3]]
-// NO-SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef [[TMP4]]) #[[ATTR6:[0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef [[TMP4]]) #[[ATTR7:[0-9]+]]
// NO-SANITIZE-WITH-ATTR-NEXT: ret void
//
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_pointer(
// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
-// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA6:![0-9]+]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20:![0-9]+]]
// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef -1) #[[ATTR3:[0-9]+]]
// SANITIZE-WITHOUT-ATTR-NEXT: ret void
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_pointer(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
-// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA6:![0-9]+]]
-// NO-SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef -1) #[[ATTR5:[0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20:![0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef -1) #[[ATTR6:[0-9]+]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
//
void test_pass_dynamic_object_size_of_pointer(struct annotated_volatile_ptr *p) {
@@ -476,39 +803,42 @@ void test_pass_dynamic_object_size_of_pointer(struct annotated_volatile_ptr *p)
// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_element_address(
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA18]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA29]]
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
-// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ule i32 [[INDEX]], [[DOTCOUNTED_BY_LOAD]], !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[DOTCOUNTED_BY_LOAD]], 0, !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]], !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label %[[CONT9:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF11]], !nosanitize [[META10]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA29]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP1]], null
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 0, i32 [[DOTCOUNTED_BY_LOAD]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ule i32 [[INDEX]], [[TMP3]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[TMP3]], 0, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT12:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
-// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB9:[0-9]+]], i64 [[TMP4]]) #[[ATTR5]], !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR: [[CONT9]]:
-// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = zext nneg i32 [[DOTCOUNTED_BY_LOAD]] to i64
+// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB17:[0-9]+]], i64 [[TMP7]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR: [[CONT12]]:
+// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[DOTCOUNTED_BY_LOAD]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDXPROM]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA18]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = icmp eq ptr [[TMP5]], null
-// SANITIZE-WITH-ATTR-NEXT: [[COUNT_OR_NULL:%.*]] = select i1 [[TMP6]], i64 0, i64 [[COUNT]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA29]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP9:%.*]] = icmp eq ptr [[TMP8]], null
+// SANITIZE-WITH-ATTR-NEXT: [[COUNT_OR_NULL:%.*]] = select i1 [[TMP9]], i64 0, i64 [[COUNT]]
// SANITIZE-WITH-ATTR-NEXT: [[RESULT:%.*]] = sub nsw i64 [[COUNT_OR_NULL]], [[IDXPROM]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = tail call i64 @llvm.smax.i64(i64 [[RESULT]], i64 0)
-// SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef [[TMP7]]) #[[ATTR6]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP10:%.*]] = tail call i64 @llvm.smax.i64(i64 [[RESULT]], i64 0)
+// SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef [[TMP10]]) #[[ATTR6]]
// SANITIZE-WITH-ATTR-NEXT: ret void
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_element_address(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR3]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR4]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA16]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA27]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDXPROM]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[COUNTED_BY_LOAD]] to i64
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA16]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA27]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP1]], null
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNT_OR_NULL:%.*]] = select i1 [[TMP2]], i64 0, i64 [[COUNT]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[RESULT:%.*]] = sub nsw i64 [[COUNT_OR_NULL]], [[IDXPROM]]
@@ -516,25 +846,25 @@ void test_pass_dynamic_object_size_of_pointer(struct annotated_volatile_ptr *p)
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[INDEX]], -1
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], i64 [[RESULT]], i64 0
-// NO-SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef [[TMP6]]) #[[ATTR6]]
+// NO-SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef [[TMP6]]) #[[ATTR7]]
// NO-SANITIZE-WITH-ATTR-NEXT: ret void
//
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_element_address(
// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
-// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA6]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20]]
// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDXPROM]]
// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef -1) #[[ATTR3]]
// SANITIZE-WITHOUT-ATTR-NEXT: ret void
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_element_address(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR3]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR4]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
-// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA6]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDXPROM]]
-// NO-SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef -1) #[[ATTR5]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef -1) #[[ATTR6]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
//
void test_pass_dynamic_object_size_of_element_address(struct annotated_volatile_ptr *p, int index) {
@@ -546,33 +876,35 @@ void test_pass_dynamic_object_size_of_element_address(struct annotated_volatile_
// SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 10737418240) i64 @test_bdos_of_element_address_through_widening_cast(
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[ANYPTR_TBAA22]]
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
-// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 4
-// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp ule i32 [[INDEX]], [[DOTCOUNTED_BY_LOAD]], !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[DOTCOUNTED_BY_LOAD]], 0, !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]], !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF11]], !nosanitize [[META10]]
+// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = sdiv i32 [[DOTCOUNTED_BY_LOAD]], 4
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 0, i32 [[TMP2]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ule i32 [[INDEX]], [[TMP3]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[TMP3]], 0, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT13:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
-// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB11:[0-9]+]], i64 [[TMP3]]) #[[ATTR5]], !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META10]]
-// SANITIZE-WITH-ATTR: [[CONT8]]:
-// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[ANYPTR_TBAA6]]
-// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = zext nneg i32 [[DOTCOUNTED_BY_LOAD]] to i64
+// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB19:[0-9]+]], i64 [[TMP7]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR: [[CONT13]]:
+// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[DOTCOUNTED_BY_LOAD]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
-// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp eq ptr [[TMP4]], null
-// SANITIZE-WITH-ATTR-NEXT: [[COUNT_OR_NULL:%.*]] = select i1 [[TMP5]], i64 0, i64 [[COUNT]]
+// SANITIZE-WITH-ATTR-NEXT: [[COUNT_OR_NULL:%.*]] = select i1 [[TMP1]], i64 0, i64 [[COUNT]]
// SANITIZE-WITH-ATTR-NEXT: [[INDEX_SIZE:%.*]] = shl nuw nsw i64 [[IDXPROM]], 2
// SANITIZE-WITH-ATTR-NEXT: [[RESULT:%.*]] = sub nsw i64 [[COUNT_OR_NULL]], [[INDEX_SIZE]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = tail call i64 @llvm.smax.i64(i64 [[RESULT]], i64 0)
-// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP6]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = tail call i64 @llvm.smax.i64(i64 [[RESULT]], i64 0)
+// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP8]]
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -10737418236, 10737418240) i64 @test_bdos_of_element_address_through_widening_cast(
-// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[ANYPTR_TBAA6]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[ANYPTR_TBAA20]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
@@ -593,7 +925,7 @@ void test_pass_dynamic_object_size_of_element_address(struct annotated_volatile_
// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_element_address_through_widening_cast(
-// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1
//
@@ -604,52 +936,100 @@ size_t test_bdos_of_element_address_through_widening_cast(struct annotated_sized
// SANITIZE-WITH-ATTR: [[META3:![0-9]+]] = !{!"int", [[META4:![0-9]+]], i64 0}
// SANITIZE-WITH-ATTR: [[META4]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}
// SANITIZE-WITH-ATTR: [[META5]] = !{!"Simple C/C++ TBAA"}
-// SANITIZE-WITH-ATTR: [[ANYPTR_TBAA6]] = !{[[META7:![0-9]+]], [[META9:![0-9]+]], i64 8}
-// SANITIZE-WITH-ATTR: [[META7]] = !{!"annotated_sized_ptr", [[META8:![0-9]+]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
+// SANITIZE-WITH-ATTR: [[_ZTS3FOOPTR_TBAA6]] = !{[[META7:![0-9]+]], [[META9:![0-9]+]], i64 8}
+// SANITIZE-WITH-ATTR: [[META7]] = !{!"annotated_ptr", [[META8:![0-9]+]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
// SANITIZE-WITH-ATTR: [[META8]] = !{!"long", [[META4]], i64 0}
-// SANITIZE-WITH-ATTR: [[META9]] = !{!"any pointer", [[META4]], i64 0}
-// SANITIZE-WITH-ATTR: [[META10]] = !{}
-// SANITIZE-WITH-ATTR: [[PROF11]] = !{!"branch_weights", i32 1048575, i32 1}
-// SANITIZE-WITH-ATTR: [[_ZTS3FOOPTR_TBAA12]] = !{[[META13:![0-9]+]], [[META14:![0-9]+]], i64 8}
-// SANITIZE-WITH-ATTR: [[META13]] = !{!"annotated_sized_ptr_non_byte_sized_pointee", [[META8]], i64 0, [[META14]], i64 8, [[META3]], i64 16}
-// SANITIZE-WITH-ATTR: [[META14]] = !{!"p1 _ZTS3foo", [[META9]], i64 0}
-// SANITIZE-WITH-ATTR: [[_ZTS13INCOMPLETE_TYPTR_TBAA15]] = !{[[META16:![0-9]+]], [[META17:![0-9]+]], i64 8}
-// SANITIZE-WITH-ATTR: [[META16]] = !{!"annotated_sized_ptr_incomplete", [[META8]], i64 0, [[META17]], i64 8, [[META3]], i64 16}
-// SANITIZE-WITH-ATTR: [[META17]] = !{!"p1 _ZTS13incomplete_ty", [[META9]], i64 0}
-// SANITIZE-WITH-ATTR: [[INTPTR_TBAA18]] = !{[[META19:![0-9]+]], [[META20:![0-9]+]], i64 0}
-// SANITIZE-WITH-ATTR: [[META19]] = !{!"annotated_volatile_ptr", [[META20]], i64 0, [[META3]], i64 8}
-// SANITIZE-WITH-ATTR: [[META20]] = !{!"p1 int", [[META9]], i64 0}
+// SANITIZE-WITH-ATTR: [[META9]] = !{!"p2 _ZTS3foo", [[META10:![0-9]+]], i64 0}
+// SANITIZE-WITH-ATTR: [[META10]] = !{!"any p2 pointer", [[META11:![0-9]+]], i64 0}
+// SANITIZE-WITH-ATTR: [[META11]] = !{!"any pointer", [[META4]], i64 0}
+// SANITIZE-WITH-ATTR: [[META12]] = !{}
+// SANITIZE-WITH-ATTR: [[PROF13]] = !{!"branch_weights", i32 1048575, i32 1}
+// SANITIZE-WITH-ATTR: [[_ZTS3FOOPTR_TBAA14]] = !{[[META15:![0-9]+]], [[META15]], i64 0}
+// SANITIZE-WITH-ATTR: [[META15]] = !{!"p1 _ZTS3foo", [[META11]], i64 0}
+// SANITIZE-WITH-ATTR: [[_ZTS18THREE_BYTE_POINTEEPTR_TBAA16]] = !{[[META17:![0-9]+]], [[META18:![0-9]+]], i64 8}
+// SANITIZE-WITH-ATTR: [[META17]] = !{!"annotated_sized_ptr_odd_pointee", [[META8]], i64 0, [[META18]], i64 8, [[META3]], i64 16}
+// SANITIZE-WITH-ATTR: [[META18]] = !{!"p1 _ZTS18three_byte_pointee", [[META11]], i64 0}
+// SANITIZE-WITH-ATTR: [[CHAR_TBAA19]] = !{[[META4]], [[META4]], i64 0}
+// SANITIZE-WITH-ATTR: [[_ZTS3FOOPTR_TBAA20]] = !{[[META21:![0-9]+]], [[META9]], i64 8}
+// SANITIZE-WITH-ATTR: [[META21]] = !{!"annotated_sized_ptr_pow2_unsigned_count", [[META8]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
+// SANITIZE-WITH-ATTR: [[ANYPTR_TBAA22]] = !{[[META23:![0-9]+]], [[META11]], i64 8}
+// SANITIZE-WITH-ATTR: [[META23]] = !{!"annotated_sized_ptr", [[META8]], i64 0, [[META11]], i64 8, [[META3]], i64 16}
+// SANITIZE-WITH-ATTR: [[_ZTS3FOOPTR_TBAA24]] = !{[[META25:![0-9]+]], [[META15]], i64 8}
+// SANITIZE-WITH-ATTR: [[META25]] = !{!"annotated_sized_ptr_non_byte_sized_pointee", [[META8]], i64 0, [[META15]], i64 8, [[META3]], i64 16}
+// SANITIZE-WITH-ATTR: [[_ZTS13INCOMPLETE_TYPTR_TBAA26]] = !{[[META27:![0-9]+]], [[META28:![0-9]+]], i64 8}
+// SANITIZE-WITH-ATTR: [[META27]] = !{!"annotated_sized_ptr_incomplete", [[META8]], i64 0, [[META28]], i64 8, [[META3]], i64 16}
+// SANITIZE-WITH-ATTR: [[META28]] = !{!"p1 _ZTS13incomplete_ty", [[META11]], i64 0}
+// SANITIZE-WITH-ATTR: [[INTPTR_TBAA29]] = !{[[META30:![0-9]+]], [[META31:![0-9]+]], i64 0}
+// SANITIZE-WITH-ATTR: [[META30]] = !{!"annotated_volatile_ptr", [[META31]], i64 0, [[META3]], i64 8}
+// SANITIZE-WITH-ATTR: [[META31]] = !{!"p1 int", [[META11]], i64 0}
//.
// NO-SANITIZE-WITH-ATTR: [[META3:![0-9]+]] = !{!"int", [[META4:![0-9]+]], i64 0}
// NO-SANITIZE-WITH-ATTR: [[META4]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}
// NO-SANITIZE-WITH-ATTR: [[META5]] = !{!"Simple C/C++ TBAA"}
-// NO-SANITIZE-WITH-ATTR: [[ANYPTR_TBAA6]] = !{[[META7:![0-9]+]], [[META9:![0-9]+]], i64 8}
-// NO-SANITIZE-WITH-ATTR: [[META7]] = !{!"annotated_sized_ptr", [[META8:![0-9]+]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
+// NO-SANITIZE-WITH-ATTR: [[_ZTS3FOOPTR_TBAA6]] = !{[[META7:![0-9]+]], [[META9:![0-9]+]], i64 8}
+// NO-SANITIZE-WITH-ATTR: [[META7]] = !{!"annotated_ptr", [[META8:![0-9]+]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
// NO-SANITIZE-WITH-ATTR: [[META8]] = !{!"long", [[META4]], i64 0}
-// NO-SANITIZE-WITH-ATTR: [[META9]] = !{!"any pointer", [[META4]], i64 0}
-// NO-SANITIZE-WITH-ATTR: [[_ZTS3FOOPTR_TBAA10]] = !{[[META11:![0-9]+]], [[META12:![0-9]+]], i64 8}
-// NO-SANITIZE-WITH-ATTR: [[META11]] = !{!"annotated_sized_ptr_non_byte_sized_pointee", [[META8]], i64 0, [[META12]], i64 8, [[META3]], i64 16}
-// NO-SANITIZE-WITH-ATTR: [[META12]] = !{!"p1 _ZTS3foo", [[META9]], i64 0}
-// NO-SANITIZE-WITH-ATTR: [[_ZTS13INCOMPLETE_TYPTR_TBAA13]] = !{[[META14:![0-9]+]], [[META15:![0-9]+]], i64 8}
-// NO-SANITIZE-WITH-ATTR: [[META14]] = !{!"annotated_sized_ptr_incomplete", [[META8]], i64 0, [[META15]], i64 8, [[META3]], i64 16}
-// NO-SANITIZE-WITH-ATTR: [[META15]] = !{!"p1 _ZTS13incomplete_ty", [[META9]], i64 0}
-// NO-SANITIZE-WITH-ATTR: [[INTPTR_TBAA16]] = !{[[META17:![0-9]+]], [[META18:![0-9]+]], i64 0}
-// NO-SANITIZE-WITH-ATTR: [[META17]] = !{!"annotated_volatile_ptr", [[META18]], i64 0, [[META3]], i64 8}
-// NO-SANITIZE-WITH-ATTR: [[META18]] = !{!"p1 int", [[META9]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[META9]] = !{!"p2 _ZTS3foo", [[META10:![0-9]+]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[META10]] = !{!"any p2 pointer", [[META11:![0-9]+]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[META11]] = !{!"any pointer", [[META4]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[_ZTS3FOOPTR_TBAA12]] = !{[[META13:![0-9]+]], [[META13]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[META13]] = !{!"p1 _ZTS3foo", [[META11]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[_ZTS18THREE_BYTE_POINTEEPTR_TBAA14]] = !{[[META15:![0-9]+]], [[META16:![0-9]+]], i64 8}
+// NO-SANITIZE-WITH-ATTR: [[META15]] = !{!"annotated_sized_ptr_odd_pointee", [[META8]], i64 0, [[META16]], i64 8, [[META3]], i64 16}
+// NO-SANITIZE-WITH-ATTR: [[META16]] = !{!"p1 _ZTS18three_byte_pointee", [[META11]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[CHAR_TBAA17]] = !{[[META4]], [[META4]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[_ZTS3FOOPTR_TBAA18]] = !{[[META19:![0-9]+]], [[META9]], i64 8}
+// NO-SANITIZE-WITH-ATTR: [[META19]] = !{!"annotated_sized_ptr_pow2_unsigned_count", [[META8]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
+// NO-SANITIZE-WITH-ATTR: [[ANYPTR_TBAA20]] = !{[[META21:![0-9]+]], [[META11]], i64 8}
+// NO-SANITIZE-WITH-ATTR: [[META21]] = !{!"annotated_sized_ptr", [[META8]], i64 0, [[META11]], i64 8, [[META3]], i64 16}
+// NO-SANITIZE-WITH-ATTR: [[_ZTS3FOOPTR_TBAA22]] = !{[[META23:![0-9]+]], [[META13]], i64 8}
+// NO-SANITIZE-WITH-ATTR: [[META23]] = !{!"annotated_sized_ptr_non_byte_sized_pointee", [[META8]], i64 0, [[META13]], i64 8, [[META3]], i64 16}
+// NO-SANITIZE-WITH-ATTR: [[_ZTS13INCOMPLETE_TYPTR_TBAA24]] = !{[[META25:![0-9]+]], [[META26:![0-9]+]], i64 8}
+// NO-SANITIZE-WITH-ATTR: [[META25]] = !{!"annotated_sized_ptr_incomplete", [[META8]], i64 0, [[META26]], i64 8, [[META3]], i64 16}
+// NO-SANITIZE-WITH-ATTR: [[META26]] = !{!"p1 _ZTS13incomplete_ty", [[META11]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[INTPTR_TBAA27]] = !{[[META28:![0-9]+]], [[META29:![0-9]+]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[META28]] = !{!"annotated_volatile_ptr", [[META29]], i64 0, [[META3]], i64 8}
+// NO-SANITIZE-WITH-ATTR: [[META29]] = !{!"p1 int", [[META11]], i64 0}
//.
// SANITIZE-WITHOUT-ATTR: [[META3:![0-9]+]] = !{!"int", [[META4:![0-9]+]], i64 0}
// SANITIZE-WITHOUT-ATTR: [[META4]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}
// SANITIZE-WITHOUT-ATTR: [[META5]] = !{!"Simple C/C++ TBAA"}
-// SANITIZE-WITHOUT-ATTR: [[INTPTR_TBAA6]] = !{[[META7:![0-9]+]], [[META8:![0-9]+]], i64 0}
-// SANITIZE-WITHOUT-ATTR: [[META7]] = !{!"annotated_volatile_ptr", [[META8]], i64 0, [[META3]], i64 8}
-// SANITIZE-WITHOUT-ATTR: [[META8]] = !{!"p1 int", [[META9:![0-9]+]], i64 0}
-// SANITIZE-WITHOUT-ATTR: [[META9]] = !{!"any pointer", [[META4]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[_ZTS3FOOPTR_TBAA6]] = !{[[META7:![0-9]+]], [[META9:![0-9]+]], i64 8}
+// SANITIZE-WITHOUT-ATTR: [[META7]] = !{!"annotated_ptr", [[META8:![0-9]+]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
+// SANITIZE-WITHOUT-ATTR: [[META8]] = !{!"long", [[META4]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[META9]] = !{!"p2 _ZTS3foo", [[META10:![0-9]+]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[META10]] = !{!"any p2 pointer", [[META11:![0-9]+]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[META11]] = !{!"any pointer", [[META4]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[_ZTS3FOOPTR_TBAA12]] = !{[[META13:![0-9]+]], [[META13]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[META13]] = !{!"p1 _ZTS3foo", [[META11]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[_ZTS18THREE_BYTE_POINTEEPTR_TBAA14]] = !{[[META15:![0-9]+]], [[META16:![0-9]+]], i64 8}
+// SANITIZE-WITHOUT-ATTR: [[META15]] = !{!"annotated_sized_ptr_odd_pointee", [[META8]], i64 0, [[META16]], i64 8, [[META3]], i64 16}
+// SANITIZE-WITHOUT-ATTR: [[META16]] = !{!"p1 _ZTS18three_byte_pointee", [[META11]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[CHAR_TBAA17]] = !{[[META4]], [[META4]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[_ZTS3FOOPTR_TBAA18]] = !{[[META19:![0-9]+]], [[META9]], i64 8}
+// SANITIZE-WITHOUT-ATTR: [[META19]] = !{!"annotated_sized_ptr_pow2_unsigned_count", [[META8]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
+// SANITIZE-WITHOUT-ATTR: [[INTPTR_TBAA20]] = !{[[META21:![0-9]+]], [[META22:![0-9]+]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[META21]] = !{!"annotated_volatile_ptr", [[META22]], i64 0, [[META3]], i64 8}
+// SANITIZE-WITHOUT-ATTR: [[META22]] = !{!"p1 int", [[META11]], i64 0}
//.
// NO-SANITIZE-WITHOUT-ATTR: [[META3:![0-9]+]] = !{!"int", [[META4:![0-9]+]], i64 0}
// NO-SANITIZE-WITHOUT-ATTR: [[META4]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}
// NO-SANITIZE-WITHOUT-ATTR: [[META5]] = !{!"Simple C/C++ TBAA"}
-// NO-SANITIZE-WITHOUT-ATTR: [[INTPTR_TBAA6]] = !{[[META7:![0-9]+]], [[META8:![0-9]+]], i64 0}
-// NO-SANITIZE-WITHOUT-ATTR: [[META7]] = !{!"annotated_volatile_ptr", [[META8]], i64 0, [[META3]], i64 8}
-// NO-SANITIZE-WITHOUT-ATTR: [[META8]] = !{!"p1 int", [[META9:![0-9]+]], i64 0}
-// NO-SANITIZE-WITHOUT-ATTR: [[META9]] = !{!"any pointer", [[META4]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[_ZTS3FOOPTR_TBAA6]] = !{[[META7:![0-9]+]], [[META9:![0-9]+]], i64 8}
+// NO-SANITIZE-WITHOUT-ATTR: [[META7]] = !{!"annotated_ptr", [[META8:![0-9]+]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
+// NO-SANITIZE-WITHOUT-ATTR: [[META8]] = !{!"long", [[META4]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[META9]] = !{!"p2 _ZTS3foo", [[META10:![0-9]+]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[META10]] = !{!"any p2 pointer", [[META11:![0-9]+]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[META11]] = !{!"any pointer", [[META4]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[_ZTS3FOOPTR_TBAA12]] = !{[[META13:![0-9]+]], [[META13]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[META13]] = !{!"p1 _ZTS3foo", [[META11]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[_ZTS18THREE_BYTE_POINTEEPTR_TBAA14]] = !{[[META15:![0-9]+]], [[META16:![0-9]+]], i64 8}
+// NO-SANITIZE-WITHOUT-ATTR: [[META15]] = !{!"annotated_sized_ptr_odd_pointee", [[META8]], i64 0, [[META16]], i64 8, [[META3]], i64 16}
+// NO-SANITIZE-WITHOUT-ATTR: [[META16]] = !{!"p1 _ZTS18three_byte_pointee", [[META11]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[CHAR_TBAA17]] = !{[[META4]], [[META4]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[_ZTS3FOOPTR_TBAA18]] = !{[[META19:![0-9]+]], [[META9]], i64 8}
+// NO-SANITIZE-WITHOUT-ATTR: [[META19]] = !{!"annotated_sized_ptr_pow2_unsigned_count", [[META8]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
+// NO-SANITIZE-WITHOUT-ATTR: [[INTPTR_TBAA20]] = !{[[META21:![0-9]+]], [[META22:![0-9]+]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[META21]] = !{!"annotated_volatile_ptr", [[META22]], i64 0, [[META3]], i64 8}
+// NO-SANITIZE-WITHOUT-ATTR: [[META22]] = !{!"p1 int", [[META11]], i64 0}
//.
>From 7957fc1c11052ea3cd29b6b52097c94033b91ef5 Mon Sep 17 00:00:00 2001
From: Dan Liew <dan at su-root.co.uk>
Date: Wed, 9 Sep 2026 00:32:06 -0700
Subject: [PATCH 2/3] Add some asserts and fix unnecessary re-emission of
member expression access.
---
clang/lib/CodeGen/CGExpr.cpp | 39 +++++++----
.../attr-counted-by-or-null-for-pointers.c | 51 +++++++-------
.../attr-sized-by-or-null-for-pointers.c | 69 +++++++++----------
3 files changed, 83 insertions(+), 76 deletions(-)
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index afe2dd8e79848..80c1c3a9bad64 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -5001,23 +5001,26 @@ void CodeGenFunction::EmitCountedByBoundsChecking(
// Create a GEP with the byte offset between the counted object and the
// count and use that to load the count value.
- ArrayInst = Builder.CreatePointerBitCastOrAddrSpaceCast(ArrayInst,
- Int8PtrTy, Int8Ty);
+ Address CountAddr = Builder.CreatePointerBitCastOrAddrSpaceCast(
+ ArrayInst, Int8PtrTy, Int8Ty);
llvm::Type *BoundsType = ConvertType(CountFD->getType());
llvm::Value *BoundsVal =
- Builder.CreateInBoundsGEP(Int8Ty, ArrayInst.emitRawPointer(*this),
+ Builder.CreateInBoundsGEP(Int8Ty, CountAddr.emitRawPointer(*this),
Builder.getInt32(*Diff), ".counted_by.gep");
BoundsVal = Builder.CreateAlignedLoad(BoundsType, BoundsVal, getIntAlign(),
".counted_by.load");
- const auto *CAT = FD->getType()->getAs<CountAttributedType>();
+ const auto *CountAttributedTy = FD->getType()->getAs<CountAttributedType>();
+ assert(CountAttributedTy && "expected FD to have a CountAttributedType");
// For the '_or_null' variants a null pointer describes no accessible
// memory, so treat the bound as 0 when the pointer is null; any access then
// traps.
- if (CAT->isOrNull()) {
- llvm::Value *Ptr = EmitScalarExpr(ME);
+ if (CountAttributedTy->isOrNull()) {
+ // Load the pointer from its address rather than re-emitting the
+ // member expression, which would re-evaluate a side-effecting base.
+ llvm::Value *Ptr = Builder.CreateLoad(ArrayInst);
llvm::Value *IsNull = Builder.CreateIsNull(Ptr);
BoundsVal = Builder.CreateSelect(
IsNull, llvm::ConstantInt::get(BoundsType, 0), BoundsVal);
@@ -5025,24 +5028,30 @@ void CodeGenFunction::EmitCountedByBoundsChecking(
// For '__sized_by' the loaded bound is a byte count. Convert it to an
// element count by dividing by the element size so the check can compare
- // the (element) index directly. '__counted_by' already counts elements, and
- // a void (or otherwise zero-/unknown-sized) pointee uses the GNU convention
- // of element size 1; both need no conversion. Use signed division for a
- // signed count field so a negative byte count stays non-positive and is
- // still rejected by the negative-bounds guard in EmitBoundsCheckImpl
- // (unsigned division would turn it into a large positive count).
- if (CAT->isCountInBytes()) {
+ // the (element) index directly. '__counted_by' already counts elements so
+ // needs no special handling.
+ if (CountAttributedTy->isCountInBytes()) {
QualType ElemTy = ArrayType->getPointeeType();
- if (!ElemTy.isNull() && !ElemTy->isIncompleteType() &&
- !ElemTy->isFunctionType()) {
+ assert(!ElemTy.isNull() && "pointee type is never null");
+ assert(!ElemTy->isFunctionType() &&
+ "Sema guarantees a '__sized_by' pointee is a non-function type");
+ if (!ElemTy->isIncompleteType()) {
CharUnits ElemSize = getContext().getTypeSizeInChars(ElemTy);
if (ElemSize > CharUnits::One()) {
llvm::Value *ElemSizeV = llvm::ConstantInt::get(
BoundsVal->getType(), ElemSize.getQuantity());
+ // Use signed division for a signed count field so a negative byte
+ // count stays non-positive and is still rejected by the
+ // negative-bounds guard in EmitBoundsCheckImpl (unsigned division
+ // would turn it into a large positive count).
BoundsVal = CountFD->getType()->isSignedIntegerOrEnumerationType()
? Builder.CreateSDiv(BoundsVal, ElemSizeV)
: Builder.CreateUDiv(BoundsVal, ElemSizeV);
}
+ } else {
+ // Only 'void' can be subscripted here; it is accessed with a 1-byte
+ // stride, so the unconverted byte count is already the element count.
+ assert(ElemTy->isVoidType() && "expected a 'void' incomplete pointee");
}
}
diff --git a/clang/test/CodeGen/attr-counted-by-or-null-for-pointers.c b/clang/test/CodeGen/attr-counted-by-or-null-for-pointers.c
index 4648ca21239e6..f7de00e62d4b2 100644
--- a/clang/test/CodeGen/attr-counted-by-or-null-for-pointers.c
+++ b/clang/test/CodeGen/attr-counted-by-or-null-for-pointers.c
@@ -43,12 +43,12 @@ struct annotated_ptr {
// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ult i32 [[INDEX]], [[TMP2]], !nosanitize [[META12:![0-9]+]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP2]], 0, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]], !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT15:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13:![0-9]+]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13:![0-9]+]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 [[TMP6]]) #[[ATTR5:[0-9]+]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR: [[CONT15]]:
+// SANITIZE-WITH-ATTR: [[CONT10]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
// SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA14:![0-9]+]]
@@ -100,12 +100,12 @@ void test_store_subscript(struct annotated_ptr *p, int index, struct foo *value)
// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ult i32 [[INDEX]], [[TMP2]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP2]], 0, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]], !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT15:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 [[TMP6]]) #[[ATTR5]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR: [[CONT15]]:
+// SANITIZE-WITH-ATTR: [[CONT10]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
// SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA14]]
@@ -157,12 +157,12 @@ void test_store_subscript_through_cast(struct annotated_ptr *p, int index, struc
// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ule i32 [[INDEX]], [[TMP2]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP2]], 0, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]], !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT15:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 [[TMP6]]) #[[ATTR5]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR: [[CONT15]]:
+// SANITIZE-WITH-ATTR: [[CONT10]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
// SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA14]]
@@ -298,12 +298,12 @@ size_t test_bdos_of_pointer_through_cast(struct annotated_ptr *p, int index) {
// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ule i32 [[INDEX]], [[TMP2]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP2]], 0, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]], !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT13:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB6:[0-9]+]], i64 [[TMP6]]) #[[ATTR5]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR: [[CONT13]]:
+// SANITIZE-WITH-ATTR: [[CONT8]]:
// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[DOTCOUNTED_BY_LOAD]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = shl nsw i64 [[COUNT]], 3
@@ -359,12 +359,12 @@ size_t test_bdos_of_element_address(struct annotated_ptr *p, int index) {
// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ult i32 [[INDEX]], [[TMP2]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP2]], 0, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]], !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT15:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB7:[0-9]+]], i64 [[TMP6]]) #[[ATTR5]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR: [[CONT15]]:
+// SANITIZE-WITH-ATTR: [[CONT10]]:
// SANITIZE-WITH-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test_bdos_of_subscript_through_cast(
@@ -573,28 +573,27 @@ void test_pass_dynamic_object_size_of_pointer(struct annotated_volatile_ptr *p)
// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20]]
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
-// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP1]], null
-// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 0, i32 [[DOTCOUNTED_BY_LOAD]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ule i32 [[INDEX]], [[TMP3]], !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[TMP3]], 0, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]], !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT12:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 0, i32 [[DOTCOUNTED_BY_LOAD]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ule i32 [[INDEX]], [[TMP2]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP2]], 0, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT9:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
-// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB9:[0-9]+]], i64 [[TMP7]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB9:[0-9]+]], i64 [[TMP6]]) #[[ATTR5]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR: [[CONT12]]:
+// SANITIZE-WITH-ATTR: [[CONT9]]:
// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[DOTCOUNTED_BY_LOAD]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDXPROM]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP9:%.*]] = icmp eq ptr [[TMP8]], null
-// SANITIZE-WITH-ATTR-NEXT: [[TMP10:%.*]] = shl nsw i64 [[COUNT]], 2
-// SANITIZE-WITH-ATTR-NEXT: [[ARRAY_SIZE:%.*]] = select i1 [[TMP9]], i64 0, i64 [[TMP10]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = icmp eq ptr [[TMP7]], null
+// SANITIZE-WITH-ATTR-NEXT: [[TMP9:%.*]] = shl nsw i64 [[COUNT]], 2
+// SANITIZE-WITH-ATTR-NEXT: [[ARRAY_SIZE:%.*]] = select i1 [[TMP8]], i64 0, i64 [[TMP9]]
// SANITIZE-WITH-ATTR-NEXT: [[RESULT:%.*]] = sub nsw i64 [[ARRAY_SIZE]], [[IDXPROM]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP11:%.*]] = tail call i64 @llvm.smax.i64(i64 [[RESULT]], i64 0)
-// SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef [[TMP11]]) #[[ATTR6]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP10:%.*]] = tail call i64 @llvm.smax.i64(i64 [[RESULT]], i64 0)
+// SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef [[TMP10]]) #[[ATTR6]]
// SANITIZE-WITH-ATTR-NEXT: ret void
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_element_address(
diff --git a/clang/test/CodeGen/attr-sized-by-or-null-for-pointers.c b/clang/test/CodeGen/attr-sized-by-or-null-for-pointers.c
index 132d0bbbf61c4..951ab6c36fc6b 100644
--- a/clang/test/CodeGen/attr-sized-by-or-null-for-pointers.c
+++ b/clang/test/CodeGen/attr-sized-by-or-null-for-pointers.c
@@ -44,12 +44,12 @@ struct annotated_ptr {
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ult i32 [[INDEX]], [[TMP3]], !nosanitize [[META12:![0-9]+]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[TMP3]], 0, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]], !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT15:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13:![0-9]+]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13:![0-9]+]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 [[TMP7]]) #[[ATTR5:[0-9]+]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR: [[CONT15]]:
+// SANITIZE-WITH-ATTR: [[CONT10]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
// SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA14:![0-9]+]]
@@ -102,12 +102,12 @@ void test_store_subscript(struct annotated_ptr *p, int index, struct foo *value)
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ult i32 [[INDEX]], [[TMP3]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[TMP3]], 0, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]], !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT15:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 [[TMP7]]) #[[ATTR5]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR: [[CONT15]]:
+// SANITIZE-WITH-ATTR: [[CONT10]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
// SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA14]]
@@ -160,12 +160,12 @@ void test_store_subscript_through_cast(struct annotated_ptr *p, int index, struc
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ule i32 [[INDEX]], [[TMP3]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[TMP3]], 0, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]], !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT15:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 [[TMP7]]) #[[ATTR5]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR: [[CONT15]]:
+// SANITIZE-WITH-ATTR: [[CONT10]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
// SANITIZE-WITH-ATTR-NEXT: store ptr [[VALUE]], ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA14]]
@@ -233,12 +233,12 @@ struct annotated_sized_ptr_odd_pointee {
// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = udiv i32 [[DOTCOUNTED_BY_LOAD]], 3
// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ugt i32 [[TMP2]], [[INDEX]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], i1 [[TMP3]], i1 false
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP4]], label %[[CONT20:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP4]], label %[[CONT15:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB7:[0-9]+]], i64 [[TMP5]]) #[[ATTR5]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR: [[CONT20]]:
+// SANITIZE-WITH-ATTR: [[CONT15]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa [[CHAR_TBAA19:![0-9]+]]
@@ -299,12 +299,12 @@ struct annotated_sized_ptr_pow2_unsigned_count {
// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = lshr i32 [[DOTCOUNTED_BY_LOAD]], 3
// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ugt i32 [[TMP2]], [[INDEX]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], i1 [[TMP3]], i1 false
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP4]], label %[[CONT15:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP4]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB9:[0-9]+]], i64 [[TMP5]]) #[[ATTR5]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR: [[CONT15]]:
+// SANITIZE-WITH-ATTR: [[CONT10]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA14]]
@@ -402,12 +402,12 @@ size_t test_bdos_of_pointer(struct annotated_sized_ptr *p) {
// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ule i32 [[INDEX]], [[TMP2]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP2]], 0, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]], !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT13:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB11:[0-9]+]], i64 [[TMP6]]) #[[ATTR5]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR: [[CONT13]]:
+// SANITIZE-WITH-ATTR: [[CONT8]]:
// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[DOTCOUNTED_BY_LOAD]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[COUNT_OR_NULL:%.*]] = select i1 [[TMP1]], i64 0, i64 [[COUNT]]
@@ -460,12 +460,12 @@ size_t test_bdos_of_element_address(struct annotated_sized_ptr *p, int index) {
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ult i32 [[INDEX]], [[TMP3]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[TMP3]], 0, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]], !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT15:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB12:[0-9]+]], i64 [[TMP7]]) #[[ATTR5]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR: [[CONT15]]:
+// SANITIZE-WITH-ATTR: [[CONT10]]:
// SANITIZE-WITH-ATTR-NEXT: ret i64 -1
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test_bdos_of_subscript_through_cast(
@@ -551,12 +551,12 @@ size_t test_bdos_of_pointer_multibyte_pointee(struct annotated_sized_ptr_non_byt
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ule i32 [[INDEX]], [[TMP3]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[TMP3]], 0, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]], !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT13:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB14:[0-9]+]], i64 [[TMP7]]) #[[ATTR5]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR: [[CONT13]]:
+// SANITIZE-WITH-ATTR: [[CONT8]]:
// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[DOTCOUNTED_BY_LOAD]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[COUNT_OR_NULL:%.*]] = select i1 [[TMP1]], i64 0, i64 [[COUNT]]
@@ -662,12 +662,12 @@ size_t test_bdos_of_pointer_incomplete_pointee(struct annotated_sized_ptr_incomp
// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ule i32 [[INDEX]], [[TMP2]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP2]], 0, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]], !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT13:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB16:[0-9]+]], i64 [[TMP6]]) #[[ATTR5]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR: [[CONT13]]:
+// SANITIZE-WITH-ATTR: [[CONT8]]:
// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[DOTCOUNTED_BY_LOAD]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[COUNT_OR_NULL:%.*]] = select i1 [[TMP1]], i64 0, i64 [[COUNT]]
@@ -806,27 +806,26 @@ void test_pass_dynamic_object_size_of_pointer(struct annotated_volatile_ptr *p)
// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA29]]
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 8
-// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA29]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP1]], null
-// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 0, i32 [[DOTCOUNTED_BY_LOAD]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ule i32 [[INDEX]], [[TMP3]], !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[TMP3]], 0, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]], !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT12:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
+// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 0, i32 [[DOTCOUNTED_BY_LOAD]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ule i32 [[INDEX]], [[TMP2]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP2]], 0, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT9:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
-// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB17:[0-9]+]], i64 [[TMP7]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB17:[0-9]+]], i64 [[TMP6]]) #[[ATTR5]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR: [[CONT12]]:
+// SANITIZE-WITH-ATTR: [[CONT9]]:
// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[DOTCOUNTED_BY_LOAD]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDXPROM]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA29]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP9:%.*]] = icmp eq ptr [[TMP8]], null
-// SANITIZE-WITH-ATTR-NEXT: [[COUNT_OR_NULL:%.*]] = select i1 [[TMP9]], i64 0, i64 [[COUNT]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA29]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = icmp eq ptr [[TMP7]], null
+// SANITIZE-WITH-ATTR-NEXT: [[COUNT_OR_NULL:%.*]] = select i1 [[TMP8]], i64 0, i64 [[COUNT]]
// SANITIZE-WITH-ATTR-NEXT: [[RESULT:%.*]] = sub nsw i64 [[COUNT_OR_NULL]], [[IDXPROM]]
-// SANITIZE-WITH-ATTR-NEXT: [[TMP10:%.*]] = tail call i64 @llvm.smax.i64(i64 [[RESULT]], i64 0)
-// SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef [[TMP10]]) #[[ATTR6]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP9:%.*]] = tail call i64 @llvm.smax.i64(i64 [[RESULT]], i64 0)
+// SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef [[TMP9]]) #[[ATTR6]]
// SANITIZE-WITH-ATTR-NEXT: ret void
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_element_address(
@@ -886,12 +885,12 @@ void test_pass_dynamic_object_size_of_element_address(struct annotated_volatile_
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ule i32 [[INDEX]], [[TMP3]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[TMP3]], 0, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]], !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT13:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB19:[0-9]+]], i64 [[TMP7]]) #[[ATTR5]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR: [[CONT13]]:
+// SANITIZE-WITH-ATTR: [[CONT8]]:
// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[DOTCOUNTED_BY_LOAD]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[COUNT_OR_NULL:%.*]] = select i1 [[TMP1]], i64 0, i64 [[COUNT]]
>From 5151d293b0df5c736c65a4eae83080698952dea8 Mon Sep 17 00:00:00 2001
From: Dan Liew <dan at su-root.co.uk>
Date: Wed, 9 Sep 2026 01:19:47 -0700
Subject: [PATCH 3/3] Fix division bug where a small count expression type
can't represent the element size
---
clang/lib/CodeGen/CGExpr.cpp | 34 ++-
.../test/CodeGen/attr-sized-by-for-pointers.c | 174 ++++++++++++---
.../attr-sized-by-or-null-for-pointers.c | 204 ++++++++++++++----
3 files changed, 330 insertions(+), 82 deletions(-)
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 80c1c3a9bad64..22fb363123c7e 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -5038,15 +5038,31 @@ void CodeGenFunction::EmitCountedByBoundsChecking(
if (!ElemTy->isIncompleteType()) {
CharUnits ElemSize = getContext().getTypeSizeInChars(ElemTy);
if (ElemSize > CharUnits::One()) {
- llvm::Value *ElemSizeV = llvm::ConstantInt::get(
- BoundsVal->getType(), ElemSize.getQuantity());
- // Use signed division for a signed count field so a negative byte
- // count stays non-positive and is still rejected by the
- // negative-bounds guard in EmitBoundsCheckImpl (unsigned division
- // would turn it into a large positive count).
- BoundsVal = CountFD->getType()->isSignedIntegerOrEnumerationType()
- ? Builder.CreateSDiv(BoundsVal, ElemSizeV)
- : Builder.CreateUDiv(BoundsVal, ElemSizeV);
+ bool CountSigned =
+ CountFD->getType()->isSignedIntegerOrEnumerationType();
+ int64_t ElemSizeQ = ElemSize.getQuantity();
+ unsigned CountWidth = BoundsVal->getType()->getIntegerBitWidth();
+
+ // The divisor must be representable in the count field's type.
+ bool ElemSizeFits =
+ CountSigned
+ ? llvm::isIntN(CountWidth, ElemSizeQ)
+ : llvm::isUIntN(CountWidth, static_cast<uint64_t>(ElemSizeQ));
+ if (ElemSizeFits) {
+ llvm::Value *ElemSizeV =
+ llvm::ConstantInt::get(BoundsVal->getType(), ElemSizeQ);
+ // Use signed division for a signed count field so a negative byte
+ // count stays non-positive and is still rejected by the
+ // negative-bounds guard in EmitBoundsCheckImpl (unsigned division
+ // would turn it into a large positive count).
+ BoundsVal = CountSigned ? Builder.CreateSDiv(BoundsVal, ElemSizeV)
+ : Builder.CreateUDiv(BoundsVal, ElemSizeV);
+ } else {
+ // No whole element fits in any representable byte count. Use a
+ // bound of 0 to always trap.
+ // FIXME: Sema should just reject this.
+ BoundsVal = llvm::ConstantInt::get(BoundsVal->getType(), 0);
+ }
}
} else {
// Only 'void' can be subscripted here; it is accessed with a 1-byte
diff --git a/clang/test/CodeGen/attr-sized-by-for-pointers.c b/clang/test/CodeGen/attr-sized-by-for-pointers.c
index ec42d54d10360..dabe3163571a5 100644
--- a/clang/test/CodeGen/attr-sized-by-for-pointers.c
+++ b/clang/test/CodeGen/attr-sized-by-for-pointers.c
@@ -37,7 +37,7 @@ struct annotated_ptr {
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7:![0-9]+]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 [[TMP4]]) #[[ATTR5:[0-9]+]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 [[TMP4]]) #[[ATTR6:[0-9]+]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[CONT10]]:
// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
@@ -93,7 +93,7 @@ void test_store_subscript(struct annotated_ptr *p, int index, struct foo *value)
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 [[TMP4]]) #[[ATTR5]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 [[TMP4]]) #[[ATTR6]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[CONT10]]:
// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
@@ -149,7 +149,7 @@ void test_store_subscript_through_cast(struct annotated_ptr *p, int index, struc
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 [[TMP4]]) #[[ATTR5]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 [[TMP4]]) #[[ATTR6]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[CONT10]]:
// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
@@ -220,7 +220,7 @@ struct annotated_sized_ptr_odd_pointee {
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label %[[CONT15:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB7:[0-9]+]], i64 [[TMP2]]) #[[ATTR5]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB7:[0-9]+]], i64 [[TMP2]]) #[[ATTR6]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[CONT15]]:
// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
@@ -284,7 +284,7 @@ struct annotated_sized_ptr_pow2_unsigned_count {
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB9:[0-9]+]], i64 [[TMP2]]) #[[ATTR5]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB9:[0-9]+]], i64 [[TMP2]]) #[[ATTR6]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[CONT10]]:
// SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
@@ -328,6 +328,104 @@ struct foo *test_load_subscript_pow2_unsigned_count(struct annotated_sized_ptr_p
return p->buf[index];
}
+// A count field can be too narrow to hold the element size, in which case no
+// whole element fits any representable byte count: the bound is 0 and every
+// access is out of bounds. Whether the element size fits depends on the count
+// field's signedness, so both an unsigned and a signed count are tested.
+//
+// Unsigned count: the element size (256) exceeds the unsigned range of the
+// count field's width (an 'unsigned char' holds at most 255).
+struct large_pointee { char data[256]; };
+struct annotated_sized_ptr_narrow_unsigned_count {
+ struct large_pointee *buf __sized_by(byte_count);
+ unsigned char byte_count;
+};
+
+// SANITIZE-WITH-ATTR-LABEL: define dso_local noundef signext i8 @test_load_subscript_narrow_unsigned_count(
+// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
+// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB11:[0-9]+]], i64 [[TMP0]]) #[[ATTR6]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
+//
+// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local signext i8 @test_load_subscript_narrow_unsigned_count(
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[_ZTS13LARGE_POINTEEPTR_TBAA20:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [256 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa [[CHAR_TBAA17]]
+// NO-SANITIZE-WITH-ATTR-NEXT: ret i8 [[TMP1]]
+//
+// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local signext i8 @test_load_subscript_narrow_unsigned_count(
+// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[_ZTS13LARGE_POINTEEPTR_TBAA20:![0-9]+]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [256 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa [[CHAR_TBAA17]]
+// SANITIZE-WITHOUT-ATTR-NEXT: ret i8 [[TMP1]]
+//
+// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local signext i8 @test_load_subscript_narrow_unsigned_count(
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[_ZTS13LARGE_POINTEEPTR_TBAA20:![0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [256 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa [[CHAR_TBAA17]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i8 [[TMP1]]
+//
+char test_load_subscript_narrow_unsigned_count(struct annotated_sized_ptr_narrow_unsigned_count *p, int index) {
+ return p->buf[index].data[0];
+}
+
+// Signed count: the element size (200) is within the count field's bit width
+// but exceeds its signed range (a 'signed char' holds at most 127) -- a case
+// the unsigned test above does not cover.
+struct midsize_pointee { char data[200]; };
+struct annotated_sized_ptr_narrow_signed_count {
+ struct midsize_pointee *buf __sized_by(byte_count);
+ signed char byte_count;
+};
+
+// SANITIZE-WITH-ATTR-LABEL: define dso_local noundef signext i8 @test_load_subscript_narrow_signed_count(
+// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
+// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB13:[0-9]+]], i64 [[TMP0]]) #[[ATTR6]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
+//
+// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local signext i8 @test_load_subscript_narrow_signed_count(
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[_ZTS15MIDSIZE_POINTEEPTR_TBAA23:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [200 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa [[CHAR_TBAA17]]
+// NO-SANITIZE-WITH-ATTR-NEXT: ret i8 [[TMP1]]
+//
+// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local signext i8 @test_load_subscript_narrow_signed_count(
+// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[_ZTS15MIDSIZE_POINTEEPTR_TBAA23:![0-9]+]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [200 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa [[CHAR_TBAA17]]
+// SANITIZE-WITHOUT-ATTR-NEXT: ret i8 [[TMP1]]
+//
+// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local signext i8 @test_load_subscript_narrow_signed_count(
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[_ZTS15MIDSIZE_POINTEEPTR_TBAA23:![0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [200 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa [[CHAR_TBAA17]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i8 [[TMP1]]
+//
+char test_load_subscript_narrow_signed_count(struct annotated_sized_ptr_narrow_signed_count *p, int index) {
+ return p->buf[index].data[0];
+}
+
struct annotated_sized_ptr {
unsigned long flags;
void *buf __sized_by(ptr_count);
@@ -377,7 +475,7 @@ size_t test_bdos_of_pointer(struct annotated_sized_ptr *p) {
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB11:[0-9]+]], i64 [[TMP3]]) #[[ATTR5]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB15:[0-9]+]], i64 [[TMP3]]) #[[ATTR6]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[CONT8]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
@@ -425,7 +523,7 @@ size_t test_bdos_of_element_address(struct annotated_sized_ptr *p, int index) {
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB12:[0-9]+]], i64 [[TMP4]]) #[[ATTR5]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB16:[0-9]+]], i64 [[TMP4]]) #[[ATTR6]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[CONT10]]:
// SANITIZE-WITH-ATTR-NEXT: ret i64 -1
@@ -503,7 +601,7 @@ size_t test_bdos_of_pointer_multibyte_pointee(struct annotated_sized_ptr_non_byt
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB14:[0-9]+]], i64 [[TMP4]]) #[[ATTR5]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB18:[0-9]+]], i64 [[TMP4]]) #[[ATTR6]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[CONT8]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
@@ -600,7 +698,7 @@ size_t test_bdos_of_pointer_incomplete_pointee(struct annotated_sized_ptr_incomp
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB16:[0-9]+]], i64 [[TMP3]]) #[[ATTR5]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB20:[0-9]+]], i64 [[TMP3]]) #[[ATTR6]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[CONT8]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
@@ -651,7 +749,7 @@ struct annotated_volatile_ptr {
void take_ptr_with_size(void *p __attribute__((pass_dynamic_object_size(0))));
// SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i64 @test_bdos_of_volatile_pointer(
-// SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readnone captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
+// SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readnone captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// SANITIZE-WITH-ATTR-NEXT: ret i64 -1
//
@@ -687,13 +785,13 @@ size_t test_bdos_of_volatile_pointer(struct annotated_volatile_ptr *p) {
// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = tail call i32 @llvm.smax.i32(i32 [[COUNTED_BY_LOAD]], i32 0)
// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = zext nneg i32 [[NARROW]] to i64
-// SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef [[TMP1]]) #[[ATTR6:[0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef [[TMP1]]) #[[ATTR7:[0-9]+]]
// SANITIZE-WITH-ATTR-NEXT: ret void
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_pointer(
// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA26:![0-9]+]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = tail call i32 @llvm.smax.i32(i32 [[COUNTED_BY_LOAD]], i32 0)
@@ -704,14 +802,14 @@ size_t test_bdos_of_volatile_pointer(struct annotated_volatile_ptr *p) {
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_pointer(
// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
-// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20:![0-9]+]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA26:![0-9]+]]
// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef -1) #[[ATTR3:[0-9]+]]
// SANITIZE-WITHOUT-ATTR-NEXT: ret void
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_pointer(
// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
-// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20:![0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA26:![0-9]+]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef -1) #[[ATTR6:[0-9]+]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
//
@@ -733,20 +831,20 @@ void test_pass_dynamic_object_size_of_pointer(struct annotated_volatile_ptr *p)
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label %[[CONT6:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB17:[0-9]+]], i64 [[TMP4]]) #[[ATTR5]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB21:[0-9]+]], i64 [[TMP4]]) #[[ATTR6]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[CONT6]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDXPROM]]
// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = zext nneg i32 [[DOTCOUNTED_BY_LOAD]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[RESULT:%.*]] = sub nuw nsw i64 [[COUNT]], [[IDXPROM]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef [[RESULT]]) #[[ATTR6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef [[RESULT]]) #[[ATTR7]]
// SANITIZE-WITH-ATTR-NEXT: ret void
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_element_address(
// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR4]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA26]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDXPROM]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
@@ -763,7 +861,7 @@ void test_pass_dynamic_object_size_of_pointer(struct annotated_volatile_ptr *p)
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_element_address(
// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
-// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA26]]
// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDXPROM]]
// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef -1) #[[ATTR3]]
@@ -772,7 +870,7 @@ void test_pass_dynamic_object_size_of_pointer(struct annotated_volatile_ptr *p)
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_element_address(
// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR4]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
-// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA26]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDXPROM]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef -1) #[[ATTR6]]
@@ -796,7 +894,7 @@ void test_pass_dynamic_object_size_of_element_address(struct annotated_volatile_
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF7]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB19:[0-9]+]], i64 [[TMP4]]) #[[ATTR5]], !nosanitize [[META6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB23:[0-9]+]], i64 [[TMP4]]) #[[ATTR6]], !nosanitize [[META6]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]]
// SANITIZE-WITH-ATTR: [[CONT8]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
@@ -878,9 +976,15 @@ size_t test_bdos_of_element_address_through_widening_cast(struct annotated_sized
// NO-SANITIZE-WITH-ATTR: [[CHAR_TBAA17]] = !{[[META4]], [[META4]], i64 0}
// NO-SANITIZE-WITH-ATTR: [[_ZTS3FOOPTR_TBAA18]] = !{[[META19:![0-9]+]], [[META9]], i64 8}
// NO-SANITIZE-WITH-ATTR: [[META19]] = !{!"annotated_sized_ptr_pow2_unsigned_count", [[META8]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
-// NO-SANITIZE-WITH-ATTR: [[INTPTR_TBAA20]] = !{[[META21:![0-9]+]], [[META22:![0-9]+]], i64 0}
-// NO-SANITIZE-WITH-ATTR: [[META21]] = !{!"annotated_volatile_ptr", [[META22]], i64 0, [[META3]], i64 8}
-// NO-SANITIZE-WITH-ATTR: [[META22]] = !{!"p1 int", [[META11]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[_ZTS13LARGE_POINTEEPTR_TBAA20]] = !{[[META21:![0-9]+]], [[META22:![0-9]+]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[META21]] = !{!"annotated_sized_ptr_narrow_unsigned_count", [[META22]], i64 0, [[META4]], i64 8}
+// NO-SANITIZE-WITH-ATTR: [[META22]] = !{!"p1 _ZTS13large_pointee", [[META11]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[_ZTS15MIDSIZE_POINTEEPTR_TBAA23]] = !{[[META24:![0-9]+]], [[META25:![0-9]+]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[META24]] = !{!"annotated_sized_ptr_narrow_signed_count", [[META25]], i64 0, [[META4]], i64 8}
+// NO-SANITIZE-WITH-ATTR: [[META25]] = !{!"p1 _ZTS15midsize_pointee", [[META11]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[INTPTR_TBAA26]] = !{[[META27:![0-9]+]], [[META28:![0-9]+]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[META27]] = !{!"annotated_volatile_ptr", [[META28]], i64 0, [[META3]], i64 8}
+// NO-SANITIZE-WITH-ATTR: [[META28]] = !{!"p1 int", [[META11]], i64 0}
//.
// SANITIZE-WITHOUT-ATTR: [[META3:![0-9]+]] = !{!"int", [[META4:![0-9]+]], i64 0}
// SANITIZE-WITHOUT-ATTR: [[META4]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}
@@ -899,9 +1003,15 @@ size_t test_bdos_of_element_address_through_widening_cast(struct annotated_sized
// SANITIZE-WITHOUT-ATTR: [[CHAR_TBAA17]] = !{[[META4]], [[META4]], i64 0}
// SANITIZE-WITHOUT-ATTR: [[_ZTS3FOOPTR_TBAA18]] = !{[[META19:![0-9]+]], [[META9]], i64 8}
// SANITIZE-WITHOUT-ATTR: [[META19]] = !{!"annotated_sized_ptr_pow2_unsigned_count", [[META8]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
-// SANITIZE-WITHOUT-ATTR: [[INTPTR_TBAA20]] = !{[[META21:![0-9]+]], [[META22:![0-9]+]], i64 0}
-// SANITIZE-WITHOUT-ATTR: [[META21]] = !{!"annotated_volatile_ptr", [[META22]], i64 0, [[META3]], i64 8}
-// SANITIZE-WITHOUT-ATTR: [[META22]] = !{!"p1 int", [[META11]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[_ZTS13LARGE_POINTEEPTR_TBAA20]] = !{[[META21:![0-9]+]], [[META22:![0-9]+]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[META21]] = !{!"annotated_sized_ptr_narrow_unsigned_count", [[META22]], i64 0, [[META4]], i64 8}
+// SANITIZE-WITHOUT-ATTR: [[META22]] = !{!"p1 _ZTS13large_pointee", [[META11]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[_ZTS15MIDSIZE_POINTEEPTR_TBAA23]] = !{[[META24:![0-9]+]], [[META25:![0-9]+]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[META24]] = !{!"annotated_sized_ptr_narrow_signed_count", [[META25]], i64 0, [[META4]], i64 8}
+// SANITIZE-WITHOUT-ATTR: [[META25]] = !{!"p1 _ZTS15midsize_pointee", [[META11]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[INTPTR_TBAA26]] = !{[[META27:![0-9]+]], [[META28:![0-9]+]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[META27]] = !{!"annotated_volatile_ptr", [[META28]], i64 0, [[META3]], i64 8}
+// SANITIZE-WITHOUT-ATTR: [[META28]] = !{!"p1 int", [[META11]], i64 0}
//.
// NO-SANITIZE-WITHOUT-ATTR: [[META3:![0-9]+]] = !{!"int", [[META4:![0-9]+]], i64 0}
// NO-SANITIZE-WITHOUT-ATTR: [[META4]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}
@@ -920,7 +1030,13 @@ size_t test_bdos_of_element_address_through_widening_cast(struct annotated_sized
// NO-SANITIZE-WITHOUT-ATTR: [[CHAR_TBAA17]] = !{[[META4]], [[META4]], i64 0}
// NO-SANITIZE-WITHOUT-ATTR: [[_ZTS3FOOPTR_TBAA18]] = !{[[META19:![0-9]+]], [[META9]], i64 8}
// NO-SANITIZE-WITHOUT-ATTR: [[META19]] = !{!"annotated_sized_ptr_pow2_unsigned_count", [[META8]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
-// NO-SANITIZE-WITHOUT-ATTR: [[INTPTR_TBAA20]] = !{[[META21:![0-9]+]], [[META22:![0-9]+]], i64 0}
-// NO-SANITIZE-WITHOUT-ATTR: [[META21]] = !{!"annotated_volatile_ptr", [[META22]], i64 0, [[META3]], i64 8}
-// NO-SANITIZE-WITHOUT-ATTR: [[META22]] = !{!"p1 int", [[META11]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[_ZTS13LARGE_POINTEEPTR_TBAA20]] = !{[[META21:![0-9]+]], [[META22:![0-9]+]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[META21]] = !{!"annotated_sized_ptr_narrow_unsigned_count", [[META22]], i64 0, [[META4]], i64 8}
+// NO-SANITIZE-WITHOUT-ATTR: [[META22]] = !{!"p1 _ZTS13large_pointee", [[META11]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[_ZTS15MIDSIZE_POINTEEPTR_TBAA23]] = !{[[META24:![0-9]+]], [[META25:![0-9]+]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[META24]] = !{!"annotated_sized_ptr_narrow_signed_count", [[META25]], i64 0, [[META4]], i64 8}
+// NO-SANITIZE-WITHOUT-ATTR: [[META25]] = !{!"p1 _ZTS15midsize_pointee", [[META11]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[INTPTR_TBAA26]] = !{[[META27:![0-9]+]], [[META28:![0-9]+]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[META27]] = !{!"annotated_volatile_ptr", [[META28]], i64 0, [[META3]], i64 8}
+// NO-SANITIZE-WITHOUT-ATTR: [[META28]] = !{!"p1 int", [[META11]], i64 0}
//.
diff --git a/clang/test/CodeGen/attr-sized-by-or-null-for-pointers.c b/clang/test/CodeGen/attr-sized-by-or-null-for-pointers.c
index 951ab6c36fc6b..05f3c57d86149 100644
--- a/clang/test/CodeGen/attr-sized-by-or-null-for-pointers.c
+++ b/clang/test/CodeGen/attr-sized-by-or-null-for-pointers.c
@@ -47,7 +47,7 @@ struct annotated_ptr {
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13:![0-9]+]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 [[TMP7]]) #[[ATTR5:[0-9]+]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 [[TMP7]]) #[[ATTR6:[0-9]+]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[CONT10]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
@@ -105,7 +105,7 @@ void test_store_subscript(struct annotated_ptr *p, int index, struct foo *value)
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 [[TMP7]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 [[TMP7]]) #[[ATTR6]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[CONT10]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
@@ -163,7 +163,7 @@ void test_store_subscript_through_cast(struct annotated_ptr *p, int index, struc
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 [[TMP7]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 [[TMP7]]) #[[ATTR6]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[CONT10]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
@@ -236,7 +236,7 @@ struct annotated_sized_ptr_odd_pointee {
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP4]], label %[[CONT15:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB7:[0-9]+]], i64 [[TMP5]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB7:[0-9]+]], i64 [[TMP5]]) #[[ATTR6]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[CONT15]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
@@ -302,7 +302,7 @@ struct annotated_sized_ptr_pow2_unsigned_count {
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP4]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB9:[0-9]+]], i64 [[TMP5]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB9:[0-9]+]], i64 [[TMP5]]) #[[ATTR6]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[CONT10]]:
// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
@@ -344,6 +344,104 @@ struct foo *test_load_subscript_pow2_unsigned_count(struct annotated_sized_ptr_p
return p->buf[index];
}
+// A count field can be too narrow to hold the element size, in which case no
+// whole element fits any representable byte count: the bound is 0 and every
+// access is out of bounds. Whether the element size fits depends on the count
+// field's signedness, so both an unsigned and a signed count are tested.
+//
+// Unsigned count: the element size (256) exceeds the unsigned range of the
+// count field's width (an 'unsigned char' holds at most 255).
+struct large_pointee { char data[256]; };
+struct annotated_sized_ptr_narrow_unsigned_count {
+ struct large_pointee *buf __sized_by_or_null(byte_count);
+ unsigned char byte_count;
+};
+
+// SANITIZE-WITH-ATTR-LABEL: define dso_local noundef signext i8 @test_load_subscript_narrow_unsigned_count(
+// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
+// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB11:[0-9]+]], i64 [[TMP0]]) #[[ATTR6]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
+//
+// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local signext i8 @test_load_subscript_narrow_unsigned_count(
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[_ZTS13LARGE_POINTEEPTR_TBAA20:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [256 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa [[CHAR_TBAA17]]
+// NO-SANITIZE-WITH-ATTR-NEXT: ret i8 [[TMP1]]
+//
+// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local signext i8 @test_load_subscript_narrow_unsigned_count(
+// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[_ZTS13LARGE_POINTEEPTR_TBAA20:![0-9]+]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [256 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa [[CHAR_TBAA17]]
+// SANITIZE-WITHOUT-ATTR-NEXT: ret i8 [[TMP1]]
+//
+// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local signext i8 @test_load_subscript_narrow_unsigned_count(
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[_ZTS13LARGE_POINTEEPTR_TBAA20:![0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [256 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa [[CHAR_TBAA17]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i8 [[TMP1]]
+//
+char test_load_subscript_narrow_unsigned_count(struct annotated_sized_ptr_narrow_unsigned_count *p, int index) {
+ return p->buf[index].data[0];
+}
+
+// Signed count: the element size (200) is within the count field's bit width
+// but exceeds its signed range (a 'signed char' holds at most 127) -- a case
+// the unsigned test above does not cover.
+struct midsize_pointee { char data[200]; };
+struct annotated_sized_ptr_narrow_signed_count {
+ struct midsize_pointee *buf __sized_by_or_null(byte_count);
+ signed char byte_count;
+};
+
+// SANITIZE-WITH-ATTR-LABEL: define dso_local noundef signext i8 @test_load_subscript_narrow_signed_count(
+// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
+// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB13:[0-9]+]], i64 [[TMP0]]) #[[ATTR6]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
+//
+// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local signext i8 @test_load_subscript_narrow_signed_count(
+// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[_ZTS15MIDSIZE_POINTEEPTR_TBAA23:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [200 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa [[CHAR_TBAA17]]
+// NO-SANITIZE-WITH-ATTR-NEXT: ret i8 [[TMP1]]
+//
+// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local signext i8 @test_load_subscript_narrow_signed_count(
+// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[_ZTS15MIDSIZE_POINTEEPTR_TBAA23:![0-9]+]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [200 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa [[CHAR_TBAA17]]
+// SANITIZE-WITHOUT-ATTR-NEXT: ret i8 [[TMP1]]
+//
+// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local signext i8 @test_load_subscript_narrow_signed_count(
+// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[_ZTS15MIDSIZE_POINTEEPTR_TBAA23:![0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [200 x i8], ptr [[TMP0]], i64 [[IDXPROM]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1, !tbaa [[CHAR_TBAA17]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i8 [[TMP1]]
+//
+char test_load_subscript_narrow_signed_count(struct annotated_sized_ptr_narrow_signed_count *p, int index) {
+ return p->buf[index].data[0];
+}
+
struct annotated_sized_ptr {
unsigned long flags;
void *buf __sized_by_or_null(ptr_count);
@@ -367,7 +465,7 @@ struct annotated_sized_ptr {
// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[ANYPTR_TBAA20:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[ANYPTR_TBAA26:![0-9]+]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
@@ -405,7 +503,7 @@ size_t test_bdos_of_pointer(struct annotated_sized_ptr *p) {
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB11:[0-9]+]], i64 [[TMP6]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB15:[0-9]+]], i64 [[TMP6]]) #[[ATTR6]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[CONT8]]:
// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[DOTCOUNTED_BY_LOAD]] to i64
@@ -419,7 +517,7 @@ size_t test_bdos_of_pointer(struct annotated_sized_ptr *p) {
// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[ANYPTR_TBAA20]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[ANYPTR_TBAA26]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
@@ -463,7 +561,7 @@ size_t test_bdos_of_element_address(struct annotated_sized_ptr *p, int index) {
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT10:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB12:[0-9]+]], i64 [[TMP7]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB16:[0-9]+]], i64 [[TMP7]]) #[[ATTR6]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[CONT10]]:
// SANITIZE-WITH-ATTR-NEXT: ret i64 -1
@@ -515,7 +613,7 @@ struct annotated_sized_ptr_non_byte_sized_pointee {
// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA22:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA28:![0-9]+]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
@@ -554,7 +652,7 @@ size_t test_bdos_of_pointer_multibyte_pointee(struct annotated_sized_ptr_non_byt
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB14:[0-9]+]], i64 [[TMP7]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB18:[0-9]+]], i64 [[TMP7]]) #[[ATTR6]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[CONT8]]:
// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[DOTCOUNTED_BY_LOAD]] to i64
@@ -569,7 +667,7 @@ size_t test_bdos_of_pointer_multibyte_pointee(struct annotated_sized_ptr_non_byt
// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA22]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS3FOOPTR_TBAA28]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
@@ -627,7 +725,7 @@ struct annotated_sized_ptr_incomplete {
// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS13INCOMPLETE_TYPTR_TBAA24:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS13INCOMPLETE_TYPTR_TBAA30:![0-9]+]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
@@ -665,7 +763,7 @@ size_t test_bdos_of_pointer_incomplete_pointee(struct annotated_sized_ptr_incomp
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB16:[0-9]+]], i64 [[TMP6]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB20:[0-9]+]], i64 [[TMP6]]) #[[ATTR6]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[CONT8]]:
// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[DOTCOUNTED_BY_LOAD]] to i64
@@ -679,7 +777,7 @@ size_t test_bdos_of_pointer_incomplete_pointee(struct annotated_sized_ptr_incomp
// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS13INCOMPLETE_TYPTR_TBAA24]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[_ZTS13INCOMPLETE_TYPTR_TBAA30]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
@@ -722,7 +820,7 @@ struct annotated_volatile_ptr {
void take_ptr_with_size(void *p __attribute__((pass_dynamic_object_size(0))));
// SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i64 @test_bdos_of_volatile_pointer(
-// SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readnone captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
+// SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readnone captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
// SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// SANITIZE-WITH-ATTR-NEXT: ret i64 -1
//
@@ -760,13 +858,13 @@ size_t test_bdos_of_volatile_pointer(struct annotated_volatile_ptr *p) {
// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = tail call i32 @llvm.smax.i32(i32 [[COUNTED_BY_LOAD]], i32 0)
// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext nneg i32 [[TMP2]] to i64
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP3]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef [[TMP4]]) #[[ATTR6:[0-9]+]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef [[TMP4]]) #[[ATTR7:[0-9]+]]
// SANITIZE-WITH-ATTR-NEXT: ret void
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_pointer(
// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA27:![0-9]+]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA33:![0-9]+]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
@@ -779,14 +877,14 @@ size_t test_bdos_of_volatile_pointer(struct annotated_volatile_ptr *p) {
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_pointer(
// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
-// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20:![0-9]+]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA26:![0-9]+]]
// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef -1) #[[ATTR3:[0-9]+]]
// SANITIZE-WITHOUT-ATTR-NEXT: ret void
//
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_pointer(
// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
-// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20:![0-9]+]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA26:![0-9]+]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[TMP0]], i64 noundef -1) #[[ATTR6:[0-9]+]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
//
@@ -814,7 +912,7 @@ void test_pass_dynamic_object_size_of_pointer(struct annotated_volatile_ptr *p)
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP5]], label %[[CONT9:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB17:[0-9]+]], i64 [[TMP6]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB21:[0-9]+]], i64 [[TMP6]]) #[[ATTR6]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[CONT9]]:
// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[DOTCOUNTED_BY_LOAD]] to i64
@@ -825,19 +923,19 @@ void test_pass_dynamic_object_size_of_pointer(struct annotated_volatile_ptr *p)
// SANITIZE-WITH-ATTR-NEXT: [[COUNT_OR_NULL:%.*]] = select i1 [[TMP8]], i64 0, i64 [[COUNT]]
// SANITIZE-WITH-ATTR-NEXT: [[RESULT:%.*]] = sub nsw i64 [[COUNT_OR_NULL]], [[IDXPROM]]
// SANITIZE-WITH-ATTR-NEXT: [[TMP9:%.*]] = tail call i64 @llvm.smax.i64(i64 [[RESULT]], i64 0)
-// SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef [[TMP9]]) #[[ATTR6]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef [[TMP9]]) #[[ATTR7]]
// SANITIZE-WITH-ATTR-NEXT: ret void
//
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_element_address(
// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR4]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA27]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA33]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDXPROM]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[COUNTED_BY_LOAD]] to i64
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA27]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA33]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP1]], null
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNT_OR_NULL:%.*]] = select i1 [[TMP2]], i64 0, i64 [[COUNT]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[RESULT:%.*]] = sub nsw i64 [[COUNT_OR_NULL]], [[IDXPROM]]
@@ -851,7 +949,7 @@ void test_pass_dynamic_object_size_of_pointer(struct annotated_volatile_ptr *p)
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_element_address(
// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
// SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
-// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20]]
+// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA26]]
// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDXPROM]]
// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef -1) #[[ATTR3]]
@@ -860,7 +958,7 @@ void test_pass_dynamic_object_size_of_pointer(struct annotated_volatile_ptr *p)
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test_pass_dynamic_object_size_of_element_address(
// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef captures(address) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR4]] {
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]]
-// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA20]]
+// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load volatile ptr, ptr [[P]], align 8, !tbaa [[INTPTR_TBAA26]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[IDXPROM]]
// NO-SANITIZE-WITHOUT-ATTR-NEXT: tail call void @take_ptr_with_size(ptr noundef [[ARRAYIDX]], i64 noundef -1) #[[ATTR6]]
@@ -888,7 +986,7 @@ void test_pass_dynamic_object_size_of_element_address(struct annotated_volatile_
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP6]], label %[[CONT8:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !prof [[PROF13]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[HANDLER_OUT_OF_BOUNDS]]:
// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META12]]
-// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB19:[0-9]+]], i64 [[TMP7]]) #[[ATTR5]], !nosanitize [[META12]]
+// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB23:[0-9]+]], i64 [[TMP7]]) #[[ATTR6]], !nosanitize [[META12]]
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META12]]
// SANITIZE-WITH-ATTR: [[CONT8]]:
// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[DOTCOUNTED_BY_LOAD]] to i64
@@ -903,7 +1001,7 @@ void test_pass_dynamic_object_size_of_element_address(struct annotated_volatile_
// NO-SANITIZE-WITH-ATTR-SAME: ptr nofree noundef readonly captures(none) [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
// NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[BUF:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
-// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[ANYPTR_TBAA20]]
+// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[BUF]], align 8, !tbaa [[ANYPTR_TBAA26]]
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 16
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i32, ptr [[COUNTED_BY_GEP]], align 8
@@ -979,16 +1077,22 @@ size_t test_bdos_of_element_address_through_widening_cast(struct annotated_sized
// NO-SANITIZE-WITH-ATTR: [[CHAR_TBAA17]] = !{[[META4]], [[META4]], i64 0}
// NO-SANITIZE-WITH-ATTR: [[_ZTS3FOOPTR_TBAA18]] = !{[[META19:![0-9]+]], [[META9]], i64 8}
// NO-SANITIZE-WITH-ATTR: [[META19]] = !{!"annotated_sized_ptr_pow2_unsigned_count", [[META8]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
-// NO-SANITIZE-WITH-ATTR: [[ANYPTR_TBAA20]] = !{[[META21:![0-9]+]], [[META11]], i64 8}
-// NO-SANITIZE-WITH-ATTR: [[META21]] = !{!"annotated_sized_ptr", [[META8]], i64 0, [[META11]], i64 8, [[META3]], i64 16}
-// NO-SANITIZE-WITH-ATTR: [[_ZTS3FOOPTR_TBAA22]] = !{[[META23:![0-9]+]], [[META13]], i64 8}
-// NO-SANITIZE-WITH-ATTR: [[META23]] = !{!"annotated_sized_ptr_non_byte_sized_pointee", [[META8]], i64 0, [[META13]], i64 8, [[META3]], i64 16}
-// NO-SANITIZE-WITH-ATTR: [[_ZTS13INCOMPLETE_TYPTR_TBAA24]] = !{[[META25:![0-9]+]], [[META26:![0-9]+]], i64 8}
-// NO-SANITIZE-WITH-ATTR: [[META25]] = !{!"annotated_sized_ptr_incomplete", [[META8]], i64 0, [[META26]], i64 8, [[META3]], i64 16}
-// NO-SANITIZE-WITH-ATTR: [[META26]] = !{!"p1 _ZTS13incomplete_ty", [[META11]], i64 0}
-// NO-SANITIZE-WITH-ATTR: [[INTPTR_TBAA27]] = !{[[META28:![0-9]+]], [[META29:![0-9]+]], i64 0}
-// NO-SANITIZE-WITH-ATTR: [[META28]] = !{!"annotated_volatile_ptr", [[META29]], i64 0, [[META3]], i64 8}
-// NO-SANITIZE-WITH-ATTR: [[META29]] = !{!"p1 int", [[META11]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[_ZTS13LARGE_POINTEEPTR_TBAA20]] = !{[[META21:![0-9]+]], [[META22:![0-9]+]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[META21]] = !{!"annotated_sized_ptr_narrow_unsigned_count", [[META22]], i64 0, [[META4]], i64 8}
+// NO-SANITIZE-WITH-ATTR: [[META22]] = !{!"p1 _ZTS13large_pointee", [[META11]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[_ZTS15MIDSIZE_POINTEEPTR_TBAA23]] = !{[[META24:![0-9]+]], [[META25:![0-9]+]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[META24]] = !{!"annotated_sized_ptr_narrow_signed_count", [[META25]], i64 0, [[META4]], i64 8}
+// NO-SANITIZE-WITH-ATTR: [[META25]] = !{!"p1 _ZTS15midsize_pointee", [[META11]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[ANYPTR_TBAA26]] = !{[[META27:![0-9]+]], [[META11]], i64 8}
+// NO-SANITIZE-WITH-ATTR: [[META27]] = !{!"annotated_sized_ptr", [[META8]], i64 0, [[META11]], i64 8, [[META3]], i64 16}
+// NO-SANITIZE-WITH-ATTR: [[_ZTS3FOOPTR_TBAA28]] = !{[[META29:![0-9]+]], [[META13]], i64 8}
+// NO-SANITIZE-WITH-ATTR: [[META29]] = !{!"annotated_sized_ptr_non_byte_sized_pointee", [[META8]], i64 0, [[META13]], i64 8, [[META3]], i64 16}
+// NO-SANITIZE-WITH-ATTR: [[_ZTS13INCOMPLETE_TYPTR_TBAA30]] = !{[[META31:![0-9]+]], [[META32:![0-9]+]], i64 8}
+// NO-SANITIZE-WITH-ATTR: [[META31]] = !{!"annotated_sized_ptr_incomplete", [[META8]], i64 0, [[META32]], i64 8, [[META3]], i64 16}
+// NO-SANITIZE-WITH-ATTR: [[META32]] = !{!"p1 _ZTS13incomplete_ty", [[META11]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[INTPTR_TBAA33]] = !{[[META34:![0-9]+]], [[META35:![0-9]+]], i64 0}
+// NO-SANITIZE-WITH-ATTR: [[META34]] = !{!"annotated_volatile_ptr", [[META35]], i64 0, [[META3]], i64 8}
+// NO-SANITIZE-WITH-ATTR: [[META35]] = !{!"p1 int", [[META11]], i64 0}
//.
// SANITIZE-WITHOUT-ATTR: [[META3:![0-9]+]] = !{!"int", [[META4:![0-9]+]], i64 0}
// SANITIZE-WITHOUT-ATTR: [[META4]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}
@@ -1007,9 +1111,15 @@ size_t test_bdos_of_element_address_through_widening_cast(struct annotated_sized
// SANITIZE-WITHOUT-ATTR: [[CHAR_TBAA17]] = !{[[META4]], [[META4]], i64 0}
// SANITIZE-WITHOUT-ATTR: [[_ZTS3FOOPTR_TBAA18]] = !{[[META19:![0-9]+]], [[META9]], i64 8}
// SANITIZE-WITHOUT-ATTR: [[META19]] = !{!"annotated_sized_ptr_pow2_unsigned_count", [[META8]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
-// SANITIZE-WITHOUT-ATTR: [[INTPTR_TBAA20]] = !{[[META21:![0-9]+]], [[META22:![0-9]+]], i64 0}
-// SANITIZE-WITHOUT-ATTR: [[META21]] = !{!"annotated_volatile_ptr", [[META22]], i64 0, [[META3]], i64 8}
-// SANITIZE-WITHOUT-ATTR: [[META22]] = !{!"p1 int", [[META11]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[_ZTS13LARGE_POINTEEPTR_TBAA20]] = !{[[META21:![0-9]+]], [[META22:![0-9]+]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[META21]] = !{!"annotated_sized_ptr_narrow_unsigned_count", [[META22]], i64 0, [[META4]], i64 8}
+// SANITIZE-WITHOUT-ATTR: [[META22]] = !{!"p1 _ZTS13large_pointee", [[META11]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[_ZTS15MIDSIZE_POINTEEPTR_TBAA23]] = !{[[META24:![0-9]+]], [[META25:![0-9]+]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[META24]] = !{!"annotated_sized_ptr_narrow_signed_count", [[META25]], i64 0, [[META4]], i64 8}
+// SANITIZE-WITHOUT-ATTR: [[META25]] = !{!"p1 _ZTS15midsize_pointee", [[META11]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[INTPTR_TBAA26]] = !{[[META27:![0-9]+]], [[META28:![0-9]+]], i64 0}
+// SANITIZE-WITHOUT-ATTR: [[META27]] = !{!"annotated_volatile_ptr", [[META28]], i64 0, [[META3]], i64 8}
+// SANITIZE-WITHOUT-ATTR: [[META28]] = !{!"p1 int", [[META11]], i64 0}
//.
// NO-SANITIZE-WITHOUT-ATTR: [[META3:![0-9]+]] = !{!"int", [[META4:![0-9]+]], i64 0}
// NO-SANITIZE-WITHOUT-ATTR: [[META4]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}
@@ -1028,7 +1138,13 @@ size_t test_bdos_of_element_address_through_widening_cast(struct annotated_sized
// NO-SANITIZE-WITHOUT-ATTR: [[CHAR_TBAA17]] = !{[[META4]], [[META4]], i64 0}
// NO-SANITIZE-WITHOUT-ATTR: [[_ZTS3FOOPTR_TBAA18]] = !{[[META19:![0-9]+]], [[META9]], i64 8}
// NO-SANITIZE-WITHOUT-ATTR: [[META19]] = !{!"annotated_sized_ptr_pow2_unsigned_count", [[META8]], i64 0, [[META9]], i64 8, [[META3]], i64 16}
-// NO-SANITIZE-WITHOUT-ATTR: [[INTPTR_TBAA20]] = !{[[META21:![0-9]+]], [[META22:![0-9]+]], i64 0}
-// NO-SANITIZE-WITHOUT-ATTR: [[META21]] = !{!"annotated_volatile_ptr", [[META22]], i64 0, [[META3]], i64 8}
-// NO-SANITIZE-WITHOUT-ATTR: [[META22]] = !{!"p1 int", [[META11]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[_ZTS13LARGE_POINTEEPTR_TBAA20]] = !{[[META21:![0-9]+]], [[META22:![0-9]+]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[META21]] = !{!"annotated_sized_ptr_narrow_unsigned_count", [[META22]], i64 0, [[META4]], i64 8}
+// NO-SANITIZE-WITHOUT-ATTR: [[META22]] = !{!"p1 _ZTS13large_pointee", [[META11]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[_ZTS15MIDSIZE_POINTEEPTR_TBAA23]] = !{[[META24:![0-9]+]], [[META25:![0-9]+]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[META24]] = !{!"annotated_sized_ptr_narrow_signed_count", [[META25]], i64 0, [[META4]], i64 8}
+// NO-SANITIZE-WITHOUT-ATTR: [[META25]] = !{!"p1 _ZTS15midsize_pointee", [[META11]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[INTPTR_TBAA26]] = !{[[META27:![0-9]+]], [[META28:![0-9]+]], i64 0}
+// NO-SANITIZE-WITHOUT-ATTR: [[META27]] = !{!"annotated_volatile_ptr", [[META28]], i64 0, [[META3]], i64 8}
+// NO-SANITIZE-WITHOUT-ATTR: [[META28]] = !{!"p1 int", [[META11]], i64 0}
//.
More information about the cfe-commits
mailing list