This revision was automatically updated to reflect the committed changes. Closed by commit rG55208f5a2126: [analyzer] Add modeling for unque_ptr::get() (authored by vrnithinkumar).
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D86029/new/ https://reviews.llvm.org/D86029 Files: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp clang/test/Analysis/smart-ptr-text-output.cpp clang/test/Analysis/smart-ptr.cpp
Index: clang/test/Analysis/smart-ptr.cpp =================================================================== --- clang/test/Analysis/smart-ptr.cpp +++ clang/test/Analysis/smart-ptr.cpp @@ -7,6 +7,7 @@ void clang_analyzer_warnIfReached(); void clang_analyzer_numTimesReached(); +void clang_analyzer_eval(bool); void derefAfterMove(std::unique_ptr<int> P) { std::unique_ptr<int> Q = std::move(P); @@ -252,3 +253,26 @@ P->foo(); // No warning. PValid->foo(); // No warning. } + +void derefOnRawPtrFromGetOnNullPtr() { + std::unique_ptr<A> P; + P.get()->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} +} + +void derefOnRawPtrFromGetOnValidPtr() { + std::unique_ptr<A> P(new A()); + P.get()->foo(); // No warning. +} + +void derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr<A> P) { + P.get()->foo(); // No warning. +} + +void derefOnRawPtrFromMultipleGetOnUnknownPtr(std::unique_ptr<A> P) { + A *X = P.get(); + A *Y = P.get(); + clang_analyzer_eval(X == Y); // expected-warning{{TRUE}} + if (!X) { + Y->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} + } +} Index: clang/test/Analysis/smart-ptr-text-output.cpp =================================================================== --- clang/test/Analysis/smart-ptr-text-output.cpp +++ clang/test/Analysis/smart-ptr-text-output.cpp @@ -116,3 +116,18 @@ P->foo(); // expected-warning {{Dereference of null smart pointer 'P' of type 'std::unique_ptr' [cplusplus.Move]}} // expected-note@-1 {{Dereference of null smart pointer 'P' of type 'std::unique_ptr'}} } + +void derefOnRawPtrFromGetOnNullPtr() { + std::unique_ptr<A> P; // FIXME: add note "Default constructed smart pointer 'P' is null" + P.get()->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} + // expected-note@-1 {{Called C++ object pointer is null}} +} + +void derefOnRawPtrFromGetOnValidPtr() { + std::unique_ptr<A> P(new A()); + P.get()->foo(); // No warning. +} + +void derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr<A> P) { + P.get()->foo(); // No warning. +} Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp +++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp @@ -56,13 +56,15 @@ void handleReset(const CallEvent &Call, CheckerContext &C) const; void handleRelease(const CallEvent &Call, CheckerContext &C) const; void handleSwap(const CallEvent &Call, CheckerContext &C) const; + void handleGet(const CallEvent &Call, CheckerContext &C) const; using SmartPtrMethodHandlerFn = void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const; CallDescriptionMap<SmartPtrMethodHandlerFn> SmartPtrMethodHandlers{ {{"reset"}, &SmartPtrModeling::handleReset}, {{"release"}, &SmartPtrModeling::handleRelease}, - {{"swap", 1}, &SmartPtrModeling::handleSwap}}; + {{"swap", 1}, &SmartPtrModeling::handleSwap}, + {{"get"}, &SmartPtrModeling::handleGet}}; }; } // end of anonymous namespace @@ -345,6 +347,33 @@ })); } +void SmartPtrModeling::handleGet(const CallEvent &Call, + CheckerContext &C) const { + ProgramStateRef State = C.getState(); + const auto *IC = dyn_cast<CXXInstanceCall>(&Call); + if (!IC) + return; + + const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion(); + if (!ThisRegion) + return; + + SVal InnerPointerVal; + if (const auto *InnerValPtr = State->get<TrackedRegionMap>(ThisRegion)) { + InnerPointerVal = *InnerValPtr; + } else { + const auto *CallExpr = Call.getOriginExpr(); + InnerPointerVal = C.getSValBuilder().conjureSymbolVal( + CallExpr, C.getLocationContext(), Call.getResultType(), C.blockCount()); + State = State->set<TrackedRegionMap>(ThisRegion, InnerPointerVal); + } + + State = State->BindExpr(Call.getOriginExpr(), C.getLocationContext(), + InnerPointerVal); + // TODO: Add NoteTag, for how the raw pointer got using 'get' method. + C.addTransition(State); +} + void ento::registerSmartPtrModeling(CheckerManager &Mgr) { auto *Checker = Mgr.registerChecker<SmartPtrModeling>(); Checker->ModelSmartPtrDereference =
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits