diff --git a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp --- a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp @@ -139,7 +139,7 @@ if (RD->getDeclName().isIdentifier()) { StringRef Name = RD->getName(); - return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr"; + return llvm::is_contained(STD_PTR_NAMES, Name); } return false; } @@ -279,6 +279,7 @@ CheckerContext &C) const { ProgramStateRef State = C.getState(); + Call.dump(); // If any one of the arg is a unique_ptr, then // we can try this function @@ -372,6 +373,35 @@ } } + if (const auto *DC = dyn_cast(&Call)) { + llvm::errs() << "Found destructor call\n"; + // FIXME: This is a sort-of redundant operation. + // But we can't remove it currently, otherwise shared_ptr and weak_ptr + // causes a crash after this. + State = DC->invalidateRegions(C.blockCount(), State); + const MemRegion *ThisRegion = DC->getCXXThisVal().getAsRegion(); + // TODO: Remove this before pushing + assert(ThisRegion && "We do not support explicit calls to destructor"); + const auto *InnerPtrVal = State->get(ThisRegion); + State = State->remove(ThisRegion); + if (InnerPtrVal) { + State = State->invalidateRegions(*InnerPtrVal, nullptr, C.blockCount(), + C.getLocationContext(), true); + + const QualType &Type = getInnerPointerType(Call, C); + const auto *RD = Type->getAsCXXRecordDecl(); + const auto *DD = RD->getDestructor(); + + const auto InnerDestrCall = + C.getStateManager().getCallEventManager().getCXXDestructorCall( + DD, nullptr, InnerPtrVal->getAsRegion(), RD->bases().empty(), + State, C.getLocationContext()); + InnerDestrCall->invalidateRegions(C.blockCount(), State); + } + C.addTransition(State); + return true; + } + if (!ModelSmartPtrDereference) return false; @@ -402,8 +432,8 @@ })); } else { const auto *TrackingExpr = Call.getArgExpr(0); - assert(TrackingExpr->getType()->isPointerType() && - "Adding a non pointer value to TrackedRegionMap"); + if (!TrackingExpr->getType()->isPointerType()) + return false; auto ArgVal = Call.getArgSVal(0); State = State->set(ThisRegion, ArgVal); diff --git a/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp b/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp --- a/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp @@ -664,14 +664,11 @@ for (const auto &EvalCallChecker : EvalCallCheckers) { // TODO: Support the situation when the call doesn't correspond // to any Expr. - ProgramPoint L = ProgramPoint::getProgramPoint( - Call.getOriginExpr(), ProgramPoint::PostStmtKind, - Pred->getLocationContext(), EvalCallChecker.Checker); bool evaluated = false; { // CheckerContext generates transitions(populates checkDest) on // destruction, so introduce the scope to make sure it gets properly // populated. - CheckerContext C(B, Eng, Pred, L); + CheckerContext C(B, Eng, Pred, Call.getProgramPoint()); evaluated = EvalCallChecker(Call, C); } assert(!(evaluated && anyEvaluated) diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -753,10 +753,13 @@ *Call, *this); ExplodedNodeSet DstInvalidated; - StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx); - for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); - I != E; ++I) - defaultEvalCall(Bldr, *I, *Call, CallOpts); + // StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx); + // for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = + // DstPreCall.end(); + // I != E; ++I) + // defaultEvalCall(Bldr, *I, *Call, CallOpts); + getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, *Call, + *this, CallOpts); getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated, *Call, *this);