meson.build: Check for statx()
[qemu.git] / scripts / coccinelle / errp-guard.cocci
blob6e789acf2d772ff6798dcc1bdb025efea3845e15
1 // Use ERRP_GUARD() (see include/qapi/error.h)
2 //
3 // Copyright (c) 2020 Virtuozzo International GmbH.
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License as
7 // published by the Free Software Foundation; either version 2 of the
8 // License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program.  If not, see
17 // <http://www.gnu.org/licenses/>.
19 // Usage example:
20 // spatch --sp-file scripts/coccinelle/errp-guard.cocci \
21 //  --macro-file scripts/cocci-macro-file.h --in-place \
22 //  --no-show-diff --max-width 80 FILES...
24 // Note: --max-width 80 is needed because coccinelle default is less
25 // than 80, and without this parameter coccinelle may reindent some
26 // lines which fit into 80 characters but not to coccinelle default,
27 // which in turn produces extra patch hunks for no reason.
29 // Switch unusual Error ** parameter names to errp
30 // (this is necessary to use ERRP_GUARD).
32 // Disable optional_qualifier to skip functions with
33 // "Error *const *errp" parameter.
35 // Skip functions with "assert(_errp && *_errp)" statement, because
36 // that signals unusual semantics, and the parameter name may well
37 // serve a purpose. (like nbd_iter_channel_error()).
39 // Skip util/error.c to not touch, for example, error_propagate() and
40 // error_propagate_prepend().
41 @ depends on !(file in "util/error.c") disable optional_qualifier@
42 identifier fn;
43 identifier _errp != errp;
46  fn(...,
47 -   Error **_errp
48 +   Error **errp
49     ,...)
50  {
52      ... when != assert(_errp && *_errp)
54      <...
55 -    _errp
56 +    errp
57      ...>
59  }
61 // Add invocation of ERRP_GUARD() to errp-functions where // necessary
63 // Note, that without "when any" the final "..." does not mach
64 // something matched by previous pattern, i.e. the rule will not match
65 // double error_prepend in control flow like in
66 // vfio_set_irq_signaling().
68 // Note, "exists" says that we want apply rule even if it does not
69 // match on all possible control flows (otherwise, it will not match
70 // standard pattern when error_propagate() call is in if branch).
71 @ disable optional_qualifier exists@
72 identifier fn, local_err;
73 symbol errp;
76  fn(..., Error **errp, ...)
77  {
78 +   ERRP_GUARD();
79     ...  when != ERRP_GUARD();
82     error_append_hint(errp, ...);
84     error_prepend(errp, ...);
86     error_vprepend(errp, ...);
88     ... when any
90     Error *local_err = NULL;
91     ...
93     error_propagate_prepend(errp, local_err, ...);
95     error_propagate(errp, local_err);
97     ...
99  }
101 // Warn when several Error * definitions are in the control flow.
102 // This rule is not chained to rule1 and less restrictive, to cover more
103 // functions to warn (even those we are not going to convert).
105 // Note, that even with one (or zero) Error * definition in the each
106 // control flow we may have several (in total) Error * definitions in
107 // the function. This case deserves attention too, but I don't see
108 // simple way to match with help of coccinelle.
109 @check1 disable optional_qualifier exists@
110 identifier fn, _errp, local_err, local_err2;
111 position p1, p2;
114  fn(..., Error **_errp, ...)
116      ...
117      Error *local_err = NULL;@p1
118      ... when any
119      Error *local_err2 = NULL;@p2
120      ... when any
123 @ script:python @
124 fn << check1.fn;
125 p1 << check1.p1;
126 p2 << check1.p2;
129 print('Warning: function {} has several definitions of '
130       'Error * local variable: at {}:{} and then at {}:{}'.format(
131           fn, p1[0].file, p1[0].line, p2[0].file, p2[0].line))
133 // Warn when several propagations are in the control flow.
134 @check2 disable optional_qualifier exists@
135 identifier fn, _errp;
136 position p1, p2;
139  fn(..., Error **_errp, ...)
141      ...
143      error_propagate_prepend(_errp, ...);@p1
145      error_propagate(_errp, ...);@p1
147      ...
149      error_propagate_prepend(_errp, ...);@p2
151      error_propagate(_errp, ...);@p2
153      ... when any
156 @ script:python @
157 fn << check2.fn;
158 p1 << check2.p1;
159 p2 << check2.p2;
162 print('Warning: function {} propagates to errp several times in '
163       'one control flow: at {}:{} and then at {}:{}'.format(
164           fn, p1[0].file, p1[0].line, p2[0].file, p2[0].line))
166 // Match functions with propagation of local error to errp.
167 // We want to refer these functions in several following rules, but I
168 // don't know a proper way to inherit a function, not just its name
169 // (to not match another functions with same name in following rules).
170 // Not-proper way is as follows: rename errp parameter in functions
171 // header and match it in following rules. Rename it back after all
172 // transformations.
174 // The common case is a single definition of local_err with at most one
175 // error_propagate_prepend() or error_propagate() on each control-flow
176 // path. Functions with multiple definitions or propagates we want to
177 // examine manually. Rules check1 and check2 emit warnings to guide us
178 // to them.
180 // Note that we match not only this "common case", but any function,
181 // which has the "common case" on at least one control-flow path.
182 @rule1 disable optional_qualifier exists@
183 identifier fn, local_err;
184 symbol errp;
187  fn(..., Error **
188 -    errp
189 +    ____
190     , ...)
192      ...
193      Error *local_err = NULL;
194      ...
196      error_propagate_prepend(errp, local_err, ...);
198      error_propagate(errp, local_err);
200      ...
203 // Convert special case with goto separately.
204 // I tried merging this into the following rule the obvious way, but
205 // it made Coccinelle hang on block.c
207 // Note interesting thing: if we don't do it here, and try to fixup
208 // "out: }" things later after all transformations (the rule will be
209 // the same, just without error_propagate() call), coccinelle fails to
210 // match this "out: }".
211 @ disable optional_qualifier@
212 identifier rule1.fn, rule1.local_err, out;
213 symbol errp;
216  fn(..., Error ** ____, ...)
218      <...
219 -    goto out;
220 +    return;
221      ...>
222 - out:
223 -    error_propagate(errp, local_err);
226 // Convert most of local_err related stuff.
228 // Note, that we inherit rule1.fn and rule1.local_err names, not
229 // objects themselves. We may match something not related to the
230 // pattern matched by rule1. For example, local_err may be defined with
231 // the same name in different blocks inside one function, and in one
232 // block follow the propagation pattern and in other block doesn't.
234 // Note also that errp-cleaning functions
235 //   error_free_errp
236 //   error_report_errp
237 //   error_reportf_errp
238 //   warn_report_errp
239 //   warn_reportf_errp
240 // are not yet implemented. They must call corresponding Error* -
241 // freeing function and then set *errp to NULL, to avoid further
242 // propagation to original errp (consider ERRP_GUARD in use).
243 // For example, error_free_errp may look like this:
245 //    void error_free_errp(Error **errp)
246 //    {
247 //        error_free(*errp);
248 //        *errp = NULL;
249 //    }
250 @ disable optional_qualifier exists@
251 identifier rule1.fn, rule1.local_err;
252 expression list args;
253 symbol errp;
256  fn(..., Error ** ____, ...)
258      <...
260 -    Error *local_err = NULL;
263 // Convert error clearing functions
265 -    error_free(local_err);
266 +    error_free_errp(errp);
268 -    error_report_err(local_err);
269 +    error_report_errp(errp);
271 -    error_reportf_err(local_err, args);
272 +    error_reportf_errp(errp, args);
274 -    warn_report_err(local_err);
275 +    warn_report_errp(errp);
277 -    warn_reportf_err(local_err, args);
278 +    warn_reportf_errp(errp, args);
280 ?-    local_err = NULL;
283 -    error_propagate_prepend(errp, local_err, args);
284 +    error_prepend(errp, args);
286 -    error_propagate(errp, local_err);
288 -    &local_err
289 +    errp
291      ...>
294 // Convert remaining local_err usage. For example, different kinds of
295 // error checking in if conditionals. We can't merge this into
296 // previous hunk, as this conflicts with other substitutions in it (at
297 // least with "- local_err = NULL").
298 @ disable optional_qualifier@
299 identifier rule1.fn, rule1.local_err;
300 symbol errp;
303  fn(..., Error ** ____, ...)
305      <...
306 -    local_err
307 +    *errp
308      ...>
311 // Always use the same pattern for checking error
312 @ disable optional_qualifier@
313 identifier rule1.fn;
314 symbol errp;
317  fn(..., Error ** ____, ...)
319      <...
320 -    *errp != NULL
321 +    *errp
322      ...>
325 // Revert temporary ___ identifier.
326 @ disable optional_qualifier@
327 identifier rule1.fn;
330  fn(..., Error **
331 -   ____
332 +   errp
333     , ...)
335      ...