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