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 } // namespace positive_cases
99 
100 namespace negative_cases {
101 
102 template <class T>
103 void just_a_decl(T&&t);
104 
105 template <class T>
106 void does_forward(T&& t) {
107   T other = std::forward<T>(t);
108 }
109 
110 template <class... Ts>
111 void does_forward_pack(Ts&&... ts) {
112   consumes_all(std::forward<Ts>(ts)...);
113 }
114 
115 void pass_by_value(S s) {
116   S other = std::move(s);
117 }
118 
119 void lvalue_ref(S& s) {
120   S other = std::move(s);
121 }
122 
123 void rvalue_ref(S&& s) {
124   S other = std::move(s);
125 }
126 
127 template <class T>
128 void templated_rvalue_ref(std::remove_reference_t<T>&& t) {
129   T other = std::move(t);
130 }
131 
132 template <class T>
133 class AClass {
134 
135   template <class U>
136   AClass(U&& u) : data(std::forward<U>(u)) {}
137 
138   template <class U>
139   AClass& operator=(U&& u) {
140     data = std::forward<U>(u);
141   }
142 
143   void rvalue_ref(T&& t) {
144     T other = std::move(t);
145   }
146 
147   T data;
148 };
149 
150 template <class T>
151 void lambda_value_reference(T&& t) {
152   [&]() { T other = std::forward<T>(t); };
153 }
154 
155 template<typename T>
156 void lambda_value_reference_capture_list_ref_1(T&& t) {
157     [=, &t] { T other = std::forward<T>(t); };
158 }
159 
160 template<typename T>
161 void lambda_value_reference_capture_list_ref_2(T&& t) {
162     [&t] { T other = std::forward<T>(t); };
163 }
164 
165 template<typename T>
166 void lambda_value_reference_capture_list(T&& t) {
167     [t = std::forward<T>(t)] { t(); };
168 }
169 
170 template <class T>
171 void lambda_value_reference_auxiliary_var(T&& t) {
172   [&x = t]() { T other = std::forward<T>(x); };
173 }
174 
175 } // namespace negative_cases
176