diff options
-rw-r--r-- | include/clang/Checker/PathSensitive/GRExprEngine.h | 4 | ||||
-rw-r--r-- | lib/Checker/GRCXXExprEngine.cpp | 24 | ||||
-rw-r--r-- | lib/Checker/GRExprEngine.cpp | 13 | ||||
-rw-r--r-- | lib/Checker/RegionStore.cpp | 2 | ||||
-rw-r--r-- | test/Analysis/dtor.cpp | 13 |
5 files changed, 55 insertions, 1 deletions
diff --git a/include/clang/Checker/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h index d49fd85e6f..bb0c068057 100644 --- a/include/clang/Checker/PathSensitive/GRExprEngine.h +++ b/include/clang/Checker/PathSensitive/GRExprEngine.h @@ -428,6 +428,10 @@ public: void VisitCXXConstructExpr(const CXXConstructExpr *E, const MemRegion *Dest, ExplodedNode *Pred, ExplodedNodeSet &Dst); + void VisitCXXDestructor(const CXXDestructorDecl *DD, + const MemRegion *Dest, const Stmt *S, + ExplodedNode *Pred, ExplodedNodeSet &Dst); + void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE, ExplodedNode *Pred, ExplodedNodeSet &Dst); diff --git a/lib/Checker/GRCXXExprEngine.cpp b/lib/Checker/GRCXXExprEngine.cpp index 642c26e240..ecc1490ce6 100644 --- a/lib/Checker/GRCXXExprEngine.cpp +++ b/lib/Checker/GRCXXExprEngine.cpp @@ -143,6 +143,30 @@ void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, } } +void GRExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD, + const MemRegion *Dest, + const Stmt *S, + ExplodedNode *Pred, + ExplodedNodeSet &Dst) { + if (!(DD->isThisDeclarationADefinition() && AMgr.shouldInlineCall())) + return; + // Create the context for 'this' region. + const StackFrameContext *SFC = AMgr.getStackFrame(DD, + Pred->getLocationContext(), + S, Builder->getBlock(), + Builder->getIndex()); + + const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC); + + CallEnter PP(S, SFC->getAnalysisContext(), Pred->getLocationContext()); + + const GRState *state = Pred->getState(); + state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest)); + ExplodedNode *N = Builder->generateNode(PP, state, Pred); + if (N) + Dst.Add(N); +} + void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE, ExplodedNode *Pred, ExplodedNodeSet &Dst) { diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index ddd3d50fe5..4483cdb76c 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/lib/Checker/GRExprEngine.cpp @@ -718,6 +718,8 @@ void GRExprEngine::ProcessInitializer(const CFGInitializer Init, void GRExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D, GRStmtNodeBuilder &builder) { + Builder = &builder; + switch (D.getDtorKind()) { case CFGElement::AutomaticObjectDtor: ProcessAutomaticObjDtor(cast<CFGAutomaticObjDtor>(D), builder); @@ -738,6 +740,17 @@ void GRExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D, void GRExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D, GRStmtNodeBuilder &builder) { + ExplodedNode *Pred = builder.getBasePredecessor(); + const GRState *state = Pred->getState(); + const VarDecl *VD = D.getVarDecl(); + const CXXRecordDecl *CD = VD->getType()->getAsCXXRecordDecl(); + const CXXDestructorDecl *DD = CD->getDestructor(); + + Loc Dest = state->getLValue(VD, Pred->getLocationContext()); + + ExplodedNodeSet Dst; + VisitCXXDestructor(DD, cast<loc::MemRegionVal>(Dest).getRegion(), + D.getTriggerStmt(), Pred, Dst); } void GRExprEngine::ProcessBaseDtor(const CFGBaseDtor D, diff --git a/lib/Checker/RegionStore.cpp b/lib/Checker/RegionStore.cpp index 7808872f5d..144c925b8c 100644 --- a/lib/Checker/RegionStore.cpp +++ b/lib/Checker/RegionStore.cpp @@ -1828,7 +1828,7 @@ Store RegionStoreManager::EnterStackFrame(const GRState *state, store = Bind(store, ValMgr.makeLoc(MRMgr.getVarRegion(*PI,frame)),ArgVal); } } else - llvm_unreachable("Unhandled call expression."); + assert(isa<CXXDestructorDecl>(frame->getDecl())); return store; } diff --git a/test/Analysis/dtor.cpp b/test/Analysis/dtor.cpp new file mode 100644 index 0000000000..ea5b04684d --- /dev/null +++ b/test/Analysis/dtor.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store region -analyzer-inline-call -cfg-add-implicit-dtors -verify %s + +class A { +public: + ~A() { + int *x = 0; + *x = 3; // expected-warning{{Dereference of null pointer}} + } +}; + +int main() { + A a; +} |