diff options
author | Jordan Rose <jordan_rose@apple.com> | 2013-09-03 17:00:57 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2013-09-03 17:00:57 +0000 |
commit | d2f4079db995c9dce34db0347b16df8ace62cf37 (patch) | |
tree | 87711f6c80a2132f91dc03f3c3a6b68328617f5e /clang/lib/Analysis/CFG.cpp | |
parent | c74c4976499b6ae5ff758cf5189b7bd69ca1ddc3 (diff) | |
download | bcm5719-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.cpp | 41 |
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() << "()"; |