2 * smatch/check_sizeof.c
4 * Copyright (C) 2012 Oracle.
6 * Licensed under the Open Software License version 1.1
14 static void check_pointer(struct expression
*expr
, char *ptr_name
)
19 if (!expr
|| expr
->type
!= EXPR_SIZEOF
)
22 get_value(expr
, &sval
);
24 expr
= strip_expr(expr
->cast_expression
);
25 name
= expr_to_str(expr
);
29 if (strcmp(ptr_name
, name
) == 0)
30 sm_msg("warn: was 'sizeof(*%s)' intended?", ptr_name
);
34 static void match_call_assignment(struct expression
*expr
)
36 struct expression
*call
= strip_expr(expr
->right
);
37 struct expression
*arg
;
40 if (!is_pointer(expr
->left
))
43 ptr_name
= expr_to_str(expr
->left
);
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
;
59 FOR_EACH_PTR(call
->args
, arg
) {
60 ptr_name
= expr_to_var(arg
);
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
;
75 FOR_EACH_PTR(call
->args
, arg
) {
76 if (arg
->type
!= EXPR_SIZEOF
)
78 obj
= strip_expr(arg
->cast_expression
);
81 name
= expr_to_var(obj
);
84 check_passes_pointer(name
, call
);
86 } END_FOR_EACH_PTR(arg
);
89 static struct string_list
*macro_takes_sizeof_argument
;
90 static void check_sizeof_number(struct expression
*expr
)
94 if (expr
->type
!= EXPR_VALUE
)
96 macro
= get_macro_name(expr
->pos
);
97 FOR_EACH_PTR(macro_takes_sizeof_argument
, tmp
) {
98 if (macro
&& strcmp(tmp
, macro
) == 0)
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)
123 snprintf(name
, 256, "%s.macro_takes_sizeof_argument", option_project_str
);
125 token
= get_tokens_file(name
);
128 if (token_type(token
) != TOKEN_STREAMBEGIN
)
131 while (token_type(token
) != TOKEN_STREAMEND
) {
132 if (token_type(token
) != TOKEN_IDENT
)
134 macro
= alloc_string(show_ident(token
->ident
));
135 add_ptr_list(¯o_takes_sizeof_argument
, macro
);
141 void check_sizeof(int 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
);