[PATCH] D54556: [analyzer] MoveChecker Pt.1: Give MisusedMovedObject checker a more consistent name.

2018-12-03 Thread Phabricator via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rC348201: [analyzer] Rename MisusedMovedObjectChecker to 
MoveChecker (authored by dergachev, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D54556?vs=174123=176484#toc

Repository:
  rC Clang

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

https://reviews.llvm.org/D54556

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
  lib/StaticAnalyzer/Checkers/MoveChecker.cpp
  test/Analysis/MisusedMovedObject.cpp
  test/Analysis/use-after-move.cpp

Index: include/clang/StaticAnalyzer/Checkers/Checkers.td
===
--- include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -303,9 +303,8 @@
   HelpText<"Check for use of iterators of different containers where iterators "
"of the same container are expected">;
 
-def MisusedMovedObjectChecker: Checker<"MisusedMovedObject">,
- HelpText<"Method calls on a moved-from object and copying a moved-from "
-  "object will be reported">;
+def MoveChecker: Checker<"Move">,
+ HelpText<"Find use-after-move bugs in C++">;
 
 def UninitializedObjectChecker: Checker<"UninitializedObject">,
  HelpText<"Reports uninitialized fields after object construction">;
Index: test/Analysis/use-after-move.cpp
===
--- test/Analysis/use-after-move.cpp
+++ test/Analysis/use-after-move.cpp
@@ -0,0 +1,716 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.cplusplus.Move -verify %s\
+// RUN:  -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\
+// RUN:  -analyzer-config exploration_strategy=unexplored_first_queue
+// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.cplusplus.Move -verify %s\
+// RUN:  -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\
+// RUN:  -analyzer-config exploration_strategy=dfs -DDFS=1
+
+namespace std {
+
+template 
+struct remove_reference;
+
+template 
+struct remove_reference { typedef _Tp type; };
+
+template 
+struct remove_reference<_Tp &> { typedef _Tp type; };
+
+template 
+struct remove_reference<_Tp &&> { typedef _Tp type; };
+
+template 
+typename remove_reference<_Tp>::type &(_Tp &&__t) {
+  return static_cast::type &&>(__t);
+}
+
+template 
+_Tp &(typename remove_reference<_Tp>::type &__t) noexcept {
+  return static_cast<_Tp &&>(__t);
+}
+
+template 
+void swap(T , T ) {
+  T c(std::move(a));
+  a = std::move(b);
+  b = std::move(c);
+}
+
+} // namespace std
+
+class B {
+public:
+  B() = default;
+  B(const B &) = default;
+  B(B &&) = default;
+  B& operator=(const B ) = default;
+  void operator=(B &) {
+return;
+  }
+  void foo() { return; }
+};
+
+class A {
+  int i;
+  double d;
+
+public:
+  B b;
+  A(int ii = 42, double dd = 1.0) : d(dd), i(ii), b(B()) {}
+  void moveconstruct(A &) {
+std::swap(b, other.b);
+std::swap(d, other.d);
+std::swap(i, other.i);
+return;
+  }
+  static A get() {
+A v(12, 13);
+return v;
+  }
+  A(A *a) {
+moveconstruct(std::move(*a));
+  }
+  A(const A ) : i(other.i), d(other.d), b(other.b) {}
+  A(A &) : i(other.i), d(other.d), b(std::move(other.b)) { // expected-note {{'b' became 'moved-from' here}}
+  }
+  A(A &, char *k) {
+moveconstruct(std::move(other));
+  }
+  void operator=(const A ) {
+i = other.i;
+d = other.d;
+b = other.b;
+return;
+  }
+  void operator=(A &) {
+moveconstruct(std::move(other));
+return;
+  }
+  int getI() { return i; }
+  int foo() const;
+  void bar() const;
+  void reset();
+  void destroy();
+  void clear();
+  bool empty() const;
+  bool isEmpty() const;
+  operator bool() const;
+};
+
+int bignum();
+
+void moveInsideFunctionCall(A a) {
+  A b = std::move(a);
+}
+void leftRefCall(A ) {
+  a.foo();
+}
+void rightRefCall(A &) {
+  a.foo();
+}
+void constCopyOrMoveCall(const A a) {
+  a.foo();
+}
+
+void copyOrMoveCall(A a) {
+  a.foo();
+}
+
+void simpleMoveCtorTest() {
+  {
+A a;
+A b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
+a.foo();// expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
+  }
+  {
+A a;
+A b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
+b = a;  // expected-warning {{Copying a 'moved-from' object 'a'}} expected-note {{Copying a 'moved-from' object 'a'}}
+  }
+  {
+A a;
+A b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
+b = std::move(a);   // expected-warning {{Moving a 'moved-from' object 'a'}} expected-note {{Moving a 'moved-from' object 'a'}}
+  }
+}
+
+void simpleMoveAssignementTest() {
+  {
+A a;
+A b;
+b = std::move(a); 

[PATCH] D54556: [analyzer] MoveChecker Pt.1: Give MisusedMovedObject checker a more consistent name.

2018-11-15 Thread Umann Kristóf via Phabricator via cfe-commits
Szelethus accepted this revision.
Szelethus added a comment.

LGTM, both the concept and the patch! I have read your followup patches up to 
part 4, I'll leave some thoughts there.


Repository:
  rC Clang

https://reviews.llvm.org/D54556



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


[PATCH] D54556: [analyzer] MoveChecker Pt.1: Give MisusedMovedObject checker a more consistent name.

2018-11-15 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.

Looks good. Do we plan to detect problems other than use after move? Maybe it 
would be worth to synchronize with the tidy checker name use-after-move or is 
it going to cause more confusion?


Repository:
  rC Clang

https://reviews.llvm.org/D54556



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


[PATCH] D54556: [analyzer] MoveChecker Pt.1: Give MisusedMovedObject checker a more consistent name.

2018-11-14 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ created this revision.
NoQ added reviewers: dcoughlin, xazax.hun, a.sidorin, george.karpenkov, szepet, 
rnkovacs, Szelethus.
Herald added subscribers: cfe-commits, dkrupp, donat.nagy, mikhail.ramalho, 
baloghadamsoftware, mgorny.
NoQ edited the summary of this revision.
NoQ added a dependency: D54372: [analyzer] MisusedMovedObject: NFC: Remove dead 
code after D18860.

I'd like to try to enable the use-after-move checker developed heroically by 
Peter "@szepet" Szecsi by default. While currently being a good opt-in lint 
check for enforcing coding style, currently it has too many false positives for 
an on-by-default check. The false positives seem to concentrate around objects 
that are fine to be used after they were moved from, even if no "state reset" 
method has been called on them, simply because their respective 
move-constructor/move-assignment leaves the object that is being moved in a 
well-specified state (eg., a null smart pointer or an empty set). This is not 
the case for STL objects, but it is the case for many custom objects.

I'll proceed to post a few patches and i'd love to hear your thoughts! The plan 
(of which this patch implements the first step) is as follows:

1. Rename the checker. In our tradition, "XChecker" usually means a checker 
that checks if "X" is used correctly, not a checker that finds "X". Eg., 
MallocChecker warns on misuse of malloc()/free(), but we don't call it 
"MisusedMallocChecker". The proposed name is "MoveChecker", i.e. checker that 
checks moves.
2. Address false positives under an on-by-default checker option. The proposed 
idea is to only warn by default in the following three cases:
  - If the object is a known STL object - because we know that it's left in 
unspecified state after move and we can memorize all state reset methods.
  - If the object is a local (or parameter) variable and hence there's no 
temptation to re-use the storage instead of making another local variable.
  - If the object is taken from a local (or parameter) rvalue reference, for 
the same reason.
3. Make warning messages more specific based information provided by facilities 
introduced on step 2.
4. Add a few missing state-reset methods.
5. Enable the checker, as restricted on step 2, by default. Keep the aggressive 
variant around in case someone needs it, but i don't have any specific plans 
for it.


Repository:
  rC Clang

https://reviews.llvm.org/D54556

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
  lib/StaticAnalyzer/Checkers/MoveChecker.cpp
  test/Analysis/MisusedMovedObject.cpp
  test/Analysis/use-after-move.cpp

Index: test/Analysis/use-after-move.cpp
===
--- test/Analysis/use-after-move.cpp
+++ test/Analysis/use-after-move.cpp
@@ -1,5 +1,9 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.MisusedMovedObject -std=c++11 -verify -analyzer-output=text -analyzer-config exploration_strategy=unexplored_first_queue,eagerly-assume=false %s
-// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.MisusedMovedObject -std=c++11 -analyzer-config exploration_strategy=dfs,eagerly-assume=false -verify -analyzer-output=text -DDFS=1 %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.cplusplus.Move -verify %s\
+// RUN:  -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\
+// RUN:  -analyzer-config exploration_strategy=unexplored_first_queue
+// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.cplusplus.Move -verify %s\
+// RUN:  -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\
+// RUN:  -analyzer-config exploration_strategy=dfs -DDFS=1
 
 namespace std {
 
Index: lib/StaticAnalyzer/Checkers/MoveChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/MoveChecker.cpp
+++ lib/StaticAnalyzer/Checkers/MoveChecker.cpp
@@ -1,4 +1,4 @@
-// MisusedMovedObjectChecker.cpp - Check use of moved-from objects. - C++ -===//
+// MoveChecker.cpp - Check use of moved-from objects. - C++ ---===//
 //
 // The LLVM Compiler Infrastructure
 //
@@ -42,7 +42,7 @@
   void Profile(llvm::FoldingSetNodeID ) const { ID.AddInteger(K); }
 };
 
-class MisusedMovedObjectChecker
+class MoveChecker
 : public Checker {
 public:
@@ -116,9 +116,8 @@
 }
 
 std::shared_ptr
-MisusedMovedObjectChecker::MovedBugVisitor::VisitNode(const ExplodedNode *N,
-  BugReporterContext ,
-  BugReport &) {
+MoveChecker::MovedBugVisitor::VisitNode(const ExplodedNode *N,
+BugReporterContext , BugReport &) {
   // We need only the last move of the reported object's region.
   // The visitor walks the ExplodedGraph backwards.
   if (Found)
@@ -156,8 +155,9 @@