1 | // RUN: %check_clang_tidy %s performance-move-const-arg %t \ |
2 | // RUN: -config='{CheckOptions: \ |
3 | // RUN: {performance-move-const-arg.CheckTriviallyCopyableMove: false}}' |
4 | |
5 | namespace std { |
6 | |
7 | template <typename> struct remove_reference; |
8 | template <typename _Tp> struct remove_reference { typedef _Tp type; }; |
9 | template <typename _Tp> struct remove_reference<_Tp &> { typedef _Tp type; }; |
10 | template <typename _Tp> struct remove_reference<_Tp &&> { typedef _Tp type; }; |
11 | |
12 | template <typename _Tp> |
13 | constexpr typename std::remove_reference<_Tp>::type &&move(_Tp &&__t) { |
14 | return static_cast<typename std::remove_reference<_Tp>::type &&>(__t); |
15 | } |
16 | |
17 | template <typename _Tp> |
18 | constexpr _Tp && |
19 | forward(typename remove_reference<_Tp>::type &__t) noexcept { |
20 | return static_cast<_Tp &&>(__t); |
21 | } |
22 | |
23 | } // namespace std |
24 | |
25 | class NoMoveSemantics { |
26 | public: |
27 | NoMoveSemantics(); |
28 | NoMoveSemantics(const NoMoveSemantics &); |
29 | |
30 | NoMoveSemantics &operator=(const NoMoveSemantics &); |
31 | }; |
32 | |
33 | void callByConstRef(const NoMoveSemantics &); |
34 | void callByConstRef(int i, const NoMoveSemantics &); |
35 | |
36 | void moveToConstReferencePositives() { |
37 | NoMoveSemantics obj; |
38 | |
39 | // Basic case. It is here just to have a single "detected and fixed" case. |
40 | callByConstRef(std::move(obj)); |
41 | // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: passing result of std::move() as a const reference argument; no move will actually happen [performance-move-const-arg] |
42 | // CHECK-FIXES: callByConstRef(obj); |
43 | } |
44 | |
45 | struct TriviallyCopyable { |
46 | int i; |
47 | }; |
48 | |
49 | void f(TriviallyCopyable) {} |
50 | |
51 | void g() { |
52 | TriviallyCopyable obj; |
53 | f(std::move(obj)); |
54 | } |
55 | |
56 | class MoveSemantics { |
57 | public: |
58 | MoveSemantics(); |
59 | MoveSemantics(MoveSemantics &&); |
60 | |
61 | MoveSemantics &operator=(MoveSemantics &&); |
62 | }; |
63 | |
64 | void fmovable(MoveSemantics); |
65 | |
66 | void lambda1() { |
67 | auto f = [](MoveSemantics m) { |
68 | fmovable(std::move(m)); |
69 | }; |
70 | f(MoveSemantics()); |
71 | } |
72 | |
73 | template<class T> struct function {}; |
74 | |
75 | template<typename Result, typename... Args> |
76 | class function<Result(Args...)> { |
77 | public: |
78 | function() = default; |
79 | void operator()(Args... args) const { |
80 | fmovable(std::forward<Args>(args)...); |
81 | } |
82 | }; |
83 | |
84 | void functionInvocation() { |
85 | function<void(MoveSemantics)> callback; |
86 | MoveSemantics m; |
87 | callback(std::move(m)); |
88 | } |
89 | |
90 | void lambda2() { |
91 | function<void(MoveSemantics)> callback; |
92 | |
93 | auto f = [callback = std::move(callback)](MoveSemantics m) mutable { |
94 | callback(std::move(m)); |
95 | }; |
96 | f(MoveSemantics()); |
97 | } |
98 | |