db: improve database debugging
[smatch.git] / check_sizeof.c
blob301dcf54dc0570b5089a7d17fef264ad1aba8b17
1 /*
2 * smatch/check_sizeof.c
4 * Copyright (C) 2012 Oracle.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include "smatch.h"
12 static int my_id;
14 static void check_pointer(struct expression *expr, char *ptr_name)
16 char *name;
17 sval_t sval;
19 if (!expr || expr->type != EXPR_SIZEOF)
20 return;
22 get_value(expr, &sval);
24 expr = strip_expr(expr->cast_expression);
25 name = expr_to_str(expr);
26 if (!name)
27 return;
29 if (strcmp(ptr_name, name) == 0)
30 sm_msg("warn: was 'sizeof(*%s)' intended?", ptr_name);
31 free_string(name);
34 static void match_call_assignment(struct expression *expr)
36 struct expression *call = strip_expr(expr->right);
37 struct expression *arg;
38 char *ptr_name;
40 if (!is_pointer(expr->left))
41 return;
43 ptr_name = expr_to_str(expr->left);
44 if (!ptr_name)
45 return;
47 FOR_EACH_PTR(call->args, arg) {
48 check_pointer(arg, ptr_name);
49 } END_FOR_EACH_PTR(arg);
51 free_string(ptr_name);
54 static void check_passes_pointer(char *name, struct expression *call)
56 struct expression *arg;
57 char *ptr_name;
59 FOR_EACH_PTR(call->args, arg) {
60 ptr_name = expr_to_var(arg);
61 if (!ptr_name)
62 continue;
63 if (strcmp(name, ptr_name) == 0)
64 sm_msg("warn: was 'sizeof(*%s)' intended?", name);
65 free_string(ptr_name);
66 } END_FOR_EACH_PTR(arg);
69 static void match_check_params(struct expression *call)
71 struct expression *arg;
72 struct expression *obj;
73 char *name;
75 FOR_EACH_PTR(call->args, arg) {
76 if (arg->type != EXPR_SIZEOF)
77 continue;
78 obj = strip_expr(arg->cast_expression);
79 if (!is_pointer(obj))
80 continue;
81 name = expr_to_var(obj);
82 if (!name)
83 continue;
84 check_passes_pointer(name, call);
85 free_string(name);
86 } END_FOR_EACH_PTR(arg);
89 static struct string_list *macro_takes_sizeof_argument;
90 static void check_sizeof_number(struct expression *expr)
92 char *macro, *tmp;
94 if (expr->type != EXPR_VALUE)
95 return;
96 macro = get_macro_name(expr->pos);
97 FOR_EACH_PTR(macro_takes_sizeof_argument, tmp) {
98 if (macro && strcmp(tmp, macro) == 0)
99 return;
100 } END_FOR_EACH_PTR(tmp);
102 sm_msg("warn: sizeof(NUMBER)?");
105 static void match_sizeof(struct expression *expr)
107 check_sizeof_number(expr);
108 if (expr->type == EXPR_PREOP && expr->op == '&')
109 sm_msg("warn: sizeof(&pointer)?");
110 if (expr->type == EXPR_SIZEOF)
111 sm_msg("warn: sizoef(sizeof())?");
112 /* the ilog2() macro is a valid place to check the size of a binop */
113 if (expr->type == EXPR_BINOP && !get_macro_name(expr->pos))
114 sm_msg("warn: taking sizeof binop");
117 static void register_macro_takes_sizeof_argument(void)
119 struct token *token;
120 char *macro;
121 char name[256];
123 snprintf(name, 256, "%s.macro_takes_sizeof_argument", option_project_str);
125 token = get_tokens_file(name);
126 if (!token)
127 return;
128 if (token_type(token) != TOKEN_STREAMBEGIN)
129 return;
130 token = token->next;
131 while (token_type(token) != TOKEN_STREAMEND) {
132 if (token_type(token) != TOKEN_IDENT)
133 return;
134 macro = alloc_string(show_ident(token->ident));
135 add_ptr_list(&macro_takes_sizeof_argument, macro);
136 token = token->next;
138 clear_token_alloc();
141 void check_sizeof(int id)
143 my_id = id;
145 register_macro_takes_sizeof_argument();
146 add_hook(&match_call_assignment, CALL_ASSIGNMENT_HOOK);
147 add_hook(&match_check_params, FUNCTION_CALL_HOOK);
148 add_hook(&match_sizeof, SIZEOF_HOOK);