diff options
author | Marcin Swiderski <marcin.sfider@gmail.com> | 2010-10-05 05:37:00 +0000 |
---|---|---|
committer | Marcin Swiderski <marcin.sfider@gmail.com> | 2010-10-05 05:37:00 +0000 |
commit | 7c625d8ffc20b92fff9e1690cd2484fcb6498183 (patch) | |
tree | 56800778c4cd3cad1b9f6cc9a41c1853c65ba6b5 /lib/Analysis/CFG.cpp | |
parent | 25e7e1672886b78a00ce25a084c0581704b73a7b (diff) |
Added support for base and member destructors in destructor.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@115592 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/CFG.cpp')
-rw-r--r-- | lib/Analysis/CFG.cpp | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index 4eac9ae351..53479bc058 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -307,6 +307,7 @@ private: CFGBlock *addInitializer(CXXBaseOrMemberInitializer *I); void addAutomaticObjDtors(LocalScope::const_iterator B, LocalScope::const_iterator E, Stmt* S); + void addImplicitDtorsForDestructor(const CXXDestructorDecl *DD); // Local scopes creation. LocalScope* createOrReuseLocalScope(LocalScope* Scope); @@ -325,6 +326,12 @@ private: void appendInitializer(CFGBlock *B, CXXBaseOrMemberInitializer *I) { B->appendInitializer(I, cfg->getBumpVectorContext()); } + void appendBaseDtor(CFGBlock *B, const CXXBaseSpecifier *BS) { + B->appendBaseDtor(BS, cfg->getBumpVectorContext()); + } + void appendMemberDtor(CFGBlock *B, FieldDecl *FD) { + B->appendMemberDtor(FD, cfg->getBumpVectorContext()); + } void insertAutomaticObjDtors(CFGBlock* Blk, CFGBlock::iterator I, LocalScope::const_iterator B, LocalScope::const_iterator E, Stmt* S); @@ -407,6 +414,10 @@ CFG* CFGBuilder::buildCFG(const Decl *D, Stmt* Statement, ASTContext* C, assert(Succ == &cfg->getExit()); Block = NULL; // the EXIT block is empty. Create all other blocks lazily. + if (BuildOpts.AddImplicitDtors) + if (const CXXDestructorDecl *DD = dyn_cast_or_null<CXXDestructorDecl>(D)) + addImplicitDtorsForDestructor(DD); + // Visit the statements and create the CFG. CFGBlock *B = addStmt(Statement); @@ -509,6 +520,46 @@ void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B, appendAutomaticObjDtors(Block, B, E, S); } +/// addImplicitDtorsForDestructor - Add implicit destructors generated for +/// base and member objects in destructor. +void CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) { + assert (BuildOpts.AddImplicitDtors + && "Can be called only when dtors should be added"); + const CXXRecordDecl *RD = DD->getParent(); + + // At the end destroy virtual base objects. + for (CXXRecordDecl::base_class_const_iterator VI = RD->vbases_begin(), + VE = RD->vbases_end(); VI != VE; ++VI) { + const CXXRecordDecl *CD = VI->getType()->getAsCXXRecordDecl(); + if (!CD->hasTrivialDestructor()) { + autoCreateBlock(); + appendBaseDtor(Block, VI); + } + } + + // Before virtual bases destroy direct base objects. + for (CXXRecordDecl::base_class_const_iterator BI = RD->bases_begin(), + BE = RD->bases_end(); BI != BE; ++BI) { + if (!BI->isVirtual()) { + const CXXRecordDecl *CD = BI->getType()->getAsCXXRecordDecl(); + if (!CD->hasTrivialDestructor()) { + autoCreateBlock(); + appendBaseDtor(Block, BI); + } + } + } + + // First destroy member objects. + for (CXXRecordDecl::field_iterator FI = RD->field_begin(), + FE = RD->field_end(); FI != FE; ++FI) { + if (const CXXRecordDecl *CD = FI->getType()->getAsCXXRecordDecl()) + if (!CD->hasTrivialDestructor()) { + autoCreateBlock(); + appendMemberDtor(Block, *FI); + } + } +} + /// createOrReuseLocalScope - If Scope is NULL create new LocalScope. Either /// way return valid LocalScope object. LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) { @@ -2660,6 +2711,17 @@ static void print_elem(llvm::raw_ostream &OS, StmtPrinterHelper* Helper, OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()"; OS << " (Implicit destructor)\n"; + + } else if (CFGBaseDtor BE = E.getAs<CFGBaseDtor>()) { + const CXXBaseSpecifier *BS = BE.getBaseSpecifier(); + OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()"; + OS << " (Base destructor)\n"; + + } else if (CFGMemberDtor ME = E.getAs<CFGMemberDtor>()) { + FieldDecl *FD = ME.getFieldDecl(); + OS << "this->" << FD->getName(); + OS << ".~" << FD->getType()->getAsCXXRecordDecl()->getName() << "()"; + OS << " (Member destructor)\n"; } } |