diff options
author | Arnaud Charlet <charlet@gcc.gnu.org> | 2011-08-29 13:06:09 +0200 |
---|---|---|
committer | Arnaud Charlet <charlet@gcc.gnu.org> | 2011-08-29 13:06:09 +0200 |
commit | 5accd7b6ca81d3f3b399bf55e201fc6f78771a13 (patch) | |
tree | 5296dea30b4ab9b51a3198c680e9713accd59479 /gcc | |
parent | 2ef48385c29c519a157e3a6d60011196cd7e9409 (diff) | |
download | gcc-5accd7b6ca81d3f3b399bf55e201fc6f78771a13.zip gcc-5accd7b6ca81d3f3b399bf55e201fc6f78771a13.tar.gz gcc-5accd7b6ca81d3f3b399bf55e201fc6f78771a13.tar.bz2 |
[multiple changes]
2011-08-29 Yannick Moy <moy@adacore.com>
* sem_ch13.adb (Analyze_Aspect_Specifications): Reject test-case on
library-level subprogram.
* sem_prag.adb (Check_Test_Case): Stricter rules for test-case
placement.
(Analyze_Pragma): Change name "Normal" for "Nominal" in test-case
component.
* snames.ads-tmpl: Change name "Normal" for "Nominal" in test-case
component.
* gnat_rm.texi: Update doc for Test_Case pragma.
2011-08-29 Tristan Gingold <gingold@adacore.com>
* a-exexpr-gcc.adb (Unwind_Exception): Remove default value, made it
convention C.
(GCC_Exception_Access): New type.
(Unwind_DeleteException): New imported procedure
(Foreign_Exception): Import it.
(GNAT_GCC_Exception): Simply have the occurrence inside.
(To_GCC_Exception): New function.
(To_GNAT_GCC_Exception): New function.
(GNAT_GCC_Exception_Cleanup): New procedure..
(Propagate_GCC_Exception): New procedure.
(Reraise_GCC_Exception): New procedure.
(Setup_Current_Excep): New procedure.
(CleanupUnwind_Handler): Change type of UW_Exception parameter.
(Unwind_RaiseException): Ditto.
(Unwind_ForcedUnwind): Ditto.
(Remove): Removed.
(Begin_Handler): Change type of parameter.
(End_Handler): Ditto. Now delete the exception if still present.
(Setup_Key): Removed.
(Is_Setup_And_Not_Propagated): Removed.
(Set_Setup_And_Not_Propagated): Ditto.
(Clear_Setup_And_Not_Propagated): Ditto.
(Save_Occurrence_And_Private): Ditto.
(EID_For): Add 'not null' constraint on parameter.
(Setup_Exception): Does nothing.
(Propagate_Exception): Simplified.
* exp_ch11.adb (Expand_N_Raise_Statement): In back-end exception model,
re-raise is not expanded anymore.
* s-except.ads (Foreign_Exception): New exception - placeholder for
non Ada exceptions.
* raise-gcc.c (__gnat_setup_current_excep): Declare
(CXX_EXCEPTION_CLASS): Define (not yet used)
(GNAT_EXCEPTION_CLASS): Define.
(is_handled_by): Handle foreign exceptions.
(PERSONALITY_FUNCTION): Call __gnat_setup_current_excep.
2011-08-29 Jose Ruiz <ruiz@adacore.com>
* a-synbar.adb (Synchronous_Barrier): Some additional clarification.
From-SVN: r178204
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ada/ChangeLog | 54 | ||||
-rw-r--r-- | gcc/ada/a-exexpr-gcc.adb | 495 | ||||
-rw-r--r-- | gcc/ada/a-synbar.adb | 7 | ||||
-rw-r--r-- | gcc/ada/exp_ch11.adb | 9 | ||||
-rw-r--r-- | gcc/ada/gnat_rm.texi | 20 | ||||
-rw-r--r-- | gcc/ada/raise-gcc.c | 87 | ||||
-rw-r--r-- | gcc/ada/s-except.ads | 5 | ||||
-rw-r--r-- | gcc/ada/sem_ch13.adb | 6 | ||||
-rw-r--r-- | gcc/ada/sem_prag.adb | 84 | ||||
-rw-r--r-- | gcc/ada/snames.ads-tmpl | 2 |
10 files changed, 358 insertions, 411 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 17a2e5d..ba9fcbe 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,57 @@ +2011-08-29 Yannick Moy <moy@adacore.com> + + * sem_ch13.adb (Analyze_Aspect_Specifications): Reject test-case on + library-level subprogram. + * sem_prag.adb (Check_Test_Case): Stricter rules for test-case + placement. + (Analyze_Pragma): Change name "Normal" for "Nominal" in test-case + component. + * snames.ads-tmpl: Change name "Normal" for "Nominal" in test-case + component. + * gnat_rm.texi: Update doc for Test_Case pragma. + +2011-08-29 Tristan Gingold <gingold@adacore.com> + + * a-exexpr-gcc.adb (Unwind_Exception): Remove default value, made it + convention C. + (GCC_Exception_Access): New type. + (Unwind_DeleteException): New imported procedure + (Foreign_Exception): Import it. + (GNAT_GCC_Exception): Simply have the occurrence inside. + (To_GCC_Exception): New function. + (To_GNAT_GCC_Exception): New function. + (GNAT_GCC_Exception_Cleanup): New procedure.. + (Propagate_GCC_Exception): New procedure. + (Reraise_GCC_Exception): New procedure. + (Setup_Current_Excep): New procedure. + (CleanupUnwind_Handler): Change type of UW_Exception parameter. + (Unwind_RaiseException): Ditto. + (Unwind_ForcedUnwind): Ditto. + (Remove): Removed. + (Begin_Handler): Change type of parameter. + (End_Handler): Ditto. Now delete the exception if still present. + (Setup_Key): Removed. + (Is_Setup_And_Not_Propagated): Removed. + (Set_Setup_And_Not_Propagated): Ditto. + (Clear_Setup_And_Not_Propagated): Ditto. + (Save_Occurrence_And_Private): Ditto. + (EID_For): Add 'not null' constraint on parameter. + (Setup_Exception): Does nothing. + (Propagate_Exception): Simplified. + * exp_ch11.adb (Expand_N_Raise_Statement): In back-end exception model, + re-raise is not expanded anymore. + * s-except.ads (Foreign_Exception): New exception - placeholder for + non Ada exceptions. + * raise-gcc.c (__gnat_setup_current_excep): Declare + (CXX_EXCEPTION_CLASS): Define (not yet used) + (GNAT_EXCEPTION_CLASS): Define. + (is_handled_by): Handle foreign exceptions. + (PERSONALITY_FUNCTION): Call __gnat_setup_current_excep. + +2011-08-29 Jose Ruiz <ruiz@adacore.com> + + * a-synbar.adb (Synchronous_Barrier): Some additional clarification. + 2011-08-29 Thomas Quinot <quinot@adacore.com> * a-synbar-posix.adb: Minor reformatting. diff --git a/gcc/ada/a-exexpr-gcc.adb b/gcc/ada/a-exexpr-gcc.adb index ac0272d..d32e7a4 100644 --- a/gcc/ada/a-exexpr-gcc.adb +++ b/gcc/ada/a-exexpr-gcc.adb @@ -104,11 +104,12 @@ package body Exception_Propagation is -- Map the corresponding C type used in Unwind_Exception below type Unwind_Exception is record - Class : Exception_Class := GNAT_Exception_Class; - Cleanup : System.Address := System.Null_Address; + Class : Exception_Class; + Cleanup : System.Address; Private1 : Unwind_Word; Private2 : Unwind_Word; end record; + pragma Convention (C, Unwind_Exception); -- Map the GCC struct used for exception handling for Unwind_Exception'Alignment use Standard'Maximum_Alignment; @@ -117,6 +118,19 @@ package body Exception_Propagation is -- maximally aligned (see unwind.h). See additional comments on the -- alignment below. + type GCC_Exception_Access is access all Unwind_Exception; + pragma Convention (C, GCC_Exception_Access); + -- Pointer to a GCC exception + + procedure Unwind_DeleteException (Excp : not null GCC_Exception_Access); + pragma Import (C, Unwind_DeleteException, "_Unwind_DeleteException"); + -- Procedure to free any GCC exception + + Foreign_Exception : aliased System.Standard_Library.Exception_Data; + pragma Import (Ada, Foreign_Exception, + "system__exceptions__foreign_exception"); + -- Id for foreign exceptions + -------------------------------------------------------------- -- GNAT Specific Entities To Deal With The GCC EH Circuitry -- -------------------------------------------------------------- @@ -128,13 +142,8 @@ package body Exception_Propagation is Header : Unwind_Exception; -- ABI Exception header first - Id : Exception_Id; - -- GNAT Exception identifier. This is filled by Propagate_Exception - -- and then used by the personality routine to determine if the context - -- it examines contains a handler for the exception being propagated. - - Next_Exception : EOA; - -- Used to create a linked list of exception occurrences + Occurrence : Exception_Occurrence; + -- The Ada occurrence end record; pragma Convention (C, GNAT_GCC_Exception); @@ -158,20 +167,40 @@ package body Exception_Propagation is type GNAT_GCC_Exception_Access is access all GNAT_GCC_Exception; - function To_GNAT_GCC_Exception is new - Unchecked_Conversion (System.Address, GNAT_GCC_Exception_Access); + function To_GCC_Exception is new + Unchecked_Conversion (GNAT_GCC_Exception_Access, GCC_Exception_Access); - procedure Free is new Unchecked_Deallocation - (GNAT_GCC_Exception, GNAT_GCC_Exception_Access); - - procedure Free is new Unchecked_Deallocation - (Exception_Occurrence, EOA); + function To_GNAT_GCC_Exception is new + Unchecked_Conversion (GCC_Exception_Access, GNAT_GCC_Exception_Access); + + procedure GNAT_GCC_Exception_Cleanup + (Reason : Unwind_Reason_Code; + Excep : not null GNAT_GCC_Exception_Access); + pragma Convention (C, GNAT_GCC_Exception_Cleanup); + -- Procedure called when a GNAT GCC exception is free. + + procedure Propagate_GCC_Exception + (GCC_Exception : not null GCC_Exception_Access); + pragma No_Return (Propagate_GCC_Exception); + -- Propagate a GCC exception + + procedure Reraise_GCC_Exception + (GCC_Exception : not null GCC_Exception_Access); + pragma No_Return (Reraise_GCC_Exception); + pragma Export (C, Reraise_GCC_Exception, "__gnat_reraise_zcx"); + -- Called to implement raise without exception, ie reraise. Called + -- directly from gigi. + + procedure Setup_Current_Excep + (GCC_Exception : not null GCC_Exception_Access); + pragma Export (C, Setup_Current_Excep, "__gnat_setup_current_excep"); + -- Write Get_Current_Excep.all from GCC_Exception function CleanupUnwind_Handler (UW_Version : Integer; UW_Phases : Unwind_Action; UW_Eclass : Exception_Class; - UW_Exception : not null access GNAT_GCC_Exception; + UW_Exception : not null GCC_Exception_Access; UW_Context : System.Address; UW_Argument : System.Address) return Unwind_Reason_Code; -- Hook called at each step of the forced unwinding we perform to @@ -183,57 +212,25 @@ package body Exception_Propagation is -- __gnat stubs for these. procedure Unwind_RaiseException - (UW_Exception : not null access GNAT_GCC_Exception); + (UW_Exception : not null GCC_Exception_Access); pragma Import (C, Unwind_RaiseException, "__gnat_Unwind_RaiseException"); procedure Unwind_ForcedUnwind - (UW_Exception : not null access GNAT_GCC_Exception; + (UW_Exception : not null GCC_Exception_Access; UW_Handler : System.Address; UW_Argument : System.Address); pragma Import (C, Unwind_ForcedUnwind, "__gnat_Unwind_ForcedUnwind"); - ------------------------------------------------------------------ - -- Occurrence Stack Management Facilities for the GCC-EH Scheme -- - ------------------------------------------------------------------ - - function Remove - (Top : EOA; - Excep : GNAT_GCC_Exception_Access) return Boolean; - -- Remove Excep from the stack starting at Top. - -- Return True if Excep was found and removed, false otherwise. - -- Hooks called when entering/leaving an exception handler for a given -- occurrence, aimed at handling the stack of active occurrences. The -- calls are generated by gigi in tree_transform/N_Exception_Handler. - procedure Begin_Handler (GCC_Exception : GNAT_GCC_Exception_Access); + procedure Begin_Handler (GCC_Exception : not null GCC_Exception_Access); pragma Export (C, Begin_Handler, "__gnat_begin_handler"); - procedure End_Handler (GCC_Exception : GNAT_GCC_Exception_Access); + procedure End_Handler (GCC_Exception : GCC_Exception_Access); pragma Export (C, End_Handler, "__gnat_end_handler"); - Setup_Key : constant := 16#DEAD#; - -- To handle the case of a task "transferring" an exception occurrence to - -- another task, for instance via Exceptional_Complete_Rendezvous, we need - -- to be able to identify occurrences which have been Setup and not yet - -- Propagated. We hijack one of the common header fields for that purpose, - -- setting it to a special key value during the setup process, clearing it - -- at the very beginning of the propagation phase, and expecting it never - -- to be reset to the special value later on. A 16-bit value is used rather - -- than a 32-bit value for static compatibility with 16-bit targets such as - -- AAMP (where type Unwind_Word will be 16 bits). - - function Is_Setup_And_Not_Propagated (E : EOA) return Boolean; - - procedure Set_Setup_And_Not_Propagated (E : EOA); - procedure Clear_Setup_And_Not_Propagated (E : EOA); - - procedure Save_Occurrence_And_Private - (Target : out Exception_Occurrence; - Source : Exception_Occurrence); - -- Copy all the components of Source to Target as well as the - -- Private_Data pointer. - -------------------------------------------------------------------- -- Accessors to Basic Components of a GNAT Exception Data Pointer -- -------------------------------------------------------------------- @@ -254,7 +251,7 @@ package body Exception_Propagation is function Import_Code_For (E : Exception_Data_Ptr) return Exception_Code; pragma Export (C, Import_Code_For, "__gnat_import_code_for"); - function EID_For (GNAT_Exception : GNAT_GCC_Exception_Access) + function EID_For (GNAT_Exception : not null GNAT_GCC_Exception_Access) return Exception_Id; pragma Export (C, EID_For, "__gnat_eid_for"); @@ -274,64 +271,24 @@ package body Exception_Propagation is All_Others_Value : constant Integer := 16#7FFF#; pragma Export (C, All_Others_Value, "__gnat_all_others_value"); - ------------ - -- Remove -- - ------------ - - function Remove - (Top : EOA; - Excep : GNAT_GCC_Exception_Access) return Boolean - is - Prev : GNAT_GCC_Exception_Access := null; - Iter : EOA := Top; - GCC_Exception : GNAT_GCC_Exception_Access; - - begin - -- Pop stack - - loop - pragma Assert (Iter.Private_Data /= System.Null_Address); - - GCC_Exception := To_GNAT_GCC_Exception (Iter.Private_Data); - - if GCC_Exception = Excep then - if Prev = null then - - -- Special case for the top of the stack: shift the contents - -- of the next item to the top, since top is at a fixed - -- location and can't be changed. - - Iter := GCC_Exception.Next_Exception; - - if Iter = null then - - -- Stack is now empty - - Top.Private_Data := System.Null_Address; - - else - Save_Occurrence_And_Private (Top.all, Iter.all); - Free (Iter); - end if; - - else - Prev.Next_Exception := GCC_Exception.Next_Exception; - Free (Iter); - end if; - - Free (GCC_Exception); + -------------------------------- + -- GNAT_GCC_Exception_Cleanup -- + -------------------------------- - return True; - end if; + procedure GNAT_GCC_Exception_Cleanup + (Reason : Unwind_Reason_Code; + Excep : not null GNAT_GCC_Exception_Access) is + pragma Unreferenced (Reason); - exit when GCC_Exception.Next_Exception = null; + procedure Free is new Unchecked_Deallocation + (GNAT_GCC_Exception, GNAT_GCC_Exception_Access); - Prev := GCC_Exception; - Iter := GCC_Exception.Next_Exception; - end loop; + Copy : GNAT_GCC_Exception_Access := Excep; + begin + -- Simply free the memory - return False; - end Remove; + Free (Copy); + end GNAT_GCC_Exception_Cleanup; --------------------------- -- CleanupUnwind_Handler -- @@ -341,17 +298,16 @@ package body Exception_Propagation is (UW_Version : Integer; UW_Phases : Unwind_Action; UW_Eclass : Exception_Class; - UW_Exception : not null access GNAT_GCC_Exception; + UW_Exception : not null GCC_Exception_Access; UW_Context : System.Address; UW_Argument : System.Address) return Unwind_Reason_Code is - pragma Unreferenced - (UW_Version, UW_Eclass, UW_Exception, UW_Context, UW_Argument); - + pragma Unreferenced (UW_Version, UW_Eclass, UW_Context, UW_Argument); begin -- Terminate when the end of the stack is reached if UW_Phases >= UA_END_OF_STACK then + Setup_Current_Excep (UW_Exception); Unhandled_Exception_Terminate; end if; @@ -362,54 +318,6 @@ package body Exception_Propagation is return URC_NO_REASON; end CleanupUnwind_Handler; - --------------------------------- - -- Is_Setup_And_Not_Propagated -- - --------------------------------- - - function Is_Setup_And_Not_Propagated (E : EOA) return Boolean is - GCC_E : constant GNAT_GCC_Exception_Access := - To_GNAT_GCC_Exception (E.Private_Data); - begin - return GCC_E /= null and then GCC_E.Header.Private1 = Setup_Key; - end Is_Setup_And_Not_Propagated; - - ------------------------------------ - -- Clear_Setup_And_Not_Propagated -- - ------------------------------------ - - procedure Clear_Setup_And_Not_Propagated (E : EOA) is - GCC_E : constant GNAT_GCC_Exception_Access := - To_GNAT_GCC_Exception (E.Private_Data); - begin - pragma Assert (GCC_E /= null); - GCC_E.Header.Private1 := 0; - end Clear_Setup_And_Not_Propagated; - - ---------------------------------- - -- Set_Setup_And_Not_Propagated -- - ---------------------------------- - - procedure Set_Setup_And_Not_Propagated (E : EOA) is - GCC_E : constant GNAT_GCC_Exception_Access := - To_GNAT_GCC_Exception (E.Private_Data); - begin - pragma Assert (GCC_E /= null); - GCC_E.Header.Private1 := Setup_Key; - end Set_Setup_And_Not_Propagated; - - -------------------------------- - -- Save_Occurrence_And_Private -- - -------------------------------- - - procedure Save_Occurrence_And_Private - (Target : out Exception_Occurrence; - Source : Exception_Occurrence) - is - begin - Save_Occurrence_No_Private (Target, Source); - Target.Private_Data := Source.Private_Data; - end Save_Occurrence_And_Private; - --------------------- -- Setup_Exception -- --------------------- @@ -423,80 +331,56 @@ package body Exception_Propagation is Current : EOA; Reraised : Boolean := False) is - Top : constant EOA := Current; - Next : EOA; - GCC_Exception : GNAT_GCC_Exception_Access; - + pragma Unreferenced (Excep, Current, Reraised); begin - -- The exception Excep is soon to be propagated, and the - -- storage used for that will be the occurrence statically allocated - -- for the current thread. This storage might currently be used for a - -- still active occurrence, so we need to push it on the thread's - -- occurrence stack (headed at that static occurrence) before it gets - -- clobbered. - - -- What we do here is to trigger this push when need be, and allocate a - -- Private_Data block for the forthcoming Propagation. - - -- Some tasking rendez-vous attempts lead to an occurrence transfer - -- from the server to the client (see Exceptional_Complete_Rendezvous). - -- In those cases Setup is called twice for the very same occurrence - -- before it gets propagated: once from the server, because this is - -- where the occurrence contents is elaborated and known, and then - -- once from the client when it detects the case and actually raises - -- the exception in its own context. - - -- The Is_Setup_And_Not_Propagated predicate tells us when we are in - -- the second call to Setup for a Transferred occurrence, and there is - -- nothing to be done here in this situation. This predicate cannot be - -- True if we are dealing with a Reraise, and we may even be called - -- with a raw uninitialized Excep occurrence in this case so we should - -- not check anyway. Observe the front-end expansion for a "raise;" to - -- see that happening. We get a local occurrence and a direct call to - -- Save_Occurrence without the intermediate init-proc call. - - if not Reraised and then Is_Setup_And_Not_Propagated (Excep) then - return; - end if; + -- In the GNAT-SJLJ case this "stack" only exists implicitly, by way of + -- local occurrence declarations together with save/restore operations + -- generated by the front-end, and this routine has nothing to do. - -- Allocate what will be the Private_Data block for the exception - -- to be propagated. + null; + end Setup_Exception; - GCC_Exception := new GNAT_GCC_Exception; + ------------------------- + -- Setup_Current_Excep -- + ------------------------- - -- If the Top of the occurrence stack is not currently used for an - -- active exception (the stack is empty) we just need to setup the - -- Private_Data pointer. + procedure Setup_Current_Excep + (GCC_Exception : not null GCC_Exception_Access) is + Excep : constant EOA := Get_Current_Excep.all; + begin + -- Setup the exception occurrence - -- Otherwise, we also need to shift the contents of the Top of the - -- stack in a freshly allocated entry and link everything together. + if GCC_Exception.Class = GNAT_Exception_Class then - if Top.Private_Data /= System.Null_Address then - Next := new Exception_Occurrence; - Save_Occurrence_And_Private (Next.all, Top.all); + -- From the GCC exception - GCC_Exception.Next_Exception := Next; - Top.Private_Data := GCC_Exception.all'Address; - end if; + declare + GNAT_Occurrence : constant GNAT_GCC_Exception_Access := + To_GNAT_GCC_Exception (GCC_Exception); + begin + Excep.all := GNAT_Occurrence.Occurrence; + end; + else - Top.Private_Data := GCC_Exception.all'Address; + -- A default one - Set_Setup_And_Not_Propagated (Top); - end Setup_Exception; + Excep.Id := Foreign_Exception'Access; + Excep.Msg_Length := 0; + Excep.Cleanup_Flag := False; + Excep.Exception_Raised := True; + Excep.Pid := Local_Partition_ID; + Excep.Num_Tracebacks := 0; + Excep.Private_Data := System.Null_Address; + end if; + end Setup_Current_Excep; ------------------- -- Begin_Handler -- ------------------- - procedure Begin_Handler (GCC_Exception : GNAT_GCC_Exception_Access) is + procedure Begin_Handler (GCC_Exception : not null GCC_Exception_Access) is pragma Unreferenced (GCC_Exception); - begin - -- Every necessary operation related to the occurrence stack has - -- already been performed by Propagate_Exception. This hook remains for - -- potential future necessity in optimizing the overall scheme, as well - -- a useful debugging tool. - null; end Begin_Handler; @@ -504,13 +388,68 @@ package body Exception_Propagation is -- End_Handler -- ----------------- - procedure End_Handler (GCC_Exception : GNAT_GCC_Exception_Access) is - Removed : Boolean; + procedure End_Handler (GCC_Exception : GCC_Exception_Access) is begin - Removed := Remove (Get_Current_Excep.all, GCC_Exception); - pragma Assert (Removed); + if GCC_Exception /= null then + + -- The exception might have been reraised, in this case the cleanup + -- mustn't be called. + + Unwind_DeleteException (GCC_Exception); + end if; end End_Handler; + ----------------------------- + -- Reraise_GCC_Exception -- + ----------------------------- + + procedure Reraise_GCC_Exception + (GCC_Exception : not null GCC_Exception_Access) is + begin + -- Simply propagate it + Propagate_GCC_Exception (GCC_Exception); + end Reraise_GCC_Exception; + + ----------------------------- + -- Propagate_GCC_Exception -- + ----------------------------- + + -- Call Unwind_RaiseException to actually throw, taking care of handling + -- the two phase scheme it implements. + + procedure Propagate_GCC_Exception + (GCC_Exception : not null GCC_Exception_Access) is + begin + -- Perform a standard raise first. If a regular handler is found, it + -- will be entered after all the intermediate cleanups have run. If + -- there is no regular handler, it will return. + + Unwind_RaiseException (GCC_Exception); + + -- If we get here we know the exception is not handled, as otherwise + -- Unwind_RaiseException arranges for the handler to be entered. Take + -- the necessary steps to enable the debugger to gain control while the + -- stack is still intact. + + Setup_Current_Excep (GCC_Exception); + Notify_Unhandled_Exception; + + -- Now, un a forced unwind to trigger cleanups. Control should not + -- resume there, if there are cleanups and in any cases as the + -- unwinding hook calls Unhandled_Exception_Terminate when end of stack + -- is reached. + + Unwind_ForcedUnwind (GCC_Exception, + CleanupUnwind_Handler'Address, + System.Null_Address); + + -- We get here in case of error. + -- The debugger has been notified before the second step above. + + Setup_Current_Excep (GCC_Exception); + Unhandled_Exception_Terminate; + end Propagate_GCC_Exception; + ------------------------- -- Propagate_Exception -- ------------------------- @@ -530,18 +469,6 @@ package body Exception_Propagation is GCC_Exception : GNAT_GCC_Exception_Access; begin - pragma Assert (Excep.Private_Data /= System.Null_Address); - - -- Retrieve the Private_Data for this occurrence and set the useful - -- flags for the personality routine, which will be called for each - -- frame via Unwind_RaiseException below. - - GCC_Exception := To_GNAT_GCC_Exception (Excep.Private_Data); - - Clear_Setup_And_Not_Propagated (Excep); - - GCC_Exception.Id := Excep.Id; - -- Compute the backtrace for this occurrence if the corresponding -- binder option has been set. Call_Chain takes care of the reraise -- case. @@ -565,32 +492,17 @@ package body Exception_Propagation is Call_Chain (Excep); - -- Perform a standard raise first. If a regular handler is found, it - -- will be entered after all the intermediate cleanups have run. If - -- there is no regular handler, it will return. + -- Allocate the GCC exception - Unwind_RaiseException (GCC_Exception); + GCC_Exception := new GNAT_GCC_Exception' + (Header => (Class => GNAT_Exception_Class, + Cleanup => GNAT_GCC_Exception_Cleanup'Address, + Private1 => 0, + Private2 => 0), + Occurrence => Excep.all); - -- If we get here we know the exception is not handled, as otherwise - -- Unwind_RaiseException arranges for the handler to be entered. Take - -- the necessary steps to enable the debugger to gain control while the - -- stack is still intact. - - Notify_Unhandled_Exception; - - -- Now, un a forced unwind to trigger cleanups. Control should not - -- resume there, if there are cleanups and in any cases as the - -- unwinding hook calls Unhandled_Exception_Terminate when end of stack - -- is reached. - - Unwind_ForcedUnwind (GCC_Exception, - CleanupUnwind_Handler'Address, - System.Null_Address); - - -- We get here in case of error. - -- The debugger has been notified before the second step above. - - Unhandled_Exception_Terminate; + -- Propagate it. + Propagate_GCC_Exception (To_GCC_Exception (GCC_Exception)); end Propagate_Exception; ------------- @@ -598,10 +510,10 @@ package body Exception_Propagation is ------------- function EID_For - (GNAT_Exception : GNAT_GCC_Exception_Access) return Exception_Id + (GNAT_Exception : not null GNAT_GCC_Exception_Access) return Exception_Id is begin - return GNAT_Exception.Id; + return GNAT_Exception.Occurrence.Id; end EID_For; --------------------- @@ -633,67 +545,4 @@ package body Exception_Propagation is return E.all.Lang; end Language_For; - ----------- - -- Notes -- - ----------- - - -- The current model implemented for the stack of occurrences is a - -- simplification of previous attempts, which all proved to be flawed or - -- would have needed significant additional circuitry to be made to work - -- correctly. - - -- We now represent every propagation by a new entry on the stack, which - -- means that an exception occurrence may appear more than once (e.g. when - -- it is reraised during the course of its own handler). - - -- This may seem overcostly compared to the C++ model as implemented in - -- the g++ v3 libstd. This is actually understandable when one considers - -- the extra variations of possible run-time configurations induced by the - -- freedom offered by the Save_Occurrence/Reraise_Occurrence public - -- interface. - - -- The basic point is that arranging for an occurrence to always appear at - -- most once on the stack requires a way to determine if a given occurrence - -- is already there, which is not as easy as it might seem. - - -- An attempt was made to use the Private_Data pointer for this purpose. - -- It did not work because: - - -- 1) The Private_Data has to be saved by Save_Occurrence to be usable - -- as a key in case of a later reraise, - - -- 2) There is no easy way to synchronize End_Handler for an occurrence - -- and the data attached to potential copies, so these copies may end - -- up pointing to stale data. Moreover ... - - -- 3) The same address may be reused for different occurrences, which - -- defeats the idea of using it as a key. - - -- The example below illustrates: - - -- Saved_CE : Exception_Occurrence; - - -- begin - -- raise Constraint_Error; - -- exception - -- when CE: others => - -- Save_Occurrence (Saved_CE, CE); <= Saved_CE.PDA = CE.PDA - -- end; - - -- <= Saved_CE.PDA is stale (!) - - -- begin - -- raise Program_Error; <= Saved_CE.PDA = PE.PDA (!!) - -- exception - -- when others => - -- Reraise_Occurrence (Saved_CE); - -- end; - - -- Not releasing the Private_Data via End_Handler could be an option, - -- but making this to work while still avoiding memory leaks is far - -- from trivial. - - -- The current scheme has the advantage of being simple, and induces - -- extra costs only in reraise cases which is acceptable. - end Exception_Propagation; diff --git a/gcc/ada/a-synbar.adb b/gcc/ada/a-synbar.adb index 7966b23..35a53aa 100644 --- a/gcc/ada/a-synbar.adb +++ b/gcc/ada/a-synbar.adb @@ -40,8 +40,11 @@ package body Ada.Synchronous_Barriers is -- The condition "Wait'Count = Release_Threshold" opens the barrier when -- the required number of tasks is reached. The condition "Keep_Open" -- leaves the barrier open while there are queued tasks. While there are - -- tasks in the queue no new task will be queued, guaranteeing that the - -- barrier will remain open only for those tasks already inside. + -- tasks in the queue no new task will be queued (no new protected + -- action can be started on a protected object while another protected + -- action on the same protected object is underway, RM 9.5.1 (4)), + -- guaranteeing that the barrier will remain open only for those tasks + -- already inside the queue when the barrier was open. entry Wait (Notified : out Boolean) when Keep_Open or else Wait'Count = Release_Threshold diff --git a/gcc/ada/exp_ch11.adb b/gcc/ada/exp_ch11.adb index c18b31a..2f16743 100644 --- a/gcc/ada/exp_ch11.adb +++ b/gcc/ada/exp_ch11.adb @@ -1665,6 +1665,15 @@ package body Exp_Ch11 is -- does not have a choice parameter specification, then we provide one. else + + -- Don't expand if back end exception handling active + + if VM_Target = No_VM + and then Exception_Mechanism = Back_End_Exceptions + then + return; + end if; + -- Find innermost enclosing exception handler (there must be one, -- since the semantics has already verified that this raise statement -- is valid, and a raise with no arguments is only permitted in the diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi index b2531ad..faf3e83 100644 --- a/gcc/ada/gnat_rm.texi +++ b/gcc/ada/gnat_rm.texi @@ -5074,23 +5074,23 @@ Syntax: @smallexample @c ada pragma Test_Case ( [Name =>] static_string_Expression - ,[Mode =>] (Normal | Robustness) + ,[Mode =>] (Nominal | Robustness) [, Requires => Boolean_Expression] [, Ensures => Boolean_Expression]); @end smallexample @noindent The @code{Test_Case} pragma allows defining fine-grain specifications -for use by testing and verification tools. The compiler only checks its +for use by testing and verification tools. The compiler checks its validity but the presence of pragma @code{Test_Case} does not lead to any modification of the code generated by the compiler. @code{Test_Case} pragmas may only appear immediately following the -(separate) declaration of a subprogram. Only other pragmas may intervene -(that is appear between the subprogram declaration and its -postconditions). +(separate) declaration of a subprogram in a package declaration, inside +a package spec unit. Only other pragmas may intervene (that is appear +between the subprogram declaration and a test case). -The compiler checks that boolean expression given in @code{Requires} and +The compiler checks that boolean expressions given in @code{Requires} and @code{Ensures} are valid, where the rules for @code{Requires} are the same as the rule for an expression in @code{Precondition} and the rules for @code{Ensures} are the same as the rule for an expression in @@ -5103,7 +5103,7 @@ package Math_Functions is ... function Sqrt (Arg : Float) return Float; pragma Test_Case (Name => "Test 1", - Mode => Normal, + Mode => Nominal, Requires => Arg < 100, Ensures => Sqrt'Result < 10); ... @@ -5113,10 +5113,10 @@ end Math_Functions; @noindent The meaning of a test case is that, if the associated subprogram is executed in a context where @code{Requires} holds, then @code{Ensures} -should hold when the subprogram returns. Mode @code{Normal} indicates -that the input context should satisfy the normal precondition of the +should hold when the subprogram returns. Mode @code{Nominal} indicates +that the input context should satisfy the precondition of the subprogram, and the output context should then satisfy its -postcondition. More @code{Robustness} indicates that the normal pre- and +postcondition. More @code{Robustness} indicates that the pre- and postcondition of the subprogram should be ignored for this test case. @node Pragma Thread_Local_Storage diff --git a/gcc/ada/raise-gcc.c b/gcc/ada/raise-gcc.c index fb0ec81..6dff0de 100644 --- a/gcc/ada/raise-gcc.c +++ b/gcc/ada/raise-gcc.c @@ -101,6 +101,7 @@ __gnat_Unwind_RaiseException (_Unwind_Exception *); _Unwind_Reason_Code __gnat_Unwind_ForcedUnwind (_Unwind_Exception *, void *, void *); +extern void __gnat_setup_current_excep (_Unwind_Exception *); #ifdef IN_RTS /* For eh personality routine */ @@ -108,6 +109,10 @@ __gnat_Unwind_ForcedUnwind (_Unwind_Exception *, void *, void *); #include "unwind-dw2-fde.h" #include "unwind-pe.h" +/* The known and handled exception classes. */ + +#define CXX_EXCEPTION_CLASS 0x474e5543432b2b00ULL +#define GNAT_EXCEPTION_CLASS 0x474e552d41646100ULL /* -------------------------------------------------------------- -- The DB stuff below is there for debugging purposes only. -- @@ -853,39 +858,51 @@ extern Exception_Id EID_For (_GNAT_Exception * e); static int is_handled_by (_Unwind_Ptr choice, _GNAT_Exception * propagated_exception) { - /* Pointer to the GNAT exception data corresponding to the propagated - occurrence. */ - _Unwind_Ptr E = (_Unwind_Ptr) EID_For (propagated_exception); - - /* Base matching rules: An exception data (id) matches itself, "when - all_others" matches anything and "when others" matches anything unless - explicitly stated otherwise in the propagated occurrence. */ - - bool is_handled = - choice == E - || choice == GNAT_ALL_OTHERS - || (choice == GNAT_OTHERS && Is_Handled_By_Others (E)); - - /* In addition, on OpenVMS, Non_Ada_Error matches VMS exceptions, and we - may have different exception data pointers that should match for the - same condition code, if both an export and an import have been - registered. The import code for both the choice and the propagated - occurrence are expected to have been masked off regarding severity - bits already (at registration time for the former and from within the - low level exception vector for the latter). */ + if (propagated_exception->common.exception_class == GNAT_EXCEPTION_CLASS) + { + /* Pointer to the GNAT exception data corresponding to the propagated + occurrence. */ + _Unwind_Ptr E = (_Unwind_Ptr) EID_For (propagated_exception); + + /* Base matching rules: An exception data (id) matches itself, "when + all_others" matches anything and "when others" matches anything + unless explicitly stated otherwise in the propagated occurrence. */ + + bool is_handled = + choice == E + || choice == GNAT_ALL_OTHERS + || (choice == GNAT_OTHERS && Is_Handled_By_Others (E)); + + /* In addition, on OpenVMS, Non_Ada_Error matches VMS exceptions, and we + may have different exception data pointers that should match for the + same condition code, if both an export and an import have been + registered. The import code for both the choice and the propagated + occurrence are expected to have been masked off regarding severity + bits already (at registration time for the former and from within the + low level exception vector for the latter). */ #ifdef VMS - #define Non_Ada_Error system__aux_dec__non_ada_error - extern struct Exception_Data Non_Ada_Error; - - is_handled |= - (Language_For (E) == 'V' - && choice != GNAT_OTHERS && choice != GNAT_ALL_OTHERS - && ((Language_For (choice) == 'V' && Import_Code_For (choice) != 0 - && Import_Code_For (choice) == Import_Code_For (E)) - || choice == (_Unwind_Ptr)&Non_Ada_Error)); +# define Non_Ada_Error system__aux_dec__non_ada_error + extern struct Exception_Data Non_Ada_Error; + + is_handled |= + (Language_For (E) == 'V' + && choice != GNAT_OTHERS && choice != GNAT_ALL_OTHERS + && ((Language_For (choice) == 'V' && Import_Code_For (choice) != 0 + && Import_Code_For (choice) == Import_Code_For (E)) + || choice == (_Unwind_Ptr)&Non_Ada_Error)); #endif - return is_handled; + return is_handled; + } + else + { +# define Foreign_Exception system__exceptions__foreign_exception; + extern struct Exception_Data Foreign_Exception; + + return choice == GNAT_ALL_OTHERS + || choice == GNAT_OTHERS + || choice == (_Unwind_Ptr)&Foreign_Exception; + } } /* Fill out the ACTION to be taken from propagating UW_EXCEPTION up to @@ -1079,9 +1096,6 @@ PERSONALITY_FUNCTION (version_arg_t version_arg, Condition Handling Facility. */ int uw_version = (int) version_arg; _Unwind_Action uw_phases = (_Unwind_Action) phases_arg; - - _GNAT_Exception * gnat_exception = (_GNAT_Exception *) uw_exception; - region_descriptor region; action_descriptor action; @@ -1089,7 +1103,7 @@ PERSONALITY_FUNCTION (version_arg_t version_arg, possible variation on VMS for IA64. */ if (uw_version != 1) { - #if defined (VMS) && defined (__IA64) +#if defined (VMS) && defined (__IA64) /* Assume we're called with sigargs/mechargs arguments if really unexpected bits are set in our first two formals. Redirect to the @@ -1103,7 +1117,7 @@ PERSONALITY_FUNCTION (version_arg_t version_arg, if ((unsigned int)uw_version & version_unexpected_bits_mask && (unsigned int)uw_phases & phases_unexpected_bits_mask) return __gnat_handle_vms_condition (version_arg, phases_arg); - #endif +#endif return _URC_FATAL_PHASE1_ERROR; } @@ -1160,6 +1174,9 @@ PERSONALITY_FUNCTION (version_arg_t version_arg, setup_to_install (uw_context, uw_exception, action.landing_pad, action.ttype_filter); + /* Write current exception, so that it can be retrieved from Ada. */ + __gnat_setup_current_excep (uw_exception); + return _URC_INSTALL_CONTEXT; } diff --git a/gcc/ada/s-except.ads b/gcc/ada/s-except.ads index 30bc23a..0d21bc3 100644 --- a/gcc/ada/s-except.ads +++ b/gcc/ada/s-except.ads @@ -81,4 +81,9 @@ package System.Exceptions is private ZCX_By_Default : constant Boolean := System.ZCX_By_Default; + Foreign_Exception : exception; + pragma Unreferenced (Foreign_Exception); + -- This hidden exception is used to represent non-Ada exception to + -- Ada handlers. It is in fact referenced by its linking name. + end System.Exceptions; diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index b6d00db..1f07675 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -1365,6 +1365,12 @@ package body Sem_Ch13 is begin Args := New_List; + if Nkind (Parent (N)) = N_Compilation_Unit then + Error_Msg_N + ("incorrect placement of aspect `Test_Case`", E); + goto Continue; + end if; + if Nkind (Expr) /= N_Aggregate then Error_Msg_NE ("wrong syntax for aspect `Test_Case` for &", Id, E); diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb index f866cea..7f51294 100644 --- a/gcc/ada/sem_prag.adb +++ b/gcc/ada/sem_prag.adb @@ -500,24 +500,13 @@ package body Sem_Prag is procedure Check_Test_Case; -- Called to process a test-case pragma. The treatment is similar to the - -- one for pre- and postcondition in Check_Precondition_Postcondition. - -- There are three cases: - -- - -- The pragma appears after a subprogram spec - -- - -- The first step is to analyze the pragma, but this is skipped if - -- the subprogram spec appears within a package specification - -- (because this is the case where we delay analysis till the end of - -- the spec). Then (whether or not it was analyzed), the pragma is - -- chained to the subprogram in question (using Spec_TC_List and - -- Next_Pragma). - -- - -- The pragma appears at the start of subprogram body declarations - -- - -- In this case an immediate return to the caller is made, and the - -- pragma is NOT analyzed. - -- - -- In all other cases, an error message for bad placement is given + -- one for pre- and postcondition in Check_Precondition_Postcondition, + -- except the placement rules for the test-case pragma are stricter. + -- This pragma may only occur after a subprogram spec declared directly + -- in a package spec unit. In this case, the pragma is chained to the + -- subprogram in question (using Spec_TC_List and Next_Pragma) and + -- analysis of the pragma is delayed till the end of the spec. In + -- all other cases, an error message for bad placement is given. procedure Check_Valid_Configuration_Pragma; -- Legality checks for placement of a configuration pragma @@ -1972,9 +1961,9 @@ package body Sem_Prag is PO : Node_Id; procedure Chain_TC (PO : Node_Id); - -- If PO is an entry or a [generic] subprogram declaration node, then - -- the test-case applies to this subprogram and the processing for - -- the pragma is completed. Otherwise the pragma is misplaced. + -- If PO is a [generic] subprogram declaration node, then the + -- test-case applies to this subprogram and the processing for the + -- pragma is completed. Otherwise the pragma is misplaced. -------------- -- Chain_TC -- @@ -1993,20 +1982,22 @@ package body Sem_Prag is ("pragma% cannot be applied to abstract subprogram"); end if; + elsif Nkind (PO) = N_Entry_Declaration then + if From_Aspect_Specification (N) then + Error_Pragma ("aspect% cannot be applied to entry"); + else + Error_Pragma ("pragma% cannot be applied to entry"); + end if; + elsif not Nkind_In (PO, N_Subprogram_Declaration, - N_Generic_Subprogram_Declaration, - N_Entry_Declaration) + N_Generic_Subprogram_Declaration) then Pragma_Misplaced; end if; - -- Here if we have [generic] subprogram or entry declaration + -- Here if we have [generic] subprogram declaration - if Nkind (PO) = N_Entry_Declaration then - S := Defining_Entity (PO); - else - S := Defining_Unit_Name (Specification (PO)); - end if; + S := Defining_Unit_Name (Specification (PO)); -- Note: we do not analyze the pragma at this point. Instead we -- delay this analysis until the end of the declarative part in @@ -2054,6 +2045,16 @@ package body Sem_Prag is Pragma_Misplaced; end if; + -- Test cases should only appear in package spec unit + + if Get_Source_Unit (N) = No_Unit + or else not Nkind_In (Sinfo.Unit (Cunit (Get_Source_Unit (N))), + N_Package_Declaration, + N_Generic_Package_Declaration) + then + Pragma_Misplaced; + end if; + -- Search prior declarations P := N; @@ -2082,7 +2083,18 @@ package body Sem_Prag is elsif not Comes_From_Source (PO) then null; - -- Only remaining possibility is subprogram declaration + -- Only remaining possibility is subprogram declaration. First + -- check that it is declared directly in a package declaration. + -- This may be either the package declaration for the current unit + -- being defined or a local package declaration. + + elsif not Present (Parent (Parent (PO))) + or else not Present (Parent (Parent (Parent (PO)))) + or else not Nkind_In (Parent (Parent (PO)), + N_Package_Declaration, + N_Generic_Package_Declaration) + then + Pragma_Misplaced; else Chain_TC (PO); @@ -2090,14 +2102,6 @@ package body Sem_Prag is end if; end loop; - -- If we fall through loop, pragma is at start of list, so see if it - -- is in the pragmas after a library level subprogram. - - if Nkind (Parent (N)) = N_Compilation_Unit_Aux then - Chain_TC (Unit (Parent (Parent (N)))); - return; - end if; - -- If we fall through, pragma was misplaced Pragma_Misplaced; @@ -13301,7 +13305,7 @@ package body Sem_Prag is -- [, Requires => Boolean_EXPRESSION] -- [, Ensures => Boolean_EXPRESSION]); - -- MODE_TYPE ::= Normal | Robustness + -- MODE_TYPE ::= Nominal | Robustness when Pragma_Test_Case => Test_Case : declare begin @@ -13314,7 +13318,7 @@ package body Sem_Prag is Check_Optional_Identifier (Arg1, Name_Name); Check_Arg_Is_Static_Expression (Arg1, Standard_String); Check_Optional_Identifier (Arg2, Name_Mode); - Check_Arg_Is_One_Of (Arg2, Name_Normal, Name_Robustness); + Check_Arg_Is_One_Of (Arg2, Name_Nominal, Name_Robustness); if Arg_Count = 4 then Check_Identifier (Arg3, Name_Requires); diff --git a/gcc/ada/snames.ads-tmpl b/gcc/ada/snames.ads-tmpl index 3ff20b4..fbe0584 100644 --- a/gcc/ada/snames.ads-tmpl +++ b/gcc/ada/snames.ads-tmpl @@ -661,7 +661,7 @@ package Snames is Name_No_Requeue_Statements : constant Name_Id := N + $; Name_No_Task_Attributes : constant Name_Id := N + $; Name_No_Task_Attributes_Package : constant Name_Id := N + $; - Name_Normal : constant Name_Id := N + $; + Name_Nominal : constant Name_Id := N + $; Name_On : constant Name_Id := N + $; Name_Policy : constant Name_Id := N + $; Name_Parameter_Types : constant Name_Id := N + $; |