@@ -69,12 +69,12 @@ void interpretert::initialize(bool init)
69
69
main_it=goto_functions.function_map .find (goto_functionst::entry_point ());
70
70
71
71
if (main_it==goto_functions.function_map .end ())
72
- throw " main not found" ;
72
+ throw interpreter_errort ( " main not found" ) ;
73
73
74
74
const goto_functionst::goto_functiont &goto_function=main_it->second ;
75
75
76
76
if (!goto_function.body_available ())
77
- throw " main has no body" ;
77
+ throw interpreter_errort ( " main has no body" ) ;
78
78
79
79
pc=goto_function.body .instructions .begin ();
80
80
function=main_it;
@@ -291,8 +291,11 @@ void interpretert::step()
291
291
292
292
case RETURN:
293
293
trace_step.type =goto_trace_stept::typet::FUNCTION_RETURN;
294
- if (call_stack.empty ())
295
- throw " RETURN without call" ; // NOLINT(readability/throw)
294
+ if (call_stack.empty ()) {
295
+ // FIXME I left this as an exception because I think this
296
+ // could happen if fed with a broken goto program?
297
+ throw interpreter_errort (" RETURN without call" ); // NOLINT(readability/throw)
298
+ }
296
299
297
300
if (pc->code .operands ().size ()==1 &&
298
301
call_stack.top ().return_value_address !=0 )
@@ -317,19 +320,20 @@ void interpretert::step()
317
320
318
321
case START_THREAD:
319
322
trace_step.type =goto_trace_stept::typet::SPAWN;
320
- throw " START_THREAD not yet implemented" ; // NOLINT(readability/throw)
323
+ // Could be triggered by wrong input, therefore throw?
324
+ throw interpreter_errort (" START_THREAD not yet implemented" ); // NOLINT(readability/throw)
321
325
322
326
case END_THREAD:
323
- throw " END_THREAD not yet implemented" ; // NOLINT(readability/throw)
327
+ throw interpreter_errort ( " END_THREAD not yet implemented" ) ; // NOLINT(readability/throw)
324
328
break ;
325
329
326
330
case ATOMIC_BEGIN:
327
331
trace_step.type =goto_trace_stept::typet::ATOMIC_BEGIN;
328
- throw " ATOMIC_BEGIN not yet implemented" ; // NOLINT(readability/throw)
332
+ throw interpreter_errort ( " ATOMIC_BEGIN not yet implemented" ) ; // NOLINT(readability/throw)
329
333
330
334
case ATOMIC_END:
331
335
trace_step.type =goto_trace_stept::typet::ATOMIC_END;
332
- throw " ATOMIC_END not yet implemented" ; // NOLINT(readability/throw)
336
+ throw interpreter_errort ( " ATOMIC_END not yet implemented" ) ; // NOLINT(readability/throw)
333
337
334
338
case DEAD:
335
339
trace_step.type =goto_trace_stept::typet::DEAD;
@@ -359,7 +363,7 @@ void interpretert::step()
359
363
case CATCH:
360
364
break ;
361
365
default :
362
- throw " encountered instruction with undefined instruction type " ;
366
+ UNREACHABLE; // I'm assuming we'd catch such a thing before this point
363
367
}
364
368
pc=next_pc;
365
369
}
@@ -369,11 +373,8 @@ void interpretert::execute_goto()
369
373
{
370
374
if (evaluate_boolean (pc->guard ))
371
375
{
372
- if (pc->targets .empty ())
373
- throw " taken goto without target" ;
374
-
375
- if (pc->targets .size ()>=2 )
376
- throw " non-deterministic goto encountered" ;
376
+ DATA_INVARIANT (pc->targets .size () == 1 ,
377
+ " a goto should have exactly one target location" );
377
378
378
379
next_pc=pc->targets .front ();
379
380
}
@@ -383,6 +384,10 @@ void interpretert::execute_goto()
383
384
void interpretert::execute_other ()
384
385
{
385
386
const irep_idt &statement=pc->code .get_statement ();
387
+ PRECONDITION (statement == ID_expression
388
+ || statement == ID_array_set
389
+ || statement == ID_output);
390
+
386
391
if (statement==ID_expression)
387
392
{
388
393
DATA_INVARIANT (
@@ -410,8 +415,6 @@ void interpretert::execute_other()
410
415
{
411
416
return ;
412
417
}
413
- else
414
- throw " unexpected OTHER statement: " +id2string (statement);
415
418
}
416
419
417
420
void interpretert::execute_decl ()
@@ -427,8 +430,7 @@ struct_typet::componentt interpretert::get_component(
427
430
{
428
431
const symbolt &symbol=ns.lookup (object);
429
432
const typet real_type=ns.follow (symbol.type );
430
- if (real_type.id ()!=ID_struct)
431
- throw " request for member of non-struct" ;
433
+ PRECONDITION (real_type.id () == ID_struct);
432
434
433
435
const struct_typet &struct_type=to_struct_type (real_type);
434
436
const struct_typet::componentst &components=struct_type.components ();
@@ -443,7 +445,9 @@ struct_typet::componentt interpretert::get_component(
443
445
tmp_offset-=get_size (c.type ());
444
446
}
445
447
446
- throw " access out of struct bounds" ;
448
+ // FIXME not sure if its possible to catch this in advance
449
+ // so I've left it as an exception for now
450
+ throw interpreter_errort (" access out of struct bounds" );
447
451
}
448
452
449
453
// / returns the type object corresponding to id
@@ -639,7 +643,7 @@ exprt interpretert::get_value(
639
643
error () << " interpreter: invalid pointer " << rhs[integer2size_t (offset)]
640
644
<< " > object count " << memory.size () << eom;
641
645
642
- throw " interpreter: reading from invalid pointer" ;
646
+ throw interpreter_errort ( " interpreter: reading from invalid pointer" ) ;
643
647
}
644
648
else if (real_type.id ()==ID_string)
645
649
{
@@ -729,15 +733,15 @@ void interpretert::assign(
729
733
void interpretert::execute_assume ()
730
734
{
731
735
if (!evaluate_boolean (pc->guard ))
732
- throw " assumption failed" ;
736
+ throw interpreter_errort ( " assumption failed" ) ;
733
737
}
734
738
735
739
void interpretert::execute_assert ()
736
740
{
737
741
if (!evaluate_boolean (pc->guard ))
738
742
{
739
743
if ((target_assert==pc) || stop_on_assertion)
740
- throw " program assertion reached" ;
744
+ throw interpreter_errort ( " program assertion reached" ) ;
741
745
else if (show)
742
746
error () << " assertion failed at " << pc->location_number
743
747
<< " \n " << eom;
@@ -753,9 +757,9 @@ void interpretert::execute_function_call()
753
757
mp_integer address=evaluate_address (function_call.function ());
754
758
755
759
if (address==0 )
756
- throw " function call to NULL" ;
760
+ throw interpreter_errort ( " function call to NULL" ) ;
757
761
else if (address>=memory.size ())
758
- throw " out-of-range function call" ;
762
+ throw interpreter_errort ( " out-of-range function call" ) ;
759
763
760
764
// Retrieve the empty last trace step struct we pushed for this step
761
765
// of the interpreter run to fill it with the corresponding data
@@ -769,8 +773,8 @@ void interpretert::execute_function_call()
769
773
const goto_functionst::function_mapt::const_iterator f_it=
770
774
goto_functions.function_map .find (identifier);
771
775
772
- if (f_it== goto_functions.function_map .end ())
773
- throw " failed to find function " + id2string (identifier );
776
+ INVARIANT (f_it != goto_functions.function_map .end (),
777
+ " FIXME I don't think this can happen if we have a typechecking phase before this? " );
774
778
775
779
// return value
776
780
mp_integer return_value_address;
@@ -815,8 +819,8 @@ void interpretert::execute_function_call()
815
819
const code_typet::parameterst ¶meters=
816
820
to_code_type (f_it->second .type ).parameters ();
817
821
818
- if (argument_values.size ()< parameters.size ())
819
- throw " not enough arguments " ;
822
+ INVARIANT (argument_values.size () != parameters.size (),
823
+ " FIXME I don't think this can happen if we have a typechecking phase before this? " ) ;
820
824
821
825
for (std::size_t i=0 ; i<parameters.size (); i++)
822
826
{
@@ -1090,3 +1094,11 @@ void interpreter(
1090
1094
message_handler);
1091
1095
interpreter ();
1092
1096
}
1097
+
1098
+ interpreter_errort::interpreter_errort (std::string message)
1099
+ : message(message)
1100
+ {}
1101
+
1102
+ std::string interpreter_errort::what () const noexcept {
1103
+ return message;
1104
+ }
0 commit comments