comp.lang.ada
 help / color / mirror / Atom feed
From: brbarkstrom@gmail.com
Subject: Re: How to get nice with GNAT?
Date: Sun, 23 Nov 2014 19:05:18 -0800 (PST)
Date: 2014-11-23T19:05:18-08:00	[thread overview]
Message-ID: <0d8452a9-68c9-4835-b6f3-17407132ca9f@googlegroups.com> (raw)
In-Reply-To: <m4th8h$jce$1@dont-email.me>

On Sunday, November 23, 2014 3:49:38 PM UTC-5, Jeffrey Carter wrote:
> On 11/23/2014 10:41 AM, brbarkstrom wrote:
> > 
> > I'm working in GNAT GPL, so my suggestion may not work with every
> > compiler.
> > 
> > On the other hand, in my code, the if following the exception in the
> > procedure is picked up and executed properly.  The code doesn't act
> > like the program has to fail if any exception is raised.
> 
> I don't think you're talking about exceptions. I took this program:
> 
> with Ada.Text_IO;
> procedure Boolean_Exception is
>    procedure Test (OK : out Boolean) is
>       -- empty declarative part
>    begin -- Test
>       OK := False;
> 
>       raise Constraint_Error;
>    end Test;
> 
>    OK : Boolean := True;
> begin -- Boolean_Exception
>    Test (OK => OK);
>    Ada.Text_IO.Put_Line (Item => "No exception");
> exception -- Boolean_Exception
> when others =>
>    Ada.Text_IO.Put_Line (Item => Boolean'Image (OK) );
> end Boolean_Exception;
> 
> compiled with GNAT 4.6 on Linux, and got:
> 
> $ gnatmake -gnatwa -gnatano -O2 -fstack-check boolean_exception.adb
> gcc-4.6 -c -gnatwa -gnatano -O2 -fstack-check boolean_exception.adb
> boolean_exception.adb:6:10: warning: assignment to pass-by-copy formal may have
> no effect
> boolean_exception.adb:6:10: warning: "raise" statement may result in abnormal
> return (RM 6.4.1(17))
> gnatbind -x boolean_exception.ali
> gnatlink boolean_exception.ali -O2 -fstack-check
> $ ./boolean_exception
> TRUE
> 
> What you're talking about doesn't work with GNAT.
> 
> -- 
> Jeff Carter
> "This school was here before you came,
> and it'll be here before you go."
> Horse Feathers
> 48

Here's a rather long response to your post:

I don't think you'll get a sensible response when you try to set
Test(OK => True); or Test(OK => False) when the specification of
the procedure Test has OK as an "out" variable.  It doesn't make 
sense try to set this value as input to a variable that emerges from the procedure (Test).

Here's a slight rewriting of the code you provided:

with Ada.Text_IO;
procedure exception_handling_0 is

   procedure test (OK : out Boolean) is
      -- empty declarative part
   begin -- test
      OK := False;
      raise Constraint_Error;
   end test;

   OK : Boolean := True;

begin -- exception_handling_0
   test (OK => OK);
   Ada.Text_IO.Put_Line (Item => "No exception");

exception
   when others =>
      Ada.Text_IO.Put_Line (Item => Boolean'Image (OK) );
end exception_handling_0;

The GNAT GPL GPS tool on my Ubuntu 14.04 LTS system returns the
two warnings:
7.10     warning: assignment to pass-by-copy formal may have no effect
7.10     warning: "raise" statement may result in abnormal return
           (RM 6.4.1(17))

In other words, a programmer shouldn't expect a variable input to
an "out" variable in the interface specification to have any relation
to whatever is generated in the procedure that is called.  Secondly,
an exception raised in the procedure test may result in an abnormal
return.  This is hardly a clean piece of code. 

When I run it, the output from the code does something that seems
to me to be an abnormal return.  It returns the output "TRUE".
The output claims that "the process terminated successfully, ...".  
It certainly isn't the expected behavior in a reasonable reading of the 
procedure text.  Rather it suggests that the compiler completely ignored
whatever went on in the procedure.

Putting the same code into a Windows XP installation of GNAT GPL 2014 with GPS
produces exactly the same warnings, compilation, and output.

In the original source code I provided, I used the following specification
file (called Common_Defs.ads):

with Ada.Characters.Latin_1;
with Ada.Strings;
with Ada.Strings.Bounded;
with Ada.Numerics;
with Ada.Numerics.generic_elementary_functions;

package Common_Defs is
  ------------------------------------------------------------------------------
  -- Generic Packages
  ------------------------------------------------------------------------------
  subtype real        is long_float;
  package Usr_Math    is new
                        Ada.Numerics.generic_elementary_functions(real);
  Std_Vstring_Length  : constant :=  256;
  package VString     is new
                        Ada.Strings.Bounded.Generic_Bounded_Length(Std_Vstring_Length);
  Long_Vstring_Lngth  : constant := 5000;
  package Long_Vstring is new
                        Ada.Strings.Bounded.Generic_Bounded_Length(Long_Vstring_Lngth);
  ------------------------------------------------------------------------------
  -- Constant
  ------------------------------------------------------------------------------
   TAB                         : constant Character := Ada.Characters.Latin_1.HT;
end Common_Defs;

Then, I created the source code

with Ada.Text_IO;
with Common_Defs; use Common_Defs;
procedure Test_Exception is

   -- Local Procedure Specification
   procedure Test (I       : in     Natural;
                   OK      :    out Boolean;
                   Err_Msg :    out Vstring.Bounded_String);

   -- Variables
   I       : Natural := 20;
   Test_OK : Boolean;
   Err_Msg : Vstring.Bounded_String;

   -- Local Procedure Body
   procedure Test (I       : in     Natural;
                   OK      :    out Boolean;
                   Err_Msg :    out Vstring.Bounded_String) is
      Max_I          : Natural := 10;
      I_Out_Of_Range : exception;      
   begin -- Test
      OK := False;
      Err_Msg := Vstring.To_Bounded_String("procedure Test was not initialized when this message was created.");
      if I <= Max_I then
         OK := True;
         Err_Msg := Vstring.To_Bounded_String("In procedure Test, I as input : ");
         Err_Msg := Vstring.Append(Err_Msg, Natural'image(I));
         Err_Msg := Vstring.Append(Err_Msg, " was less than or equal to ");
         Err_Msg := Vstring.Append(Err_Msg, Natural'image(Max_I));
      else
         raise I_Out_Of_Range;
      end if;
   exception
      when I_Out_Of_Range =>
         Err_Msg := Vstring.To_Bounded_String("In procedure Test, I as input : ");
         Err_Msg := Vstring.Append(Err_Msg, Natural'image(I));
         Err_Msg := Vstring.Append(Err_Msg, " was greater than ");
         Err_Msg := Vstring.Append(Err_Msg, Natural'image(Max_I));
         Err_Msg := Vstring.Append(Err_Msg, " which raises the constraint 'I_Out_Of_Range'.");
      when others =>
         Err_Msg := Vstring.To_Bounded_String("In procedure Test, something unexpected happened.");
   end Test;

begin -- Test_Exception
   Test (I       => 25,
         OK      => Test_OK,
         Err_Msg => Err_Msg);
   if Test_OK then
      Ada.Text_IO.Put_Line(Vstring.To_String(Err_Msg));
   else
      Ada.Text_IO.Put_Line(Vstring.To_String(Err_Msg));
   end if;
end Test_Exception; 

On Windows, this compiles without warnings.  After compilation, binding, and linking, it
runs and outputs the message 
"In procedure Test, I as input :  25 was greater than  10 which raises the constraint 'I_Out_Of_Range'."  It is clear that the initial setting of
OK and Err_Msg in the procedure have been changed as a result of the
operations during execution.

The behavior on the Ubuntu Linux 64-bit installation of GNAT GPL is identical.

My conclusions:

1.  One should not call a procedure to input an "out" variable as declared in the spec and
expect it to return values from the interior of the procedure.  In this code, the exception is not one of the system exceptions.
Rather, it is one declared normally in accord with the RM (11.1).  An exception handler follows the
specification in RM (11.2), where the Examples at the end of this definition show an approach
that the code I've provided follows.

2.  The handled sequence of statements allow variables set as "out" in the procedure specification
to appear as legitimate values (even using the "pass-by-copy" rule).  Thus, these "out" variables
can guide procedure actions for the calling procedure even when the called
procedure throws an exception.

Bruce B.


  reply	other threads:[~2014-11-24  3:05 UTC|newest]

Thread overview: 59+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-11-21 11:41 How to get nice with GNAT? Natasha Kerensikova
2014-11-21 12:42 ` Björn Lundin
2014-11-21 22:55 ` Randy Brukardt
2014-11-21 23:13   ` Björn Lundin
2014-11-22  9:45   ` How to get nice traceback " Natasha Kerensikova
2014-11-22  9:57     ` Dmitry A. Kazakov
2014-11-24 22:35     ` Randy Brukardt
2014-11-22 10:11 ` How to get nice " gautier_niouzes
2014-11-22 10:40   ` Natasha Kerensikova
2014-11-22 22:44 ` brbarkstrom
2014-11-22 23:24   ` Jeffrey Carter
2014-11-23 18:06   ` Björn Lundin
2014-11-23 16:13 ` brbarkstrom
2014-11-23 16:18   ` J-P. Rosen
2014-11-23 17:02   ` Jeffrey Carter
2014-11-23 17:41 ` brbarkstrom
2014-11-23 19:22   ` Simon Wright
2014-11-23 20:49   ` Jeffrey Carter
2014-11-24  3:05     ` brbarkstrom [this message]
2014-11-24  6:25       ` Jeffrey Carter
2014-11-24 14:39         ` brbarkstrom
2014-11-24 17:42       ` Dennis Lee Bieber
2014-11-25 13:45         ` brbarkstrom
2014-11-25 15:07           ` ake.ragnar.dahlgren
2014-11-25 15:51             ` brbarkstrom
2014-11-25 16:52             ` Jeffrey Carter
2014-11-25 19:18             ` G.B.
2014-11-25 20:47               ` brbarkstrom
2014-11-25 22:12             ` Randy Brukardt
2014-11-25 23:30               ` Simon Wright
2014-11-26  1:25                 ` G.B.
2014-11-26  7:35                   ` Simon Wright
2014-11-26 11:55                     ` Georg Bauhaus
2014-11-26 13:06                       ` Dmitry A. Kazakov
2014-11-26 13:36                         ` brbarkstrom
2014-11-26 21:27                         ` Randy Brukardt
2014-11-26 22:38                           ` brbarkstrom
2014-11-27  9:01                             ` Dmitry A. Kazakov
2014-11-27 13:53                               ` brbarkstrom
2014-11-27 17:19                                 ` Dmitry A. Kazakov
2014-12-01 22:25                                   ` Randy Brukardt
2014-12-02  8:42                                     ` Dmitry A. Kazakov
2014-12-03 21:41                                       ` Randy Brukardt
2014-12-06 12:02                                         ` Dmitry A. Kazakov
2014-12-08 22:45                                           ` Randy Brukardt
2014-12-09  8:51                                             ` Dmitry A. Kazakov
2014-12-09 23:14                                               ` Brad Moore
2014-12-09 17:59                                                 ` Dmitry A. Kazakov
2014-11-27  8:52                           ` Dmitry A. Kazakov
2014-11-26  6:18                 ` J-P. Rosen
2014-11-26  7:37                   ` Simon Wright
2014-11-26  8:41               ` Dmitry A. Kazakov
2014-11-25 18:33           ` Dennis Lee Bieber
2014-11-26  1:27             ` Dennis Lee Bieber
2014-11-26  3:29               ` brbarkstrom
2014-11-23 18:55 ` brbarkstrom
2014-11-23 19:30 ` brbarkstrom
2014-11-23 22:38   ` Simon Wright
2014-11-24  2:47     ` brbarkstrom
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox