From: Fariborz Jahanian Date: Thu, 30 Jul 2009 17:49:11 +0000 (+0000) Subject: Patch for future ir-gen for destructor calls. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=426cc3828ce07a2cff15c9837f5958e6fc4b7739;p=clang Patch for future ir-gen for destructor calls. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77608 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 3da7230ab0..5a4923c869 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -1096,7 +1096,7 @@ public: return 0; } /// getMemberToDestroy - Get the member for the given object. - FieldDecl *getMemberToDestroy(uintptr_t Member) { + FieldDecl *getMemberToDestroy(uintptr_t Member) const { if (isMemberToDestroy(Member)) return reinterpret_cast(Member); return 0; diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index bce22e5ec3..8c960c7f98 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -489,7 +489,7 @@ const char *CodeGenModule::getMangledCXXDtorName(const CXXDestructorDecl *D, /// base classes and non-static data members belonging to this constructor. void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD) { const CXXRecordDecl *ClassDecl = cast(CD->getDeclContext()); - assert(ClassDecl->vbases_begin() == ClassDecl->vbases_end() + assert(!ClassDecl->isPolymorphic() && "FIXME. virtual base initialization unsupported"); for (CXXConstructorDecl::init_const_iterator B = CD->init_begin(), @@ -538,3 +538,43 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD) { } } } + +/// EmitDtorEpilogue - Emit all code that comes at the end of class's +/// destructor. This is to call destructors on members and base classes +/// in reverse order of their construction. +void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD) { + const CXXRecordDecl *ClassDecl = cast(DD->getDeclContext()); + assert(!ClassDecl->isPolymorphic() && + "FIXME. polymorphic destruction not supported"); + (void)ClassDecl; // prevent warning. + + for (CXXDestructorDecl::destr_const_iterator *B = DD->destr_begin(), + *E = DD->destr_end(); B != E; ++B) { + uintptr_t BaseOrMember = (*B); + if (DD->isMemberToDestroy(BaseOrMember)) { + FieldDecl *FD = DD->getMemberToDestroy(BaseOrMember); + QualType FieldType = getContext().getCanonicalType((FD)->getType()); + assert(!getContext().getAsArrayType(FieldType) + && "FIXME. Field arrays destruction unsupported"); + const RecordType *RT = FieldType->getAs(); + CXXRecordDecl *FieldClassDecl = cast(RT->getDecl()); + if (FieldClassDecl->hasTrivialDestructor()) + continue; + llvm::Value *LoadOfThis = LoadCXXThis(); + LValue LHS = EmitLValueForField(LoadOfThis, FD, false, 0); + EmitCXXDestructorCall(FieldClassDecl->getDestructor(getContext()), + Dtor_Complete, LHS.getAddress()); + } + else { + const RecordType *RT = + DD->getAnyBaseClassToDestroy(BaseOrMember)->getAs(); + CXXRecordDecl *BaseClassDecl = cast(RT->getDecl()); + if (BaseClassDecl->hasTrivialDestructor()) + continue; + llvm::Value *V = AddressCXXOfBaseClass(LoadCXXThis(), + ClassDecl,BaseClassDecl); + EmitCXXDestructorCall(BaseClassDecl->getDestructor(getContext()), + Dtor_Complete, V); + } + } +} diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 82ec1eb603..fb4b924765 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -234,6 +234,8 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD, if (const CXXConstructorDecl *CD = dyn_cast(FD)) EmitCtorPrologue(CD); EmitStmt(S); + if (const CXXDestructorDecl *DD = dyn_cast(FD)) + EmitDtorEpilogue(DD); FinishFunction(S->getRBracLoc()); } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index a3e3796310..4f8a14af14 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -359,7 +359,12 @@ public: void FinishFunction(SourceLocation EndLoc=SourceLocation()); void EmitCtorPrologue(const CXXConstructorDecl *CD); - + + /// EmitDtorEpilogue - Emit all code that comes at the end of class's + /// destructor. This is to call destructors on members and base classes + /// in reverse order of their construction. + void EmitDtorEpilogue(const CXXDestructorDecl *DD); + /// EmitFunctionProlog - Emit the target specific LLVM code to load the /// arguments for the given function. This is also responsible for naming the /// LLVM function arguments.