Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -802,16 +802,16 @@ /// Creates an implicit destructor. /// /// \param DD The destructor that will be called. - /// \param Trigger The statement whose completion causes this destructor call. - /// \param Target The object region to be destructed. - /// \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, + /// \param TriggerLocation The location where this destructor call is + /// triggered. \param Target The object region to be destructed. \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, SourceLocation TriggerLocation, const MemRegion *Target, bool IsBaseDestructor, ProgramStateRef St, const LocationContext *LCtx) : CXXInstanceCall(DD, St, LCtx) { Data = DtorDataTy(Target, IsBaseDestructor).getOpaqueValue(); - Location = Trigger->getEndLoc(); + Location = TriggerLocation; } CXXDestructorCall(const CXXDestructorCall &Other) = default; @@ -1330,10 +1330,12 @@ } CallEventRef - getCXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger, + getCXXDestructorCall(const CXXDestructorDecl *DD, + const SourceLocation TriggerLocation, const MemRegion *Target, bool IsBase, ProgramStateRef State, const LocationContext *LCtx) { - return create(DD, Trigger, Target, IsBase, State, LCtx); + return create(DD, TriggerLocation, Target, IsBase, State, + LCtx); } CallEventRef Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -567,9 +567,9 @@ ExplodedNode *Pred, ExplodedNodeSet &Dst); void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest, - const Stmt *S, bool IsBaseDtor, - ExplodedNode *Pred, ExplodedNodeSet &Dst, - EvalCallOptions &Options); + const Stmt *S, SourceLocation TriggerLocation, + bool IsBaseDtor, ExplodedNode *Pred, + ExplodedNodeSet &Dst, EvalCallOptions &Options); void VisitCXXNewAllocatorCall(const CXXNewExpr *CNE, ExplodedNode *Pred, Index: clang/lib/StaticAnalyzer/Core/CallEvent.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/CallEvent.cpp +++ clang/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -1442,7 +1442,7 @@ else Trigger = Dtor->getBody(); - return getCXXDestructorCall(Dtor, Trigger, ThisVal.getAsRegion(), + return getCXXDestructorCall(Dtor, Trigger->getEndLoc(), ThisVal.getAsRegion(), E.getAs().has_value(), State, CallerCtx); } Index: clang/lib/StaticAnalyzer/Core/ExprEngine.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1385,7 +1385,8 @@ return; Bldr.takeNodes(Pred); - VisitCXXDestructor(varType, Region, Dtor.getTriggerStmt(), + const Stmt *TriggerStmt = Dtor.getTriggerStmt(); + VisitCXXDestructor(varType, Region, TriggerStmt, TriggerStmt->getEndLoc(), /*IsBase=*/false, Pred, Dst, CallOpts); } @@ -1460,7 +1461,8 @@ return; Bldr.takeNodes(Pred); - VisitCXXDestructor(DTy, ArgR, DE, /*IsBase=*/false, Pred, Dst, CallOpts); + VisitCXXDestructor(DTy, ArgR, DE, DE->getEndLoc(), /*IsBase=*/false, Pred, + Dst, CallOpts); } void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D, @@ -1480,6 +1482,7 @@ EvalCallOptions CallOpts; VisitCXXDestructor(BaseTy, BaseVal.getAsRegion(), CurDtor->getBody(), + Base->getEndLoc(), /*IsBase=*/true, Pred, Dst, CallOpts); } @@ -1537,6 +1540,7 @@ Bldr.takeNodes(Pred); VisitCXXDestructor(T, FieldVal.getAsRegion(), CurDtor->getBody(), + Member->getLocation(), /*IsBase=*/false, Pred, Dst, CallOpts); } @@ -1613,7 +1617,8 @@ // but for now we don't have the respective construction contexts, // so MR would always be null in this case. Do nothing for now. } - VisitCXXDestructor(T, MR, D.getBindTemporaryExpr(), + const CXXBindTemporaryExpr *TmpExpr = D.getBindTemporaryExpr(); + VisitCXXDestructor(T, MR, TmpExpr, TmpExpr->getEndLoc(), /*IsBase=*/false, CleanPred, Dst, CallOpts); } Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -847,11 +847,10 @@ handleConstructor(CE, Pred, Dst); } -void ExprEngine::VisitCXXDestructor(QualType ObjectType, - const MemRegion *Dest, +void ExprEngine::VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest, const Stmt *S, - bool IsBaseDtor, - ExplodedNode *Pred, + SourceLocation TriggerLocation, + bool IsBaseDtor, ExplodedNode *Pred, ExplodedNodeSet &Dst, EvalCallOptions &CallOpts) { assert(S && "A destructor without a trigger!"); @@ -893,8 +892,8 @@ } CallEventManager &CEMgr = getStateManager().getCallEventManager(); - CallEventRef Call = - CEMgr.getCXXDestructorCall(DtorDecl, S, Dest, IsBaseDtor, State, LCtx); + CallEventRef Call = CEMgr.getCXXDestructorCall( + DtorDecl, TriggerLocation, Dest, IsBaseDtor, State, LCtx); PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), Call->getSourceRange().getBegin(), Index: clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -837,7 +837,8 @@ State = bindReturnValue(Call, Pred->getLocationContext(), State); // And make the result node. - Bldr.generateNode(Call.getProgramPoint(), State, Pred); + static SimpleProgramPointTag PT("ExprEngine", "Conservative eval call"); + Bldr.generateNode(Call.getProgramPoint(false, &PT), State, Pred); } ExprEngine::CallInlinePolicy Index: clang/test/Analysis/inner-pointer.cpp =================================================================== --- clang/test/Analysis/inner-pointer.cpp +++ clang/test/Analysis/inner-pointer.cpp @@ -291,7 +291,7 @@ } struct S { - std::string s; + std::string s; // expected-note {{Inner buffer of 'std::string' deallocated by call to destructor}} const char *name() { return s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} // expected-note@-1 {{Pointer to inner buffer of 'std::string' obtained here}} @@ -299,7 +299,7 @@ void clear() { s.clear(); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'clear'}} } - ~S() {} // expected-note {{Inner buffer of 'std::string' deallocated by call to destructor}} + ~S() {} }; void cleared_through_method() {