Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BoundsSafety] Don't bind lvalues with temporary locations #10352

Open
wants to merge 1 commit into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6876,14 +6876,8 @@ LValue CodeGenFunction::EmitMaterializeSequenceExprLValue(
const MaterializeSequenceExpr *MSE) {
if (MSE->isBinding()) {
for (auto *OVE : MSE->opaquevalues()) {
if (CodeGenFunction::OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
RValue PtrRV = EmitAnyExpr(OVE->getSourceExpr());
LValue LV = MakeAddrLValue(PtrRV.getAggregateAddress(), OVE->getType());
CodeGenFunction::OpaqueValueMappingData::bind(*this, OVE, LV);
} else {
CodeGenFunction::OpaqueValueMappingData::bind(
*this, OVE, OVE->getSourceExpr());
}
CodeGenFunction::OpaqueValueMappingData::bind(
*this, OVE, OVE->getSourceExpr());
}
}

Expand Down
8 changes: 1 addition & 7 deletions clang/lib/CodeGen/CGExprAgg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -595,13 +595,7 @@ void AggExprEmitter::VisitPredefinedBoundsCheckExpr(
void AggExprEmitter::VisitMaterializeSequenceExpr(MaterializeSequenceExpr *MSE) {
if (MSE->isBinding()) {
for (auto *OVE : MSE->opaquevalues()) {
if (CodeGenFunction::OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
RValue PtrRV = CGF.EmitAnyExpr(OVE->getSourceExpr());
LValue LV = CGF.MakeAddrLValue(PtrRV.getAggregateAddress(), OVE->getType());
CodeGenFunction::OpaqueValueMappingData::bind(CGF, OVE, LV);
} else {
CodeGenFunction::OpaqueValueMappingData::bind(CGF, OVE, OVE->getSourceExpr());
}
CodeGenFunction::OpaqueValueMappingData::bind(CGF, OVE, OVE->getSourceExpr());
}
}

Expand Down
106 changes: 51 additions & 55 deletions clang/test/BoundsSafety/CodeGen/array_subscript_agg.c

Large diffs are not rendered by default.

516 changes: 260 additions & 256 deletions clang/test/BoundsSafety/CodeGen/builtin-memcpy-count-annotation.c

Large diffs are not rendered by default.

903 changes: 454 additions & 449 deletions clang/test/BoundsSafety/CodeGen/call-with-count-ptr.c

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ void TestPtrOK() {
// CHECK: trap:
// CHECK-NEXT: call void @llvm.ubsantrap(i8 25) #[[ATTR5]], {{!annotation ![0-9]+}}
// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}}
// CHECK: cont57:
// CHECK: cont56:
// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 40, ptr nonnull [[ARR]]) #[[ATTR6]]
// CHECK-NEXT: ret void
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,25 @@ typedef struct {
// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[ELEMS]], i64 [[IDX_EXT]]
// CHECK-NEXT: br label [[BOUNDSCHECK_CONT]]
// CHECK: boundscheck.cont:
// CHECK-NEXT: [[AGG_TEMP2_SROA_3_0:%.*]] = phi ptr [ [[ADD_PTR]], [[BOUNDSCHECK_NOTNULL]] ], [ null, [[ENTRY:%.*]] ]
// CHECK-NEXT: [[AGG_TEMP1_SROA_3_0:%.*]] = phi ptr [ [[ADD_PTR]], [[BOUNDSCHECK_NOTNULL]] ], [ null, [[ENTRY:%.*]] ]
// CHECK-NEXT: [[CONV:%.*]] = zext i32 [[SIZE:%.*]] to i64
// CHECK-NEXT: [[CMP_NOT:%.*]] = icmp ugt ptr [[FLEX]], [[AGG_TEMP2_SROA_3_0]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[AGG_TEMP2_SROA_3_0]] to i64, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[CMP_NOT:%.*]] = icmp ugt ptr [[FLEX]], [[AGG_TEMP1_SROA_3_0]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[AGG_TEMP1_SROA_3_0]] to i64, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[FLEX]] to i64, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[CMP68_NOT:%.*]] = icmp ult i64 [[SUB_PTR_SUB]], [[CONV]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[CMP_NOT]], [[CMP68_NOT]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[CMP67_NOT:%.*]] = icmp ult i64 [[SUB_PTR_SUB]], [[CONV]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[CMP_NOT]], [[CMP67_NOT]], {{!annotation ![0-9]+}}
// CHECK-NEXT: br i1 [[OR_COND]], label [[TRAP:%.*]], label [[CONT:%.*]], {{!annotation ![0-9]+}}
// CHECK: trap:
// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4:[0-9]+]], {{!annotation ![0-9]+}}
// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}}
// CHECK: cont:
// CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr align 1 [[FLEX]], i8 0, i64 [[CONV]], i1 false)
// CHECK-NEXT: [[DOTNOT89:%.*]] = icmp ne ptr [[FLEX]], null, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[DOTNOT90:%.*]] = icmp eq i32 [[SIZE]], 0, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[OR_COND91:%.*]] = and i1 [[DOTNOT89]], [[DOTNOT90]], {{!annotation ![0-9]+}}
// CHECK-NEXT: br i1 [[OR_COND91]], label [[TRAP]], label [[CONT88:%.*]], {{!annotation ![0-9]+}}
// CHECK: cont88:
// CHECK-NEXT: [[DOTNOT88:%.*]] = icmp ne ptr [[FLEX]], null, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[DOTNOT89:%.*]] = icmp eq i32 [[SIZE]], 0, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[OR_COND90:%.*]] = and i1 [[DOTNOT88]], [[DOTNOT89]], {{!annotation ![0-9]+}}
// CHECK-NEXT: br i1 [[OR_COND90]], label [[TRAP]], label [[CONT87:%.*]], {{!annotation ![0-9]+}}
// CHECK: cont87:
// CHECK-NEXT: ret ptr [[FLEX]]
//
void *set(flex_t *flex, unsigned size) {
Expand All @@ -57,42 +57,42 @@ void *set(flex_t *flex, unsigned size) {
// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[ELEMS]], i64 [[IDX_EXT]]
// CHECK-NEXT: br label [[BOUNDSCHECK_CONT]]
// CHECK: boundscheck.cont:
// CHECK-NEXT: [[AGG_TEMP2_SROA_3_0:%.*]] = phi ptr [ [[ADD_PTR]], [[BOUNDSCHECK_NOTNULL]] ], [ null, [[ENTRY:%.*]] ]
// CHECK-NEXT: [[DOTNOT188:%.*]] = icmp eq ptr [[SRC:%.*]], null, {{!annotation ![0-9]+}}
// CHECK-NEXT: br i1 [[DOTNOT188]], label [[BOUNDSCHECK_CONT12:%.*]], label [[BOUNDSCHECK_NOTNULL5:%.*]], {{!annotation ![0-9]+}}
// CHECK: boundscheck.notnull5:
// CHECK-NEXT: [[ELEMS6:%.*]] = getelementptr inbounds nuw i8, ptr [[SRC]], i64 4
// CHECK-NEXT: [[AGG_TEMP1_SROA_3_0:%.*]] = phi ptr [ [[ADD_PTR]], [[BOUNDSCHECK_NOTNULL]] ], [ null, [[ENTRY:%.*]] ]
// CHECK-NEXT: [[DOTNOT187:%.*]] = icmp eq ptr [[SRC:%.*]], null, {{!annotation ![0-9]+}}
// CHECK-NEXT: br i1 [[DOTNOT187]], label [[BOUNDSCHECK_CONT11:%.*]], label [[BOUNDSCHECK_NOTNULL4:%.*]], {{!annotation ![0-9]+}}
// CHECK: boundscheck.notnull4:
// CHECK-NEXT: [[ELEMS5:%.*]] = getelementptr inbounds nuw i8, ptr [[SRC]], i64 4
// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[SRC]], align 4, {{!tbaa ![0-9]+}}
// CHECK-NEXT: [[IDX_EXT9:%.*]] = sext i32 [[TMP1]] to i64
// CHECK-NEXT: [[ADD_PTR10:%.*]] = getelementptr inbounds i32, ptr [[ELEMS6]], i64 [[IDX_EXT9]]
// CHECK-NEXT: br label [[BOUNDSCHECK_CONT12]]
// CHECK: boundscheck.cont12:
// CHECK-NEXT: [[AGG_TEMP4_SROA_3_0:%.*]] = phi ptr [ [[ADD_PTR10]], [[BOUNDSCHECK_NOTNULL5]] ], [ null, [[BOUNDSCHECK_CONT]] ]
// CHECK-NEXT: [[IDX_EXT8:%.*]] = sext i32 [[TMP1]] to i64
// CHECK-NEXT: [[ADD_PTR9:%.*]] = getelementptr inbounds i32, ptr [[ELEMS5]], i64 [[IDX_EXT8]]
// CHECK-NEXT: br label [[BOUNDSCHECK_CONT11]]
// CHECK: boundscheck.cont11:
// CHECK-NEXT: [[AGG_TEMP3_SROA_3_0:%.*]] = phi ptr [ [[ADD_PTR9]], [[BOUNDSCHECK_NOTNULL4]] ], [ null, [[BOUNDSCHECK_CONT]] ]
// CHECK-NEXT: [[CONV:%.*]] = zext i32 [[SIZE:%.*]] to i64
// CHECK-NEXT: [[CMP_NOT:%.*]] = icmp ugt ptr [[SRC]], [[AGG_TEMP4_SROA_3_0]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[AGG_TEMP4_SROA_3_0]] to i64, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[CMP_NOT:%.*]] = icmp ugt ptr [[SRC]], [[AGG_TEMP3_SROA_3_0]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[AGG_TEMP3_SROA_3_0]] to i64, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[SRC]] to i64, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[CMP84_NOT:%.*]] = icmp ult i64 [[SUB_PTR_SUB]], [[CONV]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[CMP_NOT]], [[CMP84_NOT]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[CMP102_NOT:%.*]] = icmp ugt ptr [[DEST]], [[AGG_TEMP2_SROA_3_0]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[OR_COND191:%.*]] = select i1 [[OR_COND]], i1 true, i1 [[CMP102_NOT]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_LHS_CAST154:%.*]] = ptrtoint ptr [[AGG_TEMP2_SROA_3_0]] to i64, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_RHS_CAST155:%.*]] = ptrtoint ptr [[DEST]] to i64, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_SUB156:%.*]] = sub i64 [[SUB_PTR_LHS_CAST154]], [[SUB_PTR_RHS_CAST155]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[CMP157_NOT:%.*]] = icmp ult i64 [[SUB_PTR_SUB156]], [[CONV]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[OR_COND192:%.*]] = select i1 [[OR_COND191]], i1 true, i1 [[CMP157_NOT]], {{!annotation ![0-9]+}}
// CHECK-NEXT: br i1 [[OR_COND192]], label [[TRAP:%.*]], label [[CONT160:%.*]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[CMP83_NOT:%.*]] = icmp ult i64 [[SUB_PTR_SUB]], [[CONV]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[CMP_NOT]], [[CMP83_NOT]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[CMP101_NOT:%.*]] = icmp ugt ptr [[DEST]], [[AGG_TEMP1_SROA_3_0]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[OR_COND190:%.*]] = select i1 [[OR_COND]], i1 true, i1 [[CMP101_NOT]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_LHS_CAST153:%.*]] = ptrtoint ptr [[AGG_TEMP1_SROA_3_0]] to i64, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_RHS_CAST154:%.*]] = ptrtoint ptr [[DEST]] to i64, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_SUB155:%.*]] = sub i64 [[SUB_PTR_LHS_CAST153]], [[SUB_PTR_RHS_CAST154]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[CMP156_NOT:%.*]] = icmp ult i64 [[SUB_PTR_SUB155]], [[CONV]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[OR_COND191:%.*]] = select i1 [[OR_COND190]], i1 true, i1 [[CMP156_NOT]], {{!annotation ![0-9]+}}
// CHECK-NEXT: br i1 [[OR_COND191]], label [[TRAP:%.*]], label [[CONT159:%.*]], {{!annotation ![0-9]+}}
// CHECK: trap:
// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}}
// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}}
// CHECK: cont160:
// CHECK: cont159:
// CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEST]], ptr align 1 [[SRC]], i64 [[CONV]], i1 false)
// CHECK-NEXT: [[DOTNOT189:%.*]] = icmp ne ptr [[DEST]], null, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[DOTNOT190:%.*]] = icmp eq i32 [[SIZE]], 0, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[OR_COND193:%.*]] = and i1 [[DOTNOT189]], [[DOTNOT190]], {{!annotation ![0-9]+}}
// CHECK-NEXT: br i1 [[OR_COND193]], label [[TRAP]], label [[CONT186:%.*]], {{!annotation ![0-9]+}}
// CHECK: cont186:
// CHECK-NEXT: [[DOTNOT188:%.*]] = icmp ne ptr [[DEST]], null, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[DOTNOT189:%.*]] = icmp eq i32 [[SIZE]], 0, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[OR_COND192:%.*]] = and i1 [[DOTNOT188]], [[DOTNOT189]], {{!annotation ![0-9]+}}
// CHECK-NEXT: br i1 [[OR_COND192]], label [[TRAP]], label [[CONT185:%.*]], {{!annotation ![0-9]+}}
// CHECK: cont185:
// CHECK-NEXT: ret ptr [[DEST]]
//
void *cpy(flex_t *dest, const flex_t *src, unsigned size) {
Expand Down Expand Up @@ -159,42 +159,42 @@ void *__unsafe_indexable pcpy(flex_t *dest, const flex_t *src, unsigned size) {
// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[ELEMS]], i64 [[IDX_EXT]]
// CHECK-NEXT: br label [[BOUNDSCHECK_CONT]]
// CHECK: boundscheck.cont:
// CHECK-NEXT: [[AGG_TEMP2_SROA_3_0:%.*]] = phi ptr [ [[ADD_PTR]], [[BOUNDSCHECK_NOTNULL]] ], [ null, [[ENTRY:%.*]] ]
// CHECK-NEXT: [[DOTNOT188:%.*]] = icmp eq ptr [[SRC:%.*]], null, {{!annotation ![0-9]+}}
// CHECK-NEXT: br i1 [[DOTNOT188]], label [[BOUNDSCHECK_CONT12:%.*]], label [[BOUNDSCHECK_NOTNULL5:%.*]], {{!annotation ![0-9]+}}
// CHECK: boundscheck.notnull5:
// CHECK-NEXT: [[ELEMS6:%.*]] = getelementptr inbounds nuw i8, ptr [[SRC]], i64 4
// CHECK-NEXT: [[AGG_TEMP1_SROA_3_0:%.*]] = phi ptr [ [[ADD_PTR]], [[BOUNDSCHECK_NOTNULL]] ], [ null, [[ENTRY:%.*]] ]
// CHECK-NEXT: [[DOTNOT187:%.*]] = icmp eq ptr [[SRC:%.*]], null, {{!annotation ![0-9]+}}
// CHECK-NEXT: br i1 [[DOTNOT187]], label [[BOUNDSCHECK_CONT11:%.*]], label [[BOUNDSCHECK_NOTNULL4:%.*]], {{!annotation ![0-9]+}}
// CHECK: boundscheck.notnull4:
// CHECK-NEXT: [[ELEMS5:%.*]] = getelementptr inbounds nuw i8, ptr [[SRC]], i64 4
// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[SRC]], align 4, {{!tbaa ![0-9]+}}
// CHECK-NEXT: [[IDX_EXT9:%.*]] = sext i32 [[TMP1]] to i64
// CHECK-NEXT: [[ADD_PTR10:%.*]] = getelementptr inbounds i32, ptr [[ELEMS6]], i64 [[IDX_EXT9]]
// CHECK-NEXT: br label [[BOUNDSCHECK_CONT12]]
// CHECK: boundscheck.cont12:
// CHECK-NEXT: [[AGG_TEMP4_SROA_3_0:%.*]] = phi ptr [ [[ADD_PTR10]], [[BOUNDSCHECK_NOTNULL5]] ], [ null, [[BOUNDSCHECK_CONT]] ]
// CHECK-NEXT: [[IDX_EXT8:%.*]] = sext i32 [[TMP1]] to i64
// CHECK-NEXT: [[ADD_PTR9:%.*]] = getelementptr inbounds i32, ptr [[ELEMS5]], i64 [[IDX_EXT8]]
// CHECK-NEXT: br label [[BOUNDSCHECK_CONT11]]
// CHECK: boundscheck.cont11:
// CHECK-NEXT: [[AGG_TEMP3_SROA_3_0:%.*]] = phi ptr [ [[ADD_PTR9]], [[BOUNDSCHECK_NOTNULL4]] ], [ null, [[BOUNDSCHECK_CONT]] ]
// CHECK-NEXT: [[CONV:%.*]] = zext i32 [[SIZE:%.*]] to i64
// CHECK-NEXT: [[CMP_NOT:%.*]] = icmp ugt ptr [[SRC]], [[AGG_TEMP4_SROA_3_0]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[AGG_TEMP4_SROA_3_0]] to i64, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[CMP_NOT:%.*]] = icmp ugt ptr [[SRC]], [[AGG_TEMP3_SROA_3_0]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[AGG_TEMP3_SROA_3_0]] to i64, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[SRC]] to i64, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[CMP84_NOT:%.*]] = icmp ult i64 [[SUB_PTR_SUB]], [[CONV]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[CMP_NOT]], [[CMP84_NOT]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[CMP102_NOT:%.*]] = icmp ugt ptr [[DEST]], [[AGG_TEMP2_SROA_3_0]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[OR_COND191:%.*]] = select i1 [[OR_COND]], i1 true, i1 [[CMP102_NOT]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_LHS_CAST154:%.*]] = ptrtoint ptr [[AGG_TEMP2_SROA_3_0]] to i64, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_RHS_CAST155:%.*]] = ptrtoint ptr [[DEST]] to i64, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_SUB156:%.*]] = sub i64 [[SUB_PTR_LHS_CAST154]], [[SUB_PTR_RHS_CAST155]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[CMP157_NOT:%.*]] = icmp ult i64 [[SUB_PTR_SUB156]], [[CONV]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[OR_COND192:%.*]] = select i1 [[OR_COND191]], i1 true, i1 [[CMP157_NOT]], {{!annotation ![0-9]+}}
// CHECK-NEXT: br i1 [[OR_COND192]], label [[TRAP:%.*]], label [[CONT160:%.*]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[CMP83_NOT:%.*]] = icmp ult i64 [[SUB_PTR_SUB]], [[CONV]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[CMP_NOT]], [[CMP83_NOT]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[CMP101_NOT:%.*]] = icmp ugt ptr [[DEST]], [[AGG_TEMP1_SROA_3_0]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[OR_COND190:%.*]] = select i1 [[OR_COND]], i1 true, i1 [[CMP101_NOT]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_LHS_CAST153:%.*]] = ptrtoint ptr [[AGG_TEMP1_SROA_3_0]] to i64, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_RHS_CAST154:%.*]] = ptrtoint ptr [[DEST]] to i64, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[SUB_PTR_SUB155:%.*]] = sub i64 [[SUB_PTR_LHS_CAST153]], [[SUB_PTR_RHS_CAST154]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[CMP156_NOT:%.*]] = icmp ult i64 [[SUB_PTR_SUB155]], [[CONV]], {{!annotation ![0-9]+}}
// CHECK-NEXT: [[OR_COND191:%.*]] = select i1 [[OR_COND190]], i1 true, i1 [[CMP156_NOT]], {{!annotation ![0-9]+}}
// CHECK-NEXT: br i1 [[OR_COND191]], label [[TRAP:%.*]], label [[CONT159:%.*]], {{!annotation ![0-9]+}}
// CHECK: trap:
// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR4]], {{!annotation ![0-9]+}}
// CHECK-NEXT: unreachable, {{!annotation ![0-9]+}}
// CHECK: cont160:
// CHECK: cont159:
// CHECK-NEXT: tail call void @llvm.memmove.p0.p0.i64(ptr align 1 [[DEST]], ptr align 1 [[SRC]], i64 [[CONV]], i1 false)
// CHECK-NEXT: [[DOTNOT189:%.*]] = icmp ne ptr [[DEST]], null, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[DOTNOT190:%.*]] = icmp eq i32 [[SIZE]], 0, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[OR_COND193:%.*]] = and i1 [[DOTNOT189]], [[DOTNOT190]], {{!annotation ![0-9]+}}
// CHECK-NEXT: br i1 [[OR_COND193]], label [[TRAP]], label [[CONT186:%.*]], {{!annotation ![0-9]+}}
// CHECK: cont186:
// CHECK-NEXT: [[DOTNOT188:%.*]] = icmp ne ptr [[DEST]], null, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[DOTNOT189:%.*]] = icmp eq i32 [[SIZE]], 0, {{!annotation ![0-9]+}}
// CHECK-NEXT: [[OR_COND192:%.*]] = and i1 [[DOTNOT188]], [[DOTNOT189]], {{!annotation ![0-9]+}}
// CHECK-NEXT: br i1 [[OR_COND192]], label [[TRAP]], label [[CONT185:%.*]], {{!annotation ![0-9]+}}
// CHECK: cont185:
// CHECK-NEXT: ret ptr [[DEST]]
//
void *move(flex_t *dest, const flex_t *src, unsigned size) {
Expand Down
43 changes: 43 additions & 0 deletions clang/test/BoundsSafety/CodeGen/nested-flexible-array-member-O2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5

// RUN: %clang_cc1 -O2 -fbounds-safety -triple arm64e-apple-ios -emit-llvm %s -o - | FileCheck %s

#include <ptrcheck.h>
typedef struct {
int count;
char arr[__counted_by(count)];
} flex_t;

typedef struct {
flex_t f;
} outer_flex_t;

void use(void *__unsafe_indexable);

// CHECK-LABEL: define void @process_frame(
// CHECK-SAME: ptr noundef [[FRAME:%.*]], i32 noundef [[FRAME_SIZE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[FRAME_SIZE]] to i64
// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i8, ptr [[FRAME]], i64 [[IDX_EXT]]
// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[FRAME]], i64 4
// CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt ptr [[TMP0]], [[ADD_PTR]], !annotation [[META2:![0-9]+]]
// CHECK-NEXT: br i1 [[DOTNOT]], label %[[TRAP:.*]], label %[[CONT10:.*]], !annotation [[META2]]
// CHECK: [[TRAP]]:
// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 25) #[[ATTR3:[0-9]+]], !annotation [[META3:![0-9]+]]
// CHECK-NEXT: unreachable, !annotation [[META3]]
// CHECK: [[CONT10]]:
// CHECK-NEXT: tail call void @use(ptr noundef [[FRAME]]) #[[ATTR4:[0-9]+]]
// CHECK-NEXT: tail call void @use(ptr noundef [[TMP0]]) #[[ATTR4]]
// CHECK-NEXT: tail call void @use(ptr noundef [[TMP0]]) #[[ATTR4]]
// CHECK-NEXT: ret void
//
void process_frame(char *__counted_by(frame_size) frame, unsigned frame_size) {
outer_flex_t *of = (outer_flex_t *) frame;
use(&of->f);
use(of->f.arr);
use(&of->f.arr[0]);
}
//.
// CHECK: [[META2]] = !{!"bounds-safety-check-ptr-lt-upper-bound"}
// CHECK: [[META3]] = !{!"bounds-safety-check-ptr-lt-upper-bound", !"bounds-safety-check-ptr-ge-lower-bound"}
//.
Loading