[clang] a560910 - [Analyzer] Add checkRegionChanges for SmartPtrModeling

2020-07-20 Thread Nithin Vadukkumchery Rajendrakumar via cfe-commits

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

2020-07-21 Thread Nithin Vadukkumchery Rajendrakumar via cfe-commits

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

2020-07-08 Thread Nithin Vadukkumchery Rajendrakumar via cfe-commits

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

2020-08-11 Thread Nithin Vadukkumchery Rajendrakumar via cfe-commits

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

2020-08-18 Thread Nithin Vadukkumchery Rajendrakumar via cfe-commits

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()

2020-08-23 Thread Nithin Vadukkumchery Rajendrakumar via cfe-commits

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

2020-08-26 Thread Nithin Vadukkumchery Rajendrakumar via cfe-commits

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

2020-08-31 Thread Nithin Vadukkumchery Rajendrakumar via cfe-commits

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

2020-08-31 Thread Nithin Vadukkumchery Rajendrakumar via cfe-commits

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

2020-10-09 Thread Nithin Vadukkumchery Rajendrakumar via cfe-commits

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