summaryrefslogtreecommitdiffstats
path: root/clang/lib/Analysis/CFG.cpp
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2013-09-03 17:00:57 +0000
committerJordan Rose <jordan_rose@apple.com>2013-09-03 17:00:57 +0000
commitd2f4079db995c9dce34db0347b16df8ace62cf37 (patch)
tree87711f6c80a2132f91dc03f3c3a6b68328617f5e /clang/lib/Analysis/CFG.cpp
parentc74c4976499b6ae5ff758cf5189b7bd69ca1ddc3 (diff)
downloadbcm5719-llvm-d2f4079db995c9dce34db0347b16df8ace62cf37.tar.gz
bcm5719-llvm-d2f4079db995c9dce34db0347b16df8ace62cf37.zip
Add an implicit dtor CFG node just before C++ 'delete' expressions.
This paves the way for adding support for modeling the destructor of a region before it is deleted. The statement "delete <expr>" now generates this series of CFG elements: 1. <expr> 2. [B1.1]->~Foo() (Implicit destructor) 3. delete [B1.1] Patch by Karthik Bhat! llvm-svn: 189828
Diffstat (limited to 'clang/lib/Analysis/CFG.cpp')
-rw-r--r--clang/lib/Analysis/CFG.cpp41
1 files changed, 41 insertions, 0 deletions
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index ad0acb7abe5..5e03f4377d3 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -363,6 +363,7 @@ private:
AddStmtChoice asc);
CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S);
CFGBlock *VisitCXXConstructExpr(CXXConstructExpr *C, AddStmtChoice asc);
+ CFGBlock *VisitCXXDeleteExpr(CXXDeleteExpr *DE, AddStmtChoice asc);
CFGBlock *VisitCXXForRangeStmt(CXXForRangeStmt *S);
CFGBlock *VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
AddStmtChoice asc);
@@ -471,6 +472,10 @@ private:
B->appendAutomaticObjDtor(VD, S, cfg->getBumpVectorContext());
}
+ void appendDeleteDtor(CFGBlock *B, CXXRecordDecl *RD, CXXDeleteExpr *DE) {
+ B->appendDeleteDtor(RD, DE, cfg->getBumpVectorContext());
+ }
+
void prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk,
LocalScope::const_iterator B, LocalScope::const_iterator E);
@@ -1117,6 +1122,9 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) {
case Stmt::CXXConstructExprClass:
return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc);
+ case Stmt::CXXDeleteExprClass:
+ return VisitCXXDeleteExpr(cast<CXXDeleteExpr>(S), asc);
+
case Stmt::CXXFunctionalCastExprClass:
return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc);
@@ -3113,6 +3121,22 @@ CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C,
return VisitChildren(C);
}
+
+CFGBlock *CFGBuilder::VisitCXXDeleteExpr(CXXDeleteExpr *DE,
+ AddStmtChoice asc) {
+ autoCreateBlock();
+ appendStmt(Block, DE);
+ QualType DTy = DE->getDestroyedType();
+ DTy = DTy.getNonReferenceType();
+ CXXRecordDecl *RD = Context->getBaseElementType(DTy)->getAsCXXRecordDecl();
+ if (RD) {
+ if (!RD->hasTrivialDestructor())
+ appendDeleteDtor(Block, RD, DE);
+ }
+
+ return VisitChildren(DE);
+}
+
CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
AddStmtChoice asc) {
if (asc.alwaysAdd(*this, E)) {
@@ -3413,6 +3437,14 @@ CFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const {
cast<CXXRecordDecl>(recordType->getDecl());
return classDecl->getDestructor();
}
+ case CFGElement::DeleteDtor: {
+ const CXXDeleteExpr *DE = castAs<CFGDeleteDtor>().getDeleteExpr();
+ QualType DTy = DE->getDestroyedType();
+ DTy = DTy.getNonReferenceType();
+ const CXXRecordDecl *classDecl =
+ astContext.getBaseElementType(DTy)->getAsCXXRecordDecl();
+ return classDecl->getDestructor();
+ }
case CFGElement::TemporaryDtor: {
const CXXBindTemporaryExpr *bindExpr =
castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
@@ -3751,6 +3783,15 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper* Helper,
OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()";
OS << " (Implicit destructor)\n";
+ } else if (Optional<CFGDeleteDtor> DE = E.getAs<CFGDeleteDtor>()) {
+ const CXXRecordDecl *RD = DE->getCXXRecordDecl();
+ if (!RD)
+ return;
+ CXXDeleteExpr *DelExpr =
+ const_cast<CXXDeleteExpr*>(DE->getDeleteExpr());
+ Helper->handledStmt(cast<Stmt>(DelExpr->getArgument()), OS);
+ OS << "->~" << RD->getName().str() << "()";
+ OS << " (Implicit destructor)\n";
} else if (Optional<CFGBaseDtor> BE = E.getAs<CFGBaseDtor>()) {
const CXXBaseSpecifier *BS = BE->getBaseSpecifier();
OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()";
OpenPOWER on IntegriCloud