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