19
19
#include < util/pointer_offset_size.h>
20
20
#include < util/source_location.h>
21
21
#include < util/std_expr.h>
22
+ #include < util/string_utils.h>
22
23
23
24
#include < analyses/does_remove_const.h>
24
25
@@ -43,24 +44,8 @@ class remove_function_pointerst
43
44
goto_programt &goto_program,
44
45
const irep_idt &function_id);
45
46
46
- // a set of function symbols
47
- using functionst = remove_const_function_pointerst::functionst;
48
-
49
- // / Replace a call to a dynamic function at location
50
- // / target in the given goto-program by a case-split
51
- // / over a given set of functions
52
- // / \param goto_program: The goto program that contains target
53
- // / \param function_id: Name of function containing the target
54
- // / \param target: location with function call with function pointer
55
- // / \param functions: The set of functions to consider
56
- void remove_function_pointer (
57
- goto_programt &goto_program,
58
- const irep_idt &function_id,
59
- goto_programt::targett target,
60
- const functionst &functions);
61
-
62
47
protected:
63
- messaget log ;
48
+ message_handlert &message_handler ;
64
49
const namespacet ns;
65
50
symbol_tablet &symbol_table;
66
51
bool add_safety_assertion;
@@ -88,21 +73,6 @@ class remove_function_pointerst
88
73
89
74
typedef std::map<irep_idt, code_typet> type_mapt;
90
75
type_mapt type_map;
91
-
92
- bool is_type_compatible (
93
- bool return_value_used,
94
- const code_typet &call_type,
95
- const code_typet &function_type);
96
-
97
- bool arg_is_type_compatible (
98
- const typet &call_type,
99
- const typet &function_type);
100
-
101
- void fix_argument_types (code_function_callt &function_call);
102
- void fix_return_type (
103
- const irep_idt &in_function_id,
104
- code_function_callt &function_call,
105
- goto_programt &dest);
106
76
};
107
77
108
78
remove_function_pointerst::remove_function_pointerst (
@@ -111,7 +81,7 @@ remove_function_pointerst::remove_function_pointerst(
111
81
bool _add_safety_assertion,
112
82
bool only_resolve_const_fps,
113
83
const goto_functionst &goto_functions)
114
- : log (_message_handler),
84
+ : message_handler (_message_handler),
115
85
ns(_symbol_table),
116
86
symbol_table(_symbol_table),
117
87
add_safety_assertion(_add_safety_assertion),
@@ -130,9 +100,10 @@ remove_function_pointerst::remove_function_pointerst(
130
100
}
131
101
}
132
102
133
- bool remove_function_pointerst:: arg_is_type_compatible (
103
+ static bool arg_is_type_compatible (
134
104
const typet &call_type,
135
- const typet &function_type)
105
+ const typet &function_type,
106
+ const namespacet &ns)
136
107
{
137
108
if (call_type == function_type)
138
109
return true ;
@@ -156,10 +127,11 @@ bool remove_function_pointerst::arg_is_type_compatible(
156
127
pointer_offset_bits (function_type, ns);
157
128
}
158
129
159
- bool remove_function_pointerst::is_type_compatible (
130
+ bool function_is_type_convertable (
160
131
bool return_value_used,
161
132
const code_typet &call_type,
162
- const code_typet &function_type)
133
+ const code_typet &function_type,
134
+ const namespacet &ns)
163
135
{
164
136
// we are willing to ignore anything that's returned
165
137
// if we call with 'void'
@@ -172,8 +144,8 @@ bool remove_function_pointerst::is_type_compatible(
172
144
}
173
145
else
174
146
{
175
- if (!arg_is_type_compatible (call_type. return_type (),
176
- function_type.return_type ()))
147
+ if (!arg_is_type_compatible (
148
+ call_type. return_type (), function_type.return_type (), ns ))
177
149
return false ;
178
150
}
179
151
@@ -198,16 +170,15 @@ bool remove_function_pointerst::is_type_compatible(
198
170
return false ;
199
171
200
172
for (std::size_t i=0 ; i<call_parameters.size (); i++)
201
- if (!arg_is_type_compatible (call_parameters[i]. type (),
202
- function_parameters[i].type ()))
173
+ if (!arg_is_type_compatible (
174
+ call_parameters[i]. type (), function_parameters[i].type (), ns ))
203
175
return false ;
204
176
}
205
177
206
178
return true ;
207
179
}
208
180
209
- void remove_function_pointerst::fix_argument_types (
210
- code_function_callt &function_call)
181
+ static void fix_argument_types (code_function_callt &function_call)
211
182
{
212
183
const code_typet &code_type = to_code_type (function_call.function ().type ());
213
184
@@ -230,9 +201,10 @@ void remove_function_pointerst::fix_argument_types(
230
201
}
231
202
}
232
203
233
- void remove_function_pointerst:: fix_return_type (
204
+ static void fix_return_type (
234
205
const irep_idt &in_function_id,
235
206
code_function_callt &function_call,
207
+ symbol_tablet &symbol_table,
236
208
goto_programt &dest)
237
209
{
238
210
// are we returning anything at all?
@@ -245,6 +217,7 @@ void remove_function_pointerst::fix_return_type(
245
217
if (function_call.lhs ().type () == code_type.return_type ())
246
218
return ;
247
219
220
+ const namespacet ns (symbol_table);
248
221
const symbolt &function_symbol =
249
222
ns.lookup (to_symbol_expr (function_call.function ()).get_identifier ());
250
223
@@ -292,6 +265,7 @@ void remove_function_pointerst::remove_function_pointer(
292
265
remove_const_function_pointerst::functionst functions;
293
266
does_remove_constt const_removal_check (goto_program, ns);
294
267
const auto does_remove_const = const_removal_check ();
268
+ messaget log {message_handler};
295
269
if (does_remove_const.first )
296
270
{
297
271
log .warning ().source_location = does_remove_const.second ;
@@ -344,7 +318,8 @@ void remove_function_pointerst::remove_function_pointer(
344
318
continue ;
345
319
346
320
// type-compatible?
347
- if (!is_type_compatible (return_value_used, call_type, t.second ))
321
+ if (!function_is_type_convertable (
322
+ return_value_used, call_type, t.second , ns))
348
323
continue ;
349
324
350
325
if (t.first ==" pthread_mutex_cleanup" )
@@ -355,14 +330,56 @@ void remove_function_pointerst::remove_function_pointer(
355
330
}
356
331
}
357
332
358
- remove_function_pointer (goto_program, function_id, target, functions);
333
+ ::remove_function_pointer (
334
+ message_handler,
335
+ symbol_table,
336
+ goto_program,
337
+ function_id,
338
+ target,
339
+ functions,
340
+ add_safety_assertion);
359
341
}
360
342
361
- void remove_function_pointerst::remove_function_pointer (
343
+ static std::string function_pointer_assertion_comment (
344
+ const std::unordered_set<symbol_exprt, irep_hash> &candidates)
345
+ {
346
+ std::stringstream comment;
347
+
348
+ comment << " dereferenced function pointer at must be " ;
349
+
350
+ if (candidates.size () == 1 )
351
+ {
352
+ comment << candidates.begin ()->get_identifier ();
353
+ }
354
+ else if (candidates.empty ())
355
+ {
356
+ comment.str (" no candidates for dereferenced function pointer" );
357
+ }
358
+ else
359
+ {
360
+ comment << " one of [" ;
361
+
362
+ join_strings (
363
+ comment,
364
+ candidates.begin (),
365
+ candidates.end (),
366
+ " , " ,
367
+ [](const symbol_exprt &s) { return s.get_identifier (); });
368
+
369
+ comment << ' ]' ;
370
+ }
371
+
372
+ return comment.str ();
373
+ }
374
+
375
+ void remove_function_pointer (
376
+ message_handlert &message_handler,
377
+ symbol_tablet &symbol_table,
362
378
goto_programt &goto_program,
363
379
const irep_idt &function_id,
364
380
goto_programt::targett target,
365
- const functionst &functions)
381
+ const std::unordered_set<symbol_exprt, irep_hash> &functions,
382
+ const bool add_safety_assertion)
366
383
{
367
384
const exprt &function = target->call_function ();
368
385
const exprt &pointer = to_dereference_expr (function).pointer ();
@@ -387,7 +404,7 @@ void remove_function_pointerst::remove_function_pointer(
387
404
fix_argument_types (new_call);
388
405
389
406
goto_programt tmp;
390
- fix_return_type (function_id, new_call, tmp);
407
+ fix_return_type (function_id, new_call, symbol_table, tmp);
391
408
392
409
auto call = new_code_calls.add (goto_programt::make_function_call (new_call));
393
410
new_code_calls.destructive_append (tmp);
@@ -411,7 +428,8 @@ void remove_function_pointerst::remove_function_pointer(
411
428
goto_programt::targett t =
412
429
new_code_gotos.add (goto_programt::make_assertion (false_exprt ()));
413
430
t->source_location .set_property_class (" pointer dereference" );
414
- t->source_location .set_comment (" invalid function pointer" );
431
+ t->source_location .set_comment (
432
+ function_pointer_assertion_comment (functions));
415
433
}
416
434
new_code_gotos.add (goto_programt::make_assumption (false_exprt ()));
417
435
@@ -449,6 +467,7 @@ void remove_function_pointerst::remove_function_pointer(
449
467
target->type =OTHER;
450
468
451
469
// report statistics
470
+ messaget log {message_handler};
452
471
log .statistics ().source_location = target->source_location ;
453
472
log .statistics () << " replacing function pointer by " << functions.size ()
454
473
<< " possible targets" << messaget::eom;
0 commit comments