@@ -107,6 +107,12 @@ class remove_exceptionst
107
107
const goto_programt::targett &,
108
108
bool may_catch);
109
109
110
+ goto_programt::targett find_universal_exception (
111
+ const remove_exceptionst::stack_catcht &stack_catch,
112
+ goto_programt &goto_program,
113
+ std::size_t &universal_try,
114
+ std::size_t &universal_catch);
115
+
110
116
void add_exception_dispatch_sequence (
111
117
goto_programt &goto_program,
112
118
const goto_programt::targett &instr_it,
@@ -229,6 +235,55 @@ void remove_exceptionst::instrument_exception_handler(
229
235
instr_it->make_skip ();
230
236
}
231
237
238
+ // / Find the innermost universal exception handler for the current
239
+ // / program location which may throw (i.e. the first catch of type
240
+ // / any in the innermost try that contains such). We record this one
241
+ // / because no handler after it can possibly catch.
242
+ // / The context is contained in stack_catch which is a stack of all the tries
243
+ // / which contain the current program location in their bodies. Each of these
244
+ // / in turn contains a list of all possible catches for that try giving the
245
+ // / type of exception they catch and the location of the handler.
246
+ // / This function returns the indices of the try and the catch within that try
247
+ // / as well as the location of the handler.
248
+ // / The first loop is in forward order because the insertion reverses the order
249
+ // / we note that try1{ try2 {} catch2c {} catch2d {}} catch1a() {} catch1b{}
250
+ // / must catch in the following order: 2c 2d 1a 1b hence the numerical index
251
+ // / is reversed whereas the letter ordering remains the same.
252
+ // / @param stack_catch exception table
253
+ // / @param goto_program program being evaluated
254
+ // / @param[out] universal_try returns the try block
255
+ // / corresponding to the desired exception handler
256
+ // / @param[out] universal_catch returns the catch block
257
+ // / corresponding to the exception desired exception handler
258
+ // / @return the desired exception handler
259
+ goto_programt::targett remove_exceptionst::find_universal_exception (
260
+ const remove_exceptionst::stack_catcht &stack_catch,
261
+ goto_programt &goto_program,
262
+ std::size_t &universal_try,
263
+ std::size_t &universal_catch)
264
+ {
265
+ for (std::size_t i=stack_catch.size (); i>0 ;)
266
+ {
267
+ i--;
268
+ for (std::size_t j=0 ; j<stack_catch[i].size (); ++j)
269
+ {
270
+ if (stack_catch[i][j].first .empty ())
271
+ {
272
+ // Record the position of the default behaviour as any further catches
273
+ // will not capture the throw
274
+ universal_try=i;
275
+ universal_catch=j;
276
+
277
+ // Universal handler. Highest on the stack takes
278
+ // precedence, so overwrite any we've already seen:
279
+ return stack_catch[i][j].second ;
280
+ }
281
+ }
282
+ }
283
+ // Unless we have a universal exception handler, jump to end of function
284
+ return goto_program.get_end_function ();
285
+ }
286
+
232
287
// / Emit the code:
233
288
// / if (exception instanceof ExnA) then goto handlerA
234
289
// / else if (exception instanceof ExnB) then goto handlerB
@@ -244,10 +299,6 @@ void remove_exceptionst::add_exception_dispatch_sequence(
244
299
const remove_exceptionst::stack_catcht &stack_catch,
245
300
const std::vector<exprt> &locals)
246
301
{
247
- // Unless we have a universal exception handler, jump to end of function
248
- // if not caught:
249
- goto_programt::targett default_target=goto_program.get_end_function ();
250
-
251
302
// Jump to the universal handler or function end, as appropriate.
252
303
// This will appear after the GOTO-based dynamic dispatch below
253
304
goto_programt::targett default_dispatch=goto_program.insert_after (instr_it);
@@ -259,21 +310,28 @@ void remove_exceptionst::add_exception_dispatch_sequence(
259
310
symbol_exprt exc_thrown =
260
311
get_inflight_exception_global ();
261
312
313
+ std::size_t default_try=0 ;
314
+ std::size_t default_catch=(!stack_catch.empty ()) ? stack_catch[0 ].size () : 0 ;
315
+
316
+ goto_programt::targett default_target=
317
+ find_universal_exception (stack_catch, goto_program,
318
+ default_try, default_catch);
319
+
262
320
// add GOTOs implementing the dynamic dispatch of the
263
- // exception handlers
264
- for (std::size_t i=stack_catch.size (); i-->0 ;)
321
+ // exception handlers.
322
+ // The first loop is in forward order because the insertion reverses the order
323
+ // we note that try1{ try2 {} catch2c {} catch2d {}} catch1a() {} catch1b{}
324
+ // must catch in the following order: 2c 2d 1a 1b hence the numerical index
325
+ // is reversed whereas the letter ordering remains the same.
326
+ for (std::size_t i=default_try; i<stack_catch.size (); i++)
265
327
{
266
- for (std::size_t j=stack_catch[i].size (); j-->0 ;)
328
+ for (std::size_t j=(i==default_try) ? default_catch : stack_catch[i].size ();
329
+ j>0 ;)
267
330
{
331
+ j--;
268
332
goto_programt::targett new_state_pc=
269
333
stack_catch[i][j].second ;
270
- if (stack_catch[i][j].first .empty ())
271
- {
272
- // Universal handler. Highest on the stack takes
273
- // precedence, so overwrite any we've already seen:
274
- default_target=new_state_pc;
275
- }
276
- else
334
+ if (!stack_catch[i][j].first .empty ())
277
335
{
278
336
// Normal exception handler, make an instanceof check.
279
337
goto_programt::targett t_exc=goto_program.insert_after (instr_it);
0 commit comments