xref: /llvm-project/clang-tools-extra/docs/clang-tidy/checks/modernize/use-auto.rst (revision 6e566bc5523f743bc34a7e26f050f1f2b4d699a8)
1.. title:: clang-tidy - modernize-use-auto
2
3modernize-use-auto
4==================
5
6This check is responsible for using the ``auto`` type specifier for variable
7declarations to *improve code readability and maintainability*. For example:
8
9.. code-block:: c++
10
11  std::vector<int>::iterator I = my_container.begin();
12
13  // transforms to:
14
15  auto I = my_container.begin();
16
17The ``auto`` type specifier will only be introduced in situations where the
18variable type matches the type of the initializer expression. In other words
19``auto`` should deduce the same type that was originally spelled in the source.
20However, not every situation should be transformed:
21
22.. code-block:: c++
23
24  int val = 42;
25  InfoStruct &I = SomeObject.getInfo();
26
27  // Should not become:
28
29  auto val = 42;
30  auto &I = SomeObject.getInfo();
31
32In this example using ``auto`` for builtins doesn't improve readability. In
33other situations it makes the code less self-documenting impairing readability
34and maintainability. As a result, ``auto`` is used only introduced in specific
35situations described below.
36
37Iterators
38---------
39
40Iterator type specifiers tend to be long and used frequently, especially in
41loop constructs. Since the functions generating iterators have a common format,
42the type specifier can be replaced without obscuring the meaning of code while
43improving readability and maintainability.
44
45.. code-block:: c++
46
47  for (std::vector<int>::iterator I = my_container.begin(),
48                                  E = my_container.end();
49       I != E; ++I) {
50  }
51
52  // becomes
53
54  for (auto I = my_container.begin(), E = my_container.end(); I != E; ++I) {
55  }
56
57The check will only replace iterator type-specifiers when all of the following
58conditions are satisfied:
59
60* The iterator is for one of the standard containers in ``std`` namespace:
61
62  * ``array``
63  * ``deque``
64  * ``forward_list``
65  * ``list``
66  * ``vector``
67  * ``map``
68  * ``multimap``
69  * ``set``
70  * ``multiset``
71  * ``unordered_map``
72  * ``unordered_multimap``
73  * ``unordered_set``
74  * ``unordered_multiset``
75  * ``queue``
76  * ``priority_queue``
77  * ``stack``
78
79* The iterator is one of the possible iterator types for standard containers:
80
81  * ``iterator``
82  * ``reverse_iterator``
83  * ``const_iterator``
84  * ``const_reverse_iterator``
85
86* In addition to using iterator types directly, typedefs or other ways of
87  referring to those types are also allowed. However, implementation-specific
88  types for which a type like ``std::vector<int>::iterator`` is itself a
89  typedef will not be transformed. Consider the following examples:
90
91.. code-block:: c++
92
93  // The following direct uses of iterator types will be transformed.
94  std::vector<int>::iterator I = MyVec.begin();
95  {
96    using namespace std;
97    list<int>::iterator I = MyList.begin();
98  }
99
100  // The type specifier for J would transform to auto since it's a typedef
101  // to a standard iterator type.
102  typedef std::map<int, std::string>::const_iterator map_iterator;
103  map_iterator J = MyMap.begin();
104
105  // The following implementation-specific iterator type for which
106  // std::vector<int>::iterator could be a typedef would not be transformed.
107  __gnu_cxx::__normal_iterator<int*, std::vector> K = MyVec.begin();
108
109* The initializer for the variable being declared is not a braced initializer
110  list. Otherwise, use of ``auto`` would cause the type of the variable to be
111  deduced as ``std::initializer_list``.
112
113New expressions
114---------------
115
116Frequently, when a pointer is declared and initialized with ``new``, the
117pointee type is written twice: in the declaration type and in the
118``new`` expression. In this case, the declaration type can be replaced with
119``auto`` improving readability and maintainability.
120
121.. code-block:: c++
122
123  TypeName *my_pointer = new TypeName(my_param);
124
125  // becomes
126
127  auto *my_pointer = new TypeName(my_param);
128
129The check will also replace the declaration type in multiple declarations, if
130the following conditions are satisfied:
131
132* All declared variables have the same type (i.e. all of them are pointers to
133  the same type).
134* All declared variables are initialized with a ``new`` expression.
135* The types of all the new expressions are the same than the pointee of the
136  declaration type.
137
138.. code-block:: c++
139
140  TypeName *my_first_pointer = new TypeName, *my_second_pointer = new TypeName;
141
142  // becomes
143
144  auto *my_first_pointer = new TypeName, *my_second_pointer = new TypeName;
145
146Cast expressions
147----------------
148
149Frequently, when a variable is declared and initialized with a cast, the
150variable type is written twice: in the declaration type and in the
151cast expression. In this case, the declaration type can be replaced with
152``auto`` improving readability and maintainability.
153
154.. code-block:: c++
155
156  TypeName *my_pointer = static_cast<TypeName>(my_param);
157
158  // becomes
159
160  auto *my_pointer = static_cast<TypeName>(my_param);
161
162The check handles ``static_cast``, ``dynamic_cast``, ``const_cast``,
163``reinterpret_cast``, functional casts, C-style casts and function templates
164that behave as casts, such as ``llvm::dyn_cast``, ``boost::lexical_cast`` and
165``gsl::narrow_cast``. Calls to function templates are considered to behave as
166casts if the first template argument is explicit and is a type, and the function
167returns that type, or a pointer or reference to it.
168
169Known Limitations
170-----------------
171
172* If the initializer is an explicit conversion constructor, the check will not
173  replace the type specifier even though it would be safe to do so.
174
175* User-defined iterators are not handled at this time.
176
177Options
178-------
179
180.. option:: MinTypeNameLength
181
182   If the option is set to non-zero (default `5`), the check will ignore type
183   names having a length less than the option value. The option affects
184   expressions only, not iterators.
185   Spaces between multi-lexeme type names (``long int``) are considered as one.
186   If the :option:`RemoveStars` option (see below) is set to `true`, then ``*s``
187   in the type are also counted as a part of the type name.
188
189.. code-block:: c++
190
191  // MinTypeNameLength = 0, RemoveStars=0
192
193  int a = static_cast<int>(foo());            // ---> auto a = ...
194  // length(bool *) = 4
195  bool *b = new bool;                         // ---> auto *b = ...
196  unsigned c = static_cast<unsigned>(foo());  // ---> auto c = ...
197
198  // MinTypeNameLength = 5, RemoveStars=0
199
200  int a = static_cast<int>(foo());                 // ---> int  a = ...
201  bool b = static_cast<bool>(foo());               // ---> bool b = ...
202  bool *pb = static_cast<bool*>(foo());            // ---> bool *pb = ...
203  unsigned c = static_cast<unsigned>(foo());       // ---> auto c = ...
204  // length(long <on-or-more-spaces> int) = 8
205  long int d = static_cast<long int>(foo());       // ---> auto d = ...
206
207  // MinTypeNameLength = 5, RemoveStars=1
208
209  int a = static_cast<int>(foo());                 // ---> int  a = ...
210  // length(int * * ) = 5
211  int **pa = static_cast<int**>(foo());            // ---> auto pa = ...
212  bool b = static_cast<bool>(foo());               // ---> bool b = ...
213  bool *pb = static_cast<bool*>(foo());            // ---> auto pb = ...
214  unsigned c = static_cast<unsigned>(foo());       // ---> auto c = ...
215  long int d = static_cast<long int>(foo());       // ---> auto d = ...
216
217.. option:: RemoveStars
218
219   If the option is set to `true` (default is `false`), the check will remove
220   stars from the non-typedef pointer types when replacing type names with
221   ``auto``. Otherwise, the check will leave stars. For example:
222
223.. code-block:: c++
224
225  TypeName *my_first_pointer = new TypeName, *my_second_pointer = new TypeName;
226
227  // RemoveStars = 0
228
229  auto *my_first_pointer = new TypeName, *my_second_pointer = new TypeName;
230
231  // RemoveStars = 1
232
233  auto my_first_pointer = new TypeName, my_second_pointer = new TypeName;
234