Skip to content

Commit 8ea36da

Browse files
author
Daniel Kroening
authored
Merge pull request #747 from tautschnig/undefined-function-assume-false
goto-instrument: Replace calls to undefined functions by assume(false)
2 parents 69674f6 + 5875335 commit 8ea36da

14 files changed

+535
-9
lines changed

CHANGELOG

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
5.8
2+
===
3+
4+
* GOTO-INSTRUMENT: New option --list-calls-args
5+
* GOTO-INSTRUMENT: New option --print-path-lenghts
6+
* GOTO-ANALYZER: New option --unreachable-functions, --reachable-functions
7+
* GOTO-INSTRUMENT: New option --undefined-function-is-assume-false
8+
9+
110
5.7
211
===
312

src/goto-analyzer/goto_analyzer_parse_options.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,54 @@ int goto_analyzer_parse_optionst::doit()
265265
return 0;
266266
}
267267

268+
if(cmdline.isset("unreachable-functions"))
269+
{
270+
const std::string json_file=cmdline.get_value("json");
271+
272+
if(json_file.empty())
273+
unreachable_functions(goto_model, false, std::cout);
274+
else if(json_file=="-")
275+
unreachable_functions(goto_model, true, std::cout);
276+
else
277+
{
278+
std::ofstream ofs(json_file);
279+
if(!ofs)
280+
{
281+
error() << "Failed to open json output `"
282+
<< json_file << "'" << eom;
283+
return 6;
284+
}
285+
286+
unreachable_functions(goto_model, true, ofs);
287+
}
288+
289+
return 0;
290+
}
291+
292+
if(cmdline.isset("reachable-functions"))
293+
{
294+
const std::string json_file=cmdline.get_value("json");
295+
296+
if(json_file.empty())
297+
reachable_functions(goto_model, false, std::cout);
298+
else if(json_file=="-")
299+
reachable_functions(goto_model, true, std::cout);
300+
else
301+
{
302+
std::ofstream ofs(json_file);
303+
if(!ofs)
304+
{
305+
error() << "Failed to open json output `"
306+
<< json_file << "'" << eom;
307+
return 6;
308+
}
309+
310+
reachable_functions(goto_model, true, ofs);
311+
}
312+
313+
return 0;
314+
}
315+
268316
if(cmdline.isset("show-local-may-alias"))
269317
{
270318
namespacet ns(goto_model.symbol_table);
@@ -489,6 +537,10 @@ void goto_analyzer_parse_optionst::help()
489537
// NOLINTNEXTLINE(whitespace/line_length)
490538
" --taint file_name perform taint analysis using rules in given file\n"
491539
" --unreachable-instructions list dead code\n"
540+
// NOLINTNEXTLINE(whitespace/line_length)
541+
" --unreachable-functions list functions unreachable from the entry point\n"
542+
// NOLINTNEXTLINE(whitespace/line_length)
543+
" --reachable-functions list functions reachable from the entry point\n"
492544
" --intervals interval analysis\n"
493545
" --non-null non-null analysis\n"
494546
"\n"

src/goto-analyzer/goto_analyzer_parse_options.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ class optionst;
3636
"(taint):(show-taint)" \
3737
"(show-local-may-alias)" \
3838
"(json):(xml):" \
39-
"(unreachable-instructions)" \
39+
"(unreachable-instructions)(unreachable-functions)" \
40+
"(reachable-functions)" \
4041
"(intervals)(show-intervals)" \
4142
"(non-null)(show-non-null)"
4243

src/goto-analyzer/unreachable_instructions.cpp

Lines changed: 153 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,12 @@ void unreachable_instructions(
198198
const goto_programt &goto_program=f_it->second.body;
199199
dead_mapt dead_map;
200200

201-
if(called.find(f_it->first)!=called.end())
201+
const symbolt &decl=ns.lookup(f_it->first);
202+
203+
// f_it->first may be a link-time renamed version, use the
204+
// base_name instead; do not list inlined functions
205+
if(called.find(decl.base_name)!=called.end() ||
206+
f_it->second.is_inlined())
202207
unreachable_instructions(goto_program, dead_map);
203208
else
204209
all_unreachable(goto_program, dead_map);
@@ -215,3 +220,150 @@ void unreachable_instructions(
215220
if(json && !json_result.array.empty())
216221
os << json_result << std::endl;
217222
}
223+
224+
/*******************************************************************\
225+
226+
Function: json_output_function
227+
228+
Inputs:
229+
230+
Outputs:
231+
232+
Purpose:
233+
234+
\*******************************************************************/
235+
236+
static void json_output_function(
237+
const irep_idt &function,
238+
const source_locationt &first_location,
239+
const source_locationt &last_location,
240+
json_arrayt &dest)
241+
{
242+
json_objectt &entry=dest.push_back().make_object();
243+
244+
entry["function"]=json_stringt(id2string(function));
245+
entry["file name"]=
246+
json_stringt(concat_dir_file(
247+
id2string(first_location.get_working_directory()),
248+
id2string(first_location.get_file())));
249+
entry["first line"]=
250+
json_numbert(id2string(first_location.get_line()));
251+
entry["last line"]=
252+
json_numbert(id2string(last_location.get_line()));
253+
}
254+
255+
/*******************************************************************\
256+
257+
Function: list_functions
258+
259+
Inputs:
260+
261+
Outputs:
262+
263+
Purpose:
264+
265+
\*******************************************************************/
266+
267+
static void list_functions(
268+
const goto_modelt &goto_model,
269+
const bool json,
270+
std::ostream &os,
271+
bool unreachable)
272+
{
273+
json_arrayt json_result;
274+
275+
std::set<irep_idt> called;
276+
compute_called_functions(goto_model, called);
277+
278+
const namespacet ns(goto_model.symbol_table);
279+
280+
forall_goto_functions(f_it, goto_model.goto_functions)
281+
{
282+
const symbolt &decl=ns.lookup(f_it->first);
283+
284+
// f_it->first may be a link-time renamed version, use the
285+
// base_name instead; do not list inlined functions
286+
if(unreachable ==
287+
(called.find(decl.base_name)!=called.end() ||
288+
f_it->second.is_inlined()))
289+
continue;
290+
291+
source_locationt first_location=decl.location;
292+
293+
source_locationt last_location;
294+
if(f_it->second.body_available())
295+
{
296+
const goto_programt &goto_program=f_it->second.body;
297+
298+
goto_programt::const_targett end_function=
299+
goto_program.instructions.end();
300+
--end_function;
301+
assert(end_function->is_end_function());
302+
last_location=end_function->source_location;
303+
}
304+
else
305+
// completely ignore functions without a body, both for
306+
// reachable and unreachable functions; we could also restrict
307+
// this to macros/asm renaming
308+
continue;
309+
310+
if(!json)
311+
{
312+
os << concat_dir_file(
313+
id2string(first_location.get_working_directory()),
314+
id2string(first_location.get_file())) << " "
315+
<< decl.base_name << " "
316+
<< first_location.get_line() << " "
317+
<< last_location.get_line() << "\n";
318+
}
319+
else
320+
json_output_function(
321+
decl.base_name,
322+
first_location,
323+
last_location,
324+
json_result);
325+
}
326+
327+
if(json && !json_result.array.empty())
328+
os << json_result << std::endl;
329+
}
330+
331+
/*******************************************************************\
332+
333+
Function: unreachable_functions
334+
335+
Inputs:
336+
337+
Outputs:
338+
339+
Purpose:
340+
341+
\*******************************************************************/
342+
343+
void unreachable_functions(
344+
const goto_modelt &goto_model,
345+
const bool json,
346+
std::ostream &os)
347+
{
348+
list_functions(goto_model, json, os, true);
349+
}
350+
351+
/*******************************************************************\
352+
353+
Function: reachable_functions
354+
355+
Inputs:
356+
357+
Outputs:
358+
359+
Purpose:
360+
361+
\*******************************************************************/
362+
363+
void reachable_functions(
364+
const goto_modelt &goto_model,
365+
const bool json,
366+
std::ostream &os)
367+
{
368+
list_functions(goto_model, json, os, false);
369+
}

src/goto-analyzer/unreachable_instructions.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,14 @@ void unreachable_instructions(
2020
const bool json,
2121
std::ostream &os);
2222

23+
void unreachable_functions(
24+
const goto_modelt &,
25+
const bool json,
26+
std::ostream &os);
27+
28+
void reachable_functions(
29+
const goto_modelt &,
30+
const bool json,
31+
std::ostream &os);
32+
2333
#endif // CPROVER_GOTO_ANALYZER_UNREACHABLE_INSTRUCTIONS_H

src/goto-instrument/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ SRC = goto_instrument_parse_options.cpp rw_set.cpp \
2323
wmm/event_graph.cpp wmm/pair_collection.cpp \
2424
goto_instrument_main.cpp horn_encoding.cpp \
2525
thread_instrumentation.cpp skip_loops.cpp loop_utils.cpp \
26-
code_contracts.cpp cover.cpp model_argc_argv.cpp
26+
code_contracts.cpp cover.cpp model_argc_argv.cpp \
27+
undefined_functions.cpp
2728

2829
OBJ += ../ansi-c/ansi-c$(LIBEXT) \
2930
../cpp/cpp$(LIBEXT) \

src/goto-instrument/call_sequences.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Date: April 2013
1313
#include <unordered_set>
1414

1515
#include <util/std_expr.h>
16+
#include <util/simplify_expr.h>
1617

1718
#include "call_sequences.h"
1819

@@ -358,3 +359,83 @@ void check_call_sequence(const goto_functionst &goto_functions)
358359

359360
check_call_sequencet(goto_functions, sequence)();
360361
}
362+
363+
/*******************************************************************\
364+
365+
Function: list_calls_and_arguments
366+
367+
Inputs:
368+
369+
Outputs:
370+
371+
Purpose:
372+
373+
\*******************************************************************/
374+
375+
static void list_calls_and_arguments(
376+
const namespacet &ns,
377+
const irep_idt &function,
378+
const goto_programt &goto_program)
379+
{
380+
forall_goto_program_instructions(i_it, goto_program)
381+
{
382+
if(!i_it->is_function_call())
383+
continue;
384+
385+
const code_function_callt call=to_code_function_call(i_it->code);
386+
387+
const exprt &f=call.function();
388+
389+
if(f.id()!=ID_symbol)
390+
continue;
391+
392+
const irep_idt &identifier=to_symbol_expr(f).get_identifier();
393+
if(identifier=="__CPROVER_initialize")
394+
continue;
395+
396+
std::string name=from_expr(ns, identifier, f);
397+
std::string::size_type java_type_suffix=name.find(":(");
398+
if(java_type_suffix!=std::string::npos)
399+
name.erase(java_type_suffix);
400+
401+
std::cout << "found call to " << name;
402+
403+
if(!call.arguments().empty())
404+
{
405+
std::cout << " with arguments ";
406+
for(exprt::operandst::const_iterator
407+
it=call.arguments().begin();
408+
it!=call.arguments().end();
409+
++it)
410+
{
411+
if(it!=call.arguments().begin())
412+
std::cout << ", ";
413+
std::cout << from_expr(ns, identifier, simplify_expr(*it, ns));
414+
}
415+
}
416+
417+
std::cout << '\n';
418+
}
419+
}
420+
421+
/*******************************************************************\
422+
423+
Function: show_call_sequences
424+
425+
Inputs:
426+
427+
Outputs:
428+
429+
Purpose:
430+
431+
\*******************************************************************/
432+
433+
void list_calls_and_arguments(
434+
const namespacet &ns,
435+
const goto_functionst &goto_functions)
436+
{
437+
// do per function
438+
439+
forall_goto_functions(f_it, goto_functions)
440+
list_calls_and_arguments(ns, f_it->first, f_it->second.body);
441+
}

src/goto-instrument/call_sequences.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,8 @@ Date: September 2011
1616
void show_call_sequences(const goto_functionst &goto_functions);
1717
void check_call_sequence(const goto_functionst &goto_functions);
1818

19+
void list_calls_and_arguments(
20+
const namespacet &ns,
21+
const goto_functionst &goto_functions);
22+
1923
#endif // CPROVER_GOTO_INSTRUMENT_CALL_SEQUENCES_H

0 commit comments

Comments
 (0)