@@ -28,6 +28,13 @@ template <class T>
28
28
class auto_ptr {
29
29
};
30
30
31
+ namespace pmr {
32
+ template <typename TYPE = void >
33
+ class allocator {};
34
+ }
35
+
36
+ struct allocator_arg_t {} allocator_arg;
37
+
31
38
} // namespace std
32
39
33
40
void assert (int expression){};
@@ -229,6 +236,122 @@ bool operator!=(Foo2 &, Foo2 &) {
229
236
};
230
237
}
231
238
239
+ // Missing call to `swap` function
240
+ class AllocatorAwareClassNoSwap {
241
+ // pointer member to trigger bugprone-unhandled-self-assignment
242
+ void *foo = nullptr ;
243
+
244
+ public:
245
+ using allocator_type = std::pmr::allocator<>;
246
+
247
+ AllocatorAwareClassNoSwap (const AllocatorAwareClassNoSwap& other) {
248
+ }
249
+
250
+ AllocatorAwareClassNoSwap (const AllocatorAwareClassNoSwap& other, const allocator_type& alloc) {
251
+ }
252
+
253
+ AllocatorAwareClassNoSwap& operator =(const AllocatorAwareClassNoSwap& other) {
254
+ // CHECK-MESSAGES: [[@LINE-1]]:32: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
255
+ AllocatorAwareClassNoSwap tmp (other, get_allocator ());
256
+ return *this ;
257
+ }
258
+
259
+ allocator_type get_allocator () const {
260
+ return allocator_type ();
261
+ }
262
+ };
263
+
264
+ // "Wrong" type is passed to member `swap` function
265
+ class AllocatorAwareClassSwapWrongArgType {
266
+ // pointer member to trigger bugprone-unhandled-self-assignment
267
+ void *foo = nullptr ;
268
+
269
+ public:
270
+ using allocator_type = std::pmr::allocator<>;
271
+
272
+ AllocatorAwareClassSwapWrongArgType (const AllocatorAwareClassSwapWrongArgType& other) {
273
+ }
274
+
275
+ AllocatorAwareClassSwapWrongArgType (const AllocatorAwareClassSwapWrongArgType& other, const allocator_type& alloc) {
276
+ }
277
+
278
+ AllocatorAwareClassSwapWrongArgType& operator =(const AllocatorAwareClassSwapWrongArgType& other) {
279
+ // CHECK-MESSAGES: [[@LINE-1]]:42: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
280
+ int tmp = 0 ;
281
+ swap (tmp);
282
+
283
+ return *this ;
284
+ }
285
+
286
+ void swap (int &) noexcept {
287
+ }
288
+
289
+ allocator_type get_allocator () const {
290
+ return allocator_type ();
291
+ }
292
+ };
293
+
294
+
295
+ // Making ADL `swap` call but with wrong argument type
296
+ class AllocatorAwareClassAdlSwapWrongArgType {
297
+ // pointer member to trigger bugprone-unhandled-self-assignment
298
+ void *foo = nullptr ;
299
+
300
+ public:
301
+ using allocator_type = std::pmr::allocator<>;
302
+
303
+ AllocatorAwareClassAdlSwapWrongArgType (const AllocatorAwareClassAdlSwapWrongArgType& other) {
304
+ }
305
+
306
+ AllocatorAwareClassAdlSwapWrongArgType (const AllocatorAwareClassAdlSwapWrongArgType& other, const allocator_type& alloc) {
307
+ }
308
+
309
+ AllocatorAwareClassAdlSwapWrongArgType& operator =(const AllocatorAwareClassAdlSwapWrongArgType& other) {
310
+ // CHECK-MESSAGES: [[@LINE-1]]:45: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
311
+ int tmp = 0 ;
312
+ swap (*this , tmp);
313
+
314
+ return *this ;
315
+ }
316
+
317
+ allocator_type get_allocator () const {
318
+ return allocator_type ();
319
+ }
320
+
321
+ friend void swap (AllocatorAwareClassAdlSwapWrongArgType&, int &) {
322
+ }
323
+ };
324
+
325
+ // `this` isn't passed to `swap`
326
+ class AllocatorAwareClassAdlSwapWrongArgs {
327
+ // pointer member to trigger bugprone-unhandled-self-assignment
328
+ void *foo = nullptr ;
329
+
330
+ public:
331
+ using allocator_type = std::pmr::allocator<>;
332
+
333
+ AllocatorAwareClassAdlSwapWrongArgs (const AllocatorAwareClassAdlSwapWrongArgs& other) {
334
+ }
335
+
336
+ AllocatorAwareClassAdlSwapWrongArgs (const AllocatorAwareClassAdlSwapWrongArgs& other, const allocator_type& alloc) {
337
+ }
338
+
339
+ AllocatorAwareClassAdlSwapWrongArgs& operator =(const AllocatorAwareClassAdlSwapWrongArgs& other) {
340
+ // CHECK-MESSAGES: [[@LINE-1]]:42: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment]
341
+ AllocatorAwareClassAdlSwapWrongArgs tmp1 (other, get_allocator ());
342
+ AllocatorAwareClassAdlSwapWrongArgs tmp2 (*this , get_allocator ());
343
+ swap (tmp1, tmp2);
344
+ return *this ;
345
+ }
346
+
347
+ allocator_type get_allocator () const {
348
+ return allocator_type ();
349
+ }
350
+
351
+ friend void swap (AllocatorAwareClassAdlSwapWrongArgs&, AllocatorAwareClassAdlSwapWrongArgs&) {
352
+ }
353
+ };
354
+
232
355
// /////////////////////////////////////////////////////////////////
233
356
// / Test cases correctly ignored by the check.
234
357
@@ -540,6 +663,89 @@ class NotACopyAssignmentOperator {
540
663
Uy *getUy () const { return Ptr2; }
541
664
};
542
665
666
+ // Support "extended" copy/move constructors
667
+ class AllocatorAwareClass {
668
+ // pointer member to trigger bugprone-unhandled-self-assignment
669
+ void *foo = nullptr ;
670
+
671
+ public:
672
+ using allocator_type = std::pmr::allocator<>;
673
+
674
+ AllocatorAwareClass (const AllocatorAwareClass& other) {
675
+ }
676
+
677
+ AllocatorAwareClass (const AllocatorAwareClass& other, const allocator_type& alloc) {
678
+ }
679
+
680
+ AllocatorAwareClass& operator =(const AllocatorAwareClass& other) {
681
+ AllocatorAwareClass tmp (other, get_allocator ());
682
+ swap (tmp);
683
+ return *this ;
684
+ }
685
+
686
+ void swap (AllocatorAwareClass& other) noexcept {
687
+ }
688
+
689
+ allocator_type get_allocator () const {
690
+ return allocator_type ();
691
+ }
692
+ };
693
+
694
+ // Support "extended" copy/move constructors + std::swap
695
+ class AllocatorAwareClassStdSwap {
696
+ // pointer member to trigger bugprone-unhandled-self-assignment
697
+ void *foo = nullptr ;
698
+
699
+ public:
700
+ using allocator_type = std::pmr::allocator<>;
701
+
702
+ AllocatorAwareClassStdSwap (const AllocatorAwareClassStdSwap& other) {
703
+ }
704
+
705
+ AllocatorAwareClassStdSwap (const AllocatorAwareClassStdSwap& other, const allocator_type& alloc) {
706
+ }
707
+
708
+ AllocatorAwareClassStdSwap& operator =(const AllocatorAwareClassStdSwap& other) {
709
+ using std::swap;
710
+
711
+ AllocatorAwareClassStdSwap tmp (other, get_allocator ());
712
+ swap (*this , tmp);
713
+ return *this ;
714
+ }
715
+
716
+ allocator_type get_allocator () const {
717
+ return allocator_type ();
718
+ }
719
+ };
720
+
721
+ // Support "extended" copy/move constructors + ADL swap
722
+ class AllocatorAwareClassAdlSwap {
723
+ // pointer member to trigger bugprone-unhandled-self-assignment
724
+ void *foo = nullptr ;
725
+
726
+ public:
727
+ using allocator_type = std::pmr::allocator<>;
728
+
729
+ AllocatorAwareClassAdlSwap (const AllocatorAwareClassAdlSwap& other) {
730
+ }
731
+
732
+ AllocatorAwareClassAdlSwap (const AllocatorAwareClassAdlSwap& other, const allocator_type& alloc) {
733
+ }
734
+
735
+ AllocatorAwareClassAdlSwap& operator =(const AllocatorAwareClassAdlSwap& other) {
736
+ AllocatorAwareClassAdlSwap tmp (other, get_allocator ());
737
+ swap (*this , tmp);
738
+ return *this ;
739
+ }
740
+
741
+ allocator_type get_allocator () const {
742
+ return allocator_type ();
743
+ }
744
+
745
+ friend void swap (AllocatorAwareClassAdlSwap&, AllocatorAwareClassAdlSwap&) {
746
+ }
747
+ };
748
+
543
749
// /////////////////////////////////////////////////////////////////
544
750
// / Test cases which should be caught by the check.
545
751
0 commit comments