Merge branch 'ab/cocci-unused'
Add Coccinelle rules to detect the pattern of initializing and then
finalizing a structure without using it in between at all, which
happens after code restructuring and the compilers fail to
recognize as an unused variable.
* ab/cocci-unused:
cocci: generalize "unused" rule to cover more than "strbuf"
cocci: add and apply a rule to find "unused" strbufs
cocci: have "coccicheck{,-pending}" depend on "coccicheck-test"
cocci: add a "coccicheck-test" target and test *.cocci rules
Makefile & .gitignore: ignore & clean "git.res", not "*.res"
Makefile: remove mandatory "spatch" arguments from SPATCH_FLAGS
This commit is contained in:
11
contrib/coccinelle/tests/free.c
Normal file
11
contrib/coccinelle/tests/free.c
Normal file
@ -0,0 +1,11 @@
|
||||
int use_FREE_AND_NULL(int *v)
|
||||
{
|
||||
free(*v);
|
||||
*v = NULL;
|
||||
}
|
||||
|
||||
int need_no_if(int *v)
|
||||
{
|
||||
if (v)
|
||||
free(v);
|
||||
}
|
||||
9
contrib/coccinelle/tests/free.res
Normal file
9
contrib/coccinelle/tests/free.res
Normal file
@ -0,0 +1,9 @@
|
||||
int use_FREE_AND_NULL(int *v)
|
||||
{
|
||||
FREE_AND_NULL(*v);
|
||||
}
|
||||
|
||||
int need_no_if(int *v)
|
||||
{
|
||||
free(v);
|
||||
}
|
||||
82
contrib/coccinelle/tests/unused.c
Normal file
82
contrib/coccinelle/tests/unused.c
Normal file
@ -0,0 +1,82 @@
|
||||
void test_strbuf(void)
|
||||
{
|
||||
struct strbuf sb1 = STRBUF_INIT;
|
||||
struct strbuf sb2 = STRBUF_INIT;
|
||||
struct strbuf sb3 = STRBUF_INIT;
|
||||
struct strbuf sb4 = STRBUF_INIT;
|
||||
struct strbuf sb5;
|
||||
struct strbuf sb6 = { 0 };
|
||||
struct strbuf sb7 = STRBUF_INIT;
|
||||
struct strbuf sb8 = STRBUF_INIT;
|
||||
struct strbuf *sp1;
|
||||
struct strbuf *sp2;
|
||||
struct strbuf *sp3;
|
||||
struct strbuf *sp4 = xmalloc(sizeof(struct strbuf));
|
||||
struct strbuf *sp5 = xmalloc(sizeof(struct strbuf));
|
||||
struct strbuf *sp6 = xmalloc(sizeof(struct strbuf));
|
||||
struct strbuf *sp7;
|
||||
|
||||
strbuf_init(&sb5, 0);
|
||||
strbuf_init(sp1, 0);
|
||||
strbuf_init(sp2, 0);
|
||||
strbuf_init(sp3, 0);
|
||||
strbuf_init(sp4, 0);
|
||||
strbuf_init(sp5, 0);
|
||||
strbuf_init(sp6, 0);
|
||||
strbuf_init(sp7, 0);
|
||||
sp7 = xmalloc(sizeof(struct strbuf));
|
||||
|
||||
use_before(&sb3);
|
||||
use_as_str("%s", sb7.buf);
|
||||
use_as_str("%s", sp1->buf);
|
||||
use_as_str("%s", sp6->buf);
|
||||
pass_pp(&sp3);
|
||||
|
||||
strbuf_release(&sb1);
|
||||
strbuf_reset(&sb2);
|
||||
strbuf_release(&sb3);
|
||||
strbuf_release(&sb4);
|
||||
strbuf_release(&sb5);
|
||||
strbuf_release(&sb6);
|
||||
strbuf_release(&sb7);
|
||||
strbuf_release(sp1);
|
||||
strbuf_release(sp2);
|
||||
strbuf_release(sp3);
|
||||
strbuf_release(sp4);
|
||||
strbuf_release(sp5);
|
||||
strbuf_release(sp6);
|
||||
strbuf_release(sp7);
|
||||
|
||||
use_after(&sb4);
|
||||
|
||||
if (when_strict())
|
||||
return;
|
||||
strbuf_release(&sb8);
|
||||
}
|
||||
|
||||
void test_other(void)
|
||||
{
|
||||
struct string_list l = STRING_LIST_INIT_DUP;
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
|
||||
string_list_clear(&l, 0);
|
||||
string_list_clear(&sb, 0);
|
||||
}
|
||||
|
||||
void test_worktrees(void)
|
||||
{
|
||||
struct worktree **w1 = get_worktrees();
|
||||
struct worktree **w2 = get_worktrees();
|
||||
struct worktree **w3;
|
||||
struct worktree **w4;
|
||||
|
||||
w3 = get_worktrees();
|
||||
w4 = get_worktrees();
|
||||
|
||||
use_it(w4);
|
||||
|
||||
free_worktrees(w1);
|
||||
free_worktrees(w2);
|
||||
free_worktrees(w3);
|
||||
free_worktrees(w4);
|
||||
}
|
||||
45
contrib/coccinelle/tests/unused.res
Normal file
45
contrib/coccinelle/tests/unused.res
Normal file
@ -0,0 +1,45 @@
|
||||
void test_strbuf(void)
|
||||
{
|
||||
struct strbuf sb3 = STRBUF_INIT;
|
||||
struct strbuf sb4 = STRBUF_INIT;
|
||||
struct strbuf sb7 = STRBUF_INIT;
|
||||
struct strbuf *sp1;
|
||||
struct strbuf *sp3;
|
||||
struct strbuf *sp6 = xmalloc(sizeof(struct strbuf));
|
||||
strbuf_init(sp1, 0);
|
||||
strbuf_init(sp3, 0);
|
||||
strbuf_init(sp6, 0);
|
||||
|
||||
use_before(&sb3);
|
||||
use_as_str("%s", sb7.buf);
|
||||
use_as_str("%s", sp1->buf);
|
||||
use_as_str("%s", sp6->buf);
|
||||
pass_pp(&sp3);
|
||||
|
||||
strbuf_release(&sb3);
|
||||
strbuf_release(&sb4);
|
||||
strbuf_release(&sb7);
|
||||
strbuf_release(sp1);
|
||||
strbuf_release(sp3);
|
||||
strbuf_release(sp6);
|
||||
|
||||
use_after(&sb4);
|
||||
|
||||
if (when_strict())
|
||||
return;
|
||||
}
|
||||
|
||||
void test_other(void)
|
||||
{
|
||||
}
|
||||
|
||||
void test_worktrees(void)
|
||||
{
|
||||
struct worktree **w4;
|
||||
|
||||
w4 = get_worktrees();
|
||||
|
||||
use_it(w4);
|
||||
|
||||
free_worktrees(w4);
|
||||
}
|
||||
43
contrib/coccinelle/unused.cocci
Normal file
43
contrib/coccinelle/unused.cocci
Normal file
@ -0,0 +1,43 @@
|
||||
// This rule finds sequences of "unused" declerations and uses of a
|
||||
// variable, where "unused" is defined to include only calling the
|
||||
// equivalent of alloc, init & free functions on the variable.
|
||||
@@
|
||||
type T;
|
||||
identifier I;
|
||||
// STRBUF_INIT, but also e.g. STRING_LIST_INIT_DUP (so no anchoring)
|
||||
constant INIT_MACRO =~ "_INIT";
|
||||
identifier MALLOC1 =~ "^x?[mc]alloc$";
|
||||
identifier INIT_ASSIGN1 =~ "^get_worktrees$";
|
||||
identifier INIT_CALL1 =~ "^[a-z_]*_init$";
|
||||
identifier REL1 =~ "^[a-z_]*_(release|reset|clear|free)$";
|
||||
identifier REL2 =~ "^(release|clear|free)_[a-z_]*$";
|
||||
@@
|
||||
|
||||
(
|
||||
- T I;
|
||||
|
|
||||
- T I = { 0 };
|
||||
|
|
||||
- T I = INIT_MACRO;
|
||||
|
|
||||
- T I = MALLOC1(...);
|
||||
|
|
||||
- T I = INIT_ASSIGN1(...);
|
||||
)
|
||||
|
||||
<... when != \( I \| &I \)
|
||||
(
|
||||
- \( INIT_CALL1 \)( \( I \| &I \), ...);
|
||||
|
|
||||
- I = \( INIT_ASSIGN1 \)(...);
|
||||
|
|
||||
- I = MALLOC1(...);
|
||||
)
|
||||
...>
|
||||
|
||||
(
|
||||
- \( REL1 \| REL2 \)( \( I \| &I \), ...);
|
||||
|
|
||||
- \( REL1 \| REL2 \)( \( &I \| I \) );
|
||||
)
|
||||
... when != \( I \| &I \)
|
||||
@ -687,7 +687,7 @@ static int cmd_diagnose(int argc, const char **argv)
|
||||
int stdout_fd = -1, archiver_fd = -1;
|
||||
time_t now = time(NULL);
|
||||
struct tm tm;
|
||||
struct strbuf path = STRBUF_INIT, buf = STRBUF_INIT;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
int res = 0;
|
||||
|
||||
argc = parse_options(argc, argv, NULL, options,
|
||||
@ -779,7 +779,6 @@ diagnose_cleanup:
|
||||
free(argv_copy);
|
||||
strvec_clear(&archiver_args);
|
||||
strbuf_release(&zip_path);
|
||||
strbuf_release(&path);
|
||||
strbuf_release(&buf);
|
||||
|
||||
return res;
|
||||
|
||||
Reference in New Issue
Block a user