conditions: pass SELECT_HOOK for select assignments
[smatch.git] / check_passes_sizeof.c
blob83e5192eeb622e0ff75f29fdfc091ee3d17f2667
1 /*
2 * Copyright (C) 2012 Oracle.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
18 #include "smatch.h"
19 #include "smatch_extra.h"
20 #include "smatch_slist.h"
22 #define NOBUF -2
24 static int my_id;
26 static struct expression *get_returned_expr(struct expression *expr)
28 struct statement *stmt;
30 stmt = last_ptr_list((struct ptr_list *)big_statement_stack);
31 if (!stmt || stmt->type != STMT_EXPRESSION)
32 return NULL;
33 if (stmt->expression->type != EXPR_ASSIGNMENT)
34 return NULL;
35 if (stmt->expression->right != expr)
36 return NULL;
37 return stmt->expression->left;
40 static struct expression *remove_dereference(struct expression *expr)
42 if (!expr || expr->type != EXPR_PREOP || expr->op != '*')
43 return expr;
44 expr = expr->unop;
45 if (!expr || expr->type != EXPR_PREOP || expr->op != '*')
46 return expr;
47 return expr->unop;
50 static int get_buf_number(struct expression *call, struct expression *size_arg)
52 struct expression *arg;
53 int idx = -1;
55 size_arg = strip_expr(size_arg->cast_expression);
56 size_arg = remove_dereference(size_arg);
58 arg = get_returned_expr(call);
59 if (arg && expr_equiv(arg, size_arg))
60 return idx;
62 FOR_EACH_PTR(call->args, arg) {
63 idx++;
64 if (expr_equiv(arg, size_arg))
65 return idx;
66 } END_FOR_EACH_PTR(arg);
68 return NOBUF;
71 static void match_call(struct expression *call)
73 struct expression *arg;
74 char *name;
75 int buf_nr;
76 int i = -1;
78 if (call->fn->type != EXPR_SYMBOL)
79 return;
81 name = expr_to_var(call->fn);
82 FOR_EACH_PTR(call->args, arg) {
83 i++;
84 if (arg->type != EXPR_SIZEOF)
85 continue;
86 buf_nr = get_buf_number(call, arg);
87 if (buf_nr == NOBUF)
88 sm_msg("info: sizeof_param '%s' %d", name, i);
89 else
90 sm_msg("info: sizeof_param '%s' %d %d", name, i, buf_nr);
91 } END_FOR_EACH_PTR(arg);
92 free_string(name);
95 void check_passes_sizeof(int id)
97 if (!option_info)
98 return;
100 my_id = id;
101 add_hook(&match_call, FUNCTION_CALL_HOOK);