diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 57 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 1 |
3 files changed, 62 insertions, 0 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 1c9c5634ab..5e71064797 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -514,6 +514,63 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { return NewPtr; } +void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { + if (E->isArrayForm()) { + ErrorUnsupported(E, "delete[] expression"); + return; + }; + + QualType DeleteTy = + E->getArgument()->getType()->getAs<PointerType>()->getPointeeType(); + + llvm::Value *Ptr = EmitScalarExpr(E->getArgument()); + + // Null check the pointer. + llvm::BasicBlock *DeleteNotNull = createBasicBlock("delete.notnull"); + llvm::BasicBlock *DeleteEnd = createBasicBlock("delete.end"); + + llvm::Value *IsNull = + Builder.CreateICmpEQ(Ptr, llvm::Constant::getNullValue(Ptr->getType()), + "isnull"); + + Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull); + EmitBlock(DeleteNotNull); + + // Call the destructor if necessary. + if (const RecordType *RT = DeleteTy->getAs<RecordType>()) { + if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) { + if (!RD->hasTrivialDestructor()) { + const CXXDestructorDecl *Dtor = RD->getDestructor(getContext()); + if (Dtor->isVirtual()) { + ErrorUnsupported(E, "delete expression with virtual destructor"); + return; + } + + EmitCXXDestructorCall(Dtor, Dtor_Complete, Ptr); + } + } + } + + // Call delete. + FunctionDecl *DeleteFD = E->getOperatorDelete(); + const FunctionProtoType *DeleteFTy = + DeleteFD->getType()->getAsFunctionProtoType(); + + CallArgList DeleteArgs; + + QualType ArgTy = DeleteFTy->getArgType(0); + llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy)); + DeleteArgs.push_back(std::make_pair(RValue::get(DeletePtr), ArgTy)); + + // Emit the call to delete. + EmitCall(CGM.getTypes().getFunctionInfo(DeleteFTy->getResultType(), + DeleteArgs), + CGM.GetAddrOfFunction(GlobalDecl(DeleteFD)), + DeleteArgs, DeleteFD); + + EmitBlock(DeleteEnd); +} + static bool canGenerateCXXstructor(const CXXRecordDecl *RD, ASTContext &Context) { // The class has base classes - we don't support that right now. diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 0b8cb8cb76..37d2995142 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -293,6 +293,10 @@ public: Value *VisitCXXNewExpr(const CXXNewExpr *E) { return CGF.EmitCXXNewExpr(E); } + Value *VisitCXXDeleteExpr(const CXXDeleteExpr *E) { + CGF.EmitCXXDeleteExpr(E); + return 0; + } // Binary Operators. Value *EmitMul(const BinOpInfo &Ops) { diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 3bf17b32b3..c41af94e20 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -607,6 +607,7 @@ public: void PopCXXTemporary(); llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E); + void EmitCXXDeleteExpr(const CXXDeleteExpr *E); //===--------------------------------------------------------------------===// // Declaration Emission |