| // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6 | |
| // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -DWITH_ATTRS -Wall -fsanitize=array-bounds,object-size,local-bounds -fstrict-flex-arrays=3 -fexperimental-late-parse-attributes -emit-llvm -o - %s | FileCheck --check-prefix=SANITIZE-WITH-ATTR %s | |
| // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -DWITH_ATTRS -Wall -fstrict-flex-arrays=3 -fexperimental-late-parse-attributes -emit-llvm -o - %s | FileCheck --check-prefix=NO-SANITIZE-WITH-ATTR %s | |
| // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -Wall -fsanitize=array-bounds,object-size,local-bounds -fstrict-flex-arrays=3 -fexperimental-late-parse-attributes -emit-llvm -o - %s | FileCheck --check-prefix=SANITIZE-WITHOUT-ATTR %s | |
| // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -Wall -fstrict-flex-arrays=3 -fexperimental-late-parse-attributes -emit-llvm -o - %s | FileCheck --check-prefix=NO-SANITIZE-WITHOUT-ATTR %s | |
| // Each test here shares its name with the corresponding test in | |
| // attr-counted-by-for-pointers.c and exercises the same scenario, but with the | |
| // __counted_by_or_null attribute. Unlike __counted_by, a null pointer is | |
| // allowed regardless of the count, so __bdos computes the size as if the count | |
| // were 0 when the pointer is null. | |
| #if !__has_attribute(counted_by_or_null) | |
| #error "has attribute broken" | |
| #endif | |
| #ifdef WITH_ATTRS | |
| #define __counted_by_or_null(member) __attribute__((__counted_by_or_null__(member))) | |
| #else | |
| #define __counted_by_or_null(member) | |
| #endif | |
| #define __bdos(P) __builtin_dynamic_object_size(P, 0) | |
| typedef long unsigned int size_t; | |
| struct foo { size_t field; }; | |
| struct annotated_ptr { | |
| unsigned long flags; | |
| struct foo **buf __counted_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:%.*]] = 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 %[[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: [[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]+]] | |
| // 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 %[[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: [[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]] | |
| // 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 %[[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: [[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]] | |
| // 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 | |
| // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null | |
| // SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = shl nsw i64 [[COUNT]], 3 | |
| // SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = tail call i64 @llvm.smax.i64(i64 [[TMP2]], i64 0) | |
| // SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP3]] | |
| // 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 #[[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]] | |
| // 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 | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = shl nsw i64 [[COUNT]], 3 | |
| // 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: 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]] { | |
| // 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 #[[ATTR1:[0-9]+]] { | |
| // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]] | |
| // NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 | |
| // | |
| size_t test_bdos_of_pointer(struct annotated_ptr *p) { | |
| return __bdos(p->buf); | |
| } | |
| // SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 0, 17179869177) i64 @test_bdos_of_pointer_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: [[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 | |
| // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null | |
| // SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = shl nsw i64 [[COUNT]], 3 | |
| // SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = tail call i64 @llvm.smax.i64(i64 [[TMP2]], i64 0) | |
| // SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP3]] | |
| // 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 #[[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]] | |
| // 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 | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = shl nsw i64 [[COUNT]], 3 | |
| // 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: ret i64 [[TMP4]] | |
| // | |
| // SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_pointer_through_cast( | |
| // SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) 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_through_cast( | |
| // 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 | |
| // | |
| size_t test_bdos_of_pointer_through_cast(struct annotated_ptr *p, int index) { | |
| return __bdos((struct foo **)((char *)p->buf)); | |
| } | |
| // 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 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 %[[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: [[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 | |
| // 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: [[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 #[[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]] | |
| // 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 | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i32 [[COUNTED_BY_LOAD]] to i64 | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = shl nsw i64 [[COUNT]], 3 | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAY_SIZE:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP2]] | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[INDEX_SIZE:%.*]] = shl nsw i64 [[IDXPROM]], 3 | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[RESULT:%.*]] = sub nsw i64 [[ARRAY_SIZE]], [[INDEX_SIZE]] | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp sgt i64 [[RESULT]], -1 | |
| // 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: ret i64 [[TMP6]] | |
| // | |
| // SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_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: 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 #[[ATTR1]] { | |
| // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]] | |
| // NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 | |
| // | |
| size_t test_bdos_of_element_address(struct annotated_ptr *p, int index) { | |
| return __bdos(&p->buf[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: [[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 %[[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: [[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 #[[ATTR2:[0-9]+]] { | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]] | |
| // NO-SANITIZE-WITH-ATTR-NEXT: ret i64 -1 | |
| // | |
| // SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test_bdos_of_subscript_through_cast( | |
| // SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) 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_subscript_through_cast( | |
| // 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 | |
| // | |
| size_t test_bdos_of_subscript_through_cast(struct annotated_ptr *p, int index) { | |
| return __bdos(((struct foo **)(char *)p->buf)[index]); | |
| } | |
| struct pr151236_struct { | |
| int *a __counted_by_or_null(a_count); | |
| short a_count; | |
| }; | |
| // 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_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 | |
| // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl nsw i64 [[COUNT]], 2 | |
| // SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null | |
| // SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = tail call i64 @llvm.smax.i64(i64 [[TMP1]], i64 0) | |
| // SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = shl nuw nsw i64 [[TMP3]], 1 | |
| // SANITIZE-WITH-ATTR-NEXT: [[ADD:%.*]] = select i1 [[TMP2]], i64 0, i64 [[TMP4]] | |
| // 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 #[[ATTR1]] { | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]] | |
| // 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 | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null | |
| // 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:%.*]] = shl nuw nsw i64 [[TMP3]], 1 | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[ADD:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP4]] | |
| // NO-SANITIZE-WITH-ATTR-NEXT: ret i64 [[ADD]] | |
| // | |
| // SANITIZE-WITHOUT-ATTR-LABEL: define dso_local range(i64 0, -1) i64 @test_bdos_of_short_count_field( | |
| // SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] { | |
| // SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]] | |
| // 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 #[[ATTR1]] { | |
| // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]] | |
| // NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -2 | |
| // | |
| size_t test_bdos_of_short_count_field(struct pr151236_struct *p) { | |
| return __bdos(p->a) + __bdos((p->a)); | |
| } | |
| // 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_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 | |
| // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl nsw i64 [[COUNT]], 2 | |
| // SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null | |
| // SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = tail call i64 @llvm.smax.i64(i64 [[TMP1]], i64 0) | |
| // SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = shl nuw nsw i64 [[TMP3]], 1 | |
| // SANITIZE-WITH-ATTR-NEXT: [[ADD:%.*]] = select i1 [[TMP2]], i64 0, i64 [[TMP4]] | |
| // 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 #[[ATTR1]] { | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]] | |
| // 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 | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null | |
| // 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:%.*]] = shl nuw nsw i64 [[TMP3]], 1 | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[ADD:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP4]] | |
| // NO-SANITIZE-WITH-ATTR-NEXT: ret i64 [[ADD]] | |
| // | |
| // SANITIZE-WITHOUT-ATTR-LABEL: define dso_local range(i64 0, -1) i64 @test_bdos_of_short_count_field_through_cast( | |
| // SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] { | |
| // SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]] | |
| // 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 #[[ATTR1]] { | |
| // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]] | |
| // NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -2 | |
| // | |
| size_t test_bdos_of_short_count_field_through_cast(struct pr151236_struct *p) { | |
| return __bdos(p->a) + __bdos(((int *)p->a)); | |
| } | |
| // These use a pass_dynamic_object_size parameter with a volatile field to make | |
| // the number of pointer loads observable. A direct __bdos(p->buf) would not | |
| // work: like sizeof, it doesn't evaluate the operand if it would produce a | |
| // side-effect, which it does for a volatile pointer load, so it just bails to | |
| // the default. pass_dynamic_object_size instead computes the size from the | |
| // value the call already loaded to pass the argument. `volatile` prevents that | |
| // load from being CSE'd at -O2. | |
| struct annotated_volatile_ptr { | |
| int *volatile buf __counted_by_or_null(count); | |
| int count; | |
| }; | |
| 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-NEXT: [[ENTRY:.*:]] | |
| // 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 #[[ATTR3:[0-9]+]] { | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]] | |
| // NO-SANITIZE-WITH-ATTR-NEXT: ret i64 -1 | |
| // | |
| // SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i64 @test_bdos_of_volatile_pointer( | |
| // SANITIZE-WITHOUT-ATTR-SAME: ptr nofree noundef readnone captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { | |
| // SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]] | |
| // 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 #[[ATTR3:[0-9]+]] { | |
| // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]] | |
| // NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 | |
| // | |
| size_t test_bdos_of_volatile_pointer(struct annotated_volatile_ptr *p) { | |
| return __bdos(p->buf); | |
| } | |
| // | |
| // | |
| // | |
| // | |
| // Only one volatile load of the pointer should be emitted. | |
| // 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_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 | |
| // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null | |
| // SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = shl nsw i64 [[COUNT]], 2 | |
| // SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = tail call i64 @llvm.smax.i64(i64 [[TMP2]], i64 0) | |
| // 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: 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_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 | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null | |
| // 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]]) #[[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_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 #[[ATTR4:[0-9]+]] { | |
| // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]] | |
| // 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) { | |
| take_ptr_with_size(p->buf); | |
| } | |
| // The '&((cast) ptr->array)[idx]' form via pass_dynamic_object_size. | |
| // FIXME: for the _or_null variants the object-size null-check re-emits the | |
| // `ptr->array` load. Instead it should reuse the value. | |
| // 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_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 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: [[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: [[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: [[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: [[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 #[[ATTR4]] { | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[ENTRY:.*:]] | |
| // 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_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]] | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[RESULT:%.*]] = sub nsw i64 [[ARRAY_SIZE]], [[IDXPROM]] | |
| // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp sgt i64 [[RESULT]], -1 | |
| // 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]]) #[[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_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 #[[ATTR4]] { | |
| // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ENTRY:.*:]] | |
| // 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) #[[ATTR6]] | |
| // NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void | |
| // | |
| void test_pass_dynamic_object_size_of_element_address(struct annotated_volatile_ptr *p, int index) { | |
| take_ptr_with_size(&((char *)p->buf)[index]); | |
| } | |
| //. | |
| // 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: [[_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]] = !{!"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: [[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} | |
| // NO-SANITIZE-WITH-ATTR: [[META5]] = !{!"Simple C/C++ TBAA"} | |
| // 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: [[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: [[_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: [[_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} | |
| //. |