Summary: | Front-end error if exception propagation disabled | ||
---|---|---|---|
Product: | gcc | Reporter: | simon |
Component: | ada | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | RESOLVED FIXED | ||
Severity: | enhancement | CC: | charlet, ebotcazou, ramana |
Priority: | P3 | ||
Version: | 4.9.1 | ||
Target Milestone: | 6.0 | ||
Host: | Target: | ||
Build: | Known to work: | ||
Known to fail: | 4.9.1, 5.1.0 | Last reconfirmed: | 2015-06-14 00:00:00 |
Bug Depends on: | |||
Bug Blocks: | 66205 | ||
Attachments: |
Demonstrators
Suggested patch |
Created attachment 35588 [details]
Suggested patch
Patches on mailing list please along with a testcase and stating how it was regression tested. (In reply to Ramana Radhakrishnan from comment #2) > Patches on mailing list please along with a testcase and stating how it was > regression tested. Done. Author: charlet Date: Wed Nov 18 10:30:12 2015 New Revision: 230531 URL: https://gcc.gnu.org/viewcvs?rev=230531&root=gcc&view=rev Log: 2015-11-18 Hristian Kirtchev <kirtchev@adacore.com> PR ada/66242 * exp_ch3.adb (Default_Initialize_Object): Reimplemented. Abort defer / undefer pairs are now encapsulated in a block with an AT END handler. Partial finalization now takes restriction No_Exception_Propagation into account when generating blocks. * exp_ch7.adb Various reformattings. (Create_Finalizer): Change the generation of abort defer / undefer pairs and explain the lack of an AT END handler. (Process_Transient_Objects): Add generation of abort defer/undefer pairs. * exp_ch9.adb Various reformattings. (Build_Protected_Subprogram_Body): Use Build_Runtime_Call to construct a call to Abort_Defer. (Build_Protected_Subprogram_Call_Cleanup): Use Build_Runtime_Call to construct a call to Abort_Undefer. (Expand_N_Asynchronous_Select): Use Build_Runtime_Call to construct a call to Abort_Defer. * exp_intr.adb (Expand_Unc_Deallocation): Abort defer / undefer pairs are now encapsulated in a block with an AT END handler. Finalization now takes restriction No_Exception_Propagation into account when generating blocks. * exp_util.ads, exp_util.adb (Wrap_Cleanup_Procedure): Removed. Modified: trunk/gcc/ada/exp_ch3.adb trunk/gcc/ada/exp_ch7.adb trunk/gcc/ada/exp_ch9.adb trunk/gcc/ada/exp_intr.adb trunk/gcc/ada/exp_util.adb trunk/gcc/ada/exp_util.ads Should be properly implemented now. |
Created attachment 35587 [details] Demonstrators First detected in GCC 4.9.1 built for arm-eabi on x86_64-apple-darwin13 (Mac OS X Mavericks) with these pragmas on System: pragma Profile (Ravenscar); pragma Restrictions (No_Enumeration_Maps); pragma Restrictions (No_Exception_Propagation); pragma Restrictions (No_Recursion); Also observed with GCC 5.1.0, same build. The demonstrators use pragma Restrictions (No_Exception_Propagation); with Ada.Finalization; package Fin is type F is new Ada.Finalization.Controlled with null record; end Fin; and show the problem with the hosted compiler. There are two, because only the first such error is detected. (1) Unchecked deallocation with Ada.Finalization; with Ada.Unchecked_Deallocation; with Fin; use Fin; procedure Fin_Deallocation is type F_P is access F; procedure Delete is new Ada.Unchecked_Deallocation (F, F_P); procedure Check_Heap_1 is An_F_P : F_P := new F'(Ada.Finalization.Controlled with null record); begin Delete (An_F_P); end Check_Heap_1; begin Check_Heap_1; end Fin_Deallocation; results in 17. procedure Check_Heap_1 is 18. An_F_P : F_P := 19. new F'(Ada.Finalization.Controlled with null record); 20. begin 21. Delete (An_F_P); | >>> "" is undefined 22. end Check_Heap_1; The end of the -gnatdg output for Check_Heap_1 is begin if an_f_p /= null then B22b : begin system__soft_links__abort_defer.all; B23b : begin [constraint_error when an_f_p = null "access check failed"] [type T24b is procedure (object : in out fin__TfC)] [subtype T25b is access T24b] T25b!(fin__fH!(fin__TfC!(an_f_p.all)._tag).all (2)).all (fin__TfC!(an_f_p.all)); exception when others => any id := true; <<<<<<<<<<<<<<< end B23b; at end system__standard_library__abort_undefer_direct; end B22b; free an_f_p; an_f_p := null; if then [program_error "finalize raised exception"] <<<<<<<<<<<<<<< end if; end if; end check_heap_1; which I take to mean that the compiler has tried to generate an exception handler which is incompatible with pragma Restrictions (No_Exception_Propagation). I've traced this to exp_intr.adb, and written a patch which resolves this problem. (2) Returning a controlled type I see also that in exp_ch7.adb all the cases where an exception handler like this one might be generated are protected by a check for No_Exception_Propagation, except for one at line 4751 in Process_Transient_Objects. To demonstrate this, with Ada.Finalization; with Fin; use Fin; procedure Fin_Return_Controlled is type R is record A, B : F; end record; function Get_F return R is begin return (A => F'(Ada.Finalization.Controlled with null record), B => F'(Ada.Finalization.Controlled with null record)); end Get_F; An_F : R; begin An_F := Get_F; end Fin_Return_Controlled; fails as 8. with Ada.Finalization; 9. with Fin; use Fin; 10. procedure Fin_Return_Controlled is 11. type R is record 12. A, B : F; 13. end record; 14. function Get_F return R is 15. begin 16. return (A => F'(Ada.Finalization.Controlled with null record), 17. B => F'(Ada.Finalization.Controlled with null record)); 18. end Get_F; 19. An_F : R; 20. begin 21. An_F := Get_F; | >>> "" is undefined 22. end Fin_Return_Controlled; and the corresponding part of the -gnatdg output is B26b : declare begin B27b : begin T25b := null; fin_return_controlled__rDF (R18b.all, f => true); exception when others => any id := true; end B27b; if then [program_error "finalize raised exception"] end if; end B26b; with the same symptoms. I have a patch for this too. The patches apply (with considerable offsets) to GCC 5.1.0, but I haven't tested them yet (indeed, I've only tested in the arm-eabi build).