This revision was not accepted when it landed; it landed in state "Needs 
Review".
This revision was automatically updated to reflect the committed changes.
Closed by commit rL349327: [analyzer] MoveChecker: Add an option to suppress 
warnings on locals. (authored by dergachev, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D55730?vs=178322&id=178427#toc

Repository:
  rL LLVM

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

https://reviews.llvm.org/D55730

Files:
  cfe/trunk/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
  cfe/trunk/test/Analysis/use-after-move.cpp

Index: cfe/trunk/test/Analysis/use-after-move.cpp
===================================================================
--- cfe/trunk/test/Analysis/use-after-move.cpp
+++ cfe/trunk/test/Analysis/use-after-move.cpp
@@ -9,12 +9,22 @@
 // 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:  -analyzer-config alpha.cplusplus.Move:Aggressive=true -DAGGRESSIVE\
+// RUN:  -analyzer-config alpha.cplusplus.Move:WarnOn=KnownsOnly -DPEACEFUL\
 // RUN:  -analyzer-checker debug.ExprInspection
 // 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\
-// RUN:  -analyzer-config alpha.cplusplus.Move:Aggressive=true -DAGGRESSIVE\
+// RUN:  -analyzer-config alpha.cplusplus.Move:WarnOn=KnownsOnly -DPEACEFUL\
+// RUN:  -analyzer-checker debug.ExprInspection
+// 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:  -analyzer-config alpha.cplusplus.Move:WarnOn=All -DAGGRESSIVE\
+// RUN:  -analyzer-checker debug.ExprInspection
+// 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\
+// RUN:  -analyzer-config alpha.cplusplus.Move:WarnOn=All -DAGGRESSIVE\
 // RUN:  -analyzer-checker debug.ExprInspection
 
 #include "Inputs/system-header-simulator-cxx.h"
@@ -119,18 +129,33 @@
 void simpleMoveCtorTest() {
   {
     A a;
-    A b = std::move(a); // expected-note {{Object 'a' is moved}}
-    a.foo();            // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
+    A b = std::move(a);
+    a.foo();
+#ifndef PEACEFUL
+    // expected-note@-3 {{Object 'a' is moved}}
+    // expected-warning@-3 {{Method called on moved-from object 'a'}}
+    // expected-note@-4    {{Method called on moved-from object 'a'}}
+#endif
   }
   {
     A a;
-    A b = std::move(a); // expected-note {{Object 'a' is moved}}
-    b = a;              // expected-warning {{Moved-from object 'a' is copied}} expected-note {{Moved-from object 'a' is copied}}
+    A b = std::move(a);
+    b = a;
+#ifndef PEACEFUL
+    // expected-note@-3 {{Object 'a' is moved}}
+    // expected-warning@-3 {{Moved-from object 'a' is copied}}
+    // expected-note@-4    {{Moved-from object 'a' is copied}}
+#endif
   }
   {
     A a;
-    A b = std::move(a); // expected-note {{Object 'a' is moved}}
-    b = std::move(a);   // expected-warning {{Moved-from object 'a' is moved}} expected-note {{Moved-from object 'a' is moved}}
+    A b = std::move(a);
+    b = std::move(a);
+#ifndef PEACEFUL
+    // expected-note@-3 {{Object 'a' is moved}}
+    // expected-warning@-3 {{Moved-from object 'a' is moved}}
+    // expected-note@-4    {{Moved-from object 'a' is moved}}
+#endif
   }
 }
 
@@ -138,20 +163,35 @@
   {
     A a;
     A b;
-    b = std::move(a); // expected-note {{Object 'a' is moved}}
-    a.foo();          // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
+    b = std::move(a);
+    a.foo();
+#ifndef PEACEFUL
+    // expected-note@-3 {{Object 'a' is moved}}
+    // expected-warning@-3 {{Method called on moved-from object 'a'}}
+    // expected-note@-4    {{Method called on moved-from object 'a'}}
+#endif
   }
   {
     A a;
     A b;
-    b = std::move(a); // expected-note {{Object 'a' is moved}}
-    A c(a);           // expected-warning {{Moved-from object 'a' is copied}} expected-note {{Moved-from object 'a' is copied}}
+    b = std::move(a);
+    A c(a);
+#ifndef PEACEFUL
+    // expected-note@-3 {{Object 'a' is moved}}
+    // expected-warning@-3 {{Moved-from object 'a' is copied}}
+    // expected-note@-4    {{Moved-from object 'a' is copied}}
+#endif
   }
   {
     A a;
     A b;
-    b = std::move(a);  // expected-note {{Object 'a' is moved}}
-    A c(std::move(a)); // expected-warning {{Moved-from object 'a' is moved}} expected-note {{Moved-from object 'a' is moved}}
+    b = std::move(a);
+    A c(std::move(a));
+#ifndef PEACEFUL
+    // expected-note@-3 {{Object 'a' is moved}}
+    // expected-warning@-3 {{Moved-from object 'a' is moved}}
+    // expected-note@-4    {{Moved-from object 'a' is moved}}
+#endif
   }
 }
 
@@ -160,8 +200,13 @@
     A a;
   };
   A a;
-  S s{std::move(a)}; // expected-note {{Object 'a' is moved}}
-  a.foo();           // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
+  S s{std::move(a)};
+  a.foo();
+#ifndef PEACEFUL
+  // expected-note@-3 {{Object 'a' is moved}}
+  // expected-warning@-3 {{Method called on moved-from object 'a'}}
+  // expected-note@-4 {{Method called on moved-from object 'a'}}
+#endif
 }
 
 // Don't report a bug if the variable was assigned to in the meantime.
@@ -175,23 +220,43 @@
   }
   {
     A a;
-    if (i == 1) { // expected-note {{Assuming 'i' is not equal to 1}} expected-note {{Taking false branch}}
-      // expected-note@-1 {{Assuming 'i' is not equal to 1}} expected-note@-1 {{Taking false branch}}
+    if (i == 1) {
+#ifndef PEACEFUL
+      // expected-note@-2 {{Assuming 'i' is not equal to 1}}
+      // expected-note@-3 {{Taking false branch}}
+      // And the other report:
+      // expected-note@-5 {{Assuming 'i' is not equal to 1}}
+      // expected-note@-6 {{Taking false branch}}
+#endif
       A b;
       b = std::move(a);
       a = A();
     }
-    if (i == 2) { // expected-note {{Assuming 'i' is not equal to 2}} expected-note {{Taking false branch}}
-      //expected-note@-1 {{Assuming 'i' is not equal to 2}} expected-note@-1 {{Taking false branch}}
+    if (i == 2) {
+#ifndef PEACEFUL
+      // expected-note@-2 {{Assuming 'i' is not equal to 2}}
+      // expected-note@-3 {{Taking false branch}}
+      // And the other report:
+      // expected-note@-5 {{Assuming 'i' is not equal to 2}}
+      // expected-note@-6 {{Taking false branch}}
+#endif
       a.foo();    // no-warning
     }
   }
   {
     A a;
-    if (i == 1) { // expected-note {{Taking false branch}} expected-note {{Taking false branch}}
+    if (i == 1) {
+#ifndef PEACEFUL
+      // expected-note@-2 {{Taking false branch}}
+      // expected-note@-3 {{Taking false branch}}
+#endif
       std::move(a);
     }
-    if (i == 2) { // expected-note {{Taking false branch}} expected-note {{Taking false branch}}
+    if (i == 2) {
+#ifndef PEACEFUL
+      // expected-note@-2 {{Taking false branch}}
+      // expected-note@-3 {{Taking false branch}}
+#endif
       a = A();
       a.foo();
     }
@@ -209,19 +274,36 @@
     A b;
     b = std::move(a);
     a = A();
-    b = std::move(a); // expected-note {{Object 'a' is moved}}
-    a.foo();          // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
+    b = std::move(a);
+    a.foo();
+#ifndef PEACEFUL
+    // expected-note@-3 {{Object 'a' is moved}}
+    // expected-warning@-3 {{Method called on moved-from object 'a'}}
+    // expected-note@-4    {{Method called on moved-from object 'a'}}
+#endif
   }
   // If a path exist where we not reinitialize the variable we report a bug.
   {
     A a;
     A b;
-    b = std::move(a); // expected-note {{Object 'a' is moved}}
-    if (i < 10) {     // expected-note {{Assuming 'i' is >= 10}} expected-note {{Taking false branch}}
+    b = std::move(a);
+#ifndef PEACEFUL
+    // expected-note@-2 {{Object 'a' is moved}}
+#endif
+    if (i < 10) {
+#ifndef PEACEFUL
+      // expected-note@-2 {{Assuming 'i' is >= 10}}
+      // expected-note@-3 {{Taking false branch}}
+#endif
       a = A();
     }
-    if (i > 5) { // expected-note {{Taking true branch}}
-      a.foo();   // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
+    if (i > 5) {
+      a.foo();
+#ifndef PEACEFUL
+      // expected-note@-3 {{Taking true branch}}
+      // expected-warning@-3 {{Method called on moved-from object 'a'}}
+      // expected-note@-4    {{Method called on moved-from object 'a'}}
+#endif
     }
   }
 }
@@ -236,79 +318,117 @@
 void loopTest() {
   {
     A a;
-    for (int i = 0; i < bignum(); i++) { // expected-note {{Loop condition is false. Execution jumps to the end of the function}}
+    for (int i = 0; i < bignum(); i++) {
+#ifndef PEACEFUL
+      // expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
+#endif
       rightRefCall(std::move(a));        // no-warning
     }
   }
   {
     A a;
-    for (int i = 0; i < 2; i++) { // expected-note {{Loop condition is true.  Entering loop body}}
-      //expected-note@-1 {{Loop condition is true.  Entering loop body}}
-			//expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
+    for (int i = 0; i < 2; i++) {
+#ifndef PEACEFUL
+      // expected-note@-2 {{Loop condition is true.  Entering loop body}}
+      // expected-note@-3 {{Loop condition is true.  Entering loop body}}
+      // expected-note@-4 {{Loop condition is false. Execution jumps to the end of the function}}
+#endif
       rightRefCall(std::move(a)); // no-warning
     }
   }
   {
     A a;
-    for (int i = 0; i < bignum(); i++) { // expected-note {{Loop condition is false. Execution jumps to the end of the function}}
+    for (int i = 0; i < bignum(); i++) {
+#ifndef PEACEFUL
+      // expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
+#endif
       leftRefCall(a);                    // no-warning
     }
   }
   {
     A a;
-    for (int i = 0; i < 2; i++) { // expected-note {{Loop condition is true.  Entering loop body}} 
-      //expected-note@-1 {{Loop condition is true.  Entering loop body}}
-			//expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
+    for (int i = 0; i < 2; i++) {
+#ifndef PEACEFUL
+      // expected-note@-2 {{Loop condition is true.  Entering loop body}}
+      // expected-note@-3 {{Loop condition is true.  Entering loop body}}
+      // expected-note@-4 {{Loop condition is false. Execution jumps to the end of the function}}
+#endif
       leftRefCall(a);             // no-warning
     }
   }
   {
     A a;
-    for (int i = 0; i < bignum(); i++) { // expected-note {{Loop condition is false. Execution jumps to the end of the function}}
+    for (int i = 0; i < bignum(); i++) {
+#ifndef PEACEFUL
+      // expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
+#endif
       constCopyOrMoveCall(a);            // no-warning
     }
   }
   {
     A a;
-    for (int i = 0; i < 2; i++) { // expected-note {{Loop condition is true.  Entering loop body}} 
-      //expected-note@-1 {{Loop condition is true.  Entering loop body}}
-			//expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
+    for (int i = 0; i < 2; i++) {
+#ifndef PEACEFUL
+      // expected-note@-2 {{Loop condition is true.  Entering loop body}}
+      // expected-note@-3 {{Loop condition is true.  Entering loop body}}
+      // expected-note@-4 {{Loop condition is false. Execution jumps to the end of the function}}
+#endif
       constCopyOrMoveCall(a);     // no-warning
     }
   }
   {
     A a;
-    for (int i = 0; i < bignum(); i++) { // expected-note {{Loop condition is false. Execution jumps to the end of the function}}
+    for (int i = 0; i < bignum(); i++) {
+#ifndef PEACEFUL
+      // expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
+#endif
       moveInsideFunctionCall(a);         // no-warning
     }
   }
   {
     A a;
-    for (int i = 0; i < 2; i++) { // expected-note {{Loop condition is true.  Entering loop body}}
-      //expected-note@-1 {{Loop condition is true.  Entering loop body}}
-			//expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
+    for (int i = 0; i < 2; i++) {
+#ifndef PEACEFUL
+      // expected-note@-2 {{Loop condition is true.  Entering loop body}}
+      // expected-note@-3 {{Loop condition is true.  Entering loop body}}
+      // expected-note@-4 {{Loop condition is false. Execution jumps to the end of the function}}
+#endif
       moveInsideFunctionCall(a);  // no-warning
     }
   }
   {
     A a;
-    for (int i = 0; i < bignum(); i++) { // expected-note {{Loop condition is false. Execution jumps to the end of the function}}
+    for (int i = 0; i < bignum(); i++) {
+#ifndef PEACEFUL
+      // expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
+#endif
       copyOrMoveCall(a);                 // no-warning
     }
   }
   {
     A a;
-    for (int i = 0; i < 2; i++) { // expected-note {{Loop condition is true.}}
-      //expected-note@-1 {{Loop condition is true.  Entering loop body}}
-			//expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
+    for (int i = 0; i < 2; i++) {
+#ifndef PEACEFUL
+      // expected-note@-2 {{Loop condition is true.  Entering loop body}}
+      // expected-note@-3 {{Loop condition is true.  Entering loop body}}
+      // expected-note@-4 {{Loop condition is false. Execution jumps to the end of the function}}
+#endif
       copyOrMoveCall(a);          // no-warning
     }
   }
   {
     A a;
-    for (int i = 0; i < bignum(); i++) { // expected-note {{Loop condition is true.  Entering loop body}} expected-note {{Loop condition is true.  Entering loop body}}
-      constCopyOrMoveCall(std::move(a)); // expected-warning {{Moved-from object 'a' is moved}} expected-note {{Moved-from object 'a' is moved}}
-      // expected-note@-1 {{Object 'a' is moved}}
+    for (int i = 0; i < bignum(); i++) {
+#ifndef PEACEFUL
+      // expected-note@-2 {{Loop condition is true.  Entering loop body}}
+      // expected-note@-3 {{Loop condition is true.  Entering loop body}}
+#endif
+      constCopyOrMoveCall(std::move(a));
+#ifndef PEACEFUL
+      // expected-note@-2    {{Object 'a' is moved}}
+      // expected-warning@-3 {{Moved-from object 'a' is moved}}
+      // expected-note@-4 {{Moved-from object 'a' is moved}}
+#endif
     }
   }
 
@@ -326,14 +446,21 @@
   }
 }
 
-//report a usage of a moved-from object only at the first use
+// Report a usage of a moved-from object only at the first use.
 void uniqueTest(bool cond) {
   A a(42, 42.0);
   A b;
-  b = std::move(a); // expected-note {{Object 'a' is moved}}
+  b = std::move(a);
 
-  if (cond) { // expected-note {{Assuming 'cond' is not equal to 0}} expected-note {{Taking true branch}}
-    a.foo();  // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
+  if (cond) {
+    a.foo();
+#ifndef PEACEFUL
+  // expected-note@-5 {{Object 'a' is moved}}
+  // expected-note@-4 {{Assuming 'cond' is not equal to 0}}
+  // expected-note@-5 {{Taking true branch}}
+  // expected-warning@-5 {{Method called on moved-from object 'a'}}
+  // expected-note@-6    {{Method called on moved-from object 'a'}}
+#endif
   }
   if (cond) {
     a.bar(); // no-warning
@@ -344,8 +471,13 @@
 
 void uniqueTest2() {
   A a;
-  A a1 = std::move(a); // expected-note {{Object 'a' is moved}}
-  a.foo();             // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
+  A a1 = std::move(a);
+  a.foo();
+#ifndef PEACEFUL
+  // expected-note@-3 {{Object 'a' is moved}}
+  // expected-warning@-3 {{Method called on moved-from object 'a'}}
+  // expected-note@-4    {{Method called on moved-from object 'a'}}
+#endif
 
   A a2 = std::move(a); // no-warning
   a.foo();             // no-warning
@@ -355,12 +487,19 @@
 //even on moved-from objects.
 void moveSafeFunctionsTest() {
   A a;
-  A b = std::move(a); // expected-note {{Object 'a' is moved}}
+  A b = std::move(a);
+#ifndef PEACEFUL
+  // expected-note@-2 {{Object 'a' is moved}}
+#endif
   a.empty();          // no-warning
   a.isEmpty();        // no-warning
   (void)a;            // no-warning
   (bool)a;            // expected-warning {{expression result unused}}
-  a.foo();            // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
+  a.foo();
+#ifndef PEACEFUL
+  // expected-warning@-2 {{Method called on moved-from object 'a'}}
+  // expected-note@-3    {{Method called on moved-from object 'a'}}
+#endif
 }
 
 void moveStateResetFunctionsTest() {
@@ -496,7 +635,11 @@
   // Don't warn if the use is in a different branch from the move.
   {
     A a;
-    if (i > 0) { // expected-note {{Assuming 'i' is > 0}} expected-note {{Taking true branch}}
+    if (i > 0) {
+#ifndef PEACEFUL
+    // expected-note@-2 {{Assuming 'i' is > 0}}
+    // expected-note@-3 {{Taking true branch}}
+#endif
       A b;
       b = std::move(a);
     } else {
@@ -506,24 +649,40 @@
   // Same thing, but with a ternary operator.
   {
     A a, b;
-    i > 0 ? (void)(b = std::move(a)) : a.bar(); // no-warning  // expected-note {{'?' condition is true}}
+    i > 0 ? (void)(b = std::move(a)) : a.bar(); // no-warning
+#ifndef PEACEFUL
+    // expected-note@-2 {{'?' condition is true}}
+#endif
   }
   // A variation on the theme above.
   {
     A a;
+    a.foo() > 0 ? a.foo() : A(std::move(a)).foo();
 #ifdef DFS
-    a.foo() > 0 ? a.foo() : A(std::move(a)).foo(); // expected-note {{Assuming the condition is false}} expected-note {{'?' condition is false}}
+  #ifndef PEACEFUL
+    // expected-note@-3 {{Assuming the condition is false}}
+    // expected-note@-4 {{'?' condition is false}}
+  #endif
 #else
-    a.foo() > 0 ? a.foo() : A(std::move(a)).foo(); // expected-note {{Assuming the condition is true}} expected-note {{'?' condition is true}}
+  #ifndef PEACEFUL
+    // expected-note@-8 {{Assuming the condition is true}}
+    // expected-note@-9 {{'?' condition is true}}
+  #endif
 #endif
   }
   // Same thing, but with a switch statement.
   {
     A a, b;
-    switch (i) { // expected-note {{Control jumps to 'case 1:'}}
+    switch (i) {
+#ifndef PEACEFUL
+    // expected-note@-2 {{Control jumps to 'case 1:'}}
+#endif
     case 1:
       b = std::move(a); // no-warning
-      break;            // expected-note {{Execution jumps to the end of the function}}
+      break;
+#ifndef PEACEFUL
+      // expected-note@-2 {{Execution jumps to the end of the function}}
+#endif
     case 2:
       a.foo(); // no-warning
       break;
@@ -532,11 +691,21 @@
   // However, if there's a fallthrough, we do warn.
   {
     A a, b;
-    switch (i) { // expected-note {{Control jumps to 'case 1:'}}
+    switch (i) {
+#ifndef PEACEFUL
+    // expected-note@-2 {{Control jumps to 'case 1:'}}
+#endif
     case 1:
-      b = std::move(a); // expected-note {{Object 'a' is moved}}
+      b = std::move(a);
+#ifndef PEACEFUL
+      // expected-note@-2 {{Object 'a' is moved}}
+#endif
     case 2:
-      a.foo(); // expected-warning {{Method called on moved-from object}} expected-note {{Method called on moved-from object 'a'}}
+      a.foo();
+#ifndef PEACEFUL
+      // expected-warning@-2 {{Method called on moved-from object}}
+      // expected-note@-3    {{Method called on moved-from object 'a'}}
+#endif
       break;
     }
   }
@@ -551,14 +720,22 @@
 }
 
 void interFunTest1(A &a) {
-  a.bar(); // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
+  a.bar();
+#ifndef PEACEFUL
+  // expected-warning@-2 {{Method called on moved-from object 'a'}}
+  // expected-note@-3    {{Method called on moved-from object 'a'}}
+#endif
 }
 
 void interFunTest2() {
   A a;
   A b;
-  b = std::move(a); // expected-note {{Object 'a' is moved}}
-  interFunTest1(a); // expected-note {{Calling 'interFunTest1'}}
+  b = std::move(a);
+  interFunTest1(a);
+#ifndef PEACEFUL
+  // expected-note@-3 {{Object 'a' is moved}}
+  // expected-note@-3 {{Calling 'interFunTest1'}}
+#endif
 }
 
 void foobar(A a, int i);
@@ -566,8 +743,12 @@
 
 void paramEvaluateOrderTest() {
   A a;
-  foobar(std::move(a), a.getI()); // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
-  // expected-note@-1 {{Object 'a' is moved}}
+  foobar(std::move(a), a.getI());
+#ifndef PEACEFUL
+  // expected-note@-2 {{Object 'a' is moved}}
+  // expected-warning@-3 {{Method called on moved-from object 'a'}}
+  // expected-note@-4    {{Method called on moved-from object 'a'}}
+#endif
 
   //FALSE NEGATIVE since parameters evaluate order is undefined
   foobar(a.getI(), std::move(a)); //no-warning
@@ -590,10 +771,14 @@
   {
     A a;
     A b;
-    b = std::move(a); // expected-note{{Object 'a' is moved}}
+    b = std::move(a);
     not_known_pass_by_const_ref(a);
-    a.foo(); // expected-warning{{Method called on moved-from object 'a'}}
-             // expected-note@-1{{Method called on moved-from object 'a'}}
+    a.foo();
+#ifndef PEACEFUL
+    // expected-note@-4{{Object 'a' is moved}}
+    // expected-warning@-3{{Method called on moved-from object 'a'}}
+    // expected-note@-4   {{Method called on moved-from object 'a'}}
+#endif
   }
   {
     A a;
@@ -612,10 +797,14 @@
   {
     A a;
     A b;
-    b = std::move(a); // expected-note{{Object 'a' is moved}}
+    b = std::move(a);
     not_known_pass_by_const_ptr(&a);
-    a.foo(); // expected-warning{{Method called on moved-from object 'a'}}
-             // expected-note@-1{{Method called on moved-from object 'a'}}
+    a.foo();
+#ifndef PEACEFUL
+    // expected-note@-4{{Object 'a' is moved}}
+    // expected-warning@-3{{Method called on moved-from object 'a'}}
+    // expected-note@-4   {{Method called on moved-from object 'a'}}
+#endif
   }
 }
 
@@ -628,8 +817,12 @@
   }
   {
     A a;
-    A a1 = std::move(a), a2 = a; // expected-warning {{Moved-from object 'a' is copied}} expected-note {{Moved-from object 'a' is copied}}
-    // expected-note@-1 {{Object 'a' is moved}}
+    A a1 = std::move(a), a2 = a;
+#ifndef PEACEFUL
+    // expected-note@-2 {{Object 'a' is moved}}
+    // expected-warning@-3 {{Moved-from object 'a' is copied}}
+    // expected-note@-4    {{Moved-from object 'a' is copied}}
+#endif
   }
 }
 
@@ -637,43 +830,74 @@
 void logicalOperatorsSequenceTest() {
   {
     A a;
-    if (a.foo() > 0 && A(std::move(a)).foo() > 0) { // expected-note {{Assuming the condition is false}} expected-note {{Assuming the condition is false}} 
-      // expected-note@-1 {{Left side of '&&' is false}} expected-note@-1 {{Left side of '&&' is false}}
-			//expected-note@-2 {{Taking false branch}} expected-note@-2 {{Taking false branch}}
+    if (a.foo() > 0 && A(std::move(a)).foo() > 0) {
+#ifndef PEACEFUL
+      // expected-note@-2 {{Assuming the condition is false}}
+      // expected-note@-3 {{Left side of '&&' is false}}
+      // expected-note@-4 {{Taking false branch}}
+      // And the other report:
+      // expected-note@-6 {{Assuming the condition is false}}
+      // expected-note@-7 {{Left side of '&&' is false}}
+      // expected-note@-8 {{Taking false branch}}
       A().bar();
+#endif
     }
   }
   // A variation: Negate the result of the && (which pushes the && further down
   // into the AST).
   {
     A a;
-    if (!(a.foo() > 0 && A(std::move(a)).foo() > 0)) { // expected-note {{Assuming the condition is false}} expected-note {{Assuming the condition is false}}
-      // expected-note@-1 {{Left side of '&&' is false}} expected-note@-1 {{Left side of '&&' is false}}
-      // expected-note@-2 {{Taking true branch}} expected-note@-2 {{Taking true branch}}
+    if (!(a.foo() > 0 && A(std::move(a)).foo() > 0)) {
+#ifndef PEACEFUL
+      // expected-note@-2 {{Assuming the condition is false}}
+      // expected-note@-3 {{Left side of '&&' is false}}
+      // expected-note@-4 {{Taking true branch}}
+      // And the other report:
+      // expected-note@-6 {{Assuming the condition is false}}
+      // expected-note@-7 {{Left side of '&&' is false}}
+      // expected-note@-8 {{Taking true branch}}
+#endif
       A().bar();
     }
   }
   {
     A a;
-    if (A(std::move(a)).foo() > 0 && a.foo() > 0) { // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
-      // expected-note@-1 {{Object 'a' is moved}} expected-note@-1 {{Assuming the condition is true}} expected-note@-1 {{Assuming the condition is false}}
-      // expected-note@-2 {{Left side of '&&' is false}} expected-note@-2 {{Left side of '&&' is true}}
-      // expected-note@-3 {{Taking false branch}}
+    if (A(std::move(a)).foo() > 0 && a.foo() > 0) {
+#ifndef PEACEFUL
+      // expected-note@-2 {{Object 'a' is moved}}
+      // expected-note@-3 {{Assuming the condition is true}}
+      // expected-note@-4 {{Left side of '&&' is true}}
+      // expected-warning@-5 {{Method called on moved-from object 'a'}}
+      // expected-note@-6    {{Method called on moved-from object 'a'}}
+      // And the other report:
+      // expected-note@-8 {{Assuming the condition is false}}
+      // expected-note@-9 {{Left side of '&&' is false}}
+      // expected-note@-10{{Taking false branch}}
+#endif
       A().bar();
     }
   }
   {
     A a;
-    if (a.foo() > 0 || A(std::move(a)).foo() > 0) { // expected-note {{Assuming the condition is true}} 
-			//expected-note@-1 {{Left side of '||' is true}}
-			//expected-note@-2 {{Taking true branch}}
+    if (a.foo() > 0 || A(std::move(a)).foo() > 0) {
+#ifndef PEACEFUL
+      // expected-note@-2 {{Assuming the condition is true}}
+      // expected-note@-3 {{Left side of '||' is true}}
+      // expected-note@-4 {{Taking true branch}}
+#endif
       A().bar();
     }
   }
   {
     A a;
-    if (A(std::move(a)).foo() > 0 || a.foo() > 0) { // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
-      // expected-note@-1 {{Object 'a' is moved}} expected-note@-1 {{Assuming the condition is false}} expected-note@-1 {{Left side of '||' is false}}
+    if (A(std::move(a)).foo() > 0 || a.foo() > 0) {
+#ifndef PEACEFUL
+      // expected-note@-2 {{Object 'a' is moved}}
+      // expected-note@-3 {{Assuming the condition is false}}
+      // expected-note@-4 {{Left side of '||' is false}}
+      // expected-warning@-5 {{Method called on moved-from object 'a'}}
+      // expected-note@-6    {{Method called on moved-from object 'a'}}
+#endif
       A().bar();
     }
   }
@@ -729,14 +953,24 @@
   // Don't report a misuse if any SuperRegion is already reported.
   {
     A a;
-    A a1 = std::move(a); // expected-note {{Object 'a' is moved}}
-    a.foo();             // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
+    A a1 = std::move(a);
+    a.foo();
+#ifndef PEACEFUL
+    // expected-note@-3 {{Object 'a' is moved}}
+    // expected-warning@-3 {{Method called on moved-from object 'a'}}
+    // expected-note@-4    {{Method called on moved-from object 'a'}}
+#endif
     a.b.foo();           // no-warning
   }
   {
     C c;
-    C c1 = std::move(c); // expected-note {{Object 'c' is moved}}
-    c.foo();             // expected-warning {{Method called on moved-from object 'c'}} expected-note {{Method called on moved-from object 'c'}}
+    C c1 = std::move(c);
+    c.foo();
+#ifndef PEACEFUL
+    // expected-note@-3 {{Object 'c' is moved}}
+    // expected-warning@-3 {{Method called on moved-from object 'c'}}
+    // expected-note@-4    {{Method called on moved-from object 'c'}}
+#endif
     c.b.foo();           // no-warning
   }
 }
@@ -757,8 +991,13 @@
 
 void reportSuperClass() {
   C c;
-  C c1 = std::move(c); // expected-note {{Object 'c' is moved}}
-  c.foo();             // expected-warning {{Method called on moved-from object 'c'}} expected-note {{Method called on moved-from object 'c'}}
+  C c1 = std::move(c);
+  c.foo();
+#ifndef PEACEFUL
+  // expected-note@-3 {{Object 'c' is moved}}
+  // expected-warning@-3 {{Method called on moved-from object 'c'}}
+  // expected-note@-4    {{Method called on moved-from object 'c'}}
+#endif
   C c2 = c;            // no-warning
 }
 
@@ -872,17 +1111,25 @@
 };
 
 void localRValueMove(A &&a) {
-  A b = std::move(a); // expected-note{{Object 'a' is moved}}
-  a.foo(); // expected-warning{{Method called on moved-from object 'a'}}
-           // expected-note@-1{{Method called on moved-from object 'a'}}
+  A b = std::move(a);
+  a.foo();
+#ifndef PEACEFUL
+  // expected-note@-3 {{Object 'a' is moved}}
+  // expected-warning@-3 {{Method called on moved-from object 'a'}}
+  // expected-note@-4    {{Method called on moved-from object 'a'}}
+#endif
 }
 
 void localUniquePtr(std::unique_ptr<int> P) {
   // Even though unique_ptr is safe to use after move,
   // reusing a local variable this way usually indicates a bug.
-  std::unique_ptr<int> Q = std::move(P); // expected-note{{Object 'P' is moved}}
-  P.get(); // expected-warning{{Method called on moved-from object 'P'}}
-           // expected-note@-1{{Method called on moved-from object 'P'}}
+  std::unique_ptr<int> Q = std::move(P);
+  P.get();
+#ifndef PEACEFUL
+  // expected-note@-3 {{Object 'P' is moved}}
+  // expected-warning@-3 {{Method called on moved-from object 'P'}}
+  // expected-note@-4    {{Method called on moved-from object 'P'}}
+#endif
 }
 
 void localUniquePtrWithArrow(std::unique_ptr<A> P) {
Index: cfe/trunk/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
===================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
@@ -26,7 +26,6 @@
 using namespace ento;
 
 namespace {
-
 struct RegionState {
 private:
   enum Kind { Moved, Reported } K;
@@ -42,7 +41,9 @@
   bool operator==(const RegionState &X) const { return K == X.K; }
   void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(K); }
 };
+} // end of anonymous namespace
 
+namespace {
 class MoveChecker
     : public Checker<check::PreCall, check::PostCall,
                      check::DeadSymbols, check::RegionChanges> {
@@ -62,8 +63,18 @@
 
 private:
   enum MisuseKind { MK_FunCall, MK_Copy, MK_Move, MK_Dereference };
+  // This needs to be unsigned in order to avoid undefined behavior
+  // when putting it into a tight bitfield.
   enum StdObjectKind : unsigned { SK_NonStd, SK_Unsafe, SK_Safe, SK_SmartPtr };
 
+  enum AggressivenessKind { // In any case, don't warn after a reset.
+    AK_Invalid = -1,
+    AK_KnownsOnly = 0,      // Warn only about known move-unsafe classes.
+    AK_KnownsAndLocals = 1, // Also warn about all local objects.
+    AK_All = 2,             // Warn on any use-after-move.
+    AK_NumKinds = AK_All
+  };
+
   static bool misuseCausesCrash(MisuseKind MK) {
     return MK == MK_Dereference;
   }
@@ -117,8 +128,9 @@
     // In aggressive mode, warn on any use-after-move because the user has
     // intentionally asked us to completely eliminate use-after-move
     // in his code.
-    return IsAggressive || OK.IsLocal
-                        || OK.StdKind == SK_Unsafe || OK.StdKind == SK_SmartPtr;
+    return (Aggressiveness == AK_All) ||
+           (Aggressiveness >= AK_KnownsAndLocals && OK.IsLocal) ||
+           OK.StdKind == SK_Unsafe || OK.StdKind == SK_SmartPtr;
   }
 
   // Some objects only suffer from some kinds of misuses, but we need to track
@@ -127,8 +139,9 @@
     // Additionally, only warn on smart pointers when they are dereferenced (or
     // local or we are aggressive).
     return shouldBeTracked(OK) &&
-           (IsAggressive || OK.IsLocal
-                         || OK.StdKind != SK_SmartPtr || MK == MK_Dereference);
+           ((Aggressiveness == AK_All) ||
+            (Aggressiveness >= AK_KnownsAndLocals && OK.IsLocal) ||
+            OK.StdKind != SK_SmartPtr || MK == MK_Dereference);
   }
 
   // Obtains ObjectKind of an object. Because class declaration cannot always
@@ -173,10 +186,17 @@
     bool Found;
   };
 
-  bool IsAggressive = false;
+  AggressivenessKind Aggressiveness;
 
 public:
-  void setAggressiveness(bool Aggressive) { IsAggressive = Aggressive; }
+  void setAggressiveness(StringRef Str) {
+    Aggressiveness =
+        llvm::StringSwitch<AggressivenessKind>(Str)
+            .Case("KnownsOnly", AK_KnownsOnly)
+            .Case("KnownsAndLocals", AK_KnownsAndLocals)
+            .Case("All", AK_All)
+            .Default(AK_KnownsAndLocals); // A sane default.
+  };
 
 private:
   mutable std::unique_ptr<BugType> BT;
@@ -717,6 +737,6 @@
 }
 void ento::registerMoveChecker(CheckerManager &mgr) {
   MoveChecker *chk = mgr.registerChecker<MoveChecker>();
-  chk->setAggressiveness(mgr.getAnalyzerOptions().getCheckerBooleanOption(
-      "Aggressive", false, chk));
+  chk->setAggressiveness(
+      mgr.getAnalyzerOptions().getCheckerStringOption("WarnOn", "", chk));
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to