aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/CFG.cpp
diff options
context:
space:
mode:
authorMarcin Swiderski <marcin.sfider@gmail.com>2010-10-05 05:37:00 +0000
committerMarcin Swiderski <marcin.sfider@gmail.com>2010-10-05 05:37:00 +0000
commit7c625d8ffc20b92fff9e1690cd2484fcb6498183 (patch)
tree56800778c4cd3cad1b9f6cc9a41c1853c65ba6b5 /lib/Analysis/CFG.cpp
parent25e7e1672886b78a00ce25a084c0581704b73a7b (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.cpp62
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";
}
}