[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-31 Thread Nithin VR 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 rGbc3d4d9ed783: [analyzer] Add bool operator modeling for 
unque_ptr (authored by vrnithinkumar).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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

Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -8,12 +8,13 @@
 void clang_analyzer_warnIfReached();
 void clang_analyzer_numTimesReached();
 void clang_analyzer_eval(bool);
+void clang_analyzer_warnOnDeadSymbol(int *);
 
 void derefAfterMove(std::unique_ptr P) {
   std::unique_ptr Q = std::move(P);
   if (Q)
 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
-  *Q.get() = 1; // no-warning
+  *Q.get() = 1; // expected-warning {{Dereference of null pointer [core.NullDereference]}}
   if (P)
 clang_analyzer_warnIfReached(); // no-warning
   // TODO: Report a null dereference (instead).
@@ -375,3 +376,77 @@
   std::unique_ptr P(functionReturnsRValueRef());
   P->foo();  // No warning.
 }
+
+void derefConditionOnNullPtr() {
+  std::unique_ptr P;
+  if (P)
+P->foo(); // No warning.
+  else
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefConditionOnNotNullPtr() {
+  std::unique_ptr P;
+  if (!P)
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefConditionOnValidPtr() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull;
+  if (P)
+PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefConditionOnNotValidPtr() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull;
+  if (!P)
+PNull->foo(); // No warning.
+}
+
+void derefConditionOnUnKnownPtr(std::unique_ptr P) {
+  if (P)
+P->foo(); // No warning.
+  else
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefOnValidPtrAfterReset(std::unique_ptr P) {
+  P.reset(new A());
+  if (!P)
+P->foo(); // No warning.
+  else
+P->foo(); // No warning.
+}
+
+void innerPointerSymbolLiveness() {
+  std::unique_ptr P(new int());
+  clang_analyzer_warnOnDeadSymbol(P.get());
+  int *RP = P.release();
+} // expected-warning{{SYMBOL DEAD}}
+
+void boolOpCreatedConjuredSymbolLiveness(std::unique_ptr P) {
+  if (P) {
+int *X = P.get();
+clang_analyzer_warnOnDeadSymbol(X);
+  }
+} // expected-warning{{SYMBOL DEAD}}
+
+void getCreatedConjuredSymbolLiveness(std::unique_ptr P) {
+  int *X = P.get();
+  clang_analyzer_warnOnDeadSymbol(X);
+  int Y;
+  if (!P) {
+Y = *P.get(); // expected-warning {{Dereference of null pointer [core.NullDereference]}}
+// expected-warning@-1 {{SYMBOL DEAD}}
+  }
+}
+
+int derefConditionOnUnKnownPtr(int *q) {
+  std::unique_ptr P(q);
+  if (P)
+return *P; // No warning.
+  else
+return *P; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
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
@@ -199,3 +199,108 @@
   PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
   // expected-note@-1{{Dereference of null smart pointer 'PToMove'}}
 }
+
+void derefConditionOnNullPtrFalseBranch() {
+  std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}}
+  if (P) { // expected-note {{Taking false branch}}
+P->foo(); // No warning.
+  } else {
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+// expected-note@-1{{Dereference of null smart pointer 'P'}}
+  }
+}
+
+void derefConditionOnNullPtrTrueBranch() {
+  std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}}
+  if (!P) { // expected-note {{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'}}
+  }
+}
+
+void derefConditionOnValidPtrTrueBranch() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}}
+  if (P) { // expected-note {{Taking true branch}}
+PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
+// expected-note@-1{{Dereference of null smart 

[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-31 Thread Gábor Horváth via Phabricator via cfe-commits
xazax.hun accepted this revision.
xazax.hun added a comment.
This revision is now accepted and ready to land.

LG! Thanks!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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


[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-31 Thread Nithin VR via Phabricator via cfe-commits
vrnithinkumar marked an inline comment as done.
vrnithinkumar added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:556
+const LocationContext *LC = C.getLocationContext();
+InnerPointerVal = C.getSValBuilder().conjureSymbolVal(
+CallExpr, LC, InnerPointerType, C.blockCount());

xazax.hun wrote:
> Don't we want to actually add InnerPointerVal to TrackedRegionMap in this 
> case?
> 
> I might be wrong but I cannot find where do we actually record the fact that 
> this freshly conjured symbol belongs to the unique_ptr we are modeling.
Thanks for catching that. 
We have to update the `TrackedRegionMap` to track the created conjureSymbolVal  
`InnerPointerVal`.
Updated to add it to the `TrackedRegionMap`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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


[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-31 Thread Nithin VR via Phabricator via cfe-commits
vrnithinkumar updated this revision to Diff 288974.
vrnithinkumar added a comment.

- Fixing minor spacing issue


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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

Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -8,12 +8,13 @@
 void clang_analyzer_warnIfReached();
 void clang_analyzer_numTimesReached();
 void clang_analyzer_eval(bool);
+void clang_analyzer_warnOnDeadSymbol(int *);
 
 void derefAfterMove(std::unique_ptr P) {
   std::unique_ptr Q = std::move(P);
   if (Q)
 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
-  *Q.get() = 1; // no-warning
+  *Q.get() = 1; // expected-warning {{Dereference of null pointer [core.NullDereference]}}
   if (P)
 clang_analyzer_warnIfReached(); // no-warning
   // TODO: Report a null dereference (instead).
@@ -375,3 +376,77 @@
   std::unique_ptr P(functionReturnsRValueRef());
   P->foo();  // No warning.
 }
+
+void derefConditionOnNullPtr() {
+  std::unique_ptr P;
+  if (P)
+P->foo(); // No warning.
+  else
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefConditionOnNotNullPtr() {
+  std::unique_ptr P;
+  if (!P)
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefConditionOnValidPtr() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull;
+  if (P)
+PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefConditionOnNotValidPtr() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull;
+  if (!P)
+PNull->foo(); // No warning.
+}
+
+void derefConditionOnUnKnownPtr(std::unique_ptr P) {
+  if (P)
+P->foo(); // No warning.
+  else
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefOnValidPtrAfterReset(std::unique_ptr P) {
+  P.reset(new A());
+  if (!P)
+P->foo(); // No warning.
+  else
+P->foo(); // No warning.
+}
+
+void innerPointerSymbolLiveness() {
+  std::unique_ptr P(new int());
+  clang_analyzer_warnOnDeadSymbol(P.get());
+  int *RP = P.release();
+} // expected-warning{{SYMBOL DEAD}}
+
+void boolOpCreatedConjuredSymbolLiveness(std::unique_ptr P) {
+  if (P) {
+int *X = P.get();
+clang_analyzer_warnOnDeadSymbol(X);
+  }
+} // expected-warning{{SYMBOL DEAD}}
+
+void getCreatedConjuredSymbolLiveness(std::unique_ptr P) {
+  int *X = P.get();
+  clang_analyzer_warnOnDeadSymbol(X);
+  int Y;
+  if (!P) {
+Y = *P.get(); // expected-warning {{Dereference of null pointer [core.NullDereference]}}
+// expected-warning@-1 {{SYMBOL DEAD}}
+  }
+}
+
+int derefConditionOnUnKnownPtr(int *q) {
+  std::unique_ptr P(q);
+  if (P)
+return *P; // No warning.
+  else
+return *P; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
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
@@ -199,3 +199,108 @@
   PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
   // expected-note@-1{{Dereference of null smart pointer 'PToMove'}}
 }
+
+void derefConditionOnNullPtrFalseBranch() {
+  std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}}
+  if (P) { // expected-note {{Taking false branch}}
+P->foo(); // No warning.
+  } else {
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+// expected-note@-1{{Dereference of null smart pointer 'P'}}
+  }
+}
+
+void derefConditionOnNullPtrTrueBranch() {
+  std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}}
+  if (!P) { // expected-note {{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'}}
+  }
+}
+
+void derefConditionOnValidPtrTrueBranch() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}}
+  if (P) { // expected-note {{Taking true branch}}
+PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
+// expected-note@-1{{Dereference of null smart pointer 'PNull'}}
+  } else {
+PNull->foo(); // No warning
+  }
+}
+
+void derefConditionOnValidPtrFalseBranch() {
+  

[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-31 Thread Nithin VR via Phabricator via cfe-commits
vrnithinkumar updated this revision to Diff 288972.
vrnithinkumar added a comment.

- Addressing review comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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

Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -8,12 +8,13 @@
 void clang_analyzer_warnIfReached();
 void clang_analyzer_numTimesReached();
 void clang_analyzer_eval(bool);
+void clang_analyzer_warnOnDeadSymbol(int *);
 
 void derefAfterMove(std::unique_ptr P) {
   std::unique_ptr Q = std::move(P);
   if (Q)
 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
-  *Q.get() = 1; // no-warning
+  *Q.get() = 1; // expected-warning {{Dereference of null pointer [core.NullDereference]}}
   if (P)
 clang_analyzer_warnIfReached(); // no-warning
   // TODO: Report a null dereference (instead).
@@ -375,3 +376,77 @@
   std::unique_ptr P(functionReturnsRValueRef());
   P->foo();  // No warning.
 }
+
+void derefConditionOnNullPtr() {
+  std::unique_ptr P;
+  if (P)
+P->foo(); // No warning.
+  else
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefConditionOnNotNullPtr() {
+  std::unique_ptr P;
+  if (!P)
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefConditionOnValidPtr() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull;
+  if (P)
+PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefConditionOnNotValidPtr() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull;
+  if (!P)
+PNull->foo(); // No warning.
+}
+
+void derefConditionOnUnKnownPtr(std::unique_ptr P) {
+  if (P)
+P->foo(); // No warning.
+  else
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefOnValidPtrAfterReset(std::unique_ptr P) {
+  P.reset(new A());
+  if (!P)
+P->foo(); // No warning.
+  else
+P->foo(); // No warning.
+}
+
+void innerPointerSymbolLiveness() {
+  std::unique_ptr P(new int());
+  clang_analyzer_warnOnDeadSymbol(P.get());
+  int *RP = P.release();
+} // expected-warning{{SYMBOL DEAD}}
+
+void boolOpCreatedConjuredSymbolLiveness(std::unique_ptr P) {
+  if (P) {
+int *X = P.get();
+clang_analyzer_warnOnDeadSymbol(X);
+  }
+} // expected-warning{{SYMBOL DEAD}}
+
+void getCreatedConjuredSymbolLiveness(std::unique_ptr P) {
+  int *X = P.get();
+  clang_analyzer_warnOnDeadSymbol(X);
+  int Y;
+  if (!P) {
+Y = *P.get(); // expected-warning {{Dereference of null pointer [core.NullDereference]}}
+// expected-warning@-1 {{SYMBOL DEAD}}
+  }
+}
+
+int derefConditionOnUnKnownPtr(int *q) {
+  std::unique_ptr P(q);
+  if (P)
+return *P; // No warning.
+  else
+return *P; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
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
@@ -170,7 +170,6 @@
   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   // expected-note@-1 {{Dereference of null smart pointer 'P'}}
 }
-
 void derefMoveConstructedWithNullPtr() {
   std::unique_ptr PToMove; // expected-note {{Default constructed smart pointer 'PToMove' is null}}
   std::unique_ptr P(std::move(PToMove)); // expected-note {{A null pointer value is moved to 'P'}}
@@ -199,3 +198,109 @@
   PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
   // expected-note@-1{{Dereference of null smart pointer 'PToMove'}}
 }
+
+void derefConditionOnNullPtrFalseBranch() {
+  std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}}
+  if (P) { // expected-note {{Taking false branch}}
+P->foo(); // No warning.
+  } else {
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+// expected-note@-1{{Dereference of null smart pointer 'P'}}
+  }
+}
+
+void derefConditionOnNullPtrTrueBranch() {
+  std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}}
+  if (!P) { // expected-note {{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'}}
+  }
+}
+
+void derefConditionOnValidPtrTrueBranch() {
+  std::unique_ptr P(new A());
+  

[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-31 Thread Gábor Horváth via Phabricator via cfe-commits
xazax.hun added inline comments.
Herald added a subscriber: danielkiss.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:556
+const LocationContext *LC = C.getLocationContext();
+InnerPointerVal = C.getSValBuilder().conjureSymbolVal(
+CallExpr, LC, InnerPointerType, C.blockCount());

Don't we want to actually add InnerPointerVal to TrackedRegionMap in this case?

I might be wrong but I cannot find where do we actually record the fact that 
this freshly conjured symbol belongs to the unique_ptr we are modeling.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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


[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-27 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ accepted this revision.
NoQ added a comment.

I have no other concerns, i think this is good to go!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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


[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-26 Thread Nithin VR via Phabricator via cfe-commits
vrnithinkumar marked 2 inline comments as done.
vrnithinkumar added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:483
+llvm::raw_ostream ) {
+ BR.markInteresting(ThisRegion);
+ OS << "Smart pointer";

NoQ wrote:
> Wait, why are we marking the region interesting here? Not every null smart 
> pointer is interesting, only the ones that are actually dereferenced.
This was added to show how the smart pointer, even though it is not 
dereferenced. But why did we take true/false branch based on this.




Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:497-499
+ OS << "Smart pointer";
+ checkAndPrettyPrintRegion(OS, ThisRegion);
+ OS << " is non-null";

NoQ wrote:
> Also i'm starting to suspect that these notes aren't actually needed when 
> there's no "Assuming..."; in particular, we don't emit such notes for raw 
> pointers, so we probably shouldn't emit them for smart pointers either. 
> There's anyway going to be a note about "Taking true branch..." or something 
> like that, which is sufficient to understand what was the smart pointer.
> 
> I.e., this note is unnecessary:
> ```lang=c++
> void foo() {
>   std::unique_ptr P = nullptr;
>   if (P) {// Smart pointer 'P' is null
>   // Taking false branch
>   }
> }
> ```
> The second note, "Taking false branch", is sufficient for explaining to the 
> user that the smart pointer is known to be null. The user may ask why the 
> smart pointer is null, but the note isn't explaining it. The way you marked 
> the region as interesting (as i noticed in the above inline comment) would 
> have indeed explained why it's null, but at this point we draw the line and 
> believe that if the region isn't already interesting then the user most 
> likely doesn't need to know why it's null (and if it's already interesting 
> then there's no need to mark it again).
> 
> But this note is necessary:
> ```lang=c++
> void foo(std::unique_ptr P) {
>   if (P) {// Assuming smart pointer 'P' is null
>   // Taking false branch
>   }
> }
> ```
> This note conveys the extra information that we don't know for a fact that 
> the smart pointer is null on the current path based on previous analysis, but 
> instead the analyzer is *assuming* that it's possible that it's null due to 
> the presence of the check in the code. That's a big deal.
Since the "Taking false branch" is enough to implies the smart pointer in null, 
removing the notes which are unnecessary.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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


[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-26 Thread Nithin VR via Phabricator via cfe-commits
vrnithinkumar updated this revision to Diff 288048.
vrnithinkumar marked an inline comment as done.
vrnithinkumar added a comment.

- Removing unnecessary notetags.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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

Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -8,12 +8,13 @@
 void clang_analyzer_warnIfReached();
 void clang_analyzer_numTimesReached();
 void clang_analyzer_eval(bool);
+void clang_analyzer_warnOnDeadSymbol(int *);
 
 void derefAfterMove(std::unique_ptr P) {
   std::unique_ptr Q = std::move(P);
   if (Q)
 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
-  *Q.get() = 1; // no-warning
+  *Q.get() = 1; // expected-warning {{Dereference of null pointer [core.NullDereference]}}
   if (P)
 clang_analyzer_warnIfReached(); // no-warning
   // TODO: Report a null dereference (instead).
@@ -333,3 +334,69 @@
   P = returnRValRefOfUniquePtr();
   P->foo(); // No warning. 
 }
+
+void derefConditionOnNullPtr() {
+  std::unique_ptr P;
+  if (P)
+P->foo(); // No warning.
+  else
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefConditionOnNotNullPtr() {
+  std::unique_ptr P;
+  if (!P)
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefConditionOnValidPtr() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull;
+  if (P)
+PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefConditionOnNotValidPtr() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull;
+  if (!P)
+PNull->foo(); // No warning.
+}
+
+void derefConditionOnUnKnownPtr(std::unique_ptr P) {
+  if (P)
+P->foo(); // No warning.
+  else
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefOnValidPtrAfterReset(std::unique_ptr P) {
+  P.reset(new A());
+  if (!P)
+P->foo(); // No warning.
+  else
+P->foo(); // No warning.
+}
+
+void innerPointerSymbolLiveness() {
+  std::unique_ptr P(new int());
+  clang_analyzer_warnOnDeadSymbol(P.get());
+  int *RP = P.release();
+} // expected-warning{{SYMBOL DEAD}}
+
+void boolOpCreatedConjuredSymbolLiveness(std::unique_ptr P) {
+  if (P) {
+int *X = P.get();
+clang_analyzer_warnOnDeadSymbol(X);
+  }
+} // expected-warning{{SYMBOL DEAD}}
+
+void getCreatedConjuredSymbolLiveness(std::unique_ptr P) {
+  int *X = P.get();
+  clang_analyzer_warnOnDeadSymbol(X);
+  int Y;
+  if (!P) {
+Y = *P.get(); // expected-warning {{Dereference of null pointer [core.NullDereference]}}
+// expected-warning@-1 {{SYMBOL DEAD}}
+  }
+}
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
@@ -170,3 +170,108 @@
   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   // expected-note@-1 {{Dereference of null smart pointer 'P'}}
 }
+
+void derefConditionOnNullPtrFalseBranch() {
+  std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}}
+  if (P) { // expected-note {{Taking false branch}}
+P->foo(); // No warning.
+  } else {
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+// expected-note@-1{{Dereference of null smart pointer 'P'}}
+  }
+}
+
+void derefConditionOnNullPtrTrueBranch() {
+  std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}}
+  if (!P) { // expected-note {{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'}}
+  }
+}
+
+void derefConditionOnValidPtrTrueBranch() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}}
+  if (P) { // expected-note {{Taking true branch}}
+PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
+// expected-note@-1{{Dereference of null smart pointer 'PNull'}}
+  } else {
+PNull->foo(); // No warning
+  }
+}
+
+void derefConditionOnValidPtrFalseBranch() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}}
+  if (!P) { // expected-note {{Taking false branch}}
+PNull->foo(); // No warning
+  } 

[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-25 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:483
+llvm::raw_ostream ) {
+ BR.markInteresting(ThisRegion);
+ OS << "Smart pointer";

Wait, why are we marking the region interesting here? Not every null smart 
pointer is interesting, only the ones that are actually dereferenced.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:497-499
+ OS << "Smart pointer";
+ checkAndPrettyPrintRegion(OS, ThisRegion);
+ OS << " is non-null";

Also i'm starting to suspect that these notes aren't actually needed when 
there's no "Assuming..."; in particular, we don't emit such notes for raw 
pointers, so we probably shouldn't emit them for smart pointers either. There's 
anyway going to be a note about "Taking true branch..." or something like that, 
which is sufficient to understand what was the smart pointer.

I.e., this note is unnecessary:
```lang=c++
void foo() {
  std::unique_ptr P = nullptr;
  if (P) {// Smart pointer 'P' is null
  // Taking false branch
  }
}
```
The second note, "Taking false branch", is sufficient for explaining to the 
user that the smart pointer is known to be null. The user may ask why the smart 
pointer is null, but the note isn't explaining it. The way you marked the 
region as interesting (as i noticed in the above inline comment) would have 
indeed explained why it's null, but at this point we draw the line and believe 
that if the region isn't already interesting then the user most likely doesn't 
need to know why it's null (and if it's already interesting then there's no 
need to mark it again).

But this note is necessary:
```lang=c++
void foo(std::unique_ptr P) {
  if (P) {// Assuming smart pointer 'P' is null
  // Taking false branch
  }
}
```
This note conveys the extra information that we don't know for a fact that the 
smart pointer is null on the current path based on previous analysis, but 
instead the analyzer is *assuming* that it's possible that it's null due to the 
presence of the check in the code. That's a big deal.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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


[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-25 Thread Nithin VR via Phabricator via cfe-commits
vrnithinkumar marked an inline comment as done.
vrnithinkumar added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:494-496
+  OS << "Smart pointer";
+  checkAndPrettyPrintRegion(OS, ThisRegion);
+  OS << " is non-null";

NoQ wrote:
> Because these note tags aren't specific to the bug report at hand, they have 
> to be marked as //prunable// (i.e., the optional `getNoteTag()`'s parameter 
> "`IsPrunable`" should be set to true). That'd reduce bug report clutter by 
> not bringing in stack frames that aren't otherwise interesting for the bug 
> report.
> 
> Something like this may act as a test (i didn't try):
> ```lang=c++
> struct S {
>   std::unique_ptr P;
> 
>   void foo() {
> if (!P) { // no-note because foo() is pruned
>   return;
> }
>   }
> 
>   int bar() {
> P = new int(0);
> foo();
> return 1 / *P; // warning: division by zero
>   }
> 
> }
> 
> ```
Marked these tags as prunable and added the tests.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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


[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-25 Thread Nithin VR via Phabricator via cfe-commits
vrnithinkumar updated this revision to Diff 287641.
vrnithinkumar added a comment.

- Making the note tags prunable


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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

Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -8,12 +8,13 @@
 void clang_analyzer_warnIfReached();
 void clang_analyzer_numTimesReached();
 void clang_analyzer_eval(bool);
+void clang_analyzer_warnOnDeadSymbol(int *);
 
 void derefAfterMove(std::unique_ptr P) {
   std::unique_ptr Q = std::move(P);
   if (Q)
 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
-  *Q.get() = 1; // no-warning
+  *Q.get() = 1; // expected-warning {{Dereference of null pointer [core.NullDereference]}}
   if (P)
 clang_analyzer_warnIfReached(); // no-warning
   // TODO: Report a null dereference (instead).
@@ -276,3 +277,69 @@
 Y->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}}
   }
 }
+
+void derefConditionOnNullPtr() {
+  std::unique_ptr P;
+  if (P)
+P->foo(); // No warning.
+  else
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefConditionOnNotNullPtr() {
+  std::unique_ptr P;
+  if (!P)
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefConditionOnValidPtr() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull;
+  if (P)
+PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefConditionOnNotValidPtr() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull;
+  if (!P)
+PNull->foo(); // No warning.
+}
+
+void derefConditionOnUnKnownPtr(std::unique_ptr P) {
+  if (P)
+P->foo(); // No warning.
+  else
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefOnValidPtrAfterReset(std::unique_ptr P) {
+  P.reset(new A());
+  if (!P)
+P->foo(); // No warning.
+  else
+P->foo(); // No warning.
+}
+
+void innerPointerSymbolLiveness() {
+  std::unique_ptr P(new int());
+  clang_analyzer_warnOnDeadSymbol(P.get());
+  int *RP = P.release();
+} // expected-warning{{SYMBOL DEAD}}
+
+void boolOpCreatedConjuredSymbolLiveness(std::unique_ptr P) {
+  if (P) {
+int *X = P.get();
+clang_analyzer_warnOnDeadSymbol(X);
+  }
+} // expected-warning{{SYMBOL DEAD}}
+
+void getCreatedConjuredSymbolLiveness(std::unique_ptr P) {
+  int *X = P.get();
+  clang_analyzer_warnOnDeadSymbol(X);
+  int Y;
+  if (!P) {
+Y = *P.get(); // expected-warning {{Dereference of null pointer [core.NullDereference]}}
+// expected-warning@-1 {{SYMBOL DEAD}}
+  }
+}
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
@@ -131,3 +131,112 @@
 void derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr P) {
   P.get()->foo(); // No warning.
 }
+
+void derefConditionOnNullPtrFalseBranch() {
+  std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}}
+  if (P) { // expected-note {{Taking false branch}}
+// expected-note@-1{{Smart pointer 'P' is nul}}
+P->foo(); // No warning.
+  } else {
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+// expected-note@-1{{Dereference of null smart pointer 'P'}}
+  }
+}
+
+void derefConditionOnNullPtrTrueBranch() {
+  std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}}
+  if (!P) { // expected-note {{Taking true branch}}
+// expected-note@-1{{Smart pointer 'P' is nul}}
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+// expected-note@-1{{Dereference of null smart pointer 'P'}}
+  }
+}
+
+void derefConditionOnValidPtrTrueBranch() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}}
+  if (P) { // expected-note {{Taking true branch}}
+// expected-note@-1{{Smart pointer 'P' is non-nul}}
+PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
+// expected-note@-1{{Dereference of null smart pointer 'PNull'}}
+  } else {
+PNull->foo(); // No warning
+  }
+}
+
+void derefConditionOnValidPtrFalseBranch() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}}
+  if (!P) { // 

[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-25 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:315-318
+SVal Val = I->second;
+for (auto si = Val.symbol_begin(), se = Val.symbol_end(); si != se; ++si) {
+  SR.markLive(*si);
+}

Yes, this looks correct, thanks!

In the ideal world we'd have checked that `I->first` is live before marking 
`I->second` live. Unfortunately, currently `checkLiveSymbols` is invoked before 
RegionStore's live symbols detection, so we can't rely on that and it's a bug; 
in order to be correct, RegionStore's live symbols detection and checker's live 
symbols callback should engage in fixpoint iteration.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:494-496
+  OS << "Smart pointer";
+  checkAndPrettyPrintRegion(OS, ThisRegion);
+  OS << " is non-null";

Because these note tags aren't specific to the bug report at hand, they have to 
be marked as //prunable// (i.e., the optional `getNoteTag()`'s parameter 
"`IsPrunable`" should be set to true). That'd reduce bug report clutter by not 
bringing in stack frames that aren't otherwise interesting for the bug report.

Something like this may act as a test (i didn't try):
```lang=c++
struct S {
  std::unique_ptr P;

  void foo() {
if (!P) { // no-note because foo() is pruned
  return;
}
  }

  int bar() {
P = new int(0);
foo();
return 1 / *P; // warning: division by zero
  }

}

```


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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


[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-24 Thread Nithin VR via Phabricator via cfe-commits
vrnithinkumar updated this revision to Diff 287512.
vrnithinkumar marked 11 inline comments as done.
vrnithinkumar added a comment.

- Adding checkLiveSymbols and review comments changes


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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

Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -8,12 +8,13 @@
 void clang_analyzer_warnIfReached();
 void clang_analyzer_numTimesReached();
 void clang_analyzer_eval(bool);
+void clang_analyzer_warnOnDeadSymbol(int *);
 
 void derefAfterMove(std::unique_ptr P) {
   std::unique_ptr Q = std::move(P);
   if (Q)
 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
-  *Q.get() = 1; // no-warning
+  *Q.get() = 1; // expected-warning {{Dereference of null pointer [core.NullDereference]}}
   if (P)
 clang_analyzer_warnIfReached(); // no-warning
   // TODO: Report a null dereference (instead).
@@ -276,3 +277,69 @@
 Y->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}}
   }
 }
+
+void derefConditionOnNullPtr() {
+  std::unique_ptr P;
+  if (P)
+P->foo(); // No warning.
+  else
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefConditionOnNotNullPtr() {
+  std::unique_ptr P;
+  if (!P)
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefConditionOnValidPtr() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull;
+  if (P)
+PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefConditionOnNotValidPtr() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull;
+  if (!P)
+PNull->foo(); // No warning.
+}
+
+void derefConditionOnUnKnownPtr(std::unique_ptr P) {
+  if (P)
+P->foo(); // No warning.
+  else
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefOnValidPtrAfterReset(std::unique_ptr P) {
+  P.reset(new A());
+  if (!P)
+P->foo(); // No warning.
+  else
+P->foo(); // No warning.
+}
+
+void innerPointerSymbolLiveness() {
+  std::unique_ptr P(new int());
+  clang_analyzer_warnOnDeadSymbol(P.get());
+  int *RP = P.release();
+} // expected-warning{{SYMBOL DEAD}}
+
+void boolOpCreatedConjuredSymbolLiveness(std::unique_ptr P) {
+  if (P) {
+int *X = P.get();
+clang_analyzer_warnOnDeadSymbol(X);
+  }
+} // expected-warning{{SYMBOL DEAD}}
+
+void getCreatedConjuredSymbolLiveness(std::unique_ptr P) {
+  int *X = P.get();
+  clang_analyzer_warnOnDeadSymbol(X);
+  int Y;
+  if (!P) {
+Y = *P.get(); // expected-warning {{Dereference of null pointer [core.NullDereference]}}
+// expected-warning@-1 {{SYMBOL DEAD}}
+  }
+}
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
@@ -131,3 +131,80 @@
 void derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr P) {
   P.get()->foo(); // No warning.
 }
+
+void derefConditionOnNullPtrFalseBranch() {
+  std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}}
+  if (P) { // expected-note {{Taking false branch}}
+// expected-note@-1{{Smart pointer 'P' is nul}}
+P->foo(); // No warning.
+  } else {
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+// expected-note@-1{{Dereference of null smart pointer 'P'}}
+  }
+}
+
+void derefConditionOnNullPtrTrueBranch() {
+  std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}}
+  if (!P) { // expected-note {{Taking true branch}}
+// expected-note@-1{{Smart pointer 'P' is nul}}
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+// expected-note@-1{{Dereference of null smart pointer 'P'}}
+  }
+}
+
+void derefConditionOnValidPtrTrueBranch() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}}
+  if (P) { // expected-note {{Taking true branch}}
+// expected-note@-1{{Smart pointer 'P' is non-nul}}
+PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
+// expected-note@-1{{Dereference of null smart pointer 'PNull'}}
+  } else {
+PNull->foo(); // No warning
+  }
+}
+
+void derefConditionOnValidPtrFalseBranch() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull; // expected-note 

[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-24 Thread Nithin VR via Phabricator via cfe-commits
vrnithinkumar added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:137
+  const auto *RecordDecl = MethodDecl->getParent();
+  if (!RecordDecl || !RecordDecl->getDeclContext()->isStdNamespace())
+return InnerType;

xazax.hun wrote:
> I'd rather use `Decl::isInStdNamespace` instead of querying the DeclContext 
> of the decl. The former is more robust with inline namespaces. 
Changed to use `Decl::isInStdNamespace`



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:141
+  const auto *TSD = dyn_cast(RecordDecl);
+  if (TSD) {
+auto TemplateArgs = TSD->getTemplateArgs().asArray();

xazax.hun wrote:
> Inverting this condition would reduce the indentation in the rest of the 
> function.
inverted the if condition



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:145
+TemplateArgs.size() > 0 &&
+"Smart pointer should have specialized with atleast one template 
type");
+auto InnerValueType = TemplateArgs[0].getAsType();

NoQ wrote:
> That's pretty fundamental, right? If it's a specialization, it must have 
> something specialized. It isn't specific to unique pointers, right?
> 
> Because unique pointers aren't special; technically anybody can define an 
> arbitrary class with name `std::unique_ptr` and any properties they'd like. 
> It's going to be undefined behavior according to the standard (because 
> namespace `std` is explicitly reserved for the standard library) but if the 
> compiler *crashes* it'll still be our fault.
> 
> 
added a check for `TemplateArgs.size() == 0` before accessing the first 
Template argument.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:147
+auto InnerValueType = TemplateArgs[0].getAsType();
+InnerType =
+C.getASTContext().getPointerType(InnerValueType.getCanonicalType());

xazax.hun wrote:
> You could return the real inner type here and replace all other returns with 
> `return {};` making the code a bit cleaner.
Updated to return with {}



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:404
 
+void SmartPtrModeling::handleBoolOperation(const CallEvent ,
+   CheckerContext ) const {

vsavchenko wrote:
> I suggest `BoolConversion`
yeah thats sounds better.
Changed.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:413
+  if (InnerPointVal) {
+bool IsInnerPtrNull = InnerPointVal->isZeroConstant();
+State = State->BindExpr(CallExpr, C.getLocationContext(),

xazax.hun wrote:
> Is this actually correct? What if the InnerPtr is an unconstrained symbol. In 
> that case, it is not a zero constant so we will assume that it is constrained 
> to non-zero. As far as I understand.
Fixed as you suggested in the below comments



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:432
+return;
+  } else {
+// In case of inner pointer SVal is not available we create

xazax.hun wrote:
> I'd do it the other way around as we discussed during the call.
> * Move the task of conjuring a new symbol to the beginning of the method.
> * Start by calling this function at the beginning of modeling operator bool.
> * The rest of the function could assume that there always is a symbol. It 
> could be constrained to be non-null, it could be the zero constant, or it 
> could be a completely unconstrained symbol. The latter will not work as 
> expected with your current implementation, see my comment above.
Made the changes as suggested above



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:448
+
+if (NullState) {
+  auto NullVal = C.getSValBuilder().makeNull();

xazax.hun wrote:
> NoQ wrote:
> > There's no need to check. You just conjured a brand new symbol out of thin 
> > air; you can be sure that it's completely unconstrained and both states are 
> > feasible. You can instead `assert()` that they're both feasible.
> I think instead of removing this check, this method should be reworked. I 
> think it might have some bugs, see my comment at the beginning of this method.
Refactored the method as suggested.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:458-460
+OS << "Assuming smart pointer ";
+ThisRegion->printPretty(OS);
+OS << " is null";

NoQ wrote:
> Wait, what happens when the region can't be pretty-printed? Does it print two 
> spaces between "pointer" and "is"?
Yes.
Created `checkAndPrettyPrintRegion` to check if the region can be pretty 
printed or not to avoid two spaces.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  

[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-24 Thread Valeriy Savchenko via Phabricator via cfe-commits
vsavchenko added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:404
 
+void SmartPtrModeling::handleBoolOperation(const CallEvent ,
+   CheckerContext ) const {

I suggest `BoolConversion`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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


[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-22 Thread Gábor Horváth via Phabricator via cfe-commits
xazax.hun requested changes to this revision.
xazax.hun added a comment.
This revision now requires changes to proceed.

Please add a test case, where the unique_ptr is initialized from a pointer 
parameter that has no assumptions. I think that case is not handled correctly.




Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:137
+  const auto *RecordDecl = MethodDecl->getParent();
+  if (!RecordDecl || !RecordDecl->getDeclContext()->isStdNamespace())
+return InnerType;

I'd rather use `Decl::isInStdNamespace` instead of querying the DeclContext of 
the decl. The former is more robust with inline namespaces. 



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:141
+  const auto *TSD = dyn_cast(RecordDecl);
+  if (TSD) {
+auto TemplateArgs = TSD->getTemplateArgs().asArray();

Inverting this condition would reduce the indentation in the rest of the 
function.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:147
+auto InnerValueType = TemplateArgs[0].getAsType();
+InnerType =
+C.getASTContext().getPointerType(InnerValueType.getCanonicalType());

You could return the real inner type here and replace all other returns with 
`return {};` making the code a bit cleaner.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:413
+  if (InnerPointVal) {
+bool IsInnerPtrNull = InnerPointVal->isZeroConstant();
+State = State->BindExpr(CallExpr, C.getLocationContext(),

Is this actually correct? What if the InnerPtr is an unconstrained symbol. In 
that case, it is not a zero constant so we will assume that it is constrained 
to non-zero. As far as I understand.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:432
+return;
+  } else {
+// In case of inner pointer SVal is not available we create

I'd do it the other way around as we discussed during the call.
* Move the task of conjuring a new symbol to the beginning of the method.
* Start by calling this function at the beginning of modeling operator bool.
* The rest of the function could assume that there always is a symbol. It could 
be constrained to be non-null, it could be the zero constant, or it could be a 
completely unconstrained symbol. The latter will not work as expected with your 
current implementation, see my comment above.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:448
+
+if (NullState) {
+  auto NullVal = C.getSValBuilder().makeNull();

NoQ wrote:
> There's no need to check. You just conjured a brand new symbol out of thin 
> air; you can be sure that it's completely unconstrained and both states are 
> feasible. You can instead `assert()` that they're both feasible.
I think instead of removing this check, this method should be reworked. I think 
it might have some bugs, see my comment at the beginning of this method.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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


[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-22 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:130
+// Returns empty type if not found valid inner pointer type.
+static QualType getInnerPointerType(const CallEvent , CheckerContext ) {
+  QualType InnerType{};

vrnithinkumar wrote:
> It seems like a long shot to me.
> I am not sure is there any direct or easy way to get inner pointer type from 
> a smart pointer  
That's about right. You're doing exactly what you're asked: grab the template 
parameter of the class. The problem is indeed that complicated!



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:145
+TemplateArgs.size() > 0 &&
+"Smart pointer should have specialized with atleast one template 
type");
+auto InnerValueType = TemplateArgs[0].getAsType();

That's pretty fundamental, right? If it's a specialization, it must have 
something specialized. It isn't specific to unique pointers, right?

Because unique pointers aren't special; technically anybody can define an 
arbitrary class with name `std::unique_ptr` and any properties they'd like. 
It's going to be undefined behavior according to the standard (because 
namespace `std` is explicitly reserved for the standard library) but if the 
compiler *crashes* it'll still be our fault.





Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:448
+
+if (NullState) {
+  auto NullVal = C.getSValBuilder().makeNull();

There's no need to check. You just conjured a brand new symbol out of thin air; 
you can be sure that it's completely unconstrained and both states are 
feasible. You can instead `assert()` that they're both feasible.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:458-460
+OS << "Assuming smart pointer ";
+ThisRegion->printPretty(OS);
+OS << " is null";

Wait, what happens when the region can't be pretty-printed? Does it print two 
spaces between "pointer" and "is"?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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


[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-19 Thread Nithin VR via Phabricator via cfe-commits
vrnithinkumar added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:130
+// Returns empty type if not found valid inner pointer type.
+static QualType getInnerPointerType(const CallEvent , CheckerContext ) {
+  QualType InnerType{};

It seems like a long shot to me.
I am not sure is there any direct or easy way to get inner pointer type from a 
smart pointer  


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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


[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-19 Thread Nithin VR via Phabricator via cfe-commits
vrnithinkumar updated this revision to Diff 286632.
vrnithinkumar marked 5 inline comments as done.
vrnithinkumar added a comment.

Changes to use conjureSymbolVal if the inner pointer value is missing


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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

Index: clang/test/Analysis/smart-ptr.cpp
===
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -252,3 +252,46 @@
   P->foo(); // No warning.
   PValid->foo(); // No warning.
 }
+
+void derefConditionOnNullPtr() {
+  std::unique_ptr P;
+  if (P)
+P->foo(); // No warning.
+  else
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefConditionOnNotNullPtr() {
+  std::unique_ptr P;
+  if (!P)
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefConditionOnValidPtr() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull;
+  if (P)
+PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefConditionOnNotValidPtr() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull;
+  if (!P)
+PNull->foo(); // No warning.
+}
+
+void derefConditionOnUnKnownPtr(std::unique_ptr P) {
+  if (P)
+P->foo(); // No warning.
+  else
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefOnValidPtrAfterReset(std::unique_ptr P) {
+  P.reset(new A());
+  if (!P)
+P->foo(); // No warning.
+  else
+P->foo(); // No warning.
+}
Index: clang/test/Analysis/smart-ptr-text-output.cpp
===
--- clang/test/Analysis/smart-ptr-text-output.cpp
+++ clang/test/Analysis/smart-ptr-text-output.cpp
@@ -116,3 +116,80 @@
   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' of type 'std::unique_ptr' [cplusplus.Move]}}
   // expected-note@-1 {{Dereference of null smart pointer 'P' of type 'std::unique_ptr'}}
 }
+
+void derefConditionOnNullPtrFalseBranch() {
+  std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}}
+  if (P) { // expected-note {{Taking false branch}}
+// expected-note@-1{{Smart pointer 'P' is nul}}
+P->foo(); // No warning.
+  } else {
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+// expected-note@-1{{Dereference of null smart pointer 'P'}}
+  }
+}
+
+void derefConditionOnNullPtrTrueBranch() {
+  std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}}
+  if (!P) { // expected-note {{Taking true branch}}
+// expected-note@-1{{Smart pointer 'P' is nul}}
+P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+// expected-note@-1{{Dereference of null smart pointer 'P'}}
+  }
+}
+
+void derefConditionOnValidPtrTrueBranch() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}}
+  if (P) { // expected-note {{Taking true branch}}
+// expected-note@-1{{Smart pointer 'P' is non-nul}}
+PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
+// expected-note@-1{{Dereference of null smart pointer 'PNull'}}
+  } else {
+PNull->foo(); // No warning
+  }
+}
+
+void derefConditionOnValidPtrFalseBranch() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}}
+  if (!P) { // expected-note {{Taking false branch}}
+// expected-note@-1{{Smart pointer 'P' is non-nul}}
+PNull->foo(); // No warning
+  } else {
+PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
+// expected-note@-1{{Dereference of null smart pointer 'PNull'}}
+  }
+}
+
+void derefConditionOnNotValidPtr() {
+  std::unique_ptr P(new A());
+  std::unique_ptr PNull;
+  if (!P)
+PNull->foo(); // No warning.
+}
+
+void derefConditionOnUnKnownPtrAssumeNull(std::unique_ptr P) {
+  std::unique_ptr PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}}
+  if (!P) { // expected-note {{Taking true branch}}
+// expected-note@-1{{Assuming smart pointer 'P' is null}}
+PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}}
+// expected-note@-1{{Dereference of null smart pointer 'PNull'}}
+  }
+}
+
+void derefConditionOnUnKnownPtrAssumeNonNull(std::unique_ptr P) {
+  std::unique_ptr PNull; // expected-note {{Default 

[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-19 Thread Nithin VR via Phabricator via cfe-commits
vrnithinkumar added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:147
 
-if (!move::isMovedFrom(State, ThisR)) {
-  // TODO: Model this case as well. At least, avoid invalidation of
-  // globals.
-  return false;
+if (ModelSmartPtrDereference) {
+  handleBoolOperation(Call, C);

xazax.hun wrote:
> vrnithinkumar wrote:
> > This seems little messy here.
> > I guess once we model the `std::move` for smart ptr it will be less messy 
> I agree. `isNullAfterMoveMethod` is especially confusing as it does not do 
> what the name of the function says. It checks if the `Call` is a boolean 
> conversion operator. I'd suggest renaming that method to make this code a bit 
> more sensible. 
> 
> Moreover, when `ModelSmartPtrDereference` is true, we no longer model moves 
> below right? I think a comment that this logic is duplicated 
> `handleBoolOperation` might make the code cleaner. 
> 
> But yeah, this needs to be cleaned up, hopefully really soon.
- Renamed the method to `isBooleanOpMethod`
- Added comments and FIXME
Hopefully we can clean up once `std::move` is modeled.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:389
+}
+C.addTransition(State);
+  } else if (move::isMovedFrom(State, ThisRegion)) {

xazax.hun wrote:
> This looks fine for now, but we often prefer adding a return after each case 
> to avoid executing multiple `addTransition`s accidentally after refactoring.
Added return



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:411
+  if (NotNullState) {
+auto NonNullVal = C.getSValBuilder().makeTruthVal(true);
+NotNullState =

NoQ wrote:
> vrnithinkumar wrote:
> > Since the inner pointer value can be any non-null value, I am not sure what 
> > should be the value to be added to the map for tracking.
> > 
> Don't add values, constrain existing values.
Made changes to create the conjured symbol and use that to constrain. 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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


[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-17 Thread Gábor Horváth via Phabricator via cfe-commits
xazax.hun added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:147
 
-if (!move::isMovedFrom(State, ThisR)) {
-  // TODO: Model this case as well. At least, avoid invalidation of
-  // globals.
-  return false;
+if (ModelSmartPtrDereference) {
+  handleBoolOperation(Call, C);

vrnithinkumar wrote:
> This seems little messy here.
> I guess once we model the `std::move` for smart ptr it will be less messy 
I agree. `isNullAfterMoveMethod` is especially confusing as it does not do what 
the name of the function says. It checks if the `Call` is a boolean conversion 
operator. I'd suggest renaming that method to make this code a bit more 
sensible. 

Moreover, when `ModelSmartPtrDereference` is true, we no longer model moves 
below right? I think a comment that this logic is duplicated 
`handleBoolOperation` might make the code cleaner. 

But yeah, this needs to be cleaned up, hopefully really soon.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:389
+}
+C.addTransition(State);
+  } else if (move::isMovedFrom(State, ThisRegion)) {

This looks fine for now, but we often prefer adding a return after each case to 
avoid executing multiple `addTransition`s accidentally after refactoring.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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


[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-15 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:400
+  ProgramStateRef NotNullState, NullState;
+  std::tie(NotNullState, NullState) = 
State->assume(CallExprVal.getValue());
+

vrnithinkumar wrote:
> NoQ wrote:
> > It's always `UnknownVal` because the call has not been evaluated yet. This 
> > `assume()` does nothing.
> Okay.
> So in that case the `NotNullState` and `NullState` will be same as the 
> original state?
Yup.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:411
+  if (NotNullState) {
+auto NonNullVal = C.getSValBuilder().makeTruthVal(true);
+NotNullState =

vrnithinkumar wrote:
> Since the inner pointer value can be any non-null value, I am not sure what 
> should be the value to be added to the map for tracking.
> 
Don't add values, constrain existing values.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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


[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-15 Thread Nithin VR via Phabricator via cfe-commits
vrnithinkumar added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:400
+  ProgramStateRef NotNullState, NullState;
+  std::tie(NotNullState, NullState) = 
State->assume(CallExprVal.getValue());
+

NoQ wrote:
> It's always `UnknownVal` because the call has not been evaluated yet. This 
> `assume()` does nothing.
Okay.
So in that case the `NotNullState` and `NullState` will be same as the original 
state?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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


[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-15 Thread Nithin VR via Phabricator via cfe-commits
vrnithinkumar added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:411
+  if (NotNullState) {
+auto NonNullVal = C.getSValBuilder().makeTruthVal(true);
+NotNullState =

Since the inner pointer value can be any non-null value, I am not sure what 
should be the value to be added to the map for tracking.



Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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


[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-15 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:400
+  ProgramStateRef NotNullState, NullState;
+  std::tie(NotNullState, NullState) = 
State->assume(CallExprVal.getValue());
+

It's always `UnknownVal` because the call has not been evaluated yet. This 
`assume()` does nothing.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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


[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-15 Thread Nithin VR via Phabricator via cfe-commits
vrnithinkumar added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp:147
 
-if (!move::isMovedFrom(State, ThisR)) {
-  // TODO: Model this case as well. At least, avoid invalidation of
-  // globals.
-  return false;
+if (ModelSmartPtrDereference) {
+  handleBoolOperation(Call, C);

This seems little messy here.
I guess once we model the `std::move` for smart ptr it will be less messy 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86027

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


[PATCH] D86027: [analyzer] Add bool operator modeling for unque_ptr

2020-08-15 Thread Nithin VR via Phabricator via cfe-commits
vrnithinkumar created this revision.
Herald added subscribers: cfe-commits, steakhal, ASDenysPetrov, martong, 
Charusso, dkrupp, donat.nagy, Szelethus, mikhail.ramalho, a.sidorin, szepet, 
baloghadamsoftware, xazax.hun.
Herald added a project: clang.
vrnithinkumar requested review of this revision.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D86027

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
@@ -87,6 +87,7 @@
 void derefAfterResetWithNonNull() {
   std::unique_ptr P;
   P.reset(new A());
+  clang_analyzer_numTimesReached(); // expected-warning {{1}}
   P->foo(); // No warning.
 }
 
@@ -117,36 +118,39 @@
 void pass_smart_ptr_by_const_ptr(const std::unique_ptr *a);
 
 void regioninvalidationTest() {
-  {
-std::unique_ptr P;
-pass_smart_ptr_by_ref(P);
-P->foo(); // no-warning
-  }
-  {
-std::unique_ptr P;
-pass_smart_ptr_by_const_ref(P);
-P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
-  }
-  {
-std::unique_ptr P;
-pass_smart_ptr_by_rvalue_ref(std::move(P));
-P->foo(); // no-warning
-  }
-  {
-std::unique_ptr P;
-pass_smart_ptr_by_const_rvalue_ref(std::move(P));
-P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
-  }
-  {
-std::unique_ptr P;
-pass_smart_ptr_by_ptr();
-P->foo();
-  }
-  {
-std::unique_ptr P;
-pass_smart_ptr_by_const_ptr();
-P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
-  }
+  std::unique_ptr P;
+  pass_smart_ptr_by_ref(P);
+  P->foo(); // no-warning
+}
+
+void regioninvalidationTest1() {
+  std::unique_ptr P;
+  pass_smart_ptr_by_const_ref(P);
+  P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void regioninvalidationTest2() {
+  std::unique_ptr P;
+  pass_smart_ptr_by_rvalue_ref(std::move(P));
+  P->foo(); // no-warning
+}
+
+void regioninvalidationTest3() {
+  std::unique_ptr P;
+  pass_smart_ptr_by_const_rvalue_ref(std::move(P));
+  P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void regioninvalidationTest4() {
+  std::unique_ptr P;
+  pass_smart_ptr_by_ptr();
+  P->foo();
+}
+
+void regioninvalidationTest5() {
+  std::unique_ptr P;
+  pass_smart_ptr_by_const_ptr();
+  P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
 }
 
 struct StructWithSmartPtr {
@@ -161,36 +165,39 @@
 void pass_struct_with_smart_ptr_by_const_ptr(const StructWithSmartPtr *a);
 
 void regioninvalidationTestWithinStruct() {
-  {
-StructWithSmartPtr S;
-pass_struct_with_smart_ptr_by_ref(S);
-S.P->foo(); // no-warning
-  }
-  {
-StructWithSmartPtr S;
-pass_struct_with_smart_ptr_by_const_ref(S);
-S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}}
-  }
-  {
-StructWithSmartPtr S;
-pass_struct_with_smart_ptr_by_rvalue_ref(std::move(S));
-S.P->foo(); // no-warning
-  }
-  {
-StructWithSmartPtr S;
-pass_struct_with_smart_ptr_by_const_rvalue_ref(std::move(S));
-S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}}
-  }
-  {
-StructWithSmartPtr S;
-pass_struct_with_smart_ptr_by_ptr();
-S.P->foo();
-  }
-  {
-StructWithSmartPtr S;
-pass_struct_with_smart_ptr_by_const_ptr();
-S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}}
-  }
+  StructWithSmartPtr S;
+  pass_struct_with_smart_ptr_by_ref(S);
+  S.P->foo(); // no-warning
+}
+
+void regioninvalidationTestWithinStruct2() {
+  StructWithSmartPtr S;
+  pass_struct_with_smart_ptr_by_const_ref(S);
+  S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void regioninvalidationTestWithinStruct3() {
+  StructWithSmartPtr S;
+  pass_struct_with_smart_ptr_by_rvalue_ref(std::move(S));
+  S.P->foo(); // no-warning
+}
+
+void regioninvalidationTestWithinStruct4() {
+  StructWithSmartPtr S;
+  pass_struct_with_smart_ptr_by_const_rvalue_ref(std::move(S));
+  S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void regioninvalidationTestWithinStruct5() {
+  StructWithSmartPtr S;
+  pass_struct_with_smart_ptr_by_ptr();
+  S.P->foo(); // no-warning
+}
+
+void regioninvalidationTestWithinStruct6() {
+  StructWithSmartPtr S;
+  pass_struct_with_smart_ptr_by_const_ptr();
+  S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}}
 }
 
 void derefAfterAssignment() {
@@ -217,14