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