diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1249,7 +1249,7 @@ LValue CodeGenFunction::EmitCheckedLValue(const Expr *E, TypeCheckKind TCK) { LValue LV; - if (SanOpts.has(SanitizerKind::ArrayBounds) && isa(E)) + if (isa(E)) LV = EmitArraySubscriptExpr(cast(E), /*Accessed*/true); else LV = EmitLValue(E); @@ -3691,6 +3691,32 @@ return Address(eltPtr, eltAlign); } +// Add range metadata: It is UB to subscript outside of the array, therefore +// array indices are known to be in range: +// * [0, indexing_bound) if the array is accessed. +// * [0, indexing_bound] if only address computation is preformed. +static llvm::Value *addArrayIndexingRangeMetadata(CodeGenFunction &CGF, + const Expr *Base, + llvm::Value *Idx, + bool Accessed) { + QualType IdxTy; + llvm::ConstantInt *Bound = dyn_cast_or_null( + getArrayIndexingBound(CGF, Base, IdxTy)); + if (Bound == nullptr) + return Idx; + llvm::Instruction *AnnotatedIdx = + CGF.Builder.CreateIntrinsic(llvm::Intrinsic::annotation, {Idx->getType()}, + {Idx, llvm::UndefValue::get(CGF.Int8PtrTy), + llvm::UndefValue::get(CGF.Int8PtrTy), + llvm::UndefValue::get(CGF.Int32Ty)}); + llvm::MDBuilder MDHelper(CGF.getLLVMContext()); + AnnotatedIdx->setMetadata( + llvm::LLVMContext::MD_range, + MDHelper.createRange(llvm::APInt(Bound->getBitWidth(), 0), + Bound->getValue() + (Accessed ? 0 : 1))); + return AnnotatedIdx; +} + LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, bool Accessed) { // The index must always be an integer, which is not an aggregate. Emit it @@ -3716,6 +3742,9 @@ if (Promote && Idx->getType() != IntPtrTy) Idx = Builder.CreateIntCast(Idx, IntPtrTy, IdxSigned, "idxprom"); + if (CGM.getCodeGenOpts().OptimizationLevel > 0) + Idx = addArrayIndexingRangeMetadata(*this, E->getBase(), Idx, Accessed); + return Idx; }; IdxPre = nullptr;