@@ -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
@@ -634,7 +638,7 @@ exprt interpretert::get_value(
634
638
error () << " interpreter: invalid pointer " << rhs[integer2size_t (offset)]
635
639
<< " > object count " << memory.size () << eom;
636
640
637
- throw " interpreter: reading from invalid pointer" ;
641
+ throw interpreter_errort ( " interpreter: reading from invalid pointer" ) ;
638
642
}
639
643
else if (real_type.id ()==ID_string)
640
644
{
@@ -724,15 +728,15 @@ void interpretert::assign(
724
728
void interpretert::execute_assume ()
725
729
{
726
730
if (!evaluate_boolean (pc->guard ))
727
- throw " assumption failed" ;
731
+ throw interpreter_errort ( " assumption failed" ) ;
728
732
}
729
733
730
734
void interpretert::execute_assert ()
731
735
{
732
736
if (!evaluate_boolean (pc->guard ))
733
737
{
734
738
if ((target_assert==pc) || stop_on_assertion)
735
- throw " program assertion reached" ;
739
+ throw interpreter_errort ( " program assertion reached" ) ;
736
740
else if (show)
737
741
error () << " assertion failed at " << pc->location_number
738
742
<< " \n " << eom;
@@ -748,9 +752,9 @@ void interpretert::execute_function_call()
748
752
mp_integer address=evaluate_address (function_call.function ());
749
753
750
754
if (address==0 )
751
- throw " function call to NULL" ;
755
+ throw interpreter_errort ( " function call to NULL" ) ;
752
756
else if (address>=memory.size ())
753
- throw " out-of-range function call" ;
757
+ throw interpreter_errort ( " out-of-range function call" ) ;
754
758
755
759
// Retrieve the empty last trace step struct we pushed for this step
756
760
// of the interpreter run to fill it with the corresponding data
@@ -764,8 +768,8 @@ void interpretert::execute_function_call()
764
768
const goto_functionst::function_mapt::const_iterator f_it=
765
769
goto_functions.function_map .find (identifier);
766
770
767
- if (f_it== goto_functions.function_map .end ())
768
- throw " failed to find function " + id2string (identifier );
771
+ INVARIANT (f_it != goto_functions.function_map .end (),
772
+ " FIXME I don't think this can happen if we have a typechecking phase before this? " );
769
773
770
774
// return value
771
775
mp_integer return_value_address;
@@ -810,8 +814,8 @@ void interpretert::execute_function_call()
810
814
const code_typet::parameterst ¶meters=
811
815
to_code_type (f_it->second .type ).parameters ();
812
816
813
- if (argument_values.size ()< parameters.size ())
814
- throw " not enough arguments " ;
817
+ INVARIANT (argument_values.size () != parameters.size (),
818
+ " FIXME I don't think this can happen if we have a typechecking phase before this? " ) ;
815
819
816
820
for (std::size_t i=0 ; i<parameters.size (); i++)
817
821
{
@@ -1085,3 +1089,11 @@ void interpreter(
1085
1089
message_handler);
1086
1090
interpreter ();
1087
1091
}
1092
+
1093
+ interpreter_errort::interpreter_errort (std::string message)
1094
+ : message(message)
1095
+ {}
1096
+
1097
+ std::string interpreter_errort::what () const noexcept {
1098
+ return message;
1099
+ }
0 commit comments