-- Convenient shortcut
type Exception_Action is access procedure (E : Exception_Occurrence);
+ pragma Favor_Top_Level (Exception_Action);
+
Global_Action : Exception_Action := null;
+ pragma Atomic (Global_Action);
pragma Export
(Ada, Global_Action, "__gnat_exception_actions_global_action");
-- Global action, executed whenever an exception is raised. Changing the
-- export name must be coordinated with code in g-excact.adb.
+ Global_Unhandled_Action : Exception_Action := null;
+ pragma Atomic (Global_Unhandled_Action);
+ pragma Export
+ (Ada, Global_Unhandled_Action,
+ "__gnat_exception_actions_global_unhandled_action");
+ -- Global action, executed whenever an unhandled exception is raised.
+ -- Changing the export name must be coordinated with code in g-excact.adb.
+
Raise_Hook_Initialized : Boolean := False;
pragma Export
(Ada, Raise_Hook_Initialized, "__gnat_exception_actions_initialized");
----------------------
procedure Notify_Exception (Excep : EOA; Is_Unhandled : Boolean) is
+ -- Save actions locally to avoid any race condition that would
+ -- reset them to null.
+ Action : constant Exception_Action := Global_Action;
+ Unhandled_Action : constant Exception_Action := Global_Unhandled_Action;
+
begin
-- Output the exception information required by the Exception_Trace
-- configuration. Take care not to output information about internal
To_Action (Exception_Data_Ptr (Excep.Id).Raise_Hook) (Excep.all);
end if;
- if Global_Action /= null then
- Global_Action (Excep.all);
+ if Is_Unhandled and Unhandled_Action /= null then
+ Unhandled_Action (Excep.all);
+ end if;
+
+ if Action /= null then
+ Action (Excep.all);
end if;
end Notify_Exception;
package body GNAT.Exception_Actions is
Global_Action : Exception_Action;
- pragma Import (C, Global_Action, "__gnat_exception_actions_global_action");
+ pragma Import
+ (Ada, Global_Action, "__gnat_exception_actions_global_action");
+ pragma Atomic (Global_Action);
-- Imported from Ada.Exceptions. Any change in the external name needs to
- -- be coordinated with a-except.adb
+ -- be coordinated with a-exextr.adb.
+
+ Global_Unhandled_Action : Exception_Action;
+ pragma Import
+ (Ada, Global_Unhandled_Action,
+ "__gnat_exception_actions_global_unhandled_action");
+ pragma Atomic (Global_Unhandled_Action);
+ -- Imported from Ada.Exceptions. Any change in the external name needs to
+ -- be coordinated with a-exextr.adb.
Raise_Hook_Initialized : Boolean;
pragma Import
procedure Register_Global_Action (Action : Exception_Action) is
begin
- Lock_Task.all;
Global_Action := Action;
- Unlock_Task.all;
end Register_Global_Action;
+ --------------------------------------
+ -- Register_Global_Unhandled_Action --
+ --------------------------------------
+
+ procedure Register_Global_Unhandled_Action (Action : Exception_Action) is
+ begin
+ Global_Unhandled_Action := Action;
+ end Register_Global_Unhandled_Action;
+
------------------------
-- Register_Id_Action --
------------------------
type Exception_Action is access
procedure (Occurrence : Exception_Occurrence);
+ pragma Favor_Top_Level (Exception_Action);
-- General callback type whenever an exception is raised. The callback
-- procedure must not propagate an exception (execution of the program
-- is erroneous if such an exception is propagated).
-- Action is called before the exception is propagated to user's code.
-- If Action is null, this will in effect cancel all exception actions.
+ procedure Register_Global_Unhandled_Action (Action : Exception_Action);
+ -- Similar to Register_Global_Action, called on unhandled exceptions
+ -- only.
+
procedure Register_Id_Action
(Id : Exception_Id;
Action : Exception_Action);
-------------------------------------
type Raise_Action is access procedure;
+ pragma Favor_Top_Level (Raise_Action);
-- A pointer to a procedure used in the Raise_Hook field
type Exception_Data;
-- the message if the variable is volatile, has an address
-- clause, is aliased, or is a renaming, or is imported.
- if Referenced_As_LHS_Check_Spec (E)
- and then No (Address_Clause (E))
- and then not Is_Volatile (E)
- then
+ if Referenced_As_LHS_Check_Spec (E) then
if Warn_On_Modified_Unread
+ and then No (Address_Clause (E))
+ and then not Is_Volatile (E)
and then not Is_Imported (E)
and then not Is_Aliased (E)
and then No (Renamed_Object (E))