!standard 11.4.1 (14) 06-02-03 AI95-00446/01 !class binding interpretation 06-02-03 !status Amendment 200Y 04-03-24 !status WG9 Approved 06-06-09 !status work item 06-02-03 !status WG9 Approved (as part of AI-329) 04-06-18 !status ARG Approved (as part of AI-329) 9-0-1 04-03-06 !status work item 06-02-03 !status received 06-02-03 !priority High !difficulty Easy !subject Raise_Exception for Null_Id !summary Ada.Exceptions.Raise_Exception is changed to always raise an exception. If Raise_Exception is passed Null_Id, it raises Constraint_Error, like several of the other operations in Ada.Exceptions. !question Ada 2005 introduces the No_Return pragma. This pragra could be applied to Raise_Exception if it always raised an exception. It does not only if passed a Null_Id. But this case is most likely to represent a bug rather than an intended result. Should Raise_Exception always raise an exception? (Yes.) !recommendation (See Summary.) !wording Modify 11.4.1(14) as follows: [Raise_Exception and] Reraise_Occurrence [have] {has} no effect in the case of [Null_Id or] Null_Occurrence. {Raise_Exception,} Exception_Message, ... !discussion The existing situation where Raise_Exception has no effect when passed Null_Id seems to be of little value. Being able to declare Raise_Exception as a No_Return procedure would have significant value, since it is essentially always used that way. To be consistent with other subprograms in this package, it would seem best to raise Constraint_Error when Raise_Exception is given a Null_Id (though Program_Error would be another reasonable choice). We considered a similar change to Ada.Exceptions.Reraise_Occurrence as well. It has no effect when Null_Occurrence is passed, and that would need to change in order to apply the pragma. However, it is not unusual to pass the occurrence of an exception to other code to delay raising it. If there was no exception, passing Null_Occurrence for this works fine. Moreover, as there is no test for Null_Occurrence in Ada 95, this is the only way to write such code without additional flags. Thus, we considered the incompatibility unacceptable for Reraise_Occurrence. !corrigendum 11.4.1(14) @drepl Raise_Exception and Reraise_Occurrence have no effect in the case of Null_Id or Null_Occurrence. Exception_Message, Exception_Identity, Exception_Name, and Exception_Information raise Constraint_Error for a Null_Id or Null_Occurrence. @dby Reraise_Occurrence has no effect in the case of Null_Occurrence. Raise_Exception, Exception_Message, Exception_Identity, Exception_Name, and Exception_Information raise Constraint_Error for a Null_Id or Null_Occurrence. !ACATS test Create/modify an ACATS test to ensure that Raise_Exception, when passed a Null_Id, raises Constraint_Error. !appendix From: Robert Dewar Sent: Thursday, December 8, 2005 11:45 AM For the record, we already implemented this as described, namely maintaining a difference between Ada 95 behavior (returns silently) and Ada 2005 behavior (raises CE) when passed a null Exception_Id, but again, I would prefer to see Ada 95 compilers be allowed to adopt the Ada 2005 behavior (in the same way we allowed Ada 83 compilers to adopt the 8-bit characters of Ada 95). Either this is a trivial incompatibility, in which case why insist on it, or it is not, in which case it is a gratuitous non-upwards compatible change. It seems to me that insisting on different behavior in Ada 95 and Ada 2005 is trying to have it both ways. P.S. by the way, one of the reasons I think it is very important to be able to handle Ada 95 and Ada 2005 with a common run time is that for the forseeable future I envision mixed applications, with some units compiled in Ada 95 mode and some in Ada 2005 mode. **************************************************************** From: Tucker Taft Sent: Thursday, December 8, 2005 1:51 PM I guess this is another case where I would stick with the "Ada 95 is Ada 95" view, and have some kind of configuration pragma to request Ada 2005 semantics for things like this. If you believe mixed systems are likely, then you might want to make this the default for your customers, but I wouldn't expect other vendors to necessarily make the same decision about the "default" mode. **************************************************************** From: Robert Dewar Sent: Thursday, December 8, 2005 3:17 PM Well that is of course what we do, but once again if the view is that the semantics in this case are significantly different enough to worry about in this way, then I think it is totally unjustified to have introduced this gratuitous non-upwards compatibility. The only acceptable argument for a non-upwards compatibility is that you convince yourself that no Ada 95 program will run into the problem. But if that is the case, why worry about how Ada 95 programs treat the situation. If you think the Ada 95 decision was a mistake, then sure, correct it, but that should be a correction to Ada 95 (we have plenty of those :-) And by the way, this particular case is not hard to implement with zero overhead at run time, and a common library for the two modes (that's absolutely essential, and so far we have not had to compromise that requirement, though we have had to do some fiddling, as in this case). **************************************************************** From: Randy Brukardt Sent: Thursday, December 8, 2005 2:25 PM I disagree with Tucker, for the simple reason that the AI with this change (AI-241) is classified as a Binding Interpretation. It is *intended* to apply to Ada 95. Indeed, the ACATS tests were changed to not require either behavior years ago. The AI was originally written up as an Amendment, but it was changed to a Binding Interpretation at a meeting (November 2000). That implies that we considered whether it should apply to Ada 95, and decided it should apply to Ada 95. (The minutes unfortunately do not record the discussion that leads up to changing the status.) Surely we didn't change the status just to make more work for the editor! Ergo, there is no issue here -- what Robert wants is in fact the correct interpretation. (Indeed, when Robert asked the very same question back in May, he got the very same answer from me.) There won't be an ACATS test insisting on the change for Ada 95 (because of the WG 9 resolution), but there is no test that requires the old behavior, either. (And if any are found, it would be quickly repaired.) **************************************************************** From: Tucker Taft Sent: Thursday, December 8, 2005 2:35 PM Given this (which I suppose I should have known!), I disagree with Tucker too! If it is a BI, then it *is* Ada 95. **************************************************************** From: Robert Dewar Sent: Thursday, December 8, 2005 3:21 PM > I disagree with Tucker, for the simple reason that the AI with this change > (AI-241) is classified as a Binding Interpretation. It is *intended* to > apply to Ada 95. Indeed, the ACATS tests were changed to not require either > behavior years ago. Ah ha! What is confusing here is that this change is also written up in AI-329. Probably it does not belong there??? OK, I will remove the "and then Ada_Version >= Ada_2005" from our code :-) **************************************************************** From: Robert Dewar Sent: Thursday, December 8, 2005 3:56 PM I am confused, AI-241 is about testing for null occurrences, it does not change the semantics of Raise_Exception with a null exception_id value which is what we are talking about here. Randy??? **************************************************************** From: Randy Brukardt Sent: Thursday, December 8, 2005 4:29 PM My bad; I read "Raise_Exception" as "Raise_Occurrence". I suppose I should have actually read your subject line (it was truncated in my mailer). Anyway, I agree with you that this is another AI that is misclassified. Or more accurately, part of it is misclassified. It's silly that we have made a significant, incompatible change in this paragraph that applies to Ada 95, and yet another change that is far less likely to be incompatible in practice in the same paragraph is not supposed to apply to Ada 95. I'm reluctantly coming to the conclusion that anything short of a complete fork in technology (as we did for Ada 95 from Ada 83) is probably going to be impractical. There's just too many tiny differences, and clearly there is no will to reconcile them. (Our Ada 95 compiler has an Ada 83 switch, but it only provides "easy" compatibility; it doesn't try to undo the complex resolution changes, for instance. If you need perfect Ada 83 compatibility, we still offer a separate Ada 83 product. I wanted to avoid that this time, but it is not looking practical.) And I think that truly mixed programs won't really be possible (nor are they that likely to be necessary, as was the case with Ada 83). **************************************************************** From: Robert Dewar Sent: Thursday, December 8, 2005 4:32 PM > Anyway, I agree with you that this is another AI that is misclassified. Or > more accurately, part of it is misclassified. It's silly that we have made a > significant, incompatible change in this paragraph that applies to Ada 95, > and yet another change that is far less likely to be incompatible in > practice in the same paragraph is not supposed to apply to Ada 95. Yes, that's what I think, but no big deal, it was easy enough to accomodate without any big palava. What we do is to have the compiler recognize calls to this procedure (easy to do in our environment), and append a raise after the call if operating in Ada 2005 mode. > I'm reluctantly coming to the conclusion that anything short of a complete > fork in technology (as we did for Ada 95 from Ada 83) is probably going to > be impractical. There's just too many tiny differences, and clearly there is > no will to reconcile them. (Our Ada 95 compiler has an Ada 83 switch, but it > only provides "easy" compatibility; it doesn't try to undo the complex > resolution changes, for instance. If you need perfect Ada 83 compatibility, > we still offer a separate Ada 83 product. I wanted to avoid that this time, > but it is not looking practical.) And I think that truly mixed programs > won't really be possible (nor are they that likely to be necessary, as was > the case with Ada 83). Well we have implemented over two thirds of the Ada 2005 AI's, including almost all the big hard ones. And we have not come to this conclusion, we have managed to keep everything unified. We do have a few tricks, such as pragma Preelaborate_05; allowed only in the library, which says you are preelaborate if the program withing the library is in Ada 2005 mode, and otherwise you are not preelaborate. A bit of a kludge, but manageable. Neither of the issues I raised are blocking for us, but I do find it irritating to introduce incompatibilities, and take the attitude that it is just fine for people who want to move to Ada 2005 to face these but not fine for people using Ada 95. As I said a few times before, we took EXACTLY the opposite view when we allowed Ada 83 compilers to implement 8-bit characters. **************************************************************** From: Randy Brukardt Sent: Thursday, December 8, 2005 11:57 PM > Yes, that's what I think, but no big deal, it was easy enough to accomodate > without any big palava. What we do is to have the compiler recognize calls > to this procedure (easy to do in our environment), and append a raise after > the call if operating in Ada 2005 mode. Humm. That certainly would work, but wouldn't that cause trouble for implementing No_Return? The routine would raise Program_Error instead of Constraint_Error (a No_Return procedure that returns raises Program_Error). (Easily fixed by putting the raise conditionally before the routine, or eliminating the check if it is done at the point of the call.) (In our compiler, this is probably about the same as yours. Ada.Exceptions is a built-in package, so the compiler knows about the routine; that means no problem with No_Return (we can assume that it is OK and not include the check), and it can generate a raise rather than a skip if it is Null_Id.) > > I'm reluctantly coming to the conclusion that anything short of a complete > > fork in technology (as we did for Ada 95 from Ada 83) is probably going to > > be impractical. There's just too many tiny differences, and clearly there > > is no will to reconcile them. (Our Ada 95 compiler has an Ada 83 switch, > > but it only provides "easy" compatibility; it doesn't try to undo the > > complex resolution changes, for instance. If you need perfect Ada 83 > > compatibility, we still offer a separate Ada 83 product. I wanted to > > avoid that this time, but it is not looking practical.) And I think > > that truly mixed programs won't really be possible (nor are they > > that likely to be necessary, as was the case with Ada 83). > > Well we have implemented over two thirds of the Ada 2005 AI's, including > almost all the big hard ones. And we have not come to this conclusion, we > have managed to keep everything unified. Well, everybody's compilers are different. There just are so many interactions between things that trying to get them all perfect seems horrible. Adding a mechanism to make things "disappear" from the symbol table, for instance, is a multiday job, especially because a pragma would be very hard to make work (it would be too late to find the appropriate item). I'm sure it is possible to do (because pretty much anything is possible with enough work), but I'm wondering if starting with a clean slate would be better. I don't want to be spending lots of time inventing compatibility features rather than actually implementing useful stuff. **************************************************************** From: Robert Dewar Sent: Friday, December 9, 2005 7:02 AM > Humm. That certainly would work, but wouldn't that cause trouble for > implementing No_Return? The routine would raise Program_Error instead of > Constraint_Error (a No_Return procedure that returns raises Program_Error). > (Easily fixed by putting the raise conditionally before the routine, or > eliminating the check if it is done at the point of the call.) No, we don't mark this routine as No_Return, since it already has to be specially handled wrt No_Return in Ada 95 mode, and that same circuitry works fine in Ada 2005. > (In our compiler, this is probably about the same as yours. Ada.Exceptions > is a built-in package, so the compiler knows about the routine; that means > no problem with No_Return (we can assume that it is OK and not include the > check), and it can generate a raise rather than a skip if it is Null_Id.) Right, similar to what I describe above > Well, everybody's compilers are different. There just are so many > interactions between things that trying to get them all perfect seems > horrible. Adding a mechanism to make things "disappear" from the symbol > table, for instance, is a multiday job, especially because a pragma would be > very hard to make work (it would be too late to find the appropriate item). > > I'm sure it is possible to do (because pretty much anything is possible with > enough work), but I'm wondering if starting with a clean slate would be > better. I don't want to be spending lots of time inventing compatibility > features rather than actually implementing useful stuff. For us, this has been a minimal issue, the only times that it has seemed even a vague annoyance are the ones I brought to the attention of this list (by far the worst for us is the Wide_Wide stuff in Ada.Exceptions, but the mechanism we are adding for that, pragma Implicit_Child, will allow cleanups in the way we handle the implicit children of Text_IO in any case). And a fork would be FAR more work to deal with in terms of qualifying production compilers for dozens of targets. **************************************************************** From: Pascal Leroy Sent: Friday, December 9, 2005 4:12 AM > I would prefer to see Ada 95 compilers > be allowed to adopt the Ada 2005 behavior As we said at the last ARG meeting, we have to consider these issues on a case-by-case basis. In this particular instance I tend to agree with Robert. Passing a Null_Id to Raise_Exception is probably a bug anyway (no reason why anyone would do that) so raising C_E is actually helpful. Yes, it is unfortunate that this is entangled with the other AI 329 changes, but that's life. **************************************************************** From: Robert Dewar Sent: Friday, December 9, 2005 7:14 AM OK, so let's see if we can get a consensus on this, because it would be a nice cleanup (even though it would be extra work at this stage, since I already implemented the kludge to get different behavior in the two cases). By the way, it is not clear to me if the C_E gets raised with the given message, or an implementation dependent message (I have taken the latter view so far, which seems reasonable to me!) > Yes, it is unfortunate that this is entangled with the other AI 329 > changes, but that's life. Indeed :-) **************************************************************** From: Tucker Taft Sent: Friday, December 9, 2005 7:54 AM > As we said at the last ARG meeting, we have to consider these issues on a > case-by-case basis. In this particular instance I tend to agree with > Robert. Passing a Null_Id to Raise_Exception is probably a bug anyway (no > reason why anyone would do that) so raising C_E is actually helpful. I hate to be a curmudgeon on this, but I can see some cases where it would be intentional. For example (and this approximates some code we have in our run-time system), you have some cleanup that you want to do at the end of a routine under all circumstances, and then either return or raise an exception to report status to the caller. It seems pretty reasonable to store away an exception ID that represents the final status of the routine, then do the cleanup, and then pass this ID to Raise_Exception, and then return. If the ID is Null_Id, then Raise_Exception does nothing, and so you end up just returning. If ID is not Null_Id, then an exception is raised, and the return is bypassed. I can particularly see this when you create an Ada wrapper for a "C" routine, where you have some kind of status return from the C routine, you use that to decide whether to raise an exception or return normally, you save away your decision, you then clean up the various data structures you created to call the C routine (e.g. null-terminated strings, etc.), and then call Raise_Exception followed by return. For someone who has decided to start the transition to Ada 2005, I would assume that they would do some kind of systematic review of these kind of issues as part of that process. For someone who is sticking with Ada 95, I have trouble understanding why the semantics of this should change. You could say that if I believe the above, then why change the semantics in Ada 2005. But I think the decision process is somewhat different. For Ada 2005, we want the resulting language to be self-consistent, not look like a language with some new features bolted on. We are willing to accept some degree of upward incompatibility, if we think there are easy workarounds, and the problems will show up at compile-time or with an exception at run-time. I don't see why those decisions should affect folks who are sticking with Ada 95, or at least not until they choose to move up to a compiler that uses Ada 2005 semantics where there is a conflict (presumably to get a jump on the ultimate transition). > Yes, it is unfortunate that this is entangled with the other AI 329 > changes, but that's life. This seems like *not* something that could be considered a Binding Interpretation, even if it were all by itself as a separate AI. The existing semantics are well-defined, and even potentially useful under certain circumstances. We made the decision for Ada 2005 that the existing semantics were error prone, but that is for new code. Presumably for existing code, the error-prone-ness has already been dealt with. **************************************************************** From: Robert Dewar Sent: Friday, December 9, 2005 12:28 PM > I hate to be a curmudgeon on this, but I can see some cases where > it would be intentional. For example (and this approximates some > code we have in our run-time system), you have some cleanup that > you want to do at the end of a routine under all circumstances, > and then either return or raise an exception to report status > to the caller. It seems pretty reasonable to store away an exception > ID that represents the final status of the routine, then do the > cleanup, and then pass this ID to Raise_Exception, and then return. > If the ID is Null_Id, then Raise_Exception does nothing, and so > you end up just returning. If ID is not Null_Id, then an exception > is raised, and the return is bypassed. If you believe this then you should NEVER have countenanced this gratuitous non-upwards compatibility > For someone who has decided to start the transition to Ada 2005, > I would assume that they would do some kind of systematic review > of these kind of issues as part of that process. For someone who > is sticking with Ada 95, I have trouble understanding why the > semantics of this should change. You must live in another world, and one which would entirely prevent ANY of our serious customers moving to Ada 2005. A systematic review of millions of lines of code is simply out of the question. If this requirement had been true of Ada 95 it would have been the case that even fewer users would have made the transition to Ada 95 (as you know many still have not made this transition). > You could say that if I believe the above, then why change the > semantics in Ada 2005. But I think the decision process is > somewhat different. For Ada 2005, we want the resulting language > to be self-consistent, not look like a language with some new > features bolted on. We are willing to accept some degree of > upward incompatibility, if we think there are easy workarounds, > and the problems will show up at compile-time or with an exception > at run-time. I don't see why those decisions should affect folks > who are sticking with Ada 95, or at least not until they choose > to move up to a compiler that uses Ada 2005 semantics where there > is a conflict (presumably to get a jump on the ultimate transition). Of course such an argument may be valid in some cases, although the burden for me is very very high, and I see nothing in Ada 2005 that warrants an exception to the principle of no upwards incompatibility (I would have handled NOT NULL differently for instance), but the idea that it applies to Raise_Exception seems very dubious to me. After all, this is not causing any major issues now, Ada 95 users and vendors have lived with this for a decade, and it is not even on the radar screen as a significant problem > >> Yes, it is unfortunate that this is entangled with the other AI 329 >> changes, but that's life. > > This seems like *not* something that could be considered > a Binding Interpretation, even if it were all by itself as > a separate AI. The existing semantics are well-defined, and > even potentially useful under certain circumstances. We > made the decision for Ada 2005 that the existing semantics > were error prone, but that is for new code. Presumably for > existing code, the error-prone-ness has already been dealt with. I doubt it, are you really saying that you think all big systems are error free? Once again I am not arguing from the point of view of implementation simplicity here. Indeed if the ARG were to follow the suggestion of allowing back porting, it would be a pain in the neck, since I would have to undo what has already been done, test again, refile tests, worry about getting rid of the garbage ACATS test etc. However, I would do that if I could, just so that the situation with users in dealing with incompatibilities were clearer. **************************************************************** From: Randy Brukardt Sent: Friday, December 9, 2005 1:05 PM > This seems like *not* something that could be considered > a Binding Interpretation, even if it were all by itself as > a separate AI. The existing semantics are well-defined, and > even potentially useful under certain circumstances. We > made the decision for Ada 2005 that the existing semantics > were error prone, but that is for new code. Presumably for > existing code, the error-prone-ness has already been dealt with. If that's true, then AI-241 should not have been classified a BI. Because the same holds true there. In that case, the semantics aren't particularly useful, but we agreed that some programs might depend on those semantics simply because that was the only way to make the test. So, if anything, I think the AI-241 change is more likely in practice. My objection here is that we have two changes, similar in degree, in the *same* paragraph, and yet one is a BI requiring changes in Ada 95, and the other is an Amendment not even allowing the change in Ada 95. Does this strike anyone else as inconsistent??? So I say, let's reclassify this one (this part of this one) as a BI. **************************************************************** From: Pascal Leroy Sent: Saturday, December 10, 2005 4:50 AM Yes, it surely is inconsistent. I am open-minded and could be convinced by Tuck's argument (after all, the severity of incompatibilities is a judgment call) but then he should surely insist to reclassify AI 241 as an Amendment. **************************************************************** From: Jean-Pierre Rosen Sent: Monday, December 12, 2005 3:02 AM > I hate to be a curmudgeon on this, but I can see some cases where > it would be intentional. For example (and this approximates some > code we have in our run-time system), you have some cleanup that > you want to do at the end of a routine under all circumstances, > and then either return or raise an exception to report status > to the caller. It seems pretty reasonable to store away an exception > ID that represents the final status of the routine, then do the > cleanup, and then pass this ID to Raise_Exception, and then return. > If the ID is Null_Id, then Raise_Exception does nothing, and so > you end up just returning. If ID is not Null_Id, then an exception > is raised, and the return is bypassed. I think this issue was discussed, and the feeling was that if you do this, you are much better off saving the *occurrence* and reraising the occurrence. And reraising Null_Occurrence still does nothing. But reraising through the Exception_ID seemed very unlikely. **************************************************************** From: John Barnes Sent: Monday, December 12, 2005 2:08 AM I thought 241 was reclassified as an amendment. I discuss it in the rationale as if it were an amendment. Maybe we agreed to reclassify it but didn't actually do it. If so just reclassify it if that solves the problem. **************************************************************** From: Randy Brukardt Sent: Monday, December 12, 2005 12:57 PM > I thought 241 was reclassified as an amendment. I discuss it in the > rationale as if it were an amendment. That's backwards. It originally was an Amendment, and we decided to reclassify it as a Binding Interpretation. You probably never noticed that and failed to make that change in the Rationale. > Maybe we agreed to reclassify it but didn't actually do it. > > If so just reclassify it if that solves the problem. Well, reversing a carefully considered decision (either of them) requires more careful consideration. I'd be in favor of reclassifying the portion of AI-329 relating to Raise_Exception as a Binding Interpretation. As Jean-Pierre points out, we carefully considered compatibility and decided it wasn't a real issue. ****************************************************************