[NFC] Trim trailing whitespace in *.rst
[platform/upstream/llvm.git] / clang-tools-extra / docs / clang-tidy / checks / cppcoreguidelines-owning-memory.rst
1 .. title:: clang-tidy - cppcoreguidelines-owning-memory
2
3 cppcoreguidelines-owning-memory
4 ===============================
5
6 This check implements the type-based semantics of ``gsl::owner<T*>``, which allows
7 static analysis on code, that uses raw pointers to handle resources like
8 dynamic memory, but won't introduce RAII concepts.
9
10 The relevant sections in the `C++ Core Guidelines <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md>`_ are I.11, C.33, R.3 and GSL.Views
11 The definition of a ``gsl::owner<T*>`` is straight forward
12
13 .. code-block:: c++
14
15   namespace gsl { template <typename T> owner = T; }
16
17 It is therefore simple to introduce the owner even without using an implementation of
18 the `Guideline Support Library <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#gsl-guideline-support-library>`_.
19
20 All checks are purely type based and not (yet) flow sensitive.
21
22 The following examples will demonstrate the correct and incorrect initializations
23 of owners, assignment is handled the same way. Note that both ``new`` and
24 ``malloc()``-like resource functions are considered to produce resources.
25
26 .. code-block:: c++
27
28   // Creating an owner with factory functions is checked.
29   gsl::owner<int*> function_that_returns_owner() { return gsl::owner<int*>(new int(42)); }
30
31   // Dynamic memory must be assigned to an owner
32   int* Something = new int(42); // BAD, will be caught
33   gsl::owner<int*> Owner = new int(42); // Good
34   gsl::owner<int*> Owner = new int[42]; // Good as well
35
36   // Returned owner must be assigned to an owner
37   int* Something = function_that_returns_owner(); // Bad, factory function
38   gsl::owner<int*> Owner = function_that_returns_owner(); // Good, result lands in owner
39
40   // Something not a resource or owner should not be assigned to owners
41   int Stack = 42;
42   gsl::owner<int*> Owned = &Stack; // Bad, not a resource assigned
43
44 In the case of dynamic memory as resource, only ``gsl::owner<T*>`` variables are allowed
45 to be deleted.
46
47 .. code-block:: c++
48
49   // Example Bad, non-owner as resource handle, will be caught.
50   int* NonOwner = new int(42); // First warning here, since new must land in an owner
51   delete NonOwner; // Second warning here, since only owners are allowed to be deleted
52
53   // Example Good, Ownership correctly stated
54   gsl::owner<int*> Owner = new int(42); // Good
55   delete Owner; // Good as well, statically enforced, that only owners get deleted
56
57 The check will furthermore ensure, that functions, that expect a ``gsl::owner<T*>`` as
58 argument get called with either a ``gsl::owner<T*>`` or a newly created resource.
59
60 .. code-block:: c++
61
62   void expects_owner(gsl::owner<int*> o) { delete o; }
63
64   // Bad Code
65   int NonOwner = 42;
66   expects_owner(&NonOwner); // Bad, will get caught
67
68   // Good Code
69   gsl::owner<int*> Owner = new int(42);
70   expects_owner(Owner); // Good
71   expects_owner(new int(42)); // Good as well, recognized created resource
72
73   // Port legacy code for better resource-safety
74   gsl::owner<FILE*> File = fopen("my_file.txt", "rw+");
75   FILE* BadFile = fopen("another_file.txt", "w"); // Bad, warned
76
77   // ... use the file
78
79   fclose(File); // Ok, File is annotated as 'owner<>'
80   fclose(BadFile); // BadFile is not an 'owner<>', will be warned
81
82
83 Options
84 -------
85
86 .. option:: LegacyResourceProducers
87
88    Semicolon-separated list of fully qualified names of legacy functions that create
89    resources but cannot introduce ``gsl::owner<>``.
90    Defaults to ``::malloc;::aligned_alloc;::realloc;::calloc;::fopen;::freopen;::tmpfile``.
91
92
93 .. option:: LegacyResourceConsumers
94
95    Semicolon-separated list of fully qualified names of legacy functions expecting
96    resource owners as pointer arguments but cannot introduce ``gsl::owner<>``.
97    Defaults to ``::free;::realloc;::freopen;::fclose``.
98
99
100 Limitations
101 -----------
102
103 Using ``gsl::owner<T*>`` in a typedef or alias is not handled correctly.
104
105 .. code-block:: c++
106
107   using heap_int = gsl::owner<int*>;
108   heap_int allocated = new int(42); // False positive!
109
110 The ``gsl::owner<T*>`` is declared as a templated type alias.
111 In template functions and classes, like in the example below, the information
112 of the type aliases gets lost. Therefore using ``gsl::owner<T*>`` in a heavy templated
113 code base might lead to false positives.
114
115 Known code constructs that do not get diagnosed correctly are:
116
117 - ``std::exchange``
118 - ``std::vector<gsl::owner<T*>>``
119
120 .. code-block:: c++
121
122   // This template function works as expected. Type information doesn't get lost.
123   template <typename T>
124   void delete_owner(gsl::owner<T*> owned_object) {
125     delete owned_object; // Everything alright
126   }
127
128   gsl::owner<int*> function_that_returns_owner() { return gsl::owner<int*>(new int(42)); }
129
130   // Type deduction does not work for auto variables.
131   // This is caught by the check and will be noted accordingly.
132   auto OwnedObject = function_that_returns_owner(); // Type of OwnedObject will be int*
133
134   // Problematic function template that looses the typeinformation on owner
135   template <typename T>
136   void bad_template_function(T some_object) {
137     // This line will trigger the warning, that a non-owner is assigned to an owner
138     gsl::owner<T*> new_owner = some_object;
139   }
140
141   // Calling the function with an owner still yields a false positive.
142   bad_template_function(gsl::owner<int*>(new int(42)));
143
144
145   // The same issue occurs with templated classes like the following.
146   template <typename T>
147   class OwnedValue {
148   public:
149     const T getValue() const { return _val; }
150   private:
151     T _val;
152   };
153
154   // Code, that yields a false positive.
155   OwnedValue<gsl::owner<int*>> Owner(new int(42)); // Type deduction yield T -> int *
156   // False positive, getValue returns int* and not gsl::owner<int*>
157   gsl::owner<int*> OwnedInt = Owner.getValue();
158
159 Another limitation of the current implementation is only the type based checking.
160 Suppose you have code like the following:
161
162 .. code-block:: c++
163
164   // Two owners with assigned resources
165   gsl::owner<int*> Owner1 = new int(42);
166   gsl::owner<int*> Owner2 = new int(42);
167
168   Owner2 = Owner1; // Conceptual Leak of initial resource of Owner2!
169   Owner1 = nullptr;
170
171 The semantic of a ``gsl::owner<T*>`` is mostly like a ``std::unique_ptr<T>``, therefore
172 assignment of two ``gsl::owner<T*>`` is considered a move, which requires that the
173 resource ``Owner2`` must have been released before the assignment.
174 This kind of condition could be caught in later improvements of this check with
175 flowsensitive analysis. Currently, the `Clang Static Analyzer` catches this bug
176 for dynamic memory, but not for general types of resources.