2 * sparse/check_redundant_null_check.c
4 * Copyright (C) 2009 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
11 * Some functions are designed to handle NULL values but people always
12 * do stuff like: if (foo) kfree(foo);
13 * The if check is unneeded and a waste of precious CPU cycles. Also a
16 * List of wine functions taken from Michael Stefaniuc's
17 * redundant_null_check.pl
19 * This test is not the prettiest. Smatch has a feature where it
20 * simplifies comparisons to zero and I wanted to take advantage of
21 * that, but that also makes things a bit complicated.
23 * We work backwards. When we hit a kfree() we ask was the last statement
24 * an if statement, and was the last comparison checking the pointer we
25 * are about to free? If all three answers are yes, then print a message.
33 static struct statement
*this_statement
= NULL
;
34 static struct statement
*previous_statement
= NULL
;
35 static struct expression
*previous_condition
= NULL
;
37 static const char *wine_funcs
[] = {
43 "FreeEnvironmentStringsA",
51 "SetupTermDefaultQueueCallback",
54 static void dont_check(const char *fn
, struct expression
*expr
, void *unused
)
56 struct expression
*arg
;
58 char *condition_name
= NULL
;
60 if (!previous_statement
|| !previous_condition
|| previous_statement
->type
!= STMT_IF
)
63 arg
= get_argument_from_call_expr(expr
->args
, 0);
64 name
= get_variable_from_expr(arg
, NULL
);
67 condition_name
= get_variable_from_expr(previous_condition
, NULL
);
70 if (!strcmp(name
, condition_name
))
71 sm_msg("info: redundant null check on %s calling %s()", name
, fn
);
75 free_string(condition_name
);
78 static void match_statement(struct statement
*stmt
)
80 if (stmt
->type
== STMT_COMPOUND
)
82 previous_statement
= this_statement
;
83 this_statement
= stmt
;
86 static void match_condition(struct expression
*expr
)
88 previous_condition
= expr
;
91 void check_redundant_null_check(int id
)
96 add_hook(&match_statement
, STMT_HOOK
);
97 add_hook(&match_condition
, CONDITION_HOOK
);
98 add_function_hook("free", &dont_check
, NULL
);
99 if (option_project
== PROJ_KERNEL
) {
100 add_function_hook("kfree", &dont_check
, NULL
);
101 } else if (option_project
== PROJ_WINE
) {
102 for (i
= 0; i
< ARRAY_SIZE(wine_funcs
); i
++) {
103 add_function_hook(wine_funcs
[i
], &dont_check
, NULL
);