[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / clang-tools-extra / docs / clang-tidy / checks / bugprone / unhandled-self-assignment.rst
blobdee139861c8cfef2cd21b05c25d185b1c29379fc
1 .. title:: clang-tidy - bugprone-unhandled-self-assignment
3 bugprone-unhandled-self-assignment
4 ==================================
6 `cert-oop54-cpp` redirects here as an alias for this check. For the CERT alias,
7 the `WarnOnlyIfThisHasSuspiciousField` option is set to `false`.
9 Finds user-defined copy assignment operators which do not protect the code
10 against self-assignment either by checking self-assignment explicitly or
11 using the copy-and-swap or the copy-and-move method.
13 By default, this check searches only those classes which have any pointer or C array field
14 to avoid false positives. In case of a pointer or a C array, it's likely that self-copy
15 assignment breaks the object if the copy assignment operator was not written with care.
17 See also:
18 `OOP54-CPP. Gracefully handle self-copy assignment
19 <https://wiki.sei.cmu.edu/confluence/display/cplusplus/OOP54-CPP.+Gracefully+handle+self-copy+assignment>`_
21 A copy assignment operator must prevent that self-copy assignment ruins the
22 object state. A typical use case is when the class has a pointer field
23 and the copy assignment operator first releases the pointed object and
24 then tries to assign it:
26 .. code-block:: c++
28   class T {
29   int* p;
31   public:
32     T(const T &rhs) : p(rhs.p ? new int(*rhs.p) : nullptr) {}
33     ~T() { delete p; }
35     // ...
37     T& operator=(const T &rhs) {
38       delete p;
39       p = new int(*rhs.p);
40       return *this;
41     }
42   };
44 There are two common C++ patterns to avoid this problem. The first is
45 the self-assignment check:
47 .. code-block:: c++
49   class T {
50   int* p;
52   public:
53     T(const T &rhs) : p(rhs.p ? new int(*rhs.p) : nullptr) {}
54     ~T() { delete p; }
56     // ...
58     T& operator=(const T &rhs) {
59       if(this == &rhs)
60         return *this;
62       delete p;
63       p = new int(*rhs.p);
64       return *this;
65     }
66   };
68 The second one is the copy-and-swap method when we create a temporary copy
69 (using the copy constructor) and then swap this temporary object with ``this``:
71 .. code-block:: c++
73   class T {
74   int* p;
76   public:
77     T(const T &rhs) : p(rhs.p ? new int(*rhs.p) : nullptr) {}
78     ~T() { delete p; }
80     // ...
82     void swap(T &rhs) {
83       using std::swap;
84       swap(p, rhs.p);
85     }
87     T& operator=(const T &rhs) {
88       T(rhs).swap(*this);
89       return *this;
90     }
91   };
93 There is a third pattern which is less common. Let's call it the copy-and-move method
94 when we create a temporary copy (using the copy constructor) and then move this
95 temporary object into ``this`` (needs a move assignment operator):
97 .. code-block:: c++
99   class T {
100   int* p;
102   public:
103     T(const T &rhs) : p(rhs.p ? new int(*rhs.p) : nullptr) {}
104     ~T() { delete p; }
106     // ...
108     T& operator=(const T &rhs) {
109       T t = rhs;
110       *this = std::move(t);
111       return *this;
112     }
114     T& operator=(T &&rhs) {
115       p = rhs.p;
116       rhs.p = nullptr;
117       return *this;
118     }
119   };
121 .. option:: WarnOnlyIfThisHasSuspiciousField
123   When `true`, the check will warn only if the container class of the copy assignment operator
124   has any suspicious fields (pointer or C array). This option is set to `true` by default.