1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
| | // This rule finds sequences of "unused" declerations and uses of
// "struct strbuf".
//
// I.e. this finds cases where we only declare the variable, and then
// release it, e.g.:
//
// struct strbuf buf = STRBUF_INIT;
// [.. no other use of "buf" in the function ..]
// strbuf_release(&buf)
//
// Or:
//
// struct strbuf buf;
// [.. no other use of "buf" in the function ..]
// strbuf_init(&buf, 0);
// [.. no other use of "buf" in the function ..]
// strbuf_release(&buf)
//
// To do do this we find (continued below)...
@@
type T;
identifier I;
// STRBUF_INIT
constant INIT_MACRO =~ "^STRBUF_INIT$";
// x[mc]alloc() etc.
identifier MALLOC1 =~ "^x?[mc]alloc$";
// strbuf_init(&I, ...) etc.
identifier INIT_CALL1 =~ "^strbuf_init$";
// strbuf_release()
identifier REL1 =~ "^strbuf_release$";
@@
// .. A declaration like "struct strbuf buf;"...
(
- T I;
// ... or "struct strbuf buf = { 0 };" ...
|
- T I = { 0 };
// ... or "struct STRBUF buf = STRBUF_INIT;" ...
|
- T I = INIT_MACRO;
|
// ... or "struct strbuf *buf = xmalloc(...)" etc. ...
- T I = MALLOC1(...);
)
// ... Optionally followed by lines that make no use of "buf", "&buf"
// etc., but which ...
<... when != \( I \| &I \)
when strict
(
// .. (only) make use of "buf" or "&buf" to call something like
// "strbuf_init(&buf, ...)" ...
- \( INIT_CALL1 \)( \( I \| &I \), ...);
|
// .. or to follow-up a "struct strbuf *buf" with e.g. "buf =
// xmalloc(...)" (which may in turn be followed-up by a
// "strbuf_init()", which we'll match with INIT_CALL1) ...
- I = MALLOC1(...);
)
...>
// ... and then no mention of "buf" or "&buf" until we get to a
// strbuf_release(&buf) at the end ...
- \( REL1 \)( \( &I \| I \) );
// ... and no use *after* either, e.g. we don't want to delete
// init/strbuf_release() patterns, where "&buf" could be used
// afterwards.
... when != \( I \| &I \)
when strict
// This rule also isn't capable of finding cases where &buf is used,
// but only to e.g. pass that variable to a static function which
// doesn't use it. The analysis is only function-local.
|