417 lines · cpp
1// RUN: %check_clang_tidy %s performance-noexcept-move-constructor %t -- -- -fexceptions2// RUN: %check_clang_tidy -std=c++17 -check-suffixes=,ERR %s performance-noexcept-move-constructor %t \3// RUN: -- --fix-errors -- -fexceptions -DENABLE_ERROR4 5namespace std6{7 template <typename T>8 struct is_nothrow_move_constructible9 {10 static constexpr bool value = __is_nothrow_constructible(T, __add_rvalue_reference(T));11 };12} // namespace std13 14struct Empty15{};16 17struct IntWrapper {18 int value;19};20 21template <typename T>22struct FalseT {23 static constexpr bool value = false;24};25 26template <typename T>27struct TrueT {28 static constexpr bool value = true;29};30 31struct ThrowOnAnything {32 ThrowOnAnything() noexcept(false);33 ThrowOnAnything(ThrowOnAnything&&) noexcept(false);34 ThrowOnAnything& operator=(ThrowOnAnything &&) noexcept(false);35 ~ThrowOnAnything() noexcept(false);36};37 38class A {39 A(A &&);40 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor]41 // CHECK-FIXES: A(A &&) noexcept ;42 A &operator=(A &&);43 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor]44 // CHECK-FIXES: A &operator=(A &&) noexcept ;45};46 47struct B {48 static constexpr bool kFalse = false;49 B(B &&) noexcept(kFalse);50 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor]51 B &operator=(B &&) noexcept(kFalse);52 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false' [performance-noexcept-move-constructor]53};54 55template <typename>56struct C {57 C(C &&);58 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor]59 // CHECK-FIXES: C(C &&) noexcept ;60 C& operator=(C &&);61 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor]62 // CHECK-FIXES: C& operator=(C &&) noexcept ;63};64 65struct D {66 static constexpr bool kFalse = false;67 D(D &&) noexcept(kFalse) = default;68 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor]69 D& operator=(D &&) noexcept(kFalse) = default;70 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false' [performance-noexcept-move-constructor]71};72 73template <typename>74struct E {75 static constexpr bool kFalse = false;76 E(E &&) noexcept(kFalse);77 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor]78 E& operator=(E &&) noexcept(kFalse);79 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false'80};81 82template <typename>83struct F {84 static constexpr bool kFalse = false;85 F(F &&) noexcept(kFalse) = default;86 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor]87 F& operator=(F &&) noexcept(kFalse) = default;88 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false' [performance-noexcept-move-constructor]89};90 91struct G {92 G(G &&) = default;93 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor]94 // CHECK-FIXES: G(G &&) noexcept = default;95 G& operator=(G &&) = default;96 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor]97 // CHECK-FIXES: G& operator=(G &&) noexcept = default;98 99 ThrowOnAnything field;100};101 102void throwing_function() noexcept(false) {}103 104struct H {105 H(H &&) noexcept(noexcept(throwing_function()));106 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor]107 H &operator=(H &&) noexcept(noexcept(throwing_function()));108 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false' [performance-noexcept-move-constructor]109};110 111template <typename>112struct I {113 I(I &&) noexcept(noexcept(throwing_function()));114 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor]115 I &operator=(I &&) noexcept(noexcept(throwing_function()));116 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false' [performance-noexcept-move-constructor]117};118 119template <typename T> struct TemplatedType {120 static void f() {}121};122 123template <> struct TemplatedType<int> {124 static void f() noexcept {}125};126 127struct J {128 J(J &&) noexcept(noexcept(TemplatedType<double>::f()));129 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor]130 J &operator=(J &&) noexcept(noexcept(TemplatedType<double>::f()));131 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false' [performance-noexcept-move-constructor]132};133 134struct K : public ThrowOnAnything {135 K(K &&) = default;136 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor]137 // CHECK-FIXES: K(K &&) noexcept = default;138 K &operator=(K &&) = default;139 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor]140 // CHECK-FIXES: K &operator=(K &&) noexcept = default;141};142 143struct InheritFromThrowOnAnything : public ThrowOnAnything144{};145 146struct L {147 L(L &&) = default;148 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor]149 // CHECK-FIXES: L(L &&) noexcept = default;150 L &operator=(L &&) = default;151 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor]152 // CHECK-FIXES: L &operator=(L &&) noexcept = default;153 154 InheritFromThrowOnAnything IFF;155};156 157struct M : public InheritFromThrowOnAnything {158 M(M &&) = default;159 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor]160 // CHECK-FIXES: M(M &&) noexcept = default;161 M &operator=(M &&) = default;162 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor]163 // CHECK-FIXES: M &operator=(M &&) noexcept = default;164};165 166struct N : public IntWrapper, ThrowOnAnything {167 N(N &&) = default;168 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor]169 // CHECK-FIXES: N(N &&) noexcept = default;170 N &operator=(N &&) = default;171 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor]172 // CHECK-FIXES: N &operator=(N &&) noexcept = default;173};174 175struct O : virtual IntWrapper, ThrowOnAnything {176 O(O &&) = default;177 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor]178 // CHECK-FIXES: O(O &&) noexcept = default;179 O &operator=(O &&) = default;180 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor]181 // CHECK-FIXES: O &operator=(O &&) noexcept = default;182};183 184class OK {};185 186void f() {187 OK a;188 a = OK();189}190 191struct OK1 {192 OK1(const OK1 &);193 OK1(OK1 &&) noexcept;194 OK1 &operator=(OK1 &&) noexcept;195 void f();196 void g() noexcept;197};198 199struct OK2 {200 static constexpr bool kTrue = true;201 202 OK2(OK2 &&) noexcept(true) {}203 OK2 &operator=(OK2 &&) noexcept(kTrue) { return *this; }204};205 206struct OK4 {207 OK4(OK4 &&) noexcept(false) {}208 OK4 &operator=(OK4 &&) = delete;209};210 211struct OK3 {212 OK3(OK3 &&) noexcept = default;213 OK3 &operator=(OK3 &&) noexcept = default;214};215 216struct OK5 {217 OK5(OK5 &&) noexcept(true) = default;218 OK5 &operator=(OK5 &&) noexcept(true) = default;219};220 221struct OK6 {222 OK6(OK6 &&) = default;223 OK6& operator=(OK6 &&) = default;224};225 226template <typename>227struct OK7 {228 OK7(OK7 &&) = default;229 OK7& operator=(OK7 &&) = default;230};231 232template <typename>233struct OK8 {234 OK8(OK8 &&) noexcept = default;235 OK8& operator=(OK8 &&) noexcept = default;236};237 238template <typename>239struct OK9 {240 OK9(OK9 &&) noexcept(true) = default;241 OK9& operator=(OK9 &&) noexcept(true) = default;242};243 244template <typename>245struct OK10 {246 OK10(OK10 &&) noexcept(false) = default;247 OK10& operator=(OK10 &&) noexcept(false) = default;248};249 250template <typename>251struct OK11 {252 OK11(OK11 &&) = delete;253 OK11& operator=(OK11 &&) = delete;254};255 256void noexcept_function() noexcept {}257 258struct OK12 {259 OK12(OK12 &&) noexcept(noexcept(noexcept_function()));260 OK12 &operator=(OK12 &&) noexcept(noexcept(noexcept_function));261};262 263struct OK13 {264 OK13(OK13 &&) noexcept(noexcept(noexcept_function)) = default;265 OK13 &operator=(OK13 &&) noexcept(noexcept(noexcept_function)) = default;266};267 268template <typename>269struct OK14 {270 OK14(OK14 &&) noexcept(noexcept(TemplatedType<int>::f()));271 OK14 &operator=(OK14 &&) noexcept(noexcept(TemplatedType<int>::f()));272};273 274struct OK15 {275 OK15(OK15 &&) = default;276 OK15 &operator=(OK15 &&) = default;277 278 int member;279};280 281template <typename>282struct OK16 {283 OK16(OK16 &&) = default;284 OK16 &operator=(OK16 &&) = default;285 286 int member;287};288 289struct OK17 {290 OK17(OK17 &&) = default;291 OK17 &operator=(OK17 &&) = default;292 293 OK empty_field;294};295 296template <typename>297struct OK18 {298 OK18(OK18 &&) = default;299 OK18 &operator=(OK18 &&) = default;300 301 OK empty_field;302};303 304struct OK19 : public OK {305 OK19(OK19 &&) = default;306 OK19 &operator=(OK19 &&) = default;307};308 309struct OK20 : virtual OK {310 OK20(OK20 &&) = default;311 OK20 &operator=(OK20 &&) = default;312};313 314template <typename T>315struct OK21 : public T {316 OK21() = default;317 OK21(OK21 &&) = default;318 OK21 &operator=(OK21 &&) = default;319};320 321template <typename T>322struct OK22 : virtual T {323 OK22() = default;324 OK22(OK22 &&) = default;325 OK22 &operator=(OK22 &&) = default;326};327 328template <typename T>329struct OK23 {330 OK23() = default;331 OK23(OK23 &&) = default;332 OK23 &operator=(OK23 &&) = default;333 334 T member;335};336 337void testTemplates() {338 OK21<Empty> value(OK21<Empty>{});339 value = OK21<Empty>{};340 341 OK22<Empty> value2{OK22<Empty>{}};342 value2 = OK22<Empty>{};343 344 OK23<Empty> value3{OK23<Empty>{}};345 value3 =OK23<Empty>{};346}347 348struct OK24 : public Empty, OK1 {349 OK24(OK24 &&) = default;350 OK24 &operator=(OK24 &&) = default;351};352 353struct OK25 : virtual Empty, OK1 {354 OK25(OK25 &&) = default;355 OK25 &operator=(OK25 &&) = default;356};357 358struct OK26 : public Empty, IntWrapper {359 OK26(OK26 &&) = default;360 OK26 &operator=(OK26 &&) = default;361};362 363template <typename T>364struct OK27 : public T {365 OK27(OK27 &&) = default;366 OK27 &operator=(OK27 &&) = default;367};368 369template <typename T>370struct OK28 : virtual T {371 OK28(OK28 &&) = default;372 OK28 &operator=(OK28 &&) = default;373};374 375template <typename T>376struct OK29 {377 OK29(OK29 &&) = default;378 OK29 &operator=(OK29 &&) = default;379 380 T member;381};382 383struct OK30 {384 OK30(OK30 &&) noexcept(TrueT<OK30>::value) = default;385 OK30& operator=(OK30 &&) noexcept(TrueT<OK30>::value) = default;386};387 388template <typename>389struct OK31 {390 OK31(OK31 &&) noexcept(TrueT<int>::value) = default;391 OK31& operator=(OK31 &&) noexcept(TrueT<int>::value) = default;392};393 394namespace gh68101395{396 template <typename T>397 class Container {398 public:399 Container(Container&&) noexcept(std::is_nothrow_move_constructible<T>::value);400 };401} // namespace gh68101402 403namespace gh111436404{405 406template <typename value_type> class set {407 set(set &&) = default;408 409#ifdef ENABLE_ERROR410 set(initializer_list<value_type> __l) {};411 // CHECK-MESSAGES-ERR: :[[@LINE-1]]:7: error: member 'initializer_list' cannot have template arguments [clang-diagnostic-error]412 // CHECK-MESSAGES-ERR: :[[@LINE-2]]:36: error: expected ')' [clang-diagnostic-error]413#endif414};415 416} // namespace gh111436417