mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 12:26:52 +08:00
[CodeGen] Revamp counted_by calculations (#70606)
Break down the counted_by calculations so that they correctly handle anonymous structs, which are specified internally as IndirectFieldDecls. Improves the calculation of __bdos on a different field member in the struct. And also improves support for __bdos in an index into the FAM. If the index is further out than the length of the FAM, then we return __bdos's "can't determine the size" value (zero or negative one, depending on type). Also simplify the code to use helper methods to get the field referenced by counted_by and the flexible array member itself, which also had some issues with FAMs in sub-structs.
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#include "clang/AST/Attr.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/OSLog.h"
|
||||
#include "clang/AST/OperationKinds.h"
|
||||
#include "clang/Basic/TargetBuiltins.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "clang/Basic/TargetOptions.h"
|
||||
@@ -858,63 +859,155 @@ CodeGenFunction::emitBuiltinObjectSize(const Expr *E, unsigned Type,
|
||||
}
|
||||
}
|
||||
|
||||
if (IsDynamic) {
|
||||
LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel =
|
||||
getLangOpts().getStrictFlexArraysLevel();
|
||||
const Expr *Base = E->IgnoreParenImpCasts();
|
||||
|
||||
if (FieldDecl *FD = FindCountedByField(Base, StrictFlexArraysLevel)) {
|
||||
const auto *ME = dyn_cast<MemberExpr>(Base);
|
||||
llvm::Value *ObjectSize = nullptr;
|
||||
|
||||
if (!ME) {
|
||||
const auto *DRE = dyn_cast<DeclRefExpr>(Base);
|
||||
ValueDecl *VD = nullptr;
|
||||
|
||||
ObjectSize = ConstantInt::get(
|
||||
ResType,
|
||||
getContext().getTypeSize(DRE->getType()->getPointeeType()) / 8,
|
||||
true);
|
||||
|
||||
if (auto *RD = DRE->getType()->getPointeeType()->getAsRecordDecl())
|
||||
VD = RD->getLastField();
|
||||
|
||||
Expr *ICE = ImplicitCastExpr::Create(
|
||||
getContext(), DRE->getType(), CK_LValueToRValue,
|
||||
const_cast<Expr *>(cast<Expr>(DRE)), nullptr, VK_PRValue,
|
||||
FPOptionsOverride());
|
||||
ME = MemberExpr::CreateImplicit(getContext(), ICE, true, VD,
|
||||
VD->getType(), VK_LValue, OK_Ordinary);
|
||||
}
|
||||
|
||||
// At this point, we know that \p ME is a flexible array member.
|
||||
const auto *ArrayTy = getContext().getAsArrayType(ME->getType());
|
||||
unsigned Size = getContext().getTypeSize(ArrayTy->getElementType());
|
||||
|
||||
llvm::Value *CountField =
|
||||
EmitAnyExprToTemp(MemberExpr::CreateImplicit(
|
||||
getContext(), const_cast<Expr *>(ME->getBase()),
|
||||
ME->isArrow(), FD, FD->getType(), VK_LValue,
|
||||
OK_Ordinary))
|
||||
.getScalarVal();
|
||||
|
||||
llvm::Value *Mul = Builder.CreateMul(
|
||||
CountField, llvm::ConstantInt::get(CountField->getType(), Size / 8));
|
||||
Mul = Builder.CreateZExtOrTrunc(Mul, ResType);
|
||||
|
||||
if (ObjectSize)
|
||||
return Builder.CreateAdd(ObjectSize, Mul);
|
||||
|
||||
return Mul;
|
||||
}
|
||||
}
|
||||
|
||||
// LLVM can't handle Type=3 appropriately, and __builtin_object_size shouldn't
|
||||
// evaluate E for side-effects. In either case, we shouldn't lower to
|
||||
// @llvm.objectsize.
|
||||
if (Type == 3 || (!EmittedE && E->HasSideEffects(getContext())))
|
||||
return getDefaultBuiltinObjectSizeResult(Type, ResType);
|
||||
|
||||
if (IsDynamic) {
|
||||
// The code generated here calculates the size of a struct with a flexible
|
||||
// array member that uses the counted_by attribute. There are two instances
|
||||
// we handle:
|
||||
//
|
||||
// struct s {
|
||||
// unsigned long flags;
|
||||
// int count;
|
||||
// int array[] __attribute__((counted_by(count)));
|
||||
// }
|
||||
//
|
||||
// 1) bdos of the flexible array itself:
|
||||
//
|
||||
// __builtin_dynamic_object_size(p->array, 1) ==
|
||||
// p->count * sizeof(*p->array)
|
||||
//
|
||||
// 2) bdos of a pointer into the flexible array:
|
||||
//
|
||||
// __builtin_dynamic_object_size(&p->array[42], 1) ==
|
||||
// (p->count - 42) * sizeof(*p->array)
|
||||
//
|
||||
// 2) bdos of the whole struct, including the flexible array:
|
||||
//
|
||||
// __builtin_dynamic_object_size(p, 1) ==
|
||||
// max(sizeof(struct s),
|
||||
// offsetof(struct s, array) + p->count * sizeof(*p->array))
|
||||
//
|
||||
const Expr *Base = E->IgnoreParenImpCasts();
|
||||
const Expr *Idx = nullptr;
|
||||
if (const auto *UO = dyn_cast<UnaryOperator>(Base);
|
||||
UO && UO->getOpcode() == UO_AddrOf) {
|
||||
if (const auto *ASE =
|
||||
dyn_cast<ArraySubscriptExpr>(UO->getSubExpr()->IgnoreParens())) {
|
||||
Base = ASE->getBase();
|
||||
Idx = ASE->getIdx()->IgnoreParenImpCasts();
|
||||
|
||||
if (const auto *IL = dyn_cast<IntegerLiteral>(Idx);
|
||||
IL && !IL->getValue().getSExtValue())
|
||||
Idx = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (const ValueDecl *CountedByFD = FindCountedByField(Base)) {
|
||||
bool IsSigned = CountedByFD->getType()->isSignedIntegerType();
|
||||
const RecordDecl *OuterRD =
|
||||
CountedByFD->getDeclContext()->getOuterLexicalRecordContext();
|
||||
ASTContext &Ctx = getContext();
|
||||
|
||||
// Load the counted_by field.
|
||||
const Expr *CountedByExpr = BuildCountedByFieldExpr(Base, CountedByFD);
|
||||
Value *CountedByInst = EmitAnyExprToTemp(CountedByExpr).getScalarVal();
|
||||
llvm::Type *CountedByTy = CountedByInst->getType();
|
||||
|
||||
if (Idx) {
|
||||
// There's an index into the array. Remove it from the count.
|
||||
bool IdxSigned = Idx->getType()->isSignedIntegerType();
|
||||
Value *IdxInst = EmitAnyExprToTemp(Idx).getScalarVal();
|
||||
IdxInst = IdxSigned ? Builder.CreateSExtOrTrunc(IdxInst, CountedByTy)
|
||||
: Builder.CreateZExtOrTrunc(IdxInst, CountedByTy);
|
||||
|
||||
// If the index is negative, don't subtract it from the counted_by
|
||||
// value. The pointer is pointing to something before the FAM.
|
||||
IdxInst = Builder.CreateNeg(IdxInst, "", !IdxSigned, IdxSigned);
|
||||
CountedByInst =
|
||||
Builder.CreateAdd(CountedByInst, IdxInst, "", !IsSigned, IsSigned);
|
||||
}
|
||||
|
||||
// Get the size of the flexible array member's base type.
|
||||
const ValueDecl *FAMDecl = nullptr;
|
||||
if (const auto *ME = dyn_cast<MemberExpr>(Base)) {
|
||||
const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel =
|
||||
getLangOpts().getStrictFlexArraysLevel();
|
||||
if (const ValueDecl *MD = ME->getMemberDecl();
|
||||
MD && Decl::isFlexibleArrayMemberLike(
|
||||
Ctx, MD, MD->getType(), StrictFlexArraysLevel,
|
||||
/*IgnoreTemplateOrMacroSubstitution=*/true))
|
||||
// Base is referencing the FAM itself.
|
||||
FAMDecl = MD;
|
||||
}
|
||||
|
||||
if (!FAMDecl)
|
||||
FAMDecl = FindFlexibleArrayMemberField(Ctx, OuterRD);
|
||||
|
||||
assert(FAMDecl && "Can't find the flexible array member field");
|
||||
|
||||
const ArrayType *ArrayTy = Ctx.getAsArrayType(FAMDecl->getType());
|
||||
CharUnits Size = Ctx.getTypeSizeInChars(ArrayTy->getElementType());
|
||||
llvm::Constant *ElemSize =
|
||||
llvm::ConstantInt::get(CountedByTy, Size.getQuantity(), IsSigned);
|
||||
|
||||
// Calculate how large the flexible array member is in bytes.
|
||||
Value *FAMSize =
|
||||
Builder.CreateMul(CountedByInst, ElemSize, "", !IsSigned, IsSigned);
|
||||
FAMSize = IsSigned ? Builder.CreateSExtOrTrunc(FAMSize, ResType)
|
||||
: Builder.CreateZExtOrTrunc(FAMSize, ResType);
|
||||
Value *Res = FAMSize;
|
||||
|
||||
if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
|
||||
// The whole struct is specificed in the __bdos.
|
||||
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(OuterRD);
|
||||
|
||||
// Get the offset of the FAM.
|
||||
CharUnits Offset = Ctx.toCharUnitsFromBits(Ctx.getFieldOffset(FAMDecl));
|
||||
llvm::Constant *FAMOffset =
|
||||
ConstantInt::get(ResType, Offset.getQuantity(), IsSigned);
|
||||
|
||||
// max(sizeof(struct s),
|
||||
// offsetof(struct s, array) + p->count * sizeof(*p->array))
|
||||
Value *OffsetAndFAMSize =
|
||||
Builder.CreateAdd(FAMOffset, Res, "", !IsSigned, IsSigned);
|
||||
|
||||
// Get the full size of the struct.
|
||||
llvm::Constant *SizeofStruct =
|
||||
ConstantInt::get(ResType, Layout.getSize().getQuantity(), IsSigned);
|
||||
|
||||
Res = IsSigned
|
||||
? Builder.CreateBinaryIntrinsic(
|
||||
llvm::Intrinsic::smax, OffsetAndFAMSize, SizeofStruct)
|
||||
: Builder.CreateBinaryIntrinsic(
|
||||
llvm::Intrinsic::umax, OffsetAndFAMSize, SizeofStruct);
|
||||
} else if (const auto *ME = dyn_cast<MemberExpr>(Base)) {
|
||||
// Pointing to a place before the FAM. Add the difference to the FAM's
|
||||
// size.
|
||||
if (const ValueDecl *MD = ME->getMemberDecl(); MD != FAMDecl) {
|
||||
CharUnits Offset = Ctx.toCharUnitsFromBits(Ctx.getFieldOffset(MD));
|
||||
CharUnits FAMOffset =
|
||||
Ctx.toCharUnitsFromBits(Ctx.getFieldOffset(FAMDecl));
|
||||
|
||||
Res = Builder.CreateAdd(
|
||||
Res, ConstantInt::get(ResType, FAMOffset.getQuantity() -
|
||||
Offset.getQuantity()));
|
||||
}
|
||||
}
|
||||
|
||||
// A negative 'FAMSize' means that the index was greater than the count,
|
||||
// or an improperly set count field. Return -1 (for types 0 and 1) or 0
|
||||
// (for types 2 and 3).
|
||||
return Builder.CreateSelect(
|
||||
Builder.CreateIsNeg(FAMSize),
|
||||
getDefaultBuiltinObjectSizeResult(Type, ResType), Res);
|
||||
}
|
||||
}
|
||||
|
||||
Value *Ptr = EmittedE ? EmittedE : EmitScalarExpr(E);
|
||||
assert(Ptr->getType()->isPointerTy() &&
|
||||
"Non-pointer passed to __builtin_object_size?");
|
||||
|
||||
@@ -938,14 +938,10 @@ static llvm::Value *getArrayIndexingBound(CodeGenFunction &CGF,
|
||||
// Ignore pass_object_size here. It's not applicable on decayed pointers.
|
||||
}
|
||||
|
||||
if (FieldDecl *FD = CGF.FindCountedByField(Base, StrictFlexArraysLevel)) {
|
||||
const auto *ME = dyn_cast<MemberExpr>(CE->getSubExpr());
|
||||
if (const ValueDecl *VD = CGF.FindCountedByField(Base)) {
|
||||
IndexedType = Base->getType();
|
||||
return CGF
|
||||
.EmitAnyExprToTemp(MemberExpr::CreateImplicit(
|
||||
CGF.getContext(), const_cast<Expr *>(ME->getBase()),
|
||||
ME->isArrow(), FD, FD->getType(), VK_LValue, OK_Ordinary))
|
||||
.getScalarVal();
|
||||
const Expr *E = CGF.BuildCountedByFieldExpr(Base, VD);
|
||||
return CGF.EmitAnyExprToTemp(E).getScalarVal();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -960,46 +956,115 @@ static llvm::Value *getArrayIndexingBound(CodeGenFunction &CGF,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FieldDecl *CodeGenFunction::FindCountedByField(
|
||||
const Expr *Base,
|
||||
LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel) {
|
||||
const ValueDecl *VD = nullptr;
|
||||
const Expr *
|
||||
CodeGenFunction::BuildCountedByFieldExpr(const Expr *Base,
|
||||
const ValueDecl *CountedByVD) {
|
||||
// Find the outer struct expr (i.e. p in p->a.b.c.d).
|
||||
Expr *CountedByExpr = const_cast<Expr *>(Base)->IgnoreParenImpCasts();
|
||||
|
||||
// Work our way up the expression until we reach the DeclRefExpr.
|
||||
while (!isa<DeclRefExpr>(CountedByExpr))
|
||||
if (const auto *ME = dyn_cast<MemberExpr>(CountedByExpr))
|
||||
CountedByExpr = ME->getBase()->IgnoreParenImpCasts();
|
||||
|
||||
// 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 (const auto *IFD = dyn_cast<IndirectFieldDecl>(CountedByVD)) {
|
||||
// The counted_by field is inside an anonymous struct / union. The
|
||||
// IndirectFieldDecl has the correct order of FieldDecls to build this
|
||||
// easily. (Yay!)
|
||||
for (NamedDecl *ND : IFD->chain()) {
|
||||
auto *VD = cast<ValueDecl>(ND);
|
||||
CountedByExpr =
|
||||
MemberExpr::CreateImplicit(getContext(), CountedByExpr,
|
||||
CountedByExpr->getType()->isPointerType(),
|
||||
VD, VD->getType(), VK_LValue, OK_Ordinary);
|
||||
}
|
||||
} else {
|
||||
CountedByExpr = MemberExpr::CreateImplicit(
|
||||
getContext(), const_cast<Expr *>(CountedByExpr),
|
||||
CountedByExpr->getType()->isPointerType(),
|
||||
const_cast<ValueDecl *>(CountedByVD), CountedByVD->getType(), VK_LValue,
|
||||
OK_Ordinary);
|
||||
}
|
||||
|
||||
return CountedByExpr;
|
||||
}
|
||||
|
||||
const ValueDecl *
|
||||
CodeGenFunction::FindFlexibleArrayMemberField(ASTContext &Ctx,
|
||||
const RecordDecl *RD) {
|
||||
const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel =
|
||||
getLangOpts().getStrictFlexArraysLevel();
|
||||
|
||||
for (const Decl *D : RD->decls()) {
|
||||
if (const auto *VD = dyn_cast<ValueDecl>(D);
|
||||
VD && Decl::isFlexibleArrayMemberLike(
|
||||
Ctx, VD, VD->getType(), StrictFlexArraysLevel,
|
||||
/*IgnoreTemplateOrMacroSubstitution=*/true))
|
||||
return VD;
|
||||
|
||||
if (const auto *Record = dyn_cast<RecordDecl>(D))
|
||||
if (const ValueDecl *VD = FindFlexibleArrayMemberField(Ctx, Record))
|
||||
return VD;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ValueDecl *CodeGenFunction::FindCountedByField(const Expr *Base) {
|
||||
ASTContext &Ctx = getContext();
|
||||
const RecordDecl *OuterRD = nullptr;
|
||||
const FieldDecl *FD = nullptr;
|
||||
|
||||
Base = Base->IgnoreParenImpCasts();
|
||||
|
||||
if (const auto *ME = dyn_cast<MemberExpr>(Base)) {
|
||||
VD = dyn_cast<ValueDecl>(ME->getMemberDecl());
|
||||
} else if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
|
||||
// Pointing to the full structure.
|
||||
VD = dyn_cast<ValueDecl>(DRE->getDecl());
|
||||
|
||||
QualType Ty = VD->getType();
|
||||
// Get the outer-most lexical RecordDecl.
|
||||
if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
|
||||
QualType Ty = DRE->getDecl()->getType();
|
||||
if (Ty->isPointerType())
|
||||
Ty = Ty->getPointeeType();
|
||||
|
||||
if (const auto *RD = Ty->getAsRecordDecl())
|
||||
VD = RD->getLastField();
|
||||
} else if (const auto *CE = dyn_cast<CastExpr>(Base)) {
|
||||
if (const auto *ME = dyn_cast<MemberExpr>(CE->getSubExpr()))
|
||||
VD = dyn_cast<ValueDecl>(ME->getMemberDecl());
|
||||
OuterRD = RD->getOuterLexicalRecordContext();
|
||||
} else if (const auto *ME = dyn_cast<MemberExpr>(Base)) {
|
||||
if (const ValueDecl *MD = ME->getMemberDecl()) {
|
||||
OuterRD = MD->getDeclContext()->getOuterLexicalRecordContext();
|
||||
|
||||
const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel =
|
||||
getLangOpts().getStrictFlexArraysLevel();
|
||||
if (Decl::isFlexibleArrayMemberLike(
|
||||
Ctx, MD, MD->getType(), StrictFlexArraysLevel,
|
||||
/*IgnoreTemplateOrMacroSubstitution=*/true))
|
||||
// Base is referencing the FAM itself.
|
||||
FD = dyn_cast<FieldDecl>(MD);
|
||||
}
|
||||
}
|
||||
|
||||
const auto *FD = dyn_cast_if_present<FieldDecl>(VD);
|
||||
if (!FD || !FD->getParent() ||
|
||||
!Decl::isFlexibleArrayMemberLike(getContext(), FD, FD->getType(),
|
||||
StrictFlexArraysLevel, true))
|
||||
if (!OuterRD)
|
||||
return nullptr;
|
||||
|
||||
if (!FD) {
|
||||
const ValueDecl *VD = FindFlexibleArrayMemberField(Ctx, OuterRD);
|
||||
FD = dyn_cast_if_present<FieldDecl>(VD);
|
||||
if (!FD)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto *CBA = FD->getAttr<CountedByAttr>();
|
||||
if (!CBA)
|
||||
return nullptr;
|
||||
|
||||
StringRef FieldName = CBA->getCountedByField()->getName();
|
||||
auto It =
|
||||
llvm::find_if(FD->getParent()->fields(), [&](const FieldDecl *Field) {
|
||||
return FieldName == Field->getName();
|
||||
});
|
||||
return It != FD->getParent()->field_end() ? *It : nullptr;
|
||||
DeclarationName DName(CBA->getCountedByField());
|
||||
DeclContext::lookup_result Lookup = OuterRD->lookup(DName);
|
||||
|
||||
if (Lookup.empty())
|
||||
return nullptr;
|
||||
|
||||
return dyn_cast<ValueDecl>(Lookup.front());
|
||||
}
|
||||
|
||||
void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base,
|
||||
|
||||
@@ -3022,11 +3022,18 @@ public:
|
||||
void EmitBoundsCheck(const Expr *E, const Expr *Base, llvm::Value *Index,
|
||||
QualType IndexType, bool Accessed);
|
||||
|
||||
// Find a struct's flexible array member. It may be embedded inside multiple
|
||||
// sub-structs, but must still be the last field.
|
||||
const ValueDecl *FindFlexibleArrayMemberField(ASTContext &Ctx,
|
||||
const RecordDecl *RD);
|
||||
|
||||
/// Find the FieldDecl specified in a FAM's "counted_by" attribute. Returns
|
||||
/// \p nullptr if either the attribute or the field doesn't exist.
|
||||
FieldDecl *FindCountedByField(
|
||||
const Expr *Base,
|
||||
LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel);
|
||||
const ValueDecl *FindCountedByField(const Expr *Base);
|
||||
|
||||
/// Build an expression accessing the "counted_by" field.
|
||||
const Expr *BuildCountedByFieldExpr(const Expr *Base,
|
||||
const ValueDecl *CountedByVD);
|
||||
|
||||
llvm::Value *EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
|
||||
bool isInc, bool isPre);
|
||||
|
||||
@@ -14,6 +14,24 @@
|
||||
#define __counted_by(member)
|
||||
#endif
|
||||
|
||||
#define DECLARE_FLEX_ARRAY(TYPE, NAME) \
|
||||
struct { \
|
||||
struct { } __empty_ ## NAME; \
|
||||
TYPE NAME[]; \
|
||||
}
|
||||
|
||||
#define DECLARE_BOUNDED_FLEX_ARRAY(COUNT_TYPE, COUNT, TYPE, NAME) \
|
||||
struct { \
|
||||
COUNT_TYPE COUNT; \
|
||||
TYPE NAME[] __counted_by(COUNT); \
|
||||
}
|
||||
|
||||
#define DECLARE_FLEX_ARRAY_COUNTED_BY(TYPE, NAME, COUNTED_BY) \
|
||||
struct { \
|
||||
struct { } __empty_ ## NAME; \
|
||||
TYPE NAME[] __counted_by(COUNTED_BY); \
|
||||
}
|
||||
|
||||
typedef long unsigned int size_t;
|
||||
|
||||
struct annotated {
|
||||
@@ -22,6 +40,22 @@ struct annotated {
|
||||
int array[] __counted_by(count);
|
||||
};
|
||||
|
||||
struct union_of_fams {
|
||||
unsigned long flags;
|
||||
union {
|
||||
/* count member type intentionally mismatched to induce padding */
|
||||
DECLARE_BOUNDED_FLEX_ARRAY(int, count_bytes, unsigned char, bytes);
|
||||
DECLARE_BOUNDED_FLEX_ARRAY(unsigned char, count_ints, unsigned char, ints);
|
||||
DECLARE_FLEX_ARRAY(unsigned char, unsafe);
|
||||
};
|
||||
};
|
||||
|
||||
struct anon_struct {
|
||||
unsigned long flags;
|
||||
size_t count;
|
||||
DECLARE_FLEX_ARRAY_COUNTED_BY(int, array, count);
|
||||
};
|
||||
|
||||
// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test1(
|
||||
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[VAL:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
|
||||
// SANITIZE-WITH-ATTR-NEXT: entry:
|
||||
@@ -33,7 +67,7 @@ struct annotated {
|
||||
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label [[CONT7:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7:![0-9]+]], !nosanitize !6
|
||||
// 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]]) #[[ATTR2:[0-9]+]], !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: cont7:
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[TMP1]]
|
||||
@@ -77,12 +111,14 @@ void test1(struct annotated *p, int index, int val) {
|
||||
// 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: handler.out_of_bounds:
|
||||
// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 [[INDEX]]) #[[ATTR2]], !nosanitize !6
|
||||
// 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: cont12:
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = shl i32 [[TMP0]], 2
|
||||
// SANITIZE-WITH-ATTR-NEXT: store i32 [[TMP3]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp sgt i32 [[TMP0]], -1
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = shl nsw i32 [[TMP0]], 2
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = select i1 [[DOTINV]], i32 [[TMP3]], i32 -1
|
||||
// SANITIZE-WITH-ATTR-NEXT: store i32 [[NARROW]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: ret void
|
||||
//
|
||||
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test2(
|
||||
@@ -90,9 +126,11 @@ void test1(struct annotated *p, int index, int val) {
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: entry:
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl i32 [[TMP0]], 2
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl nsw i32 [[TMP0]], 2
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp sgt i32 [[TMP0]], -1
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = select i1 [[DOTINV]], i32 [[TMP1]], i32 -1
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[TMP1]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[NARROW]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: ret void
|
||||
//
|
||||
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test2(
|
||||
@@ -122,22 +160,28 @@ void test2(struct annotated *p, size_t index) {
|
||||
// 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: handler.out_of_bounds:
|
||||
// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 [[INDEX]]) #[[ATTR2]], !nosanitize !6
|
||||
// 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: cont12:
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = shl i32 [[TMP0]], 2
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = add i32 [[TMP3]], 16
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = shl nsw i32 [[TMP0]], 2
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = tail call i32 @llvm.smax.i32(i32 [[TMP3]], i32 4)
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = add nuw i32 [[TMP4]], 12
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp sgt i32 [[TMP0]], -1
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i32 [[NARROW]], i32 -1
|
||||
// SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: ret void
|
||||
//
|
||||
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test3(
|
||||
// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
|
||||
// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: entry:
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl i32 [[TMP0]], 2
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = add i32 [[TMP1]], 16
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl nsw i32 [[TMP0]], 2
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = tail call i32 @llvm.smax.i32(i32 [[TMP1]], i32 4)
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = add nuw i32 [[TMP2]], 12
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp sgt i32 [[TMP0]], -1
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i32 [[NARROW]], i32 -1
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: ret void
|
||||
@@ -162,66 +206,527 @@ void test3(struct annotated *p, size_t index) {
|
||||
p->array[index] = __builtin_dynamic_object_size(p, 1);
|
||||
}
|
||||
|
||||
struct annotated_with_anon_struct {
|
||||
unsigned long flags;
|
||||
struct {
|
||||
unsigned char count;
|
||||
int array[] __counted_by(count);
|
||||
};
|
||||
};
|
||||
|
||||
// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test4(
|
||||
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
||||
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[FAM_IDX:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
||||
// SANITIZE-WITH-ATTR-NEXT: entry:
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED_WITH_ANON_STRUCT:%.*]], ptr [[P]], i64 0, i32 1
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[TMP0]], align 8, !tbaa [[TBAA8:![0-9]+]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize !6
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i8 [[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 [[CONT18:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize !6
|
||||
// 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: 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 @[[GLOB6:[0-9]+]], i64 [[TMP5]]) #[[ATTR2]], !nosanitize !6
|
||||
// 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: cont18:
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[TMP2]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = shl i8 [[TMP1]], 2
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = zext i8 [[TMP6]] to i32
|
||||
// SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
|
||||
// SANITIZE-WITH-ATTR: cont13:
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = shl i32 [[TMP0]], 2
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = add i32 [[TMP5]], -12
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = tail call i32 @llvm.smax.i32(i32 [[TMP6]], i32 -1)
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[CONV3:%.*]] = and i32 [[NARROW]], 255
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[TMP1]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV3]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[ADD:%.*]] = add nsw i32 [[INDEX]], 1
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = sext i32 [[ADD]] to i64, !nosanitize !6
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP9:%.*]] = zext i32 [[TMP7]] to i64, !nosanitize !6
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP10:%.*]] = icmp ult i64 [[TMP8]], [[TMP9]], !nosanitize !6
|
||||
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP10]], label [[CONT34:%.*]], label [[HANDLER_OUT_OF_BOUNDS29:%.*]], !prof [[PROF7]], !nosanitize !6
|
||||
// SANITIZE-WITH-ATTR: handler.out_of_bounds29:
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP11:%.*]] = 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 [[TMP11]]) #[[ATTR4]], !nosanitize !6
|
||||
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize !6
|
||||
// SANITIZE-WITH-ATTR: cont34:
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP12:%.*]] = shl i32 [[TMP7]], 2
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP13:%.*]] = add i32 [[TMP12]], -16
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[NARROW69:%.*]] = tail call i32 @llvm.smax.i32(i32 [[TMP13]], i32 -1)
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[CONV20:%.*]] = and i32 [[NARROW69]], 255
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX32:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[TMP8]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV20]], ptr [[ARRAYIDX32]], align 4, !tbaa [[TBAA2]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP14:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[ADD45:%.*]] = add nsw i32 [[INDEX]], 2
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP15:%.*]] = sext i32 [[ADD45]] to i64, !nosanitize !6
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP16:%.*]] = zext i32 [[TMP14]] to i64, !nosanitize !6
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP17:%.*]] = icmp ult i64 [[TMP15]], [[TMP16]], !nosanitize !6
|
||||
// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP17]], label [[CONT56:%.*]], label [[HANDLER_OUT_OF_BOUNDS51:%.*]], !prof [[PROF7]], !nosanitize !6
|
||||
// SANITIZE-WITH-ATTR: handler.out_of_bounds51:
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP18:%.*]] = 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 [[TMP18]]) #[[ATTR4]], !nosanitize !6
|
||||
// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize !6
|
||||
// SANITIZE-WITH-ATTR: cont56:
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX54:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[TMP15]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP19:%.*]] = sub i32 [[TMP14]], [[FAM_IDX]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp sgt i32 [[TMP19]], -1
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP20:%.*]] = shl i32 [[TMP19]], 2
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP21:%.*]] = and i32 [[TMP20]], 252
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[CONV41:%.*]] = select i1 [[DOTINV]], i32 [[TMP21]], i32 255
|
||||
// SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV41]], ptr [[ARRAYIDX54]], align 4, !tbaa [[TBAA2]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: ret void
|
||||
//
|
||||
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test4(
|
||||
// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
|
||||
// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[FAM_IDX:%.*]]) local_unnamed_addr #[[ATTR2]] {
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: entry:
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED_WITH_ANON_STRUCT:%.*]], ptr [[P]], i64 0, i32 1
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[TMP0]], align 8, !tbaa [[TBAA6:![0-9]+]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = shl i8 [[TMP1]], 2
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = zext i8 [[TMP2]] to i32
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl i32 [[TMP0]], 2
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], -12
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = tail call i32 @llvm.smax.i32(i32 [[TMP2]], i32 -1)
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV1:%.*]] = and i32 [[NARROW]], 255
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV1]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = shl i32 [[TMP3]], 2
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = add i32 [[TMP4]], -16
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[NARROW22:%.*]] = tail call i32 @llvm.smax.i32(i32 [[TMP5]], i32 -1)
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV4:%.*]] = and i32 [[NARROW22]], 255
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[ADD:%.*]] = add nsw i32 [[INDEX]], 1
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM6:%.*]] = sext i32 [[ADD]] to i64
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX7:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM6]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV4]], ptr [[ARRAYIDX7]], align 4, !tbaa [[TBAA2]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = sub i32 [[TMP6]], [[FAM_IDX]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp sgt i32 [[TMP7]], -1
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = shl i32 [[TMP7]], 2
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP9:%.*]] = and i32 [[TMP8]], 252
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV10:%.*]] = select i1 [[DOTINV]], i32 [[TMP9]], i32 255
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[ADD12:%.*]] = add nsw i32 [[INDEX]], 2
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM13:%.*]] = sext i32 [[ADD12]] to i64
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX14:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM13]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV10]], ptr [[ARRAYIDX14]], align 4, !tbaa [[TBAA2]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: ret void
|
||||
//
|
||||
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test4(
|
||||
// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[FAM_IDX:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: entry:
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]]
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: store i32 255, ptr [[ARRAYIDX5]], align 4, !tbaa [[TBAA2]]
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[ADD:%.*]] = add nsw i32 [[INDEX]], 1
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM17:%.*]] = sext i32 [[ADD]] to i64
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX18:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM17]]
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: store i32 255, ptr [[ARRAYIDX18]], align 4, !tbaa [[TBAA2]]
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[ADD31:%.*]] = add nsw i32 [[INDEX]], 2
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM32:%.*]] = sext i32 [[ADD31]] to i64
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX33:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM32]]
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: store i32 255, ptr [[ARRAYIDX33]], align 4, !tbaa [[TBAA2]]
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: ret void
|
||||
//
|
||||
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test4(
|
||||
// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[FAM_IDX:%.*]]) local_unnamed_addr #[[ATTR1]] {
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry:
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]]
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 255, ptr [[ARRAYIDX3]], align 4, !tbaa [[TBAA2]]
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ADD:%.*]] = add nsw i32 [[INDEX]], 1
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM9:%.*]] = sext i32 [[ADD]] to i64
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX10:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM9]]
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 255, ptr [[ARRAYIDX10]], align 4, !tbaa [[TBAA2]]
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ADD17:%.*]] = add nsw i32 [[INDEX]], 2
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM18:%.*]] = sext i32 [[ADD17]] to i64
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX19:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM18]]
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 255, ptr [[ARRAYIDX19]], align 4, !tbaa [[TBAA2]]
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
|
||||
//
|
||||
void test4(struct annotated *p, int index, int fam_idx) {
|
||||
// This tests calculating the size from a pointer inside the FAM.
|
||||
p->array[index] = (unsigned char)__builtin_dynamic_object_size(&p->array[3], 1);
|
||||
p->array[index + 1] = (unsigned char)__builtin_dynamic_object_size(&(p->array[4]), 1);
|
||||
p->array[index + 2] = (unsigned char)__builtin_dynamic_object_size(&(p->array[fam_idx]), 1);
|
||||
}
|
||||
|
||||
// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test5(
|
||||
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
||||
// 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: 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: 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]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = shl nuw i64 [[TMP0]], 2
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = tail call i64 @llvm.umax.i64(i64 [[TMP4]], i64 16)
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp sgt i64 [[TMP4]], -1
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i32 [[TMP6]], i32 -1
|
||||
// SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: ret void
|
||||
//
|
||||
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test5(
|
||||
// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: entry:
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 0, i32 1
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i64, ptr [[COUNT]], align 8, !tbaa [[TBAA6:![0-9]+]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl nuw i64 [[TMP0]], 2
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = tail call i64 @llvm.umax.i64(i64 [[TMP1]], i64 16)
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp sgt i64 [[TMP1]], -1
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = trunc i64 [[TMP2]] to i32
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i32 [[TMP3]], i32 -1
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT]], ptr [[P]], i64 1
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: ret void
|
||||
//
|
||||
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test4(
|
||||
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test5(
|
||||
// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: entry:
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 1
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]]
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: store i32 -1, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: ret void
|
||||
//
|
||||
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test4(
|
||||
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test5(
|
||||
// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry:
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 1
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]]
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 -1, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
|
||||
//
|
||||
void test4(struct annotated_with_anon_struct *p, int index) {
|
||||
void test5(struct anon_struct *p, int index) {
|
||||
p->array[index] = __builtin_dynamic_object_size(p, 1);
|
||||
}
|
||||
|
||||
// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test6(
|
||||
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
||||
// 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: 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: 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]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = shl nuw i64 [[TMP0]], 2
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = tail call i64 @llvm.smax.i64(i64 [[TMP4]], i64 -1)
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = trunc i64 [[TMP5]] to i32
|
||||
// SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: ret void
|
||||
//
|
||||
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test6(
|
||||
// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: entry:
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 0, i32 1
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i64, ptr [[COUNT]], align 8, !tbaa [[TBAA6]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl nuw i64 [[TMP0]], 2
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = tail call i64 @llvm.smax.i64(i64 [[TMP1]], i64 -1)
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = trunc i64 [[TMP2]] to i32
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT]], ptr [[P]], i64 1
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: ret void
|
||||
//
|
||||
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test6(
|
||||
// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: entry:
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 1
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]]
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: store i32 -1, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: ret void
|
||||
//
|
||||
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test6(
|
||||
// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry:
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 1
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]]
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 -1, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
|
||||
//
|
||||
void test6(struct anon_struct *p, int index) {
|
||||
p->array[index] = __builtin_dynamic_object_size(p->array, 1);
|
||||
}
|
||||
|
||||
// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test7(
|
||||
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
||||
// 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
|
||||
// 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: 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: 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: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[TMP5]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = icmp slt i32 [[TMP1]], 0
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = tail call i32 @llvm.smax.i32(i32 [[TMP1]], i32 12)
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = trunc i32 [[TMP7]] to i8
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP9:%.*]] = add i8 [[TMP8]], 4
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[TMP6]], i8 -1, i8 [[TMP9]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: store i8 [[CONV]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA10:![0-9]+]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: ret void
|
||||
//
|
||||
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test7(
|
||||
// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: entry:
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 8, !tbaa [[TBAA8:![0-9]+]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = tail call i32 @llvm.smax.i32(i32 [[TMP1]], i32 12)
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp slt i32 [[TMP1]], 0
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP2]] to i8
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = add i8 [[TMP4]], 4
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[TMP3]], i8 -1, i8 [[TMP5]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: store i8 [[CONV]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA8]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: ret void
|
||||
//
|
||||
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test7(
|
||||
// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: entry:
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]]
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6:![0-9]+]]
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: ret void
|
||||
//
|
||||
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test7(
|
||||
// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry:
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]]
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6:![0-9]+]]
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
|
||||
//
|
||||
void test7(struct union_of_fams *p, int index) {
|
||||
p->ints[index] = __builtin_dynamic_object_size(p, 1);
|
||||
}
|
||||
|
||||
// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test8(
|
||||
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
||||
// 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 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: 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: 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]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: store i8 [[TMP1]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA10]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: ret void
|
||||
//
|
||||
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test8(
|
||||
// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: entry:
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[TMP0]], align 8, !tbaa [[TBAA8]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: store i8 [[TMP1]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA8]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: ret void
|
||||
//
|
||||
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test8(
|
||||
// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: entry:
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]]
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]]
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: ret void
|
||||
//
|
||||
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test8(
|
||||
// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry:
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]]
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]]
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
|
||||
//
|
||||
void test8(struct union_of_fams *p, int index) {
|
||||
p->ints[index] = __builtin_dynamic_object_size(p->ints, 1);
|
||||
}
|
||||
|
||||
// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test9(
|
||||
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
||||
// 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: 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: 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]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = icmp slt i32 [[TMP1]], 0
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = tail call i32 @llvm.smax.i32(i32 [[TMP1]], i32 12)
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = trunc i32 [[TMP7]] to i8
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[TMP9:%.*]] = add i8 [[TMP8]], 4
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[TMP6]], i8 -1, i8 [[TMP9]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: store i8 [[CONV]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA10]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: ret void
|
||||
//
|
||||
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test9(
|
||||
// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: entry:
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 8, !tbaa [[TBAA8]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = tail call i32 @llvm.smax.i32(i32 [[TMP1]], i32 12)
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp slt i32 [[TMP1]], 0
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP2]] to i8
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = add i8 [[TMP4]], 4
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[TMP3]], i8 -1, i8 [[TMP5]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: store i8 [[CONV]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA8]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: ret void
|
||||
//
|
||||
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test9(
|
||||
// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: entry:
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]]
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]]
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: ret void
|
||||
//
|
||||
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test9(
|
||||
// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry:
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]]
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]]
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
|
||||
//
|
||||
void test9(struct union_of_fams *p, int index) {
|
||||
p->bytes[index] = (unsigned char)__builtin_dynamic_object_size(p, 1);
|
||||
}
|
||||
|
||||
// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test10(
|
||||
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
||||
// 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: 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: 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]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = tail call i32 @llvm.smax.i32(i32 [[TMP1]], i32 -1)
|
||||
// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = trunc i32 [[NARROW]] to i8
|
||||
// SANITIZE-WITH-ATTR-NEXT: store i8 [[CONV]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA10]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: ret void
|
||||
//
|
||||
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test10(
|
||||
// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] {
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: entry:
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 8, !tbaa [[TBAA8]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = tail call i32 @llvm.smax.i32(i32 [[TMP1]], i32 -1)
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = trunc i32 [[NARROW]] to i8
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: store i8 [[CONV]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA8]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: ret void
|
||||
//
|
||||
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test10(
|
||||
// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: entry:
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]]
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]]
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: ret void
|
||||
//
|
||||
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test10(
|
||||
// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] {
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry:
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]]
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]]
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
|
||||
//
|
||||
void test10(struct union_of_fams *p, int index) {
|
||||
p->bytes[index] = (unsigned char)__builtin_dynamic_object_size(p->bytes, 1);
|
||||
}
|
||||
|
||||
// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test11(
|
||||
// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
||||
// 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: 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: 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]]
|
||||
// SANITIZE-WITH-ATTR-NEXT: ret void
|
||||
//
|
||||
// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test11(
|
||||
// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef writeonly [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: entry:
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: store i32 4, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
|
||||
// NO-SANITIZE-WITH-ATTR-NEXT: ret void
|
||||
//
|
||||
// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test11(
|
||||
// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: entry:
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]]
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: store i32 4, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
|
||||
// SANITIZE-WITHOUT-ATTR-NEXT: ret void
|
||||
//
|
||||
// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test11(
|
||||
// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nocapture noundef writeonly [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] {
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry:
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]]
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 4, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
|
||||
// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void
|
||||
//
|
||||
void test11(struct annotated *p, int index) {
|
||||
p->array[index] = __builtin_dynamic_object_size(&p->count, 1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user