2 * sparse/smatch_struct_assignment.c
4 * Copyright (C) 2014 Oracle.
6 * Licensed under the Open Software License version 1.1
12 #include "smatch_slist.h"
13 #include "smatch_extra.h"
15 static struct symbol
*get_struct_type(struct expression
*expr
)
19 type
= get_type(expr
);
22 if (type
->type
== SYM_PTR
)
23 type
= get_real_base_type(type
);
24 if (type
&& type
->type
== SYM_STRUCT
)
29 static int known_struct_member_states(struct expression
*expr
)
31 struct state_list
*slist
= __get_cur_slist();
38 if (expr
->type
== EXPR_PREOP
&& expr
->op
== '&')
39 expr
= strip_expr(expr
->unop
);
41 name
= expr_to_var(expr
);
46 FOR_EACH_PTR(slist
, sm
) {
47 if (sm
->owner
!= SMATCH_EXTRA
)
49 cmp
= strncmp(sm
->name
, name
, len
);
53 if (sm
->name
[len
] == '.' ||
54 sm
->name
[len
] == '-' ||
55 sm
->name
[len
] == '.') {
62 } END_FOR_EACH_PTR(sm
);
68 static struct expression
*get_matching_member_expr(struct symbol
*left_type
, struct expression
*right
, struct symbol
*left_member
)
70 struct symbol
*struct_type
;
73 if (!left_member
->ident
)
76 struct_type
= get_struct_type(right
);
79 if (struct_type
!= left_type
)
82 if (right
->type
== EXPR_PREOP
&& right
->op
== '&')
83 right
= strip_expr(right
->unop
);
85 if (is_pointer(right
)) {
86 right
= deref_expression(right
);
90 return member_expression(right
, op
, left_member
->ident
);
93 void __struct_members_copy(int mode
, struct expression
*left
, struct expression
*right
)
95 struct symbol
*struct_type
, *tmp
, *type
;
96 struct expression
*left_member
, *right_member
, *assign
;
100 if (__in_fake_assign
)
103 left
= strip_expr(left
);
104 right
= strip_expr(right
);
106 struct_type
= get_struct_type(left
);
110 if (is_pointer(left
)) {
111 left
= deref_expression(left
);
115 FOR_EACH_PTR(struct_type
->symbol_list
, tmp
) {
116 type
= get_real_base_type(tmp
);
117 if (type
&& type
->type
== SYM_ARRAY
)
120 left_member
= member_expression(left
, op
, tmp
->ident
);
125 right_member
= get_matching_member_expr(struct_type
, right
, tmp
);
128 right_member
= right
;
132 right_member
= unknown_value_expression(left_member
);
133 assign
= assign_expression(left_member
, right_member
);
135 __split_expr(assign
);
137 } END_FOR_EACH_PTR(tmp
);
140 void __fake_struct_member_assignments(struct expression
*expr
)
142 __struct_members_copy(COPY_NORMAL
, expr
->left
, expr
->right
);
145 static struct expression
*remove_addr(struct expression
*expr
)
147 expr
= strip_expr(expr
);
149 if (expr
->type
== EXPR_PREOP
&& expr
->op
== '&')
150 return strip_expr(expr
->unop
);
154 static void match_memset(const char *fn
, struct expression
*expr
, void *_size_arg
)
156 struct expression
*buf
;
157 struct expression
*val
;
159 buf
= get_argument_from_call_expr(expr
->args
, 0);
160 val
= get_argument_from_call_expr(expr
->args
, 1);
162 buf
= strip_expr(buf
);
163 __struct_members_copy(COPY_MEMSET
, remove_addr(buf
), val
);
166 static void match_memcpy(const char *fn
, struct expression
*expr
, void *_arg
)
168 struct expression
*dest
;
169 struct expression
*src
;
171 dest
= get_argument_from_call_expr(expr
->args
, 0);
172 src
= get_argument_from_call_expr(expr
->args
, 1);
174 __struct_members_copy(COPY_MEMCPY
, remove_addr(dest
), remove_addr(src
));
177 static void match_memcpy_unknown(const char *fn
, struct expression
*expr
, void *_arg
)
179 struct expression
*dest
;
181 dest
= get_argument_from_call_expr(expr
->args
, 0);
182 __struct_members_copy(COPY_MEMCPY
, remove_addr(dest
), NULL
);
185 static void register_clears_param(void)
189 const char *function
;
192 if (option_project
== PROJ_NONE
)
195 snprintf(name
, 256, "%s.clears_argument", option_project_str
);
197 token
= get_tokens_file(name
);
200 if (token_type(token
) != TOKEN_STREAMBEGIN
)
203 while (token_type(token
) != TOKEN_STREAMEND
) {
204 if (token_type(token
) != TOKEN_IDENT
)
206 function
= show_ident(token
->ident
);
208 if (token_type(token
) != TOKEN_NUMBER
)
210 param
= atoi(token
->number
);
211 add_function_hook(function
, &match_memcpy_unknown
, INT_PTR(param
));
217 void register_struct_assignment(int id
)
219 add_function_hook("memset", &match_memset
, NULL
);
221 add_function_hook("memcpy", &match_memcpy
, INT_PTR(0));
222 add_function_hook("memmove", &match_memcpy
, INT_PTR(0));
224 register_clears_param();