vrnithinkumar created this revision. Herald added subscribers: cfe-commits, steakhal, ASDenysPetrov, martong, Charusso, dkrupp, donat.nagy, Szelethus, mikhail.ramalho, a.sidorin, szepet, baloghadamsoftware, xazax.hun. Herald added a project: clang. vrnithinkumar requested review of this revision.
Repository: rG LLVM Github Monorepo 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 @@ -235,3 +235,17 @@ 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. +} 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 @@ -117,3 +117,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,27 @@ })); } +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; + + const auto *InnerPointVal = State->get<TrackedRegionMap>(ThisRegion); + if (!InnerPointVal) + return; + + State = State->BindExpr(Call.getOriginExpr(), C.getLocationContext(), + *InnerPointVal); + //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 =
Index: clang/test/Analysis/smart-ptr.cpp =================================================================== --- clang/test/Analysis/smart-ptr.cpp +++ clang/test/Analysis/smart-ptr.cpp @@ -235,3 +235,17 @@ 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. +} 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 @@ -117,3 +117,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,27 @@ })); } +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; + + const auto *InnerPointVal = State->get<TrackedRegionMap>(ThisRegion); + if (!InnerPointVal) + return; + + State = State->BindExpr(Call.getOriginExpr(), C.getLocationContext(), + *InnerPointVal); + //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