Mercurial > hg > CbC > CbC_gcc
comparison gcc/ada/libgnat/a-exexpr.adb @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
comparison
equal
deleted
inserted
replaced
131:84e7813d76e9 | 145:1830386684a0 |
---|---|
4 -- -- | 4 -- -- |
5 -- A D A . E X C E P T I O N S . E X C E P T I O N _ P R O P A G A T I O N -- | 5 -- A D A . E X C E P T I O N S . E X C E P T I O N _ P R O P A G A T I O N -- |
6 -- -- | 6 -- -- |
7 -- B o d y -- | 7 -- B o d y -- |
8 -- -- | 8 -- -- |
9 -- Copyright (C) 1992-2018, Free Software Foundation, Inc. -- | 9 -- Copyright (C) 1992-2019, Free Software Foundation, Inc. -- |
10 -- -- | 10 -- -- |
11 -- GNAT is free software; you can redistribute it and/or modify it under -- | 11 -- GNAT is free software; you can redistribute it and/or modify it under -- |
12 -- terms of the GNU General Public License as published by the Free Soft- -- | 12 -- terms of the GNU General Public License as published by the Free Soft- -- |
13 -- ware Foundation; either version 3, or (at your option) any later ver- -- | 13 -- ware Foundation; either version 3, or (at your option) any later ver- -- |
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- | 14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- |
195 procedure Set_Foreign_Occurrence (Excep : EOA; Mo : System.Address); | 195 procedure Set_Foreign_Occurrence (Excep : EOA; Mo : System.Address); |
196 -- Utility routine to initialize occurrence Excep from a foreign exception | 196 -- Utility routine to initialize occurrence Excep from a foreign exception |
197 -- whose machine occurrence is Mo. The message is empty, the backtrace | 197 -- whose machine occurrence is Mo. The message is empty, the backtrace |
198 -- is empty too and the exception identity is Foreign_Exception. | 198 -- is empty too and the exception identity is Foreign_Exception. |
199 | 199 |
200 -- Hooks called when entering/leaving an exception handler for a given | 200 -- Hooks called when entering/leaving an exception handler for a |
201 -- occurrence, aimed at handling the stack of active occurrences. The | 201 -- given occurrence. The calls are generated by gigi in |
202 -- calls are generated by gigi in tree_transform/N_Exception_Handler. | 202 -- Exception_Handler_to_gnu_gcc. |
203 | |
204 -- Begin_Handler_v1, called when entering an exception handler, | |
205 -- claims responsibility for the handler to release the | |
206 -- GCC_Exception occurrence. End_Handler_v1, called when | |
207 -- leaving the handler, releases the occurrence, unless the | |
208 -- occurrence is propagating further up, or the handler is | |
209 -- dynamically nested in the context of another handler that | |
210 -- claimed responsibility for releasing that occurrence. | |
211 | |
212 -- Responsibility is claimed by changing the Cleanup field to | |
213 -- Claimed_Cleanup, which enables claimed exceptions to be | |
214 -- recognized, and avoids accidental releases even by foreign | |
215 -- handlers. | |
216 | |
217 function Begin_Handler_v1 | |
218 (GCC_Exception : not null GCC_Exception_Access) | |
219 return System.Address; | |
220 pragma Export (C, Begin_Handler_v1, "__gnat_begin_handler_v1"); | |
221 -- Called when entering an exception handler. Claim | |
222 -- responsibility for releasing GCC_Exception, by setting the | |
223 -- cleanup/release function to Claimed_Cleanup, and return the | |
224 -- address of the previous cleanup/release function. | |
225 | |
226 procedure End_Handler_v1 | |
227 (GCC_Exception : not null GCC_Exception_Access; | |
228 Saved_Cleanup : System.Address; | |
229 Propagating_Exception : GCC_Exception_Access); | |
230 pragma Export (C, End_Handler_v1, "__gnat_end_handler_v1"); | |
231 -- Called when leaving an exception handler. Restore the | |
232 -- Saved_Cleanup in the GCC_Exception occurrence, and then release | |
233 -- it, unless it remains claimed by an enclosing handler, or | |
234 -- GCC_Exception and Propagating_Exception are the same | |
235 -- occurrence. Propagating_Exception could be either an | |
236 -- occurrence (re)raised within the handler of GCC_Exception, when | |
237 -- we're executing as an exceptional cleanup, or null, if we're | |
238 -- completing the handler of GCC_Exception normally. | |
239 | |
240 procedure Claimed_Cleanup | |
241 (Reason : Unwind_Reason_Code; | |
242 GCC_Exception : not null GCC_Exception_Access); | |
243 pragma Export (C, Claimed_Cleanup, "__gnat_claimed_cleanup"); | |
244 -- A do-nothing placeholder installed as GCC_Exception.Cleanup | |
245 -- while handling GCC_Exception, to claim responsibility for | |
246 -- releasing it, and to stop it from being accidentally released. | |
247 | |
248 -- The following are version 0 implementations of the version 1 | |
249 -- hooks above. They remain in place for compatibility with the | |
250 -- output of compilers that still use version 0, such as those | |
251 -- used during bootstrap. They are interoperable with the v1 | |
252 -- hooks, except that the older versions may malfunction when | |
253 -- handling foreign exceptions passed to Reraise_Occurrence. | |
203 | 254 |
204 procedure Begin_Handler (GCC_Exception : not null GCC_Exception_Access); | 255 procedure Begin_Handler (GCC_Exception : not null GCC_Exception_Access); |
205 pragma Export (C, Begin_Handler, "__gnat_begin_handler"); | 256 pragma Export (C, Begin_Handler, "__gnat_begin_handler"); |
257 -- Called when entering an exception handler translated by an old | |
258 -- compiler. It does nothing. | |
206 | 259 |
207 procedure End_Handler (GCC_Exception : GCC_Exception_Access); | 260 procedure End_Handler (GCC_Exception : GCC_Exception_Access); |
208 pragma Export (C, End_Handler, "__gnat_end_handler"); | 261 pragma Export (C, End_Handler, "__gnat_end_handler"); |
262 -- Called when leaving an exception handler translated by an old | |
263 -- compiler. It releases GCC_Exception, unless it is null. It is | |
264 -- only ever null when the handler has a 'raise;' translated by a | |
265 -- v0-using compiler. The artificial handler variable passed to | |
266 -- End_Handler was set to null to tell End_Handler to refrain from | |
267 -- releasing the reraised exception. In v1 safer ways are used to | |
268 -- accomplish that. | |
209 | 269 |
210 -------------------------------------------------------------------- | 270 -------------------------------------------------------------------- |
211 -- Accessors to Basic Components of a GNAT Exception Data Pointer -- | 271 -- Accessors to Basic Components of a GNAT Exception Data Pointer -- |
212 -------------------------------------------------------------------- | 272 -------------------------------------------------------------------- |
213 | 273 |
350 | 410 |
351 return Excep; | 411 return Excep; |
352 end if; | 412 end if; |
353 end Setup_Current_Excep; | 413 end Setup_Current_Excep; |
354 | 414 |
415 ---------------------- | |
416 -- Begin_Handler_v1 -- | |
417 ---------------------- | |
418 | |
419 function Begin_Handler_v1 | |
420 (GCC_Exception : not null GCC_Exception_Access) | |
421 return System.Address is | |
422 Saved_Cleanup : constant System.Address := GCC_Exception.Cleanup; | |
423 begin | |
424 -- Claim responsibility for releasing this exception, and stop | |
425 -- others from releasing it. | |
426 GCC_Exception.Cleanup := Claimed_Cleanup'Address; | |
427 return Saved_Cleanup; | |
428 end Begin_Handler_v1; | |
429 | |
430 -------------------- | |
431 -- End_Handler_v1 -- | |
432 -------------------- | |
433 | |
434 procedure End_Handler_v1 | |
435 (GCC_Exception : not null GCC_Exception_Access; | |
436 Saved_Cleanup : System.Address; | |
437 Propagating_Exception : GCC_Exception_Access) is | |
438 begin | |
439 GCC_Exception.Cleanup := Saved_Cleanup; | |
440 -- Restore the Saved_Cleanup, so that it is either used to | |
441 -- release GCC_Exception below, or transferred to the next | |
442 -- handler of the Propagating_Exception occurrence. The | |
443 -- following test ensures that an occurrence is only released | |
444 -- once, even after reraises. | |
445 -- | |
446 -- The idea is that the GCC_Exception is not to be released | |
447 -- unless it had an unclaimed Cleanup when the handler started | |
448 -- (see Begin_Handler_v1 above), but if we propagate across its | |
449 -- handler a reraise of the same exception, we transfer to the | |
450 -- Propagating_Exception the responsibility for running the | |
451 -- Saved_Cleanup when its handler completes. | |
452 -- | |
453 -- This ownership transfer mechanism ensures safety, as in | |
454 -- single release and no dangling pointers, because there is no | |
455 -- way to hold on to the Machine_Occurrence of an | |
456 -- Exception_Occurrence: the only situations in which another | |
457 -- Exception_Occurrence gets the same Machine_Occurrence are | |
458 -- through Reraise_Occurrence, and plain reraise, and so we | |
459 -- have the following possibilities: | |
460 -- | |
461 -- - Reraise_Occurrence is handled within the running handler, | |
462 -- and so when completing the dynamically nested handler, we | |
463 -- must NOT release the exception. A Claimed_Cleanup upon | |
464 -- entry of the nested handler, installed when entering the | |
465 -- enclosing handler, ensures the exception will not be | |
466 -- released by the nested handler, but rather by the enclosing | |
467 -- handler. | |
468 -- | |
469 -- - Reraise_Occurrence/reraise escapes the running handler, | |
470 -- and we run as an exceptional cleanup for GCC_Exception. The | |
471 -- Saved_Cleanup was reinstalled, but since we're propagating | |
472 -- the same machine occurrence, we do not release it. Instead, | |
473 -- we transfer responsibility for releasing it to the eventual | |
474 -- handler of the propagating exception. | |
475 -- | |
476 -- - An unrelated exception propagates through the running | |
477 -- handler. We restored GCC_Exception.Saved_Cleanup above. | |
478 -- Since we're propagating a different exception, we proceed to | |
479 -- release GCC_Exception, unless Saved_Cleanup was | |
480 -- Claimed_Cleanup, because then we know we're not in the | |
481 -- outermost handler for GCC_Exception. | |
482 -- | |
483 -- - The handler completes normally, so it reinstalls the | |
484 -- Saved_Cleanup and runs it, unless it was Claimed_Cleanup. | |
485 -- If Saved_Cleanup is null, Unwind_DeleteException (currently) | |
486 -- has no effect, so we could skip it, but if it is ever | |
487 -- changed to do more in this case, we're ready for that, | |
488 -- calling it exactly once. | |
489 if Saved_Cleanup /= Claimed_Cleanup'Address | |
490 and then | |
491 Propagating_Exception /= GCC_Exception | |
492 then | |
493 declare | |
494 Current : constant EOA := Get_Current_Excep.all; | |
495 Cur_Occ : constant GCC_Exception_Access | |
496 := To_GCC_Exception (Current.Machine_Occurrence); | |
497 begin | |
498 -- If we are releasing the Machine_Occurrence of the current | |
499 -- exception, reset the access to it, so that it is no | |
500 -- longer accessible. | |
501 if Cur_Occ = GCC_Exception then | |
502 Current.Machine_Occurrence := System.Null_Address; | |
503 end if; | |
504 end; | |
505 Unwind_DeleteException (GCC_Exception); | |
506 end if; | |
507 end End_Handler_v1; | |
508 | |
509 --------------------- | |
510 -- Claimed_Cleanup -- | |
511 --------------------- | |
512 | |
513 procedure Claimed_Cleanup | |
514 (Reason : Unwind_Reason_Code; | |
515 GCC_Exception : not null GCC_Exception_Access) is | |
516 pragma Unreferenced (Reason); | |
517 pragma Unreferenced (GCC_Exception); | |
518 begin | |
519 -- This procedure should never run. If it does, it's either a | |
520 -- version 0 handler or a foreign handler, attempting to | |
521 -- release an exception while a version 1 handler that claimed | |
522 -- responsibility for releasing the exception remains still | |
523 -- active. This placeholder stops GCC_Exception from being | |
524 -- released by them. | |
525 | |
526 -- We could get away with just Null_Address instead, with | |
527 -- nearly the same effect, but with this placeholder we can | |
528 -- detect and report unexpected releases, and we can tell apart | |
529 -- a GCC_Exception without a Cleanup, from one with another | |
530 -- active handler, so as to still call Unwind_DeleteException | |
531 -- exactly once: currently, Unwind_DeleteException does nothing | |
532 -- when the Cleanup is null, but should it ever be changed to | |
533 -- do more, we'll still be safe. | |
534 null; | |
535 end Claimed_Cleanup; | |
536 | |
355 ------------------- | 537 ------------------- |
356 -- Begin_Handler -- | 538 -- Begin_Handler -- |
357 ------------------- | 539 ------------------- |
358 | 540 |
359 procedure Begin_Handler (GCC_Exception : not null GCC_Exception_Access) is | 541 procedure Begin_Handler (GCC_Exception : not null GCC_Exception_Access) is |