15902bb95SChris Cotter // RUN: %check_clang_tidy %s cppcoreguidelines-missing-std-forward %t -- -- -fno-delayed-template-parsing
25902bb95SChris Cotter 
35902bb95SChris Cotter // NOLINTBEGIN
45902bb95SChris Cotter namespace std {
55902bb95SChris Cotter 
65902bb95SChris Cotter template <typename T> struct remove_reference      { using type = T; };
75902bb95SChris Cotter template <typename T> struct remove_reference<T&>  { using type = T; };
85902bb95SChris Cotter template <typename T> struct remove_reference<T&&> { using type = T; };
95902bb95SChris Cotter 
105902bb95SChris Cotter template <typename T> using remove_reference_t = typename remove_reference<T>::type;
115902bb95SChris Cotter 
125902bb95SChris Cotter template <typename T> constexpr T &&forward(remove_reference_t<T> &t) noexcept;
135902bb95SChris Cotter template <typename T> constexpr T &&forward(remove_reference_t<T> &&t) noexcept;
145902bb95SChris Cotter template <typename T> constexpr remove_reference_t<T> &&move(T &&x);
155902bb95SChris Cotter 
165902bb95SChris Cotter } // namespace std
175902bb95SChris Cotter // NOLINTEND
185902bb95SChris Cotter 
195902bb95SChris Cotter struct S {
205902bb95SChris Cotter   S();
215902bb95SChris Cotter   S(const S&);
225902bb95SChris Cotter   S(S&&) noexcept;
235902bb95SChris Cotter   S& operator=(const S&);
245902bb95SChris Cotter   S& operator=(S&&) noexcept;
255902bb95SChris Cotter };
265902bb95SChris Cotter 
275902bb95SChris Cotter template <class... Ts>
285902bb95SChris Cotter void consumes_all(Ts&&...);
295902bb95SChris Cotter 
305902bb95SChris Cotter namespace positive_cases {
315902bb95SChris Cotter 
325902bb95SChris Cotter template <class T>
335902bb95SChris Cotter void does_not_forward(T&& t) {
345902bb95SChris Cotter   // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
355902bb95SChris Cotter   T other = t;
365902bb95SChris Cotter }
375902bb95SChris Cotter 
385902bb95SChris Cotter template <class T>
395902bb95SChris Cotter void does_not_forward_invoked(T&& t) {
405902bb95SChris Cotter   // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
415902bb95SChris Cotter   T other = t();
425902bb95SChris Cotter }
435902bb95SChris Cotter 
445902bb95SChris Cotter template <class T>
455902bb95SChris Cotter void forwards_pairwise(T&& t) {
465902bb95SChris Cotter   // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
475902bb95SChris Cotter   auto first = std::forward<T>(t.first);
485902bb95SChris Cotter   auto second = std::forward<T>(t.second);
495902bb95SChris Cotter }
505902bb95SChris Cotter 
515902bb95SChris Cotter template <class... Ts>
525902bb95SChris Cotter void does_not_forward_pack(Ts&&... ts) {
535902bb95SChris Cotter   // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: forwarding reference parameter 'ts' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
545902bb95SChris Cotter   consumes_all(ts...);
555902bb95SChris Cotter }
565902bb95SChris Cotter 
575902bb95SChris Cotter template <class T>
585902bb95SChris Cotter class AClass {
595902bb95SChris Cotter 
605902bb95SChris Cotter   template <class U>
615902bb95SChris Cotter   AClass(U&& u) : data(u) {}
625902bb95SChris Cotter   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
635902bb95SChris Cotter 
645902bb95SChris Cotter   template <class U>
655902bb95SChris Cotter   AClass& operator=(U&& u) { }
665902bb95SChris Cotter   // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
675902bb95SChris Cotter 
685902bb95SChris Cotter   template <class U>
695902bb95SChris Cotter   void mixed_params(T&& t, U&& u) {
705902bb95SChris Cotter     // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: forwarding reference parameter 'u' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
715902bb95SChris Cotter     T other1 = std::move(t);
725902bb95SChris Cotter     U other2 = std::move(u);
735902bb95SChris Cotter   }
745902bb95SChris Cotter 
755902bb95SChris Cotter   T data;
765902bb95SChris Cotter };
775902bb95SChris Cotter 
785902bb95SChris Cotter template <class T>
795902bb95SChris Cotter void does_not_forward_in_evaluated_code(T&& t) {
805902bb95SChris Cotter   // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
815902bb95SChris Cotter   using result_t = decltype(std::forward<T>(t));
825902bb95SChris Cotter   unsigned len = sizeof(std::forward<T>(t));
835902bb95SChris Cotter   T other = t;
845902bb95SChris Cotter }
855902bb95SChris Cotter 
865902bb95SChris Cotter template <class T>
875902bb95SChris Cotter void lambda_value_capture(T&& t) {
885902bb95SChris Cotter   // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
895902bb95SChris Cotter   [=]() { T other = std::forward<T>(t); };
905902bb95SChris Cotter }
915902bb95SChris Cotter 
925902bb95SChris Cotter template <class T>
93d0848292SQizhi Hu void lambda_value_capture_copy(T&& t) {
94d0848292SQizhi Hu   // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
95d0848292SQizhi Hu   [&,t]() { T other = std::forward<T>(t); };
965902bb95SChris Cotter }
975902bb95SChris Cotter 
988b326d59SQizhi Hu template <typename X>
998b326d59SQizhi Hu void use(const X &x) {}
1008b326d59SQizhi Hu 
1018b326d59SQizhi Hu template <typename X, typename Y>
1028b326d59SQizhi Hu void foo(X &&x, Y &&y) {
1038b326d59SQizhi Hu   // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: forwarding reference parameter 'y' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
1048b326d59SQizhi Hu     use(std::forward<X>(x));
1058b326d59SQizhi Hu     use(y);
1068b326d59SQizhi Hu }
1078b326d59SQizhi Hu 
1085902bb95SChris Cotter } // namespace positive_cases
1095902bb95SChris Cotter 
1105902bb95SChris Cotter namespace negative_cases {
1115902bb95SChris Cotter 
1125902bb95SChris Cotter template <class T>
1135902bb95SChris Cotter void just_a_decl(T&&t);
1145902bb95SChris Cotter 
1155902bb95SChris Cotter template <class T>
1165902bb95SChris Cotter void does_forward(T&& t) {
1175902bb95SChris Cotter   T other = std::forward<T>(t);
1185902bb95SChris Cotter }
1195902bb95SChris Cotter 
1205902bb95SChris Cotter template <class... Ts>
1215902bb95SChris Cotter void does_forward_pack(Ts&&... ts) {
1225902bb95SChris Cotter   consumes_all(std::forward<Ts>(ts)...);
1235902bb95SChris Cotter }
1245902bb95SChris Cotter 
1255902bb95SChris Cotter void pass_by_value(S s) {
1265902bb95SChris Cotter   S other = std::move(s);
1275902bb95SChris Cotter }
1285902bb95SChris Cotter 
1295902bb95SChris Cotter void lvalue_ref(S& s) {
1305902bb95SChris Cotter   S other = std::move(s);
1315902bb95SChris Cotter }
1325902bb95SChris Cotter 
1335902bb95SChris Cotter void rvalue_ref(S&& s) {
1345902bb95SChris Cotter   S other = std::move(s);
1355902bb95SChris Cotter }
1365902bb95SChris Cotter 
1375902bb95SChris Cotter template <class T>
1385902bb95SChris Cotter void templated_rvalue_ref(std::remove_reference_t<T>&& t) {
1395902bb95SChris Cotter   T other = std::move(t);
1405902bb95SChris Cotter }
1415902bb95SChris Cotter 
1425902bb95SChris Cotter template <class T>
1435902bb95SChris Cotter class AClass {
1445902bb95SChris Cotter 
1455902bb95SChris Cotter   template <class U>
1465902bb95SChris Cotter   AClass(U&& u) : data(std::forward<U>(u)) {}
1475902bb95SChris Cotter 
1485902bb95SChris Cotter   template <class U>
1495902bb95SChris Cotter   AClass& operator=(U&& u) {
1505902bb95SChris Cotter     data = std::forward<U>(u);
1515902bb95SChris Cotter   }
1525902bb95SChris Cotter 
1535902bb95SChris Cotter   void rvalue_ref(T&& t) {
1545902bb95SChris Cotter     T other = std::move(t);
1555902bb95SChris Cotter   }
1565902bb95SChris Cotter 
1575902bb95SChris Cotter   T data;
1585902bb95SChris Cotter };
1595902bb95SChris Cotter 
160d0848292SQizhi Hu template <class T>
161d0848292SQizhi Hu void lambda_value_reference(T&& t) {
162d0848292SQizhi Hu   [&]() { T other = std::forward<T>(t); };
163d0848292SQizhi Hu }
164d0848292SQizhi Hu 
165d0848292SQizhi Hu template<typename T>
166d0848292SQizhi Hu void lambda_value_reference_capture_list_ref_1(T&& t) {
167d0848292SQizhi Hu     [=, &t] { T other = std::forward<T>(t); };
168d0848292SQizhi Hu }
169d0848292SQizhi Hu 
170d0848292SQizhi Hu template<typename T>
171d0848292SQizhi Hu void lambda_value_reference_capture_list_ref_2(T&& t) {
172d0848292SQizhi Hu     [&t] { T other = std::forward<T>(t); };
173d0848292SQizhi Hu }
174d0848292SQizhi Hu 
175d0848292SQizhi Hu template<typename T>
176d0848292SQizhi Hu void lambda_value_reference_capture_list(T&& t) {
177d0848292SQizhi Hu     [t = std::forward<T>(t)] { t(); };
178d0848292SQizhi Hu }
179d0848292SQizhi Hu 
180d0848292SQizhi Hu template <class T>
181d0848292SQizhi Hu void lambda_value_reference_auxiliary_var(T&& t) {
182d0848292SQizhi Hu   [&x = t]() { T other = std::forward<T>(x); };
183d0848292SQizhi Hu }
184d0848292SQizhi Hu 
1855902bb95SChris Cotter } // namespace negative_cases
1867b11e2ecSAMS21 
1877b11e2ecSAMS21 namespace deleted_functions {
1887b11e2ecSAMS21 
1897b11e2ecSAMS21 template <typename T>
190*2f321facSJulian Schmidt void f(T &&t) = delete;
1917b11e2ecSAMS21 
1927b11e2ecSAMS21 struct S {
1937b11e2ecSAMS21     template <typename T>
194*2f321facSJulian Schmidt     S(T &&t) = delete;
1957b11e2ecSAMS21 
1967b11e2ecSAMS21     template <typename T>
197*2f321facSJulian Schmidt     void operator&(T &&t) = delete;
1987b11e2ecSAMS21 };
1997b11e2ecSAMS21 
2007b11e2ecSAMS21 } // namespace deleted_functions
20116b3e43aSDanny Mösch 
20216b3e43aSDanny Mösch namespace unused_arguments {
20316b3e43aSDanny Mösch 
20416b3e43aSDanny Mösch template<typename F>
20516b3e43aSDanny Mösch void unused_argument1(F&&) {}
20616b3e43aSDanny Mösch 
20716b3e43aSDanny Mösch template<typename F>
20816b3e43aSDanny Mösch void unused_argument2([[maybe_unused]] F&& f) {}
20916b3e43aSDanny Mösch 
21016b3e43aSDanny Mösch template<typename F>
21116b3e43aSDanny Mösch void unused_argument3(F&& _) {}
21216b3e43aSDanny Mösch 
21316b3e43aSDanny Mösch } // namespace unused_arguments
214