[cfe-commits] r115592 - in /cfe/trunk: include/clang/Analysis/CFG.h lib/Analysis/CFG.cpp test/Analysis/dtors-in-dtor-cfg-output.cpp
Marcin Swiderski
marcin.sfider at gmail.com
Mon Oct 4 22:37:00 PDT 2010
Author: sfider
Date: Tue Oct 5 00:37:00 2010
New Revision: 115592
URL: http://llvm.org/viewvc/llvm-project?rev=115592&view=rev
Log:
Added support for base and member destructors in destructor.
Added:
cfe/trunk/test/Analysis/dtors-in-dtor-cfg-output.cpp
Modified:
cfe/trunk/include/clang/Analysis/CFG.h
cfe/trunk/lib/Analysis/CFG.cpp
Modified: cfe/trunk/include/clang/Analysis/CFG.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/CFG.h?rev=115592&r1=115591&r2=115592&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/CFG.h (original)
+++ cfe/trunk/include/clang/Analysis/CFG.h Tue Oct 5 00:37:00 2010
@@ -31,8 +31,10 @@
class Decl;
class Stmt;
class Expr;
+ class FieldDecl;
class VarDecl;
class CXXBaseOrMemberInitializer;
+ class CXXBaseSpecifier;
class CFG;
class PrinterHelper;
class LangOptions;
@@ -139,7 +141,7 @@
}
};
-/// CFGAutomaticObjDtor - Represents C++ object destructor implicit generated
+/// CFGAutomaticObjDtor - Represents C++ object destructor implicitly generated
/// for automatic object or temporary bound to const reference at the point
/// of leaving its local scope.
class CFGAutomaticObjDtor: public CFGImplicitDtor {
@@ -162,19 +164,38 @@
}
};
+/// CFGBaseDtor - Represents C++ object destructor implicitly generated for
+/// base object in destructor.
class CFGBaseDtor : public CFGImplicitDtor {
public:
+ CFGBaseDtor() {}
+ CFGBaseDtor(const CXXBaseSpecifier *BS)
+ : CFGImplicitDtor(BaseDtor, const_cast<CXXBaseSpecifier*>(BS), NULL) {}
+
+ const CXXBaseSpecifier *getBaseSpecifier() const {
+ return static_cast<const CXXBaseSpecifier*>(Data1.getPointer());
+ }
+
static bool classof(const CFGElement *E) {
return E->getKind() == Dtor && E->getDtorKind() == BaseDtor;
}
};
+/// CFGMemberDtor - Represents C++ object destructor implicitly generated for
+/// member object in destructor.
class CFGMemberDtor : public CFGImplicitDtor {
public:
+ CFGMemberDtor() {}
+ CFGMemberDtor(FieldDecl *FD)
+ : CFGImplicitDtor(MemberDtor, FD, NULL) {}
+
+ FieldDecl *getFieldDecl() const {
+ return static_cast<FieldDecl*>(Data1.getPointer());
+ }
+
static bool classof(const CFGElement *E) {
return E->getKind() == Dtor && E->getDtorKind() == MemberDtor;
}
-
};
class CFGTemporaryDtor : public CFGImplicitDtor {
@@ -437,6 +458,14 @@
Elements.push_back(CFGInitializer(I), C);
}
+ void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C) {
+ Elements.push_back(CFGBaseDtor(BS), C);
+ }
+
+ void appendMemberDtor(FieldDecl *FD, BumpVectorContext &C) {
+ Elements.push_back(CFGMemberDtor(FD), C);
+ }
+
// Destructors must be inserted in reversed order. So insertion is in two
// steps. First we prepare space for some number of elements, then we insert
// the elements beginning at the last position in prepared space.
Modified: cfe/trunk/lib/Analysis/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=115592&r1=115591&r2=115592&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CFG.cpp (original)
+++ cfe/trunk/lib/Analysis/CFG.cpp Tue Oct 5 00:37:00 2010
@@ -307,6 +307,7 @@
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 @@
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 @@
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 @@
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 @@
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";
}
}
Added: cfe/trunk/test/Analysis/dtors-in-dtor-cfg-output.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/dtors-in-dtor-cfg-output.cpp?rev=115592&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/dtors-in-dtor-cfg-output.cpp (added)
+++ cfe/trunk/test/Analysis/dtors-in-dtor-cfg-output.cpp Tue Oct 5 00:37:00 2010
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -analyze -cfg-dump -cfg-add-implicit-dtors %s 2>&1 | FileCheck %s
+// XPASS: *
+
+class A {
+public:
+ ~A() {}
+};
+
+class B : public virtual A {
+public:
+ ~B() {}
+};
+
+class C : public virtual A {
+public:
+ ~C() {}
+};
+
+class TestOrder : public C, public B, public virtual A {
+ A a;
+ int i;
+ A *p;
+public:
+ ~TestOrder();
+};
+
+TestOrder::~TestOrder() {}
+
+// CHECK: [ B2 (ENTRY) ]
+// CHECK: Predecessors (0):
+// CHECK: Successors (1): B1
+// CHECK: [ B1 ]
+// CHECK: 1: this->a.~A() (Member object destructor)
+// CHECK: 2: ~B() (Base object destructor)
+// CHECK: 3: ~C() (Base object destructor)
+// CHECK: 4: ~A() (Base object destructor)
+// CHECK: Predecessors (1): B2
+// CHECK: Successors (1): B0
+// CHECK: [ B0 (EXIT) ]
+// CHECK: Predecessors (1): B1
+// CHECK: Successors (0):
More information about the cfe-commits
mailing list