Reputation: 3027
Is there a way to get GNAT to ensure all exception cases are handled?
To give an example:
package IO renames Ada.Text_IO;
package EIO renames Ada.IO_Exceptions;
procedure Open_File (File : in out IO.File_Type) is
begin
IO.Open (File, IO.In_File, "example.txt");
exception
when EIO.Use_Error =>
IO.Put_Line ("Use!");
when EIO.Device_Error =>
IO.Put_Line ("Device!");
end Open_File;
Open
can also raise Name_Error
so I would like GNAT to warn that case has not been handled.
I found pragma Restrictions (No_Exception_Propagation)
but that seems to apply the check to the standard library calls as well so Open
becomes unusable because it propagates exceptions itself. If I apply this to my example, I get:
14:07: warning: pragma Restrictions (No_Exception_Propagation) in effect
14:07: warning: this handler can never be entered, and has been removed
16:07: warning: pragma Restrictions (No_Exception_Propagation) in effect
16:07: warning: this handler can never be entered, and has been removed
For an example of what I want from another language; Nim has a raises
pragma to annotate what exceptions a procedure can raise, which the compiler enforces. The list can be empty, ie. raises: []
, and the compiler will require that all exceptions will be handled and not propagate. Is there an equivalent to this in Ada?
Upvotes: 2
Views: 185
Reputation: 39668
That is not possible in Ada.
Nim is able to do it because the raises
pragma is part of the function signature. Therefore, for any call, it is statically known which exceptions can be raised. This is not the case in Ada.
If you argue that the compiler could implicitly figure out which exceptions can be raised by any subroutine, that is true but does not solve the problem because Ada allows for both dispatching calls and function pointers. For both of these you don't know statically the function which will be called (without a pointer analysis anyway, which is out of scope for most compilers) and therefore can't know the exceptions that could be raised (since they are not part of the signature).
Upvotes: 4
Reputation: 881
If you want to handle all available exceptions, you can use when others
in exception
section. Your example will look that:
package IO renames Ada.Text_IO;
package EIO renames Ada.IO_Exceptions;
procedure Open_File (File : in out IO.File_Type) is
begin
IO.Open (File, IO.In_File, "example.txt");
exception
when An_Exception : others =>
IO.Put_Line (EIO.Exception_Message(An_Exception));
end Open_File;
If you want to handle each exception in a separated way, then you have to list each of exceptions separately (as in your example). But compiler will not warn you about missing handler of an exception.
Upvotes: 4