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