1 // RUN: %check_clang_tidy %s cppcoreguidelines-missing-std-forward %t -- -- -fno-delayed-template-parsing
2 
3 // NOLINTBEGIN
4 namespace std {
5 
6 template <typename T> struct remove_reference      { using type = T; };
7 template <typename T> struct remove_reference<T&>  { using type = T; };
8 template <typename T> struct remove_reference<T&&> { using type = T; };
9 
10 template <typename T> using remove_reference_t = typename remove_reference<T>::type;
11 
12 template <typename T> constexpr T &&forward(remove_reference_t<T> &t) noexcept;
13 template <typename T> constexpr T &&forward(remove_reference_t<T> &&t) noexcept;
14 template <typename T> constexpr remove_reference_t<T> &&move(T &&x);
15 
16 } // namespace std
17 // NOLINTEND
18 
19 struct S {
20   S();
21   S(const S&);
22   S(S&&) noexcept;
23   S& operator=(const S&);
24   S& operator=(S&&) noexcept;
25 };
26 
27 template <class... Ts>
28 void consumes_all(Ts&&...);
29 
30 namespace positive_cases {
31 
32 template <class T>
33 void does_not_forward(T&& t) {
34   // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
35   T other = t;
36 }
37 
38 template <class T>
39 void does_not_forward_invoked(T&& t) {
40   // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
41   T other = t();
42 }
43 
44 template <class T>
45 void forwards_pairwise(T&& t) {
46   // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
47   auto first = std::forward<T>(t.first);
48   auto second = std::forward<T>(t.second);
49 }
50 
51 template <class... Ts>
52 void does_not_forward_pack(Ts&&... ts) {
53   // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: forwarding reference parameter 'ts' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
54   consumes_all(ts...);
55 }
56 
57 template <class T>
58 class AClass {
59 
60   template <class U>
61   AClass(U&& u) : data(u) {}
62   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
63 
64   template <class U>
65   AClass& operator=(U&& u) { }
66   // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
67 
68   template <class U>
69   void mixed_params(T&& t, U&& u) {
70     // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
71     T other1 = std::move(t);
72     U other2 = std::move(u);
73   }
74 
75   T data;
76 };
77 
78 template <class T>
79 void does_not_forward_in_evaluated_code(T&& t) {
80   // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
81   using result_t = decltype(std::forward<T>(t));
82   unsigned len = sizeof(std::forward<T>(t));
83   T other = t;
84 }
85 
86 template <class T>
87 void lambda_value_capture(T&& t) {
88   // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
89   [=]() { T other = std::forward<T>(t); };
90 }
91 
92 template <class T>
93 void lambda_value_capture_copy(T&& t) {
94   // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
95   [&,t]() { T other = std::forward<T>(t); };
96 }
97 
98 template <typename X>
99 void use(const X &x) {}
100 
101 template <typename X, typename Y>
102 void foo(X &&x, Y &&y) {
103   // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: forwarding reference parameter 'y' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
104     use(std::forward<X>(x));
105     use(y);
106 }
107 
108 } // namespace positive_cases
109 
110 namespace negative_cases {
111 
112 template <class T>
113 void just_a_decl(T&&t);
114 
115 template <class T>
116 void does_forward(T&& t) {
117   T other = std::forward<T>(t);
118 }
119 
120 template <class... Ts>
121 void does_forward_pack(Ts&&... ts) {
122   consumes_all(std::forward<Ts>(ts)...);
123 }
124 
125 void pass_by_value(S s) {
126   S other = std::move(s);
127 }
128 
129 void lvalue_ref(S& s) {
130   S other = std::move(s);
131 }
132 
133 void rvalue_ref(S&& s) {
134   S other = std::move(s);
135 }
136 
137 template <class T>
138 void templated_rvalue_ref(std::remove_reference_t<T>&& t) {
139   T other = std::move(t);
140 }
141 
142 template <class T>
143 class AClass {
144 
145   template <class U>
146   AClass(U&& u) : data(std::forward<U>(u)) {}
147 
148   template <class U>
149   AClass& operator=(U&& u) {
150     data = std::forward<U>(u);
151   }
152 
153   void rvalue_ref(T&& t) {
154     T other = std::move(t);
155   }
156 
157   T data;
158 };
159 
160 template <class T>
161 void lambda_value_reference(T&& t) {
162   [&]() { T other = std::forward<T>(t); };
163 }
164 
165 template<typename T>
166 void lambda_value_reference_capture_list_ref_1(T&& t) {
167     [=, &t] { T other = std::forward<T>(t); };
168 }
169 
170 template<typename T>
171 void lambda_value_reference_capture_list_ref_2(T&& t) {
172     [&t] { T other = std::forward<T>(t); };
173 }
174 
175 template<typename T>
176 void lambda_value_reference_capture_list(T&& t) {
177     [t = std::forward<T>(t)] { t(); };
178 }
179 
180 template <class T>
181 void lambda_value_reference_auxiliary_var(T&& t) {
182   [&x = t]() { T other = std::forward<T>(x); };
183 }
184 
185 } // namespace negative_cases
186 
187 namespace deleted_functions {
188 
189 template <typename T>
190 void f(T &&t) = delete;
191 
192 struct S {
193     template <typename T>
194     S(T &&t) = delete;
195 
196     template <typename T>
197     void operator&(T &&t) = delete;
198 };
199 
200 } // namespace deleted_functions
201 
202 namespace unused_arguments {
203 
204 template<typename F>
205 void unused_argument1(F&&) {}
206 
207 template<typename F>
208 void unused_argument2([[maybe_unused]] F&& f) {}
209 
210 template<typename F>
211 void unused_argument3(F&& _) {}
212 
213 } // namespace unused_arguments
214