From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,b3f788f59498d3af X-Google-Attributes: gid103376,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!news1.google.com!border1.nntp.dca.giganews.com!border2.nntp.dca.giganews.com!nntp.giganews.com!cyclone1.gnilink.net!spamkiller.gnilink.net!gnilink.net!trnddc04.POSTED!72fcb693!not-for-mail From: Fionn Mac Cumhaill Newsgroups: comp.lang.ada Subject: Re: Exceptions and out procedure arguments (using GNAT GPL) Message-ID: References: <79c673pq5htg508nkoi935n3udqg5ps7r8@4ax.com> <1182181497.595409.300500@a26g2000pre.googlegroups.com> X-Newsreader: Forte Agent 4.2/32.1118 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Date: Tue, 19 Jun 2007 05:23:51 GMT NNTP-Posting-Host: 71.164.246.37 X-Complaints-To: abuse@verizon.net X-Trace: trnddc04 1182230631 71.164.246.37 (Tue, 19 Jun 2007 01:23:51 EDT) NNTP-Posting-Date: Tue, 19 Jun 2007 01:23:51 EDT Xref: g2news1.google.com comp.lang.ada:16228 X-Original-Bytes: 5187 Date: 2007-06-19T05:23:51+00:00 List-Id: On Mon, 18 Jun 2007 08:44:57 -0700, Adam Beneschan wrote: >On Jun 15, 6:05 pm, Fionn Mac Cumhaill >wrote: >> Consider a procedure that starts like this: >> >> procedure My_Procedure ( >> O: out integer >> ) >> is >> begin >> >> -- various statements follow >> >> O := 999; >> >> -- more statements follow >> >> raise My_Exception; >> >> I'm using GNAT GPL. >> >> My question is: >> >> Is the routine which calls My_Procedure guaranteed to get a value if >> it does something like this? >> >> X := 0; >> My_Procedure(X); >> >> and has an exception handler >> >> exception >> when My_Exception => >> null; >> >> Will X get a value of 999? > >No. When My_Procedure completes abnormally, due to an exception >raise, X should have the value that it had before My_Procedure was >called. An Ada compiler that causes X to be 999 here (if it wasn't >999 before) is incorrect. This isn't a matter of "is the compiler >allowed to optimize" or "all bets are off" or "you can't rely on the >value"; rather, the semantics *require* that X be unchanged. This is >because O is a by-copy parameter (6.2(3)), which means that inside the >subprogram, O denotes a *separate* object from X (6.2(2)), and O is >copied back to X only on *normal* completion of the subprogram >(6.4.1(17)), but an exception raise causes My_Procedure to be >completed abnormally (7.6.1(2)). > >By-reference parameters work differently. If, for example, your OUT >parameter were a tagged record, and you had assigned a component of it >to 999, it should still be 999 even after the exception in >My_Procedure is raised. As I interpret the rules in 11.6, this might >not be the case if the exception raise is due to a language-defined >check; if, after you assign the component to 999, you do an array >access on a nonexistent element, so that Constraint_Error is raised, >this is a language-defined check, and now I think the compiler may be >allowed to optimize in a way so that the assignment of the component >to 999 might not take place. But in your example, you have an >explicit raise of a user-defined exception, and 11.6 doesn't apply to >those, as I read it. The same would apply in an access parameter >case; if My_Procedure is abandoned due to a raise of a user-defined >exception, you can count on any assignments that you've already done >through the access value, but you can't count on assignments done >before My_Procedure is abandoned due to a language-defined check. > >Hope this helps, > -- Adam > It does indeed help, and convinces me that GNAT GPL 2007 has a bug. The example I gave is a highly condensed version of a problem I had while working on upgrading the MySQL binding in GNADE to work with MySQL 5. I found after posting my first message that the situation is even more confusing than I thought it was. Having (more or less) completed the work on the binding, I proceeded to lay another package on top of it so that I could have something that closely resembled the database package in GWindows. This would greatly simplify the task of moving a lot of Windows software to Linux. The sample is a highly condensed version of my Query procedure which raises an exception when a query sent to the MySQL database server returns no rows. The O argument in my sample is actually a handle whisch is used by other routines which extract data from the columns in the returned row set.The routine that uses My_Procedure to set the value of X is a procedure in the additional package. Let's call it My_Outer_Procedure. I have two test programs that use a query which returns no rows. What I have found is, in effect, that whether X is 0 or 999 depends on something in the routine that calls My_Outer_Procedure. I have two test programs which use a query which produces no rows, which means that My_Procedure always raises an exception. In one of the test programs, X is 0, and in the other it is 999, which makes no sense to me. I eliminated the problem by modifying the offending procedure to not raise exceptions. It now returns a status code in an additional out argument.