diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index c83ea966fdead..f46240c734ce3 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -945,7 +945,7 @@ CodeGenFunction::emitFlexibleArrayMemberSize(const Expr *E, unsigned Type, : Builder.CreateZExtOrTrunc(FAMSize, ResType); Value *Res = FAMSize; - if (const auto *DRE = dyn_cast(Base)) { + if (isa(Base)) { // The whole struct is specificed in the __bdos. const RecordDecl *OuterRD = CountedByFD->getDeclContext()->getOuterLexicalRecordContext(); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index a75f630e1a4c7..74469dc5c89bf 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -962,15 +962,36 @@ CodeGenFunction::BuildCountedByFieldExpr(const Expr *Base, // Find the outer struct expr (i.e. p in p->a.b.c.d). Expr *CountedByExpr = const_cast(Base)->IgnoreParenImpCasts(); + // Get the enclosing struct, but not the outermost enclosing struct. + const DeclContext *DC = CountedByVD->getLexicalDeclContext(); + const auto *CountedByRD = dyn_cast(DC); + if (!CountedByRD) + return nullptr; + // Work our way up the expression until we reach the DeclRefExpr. - while (!isa(CountedByExpr)) - if (const auto *ME = dyn_cast(CountedByExpr)) - CountedByExpr = ME->getBase()->IgnoreParenImpCasts(); + while (auto *ME = dyn_cast(CountedByExpr)) { + CountedByExpr = ME->getBase()->IgnoreImpCasts(); + + // Use the base of an ArraySubscriptExpr. + while (auto *ASE = dyn_cast(CountedByExpr)) + CountedByExpr = ASE->getBase()->IgnoreImpCasts(); + + QualType Ty = CountedByExpr->getType(); + if (Ty->isPointerType()) + Ty = Ty->getPointeeType(); + + // Stop when we reach the struct containing the counted_by field. + if (CountedByRD == Ty->getAsRecordDecl()) + break; + } + + ASTContext &Ctx = getContext(); - // Add back an implicit cast to create the required pr-value. - CountedByExpr = ImplicitCastExpr::Create( - getContext(), CountedByExpr->getType(), CK_LValueToRValue, CountedByExpr, - nullptr, VK_PRValue, FPOptionsOverride()); + if (!CountedByExpr->isPRValue()) + // Add an implicit cast to create the required pr-value. + CountedByExpr = ImplicitCastExpr::Create( + Ctx, CountedByExpr->getType(), CK_LValueToRValue, CountedByExpr, + nullptr, VK_PRValue, FPOptionsOverride()); if (const auto *IFD = dyn_cast(CountedByVD)) { // The counted_by field is inside an anonymous struct / union. The @@ -978,15 +999,13 @@ CodeGenFunction::BuildCountedByFieldExpr(const Expr *Base, // easily. (Yay!) for (NamedDecl *ND : IFD->chain()) { auto *VD = cast(ND); - CountedByExpr = - MemberExpr::CreateImplicit(getContext(), CountedByExpr, - CountedByExpr->getType()->isPointerType(), - VD, VD->getType(), VK_LValue, OK_Ordinary); + CountedByExpr = MemberExpr::CreateImplicit( + Ctx, CountedByExpr, CountedByExpr->getType()->isPointerType(), VD, + VD->getType(), VK_LValue, OK_Ordinary); } } else { CountedByExpr = MemberExpr::CreateImplicit( - getContext(), const_cast(CountedByExpr), - CountedByExpr->getType()->isPointerType(), + Ctx, CountedByExpr, CountedByExpr->getType()->isPointerType(), const_cast(CountedByVD), CountedByVD->getType(), VK_LValue, OK_Ordinary); } diff --git a/clang/test/CodeGen/attr-counted-by.c b/clang/test/CodeGen/attr-counted-by.c index 5cefff0e6f1cd..6826675ee92f1 100644 --- a/clang/test/CodeGen/attr-counted-by.c +++ b/clang/test/CodeGen/attr-counted-by.c @@ -61,14 +61,14 @@ struct anon_struct { // SANITIZE-WITH-ATTR-NEXT: entry: // SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2:![0-9]+]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP1]], [[TMP2]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label [[CONT7:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7:![0-9]+]], !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize [[META6:![0-9]+]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP1]], [[TMP2]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label [[CONT7:%.*]], 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 !6 -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 [[TMP4]]) #[[ATTR4:[0-9]+]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize !6 +// 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]]) #[[ATTR7:[0-9]+]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] // SANITIZE-WITH-ATTR: cont7: // SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[TMP1]] // SANITIZE-WITH-ATTR-NEXT: store i32 [[VAL]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] @@ -107,12 +107,12 @@ void test1(struct annotated *p, int index, int val) { // SANITIZE-WITH-ATTR-NEXT: entry: // SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[TMP1]], [[INDEX]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label [[CONT12:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[TMP1]], [[INDEX]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label [[CONT12:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize [[META6]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 [[INDEX]]) #[[ATTR4]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 [[INDEX]]) #[[ATTR7]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] // SANITIZE-WITH-ATTR: cont12: // SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]] // SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[TMP0]], 0 @@ -156,12 +156,12 @@ void test2(struct annotated *p, size_t index) { // SANITIZE-WITH-ATTR-NEXT: entry: // SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[TMP1]], [[INDEX]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label [[CONT12:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[TMP1]], [[INDEX]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label [[CONT12:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize [[META6]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 [[INDEX]]) #[[ATTR4]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 [[INDEX]]) #[[ATTR7]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] // SANITIZE-WITH-ATTR: cont12: // SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]] // SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[TMP0]], 0 @@ -211,14 +211,14 @@ void test3(struct annotated *p, size_t index) { // SANITIZE-WITH-ATTR-NEXT: entry: // SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP1]], [[TMP2]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label [[CONT13:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP1]], [[TMP2]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label [[CONT13:%.*]], 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 !6 -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB6:[0-9]+]], i64 [[TMP4]]) #[[ATTR4]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize !6 +// 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 @[[GLOB6:[0-9]+]], i64 [[TMP4]]) #[[ATTR7]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] // SANITIZE-WITH-ATTR: cont13: // SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[TMP0]], 2 // SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = shl i32 [[TMP0]], 2 @@ -229,14 +229,14 @@ void test3(struct annotated *p, size_t index) { // SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV3]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] // SANITIZE-WITH-ATTR-NEXT: [[TMP9:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]] // SANITIZE-WITH-ATTR-NEXT: [[ADD:%.*]] = add nsw i32 [[INDEX]], 1 -// SANITIZE-WITH-ATTR-NEXT: [[TMP10:%.*]] = sext i32 [[ADD]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: [[TMP11:%.*]] = zext i32 [[TMP9]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: [[TMP12:%.*]] = icmp ult i64 [[TMP10]], [[TMP11]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP12]], label [[CONT34:%.*]], label [[HANDLER_OUT_OF_BOUNDS29:%.*]], !prof [[PROF7]], !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP10:%.*]] = sext i32 [[ADD]] to i64, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP11:%.*]] = zext i32 [[TMP9]] to i64, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP12:%.*]] = icmp ult i64 [[TMP10]], [[TMP11]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP12]], label [[CONT34:%.*]], label [[HANDLER_OUT_OF_BOUNDS29:%.*]], !prof [[PROF7]], !nosanitize [[META6]] // SANITIZE-WITH-ATTR: handler.out_of_bounds29: -// SANITIZE-WITH-ATTR-NEXT: [[TMP13:%.*]] = zext i32 [[ADD]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB7:[0-9]+]], i64 [[TMP13]]) #[[ATTR4]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP13:%.*]] = zext i32 [[ADD]] to i64, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB7:[0-9]+]], i64 [[TMP13]]) #[[ATTR7]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] // SANITIZE-WITH-ATTR: cont34: // SANITIZE-WITH-ATTR-NEXT: [[TMP14:%.*]] = icmp sgt i32 [[TMP9]], 3 // SANITIZE-WITH-ATTR-NEXT: [[TMP15:%.*]] = shl i32 [[TMP9]], 2 @@ -247,14 +247,14 @@ void test3(struct annotated *p, size_t index) { // SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV20]], ptr [[ARRAYIDX32]], align 4, !tbaa [[TBAA2]] // SANITIZE-WITH-ATTR-NEXT: [[TMP18:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]] // SANITIZE-WITH-ATTR-NEXT: [[ADD45:%.*]] = add nsw i32 [[INDEX]], 2 -// SANITIZE-WITH-ATTR-NEXT: [[TMP19:%.*]] = sext i32 [[ADD45]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: [[TMP20:%.*]] = zext i32 [[TMP18]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: [[TMP21:%.*]] = icmp ult i64 [[TMP19]], [[TMP20]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP21]], label [[CONT56:%.*]], label [[HANDLER_OUT_OF_BOUNDS51:%.*]], !prof [[PROF7]], !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP19:%.*]] = sext i32 [[ADD45]] to i64, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP20:%.*]] = zext i32 [[TMP18]] to i64, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP21:%.*]] = icmp ult i64 [[TMP19]], [[TMP20]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP21]], label [[CONT56:%.*]], label [[HANDLER_OUT_OF_BOUNDS51:%.*]], !prof [[PROF7]], !nosanitize [[META6]] // SANITIZE-WITH-ATTR: handler.out_of_bounds51: -// SANITIZE-WITH-ATTR-NEXT: [[TMP22:%.*]] = zext i32 [[ADD45]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB8:[0-9]+]], i64 [[TMP22]]) #[[ATTR4]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP22:%.*]] = zext i32 [[ADD45]] to i64, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB8:[0-9]+]], i64 [[TMP22]]) #[[ATTR7]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] // SANITIZE-WITH-ATTR: cont56: // SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX54:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[TMP19]] // SANITIZE-WITH-ATTR-NEXT: [[TMP23:%.*]] = sub nsw i32 [[TMP18]], [[FAM_IDX]] @@ -346,13 +346,13 @@ void test4(struct annotated *p, int index, int fam_idx) { // SANITIZE-WITH-ATTR-NEXT: entry: // SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 0, i32 1 // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i64, ptr [[COUNT]], align 8, !tbaa [[TBAA8:![0-9]+]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[TMP0]], [[TMP1]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label [[CONT12:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[TMP0]], [[TMP1]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label [[CONT12:%.*]], 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 !6 -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB9:[0-9]+]], i64 [[TMP3]]) #[[ATTR4]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize !6 +// 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 @[[GLOB9:[0-9]+]], i64 [[TMP3]]) #[[ATTR7]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] // SANITIZE-WITH-ATTR: cont12: // SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT]], ptr [[P]], i64 1 // SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[TMP1]] @@ -407,13 +407,13 @@ void test5(struct anon_struct *p, int index) { // SANITIZE-WITH-ATTR-NEXT: entry: // SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 0, i32 1 // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i64, ptr [[COUNT]], align 8, !tbaa [[TBAA8]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[TMP0]], [[TMP1]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label [[CONT12:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[TMP0]], [[TMP1]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label [[CONT12:%.*]], 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 !6 -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB10:[0-9]+]], i64 [[TMP3]]) #[[ATTR4]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize !6 +// 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 @[[GLOB10:[0-9]+]], i64 [[TMP3]]) #[[ATTR7]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] // SANITIZE-WITH-ATTR: cont12: // SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT]], ptr [[P]], i64 1 // SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[TMP1]] @@ -468,14 +468,14 @@ void test6(struct anon_struct *p, int index) { // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 8 // SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], 255 // SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ugt i32 [[TMP2]], [[INDEX]] -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label [[CONT23:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label [[CONT23:%.*]], 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 !6 -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB12:[0-9]+]], i64 [[TMP4]]) #[[ATTR4]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize !6 +// 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]]) #[[ATTR7]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] // SANITIZE-WITH-ATTR: cont23: // SANITIZE-WITH-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9 -// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize [[META6]] // SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[TMP5]] // SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[TMP1]], 0 // SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = tail call i32 @llvm.smax.i32(i32 [[TMP1]], i32 12) @@ -529,13 +529,13 @@ void test7(struct union_of_fams *p, int index) { // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1 // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[TMP0]], align 8, !tbaa [[TBAA10]] // SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i64 -// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP3]], [[TMP2]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP4]], label [[CONT24:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP3]], [[TMP2]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP4]], label [[CONT24:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize [[META6]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB13:[0-9]+]], i64 [[TMP5]]) #[[ATTR4]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = 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 [[TMP5]]) #[[ATTR7]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] // SANITIZE-WITH-ATTR: cont24: // SANITIZE-WITH-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9 // SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[TMP3]] @@ -582,14 +582,14 @@ void test8(struct union_of_fams *p, int index) { // SANITIZE-WITH-ATTR-NEXT: entry: // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1 // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 8, !tbaa [[TBAA10]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[TMP1]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP2]], [[TMP3]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP4]], label [[CONT24:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[TMP1]] to i64, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP2]], [[TMP3]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP4]], label [[CONT24:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize [[META6]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB14:[0-9]+]], i64 [[TMP5]]) #[[ATTR4]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = 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 [[TMP5]]) #[[ATTR7]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] // SANITIZE-WITH-ATTR: cont24: // SANITIZE-WITH-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 // SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[TMP2]] @@ -644,14 +644,14 @@ void test9(struct union_of_fams *p, int index) { // SANITIZE-WITH-ATTR-NEXT: entry: // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1 // SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 8, !tbaa [[TBAA10]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[TMP1]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP2]], [[TMP3]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP4]], label [[CONT24:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[TMP1]] to i64, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP2]], [[TMP3]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP4]], label [[CONT24:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize [[META6]] // SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB15:[0-9]+]], i64 [[TMP5]]) #[[ATTR4]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB15:[0-9]+]], i64 [[TMP5]]) #[[ATTR7]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] // SANITIZE-WITH-ATTR: cont24: // SANITIZE-WITH-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 // SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[TMP2]] @@ -700,14 +700,14 @@ void test10(struct union_of_fams *p, int index) { // SANITIZE-WITH-ATTR-NEXT: entry: // SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 // SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP1]], [[TMP2]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label [[CONT7:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP1]], [[TMP2]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label [[CONT7:%.*]], 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 !6 -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB16:[0-9]+]], i64 [[TMP4]]) #[[ATTR4]], !nosanitize !6 -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize !6 +// 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 @[[GLOB16:[0-9]+]], i64 [[TMP4]]) #[[ATTR7]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] // SANITIZE-WITH-ATTR: cont7: // SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[TMP1]] // SANITIZE-WITH-ATTR-NEXT: store i32 4, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] @@ -740,3 +740,178 @@ void test10(struct union_of_fams *p, int index) { void test11(struct annotated *p, int index) { p->array[index] = __builtin_dynamic_object_size(&p->count, 1); } + +struct { + struct { + struct { + int num_entries; + }; + }; + int entries[] __attribute__((__counted_by__(num_entries))); +} test12_foo; + +struct hang { + int entries[6]; +} test12_bar; + +int test12_a, test12_b; + +// PR73168 - Hanging. +// SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test12( +// SANITIZE-WITH-ATTR-SAME: i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[BAZ:%.*]] = alloca [[STRUCT_HANG:%.*]], align 4 +// SANITIZE-WITH-ATTR-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[BAZ]]) #[[ATTR8:[0-9]+]] +// SANITIZE-WITH-ATTR-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 4 dereferenceable(24) [[BAZ]], ptr noundef nonnull align 4 dereferenceable(24) @test12_bar, i64 24, i1 false), !tbaa.struct [[TBAA_STRUCT11:![0-9]+]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp ult i32 [[INDEX]], 6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[INDEX]] to i64 +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP0]], label [[CONT:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB18:[0-9]+]], i64 [[TMP1]]) #[[ATTR7]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR: cont: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [6 x i32], ptr [[BAZ]], i64 0, i64 [[TMP1]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// SANITIZE-WITH-ATTR-NEXT: store i32 [[TMP2]], ptr @test12_b, align 4, !tbaa [[TBAA2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = load i32, ptr @test12_foo, align 4, !tbaa [[TBAA12:![0-9]+]] +// SANITIZE-WITH-ATTR-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP3]], 0 +// SANITIZE-WITH-ATTR-NEXT: br i1 [[DOTNOT]], label [[HANDLER_OUT_OF_BOUNDS12:%.*]], label [[HANDLER_TYPE_MISMATCH14:%.*]], !prof [[PROF15:![0-9]+]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds12: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB19:[0-9]+]], i64 0) #[[ATTR7]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR: handler.type_mismatch14: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_type_mismatch_v1_abort(ptr nonnull @[[GLOB20:[0-9]+]], i64 ptrtoint (ptr getelementptr inbounds ([[STRUCT_ANON_5:%.*]], ptr @test12_foo, i64 1, i32 0, i32 0, i32 0) to i64)) #[[ATTR7]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test12( +// NO-SANITIZE-WITH-ATTR-SAME: i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[BAZ:%.*]] = alloca [[STRUCT_HANG:%.*]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[BAZ]]) #[[ATTR9:[0-9]+]] +// NO-SANITIZE-WITH-ATTR-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 4 dereferenceable(24) [[BAZ]], ptr noundef nonnull align 4 dereferenceable(24) @test12_bar, i64 24, i1 false), !tbaa.struct [[TBAA_STRUCT9:![0-9]+]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [6 x i32], ptr [[BAZ]], i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[TMP0]], ptr @test12_b, align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr getelementptr inbounds ([[STRUCT_ANON_5:%.*]], ptr @test12_foo, i64 1, i32 0, i32 0, i32 0), align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[TMP1]], ptr @test12_a, align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: br label [[FOR_COND:%.*]] +// NO-SANITIZE-WITH-ATTR: for.cond: +// NO-SANITIZE-WITH-ATTR-NEXT: br label [[FOR_COND]] +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test12( +// SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[BAZ:%.*]] = alloca [[STRUCT_HANG:%.*]], align 4 +// SANITIZE-WITHOUT-ATTR-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[BAZ]]) #[[ATTR5:[0-9]+]] +// SANITIZE-WITHOUT-ATTR-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 4 dereferenceable(24) [[BAZ]], ptr noundef nonnull align 4 dereferenceable(24) @test12_bar, i64 24, i1 false), !tbaa.struct [[TBAA_STRUCT7:![0-9]+]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = icmp ult i32 [[INDEX]], 6 +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[INDEX]] to i64 +// SANITIZE-WITHOUT-ATTR-NEXT: br i1 [[TMP0]], label [[CONT:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF8:![0-9]+]], !nosanitize [[META9:![0-9]+]] +// SANITIZE-WITHOUT-ATTR: handler.out_of_bounds: +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 [[TMP1]]) #[[ATTR6:[0-9]+]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR: cont: +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [6 x i32], ptr [[BAZ]], i64 0, i64 [[TMP1]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// SANITIZE-WITHOUT-ATTR-NEXT: store i32 [[TMP2]], ptr @test12_b, align 4, !tbaa [[TBAA2]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP3:%.*]] = load i32, ptr @test12_foo, align 4, !tbaa [[TBAA10:![0-9]+]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP3]], 0 +// SANITIZE-WITHOUT-ATTR-NEXT: br i1 [[DOTNOT]], label [[HANDLER_OUT_OF_BOUNDS12:%.*]], label [[HANDLER_TYPE_MISMATCH14:%.*]], !prof [[PROF13:![0-9]+]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR: handler.out_of_bounds12: +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 0) #[[ATTR6]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR: handler.type_mismatch14: +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_type_mismatch_v1_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 ptrtoint (ptr getelementptr inbounds ([[STRUCT_ANON_5:%.*]], ptr @test12_foo, i64 1, i32 0, i32 0, i32 0) to i64)) #[[ATTR6]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test12( +// NO-SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[BAZ:%.*]] = alloca [[STRUCT_HANG:%.*]], align 4 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[BAZ]]) #[[ATTR6:[0-9]+]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 4 dereferenceable(24) [[BAZ]], ptr noundef nonnull align 4 dereferenceable(24) @test12_bar, i64 24, i1 false), !tbaa.struct [[TBAA_STRUCT7:![0-9]+]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [6 x i32], ptr [[BAZ]], i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 [[TMP0]], ptr @test12_b, align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr getelementptr inbounds ([[STRUCT_ANON_5:%.*]], ptr @test12_foo, i64 1, i32 0, i32 0, i32 0), align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 [[TMP1]], ptr @test12_a, align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: br label [[FOR_COND:%.*]] +// NO-SANITIZE-WITHOUT-ATTR: for.cond: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: br label [[FOR_COND]] +// +int test12(int index) { + struct hang baz = test12_bar; + + for (;; test12_a = (&test12_foo)->entries[0]) + test12_b = baz.entries[index]; + + return test12_b; +} + +struct test13_foo { + struct test13_bar *domain; +} test13_f; + +struct test13_bar { + struct test13_bar *parent; + int revmap_size; + struct test13_foo *revmap[] __attribute__((__counted_by__(revmap_size))); +}; + +// PR73168 - ICE. +// SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test13( +// SANITIZE-WITH-ATTR-SAME: i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr @test13_f, align 8, !tbaa [[TBAA16:![0-9]+]] +// SANITIZE-WITH-ATTR-NEXT: [[REVMAP_SIZE:%.*]] = getelementptr inbounds [[STRUCT_TEST13_BAR:%.*]], ptr [[TMP0]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[REVMAP_SIZE]], align 8, !tbaa [[TBAA2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = zext i32 [[TMP1]] to i64, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ugt i64 [[TMP2]], [[INDEX]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label [[CONT11:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB23:[0-9]+]], i64 [[INDEX]]) #[[ATTR7]], !nosanitize [[META6]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] +// SANITIZE-WITH-ATTR: cont11: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TEST13_BAR]], ptr [[TMP0]], i64 0, i32 2, i64 [[INDEX]] +// SANITIZE-WITH-ATTR-NEXT: store ptr null, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA19:![0-9]+]] +// SANITIZE-WITH-ATTR-NEXT: ret i32 0 +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test13( +// NO-SANITIZE-WITH-ATTR-SAME: i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR7:[0-9]+]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr @test13_f, align 8, !tbaa [[TBAA10:![0-9]+]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TEST13_BAR:%.*]], ptr [[TMP0]], i64 0, i32 2, i64 [[INDEX]] +// NO-SANITIZE-WITH-ATTR-NEXT: store ptr null, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA13:![0-9]+]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret i32 0 +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test13( +// SANITIZE-WITHOUT-ATTR-SAME: i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr @test13_f, align 8, !tbaa [[TBAA14:![0-9]+]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[REVMAP_SIZE:%.*]] = getelementptr inbounds [[STRUCT_TEST13_BAR:%.*]], ptr [[TMP0]], i64 0, i32 1 +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[REVMAP_SIZE]], align 8, !tbaa [[TBAA2]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP2:%.*]] = zext i32 [[TMP1]] to i64, !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP3:%.*]] = icmp ugt i64 [[TMP2]], [[INDEX]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: br i1 [[TMP3]], label [[CONT11:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR: handler.out_of_bounds: +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB8:[0-9]+]], i64 [[INDEX]]) #[[ATTR6]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR: cont11: +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TEST13_BAR]], ptr [[TMP0]], i64 0, i32 2, i64 [[INDEX]] +// SANITIZE-WITHOUT-ATTR-NEXT: store ptr null, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA17:![0-9]+]] +// SANITIZE-WITHOUT-ATTR-NEXT: ret i32 0 +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test13( +// NO-SANITIZE-WITHOUT-ATTR-SAME: i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR5:[0-9]+]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr @test13_f, align 8, !tbaa [[TBAA8:![0-9]+]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TEST13_BAR:%.*]], ptr [[TMP0]], i64 0, i32 2, i64 [[INDEX]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store ptr null, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA11:![0-9]+]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i32 0 +// +int test13(long index) { + test13_f.domain->revmap[index] = 0; + return 0; +}