diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGCXX.cpp | 42 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 7 |
3 files changed, 49 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index bce22e5ec36..8c960c7f985 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/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<CXXRecordDecl>(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<CXXRecordDecl>(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<RecordType>(); + CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(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<RecordType>(); + CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + if (BaseClassDecl->hasTrivialDestructor()) + continue; + llvm::Value *V = AddressCXXOfBaseClass(LoadCXXThis(), + ClassDecl,BaseClassDecl); + EmitCXXDestructorCall(BaseClassDecl->getDestructor(getContext()), + Dtor_Complete, V); + } + } +} diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 82ec1eb603f..fb4b924765d 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -234,6 +234,8 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD, if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) EmitCtorPrologue(CD); EmitStmt(S); + if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) + EmitDtorEpilogue(DD); FinishFunction(S->getRBracLoc()); } diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index a3e37963104..4f8a14af142 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/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. |