[clang] a560910 - [Analyzer] Add checkRegionChanges for SmartPtrModeling
Author: Nithin Vadukkumchery Rajendrakumar Date: 2020-07-21T01:13:40+02:00 New Revision: a5609102117d2384fb73a14f37d24a0c844e3864 URL: https://github.com/llvm/llvm-project/commit/a5609102117d2384fb73a14f37d24a0c844e3864 DIFF: https://github.com/llvm/llvm-project/commit/a5609102117d2384fb73a14f37d24a0c844e3864.diff LOG: [Analyzer] Add checkRegionChanges for SmartPtrModeling Summary: Implemented checkRegionChanges for SmartPtrModeling Reviewers: NoQ, Szelethus, vsavchenko, xazax.hun Reviewed By: NoQ, vsavchenko, xazax.hun Subscribers: martong, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D83836 Added: Modified: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp clang/test/Analysis/Inputs/system-header-simulator-cxx.h clang/test/Analysis/smart-ptr.cpp Removed: diff --git a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp index bcc7d4103c1c..1b2174501d6e 100644 --- a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp @@ -30,7 +30,8 @@ using namespace clang; using namespace ento; namespace { -class SmartPtrModeling : public Checker { +class SmartPtrModeling +: public Checker { bool isNullAfterMoveMethod(const CallEvent &Call) const; @@ -40,6 +41,12 @@ class SmartPtrModeling : public Checker { bool evalCall(const CallEvent &Call, CheckerContext &C) const; void checkPreCall(const CallEvent &Call, CheckerContext &C) const; void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; + ProgramStateRef + checkRegionChanges(ProgramStateRef State, + const InvalidatedSymbols *Invalidated, + ArrayRef ExplicitRegions, + ArrayRef Regions, + const LocationContext *LCtx, const CallEvent *Call) const; private: ProgramStateRef updateTrackedRegion(const CallEvent &Call, CheckerContext &C, @@ -87,6 +94,20 @@ bool isNullSmartPtr(const ProgramStateRef State, const MemRegion *ThisRegion) { } // namespace ento } // namespace clang +// If a region is removed all of the subregions need to be removed too. +static TrackedRegionMapTy +removeTrackedSubregions(TrackedRegionMapTy RegionMap, +TrackedRegionMapTy::Factory &RegionMapFactory, +const MemRegion *Region) { + if (!Region) +return RegionMap; + for (const auto &E : RegionMap) { +if (E.first->isSubRegionOf(Region)) + RegionMap = RegionMapFactory.remove(RegionMap, E.first); + } + return RegionMap; +} + bool SmartPtrModeling::isNullAfterMoveMethod(const CallEvent &Call) const { // TODO: Update CallDescription to support anonymous calls? // TODO: Handle other methods, such as .get() or .release(). @@ -158,6 +179,20 @@ void SmartPtrModeling::checkDeadSymbols(SymbolReaper &SymReaper, C.addTransition(State); } +ProgramStateRef SmartPtrModeling::checkRegionChanges( +ProgramStateRef State, const InvalidatedSymbols *Invalidated, +ArrayRef ExplicitRegions, +ArrayRef Regions, const LocationContext *LCtx, +const CallEvent *Call) const { + TrackedRegionMapTy RegionMap = State->get(); + TrackedRegionMapTy::Factory &RegionMapFactory = + State->get_context(); + for (const auto *Region : Regions) +RegionMap = removeTrackedSubregions(RegionMap, RegionMapFactory, +Region->getBaseRegion()); + return State->set(RegionMap); +} + void SmartPtrModeling::handleReset(const CallEvent &Call, CheckerContext &C) const { const auto *IC = dyn_cast(&Call); diff --git a/clang/test/Analysis/Inputs/system-header-simulator-cxx.h b/clang/test/Analysis/Inputs/system-header-simulator-cxx.h index 1dee3294d732..d5e7c4c9218d 100644 --- a/clang/test/Analysis/Inputs/system-header-simulator-cxx.h +++ b/clang/test/Analysis/Inputs/system-header-simulator-cxx.h @@ -953,24 +953,25 @@ next(ForwardIterator it, #if __cplusplus >= 201103L namespace std { - template // TODO: Implement the stub for deleter. - class unique_ptr { - public: -unique_ptr() {} -unique_ptr(T *) {} -unique_ptr(const unique_ptr &) = delete; -unique_ptr(unique_ptr &&); - -T *get() const; -T *release() const; -void reset(T *p = nullptr) const; -void swap(unique_ptr &p) const; - -typename std::add_lvalue_reference::type operator*() const; -T *operator->() const; -operator bool() const; - }; -} +template // TODO: Implement the stub for deleter. +class unique_ptr { +public: + unique_ptr() noexcept {} + unique_ptr(T *) noexcept {} + unique_ptr(const unique_ptr &) noexcept = delete; + unique_ptr(unique_ptr &&) noexcept; + + T *get() const noexcept; + T *release() noexcept; + void reset(T
[clang] 76c0577 - [Analyzer] Handle unique_ptr::swap() in SmartPtrModeling
Author: Nithin Vadukkumchery Rajendrakumar Date: 2020-07-21T12:05:27+02:00 New Revision: 76c0577763505ea3db1017a9aab579c1c2f135d0 URL: https://github.com/llvm/llvm-project/commit/76c0577763505ea3db1017a9aab579c1c2f135d0 DIFF: https://github.com/llvm/llvm-project/commit/76c0577763505ea3db1017a9aab579c1c2f135d0.diff LOG: [Analyzer] Handle unique_ptr::swap() in SmartPtrModeling Summary: Implemented modeling for unique_ptr::swap() SmartPtrModeling Subscribers: xazax.hun, baloghadamsoftware, szepet, a.sidorin, mikhail.ramalho, Szelethus, donat.nagy, dkrupp, Charusso, martong, ASDenysPetrov, cfe-commits Reviewers: NoQ, Szelethus, vsavchenko, xazax.hun Reviewed By: NoQ, vsavchenko, xazax.hun Tags: #clang Differential Revision: https://reviews.llvm.org/D8387 Added: Modified: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp clang/test/Analysis/Inputs/system-header-simulator-cxx.h clang/test/Analysis/smart-ptr.cpp Removed: diff --git a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp index 1b2174501d6e..c36e89c3e3a9 100644 --- a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp @@ -108,6 +108,17 @@ removeTrackedSubregions(TrackedRegionMapTy RegionMap, return RegionMap; } +static ProgramStateRef updateSwappedRegion(ProgramStateRef State, + const MemRegion *Region, + const SVal *RegionInnerPointerVal) { + if (RegionInnerPointerVal) { +State = State->set(Region, *RegionInnerPointerVal); + } else { +State = State->remove(Region); + } + return State; +} + bool SmartPtrModeling::isNullAfterMoveMethod(const CallEvent &Call) const { // TODO: Update CallDescription to support anonymous calls? // TODO: Handle other methods, such as .get() or .release(). @@ -129,7 +140,8 @@ bool SmartPtrModeling::evalCall(const CallEvent &Call, cast(&Call)->getCXXThisVal().getAsRegion(); if (!move::isMovedFrom(State, ThisR)) { - // TODO: Model this case as well. At least, avoid invalidation of globals. + // TODO: Model this case as well. At least, avoid invalidation of + // globals. return false; } @@ -204,7 +216,7 @@ void SmartPtrModeling::handleReset(const CallEvent &Call, return; auto State = updateTrackedRegion(Call, C, ThisValRegion); C.addTransition(State); - // TODO: Make sure to ivalidate the the region in the Store if we don't have + // TODO: Make sure to ivalidate the region in the Store if we don't have // time to model all methods. } @@ -232,7 +244,30 @@ void SmartPtrModeling::handleRelease(const CallEvent &Call, void SmartPtrModeling::handleSwap(const CallEvent &Call, CheckerContext &C) const { - // TODO: Add support to handle swap method. + // To model unique_ptr::swap() method. + const auto *IC = dyn_cast(&Call); + if (!IC) +return; + + const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion(); + if (!ThisRegion) +return; + + const auto *ArgRegion = Call.getArgSVal(0).getAsRegion(); + if (!ArgRegion) +return; + + auto State = C.getState(); + const auto *ThisRegionInnerPointerVal = + State->get(ThisRegion); + const auto *ArgRegionInnerPointerVal = + State->get(ArgRegion); + + // Swap the tracked region values. + State = updateSwappedRegion(State, ThisRegion, ArgRegionInnerPointerVal); + State = updateSwappedRegion(State, ArgRegion, ThisRegionInnerPointerVal); + + C.addTransition(State); } ProgramStateRef diff --git a/clang/test/Analysis/Inputs/system-header-simulator-cxx.h b/clang/test/Analysis/Inputs/system-header-simulator-cxx.h index d5e7c4c9218d..9010ce2bb9b6 100644 --- a/clang/test/Analysis/Inputs/system-header-simulator-cxx.h +++ b/clang/test/Analysis/Inputs/system-header-simulator-cxx.h @@ -971,6 +971,12 @@ class unique_ptr { operator bool() const noexcept; unique_ptr &operator=(unique_ptr &&p) noexcept; }; + +// TODO :: Once the deleter parameter is added update with additional template parameter. +template +void swap(unique_ptr &x, unique_ptr &y) noexcept { + x.swap(y); +} } // namespace std #endif diff --git a/clang/test/Analysis/smart-ptr.cpp b/clang/test/Analysis/smart-ptr.cpp index 5645afc9b657..168682ba758f 100644 --- a/clang/test/Analysis/smart-ptr.cpp +++ b/clang/test/Analysis/smart-ptr.cpp @@ -201,3 +201,30 @@ void derefAfterAssignment() { Q->foo(); // no-warning } } + +void derefOnSwappedNullPtr() { + std::unique_ptr P(new A()); + std::unique_ptr PNull; + P.swap(PNull); + PNull->foo(); // No warning. + (*P).foo(); // expected-warning {{Dereference of null smart pointer [alpha.cplusplus.SmartPtr]}} +} + +void derefOnStdSwappedNullPtr()
[clang] 20e271a - [analyzer] Warning for default constructed unique_ptr dereference
Author: Nithin Vadukkumchery Rajendrakumar Date: 2020-07-08T09:51:02+02:00 New Revision: 20e271a98de5609e22766e56f9c374b150f06982 URL: https://github.com/llvm/llvm-project/commit/20e271a98de5609e22766e56f9c374b150f06982 DIFF: https://github.com/llvm/llvm-project/commit/20e271a98de5609e22766e56f9c374b150f06982.diff LOG: [analyzer] Warning for default constructed unique_ptr dereference Summary: Add support for warning incase of default constructed unique pointer dereferences Reviewed By: NoQ, Szelethus, vsavchenko, xazax.hun Tags: #clang Differential Revision: https://reviews.llvm.org/D81315 Added: clang/lib/StaticAnalyzer/Checkers/SmartPtr.h clang/lib/StaticAnalyzer/Checkers/SmartPtrChecker.cpp Modified: clang/docs/analyzer/checkers.rst clang/include/clang/StaticAnalyzer/Checkers/Checkers.td clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp clang/test/Analysis/Inputs/system-header-simulator-cxx.h clang/test/Analysis/analyzer-config.c clang/test/Analysis/smart-ptr.cpp clang/test/Analysis/use-after-move.cpp Removed: diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst index d14bd2d68af9..1583da7aff09 100644 --- a/clang/docs/analyzer/checkers.rst +++ b/clang/docs/analyzer/checkers.rst @@ -1836,6 +1836,19 @@ Check unreachable code. [x retain]; // warn } +.. _alpha-cplusplus-SmartPtr: + +alpha.cplusplus.SmartPtr (C++) +"" +Check for dereference of null smart pointers. + +.. code-block:: cpp + + void deref_smart_ptr() { + std::unique_ptr P; + *P; // warn: dereference of a default constructed smart unique_ptr + } + alpha.llvm ^^ diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index dc1269890f93..cbd925400328 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -577,9 +577,17 @@ def CXXSelfAssignmentChecker : Checker<"SelfAssignment">, Documentation, Hidden; -def SmartPtrModeling: Checker<"SmartPtr">, +def SmartPtrModeling: Checker<"SmartPtrModeling">, HelpText<"Model behavior of C++ smart pointers">, Documentation, +CheckerOptions<[ +CmdLineOption, + ]>, Hidden; def MoveChecker: Checker<"Move">, @@ -736,6 +744,11 @@ def MismatchedIteratorChecker : Checker<"MismatchedIterator">, Dependencies<[IteratorModeling]>, Documentation; +def SmartPtrChecker: Checker<"SmartPtr">, + HelpText<"Find the dereference of null SmrtPtr">, + Dependencies<[SmartPtrModeling]>, + Documentation; + } // end: "alpha.cplusplus" diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index a71469e90ea2..d75f9f63286d 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -788,6 +788,10 @@ class CXXMemberOperatorCall : public CXXInstanceCall { // to implicit this-parameter on the declaration. return CallArgumentIndex + 1; } + + OverloadedOperatorKind getOverloadedOperator() const { +return getOriginExpr()->getOperator(); + } }; /// Represents an implicit call to a C++ destructor. diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt index 80cac237fc3b..9be1fdeb3ebf 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt +++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt @@ -98,6 +98,7 @@ add_clang_library(clangStaticAnalyzerCheckers ReturnValueChecker.cpp RunLoopAutoreleaseLeakChecker.cpp SimpleStreamChecker.cpp + SmartPtrChecker.cpp SmartPtrModeling.cpp StackAddrEscapeChecker.cpp StdLibraryFunctionsChecker.cpp diff --git a/clang/lib/StaticAnalyzer/Checkers/SmartPtr.h b/clang/lib/StaticAnalyzer/Checkers/SmartPtr.h new file mode 100644 index ..89b8965e4c9a --- /dev/null +++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtr.h @@ -0,0 +1,40 @@ +//=== SmartPtr.h - Tracking smart pointer state. ---*- C++ -*-// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// Defines inter-checker API for the smart pointer modeling. It allows +// dependent checkers to figure out if an smart pointer is null or not. +// +//===--===// + +#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHE
[clang] 06d100a - [Analyzer] Support note tags for smart ptr checker
Author: Nithin Vadukkumchery Rajendrakumar Date: 2020-08-11T23:27:16+02:00 New Revision: 06d100a69a08632e6a553a7fb4d3750b55145946 URL: https://github.com/llvm/llvm-project/commit/06d100a69a08632e6a553a7fb4d3750b55145946 DIFF: https://github.com/llvm/llvm-project/commit/06d100a69a08632e6a553a7fb4d3750b55145946.diff LOG: [Analyzer] Support note tags for smart ptr checker Summary: Added support for note tags for null smart_ptr reporting Reviewers: NoQ, Szelethus, vsavchenko, xazax.hun Reviewed By: NoQ, vsavchenko, xazax.hun Subscribers: martong, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D84600 Added: clang/test/Analysis/smart-ptr-text-output.cpp Modified: clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h clang/lib/StaticAnalyzer/Checkers/SmartPtr.h clang/lib/StaticAnalyzer/Checkers/SmartPtrChecker.cpp clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp clang/test/Analysis/smart-ptr.cpp Removed: diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h index 8fd7f52585b86..54572bd81f20f 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -301,6 +301,26 @@ class CheckerContext { IsPrunable); } + /// A shorthand version of getNoteTag that accepts a lambda with stream for + /// note. + /// + /// @param Cb Callback with 'BugReport &' and 'llvm::raw_ostream &'. + /// @param IsPrunable Whether the note is prunable. It allows BugReporter + ///to omit the note from the report if it would make the displayed + ///bug path significantly shorter. + const NoteTag *getNoteTag( + std::function &&Cb, + bool IsPrunable = false) { +return getNoteTag( +[Cb](PathSensitiveBugReport &BR) -> std::string { + llvm::SmallString<128> Str; + llvm::raw_svector_ostream OS(Str); + Cb(BR, OS); + return std::string(OS.str()); +}, +IsPrunable); + } + /// Returns the word that should be used to refer to the declaration /// in the report. StringRef getDeclDescription(const Decl *D); diff --git a/clang/lib/StaticAnalyzer/Checkers/SmartPtr.h b/clang/lib/StaticAnalyzer/Checkers/SmartPtr.h index ec43a23e30a9e..92c386bbb2b09 100644 --- a/clang/lib/StaticAnalyzer/Checkers/SmartPtr.h +++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtr.h @@ -26,6 +26,8 @@ bool isStdSmartPtrCall(const CallEvent &Call); /// Returns whether the smart pointer is null or not. bool isNullSmartPtr(const ProgramStateRef State, const MemRegion *ThisRegion); +const BugType *getNullDereferenceBugType(); + } // namespace smartptr } // namespace ento } // namespace clang diff --git a/clang/lib/StaticAnalyzer/Checkers/SmartPtrChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/SmartPtrChecker.cpp index 7bb25f397d010..8a85d454856b9 100644 --- a/clang/lib/StaticAnalyzer/Checkers/SmartPtrChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtrChecker.cpp @@ -23,23 +23,40 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" +#include "llvm/ADT/StringRef.h" using namespace clang; using namespace ento; namespace { -class SmartPtrChecker : public Checker { - BugType NullDereferenceBugType{this, "Null SmartPtr dereference", - "C++ Smart Pointer"}; +static const BugType *NullDereferenceBugTypePtr; + +class SmartPtrChecker : public Checker { public: void checkPreCall(const CallEvent &Call, CheckerContext &C) const; + BugType NullDereferenceBugType{this, "Null SmartPtr dereference", + "C++ Smart Pointer"}; private: - void reportBug(CheckerContext &C, const CallEvent &Call) const; + void reportBug(CheckerContext &C, const MemRegion *DerefRegion, + const CallEvent &Call) const; + void explainDereference(llvm::raw_ostream &OS, const MemRegion *DerefRegion, + const CallEvent &Call) const; }; } // end of anonymous namespace +// Define the inter-checker API. +namespace clang { +namespace ento { +namespace smartptr { + +const BugType *getNullDereferenceBugType() { return NullDereferenceBugTypePtr; } + +} // namespace smartptr +} // namespace ento +} // namespace clang + void SmartPtrChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const { if (!smartptr::isStdSmartPtrCall(Call)) @@ -55,23 +72,34 @@ void SmartPtrChecker::checkPreCall(const CallEvent &Call, OverloadedOperatorKind OOK = OC->getOverloadedOperator(); if (OOK == OO_Star || OOK == OO_Arrow) {
[clang] b34b1e3 - [Analysis] Bug fix for exploded graph branching in evalCall for constructor
Author: Nithin Vadukkumchery Rajendrakumar Date: 2020-08-19T00:03:31+02:00 New Revision: b34b1e38381fa4d1b1d9751a6b5233b68e734cfe URL: https://github.com/llvm/llvm-project/commit/b34b1e38381fa4d1b1d9751a6b5233b68e734cfe DIFF: https://github.com/llvm/llvm-project/commit/b34b1e38381fa4d1b1d9751a6b5233b68e734cfe.diff LOG: [Analysis] Bug fix for exploded graph branching in evalCall for constructor Summary: Make exactly single NodeBuilder exists at any given time Reviewers: NoQ, Szelethus, vsavchenko, xazax.hun Reviewed By: NoQ Subscribers: martong, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D85796 Added: Modified: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp clang/test/Analysis/smart-ptr-text-output.cpp clang/test/Analysis/smart-ptr.cpp Removed: diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 38a680eb04c00..802bc934cfb06 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -602,11 +602,11 @@ void ExprEngine::handleConstructor(const Expr *E, *Call, *this); ExplodedNodeSet DstEvaluated; - StmtNodeBuilder Bldr(DstPreCall, DstEvaluated, *currBldrCtx); if (CE && CE->getConstructor()->isTrivial() && CE->getConstructor()->isCopyOrMoveConstructor() && !CallOpts.IsArrayCtorOrDtor) { +StmtNodeBuilder Bldr(DstPreCall, DstEvaluated, *currBldrCtx); // FIXME: Handle other kinds of trivial constructors as well. for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); I != E; ++I) @@ -626,6 +626,8 @@ void ExprEngine::handleConstructor(const Expr *E, // in the CFG, would be called at the end of the full expression or // later (for life-time extended temporaries) -- but avoids infeasible // paths when no-return temporary destructors are used for assertions. + ExplodedNodeSet DstEvaluatedPostProcessed; + StmtNodeBuilder Bldr(DstEvaluated, DstEvaluatedPostProcessed, *currBldrCtx); const AnalysisDeclContext *ADC = LCtx->getAnalysisDeclContext(); if (!ADC->getCFGBuildOptions().AddTemporaryDtors) { if (llvm::isa_and_nonnull(TargetRegion) && @@ -655,7 +657,7 @@ void ExprEngine::handleConstructor(const Expr *E, } ExplodedNodeSet DstPostArgumentCleanup; - for (ExplodedNode *I : DstEvaluated) + for (ExplodedNode *I : DstEvaluatedPostProcessed) finishArgumentConstruction(DstPostArgumentCleanup, I, *Call); // If there were other constructors called for object-type arguments diff --git a/clang/test/Analysis/smart-ptr-text-output.cpp b/clang/test/Analysis/smart-ptr-text-output.cpp index 5280d0021884d..1132a37fa6679 100644 --- a/clang/test/Analysis/smart-ptr-text-output.cpp +++ b/clang/test/Analysis/smart-ptr-text-output.cpp @@ -36,14 +36,15 @@ void derefAfterCtrWithNullVariable() { } void derefAfterRelease() { - std::unique_ptr P(new A()); + std::unique_ptr P(new A()); // expected-note {{Smart pointer 'P' is constructed}} + // FIXME: should mark region as uninteresting after release, so above note will not be there P.release(); // expected-note {{Smart pointer 'P' is released and set to null}} P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'P'}} } void derefAfterReset() { - std::unique_ptr P(new A()); + std::unique_ptr P(new A()); // expected-note {{Smart pointer 'P' is constructed}} P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}} P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'P'}} @@ -51,7 +52,7 @@ void derefAfterReset() { void derefAfterResetWithNull() { A *NullInnerPtr = nullptr; // expected-note {{'NullInnerPtr' initialized to a null pointer value}} - std::unique_ptr P(new A()); + std::unique_ptr P(new A()); // expected-note {{Smart pointer 'P' is constructed}} P.reset(NullInnerPtr); // expected-note {{Smart pointer 'P' reset using a null value}} P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'P'}} @@ -67,7 +68,7 @@ void derefOnReleasedNullRawPtr() { } void derefOnSwappedNullPtr() { - std::unique_ptr P(new A()); + std::unique_ptr P(new A()); // expected-note {{Smart pointer 'P' is constructed}} std::unique_ptr PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}} P.swap(PNull); // expected-note {{Swapped null smart pointer 'PNull' with smart pointer 'P'}} PNull->foo(); // No warning. @@ -77,13 +78,11 @@ void derefOnSwappedNullPtr() { // FIXME: Fix this
[clang] 55208f5 - [analyzer] Add modeling for unque_ptr::get()
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 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(&Call); + if (!IC) +return; + + const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion(); + if (!ThisRegion) +return; + + SVal InnerPointerVal; + if (const auto *InnerValPtr = State->get(ThisRegion)) { +InnerPointerVal = *InnerValPtr; + } else { +const auto *CallExpr = Call.getOriginExpr(); +InnerPointerVal = C.getSValBuilder().conjureSymbolVal( +CallExpr, C.getLocationContext(), Call.getResultType(), C.blockCount()); +State = State->set(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(); 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 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 P(new A()); + P.get()->foo(); // No warning. +} + +void derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr 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 P) { std::unique_ptr Q = std::move(P); @@ -252,3 +253,26 @@ void derefOnSwappedValidPtr() { P->foo(); // No warning. PValid->foo(); // No warning. } + +void derefOnRawPtrFromGetOnNullPtr() { + std::unique_ptr P; + P.get()->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} +} + +void derefOnRawPtrFromGetOnValidPtr() { + std::unique_ptr P(new A()); + P.get()->foo(); // No warning. +} + +void de
[clang] 20676ca - [analyzer] Add modeling of assignment operator in smart ptr
Author: Nithin Vadukkumchery Rajendrakumar Date: 2020-08-26T11:22:55+02:00 New Revision: 20676cab1168c2c60982af85f42725955cbcd7b5 URL: https://github.com/llvm/llvm-project/commit/20676cab1168c2c60982af85f42725955cbcd7b5 DIFF: https://github.com/llvm/llvm-project/commit/20676cab1168c2c60982af85f42725955cbcd7b5.diff LOG: [analyzer] Add modeling of assignment operator in smart ptr Summary: Support for 'std::unique_ptr>::operator=' in SmartPtrModeling Reviewers: NoQ, Szelethus, vsavchenko, xazax.hun Reviewed By: NoQ, vsavchenko, xazax.hun Subscribers: martong, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D86293 Added: Modified: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp clang/test/Analysis/Inputs/system-header-simulator-cxx.h 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 0b084accbfbe..c405ef12433a 100644 --- a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp @@ -37,7 +37,7 @@ namespace { class SmartPtrModeling : public Checker { - bool isNullAfterMoveMethod(const CallEvent &Call) const; + bool isAssignOpMethod(const CallEvent &Call) const; public: // Whether the checker should model for null dereferences of smart pointers. @@ -57,6 +57,7 @@ class SmartPtrModeling void handleRelease(const CallEvent &Call, CheckerContext &C) const; void handleSwap(const CallEvent &Call, CheckerContext &C) const; void handleGet(const CallEvent &Call, CheckerContext &C) const; + bool handleAssignOp(const CallEvent &Call, CheckerContext &C) const; using SmartPtrMethodHandlerFn = void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const; @@ -123,7 +124,7 @@ static ProgramStateRef updateSwappedRegion(ProgramStateRef State, return State; } -bool SmartPtrModeling::isNullAfterMoveMethod(const CallEvent &Call) const { +bool SmartPtrModeling::isAssignOpMethod(const CallEvent &Call) const { // TODO: Update CallDescription to support anonymous calls? // TODO: Handle other methods, such as .get() or .release(). // But once we do, we'd need a visitor to explain null dereferences @@ -134,12 +135,11 @@ bool SmartPtrModeling::isNullAfterMoveMethod(const CallEvent &Call) const { bool SmartPtrModeling::evalCall(const CallEvent &Call, CheckerContext &C) const { - ProgramStateRef State = C.getState(); if (!smartptr::isStdSmartPtrCall(Call)) return false; - if (isNullAfterMoveMethod(Call)) { + if (isAssignOpMethod(Call)) { const MemRegion *ThisR = cast(&Call)->getCXXThisVal().getAsRegion(); @@ -206,6 +206,9 @@ bool SmartPtrModeling::evalCall(const CallEvent &Call, return true; } + if (handleAssignOp(Call, C)) +return true; + const SmartPtrMethodHandlerFn *Handler = SmartPtrMethodHandlers.lookup(Call); if (!Handler) return false; @@ -374,6 +377,87 @@ void SmartPtrModeling::handleGet(const CallEvent &Call, C.addTransition(State); } +bool SmartPtrModeling::handleAssignOp(const CallEvent &Call, + CheckerContext &C) const { + ProgramStateRef State = C.getState(); + const auto *OC = dyn_cast(&Call); + if (!OC) +return false; + OverloadedOperatorKind OOK = OC->getOverloadedOperator(); + if (OOK != OO_Equal) +return false; + const MemRegion *ThisRegion = OC->getCXXThisVal().getAsRegion(); + if (!ThisRegion) +return false; + + const MemRegion *OtherSmartPtrRegion = OC->getArgSVal(0).getAsRegion(); + // In case of 'nullptr' or '0' assigned + if (!OtherSmartPtrRegion) { +bool AssignedNull = Call.getArgSVal(0).isZeroConstant(); +if (!AssignedNull) + return false; +auto NullVal = C.getSValBuilder().makeNull(); +State = State->set(ThisRegion, NullVal); +C.addTransition(State, C.getNoteTag([ThisRegion](PathSensitiveBugReport &BR, + llvm::raw_ostream &OS) { + if (&BR.getBugType() != smartptr::getNullDereferenceBugType() || + !BR.isInteresting(ThisRegion)) +return; + OS << "Smart pointer "; + ThisRegion->printPretty(OS); + OS << " is assigned to null"; +})); +return true; + } + + const auto *OtherInnerPtr = State->get(OtherSmartPtrRegion); + if (OtherInnerPtr) { +State = State->set(ThisRegion, *OtherInnerPtr); +auto NullVal = C.getSValBuilder().makeNull(); +State = State->set(OtherSmartPtrRegion, NullVal); +bool IsArgValNull = OtherInnerPtr->isZeroConstant(); + +C.addTransition( +State, +C.getNoteTag([ThisRegion, OtherSmartPtrRegion, IsArgValNull]( + PathSen
[clang] 1b743a9 - [analyzer] Add modeling for unique_ptr move constructor
Author: Nithin Vadukkumchery Rajendrakumar Date: 2020-08-31T14:36:11+02:00 New Revision: 1b743a9efa0884ed3a48ebea97b6ef6cb7d73164 URL: https://github.com/llvm/llvm-project/commit/1b743a9efa0884ed3a48ebea97b6ef6cb7d73164 DIFF: https://github.com/llvm/llvm-project/commit/1b743a9efa0884ed3a48ebea97b6ef6cb7d73164.diff LOG: [analyzer] Add modeling for unique_ptr move constructor Summary: Add support for handling move contructor of std::unique_ptr. Reviewers: NoQ, Szelethus, vsavchenko, xazax.hun Reviewed By: NoQ Subscribers: martong, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D86373 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 c405ef12433a..391d038c8766 100644 --- a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp @@ -58,6 +58,10 @@ class SmartPtrModeling void handleSwap(const CallEvent &Call, CheckerContext &C) const; void handleGet(const CallEvent &Call, CheckerContext &C) const; bool handleAssignOp(const CallEvent &Call, CheckerContext &C) const; + bool handleMoveCtr(const CallEvent &Call, CheckerContext &C, + const MemRegion *ThisRegion) const; + bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion, +const MemRegion *OtherSmartPtrRegion) const; using SmartPtrMethodHandlerFn = void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const; @@ -160,13 +164,16 @@ bool SmartPtrModeling::evalCall(const CallEvent &Call, return false; if (const auto *CC = dyn_cast(&Call)) { -if (CC->getDecl()->isCopyOrMoveConstructor()) +if (CC->getDecl()->isCopyConstructor()) return false; const MemRegion *ThisRegion = CC->getCXXThisVal().getAsRegion(); if (!ThisRegion) return false; +if (CC->getDecl()->isMoveConstructor()) + return handleMoveCtr(Call, C, ThisRegion); + if (Call.getNumArgs() == 0) { auto NullVal = C.getSValBuilder().makeNull(); State = State->set(ThisRegion, NullVal); @@ -410,6 +417,22 @@ bool SmartPtrModeling::handleAssignOp(const CallEvent &Call, return true; } + return updateMovedSmartPointers(C, ThisRegion, OtherSmartPtrRegion); +} + +bool SmartPtrModeling::handleMoveCtr(const CallEvent &Call, CheckerContext &C, + const MemRegion *ThisRegion) const { + const auto *OtherSmartPtrRegion = Call.getArgSVal(0).getAsRegion(); + if (!OtherSmartPtrRegion) +return false; + + return updateMovedSmartPointers(C, ThisRegion, OtherSmartPtrRegion); +} + +bool SmartPtrModeling::updateMovedSmartPointers( +CheckerContext &C, const MemRegion *ThisRegion, +const MemRegion *OtherSmartPtrRegion) const { + ProgramStateRef State = C.getState(); const auto *OtherInnerPtr = State->get(OtherSmartPtrRegion); if (OtherInnerPtr) { State = State->set(ThisRegion, *OtherInnerPtr); @@ -430,7 +453,7 @@ bool SmartPtrModeling::handleAssignOp(const CallEvent &Call, ThisRegion->printPretty(OS); } if (BR.isInteresting(ThisRegion) && IsArgValNull) { -OS << "Null pointer value move-assigned to "; +OS << "A null pointer value is moved to "; ThisRegion->printPretty(OS); BR.markInteresting(OtherSmartPtrRegion); } diff --git a/clang/test/Analysis/smart-ptr-text-output.cpp b/clang/test/Analysis/smart-ptr-text-output.cpp index d63cd9b805f8..602a5e94c23a 100644 --- a/clang/test/Analysis/smart-ptr-text-output.cpp +++ b/clang/test/Analysis/smart-ptr-text-output.cpp @@ -144,7 +144,7 @@ void derefOnNullPtrGotMovedFromValidPtr() { std::unique_ptr P(new A()); // expected-note {{Smart pointer 'P' is constructed}} // FIXME: above note should go away once we fix marking region not interested. std::unique_ptr PToMove; // expected-note {{Default constructed smart pointer 'PToMove' is null}} - P = std::move(PToMove); // expected-note {{Null pointer value move-assigned to 'P'}} + P = std::move(PToMove); // expected-note {{A null pointer value is moved to 'P'}} P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1 {{Dereference of null smart pointer 'P'}} } @@ -170,3 +170,32 @@ void derefOnAssignedZeroToNullSmartPtr() { P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1 {{Dereference of null smart pointer 'P'}} } + +void derefMoveConstructedWithNullPtr() { + std::unique_ptr PToMove; // expected-no
[clang] bc3d4d9 - [analyzer] Add bool operator modeling for unque_ptr
Author: Nithin Vadukkumchery Rajendrakumar Date: 2020-08-31T19:25:33+02:00 New Revision: bc3d4d9ed783a3051125075f1a58ad619d8ea454 URL: https://github.com/llvm/llvm-project/commit/bc3d4d9ed783a3051125075f1a58ad619d8ea454 DIFF: https://github.com/llvm/llvm-project/commit/bc3d4d9ed783a3051125075f1a58ad619d8ea454.diff LOG: [analyzer] Add bool operator modeling for unque_ptr Summary: Implemented boolean conversion operator for unique_ptr Reviewers: NoQ, Szelethus, vsavchenko, xazax.hun Reviewed By: NoQ, xazax.hun Subscribers: martong, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D86027 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 391d038c8766..f1ca28ba339d 100644 --- a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp @@ -15,6 +15,7 @@ #include "SmartPtr.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/Type.h" #include "clang/Basic/LLVM.h" @@ -35,9 +36,10 @@ using namespace ento; namespace { class SmartPtrModeling -: public Checker { +: public Checker { - bool isAssignOpMethod(const CallEvent &Call) const; + bool isBoolConversionMethod(const CallEvent &Call) const; public: // Whether the checker should model for null dereferences of smart pointers. @@ -51,6 +53,9 @@ class SmartPtrModeling ArrayRef ExplicitRegions, ArrayRef Regions, const LocationContext *LCtx, const CallEvent *Call) const; + void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, + const char *Sep) const; + void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SR) const; private: void handleReset(const CallEvent &Call, CheckerContext &C) const; @@ -62,6 +67,7 @@ class SmartPtrModeling const MemRegion *ThisRegion) const; bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion, const MemRegion *OtherSmartPtrRegion) const; + void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const; using SmartPtrMethodHandlerFn = void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const; @@ -128,7 +134,38 @@ static ProgramStateRef updateSwappedRegion(ProgramStateRef State, return State; } -bool SmartPtrModeling::isAssignOpMethod(const CallEvent &Call) const { +// Helper method to get the inner pointer type of specialized smart pointer +// Returns empty type if not found valid inner pointer type. +static QualType getInnerPointerType(const CallEvent &Call, CheckerContext &C) { + const auto *MethodDecl = dyn_cast_or_null(Call.getDecl()); + if (!MethodDecl || !MethodDecl->getParent()) +return {}; + + const auto *RecordDecl = MethodDecl->getParent(); + if (!RecordDecl || !RecordDecl->isInStdNamespace()) +return {}; + + const auto *TSD = dyn_cast(RecordDecl); + if (!TSD) +return {}; + + auto TemplateArgs = TSD->getTemplateArgs().asArray(); + if (TemplateArgs.size() == 0) +return {}; + auto InnerValueType = TemplateArgs[0].getAsType(); + return C.getASTContext().getPointerType(InnerValueType.getCanonicalType()); +} + +// Helper method to pretty print region and avoid extra spacing. +static void checkAndPrettyPrintRegion(llvm::raw_ostream &OS, + const MemRegion *Region) { + if (Region->canPrintPretty()) { +OS << " "; +Region->printPretty(OS); + } +} + +bool SmartPtrModeling::isBoolConversionMethod(const CallEvent &Call) const { // TODO: Update CallDescription to support anonymous calls? // TODO: Handle other methods, such as .get() or .release(). // But once we do, we'd need a visitor to explain null dereferences @@ -143,21 +180,31 @@ bool SmartPtrModeling::evalCall(const CallEvent &Call, if (!smartptr::isStdSmartPtrCall(Call)) return false; - if (isAssignOpMethod(Call)) { + if (isBoolConversionMethod(Call)) { const MemRegion *ThisR = cast(&Call)->getCXXThisVal().getAsRegion(); -if (!move::isMovedFrom(State, ThisR)) { - // TODO: Model this case as well. At least, avoid invalidation of - // globals. - return false; +if (ModelSmartPtrDereference) { + // The check for the region is moved is duplicated in handleBoolOperation + // method. + // FIXME: Once we model std::move for smart pointers clean up this and use + // that modeling. + handleBoolConversion(Call, C); + return true; +} else { + if (!move::isMov
[clang] 0b4fe80 - [Analyzer] Fix for dereferece of smart pointer after branching on unknown inner pointer
Author: Nithin Vadukkumchery Rajendrakumar Date: 2020-10-09T13:42:25+02:00 New Revision: 0b4fe8086f03294907180007e7de98c80a83b0d7 URL: https://github.com/llvm/llvm-project/commit/0b4fe8086f03294907180007e7de98c80a83b0d7 DIFF: https://github.com/llvm/llvm-project/commit/0b4fe8086f03294907180007e7de98c80a83b0d7.diff LOG: [Analyzer] Fix for dereferece of smart pointer after branching on unknown inner pointer Summary: Enabling warning after dereferece of smart pointer after branching on unknown inner pointer. Reviewers: NoQ, Szelethus, vsavchenko, xazax.hun Reviewed By: NoQ Subscribers: martong, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D87043 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 1ca53590e06c..6ee7bd9252b3 100644 --- a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp @@ -103,7 +103,8 @@ bool isStdSmartPtrCall(const CallEvent &Call) { bool isNullSmartPtr(const ProgramStateRef State, const MemRegion *ThisRegion) { const auto *InnerPointVal = State->get(ThisRegion); - return InnerPointVal && InnerPointVal->isZeroConstant(); + return InnerPointVal && + !State->assume(InnerPointVal->castAs(), true); } } // namespace smartptr } // namespace ento diff --git a/clang/test/Analysis/smart-ptr-text-output.cpp b/clang/test/Analysis/smart-ptr-text-output.cpp index 16c1bddc55e1..f8ecf9192c73 100644 --- a/clang/test/Analysis/smart-ptr-text-output.cpp +++ b/clang/test/Analysis/smart-ptr-text-output.cpp @@ -304,3 +304,12 @@ struct S { // expected-note@-1 {{Division by zero}} } }; + +void derefAfterBranchingOnUnknownInnerPtr(std::unique_ptr P) { + A *RP = P.get(); + if (!RP) { // expected-note {{Assuming 'RP' is null}} +// expected-note@-1 {{Taking true branch}} +P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} +// expected-note@-1{{Dereference of null smart pointer 'P'}} + } +} diff --git a/clang/test/Analysis/smart-ptr.cpp b/clang/test/Analysis/smart-ptr.cpp index 8e8156011eb5..7761ac4cb431 100644 --- a/clang/test/Analysis/smart-ptr.cpp +++ b/clang/test/Analysis/smart-ptr.cpp @@ -333,7 +333,7 @@ std::unique_ptr &&returnRValRefOfUniquePtr(); void drefOnAssignedNullFromMethodPtrValidSmartPtr() { std::unique_ptr P(new A()); P = returnRValRefOfUniquePtr(); - P->foo(); // No warning. + P->foo(); // No warning. } void derefMoveConstructedWithValidPtr() { @@ -374,7 +374,7 @@ std::unique_ptr &&functionReturnsRValueRef(); void derefMoveConstructedWithRValueRefReturn() { std::unique_ptr P(functionReturnsRValueRef()); - P->foo(); // No warning. + P->foo(); // No warning. } void derefConditionOnNullPtr() { @@ -450,3 +450,10 @@ int derefConditionOnUnKnownPtr(int *q) { else return *P; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} } + +void derefAfterBranchingOnUnknownInnerPtr(std::unique_ptr P) { + A *RP = P.get(); + if (!RP) { +P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} + } +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits