From 6b71e27c948302faaa7927cde02286c767871bbd Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Thu, 18 Apr 2019 23:17:58 +0000 Subject: [PATCH] [analyzer] NFC: MoveChecker: Refactor tests to use -verify=prefix. This -verify=prefix feature is quite underrated. Differential Revision: https://reviews.llvm.org/D60732 llvm-svn: 358719 --- clang/test/Analysis/use-after-move.cpp | 641 +++++++++++---------------------- 1 file changed, 209 insertions(+), 432 deletions(-) diff --git a/clang/test/Analysis/use-after-move.cpp b/clang/test/Analysis/use-after-move.cpp index 837f4c7..29e62f8 100644 --- a/clang/test/Analysis/use-after-move.cpp +++ b/clang/test/Analysis/use-after-move.cpp @@ -1,31 +1,37 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move -verify %s\ +// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move %s\ // RUN: -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\ // RUN: -analyzer-config exploration_strategy=unexplored_first_queue\ -// RUN: -analyzer-checker debug.ExprInspection -// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move -verify %s\ +// RUN: -analyzer-checker debug.ExprInspection\ +// RUN: -verify=expected,peaceful,non-aggressive +// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move %s\ // RUN: -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\ -// RUN: -analyzer-config exploration_strategy=dfs -DDFS=1\ -// RUN: -analyzer-checker debug.ExprInspection -// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move -verify %s\ +// RUN: -analyzer-config exploration_strategy=dfs -DDFS\ +// RUN: -analyzer-checker debug.ExprInspection\ +// RUN: -verify=expected,peaceful,non-aggressive +// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move %s\ // RUN: -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\ // RUN: -analyzer-config exploration_strategy=unexplored_first_queue\ -// RUN: -analyzer-config cplusplus.Move:WarnOn=KnownsOnly -DPEACEFUL\ -// RUN: -analyzer-checker debug.ExprInspection +// RUN: -analyzer-config cplusplus.Move:WarnOn=KnownsOnly\ +// RUN: -analyzer-checker debug.ExprInspection\ +// RUN: -verify=expected,non-aggressive // RUN: %clang_analyze_cc1 -analyzer-checker=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 cplusplus.Move:WarnOn=KnownsOnly -DPEACEFUL\ -// RUN: -analyzer-checker debug.ExprInspection -// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move -verify %s\ +// RUN: -analyzer-config exploration_strategy=dfs -DDFS\ +// RUN: -analyzer-config cplusplus.Move:WarnOn=KnownsOnly\ +// RUN: -analyzer-checker debug.ExprInspection\ +// RUN: -verify=expected,non-aggressive +// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move %s\ // RUN: -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\ // RUN: -analyzer-config exploration_strategy=unexplored_first_queue\ -// RUN: -analyzer-config cplusplus.Move:WarnOn=All -DAGGRESSIVE\ -// RUN: -analyzer-checker debug.ExprInspection -// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move -verify %s\ +// RUN: -analyzer-config cplusplus.Move:WarnOn=All\ +// RUN: -analyzer-checker debug.ExprInspection\ +// RUN: -verify=expected,peaceful,aggressive +// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move %s\ // RUN: -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\ -// RUN: -analyzer-config exploration_strategy=dfs -DDFS=1\ -// RUN: -analyzer-config cplusplus.Move:WarnOn=All -DAGGRESSIVE\ -// RUN: -analyzer-checker debug.ExprInspection +// RUN: -analyzer-config exploration_strategy=dfs -DDFS\ +// RUN: -analyzer-config cplusplus.Move:WarnOn=All\ +// RUN: -analyzer-checker debug.ExprInspection\ +// RUN: -verify=expected,peaceful,aggressive // RUN: not %clang_analyze_cc1 -verify %s \ // RUN: -analyzer-checker=core \ @@ -75,10 +81,7 @@ public: moveconstruct(std::move(*a)); } A(const A &other) : i(other.i), d(other.d), b(other.b) {} - A(A &&other) : i(other.i), d(other.d), b(std::move(other.b)) { -#ifdef AGGRESSIVE - // expected-note@-2{{Object 'b' is moved}} -#endif + A(A &&other) : i(other.i), d(other.d), b(std::move(other.b)) { // aggressive-note{{Object 'b' is moved}} } A(A &&other, char *k) { moveconstruct(std::move(other)); @@ -141,33 +144,21 @@ void copyOrMoveCall(A a) { void simpleMoveCtorTest() { { A 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 b = std::move(a); // peaceful-note {{Object 'a' is moved}} + a.foo(); // peaceful-warning {{Method called on moved-from object 'a'}} + // peaceful-note@-1 {{Method called on moved-from object 'a'}} } { A a; - 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 b = std::move(a); // peaceful-note {{Object 'a' is moved}} + b = a; // peaceful-warning {{Moved-from object 'a' is copied}} + // peaceful-note@-1 {{Moved-from object 'a' is copied}} } { A a; - 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 + A b = std::move(a); // peaceful-note {{Object 'a' is moved}} + b = std::move(a); // peaceful-warning {{Moved-from object 'a' is moved}} + // peaceful-note@-1 {{Moved-from object 'a' is moved}} } } @@ -175,35 +166,23 @@ void simpleMoveAssignementTest() { { A a; A b; - 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 + b = std::move(a); // peaceful-note {{Object 'a' is moved}} + a.foo(); // peaceful-warning {{Method called on moved-from object 'a'}} + // peaceful-note@-1 {{Method called on moved-from object 'a'}} } { A a; A b; - 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 + b = std::move(a); // peaceful-note {{Object 'a' is moved}} + A c(a); // peaceful-warning {{Moved-from object 'a' is copied}} + // peaceful-note@-1 {{Moved-from object 'a' is copied}} } { A a; A b; - 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 + b = std::move(a); // peaceful-note {{Object 'a' is moved}} + A c(std::move(a)); // peaceful-warning {{Moved-from object 'a' is moved}} + // peaceful-note@-1 {{Moved-from object 'a' is moved}} } } @@ -212,13 +191,9 @@ void moveInInitListTest() { A a; }; A 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 + S s{std::move(a)}; // peaceful-note {{Object 'a' is moved}} + a.foo(); // peaceful-warning {{Method called on moved-from object 'a'}} + // peaceful-note@-1 {{Method called on moved-from object 'a'}} } // Don't report a bug if the variable was assigned to in the meantime. @@ -232,43 +207,23 @@ void reinitializationTest(int i) { } { A a; - 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 + if (i == 1) { // peaceful-note 2 {{Assuming 'i' is not equal to 1}} + // peaceful-note@-1 2 {{Taking false branch}} A b; b = std::move(a); a = A(); } - 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 + if (i == 2) { // peaceful-note 2 {{Assuming 'i' is not equal to 2}} + // peaceful-note@-1 2 {{Taking false branch}} a.foo(); // no-warning } } { A a; - if (i == 1) { -#ifndef PEACEFUL - // expected-note@-2 {{Taking false branch}} - // expected-note@-3 {{Taking false branch}} -#endif + if (i == 1) { // peaceful-note 2 {{Taking false branch}} std::move(a); } - if (i == 2) { -#ifndef PEACEFUL - // expected-note@-2 {{Taking false branch}} - // expected-note@-3 {{Taking false branch}} -#endif + if (i == 2) { // peaceful-note 2 {{Taking false branch}} a = A(); a.foo(); } @@ -286,36 +241,22 @@ void reinitializationTest(int i) { A b; b = std::move(a); 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 + b = std::move(a); // peaceful-note {{Object 'a' is moved}} + a.foo(); // peaceful-warning {{Method called on moved-from object 'a'}} + // peaceful-note@-1 {{Method called on moved-from object 'a'}} } // If a path exist where we not reinitialize the variable we report a bug. { A a; A b; - 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 + b = std::move(a); // peaceful-note {{Object 'a' is moved}} + if (i < 10) { // peaceful-note {{Assuming 'i' is >= 10}} + // peaceful-note@-1 {{Taking false branch}} a = 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 + if (i > 5) { // peaceful-note {{Taking true branch}} + a.foo(); // peaceful-warning {{Method called on moved-from object 'a'}} + // peaceful-note@-1 {{Method called on moved-from object 'a'}} } } } @@ -330,117 +271,82 @@ void decltypeIsNotUseTest() { void loopTest() { { A a; - 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 + // FIXME: Execution doesn't jump to the end of the function yet. + for (int i = 0; i < bignum(); i++) { // peaceful-note {{Loop condition is false. Execution jumps to the end of the function}} rightRefCall(std::move(a)); // no-warning } } { A a; - 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 + for (int i = 0; i < 2; i++) { // peaceful-note {{Loop condition is true. Entering loop body}} + // peaceful-note@-1 {{Loop condition is true. Entering loop body}} + // peaceful-note@-2 {{Loop condition is false. Execution jumps to the end of the function}} rightRefCall(std::move(a)); // no-warning } } { A a; - 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 + for (int i = 0; i < bignum(); i++) { // peaceful-note {{Loop condition is false. Execution jumps to the end of the function}} leftRefCall(a); // no-warning } } { A a; - 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 + for (int i = 0; i < 2; i++) { // peaceful-note {{Loop condition is true. Entering loop body}} + // peaceful-note@-1 {{Loop condition is true. Entering loop body}} + // peaceful-note@-2 {{Loop condition is false. Execution jumps to the end of the function}} leftRefCall(a); // no-warning } } { A a; - 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 + for (int i = 0; i < bignum(); i++) { // peaceful-note {{Loop condition is false. Execution jumps to the end of the function}} constCopyOrMoveCall(a); // no-warning } } { A a; - 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 + for (int i = 0; i < 2; i++) { // peaceful-note {{Loop condition is true. Entering loop body}} + // peaceful-note@-1 {{Loop condition is true. Entering loop body}} + // peaceful-note@-2 {{Loop condition is false. Execution jumps to the end of the function}} constCopyOrMoveCall(a); // no-warning } } { A a; - 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 + for (int i = 0; i < bignum(); i++) { // peaceful-note {{Loop condition is false. Execution jumps to the end of the function}} moveInsideFunctionCall(a); // no-warning } } { A a; - 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 + for (int i = 0; i < 2; i++) { // peaceful-note {{Loop condition is true. Entering loop body}} + // peaceful-note@-1 {{Loop condition is true. Entering loop body}} + // peaceful-note@-2 {{Loop condition is false. Execution jumps to the end of the function}} moveInsideFunctionCall(a); // no-warning } } { A a; - 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 + for (int i = 0; i < bignum(); i++) { // peaceful-note {{Loop condition is false. Execution jumps to the end of the function}} copyOrMoveCall(a); // no-warning } } { A a; - 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 + for (int i = 0; i < 2; i++) { // peaceful-note {{Loop condition is true. Entering loop body}} + // peaceful-note@-1 {{Loop condition is true. Entering loop body}} + // peaceful-note@-2 {{Loop condition is false. Execution jumps to the end of the function}} copyOrMoveCall(a); // no-warning } } { A a; - 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 + for (int i = 0; i < bignum(); i++) { // peaceful-note {{Loop condition is true. Entering loop body}} + // peaceful-note@-1 {{Loop condition is true. Entering loop body}} + constCopyOrMoveCall(std::move(a)); // peaceful-note {{Object 'a' is moved}} + // peaceful-warning@-1 {{Moved-from object 'a' is moved}} + // peaceful-note@-2 {{Moved-from object 'a' is moved}} } } @@ -462,17 +368,12 @@ void loopTest() { void uniqueTest(bool cond) { A a(42, 42.0); A b; - b = std::move(a); + b = std::move(a); // peaceful-note {{Object 'a' is moved}} - 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) { // peaceful-note {{Assuming 'cond' is not equal to 0}} + // peaceful-note@-1 {{Taking true branch}} + a.foo(); // peaceful-warning {{Method called on moved-from object 'a'}} + // peaceful-note@-1 {{Method called on moved-from object 'a'}} } if (cond) { a.bar(); // no-warning @@ -483,13 +384,9 @@ void uniqueTest(bool cond) { void uniqueTest2() { A 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 a1 = std::move(a); // peaceful-note {{Object 'a' is moved}} + a.foo(); // peaceful-warning {{Method called on moved-from object 'a'}} + // peaceful-note@-1 {{Method called on moved-from object 'a'}} A a2 = std::move(a); // no-warning a.foo(); // no-warning @@ -499,19 +396,13 @@ void uniqueTest2() { //even on moved-from objects. void moveSafeFunctionsTest() { A a; - A b = std::move(a); -#ifndef PEACEFUL - // expected-note@-2 {{Object 'a' is moved}} -#endif + A b = std::move(a); // peaceful-note {{Object 'a' is moved}} a.empty(); // no-warning a.isEmpty(); // no-warning (void)a; // no-warning (bool)a; // expected-warning {{expression result unused}} - 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 + a.foo(); // peaceful-warning {{Method called on moved-from object 'a'}} + // peaceful-note@-1 {{Method called on moved-from object 'a'}} } void moveStateResetFunctionsTest() { @@ -589,51 +480,32 @@ class memberVariablesTest { void f() { A b; - b = std::move(a); - a.foo(); -#ifdef AGGRESSIVE - // 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 + b = std::move(a); // aggressive-note {{Object 'a' is moved}} - b = std::move(static_a); - static_a.foo(); -#ifdef AGGRESSIVE - // expected-note@-3{{Object 'static_a' is moved}} - // expected-warning@-3{{Method called on moved-from object 'static_a'}} - // expected-note@-4{{Method called on moved-from object 'static_a'}} -#endif + a.foo(); // aggressive-warning {{Method called on moved-from object 'a'}} + // aggressive-note@-1 {{Method called on moved-from object 'a'}} + + b = std::move(static_a); // aggressive-note {{Object 'static_a' is moved}} + static_a.foo(); // aggressive-warning {{Method called on moved-from object 'static_a'}} + // aggressive-note@-1 {{Method called on moved-from object 'static_a'}} } }; void PtrAndArrayTest() { A *Ptr = new A(1, 1.5); A Arr[10]; - Arr[2] = std::move(*Ptr); - (*Ptr).foo(); -#ifdef AGGRESSIVE - // expected-note@-3{{Object is moved}} - // expected-warning@-3{{Method called on moved-from object}} - // expected-note@-4{{Method called on moved-from object}} -#endif + Arr[2] = std::move(*Ptr); // aggressive-note{{Object is moved}} + (*Ptr).foo(); // aggressive-warning{{Method called on moved-from object}} + // aggressive-note@-1{{Method called on moved-from object}} Ptr = &Arr[1]; - Arr[3] = std::move(Arr[1]); - Ptr->foo(); -#ifdef AGGRESSIVE - // expected-note@-3{{Object is moved}} - // expected-warning@-3{{Method called on moved-from object}} - // expected-note@-4{{Method called on moved-from object}} -#endif + Arr[3] = std::move(Arr[1]); // aggressive-note {{Object is moved}} + Ptr->foo(); // aggressive-warning {{Method called on moved-from object}} + // aggressive-note@-1 {{Method called on moved-from object}} - Arr[3] = std::move(Arr[2]); - Arr[2].foo(); -#ifdef AGGRESSIVE - // expected-note@-3{{Object is moved}} - // expected-warning@-3{{Method called on moved-from object}} - // expected-note@-4{{Method called on moved-from object}} -#endif + Arr[3] = std::move(Arr[2]); // aggressive-note{{Object is moved}} + Arr[2].foo(); // aggressive-warning{{Method called on moved-from object}} + // aggressive-note@-1{{Method called on moved-from object}} Arr[2] = std::move(Arr[3]); // reinitialization Arr[2].foo(); // no-warning @@ -654,11 +526,8 @@ void differentBranchesTest(int i) { // Don't warn if the use is in a different branch from the move. { A a; - if (i > 0) { -#ifndef PEACEFUL - // expected-note@-2 {{Assuming 'i' is > 0}} - // expected-note@-3 {{Taking true branch}} -#endif + if (i > 0) { // peaceful-note {{Assuming 'i' is > 0}} + // peaceful-note@-1 {{Taking true branch}} A b; b = std::move(a); } else { @@ -668,40 +537,28 @@ void differentBranchesTest(int i) { // Same thing, but with a ternary operator. { A a, b; - i > 0 ? (void)(b = std::move(a)) : a.bar(); // no-warning -#ifndef PEACEFUL - // expected-note@-2 {{'?' condition is true}} -#endif + i > 0 ? (void)(b = std::move(a)) : a.bar(); // no-warning // peaceful-note {{'?' condition is true}} } // A variation on the theme above. { A a; a.foo() > 0 ? a.foo() : A(std::move(a)).foo(); #ifdef DFS - #ifndef PEACEFUL - // expected-note@-3 {{Assuming the condition is false}} - // expected-note@-4 {{'?' condition is false}} - #endif + // peaceful-note@-2 {{Assuming the condition is false}} + // peaceful-note@-3 {{'?' condition is false}} #else - #ifndef PEACEFUL - // expected-note@-8 {{Assuming the condition is true}} - // expected-note@-9 {{'?' condition is true}} - #endif + // peaceful-note@-5 {{Assuming the condition is true}} + // peaceful-note@-6 {{'?' condition is true}} #endif } // Same thing, but with a switch statement. { A a, b; - switch (i) { -#ifndef PEACEFUL - // expected-note@-2 {{Control jumps to 'case 1:'}} -#endif + switch (i) { // peaceful-note {{Control jumps to 'case 1:'}} case 1: b = std::move(a); // no-warning - break; -#ifndef PEACEFUL - // expected-note@-2 {{Execution jumps to the end of the function}} -#endif + // FIXME: Execution doesn't jump to the end of the function yet. + break; // peaceful-note {{Execution jumps to the end of the function}} case 2: a.foo(); // no-warning break; @@ -710,21 +567,12 @@ void differentBranchesTest(int i) { // However, if there's a fallthrough, we do warn. { A a, b; - switch (i) { -#ifndef PEACEFUL - // expected-note@-2 {{Control jumps to 'case 1:'}} -#endif + switch (i) { // peaceful-note {{Control jumps to 'case 1:'}} case 1: - b = std::move(a); -#ifndef PEACEFUL - // expected-note@-2 {{Object 'a' is moved}} -#endif + b = std::move(a); // peaceful-note {{Object 'a' is moved}} case 2: - a.foo(); -#ifndef PEACEFUL - // expected-warning@-2 {{Method called on moved-from object}} - // expected-note@-3 {{Method called on moved-from object 'a'}} -#endif + a.foo(); // peaceful-warning {{Method called on moved-from object 'a'}} + // peaceful-note@-1 {{Method called on moved-from object 'a'}} break; } } @@ -739,22 +587,15 @@ void tempTest() { } void interFunTest1(A &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 + a.bar(); // peaceful-warning {{Method called on moved-from object 'a'}} + // peaceful-note@-1 {{Method called on moved-from object 'a'}} } void interFunTest2() { A a; A b; - b = std::move(a); - interFunTest1(a); -#ifndef PEACEFUL - // expected-note@-3 {{Object 'a' is moved}} - // expected-note@-3 {{Calling 'interFunTest1'}} -#endif + b = std::move(a); // peaceful-note {{Object 'a' is moved}} + interFunTest1(a); // peaceful-note {{Calling 'interFunTest1'}} } void foobar(A a, int i); @@ -762,12 +603,9 @@ void foobar(int i, A a); void paramEvaluateOrderTest() { A a; - 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 + foobar(std::move(a), a.getI()); // peaceful-note {{Object 'a' is moved}} + // peaceful-warning@-1 {{Method called on moved-from object 'a'}} + // peaceful-note@-2 {{Method called on moved-from object 'a'}} //FALSE NEGATIVE since parameters evaluate order is undefined foobar(a.getI(), std::move(a)); //no-warning @@ -790,14 +628,10 @@ void regionAndPointerEscapeTest() { { A a; A b; - b = std::move(a); + b = std::move(a); // peaceful-note{{Object 'a' is moved}} not_known_pass_by_const_ref(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.foo(); // peaceful-warning {{Method called on moved-from object 'a'}} + // peaceful-note@-1 {{Method called on moved-from object 'a'}} } { A a; @@ -816,14 +650,10 @@ void regionAndPointerEscapeTest() { { A a; A b; - b = std::move(a); + b = std::move(a); // peaceful-note {{Object 'a' is moved}} not_known_pass_by_const_ptr(&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.foo(); // peaceful-warning {{Method called on moved-from object 'a'}} + // peaceful-note@-1 {{Method called on moved-from object 'a'}} } } @@ -836,12 +666,9 @@ void declarationSequenceTest() { } { A a; - 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 + A a1 = std::move(a), a2 = a; // peaceful-note {{Object 'a' is moved}} + // peaceful-warning@-1 {{Moved-from object 'a' is copied}} + // peaceful-note@-2 {{Moved-from object 'a' is copied}} } } @@ -849,74 +676,59 @@ void declarationSequenceTest() { void logicalOperatorsSequenceTest() { { A a; - 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}} + if (a.foo() > 0 && A(std::move(a)).foo() > 0) { // peaceful-note {{Assuming the condition is false}} + // peaceful-note@-1 {{Left side of '&&' is false}} + // peaceful-note@-2 {{Taking false branch}} + // And the other report: + // peaceful-note@-4 {{Assuming the condition is false}} + // peaceful-note@-5 {{Left side of '&&' is false}} + // peaceful-note@-6 {{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)) { -#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 + if (!(a.foo() > 0 && A(std::move(a)).foo() > 0)) { // peaceful-note {{Assuming the condition is false}} + // peaceful-note@-1 {{Left side of '&&' is false}} + // peaceful-note@-2 {{Taking true branch}} + // And the other report: + // peaceful-note@-4 {{Assuming the condition is false}} + // peaceful-note@-5 {{Left side of '&&' is false}} + // peaceful-note@-6 {{Taking true branch}} A().bar(); } } { A a; - 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 + if (A(std::move(a)).foo() > 0 && a.foo() > 0) { // peaceful-note {{Object 'a' is moved}} + // peaceful-note@-1 {{Assuming the condition is true}} + // peaceful-note@-2 {{Left side of '&&' is true}} + // peaceful-warning@-3 {{Method called on moved-from object 'a'}} + // peaceful-note@-4 {{Method called on moved-from object 'a'}} + // And the other report: + // peaceful-note@-6 {{Assuming the condition is false}} + // peaceful-note@-7 {{Left side of '&&' is false}} + // peaceful-note@-8 {{Taking false branch}} A().bar(); } } { A a; - 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 + if (a.foo() > 0 || A(std::move(a)).foo() > 0) { // peaceful-note {{Assuming the condition is true}} + // peaceful-note@-1 {{Left side of '||' is true}} + // peaceful-note@-2 {{Taking true branch}} A().bar(); } } { A a; - 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 + if (A(std::move(a)).foo() > 0 || a.foo() > 0) { // peaceful-note {{Object 'a' is moved}} + // peaceful-note@-1 {{Assuming the condition is false}} + // peaceful-note@-2 {{Left side of '||' is false}} + // peaceful-warning@-3 {{Method called on moved-from object 'a'}} + // peaceful-note@-4 {{Method called on moved-from object 'a'}} A().bar(); } } @@ -950,47 +762,31 @@ struct C : public A { void subRegionMoveTest() { { A a; - B b = std::move(a.b); - a.b.foo(); -#ifdef AGGRESSIVE - // expected-note@-3{{Object 'b' is moved}} - // expected-warning@-3{{Method called on moved-from object 'b'}} - // expected-note@-4 {{Method called on moved-from object 'b'}} -#endif + B b = std::move(a.b); // aggressive-note {{Object 'b' is moved}} + a.b.foo(); // aggressive-warning {{Method called on moved-from object 'b'}} + // aggressive-note@-1 {{Method called on moved-from object 'b'}} } { A a; - A a1 = std::move(a); - a.b.foo(); -#ifdef AGGRESSIVE - // expected-note@-3{{Calling move constructor for 'A'}} - // expected-note@-4{{Returning from move constructor for 'A'}} - // expected-warning@-4{{Method called on moved-from object 'b'}} - // expected-note@-5{{Method called on moved-from object 'b'}} -#endif + A a1 = std::move(a); // aggressive-note {{Calling move constructor for 'A'}} + // aggressive-note@-1 {{Returning from move constructor for 'A'}} + a.b.foo(); // aggressive-warning{{Method called on moved-from object 'b'}} + // aggressive-note@-1{{Method called on moved-from object 'b'}} } // Don't report a misuse if any SuperRegion is already reported. { A 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 + A a1 = std::move(a); // peaceful-note {{Object 'a' is moved}} + a.foo(); // peaceful-warning {{Method called on moved-from object 'a'}} + // peaceful-note@-1 {{Method called on moved-from object 'a'}} + a.b.foo(); // no-warning } { C 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 + C c1 = std::move(c); // peaceful-note {{Object 'c' is moved}} + c.foo(); // peaceful-warning {{Method called on moved-from object 'c'}} + // peaceful-note@-1 {{Method called on moved-from object 'c'}} + c.b.foo(); // no-warning } } @@ -1010,14 +806,10 @@ void resetSuperClass2() { void reportSuperClass() { C 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 + C c1 = std::move(c); // peaceful-note {{Object 'c' is moved}} + c.foo(); // peaceful-warning {{Method called on moved-from object 'c'}} + // peaceful-note@-1 {{Method called on moved-from object 'c'}} + C c2 = c; // no-warning } struct Empty {}; @@ -1098,31 +890,24 @@ class HasSTLField { void testVector() { // Warn even in non-aggressive mode when it comes to STL, because // in STL the object is left in "valid but unspecified state" after move. - std::vector W = std::move(V); // expected-note{{Object 'V' of type 'std::vector' is left in a valid but unspecified state after move}} - V.push_back(123); // expected-warning{{Method called on moved-from object 'V'}} - // expected-note@-1{{Method called on moved-from object 'V'}} + std::vector W = std::move(V); // expected-note {{Object 'V' of type 'std::vector' is left in a valid but unspecified state after move}} + V.push_back(123); // expected-warning {{Method called on moved-from object 'V'}} + // expected-note@-1 {{Method called on moved-from object 'V'}} } std::unique_ptr P; void testUniquePtr() { // unique_ptr remains in a well-defined state after move. - std::unique_ptr Q = std::move(P); - P.get(); -#ifdef AGGRESSIVE - // expected-warning@-2{{Method called on moved-from object 'P'}} - // expected-note@-4{{Object 'P' is moved}} - // expected-note@-4{{Method called on moved-from object 'P'}} -#endif + std::unique_ptr Q = std::move(P); // aggressive-note {{Object 'P' is moved}} + // non-aggressive-note@-1 {{Smart pointer 'P' of type 'std::unique_ptr' is reset to null when moved from}} + P.get(); // aggressive-warning{{Method called on moved-from object 'P'}} + // aggressive-note@-1{{Method called on moved-from object 'P'}} // Because that well-defined state is null, dereference is still UB. // Note that in aggressive mode we already warned about 'P', // so no extra warning is generated. - *P += 1; -#ifndef AGGRESSIVE - // expected-warning@-2{{Dereference of null smart pointer 'P' of type 'std::unique_ptr'}} - // expected-note@-14{{Smart pointer 'P' of type 'std::unique_ptr' is reset to null when moved from}} - // expected-note@-4{{Dereference of null smart pointer 'P' of type 'std::unique_ptr'}} -#endif + *P += 1; // non-aggressive-warning{{Dereference of null smart pointer 'P' of type 'std::unique_ptr'}} + // non-aggressive-note@-1{{Dereference of null smart pointer 'P' of type 'std::unique_ptr'}} // The program should have crashed by now. clang_analyzer_warnIfReached(); // no-warning @@ -1130,25 +915,17 @@ class HasSTLField { }; void localRValueMove(A &&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 b = std::move(a); // peaceful-note {{Object 'a' is moved}} + a.foo(); // peaceful-warning {{Method called on moved-from object 'a'}} + // peaceful-note@-1 {{Method called on moved-from object 'a'}} } void localUniquePtr(std::unique_ptr P) { // Even though unique_ptr is safe to use after move, // reusing a local variable this way usually indicates a bug. - std::unique_ptr 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 + std::unique_ptr Q = std::move(P); // peaceful-note {{Object 'P' is moved}} + P.get(); // peaceful-warning {{Method called on moved-from object 'P'}} + // peaceful-note@-1 {{Method called on moved-from object 'P'}} } void localUniquePtrWithArrow(std::unique_ptr P) { -- 2.7.4