diff options
author | Anders Carlsson <andersca@mac.com> | 2009-08-16 21:13:42 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2009-08-16 21:13:42 +0000 |
commit | 81f0df9601b39ae24183a68b0b3944ac645f15ad (patch) | |
tree | 857010e12f3e8e18cd0294efc167401e87bd3d43 /clang/lib/CodeGen | |
parent | a127f4e0104b5765d6e5341e82c48477087909bc (diff) | |
download | bcm5719-llvm-81f0df9601b39ae24183a68b0b3944ac645f15ad.tar.gz bcm5719-llvm-81f0df9601b39ae24183a68b0b3944ac645f15ad.zip |
Improve handling of delete expressions.
llvm-svn: 79205
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGCXX.cpp | 57 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 1 |
3 files changed, 62 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index 1c9c5634ab0..5e71064797a 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/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/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 0b8cb8cb761..37d2995142a 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/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/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 3bf17b32b3c..c41af94e20b 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -607,6 +607,7 @@ public: void PopCXXTemporary(); llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E); + void EmitCXXDeleteExpr(const CXXDeleteExpr *E); //===--------------------------------------------------------------------===// // Declaration Emission |