diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index c5a89e032b29..6773d0bbe827 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -208,6 +208,34 @@ unsigned CodeGenFunction::getAccessedFieldNo(unsigned Idx, return cast(Elts->getOperand(Idx))->getZExtValue(); } +void CodeGenFunction::EmitCheck(llvm::Value *Address, unsigned Size) { + if (!CatchUndefined) + return; + + const llvm::IntegerType *Size_tTy + = llvm::IntegerType::get(VMContext, LLVMPointerWidth); + Address = Builder.CreateBitCast(Address, PtrToInt8Ty); + + const llvm::Type *ResType[] = { + Size_tTy + }; + llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::objectsize, ResType, 1); + const llvm::IntegerType *IntTy = cast( + CGM.getTypes().ConvertType(CGM.getContext().IntTy)); + // In time, people may want to control this and use a 1 here. + llvm::Value *Arg = llvm::ConstantInt::get(IntTy, 0); + llvm::Value *C = Builder.CreateCall2(F, Address, Arg); + llvm::BasicBlock *Cont = createBasicBlock(); + llvm::BasicBlock *Check = createBasicBlock(); + llvm::Value *NegativeOne = llvm::ConstantInt::get(Size_tTy, -1ULL); + Builder.CreateCondBr(Builder.CreateICmpEQ(C, NegativeOne), Cont, Check); + + EmitBlock(Check); + Builder.CreateCondBr(Builder.CreateICmpUGE(C, + llvm::ConstantInt::get(Size_tTy, Size)), + Cont, getTrapBB()); + EmitBlock(Cont); +} //===----------------------------------------------------------------------===// // LValue Expression Emission @@ -245,6 +273,13 @@ LValue CodeGenFunction::EmitUnsupportedLValue(const Expr *E, MakeQualifiers(E->getType())); } +LValue CodeGenFunction::EmitCheckedLValue(const Expr *E) { + LValue LV = EmitLValue(E); + if (!isa(E) && !LV.isBitfield() && LV.isSimple()) + EmitCheck(LV.getAddress(), getContext().getTypeSize(E->getType()) / 8); + return LV; +} + /// EmitLValue - Emit code to compute a designator that specifies the location /// of the expression. /// @@ -1071,8 +1106,9 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { llvm::IntegerType::get(VMContext, LLVMPointerWidth), IdxSigned, "idxprom"); + // FIXME: As llvm implements the object size checking, this can come out. if (CatchUndefined) { - if (const ImplicitCastExpr *ICE = dyn_cast(E->getBase())) { + if (const ImplicitCastExpr *ICE=dyn_cast(E->getBase())) { if (const DeclRefExpr *DRE = dyn_cast(ICE->getSubExpr())) { if (ICE->getCastKind() == CastExpr::CK_ArrayToPointerDecay) { if (const ConstantArrayType *CAT diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 2f31c051a78d..07909faa75ea 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -69,6 +69,7 @@ public: const llvm::Type *ConvertType(QualType T) { return CGF.ConvertType(T); } LValue EmitLValue(const Expr *E) { return CGF.EmitLValue(E); } + LValue EmitCheckedLValue(const Expr *E) { return CGF.EmitCheckedLValue(E); } Value *EmitLoadOfLValue(LValue LV, QualType T) { return CGF.EmitLoadOfLValue(LV, T).getScalarVal(); @@ -78,7 +79,7 @@ public: /// value l-value, this method emits the address of the l-value, then loads /// and returns the result. Value *EmitLoadOfLValue(const Expr *E) { - return EmitLoadOfLValue(EmitLValue(E), E->getType()); + return EmitLoadOfLValue(EmitCheckedLValue(E), E->getType()); } /// EmitConversionToBool - Convert the specified expression value to a @@ -1217,7 +1218,7 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E, OpInfo.Ty = E->getComputationResultType(); OpInfo.E = E; // Load/convert the LHS. - LValue LHSLV = EmitLValue(E->getLHS()); + LValue LHSLV = EmitCheckedLValue(E->getLHS()); OpInfo.LHS = EmitLoadOfLValue(LHSLV, LHSTy); OpInfo.LHS = EmitScalarConversion(OpInfo.LHS, LHSTy, E->getComputationLHSType()); @@ -1654,7 +1655,7 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) { // __block variables need to have the rhs evaluated first, plus this should // improve codegen just a little. Value *RHS = Visit(E->getRHS()); - LValue LHS = EmitLValue(E->getLHS()); + LValue LHS = EmitCheckedLValue(E->getLHS()); // Store the value into the LHS. Bit-fields are handled specially // because the result is altered by the store, i.e., [C99 6.5.16p1] diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 12e636c89702..4bacd16f9288 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -807,6 +807,8 @@ public: llvm::Value* EmitCXXTypeidExpr(const CXXTypeidExpr *E); llvm::Value *EmitDynamicCast(llvm::Value *V, const CXXDynamicCastExpr *DCE); + void EmitCheck(llvm::Value *, unsigned Size); + //===--------------------------------------------------------------------===// // Declaration Emission //===--------------------------------------------------------------------===// @@ -921,6 +923,12 @@ public: /// LValue EmitLValue(const Expr *E); + /// EmitCheckedLValue - Same as EmitLValue but additionally we generate + /// checking code to guard against undefined behavior. This is only + /// suitable when we know that the address will be used to access the + /// object. + LValue EmitCheckedLValue(const Expr *E); + /// EmitLoadOfScalar - Load a scalar value from an address, taking /// care to appropriately convert from the memory representation to /// the LLVM value representation.