@@ -15,8 +15,9 @@ Author: Daniel Kroening, kroening@kroening.com
1515#include < memory>
1616#include < sstream>
1717
18- #include < util/std_expr .h>
18+ #include < util/invariant .h>
1919#include < util/std_code.h>
20+ #include < util/std_expr.h>
2021
2122#include " is_threaded.h"
2223
@@ -50,7 +51,7 @@ void ai_baset::output(
5051 out << " **** " << i_it->location_number << " "
5152 << i_it->source_location << " \n " ;
5253
53- find_state (i_it). output (out, *this , ns);
54+ abstract_state_before (i_it)-> output (out, *this , ns);
5455 out << " \n " ;
5556 #if 1
5657 goto_program.output_instruction (ns, identifier, out, *i_it);
@@ -101,7 +102,8 @@ jsont ai_baset::output_json(
101102 json_numbert (std::to_string (i_it->location_number ));
102103 location[" sourceLocation" ]=
103104 json_stringt (i_it->source_location .as_string ());
104- location[" abstractState" ]=find_state (i_it).output_json (*this , ns);
105+ location[" abstractState" ] =
106+ abstract_state_before (i_it)->output_json (*this , ns);
105107
106108 // Ideally we need output_instruction_json
107109 std::ostringstream out;
@@ -162,7 +164,7 @@ xmlt ai_baset::output_xml(
162164 " source_location" ,
163165 i_it->source_location .as_string ());
164166
165- location.new_element (find_state (i_it). output_xml (*this , ns));
167+ location.new_element (abstract_state_before (i_it)-> output_xml (*this , ns));
166168
167169 // Ideally we need output_instruction_xml
168170 std::ostringstream out;
@@ -219,7 +221,7 @@ void ai_baset::finalize()
219221ai_baset::locationt ai_baset::get_next (
220222 working_sett &working_set)
221223{
222- assert (!working_set.empty ());
224+ PRECONDITION (!working_set.empty ());
223225
224226 working_sett::iterator i=working_set.begin ();
225227 locationt l=i->second ;
@@ -247,6 +249,7 @@ bool ai_baset::fixedpoint(
247249 {
248250 locationt l=get_next (working_set);
249251
252+ // goto_program is really only needed for iterator manipulation
250253 if (visit (l, working_set, goto_program, goto_functions, ns))
251254 new_data=true ;
252255 }
@@ -322,6 +325,8 @@ bool ai_baset::do_function_call(
322325 // initialize state, if necessary
323326 get_state (l_return);
324327
328+ PRECONDITION (l_call->is_function_call ());
329+
325330 const goto_functionst::goto_functiont &goto_function=
326331 f_it->second ;
327332
@@ -387,69 +392,27 @@ bool ai_baset::do_function_call_rec(
387392 const goto_functionst &goto_functions,
388393 const namespacet &ns)
389394{
390- assert (!goto_functions.function_map .empty ());
395+ PRECONDITION (!goto_functions.function_map .empty ());
396+
397+ // This is quite a strong assumption on the well-formedness of the program.
398+ // It means function pointers must be removed before use.
399+ DATA_INVARIANT (
400+ function.id () == ID_symbol,
401+ " Function pointers and indirect calls must be removed before analysis." );
391402
392403 bool new_data=false ;
393404
394- if (function.id ()==ID_symbol)
395- {
396- const irep_idt &identifier = to_symbol_expr (function).get_identifier ();
405+ const irep_idt &identifier = to_symbol_expr (function).get_identifier ();
397406
398- goto_functionst::function_mapt::const_iterator it=
399- goto_functions.function_map .find (identifier);
407+ goto_functionst::function_mapt::const_iterator it =
408+ goto_functions.function_map .find (identifier);
400409
401- if (it==goto_functions.function_map .end ())
402- throw " failed to find function " +id2string (identifier);
410+ DATA_INVARIANT (
411+ it != goto_functions.function_map .end (),
412+ " Function " + id2string (identifier) + " not in function map" );
403413
404- new_data=do_function_call (
405- l_call, l_return,
406- goto_functions,
407- it,
408- arguments,
409- ns);
410- }
411- else if (function.id ()==ID_if)
412- {
413- if (function.operands ().size ()!=3 )
414- throw " if has three operands" ;
415-
416- bool new_data1=
417- do_function_call_rec (
418- l_call, l_return,
419- function.op1 (),
420- arguments,
421- goto_functions,
422- ns);
423-
424- bool new_data2=
425- do_function_call_rec (
426- l_call, l_return,
427- function.op2 (),
428- arguments,
429- goto_functions,
430- ns);
431-
432- if (new_data1 || new_data2)
433- new_data=true ;
434- }
435- else if (function.id ()==ID_dereference)
436- {
437- // We can't really do this here -- we rely on
438- // these being removed by some previous analysis.
439- }
440- else if (function.id () == ID_null_object)
441- {
442- // ignore, can't be a function
443- }
444- else if (function.id ()==ID_member || function.id ()==ID_index)
445- {
446- // ignore, can't be a function
447- }
448- else
449- {
450- throw " unexpected function_call argument: " +
451- function.id_string ();
452- }
414+ new_data =
415+ do_function_call (l_call, l_return, goto_functions, it, arguments, ns);
453416
454417 return new_data;
455418}
0 commit comments