@@ -307,11 +307,9 @@ void java_record_outputs(
307
307
codet output (ID_output);
308
308
output.operands ().resize (2 );
309
309
310
- assert (symbol_table.has_symbol (id2string (function.name )+EXC_SUFFIX));
311
-
312
310
// retrieve the exception variable
313
311
const symbolt exc_symbol=symbol_table.lookup (
314
- id2string (function. name )+EXC_SUFFIX );
312
+ JAVA_ENTRY_POINT_EXCEPTION_SYMBOL );
315
313
316
314
output.op0 ()=address_of_exprt (
317
315
index_exprt (string_constantt (exc_symbol.base_name ),
@@ -613,17 +611,19 @@ bool java_entry_point(
613
611
call_main.lhs ()=return_symbol.symbol_expr ();
614
612
}
615
613
616
- if (!symbol_table.has_symbol (id2string (symbol.name )+EXC_SUFFIX))
617
- {
618
- // add the exceptional return value
619
- auxiliary_symbolt exc_symbol;
620
- exc_symbol.mode =ID_java;
621
- exc_symbol.is_static_lifetime =true ;
622
- exc_symbol.name =id2string (symbol.name )+EXC_SUFFIX;
623
- exc_symbol.base_name =id2string (symbol.name )+EXC_SUFFIX;
624
- exc_symbol.type =java_reference_type (empty_typet ());
625
- symbol_table.add (exc_symbol);
626
- }
614
+ // add the exceptional return value
615
+ auxiliary_symbolt exc_symbol;
616
+ exc_symbol.mode =ID_java;
617
+ exc_symbol.name =JAVA_ENTRY_POINT_EXCEPTION_SYMBOL;
618
+ exc_symbol.base_name =exc_symbol.name ;
619
+ exc_symbol.type =java_reference_type (empty_typet ());
620
+ symbol_table.add (exc_symbol);
621
+
622
+ // Zero-initialise the top-level exception catch variable:
623
+ init_code.copy_to_operands (
624
+ code_assignt (
625
+ exc_symbol.symbol_expr (),
626
+ null_pointer_exprt (to_pointer_type (exc_symbol.type ))));
627
627
628
628
// create code that allocates the objects used as test arguments and
629
629
// non-deterministically initializes them
@@ -638,8 +638,48 @@ bool java_entry_point(
638
638
pointer_type_selector);
639
639
call_main.arguments ()=main_arguments;
640
640
641
+ // Create target labels for the toplevel exception handler:
642
+ code_labelt toplevel_catch (" toplevel_catch" , code_skipt ());
643
+ code_labelt after_catch (" after_catch" , code_skipt ());
644
+
645
+ code_blockt call_block;
646
+
647
+ // Push a universal exception handler:
648
+ side_effect_expr_catcht push_universal_handler;
649
+ irept catch_type_list (ID_exception_list);
650
+ irept catch_target_list (ID_label);
651
+ // Catch all exceptions:
652
+ // This is equivalent to catching Throwable, but also works if some of
653
+ // the class hierarchy is missing so that we can't determine that
654
+ // the thrown instance is an indirect child of Throwable
655
+ catch_type_list.get_sub ().push_back (irept ());
656
+ catch_target_list.get_sub ().push_back (irept (toplevel_catch.get_label ()));
657
+ push_universal_handler.set (ID_exception_list, catch_type_list);
658
+ push_universal_handler.set (ID_label, catch_target_list);
659
+
660
+ call_block.copy_to_operands (code_expressiont (push_universal_handler));
661
+
641
662
// we insert the call to the method AFTER the argument initialization code
642
- init_code.move_to_operands (call_main);
663
+ call_block.move_to_operands (call_main);
664
+
665
+ // Pop the handler:
666
+ side_effect_expr_catcht pop_handler;
667
+ pop_handler.set (ID_exception_list, get_nil_irep ());
668
+ pop_handler.set (ID_label, get_nil_irep ());
669
+
670
+ // call_block.copy_to_operands(code_expressiont(pop_handler));
671
+ init_code.move_to_operands (call_block);
672
+
673
+ // Normal return: skip the exception handler:
674
+ init_code.copy_to_operands (code_gotot (after_catch.get_label ()));
675
+
676
+ // Exceptional return: catch and assign to exc_symbol.
677
+ side_effect_expr_landingpadt landingpad (exc_symbol.symbol_expr ());
678
+ init_code.copy_to_operands (toplevel_catch);
679
+ init_code.copy_to_operands (code_expressiont (landingpad));
680
+
681
+ // Converge normal and exceptional return:
682
+ init_code.move_to_operands (after_catch);
643
683
644
684
// declare certain (which?) variables as test outputs
645
685
java_record_outputs (symbol, main_arguments, init_code, symbol_table);
0 commit comments