diff --git a/clang/test/CodeGen/attr-counted-by.c b/clang/test/CodeGen/attr-counted-by.c index 59e1b134850a9..b16c044869569 100644 --- a/clang/test/CodeGen/attr-counted-by.c +++ b/clang/test/CodeGen/attr-counted-by.c @@ -2481,3 +2481,62 @@ size_t test36() { size_t test37(struct annotated *ptr) { return __builtin_dynamic_object_size((1, 2, (4, 5, (7, 8, 9, (10, ptr->array)))), 1); } + +// Don't abort when a structure isn't forward declared. This was fixed in +// 160fb11. +// See https://github.com/clangbuiltlinux/linux/issues/2114 + +struct baz; + +struct foo { + unsigned short width; + struct bar *no_forward_decl; + struct baz *array[] __attribute__((__counted_by__(width))); +}; + +// SANITIZE-WITH-ATTR-LABEL: define dso_local ptr @test38( +// SANITIZE-WITH-ATTR-SAME: ptr noundef [[Q:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i16, ptr [[Q]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[DOTNOT:%.*]] = icmp eq i16 [[DOTCOUNTED_BY_LOAD]], 0 +// SANITIZE-WITH-ATTR-NEXT: br i1 [[DOTNOT]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], label [[CONT3:%.*]], !prof [[PROF8]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB55:[0-9]+]], i64 0) #[[ATTR8]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont3: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw i8, ptr [[Q]], i64 16 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAY]], align 8, !tbaa [[TBAA27:![0-9]+]] +// SANITIZE-WITH-ATTR-NEXT: ret ptr [[TMP0]] +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local ptr @test38( +// NO-SANITIZE-WITH-ATTR-SAME: ptr noundef readonly captures(none) [[Q:%.*]]) local_unnamed_addr #[[ATTR2]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw i8, ptr [[Q]], i64 16 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAY]], align 8, !tbaa [[TBAA24:![0-9]+]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret ptr [[TMP0]] +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local ptr @test38( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[Q:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i16, ptr [[Q]], align 4 +// SANITIZE-WITHOUT-ATTR-NEXT: [[DOTNOT:%.*]] = icmp eq i16 [[DOTCOUNTED_BY_LOAD]], 0 +// SANITIZE-WITHOUT-ATTR-NEXT: br i1 [[DOTNOT]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], label [[CONT3:%.*]], !prof [[PROF10]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR: handler.out_of_bounds: +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB23:[0-9]+]], i64 0) #[[ATTR8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR: cont3: +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw i8, ptr [[Q]], i64 16 +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAY]], align 8, !tbaa [[TBAA27:![0-9]+]] +// SANITIZE-WITHOUT-ATTR-NEXT: ret ptr [[TMP0]] +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local ptr @test38( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef readonly captures(none) [[Q:%.*]]) local_unnamed_addr #[[ATTR6]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw i8, ptr [[Q]], i64 16 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAY]], align 8, !tbaa [[TBAA24:![0-9]+]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret ptr [[TMP0]] +// +struct baz *test38(struct foo *q) +{ + return q->array[0]; +}