1 // RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move -verify %s\
2 // RUN:  -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\
3 // RUN:  -analyzer-config exploration_strategy=unexplored_first_queue\
4 // RUN:  -analyzer-checker debug.ExprInspection
5 // RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move -verify %s\
6 // RUN:  -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\
7 // RUN:  -analyzer-config exploration_strategy=dfs -DDFS=1\
8 // RUN:  -analyzer-checker debug.ExprInspection
9 // RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move -verify %s\
10 // RUN:  -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\
11 // RUN:  -analyzer-config exploration_strategy=unexplored_first_queue\
12 // RUN:  -analyzer-config cplusplus.Move:WarnOn=KnownsOnly -DPEACEFUL\
13 // RUN:  -analyzer-checker debug.ExprInspection
14 // RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move -verify %s\
15 // RUN:  -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\
16 // RUN:  -analyzer-config exploration_strategy=dfs -DDFS=1\
17 // RUN:  -analyzer-config cplusplus.Move:WarnOn=KnownsOnly -DPEACEFUL\
18 // RUN:  -analyzer-checker debug.ExprInspection
19 // RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move -verify %s\
20 // RUN:  -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\
21 // RUN:  -analyzer-config exploration_strategy=unexplored_first_queue\
22 // RUN:  -analyzer-config cplusplus.Move:WarnOn=All -DAGGRESSIVE\
23 // RUN:  -analyzer-checker debug.ExprInspection
24 // RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.Move -verify %s\
25 // RUN:  -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\
26 // RUN:  -analyzer-config exploration_strategy=dfs -DDFS=1\
27 // RUN:  -analyzer-config cplusplus.Move:WarnOn=All -DAGGRESSIVE\
28 // RUN:  -analyzer-checker debug.ExprInspection
29 
30 // RUN: not %clang_analyze_cc1 -verify %s \
31 // RUN:   -analyzer-checker=core \
32 // RUN:   -analyzer-checker=cplusplus.Move \
33 // RUN:   -analyzer-config cplusplus.Move:WarnOn="a bunch of things" \
34 // RUN:   2>&1 | FileCheck %s -check-prefix=CHECK-MOVE-INVALID-VALUE
35 
36 // CHECK-MOVE-INVALID-VALUE: (frontend): invalid input for checker option
37 // CHECK-MOVE-INVALID-VALUE-SAME: 'cplusplus.Move:WarnOn', that expects either
38 // CHECK-MOVE-INVALID-VALUE-SAME: "KnownsOnly", "KnownsAndLocals" or "All"
39 // CHECK-MOVE-INVALID-VALUE-SAME: string value
40 
41 #include "Inputs/system-header-simulator-cxx.h"
42 
43 void clang_analyzer_warnIfReached();
44 
45 class B {
46 public:
47   B() = default;
48   B(const B &) = default;
49   B(B &&) = default;
50   B& operator=(const B &q) = default;
51   void operator=(B &&b) {
52     return;
53   }
54   void foo() { return; }
55 };
56 
57 class A {
58   int i;
59   double d;
60 
61 public:
62   B b;
63   A(int ii = 42, double dd = 1.0) : d(dd), i(ii), b(B()) {}
64   void moveconstruct(A &&other) {
65     std::swap(b, other.b);
66     std::swap(d, other.d);
67     std::swap(i, other.i);
68     return;
69   }
70   static A get() {
71     A v(12, 13);
72     return v;
73   }
74   A(A *a) {
75     moveconstruct(std::move(*a));
76   }
77   A(const A &other) : i(other.i), d(other.d), b(other.b) {}
78   A(A &&other) : i(other.i), d(other.d), b(std::move(other.b)) {
79 #ifdef AGGRESSIVE
80     // expected-note@-2{{Object 'b' is moved}}
81 #endif
82   }
83   A(A &&other, char *k) {
84     moveconstruct(std::move(other));
85   }
86   void operator=(const A &other) {
87     i = other.i;
88     d = other.d;
89     b = other.b;
90     return;
91   }
92   void operator=(A &&other) {
93     moveconstruct(std::move(other));
94     return;
95   }
96   int getI() { return i; }
97   int foo() const;
98   void bar() const;
99   void reset();
100   void destroy();
101   void clear();
102   void resize(std::size_t);
103   void assign(const A &);
104   bool empty() const;
105   bool isEmpty() const;
106   operator bool() const;
107 
108   void testUpdateField() {
109     A a;
110     A b = std::move(a);
111     a.i = 1;
112     a.foo(); // no-warning
113   }
114   void testUpdateFieldDouble() {
115     A a;
116     A b = std::move(a);
117     a.d = 1.0;
118     a.foo(); // no-warning
119   }
120 };
121 
122 int bignum();
123 
124 void moveInsideFunctionCall(A a) {
125   A b = std::move(a);
126 }
127 void leftRefCall(A &a) {
128   a.foo();
129 }
130 void rightRefCall(A &&a) {
131   a.foo();
132 }
133 void constCopyOrMoveCall(const A a) {
134   a.foo();
135 }
136 
137 void copyOrMoveCall(A a) {
138   a.foo();
139 }
140 
141 void simpleMoveCtorTest() {
142   {
143     A a;
144     A b = std::move(a);
145     a.foo();
146 #ifndef PEACEFUL
147     // expected-note@-3 {{Object 'a' is moved}}
148     // expected-warning@-3 {{Method called on moved-from object 'a'}}
149     // expected-note@-4    {{Method called on moved-from object 'a'}}
150 #endif
151   }
152   {
153     A a;
154     A b = std::move(a);
155     b = a;
156 #ifndef PEACEFUL
157     // expected-note@-3 {{Object 'a' is moved}}
158     // expected-warning@-3 {{Moved-from object 'a' is copied}}
159     // expected-note@-4    {{Moved-from object 'a' is copied}}
160 #endif
161   }
162   {
163     A a;
164     A b = std::move(a);
165     b = std::move(a);
166 #ifndef PEACEFUL
167     // expected-note@-3 {{Object 'a' is moved}}
168     // expected-warning@-3 {{Moved-from object 'a' is moved}}
169     // expected-note@-4    {{Moved-from object 'a' is moved}}
170 #endif
171   }
172 }
173 
174 void simpleMoveAssignementTest() {
175   {
176     A a;
177     A b;
178     b = std::move(a);
179     a.foo();
180 #ifndef PEACEFUL
181     // expected-note@-3 {{Object 'a' is moved}}
182     // expected-warning@-3 {{Method called on moved-from object 'a'}}
183     // expected-note@-4    {{Method called on moved-from object 'a'}}
184 #endif
185   }
186   {
187     A a;
188     A b;
189     b = std::move(a);
190     A c(a);
191 #ifndef PEACEFUL
192     // expected-note@-3 {{Object 'a' is moved}}
193     // expected-warning@-3 {{Moved-from object 'a' is copied}}
194     // expected-note@-4    {{Moved-from object 'a' is copied}}
195 #endif
196   }
197   {
198     A a;
199     A b;
200     b = std::move(a);
201     A c(std::move(a));
202 #ifndef PEACEFUL
203     // expected-note@-3 {{Object 'a' is moved}}
204     // expected-warning@-3 {{Moved-from object 'a' is moved}}
205     // expected-note@-4    {{Moved-from object 'a' is moved}}
206 #endif
207   }
208 }
209 
210 void moveInInitListTest() {
211   struct S {
212     A a;
213   };
214   A a;
215   S s{std::move(a)};
216   a.foo();
217 #ifndef PEACEFUL
218   // expected-note@-3 {{Object 'a' is moved}}
219   // expected-warning@-3 {{Method called on moved-from object 'a'}}
220   // expected-note@-4 {{Method called on moved-from object 'a'}}
221 #endif
222 }
223 
224 // Don't report a bug if the variable was assigned to in the meantime.
225 void reinitializationTest(int i) {
226   {
227     A a;
228     A b;
229     b = std::move(a);
230     a = A();
231     a.foo();
232   }
233   {
234     A a;
235     if (i == 1) {
236 #ifndef PEACEFUL
237       // expected-note@-2 {{Assuming 'i' is not equal to 1}}
238       // expected-note@-3 {{Taking false branch}}
239       // And the other report:
240       // expected-note@-5 {{Assuming 'i' is not equal to 1}}
241       // expected-note@-6 {{Taking false branch}}
242 #endif
243       A b;
244       b = std::move(a);
245       a = A();
246     }
247     if (i == 2) {
248 #ifndef PEACEFUL
249       // expected-note@-2 {{Assuming 'i' is not equal to 2}}
250       // expected-note@-3 {{Taking false branch}}
251       // And the other report:
252       // expected-note@-5 {{Assuming 'i' is not equal to 2}}
253       // expected-note@-6 {{Taking false branch}}
254 #endif
255       a.foo();    // no-warning
256     }
257   }
258   {
259     A a;
260     if (i == 1) {
261 #ifndef PEACEFUL
262       // expected-note@-2 {{Taking false branch}}
263       // expected-note@-3 {{Taking false branch}}
264 #endif
265       std::move(a);
266     }
267     if (i == 2) {
268 #ifndef PEACEFUL
269       // expected-note@-2 {{Taking false branch}}
270       // expected-note@-3 {{Taking false branch}}
271 #endif
272       a = A();
273       a.foo();
274     }
275   }
276   // The built-in assignment operator should also be recognized as a
277   // reinitialization. (std::move() may be called on built-in types in template
278   // code.)
279   {
280     int a1 = 1, a2 = 2;
281     std::swap(a1, a2);
282   }
283   // A std::move() after the assignment makes the variable invalid again.
284   {
285     A a;
286     A b;
287     b = std::move(a);
288     a = A();
289     b = std::move(a);
290     a.foo();
291 #ifndef PEACEFUL
292     // expected-note@-3 {{Object 'a' is moved}}
293     // expected-warning@-3 {{Method called on moved-from object 'a'}}
294     // expected-note@-4    {{Method called on moved-from object 'a'}}
295 #endif
296   }
297   // If a path exist where we not reinitialize the variable we report a bug.
298   {
299     A a;
300     A b;
301     b = std::move(a);
302 #ifndef PEACEFUL
303     // expected-note@-2 {{Object 'a' is moved}}
304 #endif
305     if (i < 10) {
306 #ifndef PEACEFUL
307       // expected-note@-2 {{Assuming 'i' is >= 10}}
308       // expected-note@-3 {{Taking false branch}}
309 #endif
310       a = A();
311     }
312     if (i > 5) {
313       a.foo();
314 #ifndef PEACEFUL
315       // expected-note@-3 {{Taking true branch}}
316       // expected-warning@-3 {{Method called on moved-from object 'a'}}
317       // expected-note@-4    {{Method called on moved-from object 'a'}}
318 #endif
319     }
320   }
321 }
322 
323 // Using decltype on an expression is not a use.
324 void decltypeIsNotUseTest() {
325   A a;
326   // A b(std::move(a));
327   decltype(a) other_a; // no-warning
328 }
329 
330 void loopTest() {
331   {
332     A a;
333     for (int i = 0; i < bignum(); i++) {
334 #ifndef PEACEFUL
335       // expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
336 #endif
337       rightRefCall(std::move(a));        // no-warning
338     }
339   }
340   {
341     A a;
342     for (int i = 0; i < 2; i++) {
343 #ifndef PEACEFUL
344       // expected-note@-2 {{Loop condition is true.  Entering loop body}}
345       // expected-note@-3 {{Loop condition is true.  Entering loop body}}
346       // expected-note@-4 {{Loop condition is false. Execution jumps to the end of the function}}
347 #endif
348       rightRefCall(std::move(a)); // no-warning
349     }
350   }
351   {
352     A a;
353     for (int i = 0; i < bignum(); i++) {
354 #ifndef PEACEFUL
355       // expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
356 #endif
357       leftRefCall(a);                    // no-warning
358     }
359   }
360   {
361     A a;
362     for (int i = 0; i < 2; i++) {
363 #ifndef PEACEFUL
364       // expected-note@-2 {{Loop condition is true.  Entering loop body}}
365       // expected-note@-3 {{Loop condition is true.  Entering loop body}}
366       // expected-note@-4 {{Loop condition is false. Execution jumps to the end of the function}}
367 #endif
368       leftRefCall(a);             // no-warning
369     }
370   }
371   {
372     A a;
373     for (int i = 0; i < bignum(); i++) {
374 #ifndef PEACEFUL
375       // expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
376 #endif
377       constCopyOrMoveCall(a);            // no-warning
378     }
379   }
380   {
381     A a;
382     for (int i = 0; i < 2; i++) {
383 #ifndef PEACEFUL
384       // expected-note@-2 {{Loop condition is true.  Entering loop body}}
385       // expected-note@-3 {{Loop condition is true.  Entering loop body}}
386       // expected-note@-4 {{Loop condition is false. Execution jumps to the end of the function}}
387 #endif
388       constCopyOrMoveCall(a);     // no-warning
389     }
390   }
391   {
392     A a;
393     for (int i = 0; i < bignum(); i++) {
394 #ifndef PEACEFUL
395       // expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
396 #endif
397       moveInsideFunctionCall(a);         // no-warning
398     }
399   }
400   {
401     A a;
402     for (int i = 0; i < 2; i++) {
403 #ifndef PEACEFUL
404       // expected-note@-2 {{Loop condition is true.  Entering loop body}}
405       // expected-note@-3 {{Loop condition is true.  Entering loop body}}
406       // expected-note@-4 {{Loop condition is false. Execution jumps to the end of the function}}
407 #endif
408       moveInsideFunctionCall(a);  // no-warning
409     }
410   }
411   {
412     A a;
413     for (int i = 0; i < bignum(); i++) {
414 #ifndef PEACEFUL
415       // expected-note@-2 {{Loop condition is false. Execution jumps to the end of the function}}
416 #endif
417       copyOrMoveCall(a);                 // no-warning
418     }
419   }
420   {
421     A a;
422     for (int i = 0; i < 2; i++) {
423 #ifndef PEACEFUL
424       // expected-note@-2 {{Loop condition is true.  Entering loop body}}
425       // expected-note@-3 {{Loop condition is true.  Entering loop body}}
426       // expected-note@-4 {{Loop condition is false. Execution jumps to the end of the function}}
427 #endif
428       copyOrMoveCall(a);          // no-warning
429     }
430   }
431   {
432     A a;
433     for (int i = 0; i < bignum(); i++) {
434 #ifndef PEACEFUL
435       // expected-note@-2 {{Loop condition is true.  Entering loop body}}
436       // expected-note@-3 {{Loop condition is true.  Entering loop body}}
437 #endif
438       constCopyOrMoveCall(std::move(a));
439 #ifndef PEACEFUL
440       // expected-note@-2    {{Object 'a' is moved}}
441       // expected-warning@-3 {{Moved-from object 'a' is moved}}
442       // expected-note@-4 {{Moved-from object 'a' is moved}}
443 #endif
444     }
445   }
446 
447   // Don't warn if we return after the move.
448   {
449     A a;
450     for (int i = 0; i < 3; ++i) {
451       a.bar();
452       if (a.foo() > 0) {
453         A b;
454         b = std::move(a); // no-warning
455         return;
456       }
457     }
458   }
459 }
460 
461 // Report a usage of a moved-from object only at the first use.
462 void uniqueTest(bool cond) {
463   A a(42, 42.0);
464   A b;
465   b = std::move(a);
466 
467   if (cond) {
468     a.foo();
469 #ifndef PEACEFUL
470   // expected-note@-5 {{Object 'a' is moved}}
471   // expected-note@-4 {{Assuming 'cond' is not equal to 0}}
472   // expected-note@-5 {{Taking true branch}}
473   // expected-warning@-5 {{Method called on moved-from object 'a'}}
474   // expected-note@-6    {{Method called on moved-from object 'a'}}
475 #endif
476   }
477   if (cond) {
478     a.bar(); // no-warning
479   }
480 
481   a.bar(); // no-warning
482 }
483 
484 void uniqueTest2() {
485   A a;
486   A a1 = std::move(a);
487   a.foo();
488 #ifndef PEACEFUL
489   // expected-note@-3 {{Object 'a' is moved}}
490   // expected-warning@-3 {{Method called on moved-from object 'a'}}
491   // expected-note@-4    {{Method called on moved-from object 'a'}}
492 #endif
493 
494   A a2 = std::move(a); // no-warning
495   a.foo();             // no-warning
496 }
497 
498 // There are exceptions where we assume in general that the method works fine
499 //even on moved-from objects.
500 void moveSafeFunctionsTest() {
501   A a;
502   A b = std::move(a);
503 #ifndef PEACEFUL
504   // expected-note@-2 {{Object 'a' is moved}}
505 #endif
506   a.empty();          // no-warning
507   a.isEmpty();        // no-warning
508   (void)a;            // no-warning
509   (bool)a;            // expected-warning {{expression result unused}}
510   a.foo();
511 #ifndef PEACEFUL
512   // expected-warning@-2 {{Method called on moved-from object 'a'}}
513   // expected-note@-3    {{Method called on moved-from object 'a'}}
514 #endif
515 }
516 
517 void moveStateResetFunctionsTest() {
518   {
519     A a;
520     A b = std::move(a);
521     a.reset(); // no-warning
522     a.foo();   // no-warning
523     // Test if resets the state of subregions as well.
524     a.b.foo(); // no-warning
525   }
526   {
527     A a;
528     A b = std::move(a);
529     a.destroy(); // no-warning
530     a.foo();     // no-warning
531   }
532   {
533     A a;
534     A b = std::move(a);
535     a.clear(); // no-warning
536     a.foo();   // no-warning
537     a.b.foo(); // no-warning
538   }
539   {
540     A a;
541     A b = std::move(a);
542     a.resize(0); // no-warning
543     a.foo();   // no-warning
544     a.b.foo(); // no-warning
545   }
546   {
547     A a;
548     A b = std::move(a);
549     a.assign(A()); // no-warning
550     a.foo();   // no-warning
551     a.b.foo(); // no-warning
552   }
553 }
554 
555 // Moves or uses that occur as part of template arguments.
556 template <int>
557 class ClassTemplate {
558 public:
559   void foo(A a);
560 };
561 
562 template <int>
563 void functionTemplate(A a);
564 
565 void templateArgIsNotUseTest() {
566   {
567     // A pattern like this occurs in the EXPECT_EQ and ASSERT_EQ macros in
568     // Google Test.
569     A a;
570     ClassTemplate<sizeof(A(std::move(a)))>().foo(std::move(a)); // no-warning
571   }
572   {
573     A a;
574     functionTemplate<sizeof(A(std::move(a)))>(std::move(a)); // no-warning
575   }
576 }
577 
578 // Moves of global variables are not reported.
579 A global_a;
580 void globalVariablesTest() {
581   std::move(global_a);
582   global_a.foo(); // no-warning
583 }
584 
585 // Moves of member variables.
586 class memberVariablesTest {
587   A a;
588   static A static_a;
589 
590   void f() {
591     A b;
592     b = std::move(a);
593     a.foo();
594 #ifdef AGGRESSIVE
595     // expected-note@-3{{Object 'a' is moved}}
596     // expected-warning@-3 {{Method called on moved-from object 'a'}}
597     // expected-note@-4{{Method called on moved-from object 'a'}}
598 #endif
599 
600     b = std::move(static_a);
601     static_a.foo();
602 #ifdef AGGRESSIVE
603     // expected-note@-3{{Object 'static_a' is moved}}
604     // expected-warning@-3{{Method called on moved-from object 'static_a'}}
605     // expected-note@-4{{Method called on moved-from object 'static_a'}}
606 #endif
607   }
608 };
609 
610 void PtrAndArrayTest() {
611   A *Ptr = new A(1, 1.5);
612   A Arr[10];
613   Arr[2] = std::move(*Ptr);
614   (*Ptr).foo();
615 #ifdef AGGRESSIVE
616   // expected-note@-3{{Object is moved}}
617   // expected-warning@-3{{Method called on moved-from object}}
618   // expected-note@-4{{Method called on moved-from object}}
619 #endif
620 
621   Ptr = &Arr[1];
622   Arr[3] = std::move(Arr[1]);
623   Ptr->foo();
624 #ifdef AGGRESSIVE
625   // expected-note@-3{{Object is moved}}
626   // expected-warning@-3{{Method called on moved-from object}}
627   // expected-note@-4{{Method called on moved-from object}}
628 #endif
629 
630   Arr[3] = std::move(Arr[2]);
631   Arr[2].foo();
632 #ifdef AGGRESSIVE
633   // expected-note@-3{{Object is moved}}
634   // expected-warning@-3{{Method called on moved-from object}}
635   // expected-note@-4{{Method called on moved-from object}}
636 #endif
637 
638   Arr[2] = std::move(Arr[3]); // reinitialization
639   Arr[2].foo();               // no-warning
640 }
641 
642 void exclusiveConditionsTest(bool cond) {
643   A a;
644   if (cond) {
645     A b;
646     b = std::move(a);
647   }
648   if (!cond) {
649     a.bar(); // no-warning
650   }
651 }
652 
653 void differentBranchesTest(int i) {
654   // Don't warn if the use is in a different branch from the move.
655   {
656     A a;
657     if (i > 0) {
658 #ifndef PEACEFUL
659     // expected-note@-2 {{Assuming 'i' is > 0}}
660     // expected-note@-3 {{Taking true branch}}
661 #endif
662       A b;
663       b = std::move(a);
664     } else {
665       a.foo(); // no-warning
666     }
667   }
668   // Same thing, but with a ternary operator.
669   {
670     A a, b;
671     i > 0 ? (void)(b = std::move(a)) : a.bar(); // no-warning
672 #ifndef PEACEFUL
673     // expected-note@-2 {{'?' condition is true}}
674 #endif
675   }
676   // A variation on the theme above.
677   {
678     A a;
679     a.foo() > 0 ? a.foo() : A(std::move(a)).foo();
680 #ifdef DFS
681   #ifndef PEACEFUL
682     // expected-note@-3 {{Assuming the condition is false}}
683     // expected-note@-4 {{'?' condition is false}}
684   #endif
685 #else
686   #ifndef PEACEFUL
687     // expected-note@-8 {{Assuming the condition is true}}
688     // expected-note@-9 {{'?' condition is true}}
689   #endif
690 #endif
691   }
692   // Same thing, but with a switch statement.
693   {
694     A a, b;
695     switch (i) {
696 #ifndef PEACEFUL
697     // expected-note@-2 {{Control jumps to 'case 1:'}}
698 #endif
699     case 1:
700       b = std::move(a); // no-warning
701       break;
702 #ifndef PEACEFUL
703       // expected-note@-2 {{Execution jumps to the end of the function}}
704 #endif
705     case 2:
706       a.foo(); // no-warning
707       break;
708     }
709   }
710   // However, if there's a fallthrough, we do warn.
711   {
712     A a, b;
713     switch (i) {
714 #ifndef PEACEFUL
715     // expected-note@-2 {{Control jumps to 'case 1:'}}
716 #endif
717     case 1:
718       b = std::move(a);
719 #ifndef PEACEFUL
720       // expected-note@-2 {{Object 'a' is moved}}
721 #endif
722     case 2:
723       a.foo();
724 #ifndef PEACEFUL
725       // expected-warning@-2 {{Method called on moved-from object}}
726       // expected-note@-3    {{Method called on moved-from object 'a'}}
727 #endif
728       break;
729     }
730   }
731 }
732 
733 void tempTest() {
734   A a = A::get();
735   A::get().foo(); // no-warning
736   for (int i = 0; i < bignum(); i++) {
737     A::get().foo(); // no-warning
738   }
739 }
740 
741 void interFunTest1(A &a) {
742   a.bar();
743 #ifndef PEACEFUL
744   // expected-warning@-2 {{Method called on moved-from object 'a'}}
745   // expected-note@-3    {{Method called on moved-from object 'a'}}
746 #endif
747 }
748 
749 void interFunTest2() {
750   A a;
751   A b;
752   b = std::move(a);
753   interFunTest1(a);
754 #ifndef PEACEFUL
755   // expected-note@-3 {{Object 'a' is moved}}
756   // expected-note@-3 {{Calling 'interFunTest1'}}
757 #endif
758 }
759 
760 void foobar(A a, int i);
761 void foobar(int i, A a);
762 
763 void paramEvaluateOrderTest() {
764   A a;
765   foobar(std::move(a), a.getI());
766 #ifndef PEACEFUL
767   // expected-note@-2 {{Object 'a' is moved}}
768   // expected-warning@-3 {{Method called on moved-from object 'a'}}
769   // expected-note@-4    {{Method called on moved-from object 'a'}}
770 #endif
771 
772   //FALSE NEGATIVE since parameters evaluate order is undefined
773   foobar(a.getI(), std::move(a)); //no-warning
774 }
775 
776 void not_known_pass_by_ref(A &a);
777 void not_known_pass_by_const_ref(const A &a);
778 void not_known_pass_by_rvalue_ref(A &&a);
779 void not_known_pass_by_ptr(A *a);
780 void not_known_pass_by_const_ptr(const A *a);
781 
782 void regionAndPointerEscapeTest() {
783   {
784     A a;
785     A b;
786     b = std::move(a);
787     not_known_pass_by_ref(a);
788     a.foo(); // no-warning
789   }
790   {
791     A a;
792     A b;
793     b = std::move(a);
794     not_known_pass_by_const_ref(a);
795     a.foo();
796 #ifndef PEACEFUL
797     // expected-note@-4{{Object 'a' is moved}}
798     // expected-warning@-3{{Method called on moved-from object 'a'}}
799     // expected-note@-4   {{Method called on moved-from object 'a'}}
800 #endif
801   }
802   {
803     A a;
804     A b;
805     b = std::move(a);
806     not_known_pass_by_rvalue_ref(std::move(a));
807     a.foo(); // no-warning
808   }
809   {
810     A a;
811     A b;
812     b = std::move(a);
813     not_known_pass_by_ptr(&a);
814     a.foo(); // no-warning
815   }
816   {
817     A a;
818     A b;
819     b = std::move(a);
820     not_known_pass_by_const_ptr(&a);
821     a.foo();
822 #ifndef PEACEFUL
823     // expected-note@-4{{Object 'a' is moved}}
824     // expected-warning@-3{{Method called on moved-from object 'a'}}
825     // expected-note@-4   {{Method called on moved-from object 'a'}}
826 #endif
827   }
828 }
829 
830 // A declaration statement containing multiple declarations sequences the
831 // initializer expressions.
832 void declarationSequenceTest() {
833   {
834     A a;
835     A a1 = a, a2 = std::move(a); // no-warning
836   }
837   {
838     A a;
839     A a1 = std::move(a), a2 = a;
840 #ifndef PEACEFUL
841     // expected-note@-2 {{Object 'a' is moved}}
842     // expected-warning@-3 {{Moved-from object 'a' is copied}}
843     // expected-note@-4    {{Moved-from object 'a' is copied}}
844 #endif
845   }
846 }
847 
848 // The logical operators && and || sequence their operands.
849 void logicalOperatorsSequenceTest() {
850   {
851     A a;
852     if (a.foo() > 0 && A(std::move(a)).foo() > 0) {
853 #ifndef PEACEFUL
854       // expected-note@-2 {{Assuming the condition is false}}
855       // expected-note@-3 {{Left side of '&&' is false}}
856       // expected-note@-4 {{Taking false branch}}
857       // And the other report:
858       // expected-note@-6 {{Assuming the condition is false}}
859       // expected-note@-7 {{Left side of '&&' is false}}
860       // expected-note@-8 {{Taking false branch}}
861       A().bar();
862 #endif
863     }
864   }
865   // A variation: Negate the result of the && (which pushes the && further down
866   // into the AST).
867   {
868     A a;
869     if (!(a.foo() > 0 && A(std::move(a)).foo() > 0)) {
870 #ifndef PEACEFUL
871       // expected-note@-2 {{Assuming the condition is false}}
872       // expected-note@-3 {{Left side of '&&' is false}}
873       // expected-note@-4 {{Taking true branch}}
874       // And the other report:
875       // expected-note@-6 {{Assuming the condition is false}}
876       // expected-note@-7 {{Left side of '&&' is false}}
877       // expected-note@-8 {{Taking true branch}}
878 #endif
879       A().bar();
880     }
881   }
882   {
883     A a;
884     if (A(std::move(a)).foo() > 0 && a.foo() > 0) {
885 #ifndef PEACEFUL
886       // expected-note@-2 {{Object 'a' is moved}}
887       // expected-note@-3 {{Assuming the condition is true}}
888       // expected-note@-4 {{Left side of '&&' is true}}
889       // expected-warning@-5 {{Method called on moved-from object 'a'}}
890       // expected-note@-6    {{Method called on moved-from object 'a'}}
891       // And the other report:
892       // expected-note@-8 {{Assuming the condition is false}}
893       // expected-note@-9 {{Left side of '&&' is false}}
894       // expected-note@-10{{Taking false branch}}
895 #endif
896       A().bar();
897     }
898   }
899   {
900     A a;
901     if (a.foo() > 0 || A(std::move(a)).foo() > 0) {
902 #ifndef PEACEFUL
903       // expected-note@-2 {{Assuming the condition is true}}
904       // expected-note@-3 {{Left side of '||' is true}}
905       // expected-note@-4 {{Taking true branch}}
906 #endif
907       A().bar();
908     }
909   }
910   {
911     A a;
912     if (A(std::move(a)).foo() > 0 || a.foo() > 0) {
913 #ifndef PEACEFUL
914       // expected-note@-2 {{Object 'a' is moved}}
915       // expected-note@-3 {{Assuming the condition is false}}
916       // expected-note@-4 {{Left side of '||' is false}}
917       // expected-warning@-5 {{Method called on moved-from object 'a'}}
918       // expected-note@-6    {{Method called on moved-from object 'a'}}
919 #endif
920       A().bar();
921     }
922   }
923 }
924 
925 // A range-based for sequences the loop variable declaration before the body.
926 void forRangeSequencesTest() {
927   A v[2] = {A(), A()};
928   for (A &a : v) {
929     A b;
930     b = std::move(a); // no-warning
931   }
932 }
933 
934 // If a variable is declared in an if statement, the declaration of the variable
935 // (which is treated like a reinitialization by the check) is sequenced before
936 // the evaluation of the condition (which constitutes a use).
937 void ifStmtSequencesDeclAndConditionTest() {
938   for (int i = 0; i < 3; ++i) {
939     if (A a = A()) {
940       A b;
941       b = std::move(a); // no-warning
942     }
943   }
944 }
945 
946 struct C : public A {
947   [[clang::reinitializes]] void reinit();
948 };
949 
950 void subRegionMoveTest() {
951   {
952     A a;
953     B b = std::move(a.b);
954     a.b.foo();
955 #ifdef AGGRESSIVE
956     // expected-note@-3{{Object 'b' is moved}}
957     // expected-warning@-3{{Method called on moved-from object 'b'}}
958     // expected-note@-4 {{Method called on moved-from object 'b'}}
959 #endif
960   }
961   {
962     A a;
963     A a1 = std::move(a);
964     a.b.foo();
965 #ifdef AGGRESSIVE
966     // expected-note@-3{{Calling move constructor for 'A'}}
967     // expected-note@-4{{Returning from move constructor for 'A'}}
968     // expected-warning@-4{{Method called on moved-from object 'b'}}
969     // expected-note@-5{{Method called on moved-from object 'b'}}
970 #endif
971   }
972   // Don't report a misuse if any SuperRegion is already reported.
973   {
974     A a;
975     A a1 = std::move(a);
976     a.foo();
977 #ifndef PEACEFUL
978     // expected-note@-3 {{Object 'a' is moved}}
979     // expected-warning@-3 {{Method called on moved-from object 'a'}}
980     // expected-note@-4    {{Method called on moved-from object 'a'}}
981 #endif
982     a.b.foo();           // no-warning
983   }
984   {
985     C c;
986     C c1 = std::move(c);
987     c.foo();
988 #ifndef PEACEFUL
989     // expected-note@-3 {{Object 'c' is moved}}
990     // expected-warning@-3 {{Method called on moved-from object 'c'}}
991     // expected-note@-4    {{Method called on moved-from object 'c'}}
992 #endif
993     c.b.foo();           // no-warning
994   }
995 }
996 
997 void resetSuperClass() {
998   C c;
999   C c1 = std::move(c);
1000   c.clear();
1001   C c2 = c; // no-warning
1002 }
1003 
1004 void resetSuperClass2() {
1005   C c;
1006   C c1 = std::move(c);
1007   c.reinit();
1008   C c2 = c; // no-warning
1009 }
1010 
1011 void reportSuperClass() {
1012   C c;
1013   C c1 = std::move(c);
1014   c.foo();
1015 #ifndef PEACEFUL
1016   // expected-note@-3 {{Object 'c' is moved}}
1017   // expected-warning@-3 {{Method called on moved-from object 'c'}}
1018   // expected-note@-4    {{Method called on moved-from object 'c'}}
1019 #endif
1020   C c2 = c;            // no-warning
1021 }
1022 
1023 struct Empty {};
1024 
1025 Empty inlinedCall() {
1026   // Used to warn because region 'e' failed to be cleaned up because no symbols
1027   // have ever died during the analysis and the checkDeadSymbols callback
1028   // was skipped entirely.
1029   Empty e{};
1030   return e; // no-warning
1031 }
1032 
1033 void checkInlinedCallZombies() {
1034   while (true)
1035     inlinedCall();
1036 }
1037 
1038 void checkLoopZombies() {
1039   while (true) {
1040     Empty e{};
1041     Empty f = std::move(e); // no-warning
1042   }
1043 }
1044 
1045 void checkMoreLoopZombies1(bool flag) {
1046   while (flag) {
1047     Empty e{};
1048     if (true)
1049       e; // expected-warning {{expression result unused}}
1050     Empty f = std::move(e); // no-warning
1051   }
1052 }
1053 
1054 bool coin();
1055 
1056 void checkMoreLoopZombies2(bool flag) {
1057   while (flag) {
1058     Empty e{};
1059     while (coin())
1060       e; // expected-warning {{expression result unused}}
1061     Empty f = std::move(e); // no-warning
1062   }
1063 }
1064 
1065 void checkMoreLoopZombies3(bool flag) {
1066   while (flag) {
1067     Empty e{};
1068     do
1069       e; // expected-warning {{expression result unused}}
1070     while (coin());
1071     Empty f = std::move(e); // no-warning
1072   }
1073 }
1074 
1075 void checkMoreLoopZombies4(bool flag) {
1076   while (flag) {
1077     Empty e{};
1078     for (; coin();)
1079       e; // expected-warning {{expression result unused}}
1080     Empty f = std::move(e); // no-warning
1081   }
1082 }
1083 
1084 struct MoveOnlyWithDestructor {
1085   MoveOnlyWithDestructor();
1086   ~MoveOnlyWithDestructor();
1087   MoveOnlyWithDestructor(const MoveOnlyWithDestructor &m) = delete;
1088   MoveOnlyWithDestructor(MoveOnlyWithDestructor &&m);
1089 };
1090 
1091 MoveOnlyWithDestructor foo() {
1092   MoveOnlyWithDestructor m;
1093   return m;
1094 }
1095 
1096 class HasSTLField {
1097   std::vector<int> V;
1098   void testVector() {
1099     // Warn even in non-aggressive mode when it comes to STL, because
1100     // in STL the object is left in "valid but unspecified state" after move.
1101     std::vector<int> W = std::move(V); // expected-note{{Object 'V' of type 'std::vector' is left in a valid but unspecified state after move}}
1102     V.push_back(123); // expected-warning{{Method called on moved-from object 'V'}}
1103                       // expected-note@-1{{Method called on moved-from object 'V'}}
1104   }
1105 
1106   std::unique_ptr<int> P;
1107   void testUniquePtr() {
1108     // unique_ptr remains in a well-defined state after move.
1109     std::unique_ptr<int> Q = std::move(P);
1110     P.get();
1111 #ifdef AGGRESSIVE
1112     // expected-warning@-2{{Method called on moved-from object 'P'}}
1113     // expected-note@-4{{Object 'P' is moved}}
1114     // expected-note@-4{{Method called on moved-from object 'P'}}
1115 #endif
1116 
1117     // Because that well-defined state is null, dereference is still UB.
1118     // Note that in aggressive mode we already warned about 'P',
1119     // so no extra warning is generated.
1120     *P += 1;
1121 #ifndef AGGRESSIVE
1122     // expected-warning@-2{{Dereference of null smart pointer 'P' of type 'std::unique_ptr'}}
1123     // expected-note@-14{{Smart pointer 'P' of type 'std::unique_ptr' is reset to null when moved from}}
1124     // expected-note@-4{{Dereference of null smart pointer 'P' of type 'std::unique_ptr'}}
1125 #endif
1126 
1127     // The program should have crashed by now.
1128     clang_analyzer_warnIfReached(); // no-warning
1129   }
1130 };
1131 
1132 void localRValueMove(A &&a) {
1133   A b = std::move(a);
1134   a.foo();
1135 #ifndef PEACEFUL
1136   // expected-note@-3 {{Object 'a' is moved}}
1137   // expected-warning@-3 {{Method called on moved-from object 'a'}}
1138   // expected-note@-4    {{Method called on moved-from object 'a'}}
1139 #endif
1140 }
1141 
1142 void localUniquePtr(std::unique_ptr<int> P) {
1143   // Even though unique_ptr is safe to use after move,
1144   // reusing a local variable this way usually indicates a bug.
1145   std::unique_ptr<int> Q = std::move(P);
1146   P.get();
1147 #ifndef PEACEFUL
1148   // expected-note@-3 {{Object 'P' is moved}}
1149   // expected-warning@-3 {{Method called on moved-from object 'P'}}
1150   // expected-note@-4    {{Method called on moved-from object 'P'}}
1151 #endif
1152 }
1153 
1154 void localUniquePtrWithArrow(std::unique_ptr<A> P) {
1155   std::unique_ptr<A> Q = std::move(P); // expected-note{{Smart pointer 'P' of type 'std::unique_ptr' is reset to null when moved from}}
1156   P->foo(); // expected-warning{{Dereference of null smart pointer 'P' of type 'std::unique_ptr'}}
1157             // expected-note@-1{{Dereference of null smart pointer 'P' of type 'std::unique_ptr'}}
1158 }
1159