Lines Matching full:a
142 class A {
144 A();
145 A(const A &);
146 A(A &&);
148 A &operator=(const A &);
149 A &operator=(A &&);
174 A a;
175 a.foo();
176 A other_a = std::move(a);
177 a.foo();
178 // CHECK-NOTES: [[@LINE-1]]:3: warning: 'a' used after it was moved
182 // Don't flag a move-to-self.
184 A a;
185 a = std::move(a);
186 a.foo();
189 // A warning should only be emitted for one use-after-move.
191 A a;
192 a.foo();
193 A other_a = std::move(a);
194 a.foo();
195 // CHECK-NOTES: [[@LINE-1]]:3: warning: 'a' used after it was moved
197 a.foo();
201 // Move-after-move also counts as a use.
203 A a;
204 std::move(a);
205 std::move(a);
206 // CHECK-NOTES: [[@LINE-1]]:15: warning: 'a' used after it was moved
212 A a;
214 std::move(a);
215 // CHECK-NOTES: [[@LINE-1]]:17: warning: 'a' used after it was moved
217 // CHECK-NOTES: [[@LINE-3]]:17: note: the use happens in a later loop
222 // Checks also works on function parameters that have a use-after move.
223 void parameters(A a) {
224 std::move(a);
225 a.foo();
226 // CHECK-NOTES: [[@LINE-1]]:3: warning: 'a' used after it was moved
232 // be null after a std::move. So the check only flags accesses that would
235 std::unique_ptr<A> ptr;
244 std::unique_ptr<A> ptr;
251 std::unique_ptr<A> ptr;
258 std::shared_ptr<A> ptr;
267 std::shared_ptr<A> ptr;
274 std::optional<A> opt;
276 A val = *opt;
283 // member functions may be called on it after a move.
284 std::weak_ptr<A> ptr;
289 // wrapped in a typedef.
291 typedef std::unique_ptr<A> PtrToA;
297 typedef std::shared_ptr<A> PtrToA;
302 // And we don't get confused if the template argument is a little more
306 typedef A AnotherNameForA;
314 std::unique_ptr<A> ptr;
315 std::unique_ptr<A>& ref_to_ptr = ptr;
320 std::unique_ptr<A> ptr;
321 std::unique_ptr<A>&& rvalue_ref_to_ptr = std::move(ptr);
341 A a;
342 std::move(a);
343 a.foo();
344 // CHECK-NOTES: [[@LINE-1]]:5: warning: 'a' used after it was moved
349 // We see the std::move() if it's inside a declaration.
351 A a;
352 A another_a(std::move(a));
353 a.foo();
354 // CHECK-NOTES: [[@LINE-1]]:3: warning: 'a' used after it was moved
359 // are a special case because they cause ASTContext::getParents() to return
366 A a;
368 A a;
369 S s{std::move(a)};
370 a.foo();
371 // CHECK-NOTES: [[@LINE-1]]:3: warning: 'a' used after it was moved
376 // Use-after-moves inside a lambda should be detected.
378 A a;
379 auto lambda = [a] {
380 std::move(a);
381 a.foo();
382 // CHECK-NOTES: [[@LINE-1]]:7: warning: 'a' used after it was moved
389 A a;
390 std::move(a);
391 a.foo();
392 // CHECK-NOTES: [[@LINE-1]]:7: warning: 'a' used after it was moved
398 // - the 'a' inside the lambda is a copy, and
401 A a;
402 auto lambda = [a] {
403 std::move(a);
405 a.foo();
407 // Don't warn if 'a' is a copy inside a synchronous lambda
409 A a;
410 A copied{[a] mutable { return std::move(a); }()};
411 a.foo();
413 // False negative (should warn if 'a' is a ref inside a synchronous lambda)
415 A a;
416 A moved{[&a] mutable { return std::move(a); }()};
417 a.foo();
419 // Warn if the use consists of a capture that happens after a move.
421 A a;
422 std::move(a);
423 auto lambda = [a]() { a.foo(); };
424 // CHECK-NOTES: [[@LINE-1]]:20: warning: 'a' used after it was moved
429 A a;
430 std::move(a);
431 auto lambda = [=]() { a.foo(); };
432 // CHECK-NOTES: [[@LINE-1]]:20: warning: 'a' used after it was moved
437 A a;
438 std::move(a);
439 auto lambda = [&a]() { a.foo(); };
440 // CHECK-NOTES: [[@LINE-1]]:21: warning: 'a' used after it was moved
444 A a;
445 std::move(a);
446 auto lambda = [&]() { a.foo(); };
447 // CHECK-NOTES: [[@LINE-1]]:20: warning: 'a' used after it was moved
452 A a;
453 auto lambda = [a]() { a.foo(); };
454 std::move(a);
458 A a;
459 auto lambda = [=]() { a.foo(); };
460 std::move(a);
464 A a;
465 auto lambda = [&a]() { a.foo(); };
466 std::move(a);
469 A a;
470 auto lambda = [&]() { a.foo(); };
471 std::move(a);
474 A a;
475 auto lambda = [a = std::move(a)] { a.foo(); };
476 a.foo();
477 // CHECK-NOTES: [[@LINE-1]]:5: warning: 'a' used after it was moved
483 // is not a dependent type.
487 A a;
488 std::move(a);
489 a.foo();
490 // CHECK-NOTES: [[@LINE-1]]:3: warning: 'a' used after it was moved
494 // And if the moved type is a dependent type, the use-after-move is detected if
504 template void movedTypeIsDependentType<A>();
507 // to a conversion operator.
510 operator A() && { return A(); }
512 void takeA(A a);
521 // Using decltype on an expression is not a use.
523 A a;
524 std::move(a);
525 decltype(a) other_a;
532 void foo(A a);
535 void functionTemplate(A a);
538 // A pattern like this occurs in the EXPECT_EQ and ASSERT_EQ macros in
540 A a;
541 ClassTemplate<sizeof(A(std::move(a)))>().foo(std::move(a));
544 A a;
545 functionTemplate<sizeof(A(std::move(a)))>(std::move(a));
550 A global_a;
558 A a;
559 static A static_a;
562 std::move(a);
563 a.foo();
570 // Ignore moves that happen in a try_emplace.
573 std::map<int, A> amap;
574 A a;
575 amap.try_emplace(1, std::move(a));
576 a.foo();
579 std::unordered_map<int, A> amap;
580 A a;
581 amap.try_emplace(1, std::move(a));
582 a.foo();
590 // Warn about use-after-moves if they happen in a later loop iteration than
593 A a;
595 a.foo();
596 // CHECK-NOTES: [[@LINE-1]]:7: warning: 'a' used after it was moved
598 // CHECK-NOTES: [[@LINE-3]]:7: note: the use happens in a later loop
599 std::move(a);
604 A a;
607 a.foo();
608 // CHECK-NOTES: [[@LINE-1]]:9: warning: 'a' used after it was moved
610 // CHECK-NOTES: [[@LINE-3]]:9: note: the use happens in a later loop
612 std::move(a);
616 // 'a' is important.
619 A a;
620 a.foo();
621 std::move(a);
625 // the same declaration as 'a'. This case is interesting because it tests that
630 A a, other;
631 a.foo();
632 std::move(a);
637 A a;
639 a.foo();
640 if (a.getInt() > 0) {
641 std::move(a);
649 // Don't warn if the use is in a different branch from the move.
651 A a;
653 std::move(a);
655 a.foo();
658 // Same thing, but with a ternary operator.
660 A a;
661 i > 0 ? (void)std::move(a) : a.foo();
663 // A variation on the theme above.
665 A a;
666 a.getInt() > 0 ? a.getInt() : A(std::move(a)).getInt();
668 // Same thing, but with a switch statement.
670 A a;
673 std::move(a);
676 a.foo();
680 // However, if there's a fallthrough, we do warn.
682 A a;
685 std::move(a);
687 a.foo();
688 // CHECK-NOTES: [[@LINE-1]]:7: warning: 'a' used after it was moved
695 // False positive: A use-after-move is flagged even though the "if (b)" and
698 A a;
700 std::move(a);
703 a.foo();
704 // CHECK-NOTES: [[@LINE-1]]:5: warning: 'a' used after it was moved
720 bool operationOnA(A);
722 A a;
724 // a use-after-move because the second iteration of the loop would be using a
728 ASSERT(operationOnA(std::move(a)));
736 void swap(T &a, T &b) {
737 T tmp = std::move(a);
738 a = std::move(b);
742 // Don't report a use-after-move if the variable was assigned to in the
745 A a;
746 std::move(a);
747 a = A();
748 a.foo();
752 // prevent a use-after-move).
754 A a;
756 std::move(a);
757 a = A();
760 a.foo();
764 A a;
766 std::move(a);
769 a = A();
770 a.foo();
773 // The built-in assignment operator should also be recognized as a
780 // A std::move() after the assignment makes the variable invalid again.
782 A a;
783 std::move(a);
784 a = A();
785 std::move(a);
786 a.foo();
787 // CHECK-NOTES: [[@LINE-1]]:5: warning: 'a' used after it was moved
790 // Report a use-after-move if we can't be sure that the variable was assigned
793 A a;
794 std::move(a);
796 a = A();
799 a.foo();
800 // CHECK-NOTES: [[@LINE-1]]:7: warning: 'a' used after it was moved
806 // Passing the object to a function through a non-const pointer or reference
807 // counts as a re-initialization.
808 void passByNonConstPointer(A *);
809 void passByNonConstReference(A &);
812 A a;
813 std::move(a);
814 passByNonConstPointer(&a);
815 a.foo();
818 A a;
819 std::move(a);
820 passByNonConstReference(a);
821 a.foo();
825 // Passing the object through a const pointer or reference counts as a use --
827 void passByConstPointer(const A *);
828 void passByConstReference(const A &);
831 // Declaring 'a' as const so that no ImplicitCastExpr is inserted into the
832 // AST -- we wouldn't want the check to rely solely on that to detect a
834 const A a;
835 std::move(a);
836 passByConstPointer(&a);
837 // CHECK-NOTES: [[@LINE-1]]:25: warning: 'a' used after it was moved
840 const A a;
841 std::move(a);
842 passByConstReference(a);
843 // CHECK-NOTES: [[@LINE-1]]:24: warning: 'a' used after it was moved
847 // Clearing a standard container using clear() is treated as a
952 // An intervening clear() on a different container does not reinitialize.
963 // Clearing a standard container using assign() is treated as a
1007 // An intervening assign() on a different container does not reinitialize.
1018 // Resetting the standard smart owning types using reset() is treated as a
1023 std::unique_ptr<A> ptr;
1025 ptr.reset(new A);
1029 std::shared_ptr<A> ptr;
1031 ptr.reset(new A);
1035 std::optional<A> opt;
1038 std::optional<A> opt2 = opt;
1042 std::any a;
1043 std::move(a);
1044 a.reset();
1045 std::any a2 = a;
1065 // Calling clear() on a different object to the one that was moved is not
1066 // considered a reinitialization.
1080 void passByRvalueReference(int i, A &&a);
1081 void passByValue(int i, A a);
1082 void passByValue(A a, int i);
1083 A g(A, A &&);
1084 int intFromA(A &&);
1088 // passByRvalueReference(). At this point, a.getInt() is guaranteed to have
1091 A a;
1092 passByRvalueReference(a.getInt(), std::move(a));
1095 // called to create a temporary, and this happens before the call to
1097 // defined, the move may happen before the call to a.getInt().
1099 // Check that we warn about a potential use-after move for both orderings of
1100 // a.getInt() and std::move(a), independent of the order in which the
1103 A a;
1104 passByValue(a.getInt(), std::move(a));
1105 // CHECK-NOTES: [[@LINE-1]]:17: warning: 'a' used after it was moved
1110 A a;
1111 passByValue(std::move(a), a.getInt());
1112 // CHECK-NOTES: [[@LINE-1]]:31: warning: 'a' used after it was moved
1118 A a;
1119 g(g(a, std::move(a)), g(a, std::move(a)));
1120 // CHECK-NOTES: [[@LINE-1]]:9: warning: 'a' used after it was moved
1123 // CHECK-NOTES: [[@LINE-4]]:29: warning: 'a' used after it was moved
1128 // operator=(). a.getInt(), by necessity, is evaluated before that call.
1130 A a;
1131 A vec[1];
1132 vec[a.getInt()] = std::move(a);
1137 A a;
1139 v[a.getInt()] = intFromA(std::move(a));
1140 // CHECK-NOTES: [[@LINE-1]]:7: warning: 'a' used after it was moved
1145 A a;
1147 v[intFromA(std::move(a))] = intFromInt(a.i);
1148 // CHECK-NOTES: [[@LINE-1]]:44: warning: 'a' used after it was moved
1157 A MutateA(A a);
1158 void passByValue(A a1, A a2);
1163 A a;
1164 passByValue(std::move(a), (a = A()));
1165 a.foo();
1166 // CHECK-NOTES: [[@LINE-1]]:5: warning: 'a' used after it was moved
1170 A a;
1171 passByValue((a = A()), std::move(a));
1172 a.foo();
1173 // CHECK-NOTES: [[@LINE-1]]:5: warning: 'a' used after it was moved
1176 // Common usage pattern: Move the object to a function that mutates it in some
1179 A a;
1180 a = MutateA(std::move(a));
1181 a.foo();
1193 A a;
1194 std::move(a);
1195 passByValue(a.getInt(), (a = A()));
1196 // CHECK-NOTES: [[@LINE-1]]:17: warning: 'a' used after it was moved
1200 A a;
1201 std::move(a);
1202 passByValue((a = A()), a.getInt());
1203 // CHECK-NOTES: [[@LINE-1]]:28: warning: 'a' used after it was moved
1211 A a;
1212 A(std::move(a))
1213 , (a = A());
1214 a.foo();
1217 A a;
1218 (a = A()), A(std::move(a));
1219 a.foo();
1220 // CHECK-NOTES: [[@LINE-1]]:5: warning: 'a' used after it was moved
1229 A a;
1233 A a;
1239 S3(int, A) {}
1240 S3(A, int) {}
1246 A a;
1247 S1 s1{a.getInt(), std::move(a)};
1250 A a;
1251 S1 s1{.i = a.getInt(), .a = std::move(a)};
1254 A a;
1255 S2 s2{std::move(a), a.getInt()};
1256 // CHECK-NOTES: [[@LINE-1]]:25: warning: 'a' used after it was moved
1260 A a;
1261 S2 s2{.a = std::move(a), .i = a.getInt()};
1262 // CHECK-NOTES: [[@LINE-1]]:35: warning: 'a' used after it was moved
1266 // Check the case where the constructed type has a constructor and the
1267 // initializer list therefore manifests as a `CXXConstructExpr` instead of
1269 A a;
1270 S3 s3{a.getInt(), std::move(a)};
1273 A a;
1274 S3 s3{std::move(a), a.getInt()};
1275 // CHECK-NOTES: [[@LINE-1]]:25: warning: 'a' used after it was moved
1282 // A declaration statement containing multiple declarations sequences the
1286 A a;
1287 A a1 = a, a2 = std::move(a);
1290 A a;
1291 A a1 = std::move(a), a2 = a;
1292 // CHECK-NOTES: [[@LINE-1]]:31: warning: 'a' used after it was moved
1300 A a;
1301 if (a.getInt() > 0 && A(std::move(a)).getInt() > 0) {
1302 A().foo();
1305 // A variation: Negate the result of the && (which pushes the && further down
1308 A a;
1309 if (!(a.getInt() > 0 && A(std::move(a)).getInt() > 0)) {
1310 A().foo();
1314 A a;
1315 if (A(std::move(a)).getInt() > 0 && a.getInt() > 0) {
1316 // CHECK-NOTES: [[@LINE-1]]:41: warning: 'a' used after it was moved
1318 A().foo();
1322 A a;
1323 if (a.getInt() > 0 || A(std::move(a)).getInt() > 0) {
1324 A().foo();
1328 A a;
1329 if (A(std::move(a)).getInt() > 0 || a.getInt() > 0) {
1330 // CHECK-NOTES: [[@LINE-1]]:41: warning: 'a' used after it was moved
1332 A().foo();
1337 // A range-based for sequences the loop variable declaration before the body.
1339 A v[2] = {A(), A()};
1340 for (A &a : v) {
1341 std::move(a);
1345 // If a variable is declared in an if, while or switch statement, the init
1348 // all tests inside a for loop to ensure that the checker understands the
1353 A a1;
1354 if (A a2 = std::move(a1)) {
1359 A a1;
1360 if (A a2 = std::move(a1); a2) {
1365 A a1;
1366 if (A a2 = std::move(a1); A a3 = std::move(a2)) {
1372 if (A a1; A(std::move(a1)).getInt() > 0) {}
1375 if (A a1; A(std::move(a1)).getInt() > a1.getInt()) {}
1381 A a1;
1382 if (A a2 = std::move(a1); A(a1) > 0) {}
1386 while (A a = A()) {
1387 std::move(a);
1390 A a1;
1391 switch (A a2 = std::move(a1); a2) {
1397 A a1;
1398 switch (A a2 = a1; A a3 = std::move(a2)) {
1405 // In a function call, the expression that determines the callee is sequenced
1408 int consumeA(std::unique_ptr<A> a);
1409 int consumeA(A &&a);
1413 std::unique_ptr<A> a;
1414 a->bar(consumeA(std::move(a)));
1415 // CHECK-NOTES-CXX11: [[@LINE-1]]:5: warning: 'a' used after it was moved
1420 std::unique_ptr<A> a;
1421 std::unique_ptr<A> getArg(std::unique_ptr<A> a);
1422 getArg(std::move(a))->bar(a->getInt());
1423 // CHECK-NOTES: [[@LINE-1]]:31: warning: 'a' used after it was moved
1428 A a;
1429 // Nominally, the callee `a.bar` is evaluated before the argument
1430 // `consumeA(std::move(a))`, but in effect `a` is only accessed after the
1431 // call to `A::bar()` happens, i.e. after the argument has been evaluted.
1432 a.bar(consumeA(std::move(a)));
1433 // CHECK-NOTES: [[@LINE-1]]:5: warning: 'a' used after it was moved
1455 struct A {
1459 A a;
1464 int a;
1465 std::move(a);
1502 : a{val.empty()}, // fine
1510 bool a;
1518 : a{val.empty()}, // fine
1541 bool a;
1551 : a{val.empty()}, // fine
1558 bool a;
1600 // This was a move, but it doesn't warn below, because it can't know if