Author: Nithin Vadukkumchery Rajendrakumar Date: 2020-08-23T14:50:26+02:00 New Revision: 55208f5a2126e491c41ba9ff6542551bfc090e86
URL: https://github.com/llvm/llvm-project/commit/55208f5a2126e491c41ba9ff6542551bfc090e86 DIFF: https://github.com/llvm/llvm-project/commit/55208f5a2126e491c41ba9ff6542551bfc090e86.diff LOG: [analyzer] Add modeling for unque_ptr::get() Summary: Implemented modeling for get() method in SmartPtrModeling Reviewers: NoQ, Szelethus, vsavchenko, xazax.hun Reviewed By: NoQ, xazax.hun Subscribers: martong, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D86029 Added: Modified: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp clang/test/Analysis/smart-ptr-text-output.cpp clang/test/Analysis/smart-ptr.cpp Removed: ################################################################################ diff --git a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp index 15f56728eaa9..0b084accbfbe 100644 --- a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp @@ -56,13 +56,15 @@ class SmartPtrModeling 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::handleSwap(const CallEvent &Call, })); } +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 = diff --git a/clang/test/Analysis/smart-ptr-text-output.cpp b/clang/test/Analysis/smart-ptr-text-output.cpp index 1132a37fa667..9af6f251e01d 100644 --- a/clang/test/Analysis/smart-ptr-text-output.cpp +++ b/clang/test/Analysis/smart-ptr-text-output.cpp @@ -116,3 +116,18 @@ void noNoteTagsForNonMatchingBugType() { 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. +} diff --git a/clang/test/Analysis/smart-ptr.cpp b/clang/test/Analysis/smart-ptr.cpp index bcf1e569d690..17f6718c6605 100644 --- a/clang/test/Analysis/smart-ptr.cpp +++ b/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 @@ void derefOnSwappedValidPtr() { 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]}} + } +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits