redundant_null_check: silence some false positives
[smatch.git] / check_passes_sizeof.c
blob202c96c7f6d902f53457d8f6543d31c457e6524b
1 /*
2 * smatch/check_passes_sizeof.c
4 * Copyright (C) 2012 Oracle.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include "smatch.h"
11 #include "smatch_extra.h"
12 #include "smatch_slist.h"
14 #define NOBUF -2
16 static int my_id;
18 static int expr_equiv(struct expression *one, struct expression *two)
20 struct symbol *one_sym, *two_sym;
21 char *one_name = NULL;
22 char *two_name = NULL;
23 int ret = 0;
25 if (!one || !two)
26 return 0;
27 if (one->type != two->type)
28 return 0;
30 one_name = expr_to_str_sym(one, &one_sym);
31 if (!one_name || !one_sym)
32 goto free;
33 two_name = expr_to_str_sym(two, &two_sym);
34 if (!two_name || !two_sym)
35 goto free;
36 if (one_sym != two_sym)
37 goto free;
38 if (strcmp(one_name, two_name) == 0)
39 ret = 1;
40 free:
41 free_string(one_name);
42 free_string(two_name);
43 return ret;
46 static struct expression *get_returned_expr(struct expression *expr)
48 struct statement *stmt;
50 stmt = last_ptr_list((struct ptr_list *)big_statement_stack);
51 if (!stmt || stmt->type != STMT_EXPRESSION)
52 return NULL;
53 if (stmt->expression->type != EXPR_ASSIGNMENT)
54 return NULL;
55 if (stmt->expression->right != expr)
56 return NULL;
57 return stmt->expression->left;
60 static struct expression *remove_dereference(struct expression *expr)
62 if (!expr || expr->type != EXPR_PREOP || expr->op != '*')
63 return expr;
64 expr = expr->unop;
65 if (!expr || expr->type != EXPR_PREOP || expr->op != '*')
66 return expr;
67 return expr->unop;
70 static int get_buf_number(struct expression *call, struct expression *size_arg)
72 struct expression *arg;
73 int idx = -1;
75 size_arg = strip_expr(size_arg->cast_expression);
76 size_arg = remove_dereference(size_arg);
78 arg = get_returned_expr(call);
79 if (arg && expr_equiv(arg, size_arg))
80 return idx;
82 FOR_EACH_PTR(call->args, arg) {
83 idx++;
84 if (expr_equiv(arg, size_arg))
85 return idx;
86 } END_FOR_EACH_PTR(arg);
88 return NOBUF;
91 static void match_call(struct expression *call)
93 struct expression *arg;
94 char *name;
95 int buf_nr;
96 int i = -1;
98 if (call->fn->type != EXPR_SYMBOL)
99 return;
101 name = expr_to_var(call->fn);
102 FOR_EACH_PTR(call->args, arg) {
103 i++;
104 if (arg->type != EXPR_SIZEOF)
105 continue;
106 buf_nr = get_buf_number(call, arg);
107 if (buf_nr == NOBUF)
108 sm_msg("info: sizeof_param '%s' %d", name, i);
109 else
110 sm_msg("info: sizeof_param '%s' %d %d", name, i, buf_nr);
111 } END_FOR_EACH_PTR(arg);
112 free_string(name);
115 void check_passes_sizeof(int id)
117 if (!option_info)
118 return;
120 my_id = id;
121 add_hook(&match_call, FUNCTION_CALL_HOOK);