370 lines · cpp
1// RUN: %check_clang_tidy -std=c++11 %s cppcoreguidelines-rvalue-reference-param-not-moved %t -- \2// RUN: -config="{CheckOptions: {cppcoreguidelines-rvalue-reference-param-not-moved.AllowPartialMove: true, cppcoreguidelines-rvalue-reference-param-not-moved.IgnoreUnnamedParams: true, cppcoreguidelines-rvalue-reference-param-not-moved.IgnoreNonDeducedTemplateTypes: true}}" -- -fno-delayed-template-parsing3// RUN: %check_clang_tidy -check-suffix=,CXX14 -std=c++14 %s cppcoreguidelines-rvalue-reference-param-not-moved %t -- \4// RUN: -config="{CheckOptions: {cppcoreguidelines-rvalue-reference-param-not-moved.AllowPartialMove: true, cppcoreguidelines-rvalue-reference-param-not-moved.IgnoreUnnamedParams: true, cppcoreguidelines-rvalue-reference-param-not-moved.IgnoreNonDeducedTemplateTypes: true}}" -- -fno-delayed-template-parsing5// RUN: %check_clang_tidy -check-suffix=,NOSUBEXPR -std=c++11 %s cppcoreguidelines-rvalue-reference-param-not-moved %t -- \6// RUN: -config="{CheckOptions: {cppcoreguidelines-rvalue-reference-param-not-moved.AllowPartialMove: false, cppcoreguidelines-rvalue-reference-param-not-moved.IgnoreUnnamedParams: true, cppcoreguidelines-rvalue-reference-param-not-moved.IgnoreNonDeducedTemplateTypes: true}}" -- -fno-delayed-template-parsing7// RUN: %check_clang_tidy -check-suffix=,UNNAMED -std=c++11 %s cppcoreguidelines-rvalue-reference-param-not-moved %t -- \8// RUN: -config="{CheckOptions: {cppcoreguidelines-rvalue-reference-param-not-moved.AllowPartialMove: true, cppcoreguidelines-rvalue-reference-param-not-moved.IgnoreUnnamedParams: false, cppcoreguidelines-rvalue-reference-param-not-moved.IgnoreNonDeducedTemplateTypes: true}}" -- -fno-delayed-template-parsing9// RUN: %check_clang_tidy -check-suffix=,NONDEDUCED -std=c++11 %s cppcoreguidelines-rvalue-reference-param-not-moved %t -- \10// RUN: -config="{CheckOptions: {cppcoreguidelines-rvalue-reference-param-not-moved.AllowPartialMove: true, cppcoreguidelines-rvalue-reference-param-not-moved.IgnoreUnnamedParams: true, cppcoreguidelines-rvalue-reference-param-not-moved.IgnoreNonDeducedTemplateTypes: false}}" -- -fno-delayed-template-parsing11 12// NOLINTBEGIN13namespace std {14template <typename>15struct remove_reference;16 17template <typename _Tp> struct remove_reference { typedef _Tp type; };18template <typename _Tp> struct remove_reference<_Tp&> { typedef _Tp type; };19template <typename _Tp> struct remove_reference<_Tp&&> { typedef _Tp type; };20 21template <typename _Tp>22constexpr typename std::remove_reference<_Tp>::type &&move(_Tp &&__t) noexcept;23 24template <typename _Tp>25constexpr _Tp &&26forward(typename remove_reference<_Tp>::type &__t) noexcept;27 28}29// NOLINTEND30 31struct Obj {32 Obj();33 Obj(const Obj&);34 Obj& operator=(const Obj&);35 Obj(Obj&&);36 Obj& operator=(Obj&&);37 void member() const;38};39 40void consumes_object(Obj);41 42void never_moves_param(Obj&& o) {43 // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: rvalue reference parameter 'o' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]44 o.member();45}46 47void just_a_declaration(Obj&& o);48 49void copies_object(Obj&& o) {50 // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: rvalue reference parameter 'o' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]51 Obj copy = o;52}53 54template <typename T>55void never_moves_param_template(Obj&& o, T t) {56 // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: rvalue reference parameter 'o' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]57 o.member();58}59 60void never_moves_params(Obj&& o1, Obj&& o2) {61 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: rvalue reference parameter 'o1' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]62 // CHECK-MESSAGES: :[[@LINE-2]]:41: warning: rvalue reference parameter 'o2' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]63}64 65void never_moves_some_params(Obj&& o1, Obj&& o2) {66 // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: rvalue reference parameter 'o1' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]67 68 Obj other{std::move(o2)};69}70 71void never_moves_unnamed(Obj&&) {}72// CHECK-MESSAGES-UNNAMED: :[[@LINE-1]]:31: warning: rvalue reference parameter '' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]73 74void never_moves_mixed(Obj o1, Obj&& o2) {75 // CHECK-MESSAGES: :[[@LINE-1]]:38: warning: rvalue reference parameter 'o2' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]76}77 78void lambda_captures_parameter_as_value(Obj&& o) {79 auto f = [o]() {80 consumes_object(std::move(o));81 };82 // CHECK-MESSAGES: :[[@LINE-4]]:47: warning: rvalue reference parameter 'o' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]83}84 85void lambda_captures_parameter_as_value_nested(Obj&& o) {86 // CHECK-MESSAGES: :[[@LINE-1]]:54: warning: rvalue reference parameter 'o' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]87 auto f = [&o]() {88 auto f_nested = [o]() {89 consumes_object(std::move(o));90 };91 };92 auto f2 = [o]() {93 auto f_nested = [&o]() {94 consumes_object(std::move(o));95 };96 };97 auto f3 = [o]() {98 auto f_nested = [&o]() {99 auto f_nested_inner = [&o]() {100 consumes_object(std::move(o));101 };102 };103 };104 auto f4 = [&o]() {105 auto f_nested = [&o]() {106 auto f_nested_inner = [o]() {107 consumes_object(std::move(o));108 };109 };110 };111}112 113void misc_lambda_checks() {114 auto never_moves = [](Obj&& o1) {115 Obj other{o1};116 };117 // CHECK-MESSAGES: :[[@LINE-3]]:31: warning: rvalue reference parameter 'o1' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]118 119#if __cplusplus >= 201402L120 auto never_moves_with_auto_param = [](Obj&& o1, auto& v) {121 Obj other{o1};122 };123 // CHECK-MESSAGES-CXX14: :[[@LINE-3]]:47: warning: rvalue reference parameter 'o1' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]124#endif125}126 127template <typename T>128void forwarding_ref(T&& t) {129 t.member();130}131 132template <typename T>133void forwarding_ref_forwarded(T&& t) {134 forwarding_ref(std::forward<T>(t));135}136 137template <typename... Ts>138void type_pack(Ts&&... ts) {139 (forwarding_ref(std::forward<Ts>(ts)), ...);140}141 142void call_forwarding_functions() {143 Obj o;144 145 forwarding_ref(Obj{});146 type_pack(Obj{});147 type_pack(Obj{}, o);148 type_pack(Obj{}, Obj{});149}150 151void moves_parameter(Obj&& o) {152 Obj moved = std::move(o);153}154 155void moves_parameter_extra_parens(Obj&& o) {156 Obj moved = std::move((o));157}158 159void does_not_move_in_evaluated(Obj&& o) {160 // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: rvalue reference parameter 'o' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]161 using result_t = decltype(std::move(o));162 unsigned size = sizeof(std::move(o));163 Obj moved = o;164}165 166template <typename T1, typename T2>167struct mypair {168 T1 first;169 T2 second;170};171 172void moves_member_of_parameter(mypair<Obj, Obj>&& pair) {173 // CHECK-MESSAGES-NOSUBEXPR: :[[@LINE-1]]:51: warning: rvalue reference parameter 'pair' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]174 Obj a = std::move(pair.first);175 Obj b = std::move(pair.second);176}177 178template <typename T>179struct myoptional {180 T& operator*() &;181 T&& operator*() &&;182};183 184void moves_deref_optional(myoptional<Obj>&& opt) {185 // CHECK-MESSAGES-NOSUBEXPR: :[[@LINE-1]]:45: warning: rvalue reference parameter 'opt' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]186 Obj other = std::move(*opt);187}188 189void moves_optional_then_deref_resulting_rvalue(myoptional<Obj>&& opt) {190 Obj other = *std::move(opt);191}192 193void pass_by_lvalue_reference(Obj& o) {194 o.member();195}196 197void pass_by_value(Obj o) {198 o.member();199}200 201void pass_by_const_lvalue_reference(const Obj& o) {202 o.member();203}204 205void pass_by_const_lvalue_reference(const Obj&& o) {206 o.member();207}208 209void lambda_captures_parameter_as_reference(Obj&& o) {210 auto f = [&o]() {211 consumes_object(std::move(o));212 };213}214 215void lambda_captures_parameter_as_reference_nested(Obj&& o) {216 auto f = [&o]() {217 auto f_nested = [&o]() {218 auto f_nested2 = [&o]() {219 consumes_object(std::move(o));220 };221 };222 };223}224 225#if __cplusplus >= 201402L226void lambda_captures_parameter_generalized(Obj&& o) {227 auto f = [o = std::move(o)]() {228 consumes_object(std::move(o));229 };230}231#endif232 233void negative_lambda_checks() {234 auto never_moves_nested = [](Obj&& o1) {235 auto nested = [&]() {236 Obj other{std::move(o1)};237 };238 };239 240#if __cplusplus >= 201402L241 auto auto_lvalue_ref_param = [](auto& o1) {242 Obj other{o1};243 };244 245 auto auto_forwarding_ref_param = [](auto&& o1) {246 Obj other{o1};247 };248 249 auto does_move_auto_rvalue_ref_param = [](auto&& o1) {250 Obj other{std::forward(o1)};251 };252#endif253 254 auto does_move = [](Obj&& o1) {255 Obj other{std::move(o1)};256 };257 258 auto not_rvalue_ref = [](Obj& o1) {259 Obj other{std::move(o1)};260 };261 262 Obj local;263 auto captures = [local]() { };264}265 266struct AClass {267 void member_with_lambda_no_move(Obj&& o) {268 // CHECK-MESSAGES: :[[@LINE-1]]:41: warning: rvalue reference parameter 'o' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]269 auto captures_this = [=, this]() {270 Obj other = std::move(o);271 };272 }273 void member_with_lambda_that_moves(Obj&& o) {274 auto captures_this = [&, this]() {275 Obj other = std::move(o);276 };277 }278};279 280void useless_move(Obj&& o) {281 // FIXME - The object is not actually moved from - this should probably be282 // flagged by *some* check. Which one?283 std::move(o);284}285 286template <typename>287class TemplatedClass;288 289template <typename T>290void unresolved_lookup(TemplatedClass<T>&& o) {291 TemplatedClass<T> moved = std::move(o);292}293 294struct DefinesMove {295 DefinesMove(DefinesMove&& rhs) : o(std::move(rhs.o)) { }296 DefinesMove& operator=(DefinesMove&& rhs) {297 if (this != &rhs) {298 o = std::move(rhs.o);299 }300 return *this;301 }302 Obj o;303};304 305struct DeclaresMove {306 DeclaresMove(DeclaresMove&& rhs);307 DeclaresMove& operator=(DeclaresMove&& rhs);308};309 310struct AnotherObj {311 AnotherObj(Obj&& o) : o(std::move(o)) {}312 AnotherObj(Obj&& o, int) { o = std::move(o); }313 Obj o;314};315 316template <class T>317struct AClassTemplate {318 AClassTemplate(T&& t) {}319 // CHECK-MESSAGES-NONDEDUCED: :[[@LINE-1]]:22: warning: rvalue reference parameter 't' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]320 321 void moves(T&& t) {322 T other = std::move(t);323 }324 void never_moves(T&& t) {}325 // CHECK-MESSAGES-NONDEDUCED: :[[@LINE-1]]:24: warning: rvalue reference parameter 't' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]326};327 328void instantiate_a_class_template() {329 Obj o;330 AClassTemplate<Obj> withObj{std::move(o)};331 withObj.never_moves(std::move(o));332 333 AClassTemplate<Obj&> withObjRef(o);334 withObjRef.never_moves(o);335}336 337namespace gh68209 {338 void f1([[maybe_unused]] int&& x) {}339 340 void f2(__attribute__((unused)) int&& x) {}341 342 void f3(int&& x) {}343 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: rvalue reference parameter 'x' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]344 345 template <typename T>346 void f4([[maybe_unused]] T&& x) {}347 348 template <typename T>349 void f5(__attribute((unused)) T&& x) {}350 351 template<typename T>352 void f6(T&& x) {}353 354 void f7([[maybe_unused]] int&& x) { x += 1; }355 // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: rvalue reference parameter 'x' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]356 357 void f8(__attribute__((unused)) int&& x) { x += 1; }358 // CHECK-MESSAGES: :[[@LINE-1]]:41: warning: rvalue reference parameter 'x' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]359} // namespace gh68209360 361namespace gh69412 {362 struct S363 {364 S(const int&);365 S(int&&) = delete;366 367 void foo(int&&) = delete;368 };369} // namespace gh69412370