@@ -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 analysis_exceptiont ( " 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 analysis_exceptiont ( " main has no body" ) ;
78
78
79
79
pc=goto_function.body .instructions .begin ();
80
80
function=main_it;
@@ -292,7 +292,10 @@ void interpretert::step()
292
292
case RETURN:
293
293
trace_step.type =goto_trace_stept::typet::FUNCTION_RETURN;
294
294
if (call_stack.empty ())
295
- throw " RETURN without call" ; // NOLINT(readability/throw)
295
+ {
296
+ throw analysis_exceptiont (
297
+ " 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,23 @@ 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
+ throw analysis_exceptiont (
324
+ " 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 analysis_exceptiont (
328
+ " END_THREAD not yet implemented" ); // NOLINT(readability/throw)
324
329
break ;
325
330
326
331
case ATOMIC_BEGIN:
327
332
trace_step.type =goto_trace_stept::typet::ATOMIC_BEGIN;
328
- throw " ATOMIC_BEGIN not yet implemented" ; // NOLINT(readability/throw)
333
+ throw analysis_exceptiont (
334
+ " ATOMIC_BEGIN not yet implemented" ); // NOLINT(readability/throw)
329
335
330
336
case ATOMIC_END:
331
337
trace_step.type =goto_trace_stept::typet::ATOMIC_END;
332
- throw " ATOMIC_END not yet implemented" ; // NOLINT(readability/throw)
338
+ throw analysis_exceptiont (
339
+ " ATOMIC_END not yet implemented" ); // NOLINT(readability/throw)
333
340
334
341
case DEAD:
335
342
trace_step.type =goto_trace_stept::typet::DEAD;
@@ -359,7 +366,7 @@ void interpretert::step()
359
366
case CATCH:
360
367
break ;
361
368
default :
362
- throw " encountered instruction with undefined instruction type " ;
369
+ UNREACHABLE; // I'm assuming we'd catch such a thing before this point
363
370
}
364
371
pc=next_pc;
365
372
}
@@ -369,11 +376,9 @@ void interpretert::execute_goto()
369
376
{
370
377
if (evaluate_boolean (pc->guard ))
371
378
{
372
- if (pc->targets .empty ())
373
- throw " taken goto without target" ;
374
-
375
- if (pc->targets .size ()>=2 )
376
- throw " non-deterministic goto encountered" ;
379
+ DATA_INVARIANT (
380
+ pc->targets .size () == 1 ,
381
+ " a goto should have exactly one target location" );
377
382
378
383
next_pc=pc->targets .front ();
379
384
}
@@ -383,6 +388,10 @@ void interpretert::execute_goto()
383
388
void interpretert::execute_other ()
384
389
{
385
390
const irep_idt &statement=pc->code .get_statement ();
391
+ PRECONDITION (
392
+ statement == ID_expression || statement == ID_array_set ||
393
+ statement == ID_output);
394
+
386
395
if (statement==ID_expression)
387
396
{
388
397
DATA_INVARIANT (
@@ -410,8 +419,6 @@ void interpretert::execute_other()
410
419
{
411
420
return ;
412
421
}
413
- else
414
- throw " unexpected OTHER statement: " +id2string (statement);
415
422
}
416
423
417
424
void interpretert::execute_decl ()
@@ -427,8 +434,7 @@ struct_typet::componentt interpretert::get_component(
427
434
{
428
435
const symbolt &symbol=ns.lookup (object);
429
436
const typet real_type=ns.follow (symbol.type );
430
- if (real_type.id ()!=ID_struct)
431
- throw " request for member of non-struct" ;
437
+ PRECONDITION (real_type.id () == ID_struct);
432
438
433
439
const struct_typet &struct_type=to_struct_type (real_type);
434
440
const struct_typet::componentst &components=struct_type.components ();
@@ -443,7 +449,7 @@ struct_typet::componentt interpretert::get_component(
443
449
tmp_offset-=get_size (c.type ());
444
450
}
445
451
446
- throw " access out of struct bounds" ;
452
+ throw analysis_exceptiont ( " access out of struct bounds" ) ;
447
453
}
448
454
449
455
// / returns the type object corresponding to id
@@ -634,7 +640,7 @@ exprt interpretert::get_value(
634
640
error () << " interpreter: invalid pointer " << rhs[integer2size_t (offset)]
635
641
<< " > object count " << memory.size () << eom;
636
642
637
- throw " interpreter: reading from invalid pointer" ;
643
+ throw analysis_exceptiont ( " interpreter: reading from invalid pointer" ) ;
638
644
}
639
645
else if (real_type.id ()==ID_string)
640
646
{
@@ -724,15 +730,15 @@ void interpretert::assign(
724
730
void interpretert::execute_assume ()
725
731
{
726
732
if (!evaluate_boolean (pc->guard ))
727
- throw " assumption failed" ;
733
+ throw analysis_exceptiont ( " assumption failed" ) ;
728
734
}
729
735
730
736
void interpretert::execute_assert ()
731
737
{
732
738
if (!evaluate_boolean (pc->guard ))
733
739
{
734
740
if ((target_assert==pc) || stop_on_assertion)
735
- throw " program assertion reached" ;
741
+ throw analysis_exceptiont ( " program assertion reached" ) ;
736
742
else if (show)
737
743
error () << " assertion failed at " << pc->location_number
738
744
<< " \n " << eom;
@@ -748,9 +754,9 @@ void interpretert::execute_function_call()
748
754
mp_integer address=evaluate_address (function_call.function ());
749
755
750
756
if (address==0 )
751
- throw " function call to NULL" ;
757
+ throw analysis_exceptiont ( " function call to NULL" ) ;
752
758
else if (address>=memory.size ())
753
- throw " out-of-range function call" ;
759
+ throw analysis_exceptiont ( " out-of-range function call" ) ;
754
760
755
761
// Retrieve the empty last trace step struct we pushed for this step
756
762
// of the interpreter run to fill it with the corresponding data
@@ -764,8 +770,9 @@ void interpretert::execute_function_call()
764
770
const goto_functionst::function_mapt::const_iterator f_it=
765
771
goto_functions.function_map .find (identifier);
766
772
767
- if (f_it==goto_functions.function_map .end ())
768
- throw " failed to find function " +id2string (identifier);
773
+ INVARIANT (
774
+ f_it != goto_functions.function_map .end (),
775
+ " calls to missing functions should be caught during typechecking" );
769
776
770
777
// return value
771
778
mp_integer return_value_address;
@@ -810,8 +817,10 @@ void interpretert::execute_function_call()
810
817
const code_typet::parameterst ¶meters=
811
818
to_code_type (f_it->second .type ).parameters ();
812
819
813
- if (argument_values.size ()<parameters.size ())
814
- throw " not enough arguments" ;
820
+ INVARIANT (
821
+ argument_values.size () != parameters.size (),
822
+ " function calls not matching function signatures should be caught during "
823
+ " typechecking" );
815
824
816
825
for (std::size_t i=0 ; i<parameters.size (); i++)
817
826
{
0 commit comments