// RUN: %check_clang_tidy %s performance-noexcept-move-constructor %t -- -- -fexceptions namespace std { template struct is_nothrow_move_constructible { static constexpr bool value = __is_nothrow_constructible(T, __add_rvalue_reference(T)); }; } // namespace std struct Empty {}; struct IntWrapper { int value; }; template struct FalseT { static constexpr bool value = false; }; template struct TrueT { static constexpr bool value = true; }; struct ThrowOnAnything { ThrowOnAnything() noexcept(false); ThrowOnAnything(ThrowOnAnything&&) noexcept(false); ThrowOnAnything& operator=(ThrowOnAnything &&) noexcept(false); ~ThrowOnAnything() noexcept(false); }; class A { A(A &&); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor] // CHECK-FIXES: A(A &&) noexcept ; A &operator=(A &&); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor] // CHECK-FIXES: A &operator=(A &&) noexcept ; }; struct B { static constexpr bool kFalse = false; B(B &&) noexcept(kFalse); // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor] B &operator=(B &&) noexcept(kFalse); // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false' [performance-noexcept-move-constructor] }; template struct C { C(C &&); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor] // CHECK-FIXES: C(C &&) noexcept ; C& operator=(C &&); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor] // CHECK-FIXES: C& operator=(C &&) noexcept ; }; struct D { static constexpr bool kFalse = false; D(D &&) noexcept(kFalse) = default; // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor] D& operator=(D &&) noexcept(kFalse) = default; // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false' [performance-noexcept-move-constructor] }; template struct E { static constexpr bool kFalse = false; E(E &&) noexcept(kFalse); // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor] E& operator=(E &&) noexcept(kFalse); // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false' }; template struct F { static constexpr bool kFalse = false; F(F &&) noexcept(kFalse) = default; // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor] F& operator=(F &&) noexcept(kFalse) = default; // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false' [performance-noexcept-move-constructor] }; struct G { G(G &&) = default; // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor] // CHECK-FIXES: G(G &&) noexcept = default; G& operator=(G &&) = default; // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor] // CHECK-FIXES: G& operator=(G &&) noexcept = default; ThrowOnAnything field; }; void throwing_function() noexcept(false) {} struct H { H(H &&) noexcept(noexcept(throwing_function())); // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor] H &operator=(H &&) noexcept(noexcept(throwing_function())); // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false' [performance-noexcept-move-constructor] }; template struct I { I(I &&) noexcept(noexcept(throwing_function())); // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor] I &operator=(I &&) noexcept(noexcept(throwing_function())); // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false' [performance-noexcept-move-constructor] }; template struct TemplatedType { static void f() {} }; template <> struct TemplatedType { static void f() noexcept {} }; struct J { J(J &&) noexcept(noexcept(TemplatedType::f())); // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor] J &operator=(J &&) noexcept(noexcept(TemplatedType::f())); // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false' [performance-noexcept-move-constructor] }; struct K : public ThrowOnAnything { K(K &&) = default; // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor] // CHECK-FIXES: K(K &&) noexcept = default; K &operator=(K &&) = default; // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor] // CHECK-FIXES: K &operator=(K &&) noexcept = default; }; struct InheritFromThrowOnAnything : public ThrowOnAnything {}; struct L { L(L &&) = default; // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor] // CHECK-FIXES: L(L &&) noexcept = default; L &operator=(L &&) = default; // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor] // CHECK-FIXES: L &operator=(L &&) noexcept = default; InheritFromThrowOnAnything IFF; }; struct M : public InheritFromThrowOnAnything { M(M &&) = default; // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor] // CHECK-FIXES: M(M &&) noexcept = default; M &operator=(M &&) = default; // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor] // CHECK-FIXES: M &operator=(M &&) noexcept = default; }; struct N : public IntWrapper, ThrowOnAnything { N(N &&) = default; // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor] // CHECK-FIXES: N(N &&) noexcept = default; N &operator=(N &&) = default; // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor] // CHECK-FIXES: N &operator=(N &&) noexcept = default; }; struct O : virtual IntWrapper, ThrowOnAnything { O(O &&) = default; // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor] // CHECK-FIXES: O(O &&) noexcept = default; O &operator=(O &&) = default; // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor] // CHECK-FIXES: O &operator=(O &&) noexcept = default; }; class OK {}; void f() { OK a; a = OK(); } struct OK1 { OK1(const OK1 &); OK1(OK1 &&) noexcept; OK1 &operator=(OK1 &&) noexcept; void f(); void g() noexcept; }; struct OK2 { static constexpr bool kTrue = true; OK2(OK2 &&) noexcept(true) {} OK2 &operator=(OK2 &&) noexcept(kTrue) { return *this; } }; struct OK4 { OK4(OK4 &&) noexcept(false) {} OK4 &operator=(OK4 &&) = delete; }; struct OK3 { OK3(OK3 &&) noexcept = default; OK3 &operator=(OK3 &&) noexcept = default; }; struct OK5 { OK5(OK5 &&) noexcept(true) = default; OK5 &operator=(OK5 &&) noexcept(true) = default; }; struct OK6 { OK6(OK6 &&) = default; OK6& operator=(OK6 &&) = default; }; template struct OK7 { OK7(OK7 &&) = default; OK7& operator=(OK7 &&) = default; }; template struct OK8 { OK8(OK8 &&) noexcept = default; OK8& operator=(OK8 &&) noexcept = default; }; template struct OK9 { OK9(OK9 &&) noexcept(true) = default; OK9& operator=(OK9 &&) noexcept(true) = default; }; template struct OK10 { OK10(OK10 &&) noexcept(false) = default; OK10& operator=(OK10 &&) noexcept(false) = default; }; template struct OK11 { OK11(OK11 &&) = delete; OK11& operator=(OK11 &&) = delete; }; void noexcept_function() noexcept {} struct OK12 { OK12(OK12 &&) noexcept(noexcept(noexcept_function())); OK12 &operator=(OK12 &&) noexcept(noexcept(noexcept_function)); }; struct OK13 { OK13(OK13 &&) noexcept(noexcept(noexcept_function)) = default; OK13 &operator=(OK13 &&) noexcept(noexcept(noexcept_function)) = default; }; template struct OK14 { OK14(OK14 &&) noexcept(noexcept(TemplatedType::f())); OK14 &operator=(OK14 &&) noexcept(noexcept(TemplatedType::f())); }; struct OK15 { OK15(OK15 &&) = default; OK15 &operator=(OK15 &&) = default; int member; }; template struct OK16 { OK16(OK16 &&) = default; OK16 &operator=(OK16 &&) = default; int member; }; struct OK17 { OK17(OK17 &&) = default; OK17 &operator=(OK17 &&) = default; OK empty_field; }; template struct OK18 { OK18(OK18 &&) = default; OK18 &operator=(OK18 &&) = default; OK empty_field; }; struct OK19 : public OK { OK19(OK19 &&) = default; OK19 &operator=(OK19 &&) = default; }; struct OK20 : virtual OK { OK20(OK20 &&) = default; OK20 &operator=(OK20 &&) = default; }; template struct OK21 : public T { OK21() = default; OK21(OK21 &&) = default; OK21 &operator=(OK21 &&) = default; }; template struct OK22 : virtual T { OK22() = default; OK22(OK22 &&) = default; OK22 &operator=(OK22 &&) = default; }; template struct OK23 { OK23() = default; OK23(OK23 &&) = default; OK23 &operator=(OK23 &&) = default; T member; }; void testTemplates() { OK21 value(OK21{}); value = OK21{}; OK22 value2{OK22{}}; value2 = OK22{}; OK23 value3{OK23{}}; value3 =OK23{}; } struct OK24 : public Empty, OK1 { OK24(OK24 &&) = default; OK24 &operator=(OK24 &&) = default; }; struct OK25 : virtual Empty, OK1 { OK25(OK25 &&) = default; OK25 &operator=(OK25 &&) = default; }; struct OK26 : public Empty, IntWrapper { OK26(OK26 &&) = default; OK26 &operator=(OK26 &&) = default; }; template struct OK27 : public T { OK27(OK27 &&) = default; OK27 &operator=(OK27 &&) = default; }; template struct OK28 : virtual T { OK28(OK28 &&) = default; OK28 &operator=(OK28 &&) = default; }; template struct OK29 { OK29(OK29 &&) = default; OK29 &operator=(OK29 &&) = default; T member; }; struct OK30 { OK30(OK30 &&) noexcept(TrueT::value) = default; OK30& operator=(OK30 &&) noexcept(TrueT::value) = default; }; template struct OK31 { OK31(OK31 &&) noexcept(TrueT::value) = default; OK31& operator=(OK31 &&) noexcept(TrueT::value) = default; }; namespace gh68101 { template class Container { public: Container(Container&&) noexcept(std::is_nothrow_move_constructible::value); }; } // namespace gh68101