diff options
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h | 28 | ||||
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h | 4 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp | 6 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/CallEvent.cpp | 13 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 6 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 3 | ||||
-rw-r--r-- | test/Analysis/dtor.cpp | 30 |
7 files changed, 73 insertions, 17 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index d9712208f0..912eea0b37 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -604,6 +604,8 @@ class CXXDestructorCall : public CXXInstanceCall { friend class CallEventManager; protected: + typedef llvm::PointerIntPair<const MemRegion *, 1, bool> DtorDataTy; + /// Creates an implicit destructor. /// /// \param DD The destructor that will be called. @@ -612,10 +614,10 @@ protected: /// \param St The path-sensitive state at this point in the program. /// \param LCtx The location context at this point in the program. CXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger, - const MemRegion *Target, ProgramStateRef St, - const LocationContext *LCtx) + const MemRegion *Target, bool IsBaseDestructor, + ProgramStateRef St, const LocationContext *LCtx) : CXXInstanceCall(DD, St, LCtx) { - Data = Target; + Data = DtorDataTy(Target, IsBaseDestructor).getOpaqueValue(); Location = Trigger->getLocEnd(); } @@ -626,9 +628,16 @@ public: virtual SourceRange getSourceRange() const { return Location; } virtual unsigned getNumArgs() const { return 0; } + virtual RuntimeDefinition getRuntimeDefinition() const; + /// \brief Returns the value of the implicit 'this' object. virtual SVal getCXXThisVal() const; + /// Returns true if this is a call to a base class destructor. + bool isBaseDestructor() const { + return DtorDataTy::getFromOpaqueValue(Data).getInt(); + } + virtual Kind getKind() const { return CE_CXXDestructor; } static bool classof(const CallEvent *CA) { @@ -882,6 +891,13 @@ class CallEventManager { return new (allocate()) T(A1, A2, A3, St, LCtx); } + template <typename T, typename Arg1, typename Arg2, typename Arg3, + typename Arg4> + T *create(Arg1 A1, Arg2 A2, Arg3 A3, Arg4 A4, ProgramStateRef St, + const LocationContext *LCtx) { + return new (allocate()) T(A1, A2, A3, A4, St, LCtx); + } + public: CallEventManager(llvm::BumpPtrAllocator &alloc) : Alloc(alloc) {} @@ -908,9 +924,9 @@ public: CallEventRef<CXXDestructorCall> getCXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger, - const MemRegion *Target, ProgramStateRef State, - const LocationContext *LCtx) { - return create<CXXDestructorCall>(DD, Trigger, Target, State, LCtx); + const MemRegion *Target, bool IsBase, + ProgramStateRef State, const LocationContext *LCtx) { + return create<CXXDestructorCall>(DD, Trigger, Target, IsBase, State, LCtx); } CallEventRef<CXXAllocatorCall> diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index ab15581938..ffc1698891 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -385,8 +385,8 @@ public: void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst); - void VisitCXXDestructor(QualType ObjectType, - const MemRegion *Dest, const Stmt *S, + void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest, + const Stmt *S, bool IsBaseDtor, ExplodedNode *Pred, ExplodedNodeSet &Dst); void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, diff --git a/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp index b636efbe35..95cc6f2287 100644 --- a/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp +++ b/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp @@ -83,14 +83,14 @@ void DynamicTypePropagation::checkPreCall(const CallEvent &Call, if (const CXXDestructorCall *Dtor = dyn_cast<CXXDestructorCall>(&Call)) { // C++11 [class.cdtor]p4 (see above) + if (!Dtor->isBaseDestructor()) + return; const MemRegion *Target = Dtor->getCXXThisVal().getAsRegion(); if (!Target) return; - // FIXME: getRuntimeDefinition() can be expensive. It would be better to do - // this when we are entering the stack frame for the destructor. - const Decl *D = Dtor->getRuntimeDefinition().getDecl(); + const Decl *D = Dtor->getDecl(); if (!D) return; diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp index 1cfa394a07..7d58e806a7 100644 --- a/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -559,10 +559,19 @@ void CXXConstructorCall::getInitialStackFrameContents( SVal CXXDestructorCall::getCXXThisVal() const { if (Data) - return loc::MemRegionVal(static_cast<const MemRegion *>(Data)); + return loc::MemRegionVal(DtorDataTy::getFromOpaqueValue(Data).getPointer()); return UnknownVal(); } +RuntimeDefinition CXXDestructorCall::getRuntimeDefinition() const { + // Base destructors are always called non-virtually. + // Skip CXXInstanceCall's devirtualization logic in this case. + if (isBaseDestructor()) + return AnyFunctionCall::getRuntimeDefinition(); + + return CXXInstanceCall::getRuntimeDefinition(); +} + CallEvent::param_iterator ObjCMethodCall::param_begin() const { const ObjCMethodDecl *D = getDecl(); @@ -892,5 +901,5 @@ CallEventManager::getCaller(const StackFrameContext *CalleeCtx, Trigger = Dtor->getBody(); return getCXXDestructorCall(Dtor, Trigger, ThisVal.getAsRegion(), - State, CallerCtx); + isa<CFGBaseDtor>(E), State, CallerCtx); } diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index b95a3fedb7..d177b60a50 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -446,7 +446,7 @@ void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor, Loc dest = state->getLValue(varDecl, Pred->getLocationContext()); VisitCXXDestructor(varType, cast<loc::MemRegionVal>(dest).getRegion(), - Dtor.getTriggerStmt(), Pred, Dst); + Dtor.getTriggerStmt(), /*IsBase=*/false, Pred, Dst); } void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D, @@ -464,7 +464,7 @@ void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D, SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy); VisitCXXDestructor(BaseTy, cast<loc::MemRegionVal>(BaseVal).getRegion(), - CurDtor->getBody(), Pred, Dst); + CurDtor->getBody(), /*IsBase=*/true, Pred, Dst); } void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D, @@ -480,7 +480,7 @@ void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D, VisitCXXDestructor(Member->getType(), cast<loc::MemRegionVal>(FieldVal).getRegion(), - CurDtor->getBody(), Pred, Dst); + CurDtor->getBody(), /*IsBase=*/false, Pred, Dst); } void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D, diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index d3d2837fe5..10ecb3b9a9 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -163,6 +163,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, void ExprEngine::VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest, const Stmt *S, + bool IsBaseDtor, ExplodedNode *Pred, ExplodedNodeSet &Dst) { const LocationContext *LCtx = Pred->getLocationContext(); @@ -183,7 +184,7 @@ void ExprEngine::VisitCXXDestructor(QualType ObjectType, CallEventManager &CEMgr = getStateManager().getCallEventManager(); CallEventRef<CXXDestructorCall> Call = - CEMgr.getCXXDestructorCall(DtorDecl, S, Dest, State, LCtx); + CEMgr.getCXXDestructorCall(DtorDecl, S, Dest, IsBaseDtor, State, LCtx); PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), Call->getSourceRange().getBegin(), diff --git a/test/Analysis/dtor.cpp b/test/Analysis/dtor.cpp index a762ebed12..99c47d5920 100644 --- a/test/Analysis/dtor.cpp +++ b/test/Analysis/dtor.cpp @@ -251,3 +251,33 @@ namespace DestructorsShouldNotAffectReturnValues { free(p); // no-warning } } + +namespace MultipleInheritanceVirtualDtors { + class VirtualDtor { + protected: + virtual ~VirtualDtor() { + clang_analyzer_checkInlined(true); // expected-warning{{TRUE}} + } + }; + + class NonVirtualDtor { + protected: + ~NonVirtualDtor() { + clang_analyzer_checkInlined(true); // expected-warning{{TRUE}} + } + }; + + class SubclassA : public VirtualDtor, public NonVirtualDtor { + public: + virtual ~SubclassA() {} + }; + class SubclassB : public NonVirtualDtor, public VirtualDtor { + public: + virtual ~SubclassB() {} + }; + + void test() { + SubclassA a; + SubclassB b; + } +} |