1 // RUN: %check_clang_tidy %s bugprone-use-after-move %t -- -- -std=c++17 -fno-delayed-template-parsing
2 
3 typedef decltype(nullptr) nullptr_t;
4 
5 namespace std {
6 typedef unsigned size_t;
7 
8 template <typename T>
9 struct unique_ptr {
10   unique_ptr();
11   T *get() const;
12   explicit operator bool() const;
13   void reset(T *ptr);
14   T &operator*() const;
15   T *operator->() const;
16   T& operator[](size_t i) const;
17 };
18 
19 template <typename T>
20 struct shared_ptr {
21   shared_ptr();
22   T *get() const;
23   explicit operator bool() const;
24   void reset(T *ptr);
25   T &operator*() const;
26   T *operator->() const;
27 };
28 
29 template <typename T>
30 struct weak_ptr {
31   weak_ptr();
32   bool expired() const;
33 };
34 
35 #define DECLARE_STANDARD_CONTAINER(name) \
36   template <typename T>                  \
37   struct name {                          \
38     name();                              \
39     void clear();                        \
40     bool empty();                        \
41   }
42 
43 #define DECLARE_STANDARD_CONTAINER_WITH_ASSIGN(name) \
44   template <typename T>                              \
45   struct name {                                      \
46     name();                                          \
47     void clear();                                    \
48     bool empty();                                    \
49     void assign(size_t, const T &);                  \
50   }
51 
52 DECLARE_STANDARD_CONTAINER_WITH_ASSIGN(basic_string);
53 DECLARE_STANDARD_CONTAINER_WITH_ASSIGN(vector);
54 DECLARE_STANDARD_CONTAINER_WITH_ASSIGN(deque);
55 DECLARE_STANDARD_CONTAINER_WITH_ASSIGN(forward_list);
56 DECLARE_STANDARD_CONTAINER_WITH_ASSIGN(list);
57 DECLARE_STANDARD_CONTAINER(set);
58 DECLARE_STANDARD_CONTAINER(map);
59 DECLARE_STANDARD_CONTAINER(multiset);
60 DECLARE_STANDARD_CONTAINER(multimap);
61 DECLARE_STANDARD_CONTAINER(unordered_set);
62 DECLARE_STANDARD_CONTAINER(unordered_map);
63 DECLARE_STANDARD_CONTAINER(unordered_multiset);
64 DECLARE_STANDARD_CONTAINER(unordered_multimap);
65 
66 typedef basic_string<char> string;
67 
68 template <typename>
69 struct remove_reference;
70 
71 template <typename _Tp>
72 struct remove_reference {
73   typedef _Tp type;
74 };
75 
76 template <typename _Tp>
77 struct remove_reference<_Tp &> {
78   typedef _Tp type;
79 };
80 
81 template <typename _Tp>
82 struct remove_reference<_Tp &&> {
83   typedef _Tp type;
84 };
85 
86 template <typename _Tp>
move(_Tp && __t)87 constexpr typename std::remove_reference<_Tp>::type &&move(_Tp &&__t) noexcept {
88   return static_cast<typename remove_reference<_Tp>::type &&>(__t);
89 }
90 
91 } // namespace std
92 
93 class A {
94 public:
95   A();
96   A(const A &);
97   A(A &&);
98 
99   A &operator=(const A &);
100   A &operator=(A &&);
101 
102   void foo() const;
103   int getInt() const;
104 
105   operator bool() const;
106 
107   int i;
108 };
109 
110 template <class T>
111 class AnnotatedContainer {
112 public:
113   AnnotatedContainer();
114 
115   void foo() const;
116   [[clang::reinitializes]] void clear();
117 };
118 
119 ////////////////////////////////////////////////////////////////////////////////
120 // General tests.
121 
122 // Simple case.
simple()123 void simple() {
124   A a;
125   a.foo();
126   A other_a = std::move(a);
127   a.foo();
128   // CHECK-NOTES: [[@LINE-1]]:3: warning: 'a' used after it was moved
129   // CHECK-NOTES: [[@LINE-3]]:15: note: move occurred here
130 }
131 
132 // A warning should only be emitted for one use-after-move.
onlyFlagOneUseAfterMove()133 void onlyFlagOneUseAfterMove() {
134   A a;
135   a.foo();
136   A other_a = std::move(a);
137   a.foo();
138   // CHECK-NOTES: [[@LINE-1]]:3: warning: 'a' used after it was moved
139   // CHECK-NOTES: [[@LINE-3]]:15: note: move occurred here
140   a.foo();
141 }
142 
moveAfterMove()143 void moveAfterMove() {
144   // Move-after-move also counts as a use.
145   {
146     A a;
147     std::move(a);
148     std::move(a);
149     // CHECK-NOTES: [[@LINE-1]]:15: warning: 'a' used after it was moved
150     // CHECK-NOTES: [[@LINE-3]]:5: note: move occurred here
151   }
152   // This is also true if the move itself turns into the use on the second loop
153   // iteration.
154   {
155     A a;
156     for (int i = 0; i < 10; ++i) {
157       std::move(a);
158       // CHECK-NOTES: [[@LINE-1]]:17: warning: 'a' used after it was moved
159       // CHECK-NOTES: [[@LINE-2]]:7: note: move occurred here
160       // CHECK-NOTES: [[@LINE-3]]:17: note: the use happens in a later loop
161     }
162   }
163 }
164 
165 // Checks also works on function parameters that have a use-after move.
parameters(A a)166 void parameters(A a) {
167   std::move(a);
168   a.foo();
169   // CHECK-NOTES: [[@LINE-1]]:3: warning: 'a' used after it was moved
170   // CHECK-NOTES: [[@LINE-3]]:3: note: move occurred here
171 }
172 
standardSmartPtr()173 void standardSmartPtr() {
174   // std::unique_ptr<>, std::shared_ptr<> and std::weak_ptr<> are guaranteed to
175   // be null after a std::move. So the check only flags accesses that would
176   // dereference the pointer.
177   {
178     std::unique_ptr<A> ptr;
179     std::move(ptr);
180     ptr.get();
181     static_cast<bool>(ptr);
182     *ptr;
183     // CHECK-NOTES: [[@LINE-1]]:6: warning: 'ptr' used after it was moved
184     // CHECK-NOTES: [[@LINE-5]]:5: note: move occurred here
185   }
186   {
187     std::unique_ptr<A> ptr;
188     std::move(ptr);
189     ptr->foo();
190     // CHECK-NOTES: [[@LINE-1]]:5: warning: 'ptr' used after it was moved
191     // CHECK-NOTES: [[@LINE-3]]:5: note: move occurred here
192   }
193   {
194     std::unique_ptr<A> ptr;
195     std::move(ptr);
196     ptr[0];
197     // CHECK-NOTES: [[@LINE-1]]:5: warning: 'ptr' used after it was moved
198     // CHECK-NOTES: [[@LINE-3]]:5: note: move occurred here
199   }
200   {
201     std::shared_ptr<A> ptr;
202     std::move(ptr);
203     ptr.get();
204     static_cast<bool>(ptr);
205     *ptr;
206     // CHECK-NOTES: [[@LINE-1]]:6: warning: 'ptr' used after it was moved
207     // CHECK-NOTES: [[@LINE-5]]:5: note: move occurred here
208   }
209   {
210     std::shared_ptr<A> ptr;
211     std::move(ptr);
212     ptr->foo();
213     // CHECK-NOTES: [[@LINE-1]]:5: warning: 'ptr' used after it was moved
214     // CHECK-NOTES: [[@LINE-3]]:5: note: move occurred here
215   }
216   {
217     // std::weak_ptr<> cannot be dereferenced directly, so we only check that
218     // member functions may be called on it after a move.
219     std::weak_ptr<A> ptr;
220     std::move(ptr);
221     ptr.expired();
222   }
223   // Make sure we recognize std::unique_ptr<> or std::shared_ptr<> if they're
224   // wrapped in a typedef.
225   {
226     typedef std::unique_ptr<A> PtrToA;
227     PtrToA ptr;
228     std::move(ptr);
229     ptr.get();
230   }
231   {
232     typedef std::shared_ptr<A> PtrToA;
233     PtrToA ptr;
234     std::move(ptr);
235     ptr.get();
236   }
237   // And we don't get confused if the template argument is a little more
238   // involved.
239   {
240     struct B {
241       typedef A AnotherNameForA;
242     };
243     std::unique_ptr<B::AnotherNameForA> ptr;
244     std::move(ptr);
245     ptr.get();
246   }
247   // Make sure we treat references to smart pointers correctly.
248   {
249     std::unique_ptr<A> ptr;
250     std::unique_ptr<A>& ref_to_ptr = ptr;
251     std::move(ref_to_ptr);
252     ref_to_ptr.get();
253   }
254   {
255     std::unique_ptr<A> ptr;
256     std::unique_ptr<A>&& rvalue_ref_to_ptr = std::move(ptr);
257     std::move(rvalue_ref_to_ptr);
258     rvalue_ref_to_ptr.get();
259   }
260   // We don't give any special treatment to types that are called "unique_ptr"
261   // or "shared_ptr" but are not in the "::std" namespace.
262   {
263     struct unique_ptr {
264       void get();
265     } ptr;
266     std::move(ptr);
267     ptr.get();
268     // CHECK-NOTES: [[@LINE-1]]:5: warning: 'ptr' used after it was moved
269     // CHECK-NOTES: [[@LINE-3]]:5: note: move occurred here
270   }
271 }
272 
273 // The check also works in member functions.
274 class Container {
useAfterMoveInMemberFunction()275   void useAfterMoveInMemberFunction() {
276     A a;
277     std::move(a);
278     a.foo();
279     // CHECK-NOTES: [[@LINE-1]]:5: warning: 'a' used after it was moved
280     // CHECK-NOTES: [[@LINE-3]]:5: note: move occurred here
281   }
282 };
283 
284 // We see the std::move() if it's inside a declaration.
moveInDeclaration()285 void moveInDeclaration() {
286   A a;
287   A another_a(std::move(a));
288   a.foo();
289   // CHECK-NOTES: [[@LINE-1]]:3: warning: 'a' used after it was moved
290   // CHECK-NOTES: [[@LINE-3]]:5: note: move occurred here
291 }
292 
293 // We see the std::move if it's inside an initializer list. Initializer lists
294 // are a special case because they cause ASTContext::getParents() to return
295 // multiple parents for certain nodes in their subtree. This is because
296 // RecursiveASTVisitor visits both the syntactic and semantic forms of
297 // InitListExpr, and the parent-child relationships are different between the
298 // two forms.
moveInInitList()299 void moveInInitList() {
300   struct S {
301     A a;
302   };
303   A a;
304   S s{std::move(a)};
305   a.foo();
306   // CHECK-NOTES: [[@LINE-1]]:3: warning: 'a' used after it was moved
307   // CHECK-NOTES: [[@LINE-3]]:7: note: move occurred here
308 }
309 
lambdas()310 void lambdas() {
311   // Use-after-moves inside a lambda should be detected.
312   {
313     A a;
314     auto lambda = [a] {
315       std::move(a);
316       a.foo();
317       // CHECK-NOTES: [[@LINE-1]]:7: warning: 'a' used after it was moved
318       // CHECK-NOTES: [[@LINE-3]]:7: note: move occurred here
319     };
320   }
321   // This is just as true if the variable was declared inside the lambda.
322   {
323     auto lambda = [] {
324       A a;
325       std::move(a);
326       a.foo();
327       // CHECK-NOTES: [[@LINE-1]]:7: warning: 'a' used after it was moved
328       // CHECK-NOTES: [[@LINE-3]]:7: note: move occurred here
329     };
330   }
331   // But don't warn if the move happened inside the lambda but the use happened
332   // outside -- because
333   // - the 'a' inside the lambda is a copy, and
334   // - we don't know when the lambda will get called anyway
335   {
336     A a;
337     auto lambda = [a] {
338       std::move(a);
339     };
340     a.foo();
341   }
342   // Warn if the use consists of a capture that happens after a move.
343   {
344     A a;
345     std::move(a);
346     auto lambda = [a]() { a.foo(); };
347     // CHECK-NOTES: [[@LINE-1]]:20: warning: 'a' used after it was moved
348     // CHECK-NOTES: [[@LINE-3]]:5: note: move occurred here
349   }
350   // ...even if the capture was implicit.
351   {
352     A a;
353     std::move(a);
354     auto lambda = [=]() { a.foo(); };
355     // CHECK-NOTES: [[@LINE-1]]:20: warning: 'a' used after it was moved
356     // CHECK-NOTES: [[@LINE-3]]:5: note: move occurred here
357   }
358   // Same tests but for capture by reference.
359   {
360     A a;
361     std::move(a);
362     auto lambda = [&a]() { a.foo(); };
363     // CHECK-NOTES: [[@LINE-1]]:21: warning: 'a' used after it was moved
364     // CHECK-NOTES: [[@LINE-3]]:5: note: move occurred here
365   }
366   {
367     A a;
368     std::move(a);
369     auto lambda = [&]() { a.foo(); };
370     // CHECK-NOTES: [[@LINE-1]]:20: warning: 'a' used after it was moved
371     // CHECK-NOTES: [[@LINE-3]]:5: note: move occurred here
372   }
373   // But don't warn if the move happened after the capture.
374   {
375     A a;
376     auto lambda = [a]() { a.foo(); };
377     std::move(a);
378   }
379   // ...and again, same thing with an implicit move.
380   {
381     A a;
382     auto lambda = [=]() { a.foo(); };
383     std::move(a);
384   }
385   // Same tests but for capture by reference.
386   {
387     A a;
388     auto lambda = [&a]() { a.foo(); };
389     std::move(a);
390   }
391   {
392     A a;
393     auto lambda = [&]() { a.foo(); };
394     std::move(a);
395   }
396 }
397 
398 // Use-after-moves are detected in uninstantiated templates if the moved type
399 // is not a dependent type.
400 template <class T>
movedTypeIsNotDependentType()401 void movedTypeIsNotDependentType() {
402   T t;
403   A a;
404   std::move(a);
405   a.foo();
406   // CHECK-NOTES: [[@LINE-1]]:3: warning: 'a' used after it was moved
407   // CHECK-NOTES: [[@LINE-3]]:3: note: move occurred here
408 }
409 
410 // And if the moved type is a dependent type, the use-after-move is detected if
411 // the template is instantiated.
412 template <class T>
movedTypeIsDependentType()413 void movedTypeIsDependentType() {
414   T t;
415   std::move(t);
416   t.foo();
417   // CHECK-NOTES: [[@LINE-1]]:3: warning: 't' used after it was moved
418   // CHECK-NOTES: [[@LINE-3]]:3: note: move occurred here
419 }
420 template void movedTypeIsDependentType<A>();
421 
422 // We handle the case correctly where the move consists of an implicit call
423 // to a conversion operator.
implicitConversionOperator()424 void implicitConversionOperator() {
425   struct Convertible {
426     operator A() && { return A(); }
427   };
428   void takeA(A a);
429 
430   Convertible convertible;
431   takeA(std::move(convertible));
432   convertible;
433   // CHECK-NOTES: [[@LINE-1]]:3: warning: 'convertible' used after it was moved
434   // CHECK-NOTES: [[@LINE-3]]:9: note: move occurred here
435 }
436 
437 // Using decltype on an expression is not a use.
decltypeIsNotUse()438 void decltypeIsNotUse() {
439   A a;
440   std::move(a);
441   decltype(a) other_a;
442 }
443 
444 // Ignore moves or uses that occur as part of template arguments.
445 template <int>
446 class ClassTemplate {
447 public:
448   void foo(A a);
449 };
450 template <int>
451 void functionTemplate(A a);
templateArgIsNotUse()452 void templateArgIsNotUse() {
453   {
454     // A pattern like this occurs in the EXPECT_EQ and ASSERT_EQ macros in
455     // Google Test.
456     A a;
457     ClassTemplate<sizeof(A(std::move(a)))>().foo(std::move(a));
458   }
459   {
460     A a;
461     functionTemplate<sizeof(A(std::move(a)))>(std::move(a));
462   }
463 }
464 
465 // Ignore moves of global variables.
466 A global_a;
ignoreGlobalVariables()467 void ignoreGlobalVariables() {
468   std::move(global_a);
469   global_a.foo();
470 }
471 
472 // Ignore moves of member variables.
473 class IgnoreMemberVariables {
474   A a;
475   static A static_a;
476 
f()477   void f() {
478     std::move(a);
479     a.foo();
480 
481     std::move(static_a);
482     static_a.foo();
483   }
484 };
485 
486 ////////////////////////////////////////////////////////////////////////////////
487 // Tests involving control flow.
488 
useAndMoveInLoop()489 void useAndMoveInLoop() {
490   // Warn about use-after-moves if they happen in a later loop iteration than
491   // the std::move().
492   {
493     A a;
494     for (int i = 0; i < 10; ++i) {
495       a.foo();
496       // CHECK-NOTES: [[@LINE-1]]:7: warning: 'a' used after it was moved
497       // CHECK-NOTES: [[@LINE+2]]:7: note: move occurred here
498       // CHECK-NOTES: [[@LINE-3]]:7: note: the use happens in a later loop
499       std::move(a);
500     }
501   }
502   // However, this case shouldn't be flagged -- the scope of the declaration of
503   // 'a' is important.
504   {
505     for (int i = 0; i < 10; ++i) {
506       A a;
507       a.foo();
508       std::move(a);
509     }
510   }
511   // Same as above, except that we have an unrelated variable being declared in
512   // the same declaration as 'a'. This case is interesting because it tests that
513   // the synthetic DeclStmts generated by the CFG are sequenced correctly
514   // relative to the other statements.
515   {
516     for (int i = 0; i < 10; ++i) {
517       A a, other;
518       a.foo();
519       std::move(a);
520     }
521   }
522   // Don't warn if we return after the move.
523   {
524     A a;
525     for (int i = 0; i < 10; ++i) {
526       a.foo();
527       if (a.getInt() > 0) {
528         std::move(a);
529         return;
530       }
531     }
532   }
533 }
534 
differentBranches(int i)535 void differentBranches(int i) {
536   // Don't warn if the use is in a different branch from the move.
537   {
538     A a;
539     if (i > 0) {
540       std::move(a);
541     } else {
542       a.foo();
543     }
544   }
545   // Same thing, but with a ternary operator.
546   {
547     A a;
548     i > 0 ? (void)std::move(a) : a.foo();
549   }
550   // A variation on the theme above.
551   {
552     A a;
553     a.getInt() > 0 ? a.getInt() : A(std::move(a)).getInt();
554   }
555   // Same thing, but with a switch statement.
556   {
557     A a;
558     switch (i) {
559     case 1:
560       std::move(a);
561       break;
562     case 2:
563       a.foo();
564       break;
565     }
566   }
567   // However, if there's a fallthrough, we do warn.
568   {
569     A a;
570     switch (i) {
571     case 1:
572       std::move(a);
573     case 2:
574       a.foo();
575       // CHECK-NOTES: [[@LINE-1]]:7: warning: 'a' used after it was moved
576       // CHECK-NOTES: [[@LINE-4]]:7: note: move occurred here
577       break;
578     }
579   }
580 }
581 
582 // False positive: A use-after-move is flagged even though the "if (b)" and
583 // "if (!b)" are mutually exclusive.
mutuallyExclusiveBranchesFalsePositive(bool b)584 void mutuallyExclusiveBranchesFalsePositive(bool b) {
585   A a;
586   if (b) {
587     std::move(a);
588   }
589   if (!b) {
590     a.foo();
591     // CHECK-NOTES: [[@LINE-1]]:5: warning: 'a' used after it was moved
592     // CHECK-NOTES: [[@LINE-5]]:5: note: move occurred here
593   }
594 }
595 
596 // Destructors marked [[noreturn]] are handled correctly in the control flow
597 // analysis. (These are used in some styles of assertion macros.)
598 class FailureLogger {
599 public:
600   FailureLogger();
601   [[noreturn]] ~FailureLogger();
602   void log(const char *);
603 };
604 #define ASSERT(x) \
605   while (x)       \
606   FailureLogger().log(#x)
607 bool operationOnA(A);
noreturnDestructor()608 void noreturnDestructor() {
609   A a;
610   // The while loop in the ASSERT() would ordinarily have the potential to cause
611   // a use-after-move because the second iteration of the loop would be using a
612   // variable that had been moved from in the first iteration. Check that the
613   // CFG knows that the second iteration of the loop is never reached because
614   // the FailureLogger destructor is marked [[noreturn]].
615   ASSERT(operationOnA(std::move(a)));
616 }
617 #undef ASSERT
618 
619 ////////////////////////////////////////////////////////////////////////////////
620 // Tests for reinitializations
621 
622 template <class T>
swap(T & a,T & b)623 void swap(T &a, T &b) {
624   T tmp = std::move(a);
625   a = std::move(b);
626   b = std::move(tmp);
627 }
assignments(int i)628 void assignments(int i) {
629   // Don't report a use-after-move if the variable was assigned to in the
630   // meantime.
631   {
632     A a;
633     std::move(a);
634     a = A();
635     a.foo();
636   }
637   // The assignment should also be recognized if move, assignment and use don't
638   // all happen in the same block (but the assignment is still guaranteed to
639   // prevent a use-after-move).
640   {
641     A a;
642     if (i == 1) {
643       std::move(a);
644       a = A();
645     }
646     if (i == 2) {
647       a.foo();
648     }
649   }
650   {
651     A a;
652     if (i == 1) {
653       std::move(a);
654     }
655     if (i == 2) {
656       a = A();
657       a.foo();
658     }
659   }
660   // The built-in assignment operator should also be recognized as a
661   // reinitialization. (std::move() may be called on built-in types in template
662   // code.)
663   {
664     int a1 = 1, a2 = 2;
665     swap(a1, a2);
666   }
667   // A std::move() after the assignment makes the variable invalid again.
668   {
669     A a;
670     std::move(a);
671     a = A();
672     std::move(a);
673     a.foo();
674     // CHECK-NOTES: [[@LINE-1]]:5: warning: 'a' used after it was moved
675     // CHECK-NOTES: [[@LINE-3]]:5: note: move occurred here
676   }
677   // Report a use-after-move if we can't be sure that the variable was assigned
678   // to.
679   {
680     A a;
681     std::move(a);
682     if (i < 10) {
683       a = A();
684     }
685     if (i > 5) {
686       a.foo();
687       // CHECK-NOTES: [[@LINE-1]]:7: warning: 'a' used after it was moved
688       // CHECK-NOTES: [[@LINE-7]]:5: note: move occurred here
689     }
690   }
691 }
692 
693 // Passing the object to a function through a non-const pointer or reference
694 // counts as a re-initialization.
695 void passByNonConstPointer(A *);
696 void passByNonConstReference(A &);
passByNonConstPointerIsReinit()697 void passByNonConstPointerIsReinit() {
698   {
699     A a;
700     std::move(a);
701     passByNonConstPointer(&a);
702     a.foo();
703   }
704   {
705     A a;
706     std::move(a);
707     passByNonConstReference(a);
708     a.foo();
709   }
710 }
711 
712 // Passing the object through a const pointer or reference counts as a use --
713 // since the called function cannot reinitialize the object.
714 void passByConstPointer(const A *);
715 void passByConstReference(const A &);
passByConstPointerIsUse()716 void passByConstPointerIsUse() {
717   {
718     // Declaring 'a' as const so that no ImplicitCastExpr is inserted into the
719     // AST -- we wouldn't want the check to rely solely on that to detect a
720     // const pointer argument.
721     const A a;
722     std::move(a);
723     passByConstPointer(&a);
724     // CHECK-NOTES: [[@LINE-1]]:25: warning: 'a' used after it was moved
725     // CHECK-NOTES: [[@LINE-3]]:5: note: move occurred here
726   }
727   const A a;
728   std::move(a);
729   passByConstReference(a);
730   // CHECK-NOTES: [[@LINE-1]]:24: warning: 'a' used after it was moved
731   // CHECK-NOTES: [[@LINE-3]]:3: note: move occurred here
732 }
733 
734 // Clearing a standard container using clear() is treated as a
735 // re-initialization.
standardContainerClearIsReinit()736 void standardContainerClearIsReinit() {
737   {
738     std::string container;
739     std::move(container);
740     container.clear();
741     container.empty();
742   }
743   {
744     std::vector<int> container;
745     std::move(container);
746     container.clear();
747     container.empty();
748 
749     auto container2 = container;
750     std::move(container2);
751     container2.clear();
752     container2.empty();
753   }
754   {
755     std::deque<int> container;
756     std::move(container);
757     container.clear();
758     container.empty();
759   }
760   {
761     std::forward_list<int> container;
762     std::move(container);
763     container.clear();
764     container.empty();
765   }
766   {
767     std::list<int> container;
768     std::move(container);
769     container.clear();
770     container.empty();
771   }
772   {
773     std::set<int> container;
774     std::move(container);
775     container.clear();
776     container.empty();
777   }
778   {
779     std::map<int> container;
780     std::move(container);
781     container.clear();
782     container.empty();
783   }
784   {
785     std::multiset<int> container;
786     std::move(container);
787     container.clear();
788     container.empty();
789   }
790   {
791     std::multimap<int> container;
792     std::move(container);
793     container.clear();
794     container.empty();
795   }
796   {
797     std::unordered_set<int> container;
798     std::move(container);
799     container.clear();
800     container.empty();
801   }
802   {
803     std::unordered_map<int> container;
804     std::move(container);
805     container.clear();
806     container.empty();
807   }
808   {
809     std::unordered_multiset<int> container;
810     std::move(container);
811     container.clear();
812     container.empty();
813   }
814   {
815     std::unordered_multimap<int> container;
816     std::move(container);
817     container.clear();
818     container.empty();
819   }
820   // This should also work for typedefs of standard containers.
821   {
822     typedef std::vector<int> IntVector;
823     IntVector container;
824     std::move(container);
825     container.clear();
826     container.empty();
827   }
828   // But it shouldn't work for non-standard containers.
829   {
830     // This might be called "vector", but it's not in namespace "std".
831     struct vector {
832       void clear() {}
833     } container;
834     std::move(container);
835     container.clear();
836     // CHECK-NOTES: [[@LINE-1]]:5: warning: 'container' used after it was
837     // CHECK-NOTES: [[@LINE-3]]:5: note: move occurred here
838   }
839   // An intervening clear() on a different container does not reinitialize.
840   {
841     std::vector<int> container1, container2;
842     std::move(container1);
843     container2.clear();
844     container1.empty();
845     // CHECK-NOTES: [[@LINE-1]]:5: warning: 'container1' used after it was
846     // CHECK-NOTES: [[@LINE-4]]:5: note: move occurred here
847   }
848 }
849 
850 // Clearing a standard container using assign() is treated as a
851 // re-initialization.
standardContainerAssignIsReinit()852 void standardContainerAssignIsReinit() {
853   {
854     std::string container;
855     std::move(container);
856     container.assign(0, ' ');
857     container.empty();
858   }
859   {
860     std::vector<int> container;
861     std::move(container);
862     container.assign(0, 0);
863     container.empty();
864   }
865   {
866     std::deque<int> container;
867     std::move(container);
868     container.assign(0, 0);
869     container.empty();
870   }
871   {
872     std::forward_list<int> container;
873     std::move(container);
874     container.assign(0, 0);
875     container.empty();
876   }
877   {
878     std::list<int> container;
879     std::move(container);
880     container.clear();
881     container.empty();
882   }
883   // But it doesn't work for non-standard containers.
884   {
885     // This might be called "vector", but it's not in namespace "std".
886     struct vector {
887       void assign(std::size_t, int) {}
888     } container;
889     std::move(container);
890     container.assign(0, 0);
891     // CHECK-NOTES: [[@LINE-1]]:5: warning: 'container' used after it was
892     // CHECK-NOTES: [[@LINE-3]]:5: note: move occurred here
893   }
894   // An intervening assign() on a different container does not reinitialize.
895   {
896     std::vector<int> container1, container2;
897     std::move(container1);
898     container2.assign(0, 0);
899     container1.empty();
900     // CHECK-NOTES: [[@LINE-1]]:5: warning: 'container1' used after it was
901     // CHECK-NOTES: [[@LINE-4]]:5: note: move occurred here
902   }
903 }
904 
905 // Resetting the standard smart pointer types using reset() is treated as a
906 // re-initialization. (We don't test std::weak_ptr<> because it can't be
907 // dereferenced directly.)
standardSmartPointerResetIsReinit()908 void standardSmartPointerResetIsReinit() {
909   {
910     std::unique_ptr<A> ptr;
911     std::move(ptr);
912     ptr.reset(new A);
913     *ptr;
914   }
915   {
916     std::shared_ptr<A> ptr;
917     std::move(ptr);
918     ptr.reset(new A);
919     *ptr;
920   }
921 }
922 
reinitAnnotation()923 void reinitAnnotation() {
924   {
925     AnnotatedContainer<int> obj;
926     std::move(obj);
927     obj.foo();
928     // CHECK-NOTES: [[@LINE-1]]:5: warning: 'obj' used after it was
929     // CHECK-NOTES: [[@LINE-3]]:5: note: move occurred here
930   }
931   {
932     AnnotatedContainer<int> obj;
933     std::move(obj);
934     obj.clear();
935     obj.foo();
936   }
937   {
938     // Calling clear() on a different object to the one that was moved is not
939     // considered a reinitialization.
940     AnnotatedContainer<int> obj1, obj2;
941     std::move(obj1);
942     obj2.clear();
943     obj1.foo();
944     // CHECK-NOTES: [[@LINE-1]]:5: warning: 'obj1' used after it was
945     // CHECK-NOTES: [[@LINE-4]]:5: note: move occurred here
946   }
947 }
948 
949 ////////////////////////////////////////////////////////////////////////////////
950 // Tests related to order of evaluation within expressions
951 
952 // Relative sequencing of move and use.
953 void passByRvalueReference(int i, A &&a);
954 void passByValue(int i, A a);
955 void passByValue(A a, int i);
956 A g(A, A &&);
957 int intFromA(A &&);
958 int intFromInt(int);
sequencingOfMoveAndUse()959 void sequencingOfMoveAndUse() {
960   // This case is fine because the move only happens inside
961   // passByRvalueReference(). At this point, a.getInt() is guaranteed to have
962   // been evaluated.
963   {
964     A a;
965     passByRvalueReference(a.getInt(), std::move(a));
966   }
967   // However, if we pass by value, the move happens when the move constructor is
968   // called to create a temporary, and this happens before the call to
969   // passByValue(). Because the order in which arguments are evaluated isn't
970   // defined, the move may happen before the call to a.getInt().
971   //
972   // Check that we warn about a potential use-after move for both orderings of
973   // a.getInt() and std::move(a), independent of the order in which the
974   // arguments happen to get evaluated by the compiler.
975   {
976     A a;
977     passByValue(a.getInt(), std::move(a));
978     // CHECK-NOTES: [[@LINE-1]]:17: warning: 'a' used after it was moved
979     // CHECK-NOTES: [[@LINE-2]]:29: note: move occurred here
980     // CHECK-NOTES: [[@LINE-3]]:17: note: the use and move are unsequenced
981   }
982   {
983     A a;
984     passByValue(std::move(a), a.getInt());
985     // CHECK-NOTES: [[@LINE-1]]:31: warning: 'a' used after it was moved
986     // CHECK-NOTES: [[@LINE-2]]:17: note: move occurred here
987     // CHECK-NOTES: [[@LINE-3]]:31: note: the use and move are unsequenced
988   }
989   // An even more convoluted example.
990   {
991     A a;
992     g(g(a, std::move(a)), g(a, std::move(a)));
993     // CHECK-NOTES: [[@LINE-1]]:9: warning: 'a' used after it was moved
994     // CHECK-NOTES: [[@LINE-2]]:27: note: move occurred here
995     // CHECK-NOTES: [[@LINE-3]]:9: note: the use and move are unsequenced
996     // CHECK-NOTES: [[@LINE-4]]:29: warning: 'a' used after it was moved
997     // CHECK-NOTES: [[@LINE-5]]:7: note: move occurred here
998     // CHECK-NOTES: [[@LINE-6]]:29: note: the use and move are unsequenced
999   }
1000   // This case is fine because the actual move only happens inside the call to
1001   // operator=(). a.getInt(), by necessity, is evaluated before that call.
1002   {
1003     A a;
1004     A vec[1];
1005     vec[a.getInt()] = std::move(a);
1006   }
1007   // However, in the following case, the move happens before the assignment, and
1008   // so the order of evaluation is not guaranteed.
1009   {
1010     A a;
1011     int v[3];
1012     v[a.getInt()] = intFromA(std::move(a));
1013     // CHECK-NOTES: [[@LINE-1]]:7: warning: 'a' used after it was moved
1014     // CHECK-NOTES: [[@LINE-2]]:21: note: move occurred here
1015     // CHECK-NOTES: [[@LINE-3]]:7: note: the use and move are unsequenced
1016   }
1017   {
1018     A a;
1019     int v[3];
1020     v[intFromA(std::move(a))] = intFromInt(a.i);
1021     // CHECK-NOTES: [[@LINE-1]]:44: warning: 'a' used after it was moved
1022     // CHECK-NOTES: [[@LINE-2]]:7: note: move occurred here
1023     // CHECK-NOTES: [[@LINE-3]]:44: note: the use and move are unsequenced
1024   }
1025 }
1026 
1027 // Relative sequencing of move and reinitialization. If the two are unsequenced,
1028 // we conservatively assume that the move happens after the reinitialization,
1029 // i.e. the that object does not get reinitialized after the move.
1030 A MutateA(A a);
1031 void passByValue(A a1, A a2);
sequencingOfMoveAndReinit()1032 void sequencingOfMoveAndReinit() {
1033   // Move and reinitialization as function arguments (which are indeterminately
1034   // sequenced). Again, check that we warn for both orderings.
1035   {
1036     A a;
1037     passByValue(std::move(a), (a = A()));
1038     a.foo();
1039     // CHECK-NOTES: [[@LINE-1]]:5: warning: 'a' used after it was moved
1040     // CHECK-NOTES: [[@LINE-3]]:17: note: move occurred here
1041   }
1042   {
1043     A a;
1044     passByValue((a = A()), std::move(a));
1045     a.foo();
1046     // CHECK-NOTES: [[@LINE-1]]:5: warning: 'a' used after it was moved
1047     // CHECK-NOTES: [[@LINE-3]]:28: note: move occurred here
1048   }
1049   // Common usage pattern: Move the object to a function that mutates it in some
1050   // way, then reassign the result to the object. This pattern is fine.
1051   {
1052     A a;
1053     a = MutateA(std::move(a));
1054     a.foo();
1055   }
1056 }
1057 
1058 // Relative sequencing of reinitialization and use. If the two are unsequenced,
1059 // we conservatively assume that the reinitialization happens after the use,
1060 // i.e. that the object is not reinitialized at the point in time when it is
1061 // used.
sequencingOfReinitAndUse()1062 void sequencingOfReinitAndUse() {
1063   // Reinitialization and use in function arguments. Again, check both possible
1064   // orderings.
1065   {
1066     A a;
1067     std::move(a);
1068     passByValue(a.getInt(), (a = A()));
1069     // CHECK-NOTES: [[@LINE-1]]:17: warning: 'a' used after it was moved
1070     // CHECK-NOTES: [[@LINE-3]]:5: note: move occurred here
1071   }
1072   {
1073     A a;
1074     std::move(a);
1075     passByValue((a = A()), a.getInt());
1076     // CHECK-NOTES: [[@LINE-1]]:28: warning: 'a' used after it was moved
1077     // CHECK-NOTES: [[@LINE-3]]:5: note: move occurred here
1078   }
1079 }
1080 
1081 // The comma operator sequences its operands.
commaOperatorSequences()1082 void commaOperatorSequences() {
1083   {
1084     A a;
1085     A(std::move(a))
1086     , (a = A());
1087     a.foo();
1088   }
1089   {
1090     A a;
1091     (a = A()), A(std::move(a));
1092     a.foo();
1093     // CHECK-NOTES: [[@LINE-1]]:5: warning: 'a' used after it was moved
1094     // CHECK-NOTES: [[@LINE-3]]:16: note: move occurred here
1095   }
1096 }
1097 
1098 // An initializer list sequences its initialization clauses.
initializerListSequences()1099 void initializerListSequences() {
1100   {
1101     struct S1 {
1102       int i;
1103       A a;
1104     };
1105     A a;
1106     S1 s1{a.getInt(), std::move(a)};
1107   }
1108   {
1109     struct S2 {
1110       A a;
1111       int i;
1112     };
1113     A a;
1114     S2 s2{std::move(a), a.getInt()};
1115     // CHECK-NOTES: [[@LINE-1]]:25: warning: 'a' used after it was moved
1116     // CHECK-NOTES: [[@LINE-2]]:11: note: move occurred here
1117   }
1118 }
1119 
1120 // A declaration statement containing multiple declarations sequences the
1121 // initializer expressions.
declarationSequences()1122 void declarationSequences() {
1123   {
1124     A a;
1125     A a1 = a, a2 = std::move(a);
1126   }
1127   {
1128     A a;
1129     A a1 = std::move(a), a2 = a;
1130     // CHECK-NOTES: [[@LINE-1]]:31: warning: 'a' used after it was moved
1131     // CHECK-NOTES: [[@LINE-2]]:12: note: move occurred here
1132   }
1133 }
1134 
1135 // The logical operators && and || sequence their operands.
logicalOperatorsSequence()1136 void logicalOperatorsSequence() {
1137   {
1138     A a;
1139     if (a.getInt() > 0 && A(std::move(a)).getInt() > 0) {
1140       A().foo();
1141     }
1142   }
1143   // A variation: Negate the result of the && (which pushes the && further down
1144   // into the AST).
1145   {
1146     A a;
1147     if (!(a.getInt() > 0 && A(std::move(a)).getInt() > 0)) {
1148       A().foo();
1149     }
1150   }
1151   {
1152     A a;
1153     if (A(std::move(a)).getInt() > 0 && a.getInt() > 0) {
1154       // CHECK-NOTES: [[@LINE-1]]:41: warning: 'a' used after it was moved
1155       // CHECK-NOTES: [[@LINE-2]]:9: note: move occurred here
1156       A().foo();
1157     }
1158   }
1159   {
1160     A a;
1161     if (a.getInt() > 0 || A(std::move(a)).getInt() > 0) {
1162       A().foo();
1163     }
1164   }
1165   {
1166     A a;
1167     if (A(std::move(a)).getInt() > 0 || a.getInt() > 0) {
1168       // CHECK-NOTES: [[@LINE-1]]:41: warning: 'a' used after it was moved
1169       // CHECK-NOTES: [[@LINE-2]]:9: note: move occurred here
1170       A().foo();
1171     }
1172   }
1173 }
1174 
1175 // A range-based for sequences the loop variable declaration before the body.
forRangeSequences()1176 void forRangeSequences() {
1177   A v[2] = {A(), A()};
1178   for (A &a : v) {
1179     std::move(a);
1180   }
1181 }
1182 
1183 // If a variable is declared in an if, while or switch statement, the init
1184 // statement (for if and switch) is sequenced before the variable declaration,
1185 // which in turn is sequenced before the evaluation of the condition. We place
1186 // all tests inside a for loop to ensure that the checker understands the
1187 // sequencing. If it didn't, then the loop would trigger the "moved twice"
1188 // logic.
ifWhileAndSwitchSequenceInitDeclAndCondition()1189 void ifWhileAndSwitchSequenceInitDeclAndCondition() {
1190   for (int i = 0; i < 10; ++i) {
1191     A a1;
1192     if (A a2 = std::move(a1)) {
1193       std::move(a2);
1194     }
1195   }
1196   for (int i = 0; i < 10; ++i) {
1197     A a1;
1198     if (A a2 = std::move(a1); a2) {
1199       std::move(a2);
1200     }
1201   }
1202   for (int i = 0; i < 10; ++i) {
1203     A a1;
1204     if (A a2 = std::move(a1); A a3 = std::move(a2)) {
1205       std::move(a3);
1206     }
1207   }
1208   for (int i = 0; i < 10; ++i) {
1209     // init followed by condition with move, but without variable declaration.
1210     if (A a1; A(std::move(a1)).getInt() > 0) {}
1211   }
1212   for (int i = 0; i < 10; ++i) {
1213     if (A a1; A(std::move(a1)).getInt() > a1.getInt()) {}
1214     // CHECK-NOTES: [[@LINE-1]]:43: warning: 'a1' used after it was moved
1215     // CHECK-NOTES: [[@LINE-2]]:15: note: move occurred here
1216     // CHECK-NOTES: [[@LINE-3]]:43: note: the use and move are unsequenced
1217   }
1218   for (int i = 0; i < 10; ++i) {
1219     A a1;
1220     if (A a2 = std::move(a1); A(a1) > 0) {}
1221     // CHECK-NOTES: [[@LINE-1]]:33: warning: 'a1' used after it was moved
1222     // CHECK-NOTES: [[@LINE-2]]:16: note: move occurred here
1223   }
1224   while (A a = A()) {
1225     std::move(a);
1226   }
1227   for (int i = 0; i < 10; ++i) {
1228     A a1;
1229     switch (A a2 = std::move(a1); a2) {
1230       case true:
1231         std::move(a2);
1232     }
1233   }
1234   for (int i = 0; i < 10; ++i) {
1235     A a1;
1236     switch (A a2 = a1; A a3 = std::move(a2)) {
1237       case true:
1238         std::move(a3);
1239     }
1240   }
1241 }
1242 
1243 // Some statements in templates (e.g. null, break and continue statements) may
1244 // be shared between the uninstantiated and instantiated versions of the
1245 // template and therefore have multiple parents. Make sure the sequencing code
1246 // handles this correctly.
nullStatementSequencesInTemplate()1247 template <class> void nullStatementSequencesInTemplate() {
1248   int c = 0;
1249   (void)c;
1250   ;
1251   std::move(c);
1252 }
1253 template void nullStatementSequencesInTemplate<int>();
1254 
1255 namespace PR33020 {
1256 class D {
1257   ~D();
1258 };
1259 struct A {
1260   D d;
1261 };
1262 class B {
1263   A a;
1264 };
1265 template <typename T>
1266 class C : T, B {
m_fn1()1267   void m_fn1() {
1268     int a;
1269     std::move(a);
1270     C c;
1271   }
1272 };
1273 } // namespace PR33020
1274 
1275 namespace UnevalContext {
1276 struct Foo {};
noExcept()1277 void noExcept() {
1278   Foo Bar;
1279   (void) noexcept(Foo{std::move(Bar)});
1280   Foo Other{std::move(Bar)};
1281 }
sizeOf()1282 void sizeOf() {
1283   Foo Bar;
1284   (void)sizeof(Foo{std::move(Bar)});
1285   Foo Other{std::move(Bar)};
1286 }
alignOf()1287 void alignOf() {
1288   Foo Bar;
1289 #pragma clang diagnostic push
1290 #pragma clang diagnostic ignored "-Wgnu-alignof-expression"
1291   (void)alignof(Foo{std::move(Bar)});
1292 #pragma clang diagnostic pop
1293   Foo Other{std::move(Bar)};
1294 }
typeId()1295 void typeId() {
1296   Foo Bar;
1297   // error: you need to include <typeinfo> before using the 'typeid' operator
1298   // (void) typeid(Foo{std::move(Bar)}).name();
1299   Foo Other{std::move(Bar)};
1300 }
1301 } // namespace UnevalContext
1302