blob: 051bab3fed8c8d855899b445b95bf59e831f1a88 [file] [edit]
// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG \
// RUN: -std=c++14 %s 2>&1 | FileCheck %s
// RUN: %clang_analyze_cc1 -std=c++14 -analyzer-checker=core,cplusplus.Move \
// RUN: -analyzer-output=text -verify %s
#include "Inputs/system-header-simulator-cxx.h"
struct S {
int v;
int use(S &) { return v; }
};
void safe_useThenMove() {
S s{7};
auto lam = [x = s.use(s), y = std::move(s)]() mutable {
(void)x;
(void)y;
};
lam(); // no-warning: the object is used before it is moved from.
}
// CHECK-LABEL: void safe_useThenMove()
// CHECK: 1: 7
// CHECK-NEXT: 2: {[B1.1]}
// CHECK-NEXT: 3: S s{7};
// CHECK-NEXT: 4: s
// CHECK-NEXT: 5: [B1.4].use
// CHECK-NEXT: 6: s
// CHECK-NEXT: 7: [B1.5]([B1.6])
// CHECK-NEXT: 8: std::move
// CHECK-NEXT: 9: [B1.8] (ImplicitCastExpr, BuiltinFnToFnPtr, typename remove_reference<S &>::type &&(*)(struct S &))
// CHECK-NEXT: 10: s
// CHECK-NEXT: 11: [B1.9]([B1.10])
// CHECK-NEXT: 12: [B1.11] (CXXConstructExpr{{.*}}, typename remove_reference<S &>::type)
// CHECK-NEXT: 13: [x = [B1.7], y = [B1.12]]() mutable {
void unsafe_moveThenUse() {
S s{7};
auto lam = [y = std::move(s), x = s.use(s)]() mutable {
// expected-warning@-1 {{Method called on moved-from object 's'}}
// expected-note@-2 {{Method called on moved-from object 's'}}
// expected-note@-3 {{Object 's' is moved}}
(void)x;
(void)y;
};
lam();
}
// CHECK-LABEL: void unsafe_moveThenUse()
// CHECK: 1: 7
// CHECK-NEXT: 2: {[B1.1]}
// CHECK-NEXT: 3: S s{7};
// CHECK-NEXT: 4: std::move
// CHECK-NEXT: 5: [B1.4] (ImplicitCastExpr, BuiltinFnToFnPtr, typename remove_reference<S &>::type &&(*)(struct S &))
// CHECK-NEXT: 6: s
// CHECK-NEXT: 7: [B1.5]([B1.6])
// CHECK-NEXT: 8: [B1.7] (CXXConstructExpr{{.*}}, typename remove_reference<S &>::type)
// CHECK-NEXT: 9: s
// CHECK-NEXT: 10: [B1.9].use
// CHECK-NEXT: 11: s
// CHECK-NEXT: 12: [B1.10]([B1.11])
// CHECK-NEXT: 13: [y = [B1.8], x = [B1.12]]() mutable {