[PATCH] D98726: [analyzer] Enabling MallocChecker to take up after SmartPtrModelling

2021-11-07 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

The issues highlighted here have been partially (one could argue mostly) solved 
by D105821 . That patch hasn't been merged 
because it needs more tests and also needs to be split.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D98726/new/

https://reviews.llvm.org/D98726

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D110032: [analyzer] Move docs of SmartPtr to correct subcategory

2021-09-20 Thread Deep Majumder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG5dee50111c13: [analyzer] Move docs of SmartPtr to correct 
subcategory (authored by RedDocMD).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D110032/new/

https://reviews.llvm.org/D110032

Files:
  clang/docs/analyzer/checkers.rst


Index: clang/docs/analyzer/checkers.rst
===
--- clang/docs/analyzer/checkers.rst
+++ clang/docs/analyzer/checkers.rst
@@ -1838,6 +1838,20 @@
a.foo();// warn: method call on a 'moved-from' object 'a'
  }
 
+.. _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.deadcode
 ^^
 .. _alpha-deadcode-UnreachableCode:
@@ -1872,19 +1886,6 @@
[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.fuchsia
 ^
 


Index: clang/docs/analyzer/checkers.rst
===
--- clang/docs/analyzer/checkers.rst
+++ clang/docs/analyzer/checkers.rst
@@ -1838,6 +1838,20 @@
a.foo();// warn: method call on a 'moved-from' object 'a'
  }
 
+.. _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.deadcode
 ^^
 .. _alpha-deadcode-UnreachableCode:
@@ -1872,19 +1886,6 @@
[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.fuchsia
 ^
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D110032: [analyzer] Move docs of SmartPtr to correct subcategory

2021-09-19 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD created this revision.
RedDocMD added reviewers: NoQ, teemperor, xazax.hun, vsavchenko.
Herald added subscribers: manas, steakhal, ASDenysPetrov, dkrupp, donat.nagy, 
Szelethus, mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware.
RedDocMD requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

The docs of alpha.cplusplus.SmartPtr was incorrectly placed under
alpha.deadcode. Moved it to under alpha.cplusplus


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D110032

Files:
  clang/docs/analyzer/checkers.rst


Index: clang/docs/analyzer/checkers.rst
===
--- clang/docs/analyzer/checkers.rst
+++ clang/docs/analyzer/checkers.rst
@@ -1838,6 +1838,20 @@
a.foo();// warn: method call on a 'moved-from' object 'a'
  }
 
+.. _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.deadcode
 ^^
 .. _alpha-deadcode-UnreachableCode:
@@ -1872,19 +1886,6 @@
[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.fuchsia
 ^
 


Index: clang/docs/analyzer/checkers.rst
===
--- clang/docs/analyzer/checkers.rst
+++ clang/docs/analyzer/checkers.rst
@@ -1838,6 +1838,20 @@
a.foo();// warn: method call on a 'moved-from' object 'a'
  }
 
+.. _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.deadcode
 ^^
 .. _alpha-deadcode-UnreachableCode:
@@ -1872,19 +1886,6 @@
[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.fuchsia
 ^
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D108912: [release][analyzer] Add 13.0.0 release notes

2021-09-03 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

In D108912#2982201 , @Szelethus wrote:

> In D108912#2982169 , @RedDocMD 
> wrote:
>
>> I suppose that the `SmartPtrModelling` patches from GSoC this year shouldn't 
>> be added since they only involve an alpha checker.
>
> Actually, you also patched the enabled-by-default modeling part of smart 
> pointers, haven't you? Those definitely deserve their mention!

Well, a part of it is in `0cd98bef1b6f [analyzer] Handle std::swap for 
std::unique_ptr`.
The other major portion is in destructor modelling 
, and this patch hasn't landed yet.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D108912/new/

https://reviews.llvm.org/D108912

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D108912: [release][analyzer] Add 13.0.0 release notes

2021-09-03 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

I suppose that the `SmartPtrModelling` patches from GSoC this year shouldn't be 
added since they only involve an alpha checker.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D108912/new/

https://reviews.llvm.org/D108912

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D106739: [analyzer] Add option to SATest.py for extra checkers

2021-08-16 Thread Deep Majumder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG198e6771e24f: [analyzer] Add option to SATest.py for extra 
checkers (authored by RedDocMD).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D106739/new/

https://reviews.llvm.org/D106739

Files:
  clang/utils/analyzer/SATest.py
  clang/utils/analyzer/SATestBuild.py


Index: clang/utils/analyzer/SATestBuild.py
===
--- clang/utils/analyzer/SATestBuild.py
+++ clang/utils/analyzer/SATestBuild.py
@@ -213,6 +213,7 @@
 project: ProjectInfo
 override_compiler: bool = False
 extra_analyzer_config: str = ""
+extra_checkers: str = ""
 is_reference_build: bool = False
 strictness: int = 0
 
@@ -233,13 +234,16 @@
 """
 A component aggregating all of the project testing.
 """
+
 def __init__(self, jobs: int, projects: List[ProjectInfo],
  override_compiler: bool, extra_analyzer_config: str,
+ extra_checkers: str,
  regenerate: bool, strictness: bool):
 self.jobs = jobs
 self.projects = projects
 self.override_compiler = override_compiler
 self.extra_analyzer_config = extra_analyzer_config
+self.extra_checkers = extra_checkers
 self.regenerate = regenerate
 self.strictness = strictness
 
@@ -252,6 +256,7 @@
 TestInfo(project,
  self.override_compiler,
  self.extra_analyzer_config,
+ self.extra_checkers,
  self.regenerate, self.strictness))
 if self.jobs <= 1:
 return self._single_threaded_test_all(projects_to_test)
@@ -305,10 +310,12 @@
 """
 A component aggregating testing for one project.
 """
+
 def __init__(self, test_info: TestInfo, silent: bool = False):
 self.project = test_info.project
 self.override_compiler = test_info.override_compiler
 self.extra_analyzer_config = test_info.extra_analyzer_config
+self.extra_checkers = test_info.extra_checkers
 self.is_reference_build = test_info.is_reference_build
 self.strictness = test_info.strictness
 self.silent = silent
@@ -414,6 +421,8 @@
 if 'SA_ADDITIONAL_CHECKERS' in os.environ:
 all_checkers = (all_checkers + ',' +
 os.environ['SA_ADDITIONAL_CHECKERS'])
+if self.extra_checkers != "":
+all_checkers += "," + self.extra_checkers
 
 # Run scan-build from within the patched source directory.
 cwd = os.path.join(directory, PATCHED_SOURCE_DIR_NAME)
Index: clang/utils/analyzer/SATest.py
===
--- clang/utils/analyzer/SATest.py
+++ clang/utils/analyzer/SATest.py
@@ -42,6 +42,7 @@
   projects,
   args.override_compiler,
   args.extra_analyzer_config,
+  args.extra_checkers,
   args.regenerate,
   args.strictness)
 tests_passed = tester.test_all()
@@ -250,6 +251,10 @@
   dest="extra_analyzer_config", type=str,
   default="",
   help="Arguments passed to to -analyzer-config")
+build_parser.add_argument("--extra-checkers",
+  dest="extra_checkers", type=str,
+  default="",
+  help="Extra checkers to enable")
 build_parser.add_argument("--projects", action="store", default="",
   help="Comma-separated list of projects to test")
 build_parser.add_argument("--max-size", action="store", default=None,


Index: clang/utils/analyzer/SATestBuild.py
===
--- clang/utils/analyzer/SATestBuild.py
+++ clang/utils/analyzer/SATestBuild.py
@@ -213,6 +213,7 @@
 project: ProjectInfo
 override_compiler: bool = False
 extra_analyzer_config: str = ""
+extra_checkers: str = ""
 is_reference_build: bool = False
 strictness: int = 0
 
@@ -233,13 +234,16 @@
 """
 A component aggregating all of the project testing.
 """
+
 def __init__(self, jobs: int, projects: List[ProjectInfo],
  override_compiler: bool, extra_analyzer_config: str,
+ extra_checkers: str,
  regenerate: bool, strictness: bool):
 self.jobs = jobs
 self.projects = projects
 self.override_compiler = override_compiler
 self.extra_analyzer_config = extra_analyzer_config
+s

[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-08-16 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 366558.
RedDocMD added a comment.

Connecting to MallocChecker


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp

Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -753,10 +753,13 @@
 *Call, *this);
 
   ExplodedNodeSet DstInvalidated;
-  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-   I != E; ++I)
-defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+  // for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E =
+  // DstPreCall.end();
+  //  I != E; ++I)
+  //   defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, *Call,
+ *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
  *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,11 @@
 for (const auto &EvalCallChecker : EvalCallCheckers) {
   // TODO: Support the situation when the call doesn't correspond
   // to any Expr.
-  ProgramPoint L = ProgramPoint::getProgramPoint(
-  Call.getOriginExpr(), ProgramPoint::PostStmtKind,
-  Pred->getLocationContext(), EvalCallChecker.Checker);
   bool evaluated = false;
   { // CheckerContext generates transitions(populates checkDest) on
 // destruction, so introduce the scope to make sure it gets properly
 // populated.
-CheckerContext C(B, Eng, Pred, L);
+CheckerContext C(B, Eng, Pred, Call.getProgramPoint());
 evaluated = EvalCallChecker(Call, C);
   }
   assert(!(evaluated && anyEvaluated)
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -11,6 +11,7 @@
 //
 //===--===//
 
+#include "AllocationState.h"
 #include "Move.h"
 #include "SmartPtr.h"
 
@@ -46,6 +47,8 @@
   bool isBoolConversionMethod(const CallEvent &Call) const;
 
 public:
+  SmartPtrModeling(CheckerManager &ChkMgr) : ChkMgr(ChkMgr) {}
+
   // Whether the checker should model for null dereferences of smart pointers.
   DefaultBool ModelSmartPtrDereference;
   bool evalCall(const CallEvent &Call, CheckerContext &C) const;
@@ -92,6 +95,7 @@
   const CallDescription StdMakeUniqueCall{{"std", "make_unique"}};
   const CallDescription StdMakeUniqueForOverwriteCall{
   {"std", "make_unique_for_overwrite"}};
+  CheckerManager &ChkMgr;
 };
 } // end of anonymous namespace
 
@@ -139,7 +143,7 @@
 
   if (RD->getDeclName().isIdentifier()) {
 StringRef Name = RD->getName();
-return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr";
+return llvm::is_contained(STD_PTR_NAMES, Name);
   }
   return false;
 }
@@ -157,20 +161,6 @@
 } // 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;
-}
-
 static ProgramStateRef updateSwappedRegion(ProgramStateRef State,
const MemRegion *Region,
const SVal *RegionInnerPointerVal) {
@@ -275,6 +265,32 @@
  smartptr::isStdSmartPtr(Call.getArgExpr(1));
 }
 
+ProgramStateRef
+invalidateInnerPointer(const MemRegion *ThisRegion, ProgramStateRef State,
+   const CallEvent &Call, CheckerContext &C) {
+  const auto *InnerPtrVal = State->get(ThisRegion);
+  if (InnerPtrVal) {
+const auto *Sym = InnerPtrVal->getAsSymbol();
+if (Sym)
+  State = allocation_state::markReleased(State, Sym, Call.getOriginExp

[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-08-08 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:440
+  State, {std::make_pair(CC->getCXXThisVal(), ArgVal)},
+  C.getLocationContext(), PSK_DirectEscapeOnCall, &Call);
 

It seems to me that this pointer escape doesn't work.
For the following code:
```lang=cpp
void foo() {
auto ptr = std::unique_ptr(new int(13));
// Leak warning emitted here
}
```
the exploded graph shows the SVal for `new int(13)` as allocated instead of 
escaped (which eventually triggers the warning).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-08-08 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 365031.
RedDocMD added a comment.

Further pointer escape


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp

Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -753,10 +753,13 @@
 *Call, *this);
 
   ExplodedNodeSet DstInvalidated;
-  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-   I != E; ++I)
-defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+  // for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E =
+  // DstPreCall.end();
+  //  I != E; ++I)
+  //   defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, *Call,
+ *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
  *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,11 @@
 for (const auto &EvalCallChecker : EvalCallCheckers) {
   // TODO: Support the situation when the call doesn't correspond
   // to any Expr.
-  ProgramPoint L = ProgramPoint::getProgramPoint(
-  Call.getOriginExpr(), ProgramPoint::PostStmtKind,
-  Pred->getLocationContext(), EvalCallChecker.Checker);
   bool evaluated = false;
   { // CheckerContext generates transitions(populates checkDest) on
 // destruction, so introduce the scope to make sure it gets properly
 // populated.
-CheckerContext C(B, Eng, Pred, L);
+CheckerContext C(B, Eng, Pred, Call.getProgramPoint());
 evaluated = EvalCallChecker(Call, C);
   }
   assert(!(evaluated && anyEvaluated)
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -46,6 +46,8 @@
   bool isBoolConversionMethod(const CallEvent &Call) const;
 
 public:
+  SmartPtrModeling(CheckerManager &ChkMgr) : ChkMgr(ChkMgr) {}
+
   // Whether the checker should model for null dereferences of smart pointers.
   DefaultBool ModelSmartPtrDereference;
   bool evalCall(const CallEvent &Call, CheckerContext &C) const;
@@ -92,6 +94,7 @@
   const CallDescription StdMakeUniqueCall{{"std", "make_unique"}};
   const CallDescription StdMakeUniqueForOverwriteCall{
   {"std", "make_unique_for_overwrite"}};
+  CheckerManager &ChkMgr;
 };
 } // end of anonymous namespace
 
@@ -139,7 +142,7 @@
 
   if (RD->getDeclName().isIdentifier()) {
 StringRef Name = RD->getName();
-return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr";
+return llvm::is_contained(STD_PTR_NAMES, Name);
   }
   return false;
 }
@@ -157,20 +160,6 @@
 } // 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;
-}
-
 static ProgramStateRef updateSwappedRegion(ProgramStateRef State,
const MemRegion *Region,
const SVal *RegionInnerPointerVal) {
@@ -275,6 +264,29 @@
  smartptr::isStdSmartPtr(Call.getArgExpr(1));
 }
 
+ProgramStateRef
+invalidateInnerPointer(const MemRegion *ThisRegion, ProgramStateRef State,
+   const CallEvent &Call, CheckerContext &C) {
+  const auto *InnerPtrVal = State->get(ThisRegion);
+  if (InnerPtrVal) {
+State = State->invalidateRegions(*InnerPtrVal, nullptr, C.blockCount(),
+ C.getLocationContext(), true);
+
+const QualType &Type = getInnerPointerType(Call, C);
+const auto *RD = Type->getAsCXXRecordDecl();
+if (!RD)
+  return State;
+const auto *DD = RD->getDestr

[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-08-05 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 364490.
RedDocMD added a comment.

Never gonna give you up.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp

Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -753,10 +753,13 @@
 *Call, *this);
 
   ExplodedNodeSet DstInvalidated;
-  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-   I != E; ++I)
-defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+  // for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E =
+  // DstPreCall.end();
+  //  I != E; ++I)
+  //   defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, *Call,
+ *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
  *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,11 @@
 for (const auto &EvalCallChecker : EvalCallCheckers) {
   // TODO: Support the situation when the call doesn't correspond
   // to any Expr.
-  ProgramPoint L = ProgramPoint::getProgramPoint(
-  Call.getOriginExpr(), ProgramPoint::PostStmtKind,
-  Pred->getLocationContext(), EvalCallChecker.Checker);
   bool evaluated = false;
   { // CheckerContext generates transitions(populates checkDest) on
 // destruction, so introduce the scope to make sure it gets properly
 // populated.
-CheckerContext C(B, Eng, Pred, L);
+CheckerContext C(B, Eng, Pred, Call.getProgramPoint());
 evaluated = EvalCallChecker(Call, C);
   }
   assert(!(evaluated && anyEvaluated)
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -139,7 +139,7 @@
 
   if (RD->getDeclName().isIdentifier()) {
 StringRef Name = RD->getName();
-return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr";
+return llvm::is_contained(STD_PTR_NAMES, Name);
   }
   return false;
 }
@@ -275,6 +275,29 @@
  smartptr::isStdSmartPtr(Call.getArgExpr(1));
 }
 
+ProgramStateRef
+invalidateInnerPointer(const MemRegion *ThisRegion, ProgramStateRef State,
+   const CallEvent &Call, CheckerContext &C) {
+  const auto *InnerPtrVal = State->get(ThisRegion);
+  if (InnerPtrVal) {
+State = State->invalidateRegions(*InnerPtrVal, nullptr, C.blockCount(),
+ C.getLocationContext(), true);
+
+const QualType &Type = getInnerPointerType(Call, C);
+const auto *RD = Type->getAsCXXRecordDecl();
+if (!RD)
+  return State;
+const auto *DD = RD->getDestructor();
+
+const auto InnerDestrCall =
+C.getStateManager().getCallEventManager().getCXXDestructorCall(
+DD, nullptr, InnerPtrVal->getAsRegion(), RD->bases().empty(), State,
+C.getLocationContext());
+InnerDestrCall->invalidateRegions(C.blockCount(), State);
+  }
+  return State;
+}
+
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
 
@@ -372,6 +395,21 @@
 }
   }
 
+  if (const auto *DC = dyn_cast(&Call)) {
+const MemRegion *ThisRegion = DC->getCXXThisVal().getAsRegion();
+if (!ThisRegion)
+  return false;
+State = State->remove(ThisRegion);
+State = invalidateInnerPointer(ThisRegion, State, Call, C);
+// This tag is required to prevent later crashes due to the non-addition
+// of new States. Having a tag ensures that the call to addTransition
+// actually adds a new state.
+static SimpleProgramPointTag SPPT("SmartPtrModeling",
+  "on destructor modeling");
+C.addTransition(State, &SPPT);
+return true;
+  }
+
   if (!ModelSmartPtrDereference)
 return false;
 
@@ -402,10 +440,14 @@
   }));
 } else {
   const auto *TrackingExpr = Call.getArgExpr(0);
-  assert(TrackingExpr->getType()->isPointerType() &&
- "Adding a non pointer

[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-08-05 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 364486.
RedDocMD added a comment.

Bug fix in modelling


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp

Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -753,10 +753,13 @@
 *Call, *this);
 
   ExplodedNodeSet DstInvalidated;
-  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-   I != E; ++I)
-defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+  // for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E =
+  // DstPreCall.end();
+  //  I != E; ++I)
+  //   defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, *Call,
+ *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
  *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,11 @@
 for (const auto &EvalCallChecker : EvalCallCheckers) {
   // TODO: Support the situation when the call doesn't correspond
   // to any Expr.
-  ProgramPoint L = ProgramPoint::getProgramPoint(
-  Call.getOriginExpr(), ProgramPoint::PostStmtKind,
-  Pred->getLocationContext(), EvalCallChecker.Checker);
   bool evaluated = false;
   { // CheckerContext generates transitions(populates checkDest) on
 // destruction, so introduce the scope to make sure it gets properly
 // populated.
-CheckerContext C(B, Eng, Pred, L);
+CheckerContext C(B, Eng, Pred, Call.getProgramPoint());
 evaluated = EvalCallChecker(Call, C);
   }
   assert(!(evaluated && anyEvaluated)
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -139,7 +139,7 @@
 
   if (RD->getDeclName().isIdentifier()) {
 StringRef Name = RD->getName();
-return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr";
+return llvm::is_contained(STD_PTR_NAMES, Name);
   }
   return false;
 }
@@ -275,6 +275,29 @@
  smartptr::isStdSmartPtr(Call.getArgExpr(1));
 }
 
+std::pair
+invalidateInnerPointer(const MemRegion *ThisRegion, ProgramStateRef State,
+   const CallEvent &Call, CheckerContext &C) {
+  const auto *InnerPtrVal = State->get(ThisRegion);
+  if (InnerPtrVal) {
+State = State->invalidateRegions(*InnerPtrVal, nullptr, C.blockCount(),
+ C.getLocationContext(), true);
+
+const QualType &Type = getInnerPointerType(Call, C);
+const auto *RD = Type->getAsCXXRecordDecl();
+if (!RD)
+  return {State, false};
+const auto *DD = RD->getDestructor();
+
+const auto InnerDestrCall =
+C.getStateManager().getCallEventManager().getCXXDestructorCall(
+DD, nullptr, InnerPtrVal->getAsRegion(), RD->bases().empty(), State,
+C.getLocationContext());
+InnerDestrCall->invalidateRegions(C.blockCount(), State);
+  }
+  return {State, true};
+}
+
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
 
@@ -372,6 +395,23 @@
 }
   }
 
+  if (const auto *DC = dyn_cast(&Call)) {
+const MemRegion *ThisRegion = DC->getCXXThisVal().getAsRegion();
+if (!ThisRegion)
+  return false;
+State = State->remove(ThisRegion);
+bool ShouldGiveUp;
+std::tie(State, ShouldGiveUp) =
+invalidateInnerPointer(ThisRegion, State, Call, C);
+// This tag is required to prevent later crashes due to the non-addition
+// of new States. Having a tag ensures that the call to addTransition
+// actually adds a new state.
+static SimpleProgramPointTag SPPT("SmartPtrModeling",
+  "on destructor modeling");
+C.addTransition(State, &SPPT);
+return !ShouldGiveUp;
+  }
+
   if (!ModelSmartPtrDereference)
 return false;
 
@@ -402,10 +442,14 @@
   }));
 } else {
   const auto *TrackingExpr = Call.getArgExpr(0);
-  assert(Tracki

[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-08-04 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

I have incorporated the bug-fixes suggested last meeting (except the pointer 
escape one). And it seems to have had dramatic results - now the only extra 
errors being reported are the pointer escape ones (5 of them, from 3 different 
projects). Some projects are actually reporting that bug reports have been 
//removed// due to this patch.F18343949: Error List 2.pdf 



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-08-04 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 364074.
RedDocMD added a comment.

Better modelling, bug fixes


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp

Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -753,10 +753,13 @@
 *Call, *this);
 
   ExplodedNodeSet DstInvalidated;
-  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-   I != E; ++I)
-defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+  // for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E =
+  // DstPreCall.end();
+  //  I != E; ++I)
+  //   defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, *Call,
+ *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
  *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,11 @@
 for (const auto &EvalCallChecker : EvalCallCheckers) {
   // TODO: Support the situation when the call doesn't correspond
   // to any Expr.
-  ProgramPoint L = ProgramPoint::getProgramPoint(
-  Call.getOriginExpr(), ProgramPoint::PostStmtKind,
-  Pred->getLocationContext(), EvalCallChecker.Checker);
   bool evaluated = false;
   { // CheckerContext generates transitions(populates checkDest) on
 // destruction, so introduce the scope to make sure it gets properly
 // populated.
-CheckerContext C(B, Eng, Pred, L);
+CheckerContext C(B, Eng, Pred, Call.getProgramPoint());
 evaluated = EvalCallChecker(Call, C);
   }
   assert(!(evaluated && anyEvaluated)
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -139,7 +139,7 @@
 
   if (RD->getDeclName().isIdentifier()) {
 StringRef Name = RD->getName();
-return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr";
+return llvm::is_contained(STD_PTR_NAMES, Name);
   }
   return false;
 }
@@ -275,6 +275,29 @@
  smartptr::isStdSmartPtr(Call.getArgExpr(1));
 }
 
+std::pair
+invalidateInnerPointer(const MemRegion *ThisRegion, ProgramStateRef State,
+   const CallEvent &Call, CheckerContext &C) {
+  const auto *InnerPtrVal = State->get(ThisRegion);
+  if (InnerPtrVal) {
+State = State->invalidateRegions(*InnerPtrVal, nullptr, C.blockCount(),
+ C.getLocationContext(), true);
+
+const QualType &Type = getInnerPointerType(Call, C);
+const auto *RD = Type->getAsCXXRecordDecl();
+if (!RD)
+  return {State, false};
+const auto *DD = RD->getDestructor();
+
+const auto InnerDestrCall =
+C.getStateManager().getCallEventManager().getCXXDestructorCall(
+DD, nullptr, InnerPtrVal->getAsRegion(), RD->bases().empty(), State,
+C.getLocationContext());
+InnerDestrCall->invalidateRegions(C.blockCount(), State);
+  }
+  return {State, true};
+}
+
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
 
@@ -372,6 +395,25 @@
 }
   }
 
+  if (const auto *DC = dyn_cast(&Call)) {
+const MemRegion *ThisRegion = DC->getCXXThisVal().getAsRegion();
+if (!ThisRegion)
+  return false;
+State = State->remove(ThisRegion);
+bool ShouldGiveUp;
+std::tie(State, ShouldGiveUp) =
+invalidateInnerPointer(ThisRegion, State, Call, C);
+if (ShouldGiveUp)
+  return false;
+// This tag is required to prevent later crashes due to the non-addition
+// of new States. Having a tag ensures that the call to addTransition
+// actually adds a new state.
+static SimpleProgramPointTag SPPT("SmartPtrModeling",
+  "on destructor modeling");
+C.addTransition(State, &SPPT);
+return true;
+  }
+
   if (!ModelSmartPtrDereference)
 return false;
 
@@ -402,8 +444,8 @@
   }));
 } else {
   const auto *TrackingExpr = 

[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-07-30 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

Well some of them are exactly the same type as the `Lame` class example above. 
Like: 
`simbody/report-TestArray.cpp-testMoveConstructionAndAssignment-27-1.html#EndPath`.
 (So the incomplete modelling of the destructor is at least one cause. The 
other reason that you suggested might as well be true).
Btw, the `destructor1.txt` file from my previous comment should be used to 
drill down the newly added reports.

F18239807: simbody.tar.xz 

F18239806: fmt.tar.xz 

F18239805: faiss.tar.xz 

F18239804: re2.tar.xz 

F18239803: oatpp.tar.xz 

F18239802: drogon.tar.xz 


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-07-30 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 363138.
RedDocMD added a comment.

Invalidating using inner pointer destructor call


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp

Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -753,10 +753,13 @@
 *Call, *this);
 
   ExplodedNodeSet DstInvalidated;
-  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-   I != E; ++I)
-defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+  // for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E =
+  // DstPreCall.end();
+  //  I != E; ++I)
+  //   defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, *Call,
+ *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
  *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,11 @@
 for (const auto &EvalCallChecker : EvalCallCheckers) {
   // TODO: Support the situation when the call doesn't correspond
   // to any Expr.
-  ProgramPoint L = ProgramPoint::getProgramPoint(
-  Call.getOriginExpr(), ProgramPoint::PostStmtKind,
-  Pred->getLocationContext(), EvalCallChecker.Checker);
   bool evaluated = false;
   { // CheckerContext generates transitions(populates checkDest) on
 // destruction, so introduce the scope to make sure it gets properly
 // populated.
-CheckerContext C(B, Eng, Pred, L);
+CheckerContext C(B, Eng, Pred, Call.getProgramPoint());
 evaluated = EvalCallChecker(Call, C);
   }
   assert(!(evaluated && anyEvaluated)
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -139,7 +139,7 @@
 
   if (RD->getDeclName().isIdentifier()) {
 StringRef Name = RD->getName();
-return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr";
+return llvm::is_contained(STD_PTR_NAMES, Name);
   }
   return false;
 }
@@ -279,6 +279,7 @@
 CheckerContext &C) const {
 
   ProgramStateRef State = C.getState();
+  Call.dump();
 
   // If any one of the arg is a unique_ptr, then
   // we can try this function
@@ -372,6 +373,35 @@
 }
   }
 
+  if (const auto *DC = dyn_cast(&Call)) {
+llvm::errs() << "Found destructor call\n";
+// FIXME: This is a sort-of redundant operation.
+// But we can't remove it currently, otherwise shared_ptr and weak_ptr
+// causes a crash after this.
+State = DC->invalidateRegions(C.blockCount(), State);
+const MemRegion *ThisRegion = DC->getCXXThisVal().getAsRegion();
+// TODO: Remove this before pushing
+assert(ThisRegion && "We do not support explicit calls to destructor");
+const auto *InnerPtrVal = State->get(ThisRegion);
+State = State->remove(ThisRegion);
+if (InnerPtrVal) {
+  State = State->invalidateRegions(*InnerPtrVal, nullptr, C.blockCount(),
+   C.getLocationContext(), true);
+
+  const QualType &Type = getInnerPointerType(Call, C);
+  const auto *RD = Type->getAsCXXRecordDecl();
+  const auto *DD = RD->getDestructor();
+
+  const auto InnerDestrCall =
+  C.getStateManager().getCallEventManager().getCXXDestructorCall(
+  DD, nullptr, InnerPtrVal->getAsRegion(), RD->bases().empty(),
+  State, C.getLocationContext());
+  InnerDestrCall->invalidateRegions(C.blockCount(), State);
+}
+C.addTransition(State);
+return true;
+  }
+
   if (!ModelSmartPtrDereference)
 return false;
 
@@ -402,8 +432,8 @@
   }));
 } else {
   const auto *TrackingExpr = Call.getArgExpr(0);
-  assert(TrackingExpr->getType()->isPointerType() &&
- "Adding a non pointer value to TrackedRegionMap");
+  if (!TrackingExpr->getType()->isPointerType())
+return false;
   auto ArgVal = Call.getArgSVal(0);
   State = State->set(ThisRegion,

[PATCH] D106739: [analyzer] Add option to SATest.py for extra checkers

2021-07-30 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

In D106739#2907647 , @ASDenysPetrov 
wrote:

> @RedDocMD Could you, please, explain the motivation and add at least one test 
> to verify it works.

Motivation: I need to run these projects with the SmartPtrChecker enabled 
(which is an alpha checker, hence not enabled by default).
Test: This is more of a helper script, not a core library, so I think we can be 
a little relaxed with the testing thing.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D106739/new/

https://reviews.llvm.org/D106739

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-07-29 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

On running this patch on the `projects` directory, a bunch of projects emit 
false-positives: mostly of the form `Potential memory leak`. This points to the 
fact that without calling the destructor of the pointee type, we are going to 
have a lot of false positives (408 for //one// project is the worst I have 
seen). I have attached the result file.F18215302: destructor1.txt 



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-07-29 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 362741.
RedDocMD added a comment.

Put in a TODO


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp


Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -753,10 +753,13 @@
 *Call, *this);
 
   ExplodedNodeSet DstInvalidated;
-  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-   I != E; ++I)
-defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+  // for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E =
+  // DstPreCall.end();
+  //  I != E; ++I)
+  //   defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, *Call,
+ *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
  *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,11 @@
 for (const auto &EvalCallChecker : EvalCallCheckers) {
   // TODO: Support the situation when the call doesn't correspond
   // to any Expr.
-  ProgramPoint L = ProgramPoint::getProgramPoint(
-  Call.getOriginExpr(), ProgramPoint::PostStmtKind,
-  Pred->getLocationContext(), EvalCallChecker.Checker);
   bool evaluated = false;
   { // CheckerContext generates transitions(populates checkDest) on
 // destruction, so introduce the scope to make sure it gets properly
 // populated.
-CheckerContext C(B, Eng, Pred, L);
+CheckerContext C(B, Eng, Pred, Call.getProgramPoint());
 evaluated = EvalCallChecker(Call, C);
   }
   assert(!(evaluated && anyEvaluated)
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -139,7 +139,7 @@
 
   if (RD->getDeclName().isIdentifier()) {
 StringRef Name = RD->getName();
-return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr";
+return llvm::is_contained(STD_PTR_NAMES, Name);
   }
   return false;
 }
@@ -279,6 +279,7 @@
 CheckerContext &C) const {
 
   ProgramStateRef State = C.getState();
+  Call.dump();
 
   // If any one of the arg is a unique_ptr, then
   // we can try this function
@@ -372,6 +373,21 @@
 }
   }
 
+  if (const auto *DC = dyn_cast(&Call)) {
+llvm::errs() << "Found destructor call\n";
+State = DC->invalidateRegions(C.blockCount(), State);
+const MemRegion *ThisRegion = DC->getCXXThisVal().getAsRegion();
+// TODO: Remove this before pushing
+assert(ThisRegion && "We do not support explicit calls to destructor");
+const auto *InnerPtrVal = State->get(ThisRegion);
+State = State->remove(ThisRegion);
+if (InnerPtrVal)
+  State = State->invalidateRegions(*InnerPtrVal, nullptr, C.blockCount(),
+   C.getLocationContext(), true);
+C.addTransition(State);
+return true;
+  }
+
   if (!ModelSmartPtrDereference)
 return false;
 
@@ -402,8 +418,8 @@
   }));
 } else {
   const auto *TrackingExpr = Call.getArgExpr(0);
-  assert(TrackingExpr->getType()->isPointerType() &&
- "Adding a non pointer value to TrackedRegionMap");
+  if (!TrackingExpr->getType()->isPointerType())
+return false;
   auto ArgVal = Call.getArgSVal(0);
   State = State->set(ThisRegion, ArgVal);
 


Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -753,10 +753,13 @@
 *Call, *this);
 
   ExplodedNodeSet DstInvalidated;
-  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-   I != E; ++I)
-defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+  // for (ExplodedNo

[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-07-29 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:381
+const MemRegion *ThisRegion = DC->getCXXThisVal().getAsRegion();
+assert(ThisRegion && "We do not support explicit calls to destructor");
+const auto *InnerPtrVal = State->get(ThisRegion);

vsavchenko wrote:
> RedDocMD wrote:
> > vsavchenko wrote:
> > > And if it happens we are going to crash with assertion failure?
> > Assuming assertions are enabled, that is.
> We should never crash or fail on valid C++ code.  We can abandon everything, 
> forbid checker to report anything on a function that has something that we 
> don't know how to handle properly, but never fail the overall analysis 
> process because of that. 
Ah right, I should have put in a TODO. This assert was put to see how often I 
run into this (none so far). It must be removed before this patch is accepted.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-07-29 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 362738.
RedDocMD added a comment.

Bug fixes, some cleanup


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp


Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -753,10 +753,13 @@
 *Call, *this);
 
   ExplodedNodeSet DstInvalidated;
-  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-   I != E; ++I)
-defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+  // for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E =
+  // DstPreCall.end();
+  //  I != E; ++I)
+  //   defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, *Call,
+ *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
  *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,11 @@
 for (const auto &EvalCallChecker : EvalCallCheckers) {
   // TODO: Support the situation when the call doesn't correspond
   // to any Expr.
-  ProgramPoint L = ProgramPoint::getProgramPoint(
-  Call.getOriginExpr(), ProgramPoint::PostStmtKind,
-  Pred->getLocationContext(), EvalCallChecker.Checker);
   bool evaluated = false;
   { // CheckerContext generates transitions(populates checkDest) on
 // destruction, so introduce the scope to make sure it gets properly
 // populated.
-CheckerContext C(B, Eng, Pred, L);
+CheckerContext C(B, Eng, Pred, Call.getProgramPoint());
 evaluated = EvalCallChecker(Call, C);
   }
   assert(!(evaluated && anyEvaluated)
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -139,7 +139,7 @@
 
   if (RD->getDeclName().isIdentifier()) {
 StringRef Name = RD->getName();
-return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr";
+return llvm::is_contained(STD_PTR_NAMES, Name);
   }
   return false;
 }
@@ -279,6 +279,7 @@
 CheckerContext &C) const {
 
   ProgramStateRef State = C.getState();
+  Call.dump();
 
   // If any one of the arg is a unique_ptr, then
   // we can try this function
@@ -372,6 +373,20 @@
 }
   }
 
+  if (const auto *DC = dyn_cast(&Call)) {
+llvm::errs() << "Found destructor call\n";
+State = DC->invalidateRegions(C.blockCount(), State);
+const MemRegion *ThisRegion = DC->getCXXThisVal().getAsRegion();
+assert(ThisRegion && "We do not support explicit calls to destructor");
+const auto *InnerPtrVal = State->get(ThisRegion);
+State = State->remove(ThisRegion);
+if (InnerPtrVal)
+  State = State->invalidateRegions(*InnerPtrVal, nullptr, C.blockCount(),
+   C.getLocationContext(), true);
+C.addTransition(State);
+return true;
+  }
+
   if (!ModelSmartPtrDereference)
 return false;
 
@@ -402,8 +417,8 @@
   }));
 } else {
   const auto *TrackingExpr = Call.getArgExpr(0);
-  assert(TrackingExpr->getType()->isPointerType() &&
- "Adding a non pointer value to TrackedRegionMap");
+  if (!TrackingExpr->getType()->isPointerType())
+return false;
   auto ArgVal = Call.getArgSVal(0);
   State = State->set(ThisRegion, ArgVal);
 


Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -753,10 +753,13 @@
 *Call, *this);
 
   ExplodedNodeSet DstInvalidated;
-  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-   I != E; ++I)
-defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+  // for (ExplodedNodeSet::iterator I = DstPreCall.

[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-07-29 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:143
+llvm::ArrayRef ValidNames(STD_PTR_NAMES);
+return llvm::is_contained(ValidNames, Name);
   }

vsavchenko wrote:
> And why can't we pass `STD_PTR_NAMES` directly to `llvm::is_contained`?
Ooh, so there is an overload for that as well. :)



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:381
+const MemRegion *ThisRegion = DC->getCXXThisVal().getAsRegion();
+assert(ThisRegion && "We do not support explicit calls to destructor");
+const auto *InnerPtrVal = State->get(ThisRegion);

vsavchenko wrote:
> And if it happens we are going to crash with assertion failure?
Assuming assertions are enabled, that is.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-07-29 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:421-422
   const auto *TrackingExpr = Call.getArgExpr(0);
-  assert(TrackingExpr->getType()->isPointerType() &&
- "Adding a non pointer value to TrackedRegionMap");
+  if (TrackingExpr->getType()->isPointerType())
+return false;
   auto ArgVal = Call.getArgSVal(0);

vsavchenko wrote:
> Okay, I'm either missing something or this condition is missing `!` here.
And that's the ghost bug I am chasing around for the last few hours.
Thanks :)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-07-28 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

Ah I see.
As a side note, without the "redundant" invalidation that is being done, the 
analyzer crashes on `shared_ptr`. (Because the `State` essentially remains the 
same and that's what causes the crash).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-07-28 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 362310.
RedDocMD added a comment.

Invalidating via the CallEvent


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp


Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -753,10 +753,13 @@
 *Call, *this);
 
   ExplodedNodeSet DstInvalidated;
-  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-   I != E; ++I)
-defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+  // for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E =
+  // DstPreCall.end();
+  //  I != E; ++I)
+  //   defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, *Call,
+ *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
  *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,11 @@
 for (const auto &EvalCallChecker : EvalCallCheckers) {
   // TODO: Support the situation when the call doesn't correspond
   // to any Expr.
-  ProgramPoint L = ProgramPoint::getProgramPoint(
-  Call.getOriginExpr(), ProgramPoint::PostStmtKind,
-  Pred->getLocationContext(), EvalCallChecker.Checker);
   bool evaluated = false;
   { // CheckerContext generates transitions(populates checkDest) on
 // destruction, so introduce the scope to make sure it gets properly
 // populated.
-CheckerContext C(B, Eng, Pred, L);
+CheckerContext C(B, Eng, Pred, Call.getProgramPoint());
 evaluated = EvalCallChecker(Call, C);
   }
   assert(!(evaluated && anyEvaluated)
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -139,7 +139,8 @@
 
   if (RD->getDeclName().isIdentifier()) {
 StringRef Name = RD->getName();
-return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr";
+llvm::ArrayRef ValidNames(STD_PTR_NAMES);
+return llvm::is_contained(ValidNames, Name);
   }
   return false;
 }
@@ -279,6 +280,7 @@
 CheckerContext &C) const {
 
   ProgramStateRef State = C.getState();
+  Call.dump();
 
   // If any one of the arg is a unique_ptr, then
   // we can try this function
@@ -372,6 +374,20 @@
 }
   }
 
+  if (const auto *DC = dyn_cast(&Call)) {
+llvm::errs() << "Found destructor call\n";
+State = DC->invalidateRegions(C.blockCount(), State);
+const MemRegion *ThisRegion = DC->getCXXThisVal().getAsRegion();
+assert(ThisRegion && "We do not support explicit calls to destructor");
+const auto *InnerPtrVal = State->get(ThisRegion);
+State = State->remove(ThisRegion);
+if (InnerPtrVal)
+  State = State->invalidateRegions(*InnerPtrVal, nullptr, C.blockCount(),
+   C.getLocationContext(), true);
+C.addTransition(State);
+return true;
+  }
+
   if (!ModelSmartPtrDereference)
 return false;
 
@@ -402,8 +418,8 @@
   }));
 } else {
   const auto *TrackingExpr = Call.getArgExpr(0);
-  assert(TrackingExpr->getType()->isPointerType() &&
- "Adding a non pointer value to TrackedRegionMap");
+  if (TrackingExpr->getType()->isPointerType())
+return false;
   auto ArgVal = Call.getArgSVal(0);
   State = State->set(ThisRegion, ArgVal);
 


Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -753,10 +753,13 @@
 *Call, *this);
 
   ExplodedNodeSet DstInvalidated;
-  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-   I != E; ++I)
-defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+ 

[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-07-25 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 361581.
RedDocMD added a comment.

Removed a fatal bug


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp


Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -753,10 +753,13 @@
 *Call, *this);
 
   ExplodedNodeSet DstInvalidated;
-  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-   I != E; ++I)
-defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+  // for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E =
+  // DstPreCall.end();
+  //  I != E; ++I)
+  //   defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, *Call,
+ *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
  *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,11 @@
 for (const auto &EvalCallChecker : EvalCallCheckers) {
   // TODO: Support the situation when the call doesn't correspond
   // to any Expr.
-  ProgramPoint L = ProgramPoint::getProgramPoint(
-  Call.getOriginExpr(), ProgramPoint::PostStmtKind,
-  Pred->getLocationContext(), EvalCallChecker.Checker);
   bool evaluated = false;
   { // CheckerContext generates transitions(populates checkDest) on
 // destruction, so introduce the scope to make sure it gets properly
 // populated.
-CheckerContext C(B, Eng, Pred, L);
+CheckerContext C(B, Eng, Pred, Call.getProgramPoint());
 evaluated = EvalCallChecker(Call, C);
   }
   assert(!(evaluated && anyEvaluated)
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -279,6 +279,7 @@
 CheckerContext &C) const {
 
   ProgramStateRef State = C.getState();
+  Call.dump();
 
   // If any one of the arg is a unique_ptr, then
   // we can try this function
@@ -372,6 +373,19 @@
 }
   }
 
+  if (const auto *DC = dyn_cast(&Call)) {
+llvm::errs() << "Found destructor call\n";
+const MemRegion *ThisRegion = DC->getCXXThisVal().getAsRegion();
+assert(ThisRegion && "We do not support explicit calls to destructor");
+const auto *InnerPtrVal = State->get(ThisRegion);
+State = State->remove(ThisRegion);
+if (InnerPtrVal)
+  State = State->invalidateRegions(*InnerPtrVal, nullptr, C.blockCount(),
+   C.getLocationContext(), true);
+C.addTransition(State);
+return true;
+  }
+
   if (!ModelSmartPtrDereference)
 return false;
 


Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -753,10 +753,13 @@
 *Call, *this);
 
   ExplodedNodeSet DstInvalidated;
-  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-   I != E; ++I)
-defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+  // for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E =
+  // DstPreCall.end();
+  //  I != E; ++I)
+  //   defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, *Call,
+ *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
  *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,11 @@
 for (const auto &EvalCallChecker : EvalCallCheckers) {
   // TODO: S

[PATCH] D106739: [analyzer] Add option to SATest.py for extra checkers

2021-07-25 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

@vsavchenko is this okay?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D106739/new/

https://reviews.llvm.org/D106739

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-07-25 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

In D105821#2897006 , @NoQ wrote:

>> the following code doesn't emit any warnings
>
> This code doesn't seem to have any `unique_ptr`s in it? It's not like you're 
> modeling this custom class as well? Can you try the same with the actual 
> `unique_ptr`?

The following code emits a warning for leaked memory:

  #include 
  
  class Lame {
int *ptr;
  public:
explicit Lame(int *ptr) : ptr(ptr) {}
~Lame() { delete ptr; }
  };
  
  void foo() {
int *ptr = new int(13);
auto smart = std::make_unique(ptr);
// No leak here
  }

It seems that there is a flaw in the way I was testing for warnings. 
Why does the following command not display the warnings? 
`./llvm/release/bin/clang -std=c++17 -Xclang -analyze -Xclang 
-analyzer-checker=core,cplusplus.Move,cplusplus.NewDelete,alpha.cplusplus.SmartPtr
 -Xclang -analyzer-output=text -Xclang -analyzer-config -Xclang 
cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true -c lame-class.cpp`


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D106739: [analyzer] Add option to SATest.py for extra checkers

2021-07-23 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

It turns out that there is already an option called `extra-analyzer-config` to 
pass analyzer configs, like setting `ModelSmartPtrDereference` to true


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D106739/new/

https://reviews.llvm.org/D106739

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D106739: [analyzer] Add option to SATest.py for extra checkers

2021-07-23 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD created this revision.
RedDocMD added reviewers: vsavchenko, NoQ, xazax.hun, teemperor.
Herald added subscribers: manas, steakhal, ASDenysPetrov, dkrupp, donat.nagy, 
Szelethus, mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware.
RedDocMD requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This patch adds the flag `extra-checkers` to the sub-command `build` for
passing a comma separated list of additional checkers to include.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D106739

Files:
  clang/utils/analyzer/SATest.py
  clang/utils/analyzer/SATestBuild.py


Index: clang/utils/analyzer/SATestBuild.py
===
--- clang/utils/analyzer/SATestBuild.py
+++ clang/utils/analyzer/SATestBuild.py
@@ -213,6 +213,7 @@
 project: ProjectInfo
 override_compiler: bool = False
 extra_analyzer_config: str = ""
+extra_checkers: str = ""
 is_reference_build: bool = False
 strictness: int = 0
 
@@ -233,13 +234,16 @@
 """
 A component aggregating all of the project testing.
 """
+
 def __init__(self, jobs: int, projects: List[ProjectInfo],
  override_compiler: bool, extra_analyzer_config: str,
+ extra_checkers: str,
  regenerate: bool, strictness: bool):
 self.jobs = jobs
 self.projects = projects
 self.override_compiler = override_compiler
 self.extra_analyzer_config = extra_analyzer_config
+self.extra_checkers = extra_checkers
 self.regenerate = regenerate
 self.strictness = strictness
 
@@ -252,6 +256,7 @@
 TestInfo(project,
  self.override_compiler,
  self.extra_analyzer_config,
+ self.extra_checkers,
  self.regenerate, self.strictness))
 if self.jobs <= 1:
 return self._single_threaded_test_all(projects_to_test)
@@ -305,10 +310,12 @@
 """
 A component aggregating testing for one project.
 """
+
 def __init__(self, test_info: TestInfo, silent: bool = False):
 self.project = test_info.project
 self.override_compiler = test_info.override_compiler
 self.extra_analyzer_config = test_info.extra_analyzer_config
+self.extra_checkers = test_info.extra_checkers
 self.is_reference_build = test_info.is_reference_build
 self.strictness = test_info.strictness
 self.silent = silent
@@ -414,6 +421,8 @@
 if 'SA_ADDITIONAL_CHECKERS' in os.environ:
 all_checkers = (all_checkers + ',' +
 os.environ['SA_ADDITIONAL_CHECKERS'])
+if self.extra_checkers != "":
+all_checkers += "," + self.extra_checkers
 
 # Run scan-build from within the patched source directory.
 cwd = os.path.join(directory, PATCHED_SOURCE_DIR_NAME)
Index: clang/utils/analyzer/SATest.py
===
--- clang/utils/analyzer/SATest.py
+++ clang/utils/analyzer/SATest.py
@@ -42,6 +42,7 @@
   projects,
   args.override_compiler,
   args.extra_analyzer_config,
+  args.extra_checkers,
   args.regenerate,
   args.strictness)
 tests_passed = tester.test_all()
@@ -250,6 +251,10 @@
   dest="extra_analyzer_config", type=str,
   default="",
   help="Arguments passed to to -analyzer-config")
+build_parser.add_argument("--extra-checkers",
+  dest="extra_checkers", type=str,
+  default="",
+  help="Extra checkers to enable")
 build_parser.add_argument("--projects", action="store", default="",
   help="Comma-separated list of projects to test")
 build_parser.add_argument("--max-size", action="store", default=None,


Index: clang/utils/analyzer/SATestBuild.py
===
--- clang/utils/analyzer/SATestBuild.py
+++ clang/utils/analyzer/SATestBuild.py
@@ -213,6 +213,7 @@
 project: ProjectInfo
 override_compiler: bool = False
 extra_analyzer_config: str = ""
+extra_checkers: str = ""
 is_reference_build: bool = False
 strictness: int = 0
 
@@ -233,13 +234,16 @@
 """
 A component aggregating all of the project testing.
 """
+
 def __init__(self, jobs: int, projects: List[ProjectInfo],
  override_compiler: bool, extra_analyzer_config: str,
+ extra_checkers: str,
  regenerate: bool, s

[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-07-22 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

> But before we go there we should decide whether we want to actually go for 
> inlining (or otherwise default-evaluating) these destructors. If we do, we 
> should probably not spend too much time on improving invalidation in the 
> checker, because default evaluation would do that properly for us anyway 
> (well, it doesn't really dodge any problems such as the absence of the 
> necessary AST so we'll probably have to solve all these problems anyway, just 
> in a different setting). So it's great that we've fixed `evalCall` for 
> destructors, this could definitely land as a separate patch (tested via 
> `debug.AnalysisOrder`), but we really need to think what to do next here. So 
> I recommend gathering some data to see if proper destructor evaluation is 
> actually a real problem.

`MallocChecker` doesn't seem to mind not evaluating destructors properly. With 
the current version of the patch, the following code doesn't emit any warnings:

  class SillyPtr {
int *ptr;
bool wasMalloced;
  public:
SillyPtr(int *ptr, bool wasMalloced = false) : 
ptr(ptr), 
wasMalloced(wasMalloced) {}
~SillyPtr() {
if (wasMalloced) free(ptr);
else delete ptr;
}
  };
  
  void foo() {
int *ptr = new int(13);
SillyPtr silly(ptr);
// No leak here!
  }

I am going to remove the debug dumps and run this patch on the projects in the 
`clang/utils/analyzer/projects` folder. If I don't find any false positives 
being caused due to this lack of modelling, then I think we can defer the 
proper handling of destructors (ie, finish up the invalidation) and move on to 
the other remaining problems (notes on get for an instance).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D106296: [analyzer] Fix for faulty namespace test in SmartPtrModelling

2021-07-21 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:291
   // we can try this function
-  if (Call.getNumArgs() == 2 &&
-  Call.getDecl()->getDeclContext()->isStdNamespace())
-if (smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
-smartptr::isStdSmartPtr(Call.getArgExpr(1)))
-  if (handleComparisionOp(Call, C))
-return true;
-
-  if (isStdOstreamOperatorCall(Call))
+  if (ModelSmartPtrDereference && isPotentiallyComparisionOpCall(Call))
+if (handleComparisionOp(Call, C))

xazax.hun wrote:
> RedDocMD wrote:
> > xazax.hun wrote:
> > > I'd prefer not repeating the `ModelSmartPtrDereference` check.
> > I don't think we can do that, since the `isBoolConversion()` check has a 
> > branch which is executed when `ModelSmartPtrDereference` is false.
> That function is way below. I was just thinking about merging the first two 
> check. 
Looks like I missed this. Sorry!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D106296/new/

https://reviews.llvm.org/D106296

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D106296: [analyzer] Fix for faulty namespace test in SmartPtrModelling

2021-07-21 Thread Deep Majumder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG80068ca6232b: [analyzer] Fix for faulty namespace test in 
SmartPtrModelling (authored by RedDocMD).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D106296/new/

https://reviews.llvm.org/D106296

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/test/Analysis/smart-ptr.cpp


Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -536,3 +536,10 @@
 }
 
 #endif
+
+// The following test isn't really a "smart-ptr" test
+// It came up during a bug fix (D106296)
+void testCheckForFunctionsWithNoDecl(void (*bar)(bool, bool)) {
+  // This should NOT crash.
+  bar(true, false);
+}
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -248,9 +248,12 @@
   return hasStdClassWithName(RD, BASIC_OSTREAM_NAMES);
 }
 
+static bool isStdFunctionCall(const CallEvent &Call) {
+  return Call.getDecl() && Call.getDecl()->getDeclContext()->isStdNamespace();
+}
+
 bool isStdOstreamOperatorCall(const CallEvent &Call) {
-  if (Call.getNumArgs() != 2 ||
-  !Call.getDecl()->getDeclContext()->isStdNamespace())
+  if (Call.getNumArgs() != 2 || !isStdFunctionCall(Call))
 return false;
   const auto *FC = dyn_cast(&Call);
   if (!FC)
@@ -265,6 +268,13 @@
  isStdBasicOstream(Call.getArgExpr(0));
 }
 
+static bool isPotentiallyComparisionOpCall(const CallEvent &Call) {
+  if (Call.getNumArgs() != 2 || !isStdFunctionCall(Call))
+return false;
+  return smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
+ smartptr::isStdSmartPtr(Call.getArgExpr(1));
+}
+
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
 
@@ -272,14 +282,11 @@
 
   // If any one of the arg is a unique_ptr, then
   // we can try this function
-  if (Call.getNumArgs() == 2 &&
-  Call.getDecl()->getDeclContext()->isStdNamespace())
-if (smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
-smartptr::isStdSmartPtr(Call.getArgExpr(1)))
-  if (handleComparisionOp(Call, C))
-return true;
-
-  if (isStdOstreamOperatorCall(Call))
+  if (ModelSmartPtrDereference && isPotentiallyComparisionOpCall(Call))
+if (handleComparisionOp(Call, C))
+  return true;
+
+  if (ModelSmartPtrDereference && isStdOstreamOperatorCall(Call))
 return handleOstreamOperator(Call, C);
 
   if (Call.isCalled(StdSwapCall)) {


Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -536,3 +536,10 @@
 }
 
 #endif
+
+// The following test isn't really a "smart-ptr" test
+// It came up during a bug fix (D106296)
+void testCheckForFunctionsWithNoDecl(void (*bar)(bool, bool)) {
+  // This should NOT crash.
+  bar(true, false);
+}
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -248,9 +248,12 @@
   return hasStdClassWithName(RD, BASIC_OSTREAM_NAMES);
 }
 
+static bool isStdFunctionCall(const CallEvent &Call) {
+  return Call.getDecl() && Call.getDecl()->getDeclContext()->isStdNamespace();
+}
+
 bool isStdOstreamOperatorCall(const CallEvent &Call) {
-  if (Call.getNumArgs() != 2 ||
-  !Call.getDecl()->getDeclContext()->isStdNamespace())
+  if (Call.getNumArgs() != 2 || !isStdFunctionCall(Call))
 return false;
   const auto *FC = dyn_cast(&Call);
   if (!FC)
@@ -265,6 +268,13 @@
  isStdBasicOstream(Call.getArgExpr(0));
 }
 
+static bool isPotentiallyComparisionOpCall(const CallEvent &Call) {
+  if (Call.getNumArgs() != 2 || !isStdFunctionCall(Call))
+return false;
+  return smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
+ smartptr::isStdSmartPtr(Call.getArgExpr(1));
+}
+
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
 
@@ -272,14 +282,11 @@
 
   // If any one of the arg is a unique_ptr, then
   // we can try this function
-  if (Call.getNumArgs() == 2 &&
-  Call.getDecl()->getDeclContext()->isStdNamespace())
-if (smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
-smartptr::isStdSmartPtr(Call.getArgExpr(1)))
-  if (handleComparisionOp(Call, C))
-return true;
-
-  if (isStdOstreamOperatorCall(Call))
+  if (ModelSmartPtrDereference && isPotentiallyComparisionOpCall(Call))
+if (handleComparisionOp(Call, C))
+ 

[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-07-20 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

This is a minimal model of destructors in smart-ptr.
Other than the need to probably model the destructor of the pointee, is there 
anything else to do?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-07-20 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 360218.
RedDocMD added a comment.

Minimal modelling of destructor


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp


Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -753,10 +753,13 @@
 *Call, *this);
 
   ExplodedNodeSet DstInvalidated;
-  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-   I != E; ++I)
-defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+  // for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E =
+  // DstPreCall.end();
+  //  I != E; ++I)
+  //   defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, *Call,
+ *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
  *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,11 @@
 for (const auto &EvalCallChecker : EvalCallCheckers) {
   // TODO: Support the situation when the call doesn't correspond
   // to any Expr.
-  ProgramPoint L = ProgramPoint::getProgramPoint(
-  Call.getOriginExpr(), ProgramPoint::PostStmtKind,
-  Pred->getLocationContext(), EvalCallChecker.Checker);
   bool evaluated = false;
   { // CheckerContext generates transitions(populates checkDest) on
 // destruction, so introduce the scope to make sure it gets properly
 // populated.
-CheckerContext C(B, Eng, Pred, L);
+CheckerContext C(B, Eng, Pred, Call.getProgramPoint());
 evaluated = EvalCallChecker(Call, C);
   }
   assert(!(evaluated && anyEvaluated)
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -269,6 +269,7 @@
 CheckerContext &C) const {
 
   ProgramStateRef State = C.getState();
+  Call.dump();
 
   // If any one of the arg is a unique_ptr, then
   // we can try this function
@@ -365,6 +366,18 @@
 }
   }
 
+  if (const auto *DC = dyn_cast(&Call)) {
+llvm::errs() << "Found destructor call\n";
+const MemRegion *ThisRegion = DC->getCXXThisVal().getAsRegion();
+assert(ThisRegion && "We do not support explicit calls to destructor");
+const auto *InnerPtrVal = State->get(ThisRegion);
+State = State->remove(ThisRegion);
+State = State->invalidateRegions({*InnerPtrVal}, nullptr, C.blockCount(),
+ C.getLocationContext(), true);
+C.addTransition(State);
+return true;
+  }
+
   if (!ModelSmartPtrDereference)
 return false;
 


Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -753,10 +753,13 @@
 *Call, *this);
 
   ExplodedNodeSet DstInvalidated;
-  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-   I != E; ++I)
-defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+  // for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E =
+  // DstPreCall.end();
+  //  I != E; ++I)
+  //   defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, *Call,
+ *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
  *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,11 @@
 for (const auto &EvalCallChecker : EvalCallCheckers) {
   // TODO: Support the s

[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-07-20 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 360202.
RedDocMD added a comment.

Reformat


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp


Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -753,10 +753,13 @@
 *Call, *this);
 
   ExplodedNodeSet DstInvalidated;
-  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-   I != E; ++I)
-defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+  // for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E =
+  // DstPreCall.end();
+  //  I != E; ++I)
+  //   defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, *Call,
+ *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
  *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,11 @@
 for (const auto &EvalCallChecker : EvalCallCheckers) {
   // TODO: Support the situation when the call doesn't correspond
   // to any Expr.
-  ProgramPoint L = ProgramPoint::getProgramPoint(
-  Call.getOriginExpr(), ProgramPoint::PostStmtKind,
-  Pred->getLocationContext(), EvalCallChecker.Checker);
   bool evaluated = false;
   { // CheckerContext generates transitions(populates checkDest) on
 // destruction, so introduce the scope to make sure it gets properly
 // populated.
-CheckerContext C(B, Eng, Pred, L);
+CheckerContext C(B, Eng, Pred, Call.getProgramPoint());
 evaluated = EvalCallChecker(Call, C);
   }
   assert(!(evaluated && anyEvaluated)
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -269,6 +269,7 @@
 CheckerContext &C) const {
 
   ProgramStateRef State = C.getState();
+  Call.dump();
 
   // If any one of the arg is a unique_ptr, then
   // we can try this function
@@ -365,6 +366,11 @@
 }
   }
 
+  if (const auto *DC = dyn_cast(&Call)) {
+llvm::errs() << "Found destructor call\n";
+return true;
+  }
+
   if (!ModelSmartPtrDereference)
 return false;
 


Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -753,10 +753,13 @@
 *Call, *this);
 
   ExplodedNodeSet DstInvalidated;
-  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-   I != E; ++I)
-defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+  // for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E =
+  // DstPreCall.end();
+  //  I != E; ++I)
+  //   defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, *Call,
+ *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
  *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,11 @@
 for (const auto &EvalCallChecker : EvalCallCheckers) {
   // TODO: Support the situation when the call doesn't correspond
   // to any Expr.
-  ProgramPoint L = ProgramPoint::getProgramPoint(
-  Call.getOriginExpr(), ProgramPoint::PostStmtKind,
-  Pred->getLocationContext(), EvalCallChecker.Checker);
   bool evaluated = false;
   { // CheckerContext generates transitions(populates checkDest) on
 // destruction, so introduce the scope to make sure it gets properly
 // po

[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-07-20 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 360199.
RedDocMD added a comment.

Retrieving patch


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp


Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -753,10 +753,11 @@
 *Call, *this);
 
   ExplodedNodeSet DstInvalidated;
-  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-   I != E; ++I)
-defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+  // for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = 
DstPreCall.end();
+  //  I != E; ++I)
+  //   defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, 
*Call, *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
  *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,11 @@
 for (const auto &EvalCallChecker : EvalCallCheckers) {
   // TODO: Support the situation when the call doesn't correspond
   // to any Expr.
-  ProgramPoint L = ProgramPoint::getProgramPoint(
-  Call.getOriginExpr(), ProgramPoint::PostStmtKind,
-  Pred->getLocationContext(), EvalCallChecker.Checker);
   bool evaluated = false;
   { // CheckerContext generates transitions(populates checkDest) on
 // destruction, so introduce the scope to make sure it gets properly
 // populated.
-CheckerContext C(B, Eng, Pred, L);
+CheckerContext C(B, Eng, Pred, Call.getProgramPoint());
 evaluated = EvalCallChecker(Call, C);
   }
   assert(!(evaluated && anyEvaluated)
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -269,6 +269,7 @@
 CheckerContext &C) const {
 
   ProgramStateRef State = C.getState();
+  Call.dump();
 
   // If any one of the arg is a unique_ptr, then
   // we can try this function
@@ -335,6 +336,11 @@
 return true;
   }
 
+  if (const auto *DC = dyn_cast(&Call)) {
+llvm::errs() << "Found destructor call\n";
+return true;
+  }
+
   if (!smartptr::isStdSmartPtrCall(Call))
 return false;
 


Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -753,10 +753,11 @@
 *Call, *this);
 
   ExplodedNodeSet DstInvalidated;
-  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-   I != E; ++I)
-defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+  // for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
+  //  I != E; ++I)
+  //   defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, *Call, *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
  *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,11 @@
 for (const auto &EvalCallChecker : EvalCallCheckers) {
   // TODO: Support the situation when the call doesn't correspond
   // to any Expr.
-  ProgramPoint L = ProgramPoint::getProgramPoint(
-  Call.getOriginExpr(), ProgramPoint::PostStmtKind,
-  Pred->getLocationContext(), EvalCallChecker.Checker);
   bool evaluated = false;
   { // CheckerContext generates transitions(populates checkDest) on
 // destruction, so introduce the scope to make sure it gets properly
 // populated.
-CheckerContext C(B, Eng, Pred, L);
+CheckerConte

[PATCH] D106296: [analyzer] Fix for faulty namespace test in SmartPtrModelling

2021-07-20 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 360064.
RedDocMD added a comment.

Removed unnecessary white space


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D106296/new/

https://reviews.llvm.org/D106296

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/test/Analysis/smart-ptr.cpp


Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -536,3 +536,10 @@
 }
 
 #endif
+
+// The following test isn't really a "smart-ptr" test
+// It came up during a bug fix (D106296)
+void testCheckForFunctionsWithNoDecl(void (*bar)(bool, bool)) {
+  // This should NOT crash.
+  bar(true, false);
+}
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -248,9 +248,12 @@
   return hasStdClassWithName(RD, BASIC_OSTREAM_NAMES);
 }
 
+static bool isStdFunctionCall(const CallEvent &Call) {
+  return Call.getDecl() && Call.getDecl()->getDeclContext()->isStdNamespace();
+}
+
 bool isStdOstreamOperatorCall(const CallEvent &Call) {
-  if (Call.getNumArgs() != 2 ||
-  !Call.getDecl()->getDeclContext()->isStdNamespace())
+  if (Call.getNumArgs() != 2 || !isStdFunctionCall(Call))
 return false;
   const auto *FC = dyn_cast(&Call);
   if (!FC)
@@ -265,6 +268,13 @@
  isStdBasicOstream(Call.getArgExpr(0));
 }
 
+static bool isPotentiallyComparisionOpCall(const CallEvent &Call) {
+  if (Call.getNumArgs() != 2 || !isStdFunctionCall(Call))
+return false;
+  return smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
+ smartptr::isStdSmartPtr(Call.getArgExpr(1));
+}
+
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
 
@@ -272,14 +282,11 @@
 
   // If any one of the arg is a unique_ptr, then
   // we can try this function
-  if (Call.getNumArgs() == 2 &&
-  Call.getDecl()->getDeclContext()->isStdNamespace())
-if (smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
-smartptr::isStdSmartPtr(Call.getArgExpr(1)))
-  if (handleComparisionOp(Call, C))
-return true;
-
-  if (isStdOstreamOperatorCall(Call))
+  if (ModelSmartPtrDereference && isPotentiallyComparisionOpCall(Call))
+if (handleComparisionOp(Call, C))
+  return true;
+
+  if (ModelSmartPtrDereference && isStdOstreamOperatorCall(Call))
 return handleOstreamOperator(Call, C);
 
   if (Call.isCalled(StdSwapCall)) {


Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -536,3 +536,10 @@
 }
 
 #endif
+
+// The following test isn't really a "smart-ptr" test
+// It came up during a bug fix (D106296)
+void testCheckForFunctionsWithNoDecl(void (*bar)(bool, bool)) {
+  // This should NOT crash.
+  bar(true, false);
+}
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -248,9 +248,12 @@
   return hasStdClassWithName(RD, BASIC_OSTREAM_NAMES);
 }
 
+static bool isStdFunctionCall(const CallEvent &Call) {
+  return Call.getDecl() && Call.getDecl()->getDeclContext()->isStdNamespace();
+}
+
 bool isStdOstreamOperatorCall(const CallEvent &Call) {
-  if (Call.getNumArgs() != 2 ||
-  !Call.getDecl()->getDeclContext()->isStdNamespace())
+  if (Call.getNumArgs() != 2 || !isStdFunctionCall(Call))
 return false;
   const auto *FC = dyn_cast(&Call);
   if (!FC)
@@ -265,6 +268,13 @@
  isStdBasicOstream(Call.getArgExpr(0));
 }
 
+static bool isPotentiallyComparisionOpCall(const CallEvent &Call) {
+  if (Call.getNumArgs() != 2 || !isStdFunctionCall(Call))
+return false;
+  return smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
+ smartptr::isStdSmartPtr(Call.getArgExpr(1));
+}
+
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
 
@@ -272,14 +282,11 @@
 
   // If any one of the arg is a unique_ptr, then
   // we can try this function
-  if (Call.getNumArgs() == 2 &&
-  Call.getDecl()->getDeclContext()->isStdNamespace())
-if (smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
-smartptr::isStdSmartPtr(Call.getArgExpr(1)))
-  if (handleComparisionOp(Call, C))
-return true;
-
-  if (isStdOstreamOperatorCall(Call))
+  if (ModelSmartPtrDereference && isPotentiallyComparisionOpCall(Call))
+if (handleComparisionOp(Call, C))
+  return true;
+
+  if (ModelSmartPtrDereference && isStdOstreamOperatorCall(Call))
 return handleOstreamOperator(Call, C);
 
   if (Call.is

[PATCH] D106296: [analyzer] Fix for faulty namespace test in SmartPtrModelling

2021-07-20 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:252
+static bool isStdFunctionCall(const CallEvent &Call) {
+  return Call.getDecl() && Call.getDecl() ->getDeclContext()->isStdNamespace();
+}

vsavchenko wrote:
> nit: there's an extra space here.
Wow, I didn't know this is even valid syntax 😂


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D106296/new/

https://reviews.llvm.org/D106296

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D106296: [analyzer] Fix for faulty namespace test in SmartPtrModelling

2021-07-20 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:252-255
+  const auto *Decl = Call.getDecl();
+  if (!Decl)
+return false;
+  return Decl->getDeclContext()->isStdNamespace();

vsavchenko wrote:
> Can we use a one-liner that I suggested?
Sure


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D106296/new/

https://reviews.llvm.org/D106296

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D106296: [analyzer] Fix for faulty namespace test in SmartPtrModelling

2021-07-20 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 360061.
RedDocMD added a comment.

More refactor


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D106296/new/

https://reviews.llvm.org/D106296

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/test/Analysis/smart-ptr.cpp


Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -536,3 +536,10 @@
 }
 
 #endif
+
+// The following test isn't really a "smart-ptr" test
+// It came up during a bug fix (D106296)
+void testCheckForFunctionsWithNoDecl(void (*bar)(bool, bool)) {
+  // This should NOT crash.
+  bar(true, false);
+}
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -248,9 +248,12 @@
   return hasStdClassWithName(RD, BASIC_OSTREAM_NAMES);
 }
 
+static bool isStdFunctionCall(const CallEvent &Call) {
+  return Call.getDecl() && Call.getDecl() ->getDeclContext()->isStdNamespace();
+}
+
 bool isStdOstreamOperatorCall(const CallEvent &Call) {
-  if (Call.getNumArgs() != 2 ||
-  !Call.getDecl()->getDeclContext()->isStdNamespace())
+  if (Call.getNumArgs() != 2 || !isStdFunctionCall(Call))
 return false;
   const auto *FC = dyn_cast(&Call);
   if (!FC)
@@ -265,6 +268,13 @@
  isStdBasicOstream(Call.getArgExpr(0));
 }
 
+static bool isPotentiallyComparisionOpCall(const CallEvent &Call) {
+  if (Call.getNumArgs() != 2 || !isStdFunctionCall(Call))
+return false;
+  return smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
+ smartptr::isStdSmartPtr(Call.getArgExpr(1));
+}
+
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
 
@@ -272,14 +282,11 @@
 
   // If any one of the arg is a unique_ptr, then
   // we can try this function
-  if (Call.getNumArgs() == 2 &&
-  Call.getDecl()->getDeclContext()->isStdNamespace())
-if (smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
-smartptr::isStdSmartPtr(Call.getArgExpr(1)))
-  if (handleComparisionOp(Call, C))
-return true;
-
-  if (isStdOstreamOperatorCall(Call))
+  if (ModelSmartPtrDereference && isPotentiallyComparisionOpCall(Call))
+if (handleComparisionOp(Call, C))
+  return true;
+
+  if (ModelSmartPtrDereference && isStdOstreamOperatorCall(Call))
 return handleOstreamOperator(Call, C);
 
   if (Call.isCalled(StdSwapCall)) {


Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -536,3 +536,10 @@
 }
 
 #endif
+
+// The following test isn't really a "smart-ptr" test
+// It came up during a bug fix (D106296)
+void testCheckForFunctionsWithNoDecl(void (*bar)(bool, bool)) {
+  // This should NOT crash.
+  bar(true, false);
+}
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -248,9 +248,12 @@
   return hasStdClassWithName(RD, BASIC_OSTREAM_NAMES);
 }
 
+static bool isStdFunctionCall(const CallEvent &Call) {
+  return Call.getDecl() && Call.getDecl() ->getDeclContext()->isStdNamespace();
+}
+
 bool isStdOstreamOperatorCall(const CallEvent &Call) {
-  if (Call.getNumArgs() != 2 ||
-  !Call.getDecl()->getDeclContext()->isStdNamespace())
+  if (Call.getNumArgs() != 2 || !isStdFunctionCall(Call))
 return false;
   const auto *FC = dyn_cast(&Call);
   if (!FC)
@@ -265,6 +268,13 @@
  isStdBasicOstream(Call.getArgExpr(0));
 }
 
+static bool isPotentiallyComparisionOpCall(const CallEvent &Call) {
+  if (Call.getNumArgs() != 2 || !isStdFunctionCall(Call))
+return false;
+  return smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
+ smartptr::isStdSmartPtr(Call.getArgExpr(1));
+}
+
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
 
@@ -272,14 +282,11 @@
 
   // If any one of the arg is a unique_ptr, then
   // we can try this function
-  if (Call.getNumArgs() == 2 &&
-  Call.getDecl()->getDeclContext()->isStdNamespace())
-if (smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
-smartptr::isStdSmartPtr(Call.getArgExpr(1)))
-  if (handleComparisionOp(Call, C))
-return true;
-
-  if (isStdOstreamOperatorCall(Call))
+  if (ModelSmartPtrDereference && isPotentiallyComparisionOpCall(Call))
+if (handleComparisionOp(Call, C))
+  return true;
+
+  if (ModelSmartPtrDereference && isStdOstreamOperatorCall(Call))
 return handleOstreamOperator(Call, C);
 
   if (Call.isCalled(StdSwapCa

[PATCH] D106296: [analyzer] Fix for faulty namespace test in SmartPtrModelling

2021-07-20 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 360051.
RedDocMD added a comment.

Refactored out check


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D106296/new/

https://reviews.llvm.org/D106296

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/test/Analysis/smart-ptr.cpp


Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -536,3 +536,10 @@
 }
 
 #endif
+
+// The following test isn't really a "smart-ptr" test
+// It came up during a bug fix (D106296)
+void testCheckForFunctionsWithNoDecl(void (*bar)(bool, bool)) {
+  // This should NOT crash.
+  bar(true, false);
+}
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -248,9 +248,15 @@
   return hasStdClassWithName(RD, BASIC_OSTREAM_NAMES);
 }
 
+static bool isStdFunctionCall(const CallEvent &Call) {
+  const auto *Decl = Call.getDecl();
+  if (!Decl)
+return false;
+  return Decl->getDeclContext()->isStdNamespace();
+}
+
 bool isStdOstreamOperatorCall(const CallEvent &Call) {
-  if (Call.getNumArgs() != 2 ||
-  !Call.getDecl()->getDeclContext()->isStdNamespace())
+  if (Call.getNumArgs() != 2 || !isStdFunctionCall(Call))
 return false;
   const auto *FC = dyn_cast(&Call);
   if (!FC)
@@ -265,6 +271,13 @@
  isStdBasicOstream(Call.getArgExpr(0));
 }
 
+static bool isPotentiallyComparisionOpCall(const CallEvent &Call) {
+  if (Call.getNumArgs() != 2 || !isStdFunctionCall(Call))
+return false;
+  return smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
+ smartptr::isStdSmartPtr(Call.getArgExpr(1));
+}
+
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
 
@@ -272,14 +285,11 @@
 
   // If any one of the arg is a unique_ptr, then
   // we can try this function
-  if (Call.getNumArgs() == 2 &&
-  Call.getDecl()->getDeclContext()->isStdNamespace())
-if (smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
-smartptr::isStdSmartPtr(Call.getArgExpr(1)))
-  if (handleComparisionOp(Call, C))
-return true;
-
-  if (isStdOstreamOperatorCall(Call))
+  if (ModelSmartPtrDereference && isPotentiallyComparisionOpCall(Call))
+if (handleComparisionOp(Call, C))
+  return true;
+
+  if (ModelSmartPtrDereference && isStdOstreamOperatorCall(Call))
 return handleOstreamOperator(Call, C);
 
   if (Call.isCalled(StdSwapCall)) {


Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -536,3 +536,10 @@
 }
 
 #endif
+
+// The following test isn't really a "smart-ptr" test
+// It came up during a bug fix (D106296)
+void testCheckForFunctionsWithNoDecl(void (*bar)(bool, bool)) {
+  // This should NOT crash.
+  bar(true, false);
+}
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -248,9 +248,15 @@
   return hasStdClassWithName(RD, BASIC_OSTREAM_NAMES);
 }
 
+static bool isStdFunctionCall(const CallEvent &Call) {
+  const auto *Decl = Call.getDecl();
+  if (!Decl)
+return false;
+  return Decl->getDeclContext()->isStdNamespace();
+}
+
 bool isStdOstreamOperatorCall(const CallEvent &Call) {
-  if (Call.getNumArgs() != 2 ||
-  !Call.getDecl()->getDeclContext()->isStdNamespace())
+  if (Call.getNumArgs() != 2 || !isStdFunctionCall(Call))
 return false;
   const auto *FC = dyn_cast(&Call);
   if (!FC)
@@ -265,6 +271,13 @@
  isStdBasicOstream(Call.getArgExpr(0));
 }
 
+static bool isPotentiallyComparisionOpCall(const CallEvent &Call) {
+  if (Call.getNumArgs() != 2 || !isStdFunctionCall(Call))
+return false;
+  return smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
+ smartptr::isStdSmartPtr(Call.getArgExpr(1));
+}
+
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
 
@@ -272,14 +285,11 @@
 
   // If any one of the arg is a unique_ptr, then
   // we can try this function
-  if (Call.getNumArgs() == 2 &&
-  Call.getDecl()->getDeclContext()->isStdNamespace())
-if (smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
-smartptr::isStdSmartPtr(Call.getArgExpr(1)))
-  if (handleComparisionOp(Call, C))
-return true;
-
-  if (isStdOstreamOperatorCall(Call))
+  if (ModelSmartPtrDereference && isPotentiallyComparisionOpCall(Call))
+if (handleComparisionOp(Call, C))
+  return true;
+
+  if (ModelSmartPtrDereference && isStdOstreamOpera

[PATCH] D106296: [analyzer] Fix for faulty namespace test in SmartPtrModelling

2021-07-19 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

Would this test do?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D106296/new/

https://reviews.llvm.org/D106296

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D106296: [analyzer] Fix for faulty namespace test in SmartPtrModelling

2021-07-19 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 360027.
RedDocMD added a comment.

Added a simple test


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D106296/new/

https://reviews.llvm.org/D106296

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/test/Analysis/smart-ptr.cpp


Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -536,3 +536,10 @@
 }
 
 #endif
+
+// The following test isn't really a "smart-ptr" test
+// It came up during a bug fix (D106296)
+void testCheckForFunctionsWithNoDecl(void (*bar)(bool, bool)) {
+  // This should NOT crash.
+  bar(true, false);
+}
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -249,8 +249,12 @@
 }
 
 bool isStdOstreamOperatorCall(const CallEvent &Call) {
-  if (Call.getNumArgs() != 2 ||
-  !Call.getDecl()->getDeclContext()->isStdNamespace())
+  if (Call.getNumArgs() != 2)
+return false;
+  const auto *Decl = Call.getDecl();
+  if (!Decl)
+return false;
+  if (!Decl->getDeclContext()->isStdNamespace())
 return false;
   const auto *FC = dyn_cast(&Call);
   if (!FC)
@@ -265,6 +269,18 @@
  isStdBasicOstream(Call.getArgExpr(0));
 }
 
+static bool isPotentiallyComparisionOpCall(const CallEvent &Call) {
+  if (Call.getNumArgs() != 2)
+return false;
+  const auto *Decl = Call.getDecl();
+  if (!Decl)
+return false;
+  if (!Decl->getDeclContext()->isStdNamespace())
+return false;
+  return smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
+ smartptr::isStdSmartPtr(Call.getArgExpr(1));
+}
+
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
 
@@ -272,14 +288,11 @@
 
   // If any one of the arg is a unique_ptr, then
   // we can try this function
-  if (Call.getNumArgs() == 2 &&
-  Call.getDecl()->getDeclContext()->isStdNamespace())
-if (smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
-smartptr::isStdSmartPtr(Call.getArgExpr(1)))
-  if (handleComparisionOp(Call, C))
-return true;
-
-  if (isStdOstreamOperatorCall(Call))
+  if (ModelSmartPtrDereference && isPotentiallyComparisionOpCall(Call))
+if (handleComparisionOp(Call, C))
+  return true;
+
+  if (ModelSmartPtrDereference && isStdOstreamOperatorCall(Call))
 return handleOstreamOperator(Call, C);
 
   if (Call.isCalled(StdSwapCall)) {


Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -536,3 +536,10 @@
 }
 
 #endif
+
+// The following test isn't really a "smart-ptr" test
+// It came up during a bug fix (D106296)
+void testCheckForFunctionsWithNoDecl(void (*bar)(bool, bool)) {
+  // This should NOT crash.
+  bar(true, false);
+}
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -249,8 +249,12 @@
 }
 
 bool isStdOstreamOperatorCall(const CallEvent &Call) {
-  if (Call.getNumArgs() != 2 ||
-  !Call.getDecl()->getDeclContext()->isStdNamespace())
+  if (Call.getNumArgs() != 2)
+return false;
+  const auto *Decl = Call.getDecl();
+  if (!Decl)
+return false;
+  if (!Decl->getDeclContext()->isStdNamespace())
 return false;
   const auto *FC = dyn_cast(&Call);
   if (!FC)
@@ -265,6 +269,18 @@
  isStdBasicOstream(Call.getArgExpr(0));
 }
 
+static bool isPotentiallyComparisionOpCall(const CallEvent &Call) {
+  if (Call.getNumArgs() != 2)
+return false;
+  const auto *Decl = Call.getDecl();
+  if (!Decl)
+return false;
+  if (!Decl->getDeclContext()->isStdNamespace())
+return false;
+  return smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
+ smartptr::isStdSmartPtr(Call.getArgExpr(1));
+}
+
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
 
@@ -272,14 +288,11 @@
 
   // If any one of the arg is a unique_ptr, then
   // we can try this function
-  if (Call.getNumArgs() == 2 &&
-  Call.getDecl()->getDeclContext()->isStdNamespace())
-if (smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
-smartptr::isStdSmartPtr(Call.getArgExpr(1)))
-  if (handleComparisionOp(Call, C))
-return true;
-
-  if (isStdOstreamOperatorCall(Call))
+  if (ModelSmartPtrDereference && isPotentiallyComparisionOpCall(Call))
+if (handleComparisionOp(Call, C))
+  return true;
+
+  if (ModelSmartPtrDereference && isStdOstreamOperatorCall(Call))
 return handle

[PATCH] D106296: [analyzer] Fix for faulty namespace test in SmartPtrModelling

2021-07-19 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:275
+return false;
+  const auto *Decl = Call.getDecl();
+  if (!Decl)

xazax.hun wrote:
> Can we model a function call without a declaration? I wonder if we should 
> make this check more eagerly in `evalCall`. 
I think it is not that there is no Decl, but it is more likely the Decl is not 
available at that time.
```
void foo(void (*bar)(bool, bool)) {
bar();
}
```
If just foo is analyzed, then there is no Decl.
If a call to foo is analyzed, then there is a Decl.
That said, I think the check can be done in `evalCall` itself. I don't think it 
will cause a problem.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:291
   // we can try this function
-  if (Call.getNumArgs() == 2 &&
-  Call.getDecl()->getDeclContext()->isStdNamespace())
-if (smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
-smartptr::isStdSmartPtr(Call.getArgExpr(1)))
-  if (handleComparisionOp(Call, C))
-return true;
-
-  if (isStdOstreamOperatorCall(Call))
+  if (ModelSmartPtrDereference && isPotentiallyComparisionOpCall(Call))
+if (handleComparisionOp(Call, C))

xazax.hun wrote:
> I'd prefer not repeating the `ModelSmartPtrDereference` check.
I don't think we can do that, since the `isBoolConversion()` check has a branch 
which is executed when `ModelSmartPtrDereference` is false.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D106296/new/

https://reviews.llvm.org/D106296

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D106296: [analyer] Fix for faulty namespace test in SmartPtrModelling

2021-07-19 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 359865.
RedDocMD added a comment.

Reformatted patch


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D106296/new/

https://reviews.llvm.org/D106296

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp


Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -249,8 +249,12 @@
 }
 
 bool isStdOstreamOperatorCall(const CallEvent &Call) {
-  if (Call.getNumArgs() != 2 ||
-  !Call.getDecl()->getDeclContext()->isStdNamespace())
+  if (Call.getNumArgs() != 2)
+return false;
+  const auto *Decl = Call.getDecl();
+  if (!Decl)
+return false;
+  if (!Decl->getDeclContext()->isStdNamespace())
 return false;
   const auto *FC = dyn_cast(&Call);
   if (!FC)
@@ -265,6 +269,18 @@
  isStdBasicOstream(Call.getArgExpr(0));
 }
 
+static bool isPotentiallyComparisionOpCall(const CallEvent &Call) {
+  if (Call.getNumArgs() != 2)
+return false;
+  const auto *Decl = Call.getDecl();
+  if (!Decl)
+return false;
+  if (!Decl->getDeclContext()->isStdNamespace())
+return false;
+  return smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
+ smartptr::isStdSmartPtr(Call.getArgExpr(1));
+}
+
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
 
@@ -272,14 +288,11 @@
 
   // If any one of the arg is a unique_ptr, then
   // we can try this function
-  if (Call.getNumArgs() == 2 &&
-  Call.getDecl()->getDeclContext()->isStdNamespace())
-if (smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
-smartptr::isStdSmartPtr(Call.getArgExpr(1)))
-  if (handleComparisionOp(Call, C))
-return true;
-
-  if (isStdOstreamOperatorCall(Call))
+  if (ModelSmartPtrDereference && isPotentiallyComparisionOpCall(Call))
+if (handleComparisionOp(Call, C))
+  return true;
+
+  if (ModelSmartPtrDereference && isStdOstreamOperatorCall(Call))
 return handleOstreamOperator(Call, C);
 
   if (Call.isCalled(StdSwapCall)) {


Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -249,8 +249,12 @@
 }
 
 bool isStdOstreamOperatorCall(const CallEvent &Call) {
-  if (Call.getNumArgs() != 2 ||
-  !Call.getDecl()->getDeclContext()->isStdNamespace())
+  if (Call.getNumArgs() != 2)
+return false;
+  const auto *Decl = Call.getDecl();
+  if (!Decl)
+return false;
+  if (!Decl->getDeclContext()->isStdNamespace())
 return false;
   const auto *FC = dyn_cast(&Call);
   if (!FC)
@@ -265,6 +269,18 @@
  isStdBasicOstream(Call.getArgExpr(0));
 }
 
+static bool isPotentiallyComparisionOpCall(const CallEvent &Call) {
+  if (Call.getNumArgs() != 2)
+return false;
+  const auto *Decl = Call.getDecl();
+  if (!Decl)
+return false;
+  if (!Decl->getDeclContext()->isStdNamespace())
+return false;
+  return smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
+ smartptr::isStdSmartPtr(Call.getArgExpr(1));
+}
+
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
 
@@ -272,14 +288,11 @@
 
   // If any one of the arg is a unique_ptr, then
   // we can try this function
-  if (Call.getNumArgs() == 2 &&
-  Call.getDecl()->getDeclContext()->isStdNamespace())
-if (smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
-smartptr::isStdSmartPtr(Call.getArgExpr(1)))
-  if (handleComparisionOp(Call, C))
-return true;
-
-  if (isStdOstreamOperatorCall(Call))
+  if (ModelSmartPtrDereference && isPotentiallyComparisionOpCall(Call))
+if (handleComparisionOp(Call, C))
+  return true;
+
+  if (ModelSmartPtrDereference && isStdOstreamOperatorCall(Call))
 return handleOstreamOperator(Call, C);
 
   if (Call.isCalled(StdSwapCall)) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D106296: [analyer] Fix for faulty namespace test in SmartPtrModelling

2021-07-19 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD created this revision.
RedDocMD added reviewers: NoQ, vsavchenko, xazax.hun, teemperor.
Herald added subscribers: martong, rnkovacs.
RedDocMD requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This patch:

- Fixes how the std-namespace test is written in SmartPtrModelling

(now accounts for functions with no Decl available)

- Adds the smart pointer checker flag check where it was missing


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D106296

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp


Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -249,8 +249,12 @@
 }
 
 bool isStdOstreamOperatorCall(const CallEvent &Call) {
-  if (Call.getNumArgs() != 2 ||
-  !Call.getDecl()->getDeclContext()->isStdNamespace())
+  if (Call.getNumArgs() != 2)
+return false;
+  const auto *Decl = Call.getDecl();
+  if (!Decl)
+return false;
+  if (!Decl->getDeclContext()->isStdNamespace())
 return false;
   const auto *FC = dyn_cast(&Call);
   if (!FC)
@@ -265,6 +269,17 @@
  isStdBasicOstream(Call.getArgExpr(0));
 }
 
+static bool isPotentiallyComparisionOpCall(const CallEvent &Call) {
+  if (Call.getNumArgs() != 2)
+return false;
+  const auto *Decl = Call.getDecl();
+  if (!Decl)
+return false;
+  if (!Decl->getDeclContext()->isStdNamespace())
+return false;
+  return smartptr::isStdSmartPtr(Call.getArgExpr(0)) || 
smartptr::isStdSmartPtr(Call.getArgExpr(1));
+}
+
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
 
@@ -272,14 +287,11 @@
 
   // If any one of the arg is a unique_ptr, then
   // we can try this function
-  if (Call.getNumArgs() == 2 &&
-  Call.getDecl()->getDeclContext()->isStdNamespace())
-if (smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
-smartptr::isStdSmartPtr(Call.getArgExpr(1)))
-  if (handleComparisionOp(Call, C))
-return true;
-
-  if (isStdOstreamOperatorCall(Call))
+  if (ModelSmartPtrDereference && isPotentiallyComparisionOpCall(Call))
+if (handleComparisionOp(Call, C))
+  return true;
+
+  if (ModelSmartPtrDereference && isStdOstreamOperatorCall(Call))
 return handleOstreamOperator(Call, C);
 
   if (Call.isCalled(StdSwapCall)) {


Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -249,8 +249,12 @@
 }
 
 bool isStdOstreamOperatorCall(const CallEvent &Call) {
-  if (Call.getNumArgs() != 2 ||
-  !Call.getDecl()->getDeclContext()->isStdNamespace())
+  if (Call.getNumArgs() != 2)
+return false;
+  const auto *Decl = Call.getDecl();
+  if (!Decl)
+return false;
+  if (!Decl->getDeclContext()->isStdNamespace())
 return false;
   const auto *FC = dyn_cast(&Call);
   if (!FC)
@@ -265,6 +269,17 @@
  isStdBasicOstream(Call.getArgExpr(0));
 }
 
+static bool isPotentiallyComparisionOpCall(const CallEvent &Call) {
+  if (Call.getNumArgs() != 2)
+return false;
+  const auto *Decl = Call.getDecl();
+  if (!Decl)
+return false;
+  if (!Decl->getDeclContext()->isStdNamespace())
+return false;
+  return smartptr::isStdSmartPtr(Call.getArgExpr(0)) || smartptr::isStdSmartPtr(Call.getArgExpr(1));
+}
+
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
 
@@ -272,14 +287,11 @@
 
   // If any one of the arg is a unique_ptr, then
   // we can try this function
-  if (Call.getNumArgs() == 2 &&
-  Call.getDecl()->getDeclContext()->isStdNamespace())
-if (smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
-smartptr::isStdSmartPtr(Call.getArgExpr(1)))
-  if (handleComparisionOp(Call, C))
-return true;
-
-  if (isStdOstreamOperatorCall(Call))
+  if (ModelSmartPtrDereference && isPotentiallyComparisionOpCall(Call))
+if (handleComparisionOp(Call, C))
+  return true;
+
+  if (ModelSmartPtrDereference && isStdOstreamOperatorCall(Call))
 return handleOstreamOperator(Call, C);
 
   if (Call.isCalled(StdSwapCall)) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D105421: [analyzer] Handle << operator for std::unique_ptr

2021-07-18 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD closed this revision.
RedDocMD added a comment.

For some reason this revision did not get automatically closed after commit, 
manually merging it.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105421/new/

https://reviews.llvm.org/D105421

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D103750: [analyzer] Handle std::make_unique for SmartPtrModeling

2021-07-18 Thread Deep Majumder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGd825309352b4: [analyzer] Handle std::make_unique (authored 
by RedDocMD).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103750/new/

https://reviews.llvm.org/D103750

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
  clang/test/Analysis/Inputs/system-header-simulator-cxx.h
  clang/test/Analysis/smart-ptr-text-output.cpp

Index: clang/test/Analysis/smart-ptr-text-output.cpp
===
--- clang/test/Analysis/smart-ptr-text-output.cpp
+++ clang/test/Analysis/smart-ptr-text-output.cpp
@@ -1,10 +1,17 @@
 // RUN: %clang_analyze_cc1\
-// RUN:  -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr\
+// RUN:  -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr,debug.ExprInspection\
+// RUN:  -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
+// RUN:  -analyzer-output=text -std=c++20 %s -verify=expected
+
+// RUN: %clang_analyze_cc1\
+// RUN:  -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr,debug.ExprInspection\
 // RUN:  -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
 // RUN:  -analyzer-output=text -std=c++11 %s -verify=expected
 
 #include "Inputs/system-header-simulator-cxx.h"
 
+void clang_analyzer_eval(bool);
+
 class A {
 public:
   A(){};
@@ -310,3 +317,61 @@
 // expected-note@-1{{Dereference of null smart pointer 'P'}}
   }
 }
+
+void makeUniqueReturnsNonNullUniquePtr() {
+  auto P = std::make_unique();
+  if (!P) {   // expected-note {{Taking false branch}}
+P->foo(); // should have no warning here, path is impossible
+  }
+  P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}}
+  // Now P is null
+  if (!P) {
+// 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'}}
+  }
+}
+
+#if __cplusplus >= 202002L
+
+void makeUniqueForOverwriteReturnsNullUniquePtr() {
+  auto P = std::make_unique_for_overwrite();
+  if (!P) {   // expected-note {{Taking false branch}}
+P->foo(); // should have no warning here, path is impossible
+  }
+  P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}}
+  // Now P is null
+  if (!P) {
+// 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'}}
+  }
+}
+
+#endif
+
+struct G {
+  int *p;
+  G(int *p): p(p) {}
+  ~G() { *p = 0; }
+};
+
+void foo() {
+  int x = 1;
+  {
+auto P = std::make_unique(&x);
+// FIXME: There should not be a state split here, it should take the true path.
+clang_analyzer_eval(*P->p == 1); // expected-warning {{TRUE}}
+// expected-warning@-1 {{FALSE}}
+// expected-note@-2 {{Assuming the condition is true}}
+// expected-note@-3 {{Assuming the condition is false}}
+// expected-note@-4 {{TRUE}}
+// expected-note@-5 {{FALSE}}
+// expected-note@-6 {{Assuming the condition is false}}
+  }
+  // FIXME: Should be fixed when unique_ptr desctructors are
+  // properly modelled. This includes modelling the call to
+  // the destructor of the inner pointer type.
+  clang_analyzer_eval(x == 0); // expected-warning {{FALSE}}
+  // expected-note@-1 {{FALSE}}
+}
Index: clang/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -1033,6 +1033,16 @@
 template 
 bool operator<=(nullptr_t x, const unique_ptr &y);
 
+template 
+unique_ptr make_unique(Args &&...args);
+
+#if __cplusplus >= 202002L
+
+template 
+unique_ptr make_unique_for_overwrite();
+
+#endif
+
 } // namespace std
 #endif
 
Index: clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
===
--- clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -192,12 +192,19 @@
   const LocationContext *LCtx,
   unsigned VisitCount) {
   QualType T = E->getType();
-  assert(Loc::isLocType(T));
-  assert(SymbolManager::canSymbolicate(T));
-  if (T->isNullPtrType())
-return makeZeroVal(T);
+  return getConjuredHeapSymbolVal(E, LCtx, T, VisitCount);
+}
+
+DefinedOrUnknownSVal
+SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
+  const LocationContext *LCtx,
+  

[PATCH] D103750: [analyzer] Handle std::make_unique for SmartPtrModeling

2021-07-18 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 359627.
RedDocMD added a comment.

Marked test with FIXME notes


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103750/new/

https://reviews.llvm.org/D103750

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
  clang/test/Analysis/Inputs/system-header-simulator-cxx.h
  clang/test/Analysis/smart-ptr-text-output.cpp

Index: clang/test/Analysis/smart-ptr-text-output.cpp
===
--- clang/test/Analysis/smart-ptr-text-output.cpp
+++ clang/test/Analysis/smart-ptr-text-output.cpp
@@ -1,10 +1,17 @@
 // RUN: %clang_analyze_cc1\
-// RUN:  -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr\
+// RUN:  -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr,debug.ExprInspection\
+// RUN:  -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
+// RUN:  -analyzer-output=text -std=c++20 %s -verify=expected
+
+// RUN: %clang_analyze_cc1\
+// RUN:  -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr,debug.ExprInspection\
 // RUN:  -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
 // RUN:  -analyzer-output=text -std=c++11 %s -verify=expected
 
 #include "Inputs/system-header-simulator-cxx.h"
 
+void clang_analyzer_eval(bool);
+
 class A {
 public:
   A(){};
@@ -310,3 +317,61 @@
 // expected-note@-1{{Dereference of null smart pointer 'P'}}
   }
 }
+
+void makeUniqueReturnsNonNullUniquePtr() {
+  auto P = std::make_unique();
+  if (!P) {   // expected-note {{Taking false branch}}
+P->foo(); // should have no warning here, path is impossible
+  }
+  P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}}
+  // Now P is null
+  if (!P) {
+// 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'}}
+  }
+}
+
+#if __cplusplus >= 202002L
+
+void makeUniqueForOverwriteReturnsNullUniquePtr() {
+  auto P = std::make_unique_for_overwrite();
+  if (!P) {   // expected-note {{Taking false branch}}
+P->foo(); // should have no warning here, path is impossible
+  }
+  P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}}
+  // Now P is null
+  if (!P) {
+// 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'}}
+  }
+}
+
+#endif
+
+struct G {
+  int *p;
+  G(int *p): p(p) {}
+  ~G() { *p = 0; }
+};
+
+void foo() {
+  int x = 1;
+  {
+auto P = std::make_unique(&x);
+// FIXME: There should not be a state split here, it should take the true path.
+clang_analyzer_eval(*P->p == 1); // expected-warning {{TRUE}}
+// expected-warning@-1 {{FALSE}}
+// expected-note@-2 {{Assuming the condition is true}}
+// expected-note@-3 {{Assuming the condition is false}}
+// expected-note@-4 {{TRUE}}
+// expected-note@-5 {{FALSE}}
+// expected-note@-6 {{Assuming the condition is false}}
+  }
+  // FIXME: Should be fixed when unique_ptr desctructors are
+  // properly modelled. This includes modelling the call to
+  // the destructor of the inner pointer type.
+  clang_analyzer_eval(x == 0); // expected-warning {{FALSE}}
+  // expected-note@-1 {{FALSE}}
+}
Index: clang/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -1033,6 +1033,16 @@
 template 
 bool operator<=(nullptr_t x, const unique_ptr &y);
 
+template 
+unique_ptr make_unique(Args &&...args);
+
+#if __cplusplus >= 202002L
+
+template 
+unique_ptr make_unique_for_overwrite();
+
+#endif
+
 } // namespace std
 #endif
 
Index: clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
===
--- clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -192,12 +192,19 @@
   const LocationContext *LCtx,
   unsigned VisitCount) {
   QualType T = E->getType();
-  assert(Loc::isLocType(T));
-  assert(SymbolManager::canSymbolicate(T));
-  if (T->isNullPtrType())
-return makeZeroVal(T);
+  return getConjuredHeapSymbolVal(E, LCtx, T, VisitCount);
+}
+
+DefinedOrUnknownSVal
+SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
+  const LocationContext *LCtx,
+  QualType type, unsigned VisitCount) {
+  assert(Loc::isLocType(type));
+  assert(Symbol

[PATCH] D103750: [analyzer] Handle std::make_unique for SmartPtrModeling

2021-07-18 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 359625.
RedDocMD added a comment.

Fixed up tests


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103750/new/

https://reviews.llvm.org/D103750

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
  clang/test/Analysis/Inputs/system-header-simulator-cxx.h
  clang/test/Analysis/smart-ptr-text-output.cpp

Index: clang/test/Analysis/smart-ptr-text-output.cpp
===
--- clang/test/Analysis/smart-ptr-text-output.cpp
+++ clang/test/Analysis/smart-ptr-text-output.cpp
@@ -1,10 +1,17 @@
 // RUN: %clang_analyze_cc1\
-// RUN:  -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr\
+// RUN:  -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr,debug.ExprInspection\
+// RUN:  -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
+// RUN:  -analyzer-output=text -std=c++20 %s -verify=expected
+
+// RUN: %clang_analyze_cc1\
+// RUN:  -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr,debug.ExprInspection\
 // RUN:  -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
 // RUN:  -analyzer-output=text -std=c++11 %s -verify=expected
 
 #include "Inputs/system-header-simulator-cxx.h"
 
+void clang_analyzer_eval(bool);
+
 class A {
 public:
   A(){};
@@ -310,3 +317,57 @@
 // expected-note@-1{{Dereference of null smart pointer 'P'}}
   }
 }
+
+void makeUniqueReturnsNonNullUniquePtr() {
+  auto P = std::make_unique();
+  if (!P) {   // expected-note {{Taking false branch}}
+P->foo(); // should have no warning here, path is impossible
+  }
+  P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}}
+  // Now P is null
+  if (!P) {
+// 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'}}
+  }
+}
+
+#if __cplusplus >= 202002L
+
+void makeUniqueForOverwriteReturnsNullUniquePtr() {
+  auto P = std::make_unique_for_overwrite();
+  if (!P) {   // expected-note {{Taking false branch}}
+P->foo(); // should have no warning here, path is impossible
+  }
+  P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}}
+  // Now P is null
+  if (!P) {
+// 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'}}
+  }
+}
+
+#endif
+
+struct G {
+  int *p;
+  G(int *p): p(p) {}
+  ~G() { *p = 0; }
+};
+
+void foo() {
+  int x = 1;
+  {
+auto P = std::make_unique(&x);
+clang_analyzer_eval(*P->p == 1); // expected-warning {{TRUE}}
+// expected-warning@-1 {{FALSE}}
+// expected-note@-2 {{Assuming the condition is true}}
+// expected-note@-3 {{Assuming the condition is false}}
+// expected-note@-4 {{TRUE}}
+// expected-note@-5 {{FALSE}}
+// expected-note@-6 {{Assuming the condition is false}}
+  }
+  clang_analyzer_eval(x == 0); // expected-warning {{FALSE}}
+  // expected-note@-1 {{FALSE}}
+}
Index: clang/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -1033,6 +1033,16 @@
 template 
 bool operator<=(nullptr_t x, const unique_ptr &y);
 
+template 
+unique_ptr make_unique(Args &&...args);
+
+#if __cplusplus >= 202002L
+
+template 
+unique_ptr make_unique_for_overwrite();
+
+#endif
+
 } // namespace std
 #endif
 
Index: clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
===
--- clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -192,12 +192,19 @@
   const LocationContext *LCtx,
   unsigned VisitCount) {
   QualType T = E->getType();
-  assert(Loc::isLocType(T));
-  assert(SymbolManager::canSymbolicate(T));
-  if (T->isNullPtrType())
-return makeZeroVal(T);
+  return getConjuredHeapSymbolVal(E, LCtx, T, VisitCount);
+}
+
+DefinedOrUnknownSVal
+SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
+  const LocationContext *LCtx,
+  QualType type, unsigned VisitCount) {
+  assert(Loc::isLocType(type));
+  assert(SymbolManager::canSymbolicate(type));
+  if (type->isNullPtrType())
+return makeZeroVal(type);
 
-  SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, T, VisitCount);
+  SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, type, VisitCount);
   return loc::MemRegionVal(MemMgr.getSymb

[PATCH] D103750: [analyzer] Handle std::make_unique for SmartPtrModeling

2021-07-18 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 359605.
RedDocMD added a comment.

Post-rebase cleanup


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103750/new/

https://reviews.llvm.org/D103750

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
  clang/test/Analysis/Inputs/system-header-simulator-cxx.h
  clang/test/Analysis/smart-ptr-text-output.cpp

Index: clang/test/Analysis/smart-ptr-text-output.cpp
===
--- clang/test/Analysis/smart-ptr-text-output.cpp
+++ clang/test/Analysis/smart-ptr-text-output.cpp
@@ -1,10 +1,17 @@
 // RUN: %clang_analyze_cc1\
-// RUN:  -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr\
+// RUN:  -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr,debug.ExprInspection\
+// RUN:  -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
+// RUN:  -analyzer-output=text -std=c++20 %s -verify=expected
+
+// RUN: %clang_analyze_cc1\
+// RUN:  -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr,debug.ExprInspection\
 // RUN:  -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
 // RUN:  -analyzer-output=text -std=c++11 %s -verify=expected
 
 #include "Inputs/system-header-simulator-cxx.h"
 
+void clang_analyzer_eval(bool);
+
 class A {
 public:
   A(){};
@@ -310,3 +317,55 @@
 // expected-note@-1{{Dereference of null smart pointer 'P'}}
   }
 }
+
+void makeUniqueReturnsNonNullUniquePtr() {
+  auto P = std::make_unique();
+  if (!P) {   // expected-note {{Taking false branch}}
+P->foo(); // should have no warning here, path is impossible
+  }
+  P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}}
+  // Now P is null
+  if (!P) {
+// 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'}}
+  }
+}
+
+#if __cplusplus >= 202002L
+
+void makeUniqueForOverwriteReturnsNullUniquePtr() {
+  auto P = std::make_unique_for_overwrite();
+  if (!P) {   // expected-note {{Taking false branch}}
+P->foo(); // should have no warning here, path is impossible
+  }
+  P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}}
+  // Now P is null
+  if (!P) {
+// 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'}}
+  }
+}
+
+#endif
+
+struct G {
+  int *p;
+  G(int *p): p(p) {}
+  ~G() { *p = 0; }
+};
+
+void foo() {
+  int x = 1;
+  {
+auto P = std::make_unique(&x);
+clang_analyzer_eval(*P->p == 1); // expected-warning {{TRUE}}
+// expected-note@-1 {{Assuming the condition is false}}
+// expected-note@-2 {{FALSE}}
+// expected-note@-3 {{Assuming the condition is true}}
+// expected-note@-4 {{TRUE}}
+  }
+  clang_analyzer_eval(x == 0); // expected-warning {{FALSE}}
+  // expected-note@-1 {{FALSE}}
+}
Index: clang/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -1033,6 +1033,16 @@
 template 
 bool operator<=(nullptr_t x, const unique_ptr &y);
 
+template 
+unique_ptr make_unique(Args &&...args);
+
+#if __cplusplus >= 202002L
+
+template 
+unique_ptr make_unique_for_overwrite();
+
+#endif
+
 } // namespace std
 #endif
 
Index: clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
===
--- clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -192,12 +192,19 @@
   const LocationContext *LCtx,
   unsigned VisitCount) {
   QualType T = E->getType();
-  assert(Loc::isLocType(T));
-  assert(SymbolManager::canSymbolicate(T));
-  if (T->isNullPtrType())
-return makeZeroVal(T);
+  return getConjuredHeapSymbolVal(E, LCtx, T, VisitCount);
+}
+
+DefinedOrUnknownSVal
+SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
+  const LocationContext *LCtx,
+  QualType type, unsigned VisitCount) {
+  assert(Loc::isLocType(type));
+  assert(SymbolManager::canSymbolicate(type));
+  if (type->isNullPtrType())
+return makeZeroVal(type);
 
-  SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, T, VisitCount);
+  SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, type, VisitCount);
   return loc::MemRegionVal(MemMgr.getSymbolicHeapRegion(sym));
 }
 
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
=

[PATCH] D104300: [analyzer] Handle std::swap for std::unique_ptr

2021-07-18 Thread Deep Majumder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG0cd98bef1b6f: [analyzer] Handle std::swap for 
std::unique_ptr (authored by RedDocMD).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104300/new/

https://reviews.llvm.org/D104300

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/BugReporter.cpp
  clang/test/Analysis/smart-ptr-text-output.cpp

Index: clang/test/Analysis/smart-ptr-text-output.cpp
===
--- clang/test/Analysis/smart-ptr-text-output.cpp
+++ clang/test/Analysis/smart-ptr-text-output.cpp
@@ -69,20 +69,17 @@
 
 void derefOnSwappedNullPtr() {
   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'}}
+  std::unique_ptr PNull;
+  P.swap(PNull);
   PNull->foo(); // No warning.
   (*P).foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   // expected-note@-1{{Dereference of null smart pointer 'P'}}
 }
 
-// FIXME: Fix this test when "std::swap" is modeled seperately.
 void derefOnStdSwappedNullPtr() {
   std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}}
-  std::unique_ptr PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}}
-  std::swap(P, PNull); // expected-note@Inputs/system-header-simulator-cxx.h:979 {{Swapped null smart pointer 'PNull' with smart pointer 'P'}}
-  // expected-note@-1 {{Calling 'swap'}}
-  // expected-note@-2 {{Returning from 'swap'}}
+  std::unique_ptr PNull;
+  std::swap(P, PNull);
   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   // expected-note@-1{{Dereference of null smart pointer 'P'}}
 }
Index: clang/lib/StaticAnalyzer/Core/BugReporter.cpp
===
--- clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -2263,6 +2263,8 @@
   // The metadata part of markInteresting is not reversed here.
   // Just making the same region not interesting is incorrect
   // in specific cases.
+  if (const auto *meta = dyn_cast(sym))
+markNotInteresting(meta->getRegion());
 }
 
 void PathSensitiveBugReport::markInteresting(const MemRegion *R,
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -63,7 +63,7 @@
 private:
   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 handleSwapMethod(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,
@@ -73,6 +73,8 @@
   void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const;
   bool handleComparisionOp(const CallEvent &Call, CheckerContext &C) const;
   bool handleOstreamOperator(const CallEvent &Call, CheckerContext &C) const;
+  bool handleSwap(ProgramStateRef State, SVal First, SVal Second,
+  CheckerContext &C) const;
   std::pair
   retrieveOrConjureInnerPtrVal(ProgramStateRef State,
const MemRegion *ThisRegion, const Expr *E,
@@ -83,8 +85,9 @@
   CallDescriptionMap SmartPtrMethodHandlers{
   {{"reset"}, &SmartPtrModeling::handleReset},
   {{"release"}, &SmartPtrModeling::handleRelease},
-  {{"swap", 1}, &SmartPtrModeling::handleSwap},
+  {{"swap", 1}, &SmartPtrModeling::handleSwapMethod},
   {{"get"}, &SmartPtrModeling::handleGet}};
+  const CallDescription StdSwapCall{{"std", "swap"}, 2};
 };
 } // end of anonymous namespace
 
@@ -259,6 +262,15 @@
   if (isStdOstreamOperatorCall(Call))
 return handleOstreamOperator(Call, C);
 
+  if (Call.isCalled(StdSwapCall)) {
+// Check the first arg, if it is of std::unique_ptr type.
+assert(Call.getNumArgs() == 2 && "std::swap should have two arguments");
+const Expr *FirstArg = Call.getArgExpr(0);
+if (!smartptr::isStdSmartPtr(FirstArg->getType()->getAsCXXRecordDecl()))
+  return false;
+return handleSwap(State, Call.getArgSVal(0), Call.getArgSVal(1), C);
+  }
+
   if (!smartptr::isStdSmartPtrCall(Call))
 return false;
 
@@ -578,43 +590,52 @@
   // pointer.
 }
 
-v

[PATCH] D104300: [analyzer] Handle std::swap for std::unique_ptr

2021-07-18 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 359600.
RedDocMD added a comment.

Post rebase cleanup


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104300/new/

https://reviews.llvm.org/D104300

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/BugReporter.cpp
  clang/test/Analysis/smart-ptr-text-output.cpp

Index: clang/test/Analysis/smart-ptr-text-output.cpp
===
--- clang/test/Analysis/smart-ptr-text-output.cpp
+++ clang/test/Analysis/smart-ptr-text-output.cpp
@@ -69,20 +69,17 @@
 
 void derefOnSwappedNullPtr() {
   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'}}
+  std::unique_ptr PNull;
+  P.swap(PNull);
   PNull->foo(); // No warning.
   (*P).foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   // expected-note@-1{{Dereference of null smart pointer 'P'}}
 }
 
-// FIXME: Fix this test when "std::swap" is modeled seperately.
 void derefOnStdSwappedNullPtr() {
   std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}}
-  std::unique_ptr PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}}
-  std::swap(P, PNull); // expected-note@Inputs/system-header-simulator-cxx.h:979 {{Swapped null smart pointer 'PNull' with smart pointer 'P'}}
-  // expected-note@-1 {{Calling 'swap'}}
-  // expected-note@-2 {{Returning from 'swap'}}
+  std::unique_ptr PNull;
+  std::swap(P, PNull);
   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   // expected-note@-1{{Dereference of null smart pointer 'P'}}
 }
Index: clang/lib/StaticAnalyzer/Core/BugReporter.cpp
===
--- clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -2263,6 +2263,8 @@
   // The metadata part of markInteresting is not reversed here.
   // Just making the same region not interesting is incorrect
   // in specific cases.
+  if (const auto *meta = dyn_cast(sym))
+markNotInteresting(meta->getRegion());
 }
 
 void PathSensitiveBugReport::markInteresting(const MemRegion *R,
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -63,7 +63,7 @@
 private:
   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 handleSwapMethod(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,
@@ -73,6 +73,8 @@
   void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const;
   bool handleComparisionOp(const CallEvent &Call, CheckerContext &C) const;
   bool handleOstreamOperator(const CallEvent &Call, CheckerContext &C) const;
+  bool handleSwap(ProgramStateRef State, SVal First, SVal Second,
+  CheckerContext &C) const;
   std::pair
   retrieveOrConjureInnerPtrVal(ProgramStateRef State,
const MemRegion *ThisRegion, const Expr *E,
@@ -83,8 +85,9 @@
   CallDescriptionMap SmartPtrMethodHandlers{
   {{"reset"}, &SmartPtrModeling::handleReset},
   {{"release"}, &SmartPtrModeling::handleRelease},
-  {{"swap", 1}, &SmartPtrModeling::handleSwap},
+  {{"swap", 1}, &SmartPtrModeling::handleSwapMethod},
   {{"get"}, &SmartPtrModeling::handleGet}};
+  const CallDescription StdSwapCall{{"std", "swap"}, 2};
 };
 } // end of anonymous namespace
 
@@ -259,6 +262,15 @@
   if (isStdOstreamOperatorCall(Call))
 return handleOstreamOperator(Call, C);
 
+  if (Call.isCalled(StdSwapCall)) {
+// Check the first arg, if it is of std::unique_ptr type.
+assert(Call.getNumArgs() == 2 && "std::swap should have two arguments");
+const Expr *FirstArg = Call.getArgExpr(0);
+if (!smartptr::isStdSmartPtr(FirstArg->getType()->getAsCXXRecordDecl()))
+  return false;
+return handleSwap(State, Call.getArgSVal(0), Call.getArgSVal(1), C);
+  }
+
   if (!smartptr::isStdSmartPtrCall(Call))
 return false;
 
@@ -578,43 +590,52 @@
   // pointer.
 }
 
-void SmartPtrModeling::handleSwap(const CallEvent &Call,
-  CheckerContext &C) const {
+void SmartPtrModeling:

[PATCH] D105421: [analyzer] Handle << operator for std::unique_ptr

2021-07-15 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 359211.
RedDocMD added a comment.

Post rebase cleanup


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105421/new/

https://reviews.llvm.org/D105421

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/test/Analysis/Inputs/system-header-simulator-cxx.h
  clang/test/Analysis/smart-ptr.cpp

Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -3,6 +3,11 @@
 // RUN:   -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
 // RUN:   -std=c++11 -verify %s
 
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection\
+// RUN:   -analyzer-checker cplusplus.Move,alpha.cplusplus.SmartPtr\
+// RUN:   -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
+// RUN:   -std=c++20 -verify %s
+
 #include "Inputs/system-header-simulator-cxx.h"
 
 void clang_analyzer_warnIfReached();
@@ -506,3 +511,28 @@
   clang_analyzer_eval(nullPtr != nullptr);// expected-warning{{FALSE}}
   clang_analyzer_eval(nullptr <= unknownPtr); // expected-warning{{TRUE}}
 }
+
+#if __cplusplus >= 202002L
+
+void testOstreamOverload(std::unique_ptr P) {
+  auto &Cout = std::cout;
+  auto &PtrCout = std::cout << P;
+  auto &StringCout = std::cout << "hello";
+  // We are testing the fact that in our modelling of
+  // operator<<(basic_ostream &, const unique_ptr &)
+  // we set the return SVal to the SVal of the ostream arg.
+  clang_analyzer_eval(&Cout == &PtrCout);// expected-warning {{TRUE}}
+  // FIXME: Technically, they should be equal,
+  // that hasn't been modelled yet.
+  clang_analyzer_eval(&Cout == &StringCout); // expected-warning {{UNKNOWN}}
+}
+
+int glob;
+void testOstreamDoesntInvalidateGlobals(std::unique_ptr P) {
+  int x = glob;
+  std::cout << P;
+  int y = glob;
+  clang_analyzer_eval(x == y); // expected-warning {{TRUE}}
+}
+
+#endif
Index: clang/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -1036,6 +1036,22 @@
 } // namespace std
 #endif
 
+namespace std {
+template 
+class basic_ostream;
+
+using ostream = basic_ostream;
+
+extern std::ostream cout;
+
+ostream &operator<<(ostream &, const string &);
+
+#if __cplusplus >= 202002L
+template 
+ostream &operator<<(ostream &, const std::unique_ptr &);
+#endif
+} // namespace std
+
 #ifdef TEST_INLINABLE_ALLOCATORS
 namespace std {
   void *malloc(size_t);
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -72,6 +72,7 @@
 const MemRegion *OtherSmartPtrRegion) const;
   void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const;
   bool handleComparisionOp(const CallEvent &Call, CheckerContext &C) const;
+  bool handleOstreamOperator(const CallEvent &Call, CheckerContext &C) const;
   std::pair
   retrieveOrConjureInnerPtrVal(ProgramStateRef State,
const MemRegion *ThisRegion, const Expr *E,
@@ -89,6 +90,31 @@
 
 REGISTER_MAP_WITH_PROGRAMSTATE(TrackedRegionMap, const MemRegion *, SVal)
 
+// Checks if RD has name in Names and is in std namespace
+static bool hasStdClassWithName(const CXXRecordDecl *RD,
+ArrayRef Names) {
+  if (!RD || !RD->getDeclContext()->isStdNamespace())
+return false;
+  if (RD->getDeclName().isIdentifier()) {
+StringRef Name = RD->getName();
+return llvm::any_of(Names, [&Name](StringRef GivenName) -> bool {
+  return Name == GivenName;
+});
+  }
+  return false;
+}
+
+constexpr llvm::StringLiteral STD_PTR_NAMES[] = {"shared_ptr", "unique_ptr",
+ "weak_ptr"};
+
+static bool isStdSmartPtr(const CXXRecordDecl *RD) {
+  return hasStdClassWithName(RD, STD_PTR_NAMES);
+}
+
+static bool isStdSmartPtr(const Expr *E) {
+  return isStdSmartPtr(E->getType()->getAsCXXRecordDecl());
+}
+
 // Define the inter-checker API.
 namespace clang {
 namespace ento {
@@ -193,6 +219,30 @@
   return CD && CD->getConversionType()->isBooleanType();
 }
 
+constexpr llvm::StringLiteral BASIC_OSTREAM_NAMES[] = {"basic_ostream"};
+
+bool isStdBasicOstream(const Expr *E) {
+  const auto *RD = E->getType()->getAsCXXRecordDecl();
+  return hasStdClassWithName(RD, BASIC_OSTREAM_NAMES);
+}
+
+bool isStdOstreamOperatorCall(const CallEvent &Call) {
+  if (Call.getNumArgs() != 2 ||
+  !Call.getDecl()->getDeclContext()->isStdNamespace())
+return false;
+  const auto *FC = dyn_cast(&Call);
+  if (!FC)
+return false;
+  const 

[PATCH] D104616: [analyzer] Model comparision methods of std::unique_ptr

2021-07-15 Thread Deep Majumder via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG48688257c52d: [analyzer] Model comparision methods of 
std::unique_ptr (authored by RedDocMD).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
  clang/test/Analysis/Inputs/system-header-simulator-cxx.h
  clang/test/Analysis/smart-ptr.cpp

Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -457,3 +457,52 @@
 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   }
 }
+
+// The following is a silly function,
+// but serves to test if we are picking out
+// standard comparision functions from custom ones.
+template 
+bool operator<(std::unique_ptr &x, double d);
+
+void uniquePtrComparision(std::unique_ptr unknownPtr) {
+  auto ptr = std::unique_ptr(new int(13));
+  auto nullPtr = std::unique_ptr();
+  auto otherPtr = std::unique_ptr(new int(29));
+
+  clang_analyzer_eval(ptr == ptr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > ptr);  // expected-warning{{FALSE}}
+  clang_analyzer_eval(ptr <= ptr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(nullPtr <= unknownPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(unknownPtr >= nullPtr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != otherPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > nullPtr);   // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != nullptr);// expected-warning{{TRUE}}
+  clang_analyzer_eval(nullPtr != nullptr);// expected-warning{{FALSE}}
+  clang_analyzer_eval(nullptr <= unknownPtr); // expected-warning{{TRUE}}
+}
+
+void uniquePtrComparisionStateSplitting(std::unique_ptr unknownPtr) {
+  auto ptr = std::unique_ptr(new int(13));
+
+  clang_analyzer_eval(ptr > unknownPtr); // expected-warning{{TRUE}}
+  // expected-warning@-1{{FALSE}}
+}
+
+void uniquePtrComparisionDifferingTypes(std::unique_ptr unknownPtr) {
+  auto ptr = std::unique_ptr(new int(13));
+  auto nullPtr = std::unique_ptr();
+  auto otherPtr = std::unique_ptr(new double(3.14));
+
+  clang_analyzer_eval(nullPtr <= unknownPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(unknownPtr >= nullPtr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != otherPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > nullPtr);   // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != nullptr);// expected-warning{{TRUE}}
+  clang_analyzer_eval(nullPtr != nullptr);// expected-warning{{FALSE}}
+  clang_analyzer_eval(nullptr <= unknownPtr); // expected-warning{{TRUE}}
+}
Index: clang/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -978,6 +978,61 @@
 void swap(unique_ptr &x, unique_ptr &y) noexcept {
   x.swap(y);
 }
+
+template 
+bool operator==(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator!=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator<(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator>(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator<=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator>=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator==(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator!=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator<(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator>(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator<=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator>=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator==(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator!=(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator>(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator<(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator>=(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator<=(nullptr_t x, const unique_ptr &y);
+
 } // namespace std
 #endif
 
Index: clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
@@ -148,5 +148,39 @@
   return IntValue.getSExtValue();
 }
 
+OperatorKind operationKindFromOverloadedOperator(OverloadedOperatorKind OOK,
+ 

[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-07-15 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 358998.
RedDocMD added a comment.

Removed one bug, many more to go


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp


Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -19,6 +19,7 @@
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "llvm/Support/raw_ostream.h"
 
 using namespace clang;
 using namespace ento;
@@ -754,9 +755,10 @@
 
   ExplodedNodeSet DstInvalidated;
   StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-   I != E; ++I)
-defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = 
DstPreCall.end();
+  //  I != E; ++I)
+  //   defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, 
*Call, *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
  *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,13 @@
 for (const auto &EvalCallChecker : EvalCallCheckers) {
   // TODO: Support the situation when the call doesn't correspond
   // to any Expr.
-  ProgramPoint L = ProgramPoint::getProgramPoint(
-  Call.getOriginExpr(), ProgramPoint::PostStmtKind,
-  Pred->getLocationContext(), EvalCallChecker.Checker);
   bool evaluated = false;
   { // CheckerContext generates transitions(populates checkDest) on
 // destruction, so introduce the scope to make sure it gets properly
 // populated.
-CheckerContext C(B, Eng, Pred, L);
+CheckerContext C(B, Eng, Pred, Call.getProgramPoint());
+Call.getProgramPoint().dump();
+llvm::errs() << "\n";
 evaluated = EvalCallChecker(Call, C);
   }
   assert(!(evaluated && anyEvaluated)
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -177,7 +177,9 @@
 
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
+
   ProgramStateRef State = C.getState();
+  Call.dump();
   if (!smartptr::isStdSmartPtrCall(Call))
 return false;
 
@@ -261,6 +263,11 @@
 return true;
   }
 
+  if (const auto *DC = dyn_cast(&Call)) {
+llvm::errs() << "Wohoo\n";
+return true;
+  }
+
   if (handleAssignOp(Call, C))
 return true;
 


Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -19,6 +19,7 @@
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "llvm/Support/raw_ostream.h"
 
 using namespace clang;
 using namespace ento;
@@ -754,9 +755,10 @@
 
   ExplodedNodeSet DstInvalidated;
   StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-   I != E; ++I)
-defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
+  //  I != E; ++I)
+  //   defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, *Call, *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
  *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,13 @@
 for (const auto &EvalCallChecker : EvalCallCheckers) {
   // TODO: Support the situation when the call doesn't correspond
   // to any Expr.
-  ProgramPoint L = P

[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-07-14 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 358839.
RedDocMD added a comment.

Cleanup, still doesn't work


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105821/new/

https://reviews.llvm.org/D105821

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp


Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -19,6 +19,7 @@
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "llvm/Support/raw_ostream.h"
 
 using namespace clang;
 using namespace ento;
@@ -757,6 +758,7 @@
   for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
I != E; ++I)
 defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, 
*Call, *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
  *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,11 @@
 for (const auto &EvalCallChecker : EvalCallCheckers) {
   // TODO: Support the situation when the call doesn't correspond
   // to any Expr.
-  ProgramPoint L = ProgramPoint::getProgramPoint(
-  Call.getOriginExpr(), ProgramPoint::PostStmtKind,
-  Pred->getLocationContext(), EvalCallChecker.Checker);
   bool evaluated = false;
   { // CheckerContext generates transitions(populates checkDest) on
 // destruction, so introduce the scope to make sure it gets properly
 // populated.
-CheckerContext C(B, Eng, Pred, L);
+CheckerContext C(B, Eng, Pred, Call.getProgramPoint());
 evaluated = EvalCallChecker(Call, C);
   }
   assert(!(evaluated && anyEvaluated)
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -177,7 +177,9 @@
 
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
+
   ProgramStateRef State = C.getState();
+  Call.dump();
   if (!smartptr::isStdSmartPtrCall(Call))
 return false;
 
@@ -261,6 +263,11 @@
 return true;
   }
 
+  if (const auto *DC = dyn_cast(&Call)) {
+llvm::errs() << "Wohoo\n";
+return true;
+  }
+
   if (handleAssignOp(Call, C))
 return true;
 


Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -19,6 +19,7 @@
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "llvm/Support/raw_ostream.h"
 
 using namespace clang;
 using namespace ento;
@@ -757,6 +758,7 @@
   for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
I != E; ++I)
 defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, *Call, *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
  *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,11 @@
 for (const auto &EvalCallChecker : EvalCallCheckers) {
   // TODO: Support the situation when the call doesn't correspond
   // to any Expr.
-  ProgramPoint L = ProgramPoint::getProgramPoint(
-  Call.getOriginExpr(), ProgramPoint::PostStmtKind,
-  Pred->getLocationContext(), EvalCallChecker.Checker);
   bool evaluated = false;
   { // CheckerContext generates transitions(populates checkDest) on
 // destruction, so introduce the scope to make sure it gets properly
 // populated.
-CheckerContext C(B, Eng, Pred, L);
+CheckerContext C(B, Eng, Pred, Call.getProgramPoint());
 evaluated = EvalCallChecker(Call, C);
   }
   assert(!(evaluated && anyEvaluated)
Index: clang/lib/StaticAnalyzer/Chec

[PATCH] D103750: [analyzer] Handle std::make_unique for SmartPtrModeling

2021-07-13 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

Is the syntax of specifying expected notes and warnings documented somewhere? I 
could not find the note-specific syntax.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103750/new/

https://reviews.llvm.org/D103750

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D103750: [analyzer] Handle std::make_unique for SmartPtrModeling

2021-07-13 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 358267.
RedDocMD added a comment.

Fixing up tests


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103750/new/

https://reviews.llvm.org/D103750

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
  clang/test/Analysis/Inputs/system-header-simulator-cxx.h
  clang/test/Analysis/smart-ptr-text-output.cpp

Index: clang/test/Analysis/smart-ptr-text-output.cpp
===
--- clang/test/Analysis/smart-ptr-text-output.cpp
+++ clang/test/Analysis/smart-ptr-text-output.cpp
@@ -1,10 +1,17 @@
 // RUN: %clang_analyze_cc1\
-// RUN:  -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr\
+// RUN:  -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr,debug.ExprInspection\
+// RUN:  -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
+// RUN:  -analyzer-output=text -std=c++20 %s -verify=expected
+
+// RUN: %clang_analyze_cc1\
+// RUN:  -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr,debug.ExprInspection\
 // RUN:  -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
 // RUN:  -analyzer-output=text -std=c++11 %s -verify=expected
 
 #include "Inputs/system-header-simulator-cxx.h"
 
+void clang_analyzer_eval(bool);
+
 class A {
 public:
   A(){};
@@ -313,3 +320,55 @@
 // expected-note@-1{{Dereference of null smart pointer 'P'}}
   }
 }
+
+void makeUniqueReturnsNonNullUniquePtr() {
+  auto P = std::make_unique();
+  if (!P) {   // expected-note {{Taking false branch}}
+P->foo(); // should have no warning here, path is impossible
+  }
+  P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}}
+  // Now P is null
+  if (!P) {
+// 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'}}
+  }
+}
+
+#if __cplusplus >= 202002L
+
+void makeUniqueForOverwriteReturnsNullUniquePtr() {
+  auto P = std::make_unique_for_overwrite();
+  if (!P) {   // expected-note {{Taking false branch}}
+P->foo(); // should have no warning here, path is impossible
+  }
+  P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}}
+  // Now P is null
+  if (!P) {
+// 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'}}
+  }
+}
+
+#endif
+
+struct G {
+  int *p;
+  G(int *p): p(p) {}
+  ~G() { *p = 0; }
+};
+
+void foo() {
+  int x = 1;
+  {
+auto P = std::make_unique(&x);
+clang_analyzer_eval(*P->p == 1); // expected-warning {{TRUE}}
+// expected-note@-1 {{Assuming the condition is false}}
+// expected-note@-2 {{FALSE}}
+// expected-note@-3 {{Assuming the condition is true}}
+// expected-note@-4 {{TRUE}}
+  }
+  clang_analyzer_eval(x == 0); // expected-warning {{FALSE}}
+  // expected-note@-1 {{FALSE}}
+}
Index: clang/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -978,6 +978,17 @@
 void swap(unique_ptr &x, unique_ptr &y) noexcept {
   x.swap(y);
 }
+
+template 
+unique_ptr make_unique(Args &&...args);
+
+#if __cplusplus >= 202002L
+
+template 
+unique_ptr make_unique_for_overwrite();
+
+#endif
+
 } // namespace std
 #endif
 
Index: clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
===
--- clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -192,12 +192,19 @@
   const LocationContext *LCtx,
   unsigned VisitCount) {
   QualType T = E->getType();
-  assert(Loc::isLocType(T));
-  assert(SymbolManager::canSymbolicate(T));
-  if (T->isNullPtrType())
-return makeZeroVal(T);
+  return getConjuredHeapSymbolVal(E, LCtx, T, VisitCount);
+}
+
+DefinedOrUnknownSVal
+SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
+  const LocationContext *LCtx,
+  QualType type, unsigned VisitCount) {
+  assert(Loc::isLocType(type));
+  assert(SymbolManager::canSymbolicate(type));
+  if (type->isNullPtrType())
+return makeZeroVal(type);
 
-  SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, T, VisitCount);
+  SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, type, VisitCount);
   return loc::MemRegionVal(MemMgr.getSymbolicHeapRegion(sym));
 }
 
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
=

[PATCH] D105421: [analyzer] Handle << operator for std::unique_ptr

2021-07-13 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 358204.
RedDocMD added a comment.

Removed stupid mistakes


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105421/new/

https://reviews.llvm.org/D105421

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/test/Analysis/Inputs/system-header-simulator-cxx.h
  clang/test/Analysis/smart-ptr.cpp

Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -3,6 +3,11 @@
 // RUN:   -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
 // RUN:   -std=c++11 -verify %s
 
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection\
+// RUN:   -analyzer-checker cplusplus.Move,alpha.cplusplus.SmartPtr\
+// RUN:   -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
+// RUN:   -std=c++20 -verify %s
+
 #include "Inputs/system-header-simulator-cxx.h"
 
 void clang_analyzer_warnIfReached();
@@ -457,3 +462,28 @@
 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   }
 }
+
+#if __cplusplus >= 202002L
+
+void testOstreamOverload(std::unique_ptr P) {
+  auto &Cout = std::cout;
+  auto &PtrCout = std::cout << P;
+  auto &StringCout = std::cout << "hello";
+  // We are testing the fact that in our modelling of
+  // operator<<(basic_ostream &, const unique_ptr &)
+  // we set the return SVal to the SVal of the ostream arg.
+  clang_analyzer_eval(&Cout == &PtrCout);// expected-warning {{TRUE}}
+  // FIXME: Technically, they should be equal,
+  // that hasn't been modelled yet.
+  clang_analyzer_eval(&Cout == &StringCout); // expected-warning {{UNKNOWN}}
+}
+
+int glob;
+void testOstreamDoesntInvalidateGlobals(std::unique_ptr P) {
+  int x = glob;
+  std::cout << P;
+  int y = glob;
+  clang_analyzer_eval(x == y); // expected-warning {{TRUE}}
+}
+
+#endif
Index: clang/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -981,6 +981,22 @@
 } // namespace std
 #endif
 
+namespace std {
+template 
+class basic_ostream;
+
+using ostream = basic_ostream;
+
+extern std::ostream cout;
+
+ostream &operator<<(ostream &, const string &);
+
+#if __cplusplus >= 202002L
+template 
+ostream &operator<<(ostream &, const std::unique_ptr &);
+#endif
+} // namespace std
+
 #ifdef TEST_INLINABLE_ALLOCATORS
 namespace std {
   void *malloc(size_t);
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -68,6 +68,7 @@
   bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion,
 const MemRegion *OtherSmartPtrRegion) const;
   void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const;
+  bool handleOstreamOperator(const CallEvent &Call, CheckerContext &C) const;
 
   using SmartPtrMethodHandlerFn =
   void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const;
@@ -81,6 +82,31 @@
 
 REGISTER_MAP_WITH_PROGRAMSTATE(TrackedRegionMap, const MemRegion *, SVal)
 
+// Checks if RD has name in Names and is in std namespace
+static bool hasStdClassWithName(const CXXRecordDecl *RD,
+ArrayRef Names) {
+  if (!RD || !RD->getDeclContext()->isStdNamespace())
+return false;
+  if (RD->getDeclName().isIdentifier()) {
+StringRef Name = RD->getName();
+return llvm::any_of(Names, [&Name](StringRef GivenName) -> bool {
+  return Name == GivenName;
+});
+  }
+  return false;
+}
+
+constexpr llvm::StringLiteral STD_PTR_NAMES[] = {"shared_ptr", "unique_ptr",
+ "weak_ptr"};
+
+static bool isStdSmartPtr(const CXXRecordDecl *RD) {
+  return hasStdClassWithName(RD, STD_PTR_NAMES);
+}
+
+static bool isStdSmartPtr(const Expr *E) {
+  return isStdSmartPtr(E->getType()->getAsCXXRecordDecl());
+}
+
 // Define the inter-checker API.
 namespace clang {
 namespace ento {
@@ -89,16 +115,7 @@
   const auto *MethodDecl = dyn_cast_or_null(Call.getDecl());
   if (!MethodDecl || !MethodDecl->getParent())
 return false;
-
-  const auto *RecordDecl = MethodDecl->getParent();
-  if (!RecordDecl || !RecordDecl->getDeclContext()->isStdNamespace())
-return false;
-
-  if (RecordDecl->getDeclName().isIdentifier()) {
-StringRef Name = RecordDecl->getName();
-return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr";
-  }
-  return false;
+  return isStdSmartPtr(MethodDecl->getParent());
 }
 
 bool isNullSmartPtr(const ProgramStateRef State, const MemRegion *ThisRegi

[PATCH] D105821: [analyzer] [WIP] Model destructor for std::unique_ptr

2021-07-12 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD created this revision.
RedDocMD added reviewers: NoQ, vsavchenko, xazax.hun, teemperor.
Herald added subscribers: manas, steakhal, ASDenysPetrov, martong, dkrupp, 
donat.nagy, Szelethus, mikhail.ramalho, a.sidorin, rnkovacs, szepet, 
baloghadamsoftware.
RedDocMD requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This is probably a "throw-away" patch which attempts
to model automatic implicit destructor calls.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D105821

Files:
  clang/include/clang/Analysis/ProgramPoint.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
  clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp

Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -19,6 +19,7 @@
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "llvm/Support/raw_ostream.h"
 
 using namespace clang;
 using namespace ento;
@@ -757,6 +758,7 @@
   for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
I != E; ++I)
 defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, *Call, *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
  *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
===
--- clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -181,6 +181,10 @@
   dispatchWorkItem(Pred, PNode->getLocation(), WU);
   break;
 }
+case ProgramPoint::DestructorCallKind:
+  // Literally do nothing, since there is no real statement
+  // So there is nothing to be done.
+  break;
 default:
   assert(Loc.getAs() ||
  Loc.getAs() ||
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,20 @@
 for (const auto &EvalCallChecker : EvalCallCheckers) {
   // TODO: Support the situation when the call doesn't correspond
   // to any Expr.
-  ProgramPoint L = ProgramPoint::getProgramPoint(
-  Call.getOriginExpr(), ProgramPoint::PostStmtKind,
+  llvm::Optional LOpt;
+  const Expr *OriginExpr = Call.getOriginExpr();
+  if (OriginExpr) {
+LOpt = ProgramPoint::getProgramPoint(
+  OriginExpr, ProgramPoint::PostStmtKind,
   Pred->getLocationContext(), EvalCallChecker.Checker);
+  } else {
+LOpt = DestructorCallPoint(Pred->getLocationContext(), EvalCallChecker.Checker);
+  }
   bool evaluated = false;
   { // CheckerContext generates transitions(populates checkDest) on
 // destruction, so introduce the scope to make sure it gets properly
 // populated.
-CheckerContext C(B, Eng, Pred, L);
+CheckerContext C(B, Eng, Pred, *LOpt);
 evaluated = EvalCallChecker(Call, C);
   }
   assert(!(evaluated && anyEvaluated)
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -29,6 +29,7 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/Support/raw_ostream.h"
 #include 
 
 using namespace clang;
@@ -177,7 +178,9 @@
 
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
+
   ProgramStateRef State = C.getState();
+  Call.dump();
   if (!smartptr::isStdSmartPtrCall(Call))
 return false;
 
@@ -261,6 +264,11 @@
 return true;
   }
 
+  if (const auto *DC = dyn_cast(&Call)) {
+llvm::errs() << "Wohoo\n";
+return true;
+  }
+
   if (handleAssignOp(Call, C))
 return true;
 
Index: clang/include/clang/Analysis/ProgramPoint.h
===
--- clang/include/clang/Analysis/ProgramPoint.h
+++ clang/include/clang/Analysis/ProgramPoint.h
@@ -84,7 +84,8 @@
   MinImplicitCallKind = PreImplicitCallKind,
   MaxImplicitCallKind = PostImplicitCallKind,
   LoopExitKind,
-  EpsilonKind};
+  

[PATCH] D105421: [analyzer] Handle << operator for std::unique_ptr

2021-07-10 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 357724.
RedDocMD added a comment.

Little refactors, one more test


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105421/new/

https://reviews.llvm.org/D105421

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/test/Analysis/Inputs/system-header-simulator-cxx.h
  clang/test/Analysis/smart-ptr.cpp

Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -3,6 +3,11 @@
 // RUN:   -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
 // RUN:   -std=c++11 -verify %s
 
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection\
+// RUN:   -analyzer-checker cplusplus.Move,alpha.cplusplus.SmartPtr\
+// RUN:   -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
+// RUN:   -std=c++20 -verify %s
+
 #include "Inputs/system-header-simulator-cxx.h"
 
 void clang_analyzer_warnIfReached();
@@ -457,3 +462,28 @@
 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   }
 }
+
+#if __cplusplus >= 202002L
+
+void testOstreamOverload(std::unique_ptr P) {
+  auto &Cout = std::cout;
+  auto &PtrCout = std::cout << P;
+  auto &StringCout = std::cout << "hello";
+  // We are testing the fact that in our modelling of
+  // operator<<(basic_ostream &, const unique_ptr &)
+  // we set the return SVal to the SVal of the ostream arg.
+  clang_analyzer_eval(&Cout == &PtrCout);// expected-warning {{TRUE}}
+  // FIXME: Technically, they should be equal,
+  // that hasn't been modelled yet.
+  clang_analyzer_eval(&Cout == &StringCout); // expected-warning {{UNKNOWN}}
+}
+
+int glob;
+void testOstreamDoesntInvalidateGlobals(std::unique_ptr P) {
+  int x = glob;
+  std::cout << P;
+  int y = glob;
+  clang_analyzer_eval(x == y); // expected-warning {{TRUE}}
+}
+
+#endif
Index: clang/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -981,6 +981,22 @@
 } // namespace std
 #endif
 
+namespace std {
+template 
+class basic_ostream;
+
+using ostream = basic_ostream;
+
+extern std::ostream cout;
+
+ostream &operator<<(ostream &, const string &);
+
+#if __cplusplus >= 202002L
+template 
+ostream &operator<<(ostream &, const std::unique_ptr &);
+#endif
+} // namespace std
+
 #ifdef TEST_INLINABLE_ALLOCATORS
 namespace std {
   void *malloc(size_t);
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -68,6 +68,7 @@
   bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion,
 const MemRegion *OtherSmartPtrRegion) const;
   void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const;
+  bool handleOstreamOperator(const CallEvent &Call, CheckerContext &C) const;
 
   using SmartPtrMethodHandlerFn =
   void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const;
@@ -81,6 +82,31 @@
 
 REGISTER_MAP_WITH_PROGRAMSTATE(TrackedRegionMap, const MemRegion *, SVal)
 
+// Checks if RD has name in Names and is in std namespace
+static bool hasStdClassWithName(const CXXRecordDecl *RD,
+const ArrayRef &Names) {
+  if (!RD || !RD->getDeclContext()->isStdNamespace())
+return false;
+  if (RD->getDeclName().isIdentifier()) {
+StringRef Name = RD->getName();
+return llvm::any_of(Names, [&Name](StringRef GivenName) -> bool {
+  return Name == GivenName;
+});
+  }
+  return false;
+}
+
+constexpr llvm::StringLiteral STD_PTR_NAMES[] = {"shared_ptr", "unique_ptr",
+ "weak_ptr"};
+
+static bool isStdSmartPtr(const CXXRecordDecl *RD) {
+  return hasStdClassWithName(RD, {STD_PTR_NAMES, 3});
+}
+
+static bool isStdSmartPtr(const Expr *E) {
+  return isStdSmartPtr(E->getType()->getAsCXXRecordDecl());
+}
+
 // Define the inter-checker API.
 namespace clang {
 namespace ento {
@@ -89,16 +115,7 @@
   const auto *MethodDecl = dyn_cast_or_null(Call.getDecl());
   if (!MethodDecl || !MethodDecl->getParent())
 return false;
-
-  const auto *RecordDecl = MethodDecl->getParent();
-  if (!RecordDecl || !RecordDecl->getDeclContext()->isStdNamespace())
-return false;
-
-  if (RecordDecl->getDeclName().isIdentifier()) {
-StringRef Name = RecordDecl->getName();
-return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr";
-  }
-  return false;
+  return isStdSmartPtr(MethodDecl->getParent());
 }
 
 bool isNullSmartPtr(const ProgramStateRef State, const

[PATCH] D105421: [analyzer] Handle << operator for std::unique_ptr

2021-07-10 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD marked 4 inline comments as done.
RedDocMD added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:195
 
+const SmallVector BasicOstreamName = {"basic_ostream"};
+

vsavchenko wrote:
> Same here + don't call it "Name" (singular).  It is a) an array and b) in the 
> future, we might add more things to it, so we shouldn't need to rename it 
> everywhere.
Well, we won't have to rename but we will still have to change the array length 
everywhere if more names are added.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105421/new/

https://reviews.llvm.org/D105421

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D105421: [analyzer] Handle << operator for std::unique_ptr

2021-07-09 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 357422.
RedDocMD added a comment.

Tests implemented


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105421/new/

https://reviews.llvm.org/D105421

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/test/Analysis/Inputs/system-header-simulator-cxx.h
  clang/test/Analysis/smart-ptr.cpp

Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -3,6 +3,11 @@
 // RUN:   -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
 // RUN:   -std=c++11 -verify %s
 
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection\
+// RUN:   -analyzer-checker cplusplus.Move,alpha.cplusplus.SmartPtr\
+// RUN:   -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
+// RUN:   -std=c++20 -verify %s
+
 #include "Inputs/system-header-simulator-cxx.h"
 
 void clang_analyzer_warnIfReached();
@@ -457,3 +462,17 @@
 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   }
 }
+
+#if __cplusplus >= 202002L
+
+void testOstreamOverload(std::unique_ptr P) {
+  auto &Cout = std::cout;
+  auto &PtrCout = std::cout << P;
+  auto &StringCout = std::cout << "hello";
+  // We are testing the fact that in our modelling of
+  // operator<<(basic_ostream &, const unique_ptr &)
+  // we set the return SVal to the SVal of the ostream arg.
+  clang_analyzer_eval(&Cout == &PtrCout);// expected-warning {{TRUE}}
+  clang_analyzer_eval(&Cout == &StringCout); // expected-warning {{UNKNOWN}}
+}
+#endif
Index: clang/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -981,6 +981,22 @@
 } // namespace std
 #endif
 
+namespace std {
+template 
+class basic_ostream;
+
+using ostream = basic_ostream;
+
+extern std::ostream cout;
+
+ostream &operator<<(ostream &, const string &);
+
+#if __cplusplus >= 202002L
+template 
+ostream &operator<<(ostream &, const std::unique_ptr &);
+#endif
+} // namespace std
+
 #ifdef TEST_INLINABLE_ALLOCATORS
 namespace std {
   void *malloc(size_t);
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -68,6 +68,7 @@
   bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion,
 const MemRegion *OtherSmartPtrRegion) const;
   void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const;
+  bool handleOstreamOperator(const CallEvent &Call, CheckerContext &C) const;
 
   using SmartPtrMethodHandlerFn =
   void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const;
@@ -81,6 +82,31 @@
 
 REGISTER_MAP_WITH_PROGRAMSTATE(TrackedRegionMap, const MemRegion *, SVal)
 
+// Checks if RD has name in Names and is in std namespace
+static bool hasStdClassWithName(const CXXRecordDecl *RD,
+const ArrayRef &Names) {
+  if (!RD || !RD->getDeclContext()->isStdNamespace())
+return false;
+  if (RD->getDeclName().isIdentifier()) {
+StringRef Name = RD->getName();
+return llvm::any_of(Names, [&Name](StringRef GivenName) -> bool {
+  return Name == GivenName;
+});
+  }
+  return false;
+}
+
+const SmallVector StdPtrNames = {"shared_ptr", "unique_ptr",
+   "weak_ptr"};
+
+static bool isStdSmartPtr(const CXXRecordDecl *RD) {
+  return hasStdClassWithName(RD, StdPtrNames);
+}
+
+static bool isStdSmartPtr(const Expr *E) {
+  return isStdSmartPtr(E->getType()->getAsCXXRecordDecl());
+}
+
 // Define the inter-checker API.
 namespace clang {
 namespace ento {
@@ -89,16 +115,7 @@
   const auto *MethodDecl = dyn_cast_or_null(Call.getDecl());
   if (!MethodDecl || !MethodDecl->getParent())
 return false;
-
-  const auto *RecordDecl = MethodDecl->getParent();
-  if (!RecordDecl || !RecordDecl->getDeclContext()->isStdNamespace())
-return false;
-
-  if (RecordDecl->getDeclName().isIdentifier()) {
-StringRef Name = RecordDecl->getName();
-return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr";
-  }
-  return false;
+  return isStdSmartPtr(MethodDecl->getParent());
 }
 
 bool isNullSmartPtr(const ProgramStateRef State, const MemRegion *ThisRegion) {
@@ -175,9 +192,37 @@
   return CD && CD->getConversionType()->isBooleanType();
 }
 
+const SmallVector BasicOstreamName = {"basic_ostream"};
+
+bool isStdBasicOstream(const Expr *E) {
+  const auto *RD = E->getType()->getAsCXXRecordDecl();
+  return hasStdClassWithName(RD, BasicOstreamName);

[PATCH] D105421: [analyzer] Handle << operator for std::unique_ptr

2021-07-08 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

I will be figuring out some tests tomorrow morning.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105421/new/

https://reviews.llvm.org/D105421

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D105421: [analyzer] Handle << operator for std::unique_ptr

2021-07-08 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 357307.
RedDocMD added a comment.

Little refactors


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105421/new/

https://reviews.llvm.org/D105421

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp

Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -68,6 +68,7 @@
   bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion,
 const MemRegion *OtherSmartPtrRegion) const;
   void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const;
+  bool handleOstreamOperator(const CallEvent &Call, CheckerContext &C) const;
 
   using SmartPtrMethodHandlerFn =
   void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const;
@@ -81,6 +82,31 @@
 
 REGISTER_MAP_WITH_PROGRAMSTATE(TrackedRegionMap, const MemRegion *, SVal)
 
+// Checks if RD has name in Names and is in std namespace
+static bool hasStdClassWithName(const CXXRecordDecl *RD,
+const ArrayRef &Names) {
+  if (!RD || !RD->getDeclContext()->isStdNamespace())
+return false;
+  if (RD->getDeclName().isIdentifier()) {
+StringRef Name = RD->getName();
+return llvm::any_of(Names, [&Name](StringRef GivenName) -> bool {
+  return Name == GivenName;
+});
+  }
+  return false;
+}
+
+const SmallVector StdPtrNames = {"shared_ptr", "unique_ptr",
+   "weak_ptr"};
+
+static bool isStdSmartPtr(const CXXRecordDecl *RD) {
+  return hasStdClassWithName(RD, StdPtrNames);
+}
+
+static bool isStdSmartPtr(const Expr *E) {
+  return isStdSmartPtr(E->getType()->getAsCXXRecordDecl());
+}
+
 // Define the inter-checker API.
 namespace clang {
 namespace ento {
@@ -89,16 +115,7 @@
   const auto *MethodDecl = dyn_cast_or_null(Call.getDecl());
   if (!MethodDecl || !MethodDecl->getParent())
 return false;
-
-  const auto *RecordDecl = MethodDecl->getParent();
-  if (!RecordDecl || !RecordDecl->getDeclContext()->isStdNamespace())
-return false;
-
-  if (RecordDecl->getDeclName().isIdentifier()) {
-StringRef Name = RecordDecl->getName();
-return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr";
-  }
-  return false;
+  return isStdSmartPtr(MethodDecl->getParent());
 }
 
 bool isNullSmartPtr(const ProgramStateRef State, const MemRegion *ThisRegion) {
@@ -175,9 +192,37 @@
   return CD && CD->getConversionType()->isBooleanType();
 }
 
+const SmallVector BasicOstreamName = {"basic_ostream"};
+
+bool isStdBasicOstream(const Expr *E) {
+  const auto *RD = E->getType()->getAsCXXRecordDecl();
+  return hasStdClassWithName(RD, BasicOstreamName);
+}
+
+bool isStdOstreamOperatorCall(const CallEvent &Call) {
+  if (Call.getNumArgs() != 2 ||
+  !Call.getDecl()->getDeclContext()->isStdNamespace())
+return false;
+  const auto *FC = dyn_cast(&Call);
+  if (!FC)
+return false;
+  const FunctionDecl *FD = FC->getDecl();
+  if (!FD->isOverloadedOperator())
+return false;
+  const OverloadedOperatorKind OOK = FD->getOverloadedOperator();
+  if (OOK != clang::OO_LessLess)
+return false;
+  return isStdSmartPtr(Call.getArgExpr(1)) &&
+ isStdBasicOstream(Call.getArgExpr(0));
+}
+
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
   ProgramStateRef State = C.getState();
+
+  if (isStdOstreamOperatorCall(Call))
+return handleOstreamOperator(Call, C);
+
   if (!smartptr::isStdSmartPtrCall(Call))
 return false;
 
@@ -272,6 +317,30 @@
   return C.isDifferent();
 }
 
+bool SmartPtrModeling::handleOstreamOperator(const CallEvent &Call,
+ CheckerContext &C) const {
+  // operator<< does not modify the smart pointer.
+  // And we don't really have much of modelling of basic_ostream.
+  // So, we are better off:
+  // 1) Invalidating the mem-region of the ostream object at hand.
+  // 2) Setting the SVal of the basic_ostream as the return value.
+  // Not very satisfying, but it gets the job done, and is better
+  // than the default handling. :)
+
+  ProgramStateRef State = C.getState();
+  const auto StreamVal = Call.getArgSVal(0);
+  const MemRegion *StreamThisRegion = StreamVal.getAsRegion();
+  if (!StreamThisRegion)
+return false;
+  State =
+  State->invalidateRegions({StreamThisRegion}, Call.getOriginExpr(),
+   C.blockCount(), C.getLocationContext(), false);
+  State =
+  State->BindExpr(Call.getOriginExpr(), C.getLocationContext(), StreamVal);
+  C.addTransition(State);
+  return true;
+}
+
 void SmartPtrModeling::checkDeadSymbols(SymbolReaper &SymReaper,
 CheckerContext &C) const {
   Program

[PATCH] D105421: [analyzer] Handle << operator for std::unique_ptr

2021-07-07 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:218-219
+
+  if (isStdOstreamOperatorCall(Call))
+return true;
+

NoQ wrote:
> When you're doing `evalCall` you're responsible for modeling *all* aspects of 
> the call. One does not simply say that they modeled all aspects of the call 
> when they didn't even set the return value :)
> 
> Similarly to how `make_unique` delegates work to the constructor of the 
> managed object and `~unique_ptr` delegates work to the destructor of the 
> managed object, I suspect this code could delegate work to 
> `basic_ostream::operator<<(T *)`. We don't yet have any facilities to 
> implement such logic yet (i.e., entering function call from a checker 
> callback).
> 
> Given that we don't do much modeling of `basic_ostream` yet, I think it's 
> perfectly fine to invalidate the stream entirely (which would be as precise 
> as whatever the default evaluation gave us) (see 
> `ProgramState::invalidateRegions`) and return the reference to the stream 
> (which is already better than what the default evaluation gave us); 
> additionally, we get extra precision because we don't invalidate the rest of 
> the heap. That's the bare minimum of what we have to do here if we are to do 
> anything at all.
> 
> This also gives some ideas of how to write tests for this patch.
> 
> That said, I suspect that this patch is not critical to enabling the checker 
> by default, because we probably already know that this method doesn't change 
> the inner pointer value (simply through not doing anything special) (and 
> accepting the smart pointer by `const` reference, so even if we implement 
> invalidation it will probably still "just work") (?).
Does this work?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105421/new/

https://reviews.llvm.org/D105421

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D105421: [analyzer] Handle << operator for std::unique_ptr

2021-07-07 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 357031.
RedDocMD added a comment.

Invalidating regions


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105421/new/

https://reviews.llvm.org/D105421

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp

Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -81,6 +81,20 @@
 
 REGISTER_MAP_WITH_PROGRAMSTATE(TrackedRegionMap, const MemRegion *, SVal)
 
+// Checks if RD has name in Names and is in std namespace
+bool hasStdClassWithName(const CXXRecordDecl *RD,
+ const SmallVectorImpl &Names) {
+  if (!RD || !RD->getDeclContext()->isStdNamespace())
+return false;
+  if (RD->getDeclName().isIdentifier()) {
+StringRef Name = RD->getName();
+return llvm::any_of(Names, [&Name](StringRef GivenName) -> bool {
+  return Name == GivenName;
+});
+  }
+  return false;
+}
+
 // Define the inter-checker API.
 namespace clang {
 namespace ento {
@@ -89,16 +103,16 @@
   const auto *MethodDecl = dyn_cast_or_null(Call.getDecl());
   if (!MethodDecl || !MethodDecl->getParent())
 return false;
+  return isStdSmartPtr(MethodDecl->getParent());
+}
 
-  const auto *RecordDecl = MethodDecl->getParent();
-  if (!RecordDecl || !RecordDecl->getDeclContext()->isStdNamespace())
-return false;
+bool isStdSmartPtr(const CXXRecordDecl *RD) {
+  return hasStdClassWithName(
+  RD, SmallVector{"shared_ptr", "unique_ptr", "weak_ptr"});
+}
 
-  if (RecordDecl->getDeclName().isIdentifier()) {
-StringRef Name = RecordDecl->getName();
-return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr";
-  }
-  return false;
+bool isStdSmartPtr(const Expr *E) {
+  return isStdSmartPtr(E->getType()->getAsCXXRecordDecl());
 }
 
 bool isNullSmartPtr(const ProgramStateRef State, const MemRegion *ThisRegion) {
@@ -175,9 +189,46 @@
   return CD && CD->getConversionType()->isBooleanType();
 }
 
+bool isStdBasicOstream(const Expr *E) {
+  const auto *RD = E->getType()->getAsCXXRecordDecl();
+  return hasStdClassWithName(RD, SmallVector{"basic_ostream"});
+}
+
+bool isStdOstreamOperatorCall(const CallEvent &Call) {
+  if (Call.getNumArgs() != 2 ||
+  !Call.getDecl()->getDeclContext()->isStdNamespace())
+return false;
+  const auto *FC = dyn_cast(&Call);
+  if (!FC)
+return false;
+  const FunctionDecl *FD = FC->getDecl();
+  if (!FD->isOverloadedOperator())
+return false;
+  const OverloadedOperatorKind OOK = FD->getOverloadedOperator();
+  if (OOK != clang::OO_LessLess)
+return false;
+  return smartptr::isStdSmartPtr(Call.getArgExpr(1)) &&
+ isStdBasicOstream(Call.getArgExpr(0));
+}
+
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
   ProgramStateRef State = C.getState();
+
+  if (isStdOstreamOperatorCall(Call)) {
+const auto StreamVal = Call.getArgSVal(0);
+const MemRegion *StreamThisRegion = StreamVal.getAsRegion();
+assert(StreamThisRegion &&
+   "expected to retrieve this pointer of basic_ostream");
+State =
+State->invalidateRegions({StreamThisRegion}, Call.getOriginExpr(),
+ C.blockCount(), C.getLocationContext(), false);
+State = State->BindExpr(Call.getOriginExpr(), C.getLocationContext(),
+StreamVal);
+C.addTransition(State);
+return true;
+  }
+
   if (!smartptr::isStdSmartPtrCall(Call))
 return false;
 
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
@@ -22,6 +22,8 @@
 
 /// Returns true if the event call is on smart pointer.
 bool isStdSmartPtrCall(const CallEvent &Call);
+bool isStdSmartPtr(const CXXRecordDecl *RD);
+bool isStdSmartPtr(const Expr *E);
 
 /// Returns whether the smart pointer is null or not.
 bool isNullSmartPtr(const ProgramStateRef State, const MemRegion *ThisRegion);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D104616: [analyzer] Model comparision methods of std::unique_ptr

2021-07-05 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 356526.
RedDocMD added a comment.

Major bug fix


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
  clang/test/Analysis/Inputs/system-header-simulator-cxx.h
  clang/test/Analysis/smart-ptr.cpp

Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -457,3 +457,52 @@
 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   }
 }
+
+// The following is a silly function,
+// but serves to test if we are picking out
+// standard comparision functions from custom ones.
+template 
+bool operator<(std::unique_ptr &x, double d);
+
+void uniquePtrComparision(std::unique_ptr unknownPtr) {
+  auto ptr = std::unique_ptr(new int(13));
+  auto nullPtr = std::unique_ptr();
+  auto otherPtr = std::unique_ptr(new int(29));
+
+  clang_analyzer_eval(ptr == ptr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > ptr);  // expected-warning{{FALSE}}
+  clang_analyzer_eval(ptr <= ptr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(nullPtr <= unknownPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(unknownPtr >= nullPtr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != otherPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > nullPtr);   // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != nullptr);// expected-warning{{TRUE}}
+  clang_analyzer_eval(nullPtr != nullptr);// expected-warning{{FALSE}}
+  clang_analyzer_eval(nullptr <= unknownPtr); // expected-warning{{TRUE}}
+}
+
+void uniquePtrComparisionStateSplitting(std::unique_ptr unknownPtr) {
+  auto ptr = std::unique_ptr(new int(13));
+
+  clang_analyzer_eval(ptr > unknownPtr); // expected-warning{{TRUE}}
+  // expected-warning@-1{{FALSE}}
+}
+
+void uniquePtrComparisionDifferingTypes(std::unique_ptr unknownPtr) {
+  auto ptr = std::unique_ptr(new int(13));
+  auto nullPtr = std::unique_ptr();
+  auto otherPtr = std::unique_ptr(new double(3.14));
+
+  clang_analyzer_eval(nullPtr <= unknownPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(unknownPtr >= nullPtr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != otherPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > nullPtr);   // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != nullptr);// expected-warning{{TRUE}}
+  clang_analyzer_eval(nullPtr != nullptr);// expected-warning{{FALSE}}
+  clang_analyzer_eval(nullptr <= unknownPtr); // expected-warning{{TRUE}}
+}
Index: clang/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -978,6 +978,61 @@
 void swap(unique_ptr &x, unique_ptr &y) noexcept {
   x.swap(y);
 }
+
+template 
+bool operator==(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator!=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator<(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator>(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator<=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator>=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator==(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator!=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator<(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator>(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator<=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator>=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator==(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator!=(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator>(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator<(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator>=(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator<=(nullptr_t x, const unique_ptr &y);
+
 } // namespace std
 #endif
 
Index: clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
@@ -148,5 +148,39 @@
   return IntValue.getSExtValue();
 }
 
+OperatorKind operationKindFromOverloadedOperator(OverloadedOperatorKind OOK,
+ bool IsBinary) {
+  llvm::StringMap BinOps{
+#defin

[PATCH] D105421: [analyzer] Handle << operator for std::unique_ptr

2021-07-05 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD created this revision.
RedDocMD added reviewers: NoQ, vsavchenko, xazax.hun, teemperor.
Herald added subscribers: manas, steakhal, ASDenysPetrov, martong, dkrupp, 
donat.nagy, Szelethus, mikhail.ramalho, a.sidorin, rnkovacs, szepet, 
baloghadamsoftware.
RedDocMD requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This patch handles the `<<` operator defined for `std::unique_ptr` in
the std namespace (ignores custom overloads of the operator).


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D105421

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp


Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -81,6 +81,20 @@
 
 REGISTER_MAP_WITH_PROGRAMSTATE(TrackedRegionMap, const MemRegion *, SVal)
 
+// Checks if RD has name in Names and is in std namespace
+bool hasStdClassWithName(const CXXRecordDecl *RD,
+ const SmallVectorImpl &Names) {
+  if (!RD || !RD->getDeclContext()->isStdNamespace())
+return false;
+  if (RD->getDeclName().isIdentifier()) {
+StringRef Name = RD->getName();
+return llvm::any_of(Names, [&Name](StringRef GivenName) -> bool {
+  return Name == GivenName;
+});
+  }
+  return false;
+}
+
 // Define the inter-checker API.
 namespace clang {
 namespace ento {
@@ -89,16 +103,16 @@
   const auto *MethodDecl = dyn_cast_or_null(Call.getDecl());
   if (!MethodDecl || !MethodDecl->getParent())
 return false;
+  return isStdSmartPtr(MethodDecl->getParent());
+}
 
-  const auto *RecordDecl = MethodDecl->getParent();
-  if (!RecordDecl || !RecordDecl->getDeclContext()->isStdNamespace())
-return false;
+bool isStdSmartPtr(const CXXRecordDecl *RD) {
+  return hasStdClassWithName(
+  RD, SmallVector{"shared_ptr", "unique_ptr", "weak_ptr"});
+}
 
-  if (RecordDecl->getDeclName().isIdentifier()) {
-StringRef Name = RecordDecl->getName();
-return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr";
-  }
-  return false;
+bool isStdSmartPtr(const Expr *E) {
+  return isStdSmartPtr(E->getType()->getAsCXXRecordDecl());
 }
 
 bool isNullSmartPtr(const ProgramStateRef State, const MemRegion *ThisRegion) {
@@ -175,9 +189,35 @@
   return CD && CD->getConversionType()->isBooleanType();
 }
 
+bool isStdBasicOstream(const Expr *E) {
+  const auto *RD = E->getType()->getAsCXXRecordDecl();
+  return hasStdClassWithName(RD, SmallVector{"basic_ostream"});
+}
+
+bool isStdOstreamOperatorCall(const CallEvent &Call) {
+  if (Call.getNumArgs() != 2 ||
+  !Call.getDecl()->getDeclContext()->isStdNamespace())
+return false;
+  const auto *FC = dyn_cast(&Call);
+  if (!FC)
+return false;
+  const FunctionDecl *FD = FC->getDecl();
+  if (!FD->isOverloadedOperator())
+return false;
+  const OverloadedOperatorKind OOK = FD->getOverloadedOperator();
+  if (OOK != clang::OO_LessLess)
+return false;
+  return smartptr::isStdSmartPtr(Call.getArgExpr(1)) &&
+ isStdBasicOstream(Call.getArgExpr(0));
+}
+
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
   ProgramStateRef State = C.getState();
+
+  if (isStdOstreamOperatorCall(Call))
+return true;
+
   if (!smartptr::isStdSmartPtrCall(Call))
 return false;
 
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
@@ -22,6 +22,8 @@
 
 /// Returns true if the event call is on smart pointer.
 bool isStdSmartPtrCall(const CallEvent &Call);
+bool isStdSmartPtr(const CXXRecordDecl *RD);
+bool isStdSmartPtr(const Expr *E);
 
 /// Returns whether the smart pointer is null or not.
 bool isNullSmartPtr(const ProgramStateRef State, const MemRegion *ThisRegion);


Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -81,6 +81,20 @@
 
 REGISTER_MAP_WITH_PROGRAMSTATE(TrackedRegionMap, const MemRegion *, SVal)
 
+// Checks if RD has name in Names and is in std namespace
+bool hasStdClassWithName(const CXXRecordDecl *RD,
+ const SmallVectorImpl &Names) {
+  if (!RD || !RD->getDeclContext()->isStdNamespace())
+return false;
+  if (RD->getDeclName().isIdentifier()) {
+StringRef Name = RD->getName();
+return llvm::any_of(Names, [&Name](StringRef GivenName) -> bool {
+  return Name == GivenName;
+});
+  }
+  return false;
+}
+
 // Define the inter-checker API.
 namespace clang {
 namespace ento {
@@

[PATCH] D104616: [analyzer] Model comparision methods of std::unique_ptr

2021-07-04 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 356371.
RedDocMD added a comment.

Little refactors


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
  clang/test/Analysis/Inputs/system-header-simulator-cxx.h
  clang/test/Analysis/smart-ptr.cpp

Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -457,3 +457,52 @@
 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   }
 }
+
+// The following is a silly function,
+// but serves to test if we are picking out
+// standard comparision functions from custom ones.
+template 
+bool operator<(std::unique_ptr &x, double d);
+
+void uniquePtrComparision(std::unique_ptr unknownPtr) {
+  auto ptr = std::unique_ptr(new int(13));
+  auto nullPtr = std::unique_ptr();
+  auto otherPtr = std::unique_ptr(new int(29));
+
+  clang_analyzer_eval(ptr == ptr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > ptr);  // expected-warning{{FALSE}}
+  clang_analyzer_eval(ptr <= ptr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(nullPtr <= unknownPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(unknownPtr >= nullPtr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != otherPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > nullPtr);   // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != nullptr);// expected-warning{{TRUE}}
+  clang_analyzer_eval(nullPtr != nullptr);// expected-warning{{FALSE}}
+  clang_analyzer_eval(nullptr <= unknownPtr); // expected-warning{{TRUE}}
+}
+
+void uniquePtrComparisionStateSplitting(std::unique_ptr unknownPtr) {
+  auto ptr = std::unique_ptr(new int(13));
+
+  clang_analyzer_eval(ptr > unknownPtr); // expected-warning{{TRUE}}
+  // expected-warning@-1{{FALSE}}
+}
+
+void uniquePtrComparisionDifferingTypes(std::unique_ptr unknownPtr) {
+  auto ptr = std::unique_ptr(new int(13));
+  auto nullPtr = std::unique_ptr();
+  auto otherPtr = std::unique_ptr(new double(3.14));
+
+  clang_analyzer_eval(nullPtr <= unknownPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(unknownPtr >= nullPtr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != otherPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > nullPtr);   // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != nullptr);// expected-warning{{TRUE}}
+  clang_analyzer_eval(nullPtr != nullptr);// expected-warning{{FALSE}}
+  clang_analyzer_eval(nullptr <= unknownPtr); // expected-warning{{TRUE}}
+}
Index: clang/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -978,6 +978,61 @@
 void swap(unique_ptr &x, unique_ptr &y) noexcept {
   x.swap(y);
 }
+
+template 
+bool operator==(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator!=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator<(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator>(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator<=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator>=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator==(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator!=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator<(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator>(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator<=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator>=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator==(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator!=(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator>(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator<(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator>=(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator<=(nullptr_t x, const unique_ptr &y);
+
 } // namespace std
 #endif
 
Index: clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
===
--- clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
@@ -148,5 +148,39 @@
   return IntValue.getSExtValue();
 }
 
+OperatorKind operationKindFromOverloadedOperator(OverloadedOperatorKind OOK,
+ bool IsBinary) {
+  llvm::StringMap BinOps{
+#de

[PATCH] D104616: [analyzer] Model comparision methods of std::unique_ptr

2021-07-04 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD marked 4 inline comments as done.
RedDocMD added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:316
+
+class OperatorKind {
+  union {

NoQ wrote:
> One good place to put this may be `CheckerHelpers.h`. This is where we dump 
> all the stuff that's probably useful in multiple checkers but not in other 
> places.
> 
> I also wonder if you plan to support unary operators. The interesting part 
> about them is that they are sometimes ambiguous to binary operators in their 
> string representation, eg. `-`.
I guess passing a parameter to chose operator arity should work.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D104616: [analyzer] Model comparision methods of std::unique_ptr

2021-07-02 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 356226.
RedDocMD added a comment.

Simplify SVal on state split, other refactors


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/test/Analysis/Inputs/system-header-simulator-cxx.h
  clang/test/Analysis/smart-ptr.cpp

Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -457,3 +457,36 @@
 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   }
 }
+
+// The following is a silly function,
+// but serves to test if we are picking out
+// standard comparision functions from custom ones.
+template 
+bool operator<(std::unique_ptr &x, double d);
+
+void uniquePtrComparision(std::unique_ptr unknownPtr) {
+  auto ptr = std::unique_ptr(new int(13));
+  auto nullPtr = std::unique_ptr();
+  auto otherPtr = std::unique_ptr(new int(29));
+
+  clang_analyzer_eval(ptr == ptr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > ptr);  // expected-warning{{FALSE}}
+  clang_analyzer_eval(ptr <= ptr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(nullPtr <= unknownPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(unknownPtr >= nullPtr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != otherPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > nullPtr);   // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != nullptr);// expected-warning{{TRUE}}
+  clang_analyzer_eval(nullPtr != nullptr);// expected-warning{{FALSE}}
+  clang_analyzer_eval(nullptr <= unknownPtr); // expected-warning{{TRUE}}
+}
+
+void uniquePtrComparisionStateSplitting(std::unique_ptr unknownPtr) {
+  auto ptr = std::unique_ptr(new int(13));
+
+  clang_analyzer_eval(ptr > unknownPtr); // expected-warning{{TRUE}}
+  // expected-warning@-1{{FALSE}}
+}
Index: clang/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -978,6 +978,61 @@
 void swap(unique_ptr &x, unique_ptr &y) noexcept {
   x.swap(y);
 }
+
+template 
+bool operator==(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator!=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator<(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator>(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator<=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator>=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator==(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator!=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator<(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator>(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator<=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator>=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator==(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator!=(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator>(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator<(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator>=(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator<=(nullptr_t x, const unique_ptr &y);
+
 } // namespace std
 #endif
 
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -29,7 +29,10 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/ErrorHandling.h"
 #include 
+#include 
 
 using namespace clang;
 using namespace ento;
@@ -68,6 +71,10 @@
   bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion,
 const MemRegion *OtherSmartPtrRegion) const;
   void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const;
+  bool handleComparisionOp(const CallEvent &Call, CheckerContext &C) const;
+  std::pair
+  retrieveOrConjureInnerPtrVal(const MemRegion *ThisRegion, const Expr *E,
+   QualType Type, CheckerContext &C) const;
 
   using SmartPtrMethodHandlerFn =
   void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const;
@@ -89,18 +96,24 @@
   const auto *MethodDecl = dyn_cast_or_null(Call.getDecl

[PATCH] D104616: [analyzer] Model comparision methods of std::unique_ptr

2021-07-02 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD marked 3 inline comments as done.
RedDocMD added inline comments.



Comment at: clang/test/Analysis/smart-ptr.cpp:484
+  clang_analyzer_eval(nullPtr != nullptr);// expected-warning{{FALSE}}
+  clang_analyzer_eval(nullptr <= unknownPtr); // expected-warning{{TRUE}}
+}

xazax.hun wrote:
> I do not see test cases where the path is actually split. Would you add some?
Oops! I removed two tests emitting UNKNOWN and forgot to put them back in.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D104616: [analyzer] Model comparision methods of std::unique_ptr

2021-07-02 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 356128.
RedDocMD added a comment.

Performing state split on normal comparision ops


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/test/Analysis/Inputs/system-header-simulator-cxx.h
  clang/test/Analysis/smart-ptr.cpp

Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -457,3 +457,29 @@
 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   }
 }
+
+// The following is a silly function,
+// but serves to test if we are picking out
+// standard comparision functions from custom ones.
+template 
+bool operator<(std::unique_ptr &x, double d);
+
+void uniquePtrComparision(std::unique_ptr unknownPtr) {
+  auto ptr = std::unique_ptr(new int(13));
+  auto nullPtr = std::unique_ptr();
+  auto otherPtr = std::unique_ptr(new int(29));
+
+  clang_analyzer_eval(ptr == ptr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > ptr);  // expected-warning{{FALSE}}
+  clang_analyzer_eval(ptr <= ptr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(nullPtr <= unknownPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(unknownPtr >= nullPtr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != otherPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > nullPtr);   // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != nullptr);// expected-warning{{TRUE}}
+  clang_analyzer_eval(nullPtr != nullptr);// expected-warning{{FALSE}}
+  clang_analyzer_eval(nullptr <= unknownPtr); // expected-warning{{TRUE}}
+}
Index: clang/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -978,6 +978,61 @@
 void swap(unique_ptr &x, unique_ptr &y) noexcept {
   x.swap(y);
 }
+
+template 
+bool operator==(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator!=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator<(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator>(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator<=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator>=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator==(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator!=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator<(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator>(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator<=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator>=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator==(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator!=(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator>(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator<(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator>=(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator<=(nullptr_t x, const unique_ptr &y);
+
 } // namespace std
 #endif
 
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -29,7 +29,10 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/ErrorHandling.h"
 #include 
+#include 
 
 using namespace clang;
 using namespace ento;
@@ -68,6 +71,10 @@
   bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion,
 const MemRegion *OtherSmartPtrRegion) const;
   void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const;
+  bool handleComparisionOp(const CallEvent &Call, CheckerContext &C) const;
+  std::pair
+  retrieveOrConjureInnerPtrVal(const MemRegion *ThisRegion, const Expr *E,
+   QualType Type, CheckerContext &C) const;
 
   using SmartPtrMethodHandlerFn =
   void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const;
@@ -89,18 +96,24 @@
   const auto *MethodDecl = dyn_cast_or_null(Call.getDecl());
   if (!MethodDecl || !MethodDecl->getParent())
 return false;
+  return isStdSmartPtr(MethodDecl->getParent());
+}
 
-  const auto *RecordDecl = MethodDecl->getParent();
-  if (!RecordDecl || !RecordDecl->getDeclCo

[PATCH] D104616: [analyzer] Model comparision methods of std::unique_ptr

2021-06-30 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:443-446
+  auto RetVal = C.getSValBuilder().evalBinOp(
+  State, BOK, FirstPtrVal, SecondPtrVal, Call.getResultType());
+  State = State->BindExpr(Call.getOriginExpr(), C.getLocationContext(), 
RetVal);
+  C.addTransition(State);

NoQ wrote:
> Because these operators are pure boolean functions, a state split would be 
> justified. It's pointless to call the operator unless both return values are 
> feasible. I think you should do an `assume()` and transition into both states.
> 
> It might also make sense to consult `-analyzer-config eagerly-assume=` before 
> doing it but it sounds like this option will stays true forever and we might 
> as well remove it.
> 
> The spaceship operator is obviously an exceptional case. Invocation of the 
> spaceship operator isn't a good indication that all three return values are 
> feasible, might be only two.
I think this comment has got displaced from its original location from 
subsequent updates. Could you please clarify?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D104616: [analyzer] Model comparision methods of std::unique_ptr

2021-06-30 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 355458.
RedDocMD added a comment.

Refactored out common block


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/test/Analysis/Inputs/system-header-simulator-cxx.h
  clang/test/Analysis/smart-ptr.cpp

Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -457,3 +457,32 @@
 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   }
 }
+
+// The following is a silly function,
+// but serves to test if we are picking out
+// standard comparision functions from custom ones.
+template 
+bool operator<(std::unique_ptr &x, double d);
+
+void uniquePtrComparision(std::unique_ptr unknownPtr) {
+  auto ptr = std::unique_ptr(new int(13));
+  auto nullPtr = std::unique_ptr();
+  auto otherPtr = std::unique_ptr(new int(29));
+
+  clang_analyzer_eval(ptr == ptr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > ptr);  // expected-warning{{FALSE}}
+  clang_analyzer_eval(ptr <= ptr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(nullPtr <= unknownPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(unknownPtr >= nullPtr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != otherPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > nullPtr);   // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != nullptr);// expected-warning{{TRUE}}
+  clang_analyzer_eval(nullPtr != nullptr);// expected-warning{{FALSE}}
+  clang_analyzer_eval(nullptr <= unknownPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(nullptr < unknownPtr);  // expected-warning{{UNKNOWN}}
+
+  clang_analyzer_eval(ptr < 2.0); // expected-warning{{UNKNOWN}}
+}
Index: clang/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -978,6 +978,61 @@
 void swap(unique_ptr &x, unique_ptr &y) noexcept {
   x.swap(y);
 }
+
+template 
+bool operator==(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator!=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator<(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator>(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator<=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator>=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator==(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator!=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator<(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator>(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator<=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator>=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator==(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator!=(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator>(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator<(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator>=(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator<=(nullptr_t x, const unique_ptr &y);
+
 } // namespace std
 #endif
 
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -29,7 +29,10 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/ErrorHandling.h"
 #include 
+#include 
 
 using namespace clang;
 using namespace ento;
@@ -68,6 +71,10 @@
   bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion,
 const MemRegion *OtherSmartPtrRegion) const;
   void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const;
+  bool handleComparisionOp(const CallEvent &Call, CheckerContext &C) const;
+  std::pair
+  retrieveOrConjureInnerPtrVal(const MemRegion *ThisRegion, const Expr *E,
+   QualType Type, CheckerContext &C) const;
 
   using SmartPtrMethodHandlerFn =
   void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const;
@@ -89,18 +96,24 @@
   const auto *MethodDecl = dyn_cast_or_null(Call.getDecl());
   if (!MethodDecl || !MethodDecl->getParent())
 return false;
+  return isStdSmartPtr(Met

[PATCH] D104616: [analyzer] Model comparision methods of std::unique_ptr

2021-06-29 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 355445.
RedDocMD added a comment.

Fixed bug in enum conversion


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/test/Analysis/Inputs/system-header-simulator-cxx.h
  clang/test/Analysis/smart-ptr.cpp

Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -457,3 +457,32 @@
 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   }
 }
+
+// The following is a silly function,
+// but serves to test if we are picking out
+// standard comparision functions from custom ones.
+template 
+bool operator<(std::unique_ptr &x, double d);
+
+void uniquePtrComparision(std::unique_ptr unknownPtr) {
+  auto ptr = std::unique_ptr(new int(13));
+  auto nullPtr = std::unique_ptr();
+  auto otherPtr = std::unique_ptr(new int(29));
+
+  clang_analyzer_eval(ptr == ptr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > ptr);  // expected-warning{{FALSE}}
+  clang_analyzer_eval(ptr <= ptr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(nullPtr <= unknownPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(unknownPtr >= nullPtr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != otherPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > nullPtr);   // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != nullptr);// expected-warning{{TRUE}}
+  clang_analyzer_eval(nullPtr != nullptr);// expected-warning{{FALSE}}
+  clang_analyzer_eval(nullptr <= unknownPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(nullptr < unknownPtr);  // expected-warning{{UNKNOWN}}
+
+  clang_analyzer_eval(ptr < 2.0); // expected-warning{{UNKNOWN}}
+}
Index: clang/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -978,6 +978,61 @@
 void swap(unique_ptr &x, unique_ptr &y) noexcept {
   x.swap(y);
 }
+
+template 
+bool operator==(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator!=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator<(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator>(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator<=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator>=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator==(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator!=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator<(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator>(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator<=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator>=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator==(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator!=(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator>(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator<(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator>=(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator<=(nullptr_t x, const unique_ptr &y);
+
 } // namespace std
 #endif
 
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -29,7 +29,10 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/ErrorHandling.h"
 #include 
+#include 
 
 using namespace clang;
 using namespace ento;
@@ -68,6 +71,7 @@
   bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion,
 const MemRegion *OtherSmartPtrRegion) const;
   void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const;
+  bool handleComparisionOp(const CallEvent &Call, CheckerContext &C) const;
 
   using SmartPtrMethodHandlerFn =
   void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const;
@@ -89,18 +93,24 @@
   const auto *MethodDecl = dyn_cast_or_null(Call.getDecl());
   if (!MethodDecl || !MethodDecl->getParent())
 return false;
+  return isStdSmartPtr(MethodDecl->getParent());
+}
 
-  const auto *RecordDecl = MethodDecl->getParent();
-  if (!RecordDecl || !RecordDecl->getDeclContext()->isStdNamespace())
+bool isSt

[PATCH] D104616: [analyzer] Model comparision methods of std::unique_ptr

2021-06-29 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

Sorry for not updating. Was down with fever.
This patch does *not* work now. `operationKindFromOverloadedOperator` is broken 
because the maps don't get populated. I am not entirely sure why this is 
happening.
Will try to fix tomorrow. @NoQ, @vsavchenko, @xazax.hun, @teemperor do you have 
a hunch as to why this may be happening?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D104616: [analyzer][WIP] Model comparision methods of std::unique_ptr

2021-06-26 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 354695.
RedDocMD added a comment.

First try at implementing conversion function from OverloadedOperatorKind to 
BinaryOperatorKind


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/test/Analysis/Inputs/system-header-simulator-cxx.h
  clang/test/Analysis/smart-ptr.cpp

Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -457,3 +457,32 @@
 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   }
 }
+
+// The following is a silly function,
+// but serves to test if we are picking out
+// standard comparision functions from custom ones.
+template 
+bool operator<(std::unique_ptr &x, double d);
+
+void uniquePtrComparision(std::unique_ptr unknownPtr) {
+  auto ptr = std::unique_ptr(new int(13));
+  auto nullPtr = std::unique_ptr();
+  auto otherPtr = std::unique_ptr(new int(29));
+
+  clang_analyzer_eval(ptr == ptr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > ptr);  // expected-warning{{FALSE}}
+  clang_analyzer_eval(ptr <= ptr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(nullPtr <= unknownPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(unknownPtr >= nullPtr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != otherPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > nullPtr);   // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != nullptr);// expected-warning{{TRUE}}
+  clang_analyzer_eval(nullPtr != nullptr);// expected-warning{{FALSE}}
+  clang_analyzer_eval(nullptr <= unknownPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(nullptr < unknownPtr);  // expected-warning{{UNKNOWN}}
+
+  clang_analyzer_eval(ptr < 2.0); // expected-warning{{UNKNOWN}}
+}
Index: clang/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -978,6 +978,61 @@
 void swap(unique_ptr &x, unique_ptr &y) noexcept {
   x.swap(y);
 }
+
+template 
+bool operator==(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator!=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator<(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator>(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator<=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator>=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator==(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator!=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator<(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator>(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator<=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator>=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator==(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator!=(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator>(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator<(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator>=(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator<=(nullptr_t x, const unique_ptr &y);
+
 } // namespace std
 #endif
 
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -29,7 +29,10 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/ErrorHandling.h"
 #include 
+#include 
 
 using namespace clang;
 using namespace ento;
@@ -68,6 +71,7 @@
   bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion,
 const MemRegion *OtherSmartPtrRegion) const;
   void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const;
+  bool handleComparisionOp(const CallEvent &Call, CheckerContext &C) const;
 
   using SmartPtrMethodHandlerFn =
   void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const;
@@ -89,18 +93,24 @@
   const auto *MethodDecl = dyn_cast_or_null(Call.getDecl());
   if (!MethodDecl || !MethodDecl->getParent())
 return false;
+  return isStdSmartPtr(MethodDecl->getParent());
+}
 
-  const auto *RecordDecl = MethodDecl->getParent();
-  if (!Recor

[PATCH] D104616: [analyzer][WIP] Model comparision methods of std::unique_ptr

2021-06-26 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added inline comments.



Comment at: clang/test/Analysis/smart-ptr.cpp:466
+
+  clang_analyzer_eval(ptr == ptr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > ptr);  // expected-warning{{FALSE}}

xazax.hun wrote:
> RedDocMD wrote:
> > xazax.hun wrote:
> > > Putting tests like this on the same path can be risky. Tests might split 
> > > the execution path (maybe not now, but in the future). I think it might 
> > > be more future proof to have a large switch statement that switches on an 
> > > unknown value and put the tests in separate cases. 
> > I didn't quite get you.
> You remember this in the other patch:
> ```
> member-constructor.cpp:15:5: warning: FALSE [debug.ExprInspection]
> clang_analyzer_eval(*P->p == 0);
> ^~~
> member-constructor.cpp:15:25: note: Assuming the condition is false
> clang_analyzer_eval(*P->p == 0);
> ^~
> member-constructor.cpp:15:5: note: FALSE
> clang_analyzer_eval(*P->p == 0);
> ^~~
> member-constructor.cpp:15:5: warning: TRUE [debug.ExprInspection]
> clang_analyzer_eval(*P->p == 0);
> ^~~
> member-constructor.cpp:15:25: note: Assuming the condition is true
> clang_analyzer_eval(*P->p == 0);
> ^~
> member-constructor.cpp:15:5: note: TRUE
> clang_analyzer_eval(*P->p == 0);
> ^~~
> 2 warnings generated.
> ```
> 
> It looks like this does not happen for overloaded comparison operators at the 
> moment. But we might want to do that in the future (@NoW what do you think). 
> I was wondering, if we want to future proof these test cases for that 
> behavior. But looking at the test cases again, you only have two, where the 
> expected result is unknown, and they are at the very end. So feel free to 
> ignore this and leave the code as is.
Then perhaps I should leave a comment to indicate this possibility.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D104616: [analyzer][WIP] Model comparision methods of std::unique_ptr

2021-06-25 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 354460.
RedDocMD added a comment.

Removed dump statement


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/test/Analysis/Inputs/system-header-simulator-cxx.h
  clang/test/Analysis/smart-ptr.cpp

Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -457,3 +457,32 @@
 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   }
 }
+
+// The following is a silly function,
+// but serves to test if we are picking out
+// standard comparision functions from custom ones.
+template 
+bool operator<(std::unique_ptr &x, double d);
+
+void uniquePtrComparision(std::unique_ptr unknownPtr) {
+  auto ptr = std::unique_ptr(new int(13));
+  auto nullPtr = std::unique_ptr();
+  auto otherPtr = std::unique_ptr(new int(29));
+
+  clang_analyzer_eval(ptr == ptr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > ptr);  // expected-warning{{FALSE}}
+  clang_analyzer_eval(ptr <= ptr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(nullPtr <= unknownPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(unknownPtr >= nullPtr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != otherPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > nullPtr);   // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != nullptr);// expected-warning{{TRUE}}
+  clang_analyzer_eval(nullPtr != nullptr);// expected-warning{{FALSE}}
+  clang_analyzer_eval(nullptr <= unknownPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(nullptr < unknownPtr);  // expected-warning{{UNKNOWN}}
+
+  clang_analyzer_eval(ptr < 2.0); // expected-warning{{UNKNOWN}}
+}
Index: clang/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -978,6 +978,61 @@
 void swap(unique_ptr &x, unique_ptr &y) noexcept {
   x.swap(y);
 }
+
+template 
+bool operator==(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator!=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator<(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator>(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator<=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator>=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator==(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator!=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator<(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator>(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator<=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator>=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator==(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator!=(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator>(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator<(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator>=(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator<=(nullptr_t x, const unique_ptr &y);
+
 } // namespace std
 #endif
 
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -68,6 +68,7 @@
   bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion,
 const MemRegion *OtherSmartPtrRegion) const;
   void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const;
+  bool handleComparisionOp(const CallEvent &Call, CheckerContext &C) const;
 
   using SmartPtrMethodHandlerFn =
   void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const;
@@ -89,18 +90,24 @@
   const auto *MethodDecl = dyn_cast_or_null(Call.getDecl());
   if (!MethodDecl || !MethodDecl->getParent())
 return false;
+  return isStdSmartPtr(MethodDecl->getParent());
+}
 
-  const auto *RecordDecl = MethodDecl->getParent();
-  if (!RecordDecl || !RecordDecl->getDeclContext()->isStdNamespace())
+bool isStdSmartPtr(const CXXRecordDecl *RD) {
+  if (!RD || !RD->getDeclContext()->isStdNamespace())
 return false;
 
-  if (RecordDecl->getDeclName().isIdentifier()) {
-StringRef Name = RecordDecl->getName();
+  if (RD->getDeclName().isIdentifier()) {
+StringRef Name = RD->getName();
 return Name == "shared_ptr" || Name == "unique_ptr" || Name == "we

[PATCH] D104616: [analyzer][WIP] Model comparision methods of std::unique_ptr

2021-06-25 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added inline comments.



Comment at: clang/test/Analysis/smart-ptr.cpp:466
+
+  clang_analyzer_eval(ptr == ptr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > ptr);  // expected-warning{{FALSE}}

xazax.hun wrote:
> Putting tests like this on the same path can be risky. Tests might split the 
> execution path (maybe not now, but in the future). I think it might be more 
> future proof to have a large switch statement that switches on an unknown 
> value and put the tests in separate cases. 
I didn't quite get you.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D104616: [analyzer][WIP] Model comparision methods of std::unique_ptr

2021-06-25 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 354459.
RedDocMD added a comment.

Refactored code, removed duplications, fixed tests, added some more


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/test/Analysis/Inputs/system-header-simulator-cxx.h
  clang/test/Analysis/smart-ptr.cpp

Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -457,3 +457,32 @@
 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   }
 }
+
+// The following is a silly function,
+// but serves to test if we are picking out
+// standard comparision functions from custom ones.
+template 
+bool operator<(std::unique_ptr &x, double d);
+
+void uniquePtrComparision(std::unique_ptr unknownPtr) {
+  auto ptr = std::unique_ptr(new int(13));
+  auto nullPtr = std::unique_ptr();
+  auto otherPtr = std::unique_ptr(new int(29));
+
+  clang_analyzer_eval(ptr == ptr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > ptr);  // expected-warning{{FALSE}}
+  clang_analyzer_eval(ptr <= ptr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(nullPtr <= unknownPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(unknownPtr >= nullPtr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != otherPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > nullPtr);   // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != nullptr);// expected-warning{{TRUE}}
+  clang_analyzer_eval(nullPtr != nullptr);// expected-warning{{FALSE}}
+  clang_analyzer_eval(nullptr <= unknownPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(nullptr < unknownPtr);  // expected-warning{{UNKNOWN}}
+
+  clang_analyzer_eval(ptr < 2.0); // expected-warning{{UNKNOWN}}
+}
Index: clang/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -978,6 +978,61 @@
 void swap(unique_ptr &x, unique_ptr &y) noexcept {
   x.swap(y);
 }
+
+template 
+bool operator==(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator!=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator<(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator>(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator<=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator>=(const unique_ptr &x, const unique_ptr &y);
+
+template 
+bool operator==(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator!=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator<(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator>(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator<=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator>=(const unique_ptr &x, nullptr_t y);
+
+template 
+bool operator==(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator!=(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator>(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator<(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator>=(nullptr_t x, const unique_ptr &y);
+
+template 
+bool operator<=(nullptr_t x, const unique_ptr &y);
+
 } // namespace std
 #endif
 
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -68,6 +68,7 @@
   bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion,
 const MemRegion *OtherSmartPtrRegion) const;
   void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const;
+  bool handleComparisionOp(const CallEvent &Call, CheckerContext &C) const;
 
   using SmartPtrMethodHandlerFn =
   void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const;
@@ -89,18 +90,24 @@
   const auto *MethodDecl = dyn_cast_or_null(Call.getDecl());
   if (!MethodDecl || !MethodDecl->getParent())
 return false;
+  return isStdSmartPtr(MethodDecl->getParent());
+}
 
-  const auto *RecordDecl = MethodDecl->getParent();
-  if (!RecordDecl || !RecordDecl->getDeclContext()->isStdNamespace())
+bool isStdSmartPtr(const CXXRecordDecl *RD) {
+  if (!RD || !RD->getDeclContext()->isStdNamespace())
 return false;
 
-  if (RecordDecl->getDeclName().isIdentifier()) {
-StringRef Name = RecordDecl->getName();
+  if (RD->getDeclName().isIdentifier()) {
+StringRef Name = RD->getName();
 return Name == "share

[PATCH] D104616: [analyzer][WIP] Model comparision methods of std::unique_ptr

2021-06-25 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD marked 4 inline comments as done.
RedDocMD added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:301
+  const OverloadedOperatorKind OOK = FD->getOverloadedOperator();
+  if (!(OOK == OO_Equal || OOK == OO_ExclaimEqual || OOK == OO_Less ||
+OOK == OO_LessEqual || OOK == OO_Greater || OOK == OO_GreaterEqual ||

xazax.hun wrote:
> So it looks like `operator<<` is the only operator we are not supporting. I 
> think it might be good to include some test code to ensure that its use does 
> not suppress warnings. (Also OK, if you decide to deal with this in a 
> follow-up PR.)
Yes that's the next patch. (and one more for `std::hash`).



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:341
+  case OO_Spaceship:
+// TODO: What would be a good thing to do here?
+  default:

xazax.hun wrote:
> Instead of marking this unreachable, I'd suggest to just return a conjured 
> symbol for now.  Usually, we should not use asserts to test user input.
Ah yes that's what is happening now. `RetVal` is initialized to a conjured 
value. If we can conclude no further, then that is what is returned - which is 
what happens here. In other cases, constraints are applied or it is replaced by 
the output from `evalBinOp`.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:354
+
+  if (FirstPtr && !SecondPtr &&
+  State->assume(FirstPtr->castAs(), false)) {

xazax.hun wrote:
> I am not sure if we actually need all this special casing. You could create 
> an `SVal` that represents a nullpointer constant and use `evalBinOp` with 
> that `SVal` when there is no symbol available.
Actually the naming is a bit misleading here, perhaps. `FirstPtr` is not the 
inner pointer itself but a pointer to the //SVal//. So the test `FirstPtr && 
!SecondPtr` checks that we know the SVal for the inner pointer of the first arg 
but we do not know that of the second arg. Using a null-pointer constant would 
not help.
However, we could use a conjured value to simplify some work.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D104616: [analyzer][WIP] Model comparision methods of std::unique_ptr

2021-06-24 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

We have a failing test  here (test at line 473).
Which makes me wonder if the `handleComparision` function is at all called. 
This is something I need to check.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D104616: [analyzer][WIP] Model comparision methods of std::unique_ptr

2021-06-24 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 354323.
RedDocMD added a comment.

Removed re-invention, added tests


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/test/Analysis/smart-ptr.cpp

Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -457,3 +457,19 @@
 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   }
 }
+
+void uniquePtrComparision(std::unique_ptr unknownPtr) {
+  auto ptr = std::unique_ptr(new int(13));
+  auto nullPtr = std::unique_ptr();
+  auto otherPtr = std::unique_ptr(new int(29));
+
+  clang_analyzer_eval(ptr == ptr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > ptr);  // expected-warning{{FALSE}}
+  clang_analyzer_eval(ptr <= ptr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(nullPtr <= unknownPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(unknownPtr >= nullPtr); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(ptr != otherPtr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr > nullPtr);   // expected-warning{{TRUE}}
+}
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -29,6 +29,7 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/Support/ErrorHandling.h"
 #include 
 
 using namespace clang;
@@ -68,6 +69,7 @@
   bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion,
 const MemRegion *OtherSmartPtrRegion) const;
   void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const;
+  bool handleComparisionOp(const CallEvent &Call, CheckerContext &C) const;
 
   using SmartPtrMethodHandlerFn =
   void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const;
@@ -89,18 +91,24 @@
   const auto *MethodDecl = dyn_cast_or_null(Call.getDecl());
   if (!MethodDecl || !MethodDecl->getParent())
 return false;
+  return isStdSmartPtr(MethodDecl->getParent());
+}
 
-  const auto *RecordDecl = MethodDecl->getParent();
-  if (!RecordDecl || !RecordDecl->getDeclContext()->isStdNamespace())
+bool isStdSmartPtr(const CXXRecordDecl *RD) {
+  if (!RD || !RD->getDeclContext()->isStdNamespace())
 return false;
 
-  if (RecordDecl->getDeclName().isIdentifier()) {
-StringRef Name = RecordDecl->getName();
+  if (RD->getDeclName().isIdentifier()) {
+StringRef Name = RD->getName();
 return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr";
   }
   return false;
 }
 
+bool isStdSmartPtr(const Expr *E) {
+  return isStdSmartPtr(E->getType()->getAsCXXRecordDecl());
+}
+
 bool isNullSmartPtr(const ProgramStateRef State, const MemRegion *ThisRegion) {
   const auto *InnerPointVal = State->get(ThisRegion);
   return InnerPointVal &&
@@ -178,6 +186,15 @@
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
 CheckerContext &C) const {
   ProgramStateRef State = C.getState();
+
+  // If any one of the arg is a unique_ptr, then
+  // we can try this function
+  if (Call.getNumArgs() == 2)
+if (smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
+smartptr::isStdSmartPtr(Call.getArgExpr(1)))
+  if (handleComparisionOp(Call, C))
+return true;
+
   if (!smartptr::isStdSmartPtrCall(Call))
 return false;
 
@@ -272,6 +289,123 @@
   return C.isDifferent();
 }
 
+bool SmartPtrModeling::handleComparisionOp(const CallEvent &Call,
+   CheckerContext &C) const {
+  const auto *FC = dyn_cast(&Call);
+  if (!FC)
+return false;
+  const FunctionDecl *FD = FC->getDecl();
+  if (!FD->isOverloadedOperator())
+return false;
+  const OverloadedOperatorKind OOK = FD->getOverloadedOperator();
+  if (!(OOK == OO_Equal || OOK == OO_ExclaimEqual || OOK == OO_Less ||
+OOK == OO_LessEqual || OOK == OO_Greater || OOK == OO_GreaterEqual ||
+OOK == OO_Spaceship))
+return false;
+
+  SVal First = Call.getArgSVal(0);
+  SVal Second = Call.getArgSVal(1);
+
+  // There are some special cases about which we can infer about
+  // the resulting answer.
+  // For reference, there is a discussion at https://reviews.llvm.org/D104616.
+  // Also, the cppreference page is good to look at
+  // https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_cmp.
+
+  ProgramStateRef State = C.getState();
+  SVal RetVal = C.getSValBuilder().conjure

[PATCH] D104616: [analyzer][WIP] Model comparision methods of std::unique_ptr

2021-06-24 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

In D104616#2835061 , @xazax.hun wrote:

> In D104616#2835030 , @RedDocMD 
> wrote:
>
>> Looks like I have wasted a good deal of effort. :(
>
> Sorry about that! :( If we learned anything new in the process it was not 
> wasted effort though.

I know what I learnt - if I am writing too much code, there is probably a 
function to that. :)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D104616: [analyzer][WIP] Model comparision methods of std::unique_ptr

2021-06-22 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

In D104616#2834770 , @xazax.hun wrote:

> In D104616#2834714 , @NoQ wrote:
>
>> Why not simply delegate this job to `assume(evalBinOp(...))` over raw 
>> pointer values, which already has all this logic written down nicely?
>
> This is what I had in mind, I just did not want to spoil it :)

Looks like I have wasted a good deal of effort. :(


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D104616: [analyzer][WIP] Model comparision methods of std::unique_ptr

2021-06-22 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 353709.
RedDocMD added a comment.

Logic for handling special cases, when both are unique_ptr


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp

Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -68,6 +68,7 @@
   bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion,
 const MemRegion *OtherSmartPtrRegion) const;
   void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const;
+  bool handleComparisionOp(const CallEvent &Call, CheckerContext &C) const;
 
   using SmartPtrMethodHandlerFn =
   void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const;
@@ -264,6 +265,11 @@
   if (handleAssignOp(Call, C))
 return true;
 
+  // FIXME: This won't work
+  // Check for one arg or the other being a smart-ptr.
+  if (handleComparisionOp(Call, C))
+return true;
+
   const SmartPtrMethodHandlerFn *Handler = SmartPtrMethodHandlers.lookup(Call);
   if (!Handler)
 return false;
@@ -272,6 +278,177 @@
   return C.isDifferent();
 }
 
+bool SmartPtrModeling::handleComparisionOp(const CallEvent &Call,
+   CheckerContext &C) const {
+  const auto *MC = llvm::dyn_cast(&Call);
+  if (!MC)
+return false;
+  const OverloadedOperatorKind OOK = MC->getOperator();
+  if (!(OOK == OO_Equal || OOK == OO_ExclaimEqual || OOK == OO_Less ||
+OOK == OO_LessEqual || OOK == OO_Greater || OOK == OO_GreaterEqual ||
+OOK == OO_Spaceship))
+return false;
+
+  SVal First = Call.getArgSVal(0);
+  SVal Second = Call.getArgSVal(1);
+
+  // There are some special cases about which we can infer about
+  // the resulting answer.
+  // For reference, there is a discussion at https://reviews.llvm.org/D104616.
+  // Also, the cppreference page is good to look at
+  // https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_cmp.
+
+  bool addTransition = false;
+  ProgramStateRef State = C.getState();
+  SVal RetVal = C.getSValBuilder().conjureSymbolVal(
+  Call.getOriginExpr(), C.getLocationContext(), Call.getResultType(),
+  C.blockCount());
+
+  if (!First.isZeroConstant() && !Second.isZeroConstant()) {
+// Neither are nullptr, so they are both std::unique_ptr. (whether the smart
+// pointers are null or not is an entire different question.)
+const MemRegion *FirstReg = First.getAsRegion();
+const MemRegion *SecondReg = Second.getAsRegion();
+if (!FirstReg || !SecondReg)
+  return false;
+
+// First and Second may refer to the same object
+if (FirstReg == SecondReg) {
+  switch (OOK) {
+  case OO_Equal:
+  case OO_GreaterEqual:
+  case OO_LessEqual:
+State =
+State->assume(llvm::dyn_cast(RetVal), true);
+addTransition = true;
+break;
+  case OO_Greater:
+  case OO_Less:
+State =
+State->assume(llvm::dyn_cast(RetVal), false);
+addTransition = true;
+break;
+  case OO_Spaceship:
+// TODO: What would be a good thing to do here?
+  default:
+assert(false && "shouldn't reach here");
+  }
+} else {
+  const auto *FirstPtr = State->get(FirstReg);
+  const auto *SecondPtr = State->get(SecondReg);
+
+  if (!FirstPtr && !SecondPtr)
+return false;
+
+  // Now, we know the inner pointer of at least one
+
+  if (FirstPtr && !SecondPtr &&
+  State->assume(llvm::dyn_cast(*FirstPtr),
+false)) {
+// FirstPtr is null, SecondPtr is unknown
+if (OOK == OO_LessEqual) {
+  State =
+  State->assume(llvm::dyn_cast(RetVal), true);
+  addTransition = true;
+}
+  }
+  if (SecondPtr && !FirstPtr &&
+  State->assume(llvm::dyn_cast(*SecondPtr),
+false)) {
+// SecondPtr is null, FirstPtr is unknown
+if (OOK == OO_GreaterEqual) {
+  State =
+  State->assume(llvm::dyn_cast(RetVal), true);
+  addTransition = true;
+}
+  }
+
+  if (FirstPtr && SecondPtr) {
+bool FirstNull{!State->assume(
+llvm::dyn_cast(*FirstPtr), true)};
+bool SecondNull{!State->assume(
+llvm::dyn_cast(*SecondPtr), true)};
+
+if (FirstNull && SecondNull) {
+  switch (OOK) {
+  case OO_Equal:
+  case OO_GreaterEqual:
+  case OO_LessEqual:
+State = State->assume(llvm::dyn_cast(RetVal),
+  true);
+addTransition = true;
+break;
+  case OO_Greate

[PATCH] D104616: [analyzer][WIP] Model comparision methods of std::unique_ptr

2021-06-20 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

The only method that I think can be realistically modelled is `==` (and thus 
`!=`). If both the operands refer to the same `unique_ptr`, we know `==` 
returns true. If they are not the same, the only way `==` can return true if 
the two smart pointers were initialized from the //same// raw pointer. This is 
of course a fatal bug in itself. So perhaps we can ignore this case and only 
consider the first case.
The ordering operators I guess can't be handled because there is no way to 
statically tell in general the address of some value. We have the following 
deductions, nevertheless, mathematically:
Let `ptr1` and `ptr2` be two `std::unique_ptr` objects.
If `(ptr1 == ptr2)` is true:

- `ptr1 < ptr2` is false
- `ptr1 > ptr2` is false
- `ptr1 <= ptr2` is true
- `ptr1 >= ptr2` is true

If `(ptr1 == ptr2)` is false, we can't say anything really.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104616/new/

https://reviews.llvm.org/D104616

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D104616: [analyzer][WIP] Model comparision methods of std::unique_ptr

2021-06-20 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD created this revision.
RedDocMD added reviewers: NoQ, vsavchenko, xazax.hun, teemperor.
Herald added subscribers: manas, steakhal, ASDenysPetrov, martong, dkrupp, 
donat.nagy, Szelethus, mikhail.ramalho, a.sidorin, rnkovacs, szepet, 
baloghadamsoftware.
RedDocMD requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This patch handles all the comparision methods (defined via overloaded
operators) on std::unique_ptr. These operators compare the underlying
pointers, which makes it difficult to model the result.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D104616

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp


Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -68,6 +68,7 @@
   bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion,
 const MemRegion *OtherSmartPtrRegion) const;
   void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const;
+  bool handleComparisionOp(const CallEvent &Call, CheckerContext &C) const;
 
   using SmartPtrMethodHandlerFn =
   void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) 
const;
@@ -264,6 +265,9 @@
   if (handleAssignOp(Call, C))
 return true;
 
+  if (handleComparisionOp(Call, C))
+return true;
+
   const SmartPtrMethodHandlerFn *Handler = SmartPtrMethodHandlers.lookup(Call);
   if (!Handler)
 return false;
@@ -272,6 +276,26 @@
   return C.isDifferent();
 }
 
+bool SmartPtrModeling::handleComparisionOp(const CallEvent &Call,
+   CheckerContext &C) const {
+  const auto *MC = llvm::dyn_cast(&Call);
+  if (!MC)
+return false;
+  const OverloadedOperatorKind OOK = MC->getOverloadedOperator();
+  if (!(OOK == OO_Equal || OOK == OO_ExclaimEqual || OOK == OO_Less ||
+OOK == OO_LessEqual || OOK == OO_Greater || OOK == OO_GreaterEqual ||
+OOK == OO_Spaceship))
+return false;
+
+  // TODO: We had better put some useful modelling here.
+  // But the problem is that all these operators act on the raw
+  // inner pointer (there are special cases for comparision with nullptr).
+  // So, we are not really comparing the value pointed to by the pointer
+  // but the *pointer* itself, which is just an address, which is not
+  // something that symbolic evaluation is concerned about.
+  return true;
+}
+
 void SmartPtrModeling::checkDeadSymbols(SymbolReaper &SymReaper,
 CheckerContext &C) const {
   ProgramStateRef State = C.getState();


Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -68,6 +68,7 @@
   bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion,
 const MemRegion *OtherSmartPtrRegion) const;
   void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const;
+  bool handleComparisionOp(const CallEvent &Call, CheckerContext &C) const;
 
   using SmartPtrMethodHandlerFn =
   void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const;
@@ -264,6 +265,9 @@
   if (handleAssignOp(Call, C))
 return true;
 
+  if (handleComparisionOp(Call, C))
+return true;
+
   const SmartPtrMethodHandlerFn *Handler = SmartPtrMethodHandlers.lookup(Call);
   if (!Handler)
 return false;
@@ -272,6 +276,26 @@
   return C.isDifferent();
 }
 
+bool SmartPtrModeling::handleComparisionOp(const CallEvent &Call,
+   CheckerContext &C) const {
+  const auto *MC = llvm::dyn_cast(&Call);
+  if (!MC)
+return false;
+  const OverloadedOperatorKind OOK = MC->getOverloadedOperator();
+  if (!(OOK == OO_Equal || OOK == OO_ExclaimEqual || OOK == OO_Less ||
+OOK == OO_LessEqual || OOK == OO_Greater || OOK == OO_GreaterEqual ||
+OOK == OO_Spaceship))
+return false;
+
+  // TODO: We had better put some useful modelling here.
+  // But the problem is that all these operators act on the raw
+  // inner pointer (there are special cases for comparision with nullptr).
+  // So, we are not really comparing the value pointed to by the pointer
+  // but the *pointer* itself, which is just an address, which is not
+  // something that symbolic evaluation is concerned about.
+  return true;
+}
+
 void SmartPtrModeling::checkDeadSymbols(SymbolReaper &SymReaper,
 CheckerContext &C) const {
   ProgramStateRef State = C.getState();
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llv

[PATCH] D103750: [analyzer] Handle std::make_unique for SmartPtrModeling

2021-06-19 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

In D103750#2827548 , @RedDocMD wrote:

> In D103750#2825342 , @NoQ wrote:
>
>> Do the above tests pass when your new `evalCall` modeling is enabled?
>
> The analyzer doesn't seem to be able to make up its mind.
>
>   member-constructor.cpp:15:5: warning: FALSE [debug.ExprInspection]
>   clang_analyzer_eval(*P->p == 0);
>   ^~~
>   member-constructor.cpp:15:25: note: Assuming the condition is false
>   clang_analyzer_eval(*P->p == 0);
>   ^~
>   member-constructor.cpp:15:5: note: FALSE
>   clang_analyzer_eval(*P->p == 0);
>   ^~~
>   member-constructor.cpp:15:5: warning: TRUE [debug.ExprInspection]
>   clang_analyzer_eval(*P->p == 0);
>   ^~~
>   member-constructor.cpp:15:25: note: Assuming the condition is true
>   clang_analyzer_eval(*P->p == 0);
>   ^~
>   member-constructor.cpp:15:5: note: TRUE
>   clang_analyzer_eval(*P->p == 0);
>   ^~~
>   2 warnings generated.

What about this?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103750/new/

https://reviews.llvm.org/D103750

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D103434: [analyzer] Allow visitors to run callbacks on completion

2021-06-18 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD abandoned this revision.
RedDocMD added a comment.

I am closing this since it has been addressed much better by the patches from 
@vsavchenko.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103434/new/

https://reviews.llvm.org/D103434

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D104300: [analyzer] Handle std::swap for std::unique_ptr

2021-06-18 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 353068.
RedDocMD added a comment.

Some more refactoring


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104300/new/

https://reviews.llvm.org/D104300

Files:
  clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/BugReporter.cpp
  clang/test/Analysis/smart-ptr-text-output.cpp

Index: clang/test/Analysis/smart-ptr-text-output.cpp
===
--- clang/test/Analysis/smart-ptr-text-output.cpp
+++ clang/test/Analysis/smart-ptr-text-output.cpp
@@ -69,20 +69,17 @@
 
 void derefOnSwappedNullPtr() {
   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'}}
+  std::unique_ptr PNull;
+  P.swap(PNull);
   PNull->foo(); // No warning.
   (*P).foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   // expected-note@-1{{Dereference of null smart pointer 'P'}}
 }
 
-// FIXME: Fix this test when "std::swap" is modeled seperately.
 void derefOnStdSwappedNullPtr() {
   std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}}
-  std::unique_ptr PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}}
-  std::swap(P, PNull); // expected-note@Inputs/system-header-simulator-cxx.h:979 {{Swapped null smart pointer 'PNull' with smart pointer 'P'}}
-  // expected-note@-1 {{Calling 'swap'}}
-  // expected-note@-2 {{Returning from 'swap'}}
+  std::unique_ptr PNull;
+  std::swap(P, PNull);
   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   // expected-note@-1{{Dereference of null smart pointer 'P'}}
 }
Index: clang/lib/StaticAnalyzer/Core/BugReporter.cpp
===
--- clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -2261,6 +2261,14 @@
 markInteresting(meta->getRegion(), TKind);
 }
 
+void PathSensitiveBugReport::markNotInteresting(SymbolRef sym) {
+  if (!sym)
+return;
+  InterestingSymbols.erase(sym);
+  if (const auto *meta = dyn_cast(sym))
+markNotInteresting(meta->getRegion());
+}
+
 void PathSensitiveBugReport::markInteresting(const MemRegion *R,
  bugreporter::TrackingKind TKind) {
   if (!R)
@@ -2273,6 +2281,17 @@
 markInteresting(SR->getSymbol(), TKind);
 }
 
+void PathSensitiveBugReport::markNotInteresting(const MemRegion *R) {
+  if (!R)
+return;
+
+  R = R->getBaseRegion();
+  InterestingRegions.erase(R);
+
+  if (const auto *SR = dyn_cast(R))
+markNotInteresting(SR->getSymbol());
+}
+
 void PathSensitiveBugReport::markInteresting(SVal V,
  bugreporter::TrackingKind TKind) {
   markInteresting(V.getAsRegion(), TKind);
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -60,7 +60,7 @@
 private:
   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 handleSwapMethod(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,
@@ -68,14 +68,17 @@
   bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion,
 const MemRegion *OtherSmartPtrRegion) const;
   void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const;
+  bool handleSwap(ProgramStateRef State, SVal First, SVal Second,
+  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::handleSwapMethod},
   {{"get"}, &SmartPtrModeling::handleGet}};
+  const CallDescription StdSwapCall{{"std", "swap"}, 2};
 };
 } // end of anonymous namespace
 
@@ -91,11 +94,15 @@
 return false;
 
   const auto *RecordDecl = MethodDecl->getParent();
-  if (!RecordDecl ||

[PATCH] D104300: [analyzer] Handle std::swap for std::unique_ptr

2021-06-18 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD marked 5 inline comments as done.
RedDocMD added inline comments.



Comment at: 
clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h:435
 
+  void markNotInteresting(SymbolRef sym);
+

xazax.hun wrote:
> Bikeshedding: I wonder if we prefer `Uninteresting` to `NotInteresting`. Or 
> alternatively, if we want to emphasize this is only the lack of 
> interestingness, we could name it `removeInterestingness`. I do not have 
> strong feelings about any of the options, I was just wondering if any of you 
> has a preference.
I was actually planning to use something like `unmarkInteresting`, but that is 
grammatically incorrect. `removeInterestingness` is fair enough, but a mouthful 
I think. As for `Uninteresting`, I think we are better off avoiding clever uses 
of English and stick with simple, programmer jargon.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:191
+// Check the first arg, if it is of std::unique_ptr type.
+assert(Call.getNumArgs() == 2 && "std::swap should have two arguments");
+const Expr *FirstArg = Call.getArgExpr(0);

xazax.hun wrote:
> I wonder about the value of this assertion. Shouldn`t 
> `Call.isCalled(StdSwapCall)` already validate the number of arguments?
About as valuable as any assertion is ;)
My reasoning is that since we are calling `Call.getArgSval(0)` and 
`Call.getArgSVal(1)`, we had better assert that there are two args.
As a side-note, I had a bug in my `CallDescriptor`, which was caught by this 
assertion



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:196-202
+const MemRegion *FirstArgThisRegion = Call.getArgSVal(0).getAsRegion();
+if (!FirstArgThisRegion)
+  return false;
+const MemRegion *SecondArgThisRegion = Call.getArgSVal(1).getAsRegion();
+if (!SecondArgThisRegion)
+  return false;
+

vsavchenko wrote:
> I guess `handleSwap` can take `SVal`s instead of `MemRegion` and we can 
> mostly cut on this boilerplate as well.
> ```
>return handleSwap(State, Call.getArgSVal(0), Call.getArgSVal(1), C);
> ```
> and
> ```
>   return handleSwap(State, IC->getCXXThisVal(), Call.getArgSVal(0), C);
> ```
Yup, okay.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:458-467
+if (BR.isInteresting(FirstThisRegion) &&
+!BR.isInteresting(SecondThisRegion)) {
+  BR.markInteresting(SecondThisRegion);
+  BR.markNotInteresting(FirstThisRegion);
+}
+if (BR.isInteresting(SecondThisRegion) &&
+!BR.isInteresting(FirstThisRegion)) {

xazax.hun wrote:
> vsavchenko wrote:
> > nit: these two pieces of code are very much the same
> I guess we could make `markInteresting` take an optional bool and swap the 
> interestingness unconditionally. 
Then we would need to rename it to something like `setInterestingness`.
And renaming such a widely used function would be a real pain.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:458-467
+if (BR.isInteresting(FirstThisRegion) &&
+!BR.isInteresting(SecondThisRegion)) {
+  BR.markInteresting(SecondThisRegion);
+  BR.markNotInteresting(FirstThisRegion);
+}
+if (BR.isInteresting(SecondThisRegion) &&
+!BR.isInteresting(FirstThisRegion)) {

RedDocMD wrote:
> xazax.hun wrote:
> > vsavchenko wrote:
> > > nit: these two pieces of code are very much the same
> > I guess we could make `markInteresting` take an optional bool and swap the 
> > interestingness unconditionally. 
> Then we would need to rename it to something like `setInterestingness`.
> And renaming such a widely used function would be a real pain.
Yes, but I don't think refactoring them into a lambda (within a lambda) would 
be that nice either.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104300/new/

https://reviews.llvm.org/D104300

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D103750: [analyzer] Handle std::make_unique for SmartPtrModeling

2021-06-18 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

In D103750#2825823 , @xazax.hun wrote:

> I believe there are a couple of comments that are done but not marked 
> accordingly. 
> I agree with Artem, if we could craft code that fails due to not calling 
> ctors, we should probably include them in the tests, even if they don't 
> reflect the desired behavior they are a great source of documentation what is 
> missing.

Do you want the new failing test to be marked //expected to fail//?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103750/new/

https://reviews.llvm.org/D103750

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D103750: [analyzer] Handle std::make_unique for SmartPtrModeling

2021-06-18 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD updated this revision to Diff 353048.
RedDocMD added a comment.

Little changes, a failing test


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103750/new/

https://reviews.llvm.org/D103750

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
  clang/test/Analysis/Inputs/system-header-simulator-cxx.h
  clang/test/Analysis/smart-ptr-text-output.cpp

Index: clang/test/Analysis/smart-ptr-text-output.cpp
===
--- clang/test/Analysis/smart-ptr-text-output.cpp
+++ clang/test/Analysis/smart-ptr-text-output.cpp
@@ -1,10 +1,17 @@
 // RUN: %clang_analyze_cc1\
-// RUN:  -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr\
+// RUN:  -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr,debug.ExprInspection\
+// RUN:  -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
+// RUN:  -analyzer-output=text -std=c++20 %s -verify=expected
+
+// RUN: %clang_analyze_cc1\
+// RUN:  -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr,debug.ExprInspection\
 // RUN:  -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
 // RUN:  -analyzer-output=text -std=c++11 %s -verify=expected
 
 #include "Inputs/system-header-simulator-cxx.h"
 
+void clang_analyzer_eval(bool);
+
 class A {
 public:
   A(){};
@@ -313,3 +320,54 @@
 // expected-note@-1{{Dereference of null smart pointer 'P'}}
   }
 }
+
+void makeUniqueReturnsNonNullUniquePtr() {
+  auto P = std::make_unique();
+  if (!P) {   // expected-note {{Taking false branch}}
+P->foo(); // should have no warning here, path is impossible
+  }
+  P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}}
+  // Now P is null
+  if (!P) {
+// 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'}}
+  }
+}
+
+#if __cplusplus >= 202002L
+
+void makeUniqueForOverwriteReturnsNullUniquePtr() {
+  auto P = std::make_unique_for_overwrite();
+  if (!P) {   // expected-note {{Taking false branch}}
+P->foo(); // should have no warning here, path is impossible
+  }
+  P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}}
+  // Now P is null
+  if (!P) {
+// 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'}}
+  }
+}
+
+#endif
+
+struct G {
+  int *p;
+  G(int *p): p(p) {}
+  ~G() { *p = 0; }
+};
+
+void foo() {
+  int x = 1;
+  {
+auto P = std::make_unique(&x);
+clang_analyzer_eval(*P->p == 1); // expected-warning {{TRUE [debug.ExprInspection]}}
+// expected-note@-1 {{TRUE}}
+// expected-note@-2 {{Assuming condition is true}}
+  }
+  clang_analyzer_eval(x == 0); // expected-warning {{TRUE [debug.ExprInspection]}}
+  // expected-note@-1 {{TRUE}}
+  // expected-note@-2 {{Assuming condition is true}}
+}
\ No newline at end of file
Index: clang/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -978,6 +978,17 @@
 void swap(unique_ptr &x, unique_ptr &y) noexcept {
   x.swap(y);
 }
+
+template 
+unique_ptr make_unique(Args &&...args);
+
+#if __cplusplus >= 202002L
+
+template 
+unique_ptr make_unique_for_overwrite();
+
+#endif
+
 } // namespace std
 #endif
 
Index: clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
===
--- clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -192,12 +192,19 @@
   const LocationContext *LCtx,
   unsigned VisitCount) {
   QualType T = E->getType();
-  assert(Loc::isLocType(T));
-  assert(SymbolManager::canSymbolicate(T));
-  if (T->isNullPtrType())
-return makeZeroVal(T);
+  return getConjuredHeapSymbolVal(E, LCtx, T, VisitCount);
+}
+
+DefinedOrUnknownSVal
+SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
+  const LocationContext *LCtx,
+  QualType type, unsigned VisitCount) {
+  assert(Loc::isLocType(type));
+  assert(SymbolManager::canSymbolicate(type));
+  if (type->isNullPtrType())
+return makeZeroVal(type);
 
-  SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, T, VisitCount);
+  SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, type, VisitCount);
   return loc::MemRegionVal(MemMgr.getSymbolicHeapRegion(sym));
 }
 
Index: clang/lib/StaticAna

[PATCH] D103750: [analyzer] Handle std::make_unique for SmartPtrModeling

2021-06-18 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD added a comment.

In D103750#2825342 , @NoQ wrote:

> In D103750#2823741 , @RedDocMD 
> wrote:
>
>> I would suppose that constructor calls are properly handled. (ie, member 
>> constructors are called properly).
>
> Do the above tests pass when your new `evalCall` modeling is enabled?

The analyzer doesn't seem to be able to make up its mind.

  member-constructor.cpp:15:5: warning: FALSE [debug.ExprInspection]
  clang_analyzer_eval(*P->p == 0);
  ^~~
  member-constructor.cpp:15:25: note: Assuming the condition is false
  clang_analyzer_eval(*P->p == 0);
  ^~
  member-constructor.cpp:15:5: note: FALSE
  clang_analyzer_eval(*P->p == 0);
  ^~~
  member-constructor.cpp:15:5: warning: TRUE [debug.ExprInspection]
  clang_analyzer_eval(*P->p == 0);
  ^~~
  member-constructor.cpp:15:25: note: Assuming the condition is true
  clang_analyzer_eval(*P->p == 0);
  ^~
  member-constructor.cpp:15:5: note: TRUE
  clang_analyzer_eval(*P->p == 0);
  ^~~
  2 warnings generated.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103750/new/

https://reviews.llvm.org/D103750

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D103750: [analyzer] Handle std::make_unique for SmartPtrModeling

2021-06-18 Thread Deep Majumder via Phabricator via cfe-commits
RedDocMD marked an inline comment as done.
RedDocMD added inline comments.



Comment at: clang/test/Analysis/smart-ptr-text-output.cpp:3
+// RUN:  -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr\
+// RUN:  -analyzer-config 
cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\
+// RUN:  -analyzer-output=text -std=c++20 %s -verify=expected

NoQ wrote:
> RedDocMD wrote:
> > NoQ wrote:
> > > Could you double-check that this flag correctly disables all the newly 
> > > introduced modeling so that it wasn't accidentally enabled for all users 
> > > before it's ready?
> > Yup. There are 133 notes and warnings (just search for "// expected-" and 
> > see the count). And on setting the flag to `false`, there are 133 errors.
> > So it works.
> I mean, specifically the modeling added by this patch? I see you wrote an 
> entire checker callback that doesn't seem to have an analyzer-config option 
> check anywhere in it. Simply having different results isn't sufficient to 
> verify this.
Oh I see.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103750/new/

https://reviews.llvm.org/D103750

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


  1   2   3   >