CVS difference for ais/ai-00224.txt
--- ais/ai-00224.txt 2000/01/20 01:36:02 1.10
+++ ais/ai-00224.txt 2000/03/14 00:05:55 1.11
@@ -966,11 +966,6 @@
Looks good. I noticed one typo (see below).
->
-> Randy.
-
--Tuck
-
One typo:
>
@@ -1067,10 +1062,8 @@
*************************************************************
-From: Randy Brukardt [Randy@RRSoftware.Com]
+From: Randy Brukardt
Sent: Thursday, December 23, 1999 1:44 PM
-To: 'Eachus,Robert I.'; 'ARG@ACM.ORG'
-Subject: RE: AI-224 (Take 2)
You're changing the actual (RM-style) wording, while Jean-Pierre was objecting
to the wording of the example (at least, that's how it appeared to me).
@@ -1082,8 +1075,406 @@
have to be made, but these aren't permissions. For instance, the
Machine_Overflows=False case seems justified by 4.5(10), which simply says that
checks are made if Annex G is supported, and saying nothing further.
+
+*************************************************************
+
+From: Tucker Taft
+Sent: Friday, March 10, 2000 4:50 PM
+
+We have recently been implementing pragma unsuppress.
+As usual, we have found some subtleties that were not
+anticipated when we all glibly agreed that "of course the
+innermost one applies" when there is more than one pragma
+applicable.
+
+Here are some nasty cases:
+
+ pragma Suppress(Access_Check, On => Some_Type);
+ pragma Unsuppress(Access_Check);
+
+Which one applies? The Unsuppress comes later, but it is less
+specific. Our conclusion: a Suppress...On can only be overridden
+by an inner/later Unsuppress...On. A non-specific Unsuppress does not
+override a Suppress...On. Similarly, an Unsuppress...On will always
+override a non-specific Suppress, independent of which is innermost.
+
+Here is another:
+
+ in one file:
+
+ package P is
+ pragma Suppress(Access_Check);
+
+ ...
+ end P;
+
+ ------------
+ in a separate file:
+
+ pragma Unsuppress(Access_Check);
+
+ package body P is
+ ...
+ end P;
+
+Is Access_Check unsuppressed inside the body of P?
+--------
+In other words, a declarative-region-wide suppress is given
+in a package spec, and then a source-wide configuration pragma
+unsuppress is given in the file where the body appears.
+Which applies?
+
+This brings up a more general question which is an issue even without
+adding "unsuppress" to the mix. If a package spec is compiled in
+a source file where a source-wide configuration pragma suppress appears,
+does that pragma apply to the body of the package, even though the
+body is in a separate file? Similar question for a stub and a subunit...
+In other words, at the end of a package spec, should one take a
+snapshot of the suppression state, and reincarnate that state when
+beginning the package body. Corresponding question applies to
+a stub/subunit. When one does reincarnate that state, how is it affected
+by any pragmas specified for the source file containing the body/subunit?
+
+One possible approach:
+ a) All [un]suppress pragmas applicable at the end of a spec/stub
+ (including source-wide config pragmas) are "inherited" by the body/subunit.
+ However..
+ b) Any [un]suppress pragmas applicable at the point immediately
+ enclosing a body/subunit (including source-wide config pragmas)
+ are presumed to be "inner" to those inherited from the spec/stub.
+
+I realize this approach does not match the visibility rules, where
+the declarations inside a package spec hide homographic declarations
+enclosing the package body. However, for something like suppress,
+it seems like physical enclosure should be more important than
+state inherited from the spec/stub.
+
+I could also be convinced otherwise, though I will admit that the above
+approach has a relatively straightforward implementation, whereas other
+approaches might require keeping a more complicated and burdensome
+"suppression" state.
+
+*************************************************************
+
+From: Robert Dewar
+Sent: Friday, March 10, 2000 11:16 PM
+
+<<Which one applies? The Unsuppress comes later, but it is less
+specific. Our conclusion: a Suppress...On can only be overridden
+by an inner/later Unsuppress...On. A non-specific Unsuppress does not
+override a Suppress...On. Similarly, an Unsuppress...On will always
+override a non-specific Suppress, independent of which is innermost.
+>>
+
+Seems obviously correct to me :-)
+
+*************************************************************
- Randy.
+From: Robert Dewar
+Sent: Friday, March 10, 2000 11:17 PM
+
+for me by the way, Tuck's notes on this are consistent with the way
+things work now with suppress, a specific entity suppress always
+supercedes the no-suppress general case.
+
+*************************************************************
+
+From: Randy Brukardt
+Sent: Monday, March 13, 2000 12:23 PM
+
+Humm, seems like a total role reversal here: I wrote the wording for it, and
+you're trying to implement it. I guess we'll both get to see the other side
+now...
+
+> Here are some nasty cases:
+>
+> pragma Suppress(Access_Check, On => Some_Type);
+> pragma Unsuppress(Access_Check);
+>
+> Which one applies? The Unsuppress comes later, but it is less
+> specific. Our conclusion: a Suppress...On can only be overridden
+> by an inner/later Unsuppress...On. A non-specific Unsuppress does not
+> override a Suppress...On. Similarly, an Unsuppress...On will always
+> override a non-specific Suppress, independent of which is innermost.
+
+Well, I considered these cases when I wrote the text, and I am certain that the
+wording covers them, but it does not get the result that you want.
+
+I suppose it would be possible to rewrite the wording to define "specific" and
+"non-specific" checking pragmas, and try to make some rules about what does and
+does not override. It appears that the only special case that you want is that a
+non-specific Unsuppress does not override a specific Suppress. Otherwise,
+everything would work as defined in the AI. Is that correct?
+
+I would be concerned about this change introducing anomalies. Once we deviate
+from a strict stacking scheme, we're a lot more likely to get some strange
+effects. For instance, does a Unsuppress...On override a Suppress...On for a
+related entity? (It is clear that the names given in the On=> may relate to
+different aspects of the same entity.) Consider:
+
+ type Some_Type is access ....
+ subtype Sub_Type is Some_Type <some constraint>;
+
+ pragma Suppress (Access_Check, On => Sub_Type);
+ pragma Unsuppress (Access_Check, On => Some_Type);
+ -- Is the check on Sub_Type suppressed here?
+
+I also wonder if this is a good idea. I don't think we really care what happens
+with same-scope Suppress/Unsuppress as long as we can define it; what is
+important that *inner* scope Unsuppress works as intended. The problem is that
+the intended use of Unsuppress is to insure that checks are made in a subprogram
+or block that depends on the raising of exceptions. A programmer needing that is
+probably going to stick one or more non-specific Unsuppress pragmas into the
+subprogram or block. They would be pretty surprised if the Unsuppress didn't
+work because somewhere in the program there was an Suppress (On =>) on the type.
+
+This reminds me why I think the Suppress (,On =>) is the tool of the devil.
+Because it allows programmers to end-run Ada checking on some type, leaving a
+situation where any definition of Unsuppress is going to cause trouble for some
+users. In this case, I tend to lean toward making the canonical Ada semantics,
+meaning that it is impossible to unsuppress too much.
+
+> Here is another:
+> --------
+> In other words, a declarative-region-wide suppress is given
+> in a package spec, and then a source-wide configuration pragma
+> unsuppress is given in the file where the body appears.
+> Which applies?
+
+I think it has to be the Suppress, because it is in an inner scope. These things
+aren't textual (I wish they were, but that's irrelevant).
+
+> This brings up a more general question which is an issue even without
+> adding "unsuppress" to the mix. If a package spec is compiled in
+> a source file where a source-wide configuration pragma suppress appears,
+> does that pragma apply to the body of the package, even though the
+> body is in a separate file? Similar question for a stub and a subunit...
+> In other words, at the end of a package spec, should one take a
+> snapshot of the suppression state, and reincarnate that state when
+> beginning the package body. Corresponding question applies to
+> a stub/subunit. When one does reincarnate that state, how is it affected
+> by any pragmas specified for the source file containing the
+> body/subunit?
+
+This seems to be a separate question worth considering irrespective of
+Unsuppress. In that case, it ought to be handled in a separate AI, as
+sticking important questions into amendment AIs that may never be approved
+or adopted is a bad idea. Everyone, is this a "question worth answering"?
+
+> One possible approach:
+> a) All [un]suppress pragmas applicable at the end of a spec/stub
+> (including source-wide config pragmas) are "inherited"
+> by the body/subunit.
+> However..
+> b) Any [un]suppress pragmas applicable at the point immediately
+> enclosing a body/subunit (including source-wide config pragmas)
+> are presumed to be "inner" to those inherited from the spec/stub.
+>
+> I realize this approach does not match the visibility rules, where
+> the declarations inside a package spec hide homographic declarations
+> enclosing the package body. However, for something like suppress,
+> it seems like physical enclosure should be more important than
+> state inherited from the spec/stub.
+>
+> I could also be convinced otherwise, though I will admit that the above
+> approach has a relatively straightforward implementation, whereas other
+> approaches might require keeping a more complicated and burdensome
+> "suppression" state.
+
+While I can sympathize with this approach, I wouldn't want to have to write
+language wording to describe this. It would be necessary to exclude
+environment-wide configuration pragmas from the "however" (otherwise, they would
+"re-emerge" in the body after overriding them in the specification). That will
+complicate the wording a lot.
+
+Moreover, I wonder if this is what compilers are actually doing. I'm pretty sure
+that Janus/Ada doesn't propagate pragma Suppress to the body or to stubs.
+
+It could be very disruptive to users to force compilers to propagate Suppress to
+a body or stubs if they don't currently do so. Any code that depended on the
+raising of exceptions would suddenly start failing. It might also cover up bugs
+(by eliminating checks that would have caught bugs).
+
+Because of these issues, I think we need to consider any rule in this area
+*very* carefully.
+
+*************************************************************
+
+From: Robert Dewar
+Sent: Monday, March 13, 2000 1:22 PM
+
+One problem in general here is that while suppress has no semantics (since
+it can be ignored), unsuppress DOES have semantics. That means that the
+question unanswered in the RM:
+
+What exact entities should be tested for suppress to see if this check
+should be carried out?
+
+Has to be answered for unsuppress if you are not careful, and that way
+lies madness.
+
+I think it is clear from both this definitional point of view, and from
+an implementation point of view that an unsupress on a specific entity
+should only have the effect of cancelling a previous suppress on that
+specific entity.
+
+Yes, it sounds useful to be able to do a general suppress, and then
+unsuppress on a specific entity, but this is simply not viable in
+practice, unless you want to leave things entirely implementation
+dependent.
+
+To see what I am talking about here consider
+
+
+subtype r is integer range 1 .. 10;
+subtype s is integer range 1 .. 20;
+
+rv : r;
+sv : s;
+
+rv := sv;
+
+Now what entities to we test for suppression:
+
+rv
+sv
+integer
+r
+s
+...
+
+The RM really does not say clearly.
+
+*************************************************************
+
+From: Randy Brukardt
+Sent: Monday, March 13, 2000 5:37 PM
+
+Robert wrote:
+
+> One problem in general here is that while suppress has no semantics (since
+> it can be ignored), unsuppress DOES have semantics. That means that the
+> question unanswered in the RM:
+>
+> What exact entities should be tested for suppress to see if this check
+> should be carried out?
+>
+> Has to be answered for unsuppress if you are not careful, and that way
+> lies madness.
+
+
+Thanks for pointing this out. This point brings a whole different perspective to
+this discussion.
+
+I agree with this point - that we have to avoid any semantics that requires
+answering this question.
+
+More from Robert:
+
+> I think it is clear from both this definitional point of view, and from
+> an implementation point of view that an unsuppress on a specific entity
+> should only have the effect of canceling a previous suppress on that
+> specific entity.
+>
+> Yes, it sounds useful to be able to do a general suppress, and then
+> unsuppress on a specific entity, but this is simply not viable in
+> practice, unless you want to leave things entirely implementation
+> dependent.
+
+
+To avoid that, we also have to avoid the following:
+
+ pragma Suppress (Access_Check); -- A configuration pragma.
+
+ pragma Suppress (Access_Check, On => Some_Type);
+ ...
+ pragma Unsuppress (Access_Check, On => Some_Type);
+
+ -- Is Access_Check suppressed here on Some_Type?
+
+If we expect Access_Check to be not suppressed on Some_Type here, we have the
+same problem that Robert is concerned about. (That is, this is equivalent to a
+specific Unsuppress on a non-specific Suppress.) So merely requiring that an
+Unsuppress matches some Suppress pragma to have an effect is insufficient.
+
+To avoid Robert's problem, we would have to define the semantics of Unsuppress
+(at least specific Suppress) as cancellation of a specific pragma, and require
+equivalence of the names in the On part. (We probably could use conformance for
+this).
+
+It appears to me that such a rule would have a complex implementation, because a
+stack of pragmas would have to kept around (and be searchable) at all times.
+Perhaps this is not a problem for other implementations - it would be for
+Janus/Ada, but it also is irrelevant since Janus/Ada doesn't support the On
+=>parameter anyway.
+
+Another effect of this definition would be that it would be (nearly) impossible
+to use Unsuppress as a general and portable preventative measure, as you would
+have to give a non-specific one AND every possible specific one to insure a
+particular check is made. To me, this means the important problem has not been
+solved.
+
+---
+
+There is an alternative way out of this dilemma, although I think some people
+won't like it: refuse to provide Unsuppress (xxx, On => ...) in the RM. This
+would necessarily mean that general Unsuppress must undo specific Suppress (but
+I believe this is necessary to solve both user problems).
+
+Keep in mind that Unsuppress has two purposes. One is to provide a band-aid when
+someone suppresses checks on a unit or program and something breaks. While this
+band-aid use is important, it is not necessary for it to be well-defined in RM
+terms. That is, the main issue when using Unsuppress to fix a problem is that it
+undoes whatever is causing the problem, not that what exactly is happening is
+well-defined. I think we can trust compiler-writers to do the right thing here.
+
+On the other hand, using Unsuppress as a preventative absolutely must be
+portable. Let me give a concrete example of what I mean by using Unsuppress as a
+preventative.
+
+We distribute the Claw bindings as source code. We do this so customers can
+recompile it on a new version of a compiler, or on a different compiler, without
+have to depend on us to support it for them. Clearly, this means that we have
+limited control over the compiler options used when compiling the source. We
+want to make the source code as bullet-proof as possible, because we don't want
+to have to spend lots of technical support time tracking down problems. Thus, we
+try to write the code as generically as possible, so that the choice of compiler
+options does not affect the code.
+
+If we had a piece of code where it is necessary to handle Ada exceptions, we
+would want to be able to tell the compiler not to mess with it. A way to do that
+with the proposal as defined in the AI would be to put a pragma Unsuppress
+(Some_Check); into the code. The idea would be to prevent any compiler options
+(or ham-handed maintenance programmer, for that matter) from causing a subtle
+bug. For this use, it is critical that the meaning of Unsuppress be
+well-defined. Moreover, for this use, it is important that Unsuppress override
+ANYTHING Suppressed in an outer scope, not matter what the syntax of the
+command.
+
+It is the preventative use that is important to be well-defined and supported
+the same way by all compilers. That means that it is the primary need for the
+ARG to standardize and the ACAA to test. To the extent that this helps
+standardize the band-aid use, all the better.
+
+In order to better support the band-aid use, I would allow implementors to
+support Unsuppress (xxx, On => ...) without trying to define exactly what it
+means. This means leaving it Implementation-Defined, much as Robert noted we
+would have to do.
+
+So far as I can tell, there is no definitional problem with a non-specific
+Unsuppress overriding specific ones, nor any implementation problem. (You have
+to be able to back them out when the end of the scope of the Suppress is reached
+anyway, so there must be some sort of list around.)
+
+Thus, I am now convinced that the wording I proposed in the AI is correct,
+except that we have to make the meaning of Unsuppress (xxx, On => ...)
+implementation defined, at least in some cases. It certainly has to be
+implementation-defined if there exists any Suppress pragmas which name an
+overlapping check (such as All_Checks) and/or a non-conformant name which
+denotes a related entity and/or are non-specific. I'm not sure it is worth the
+effort to define the case where it does have to be *not* implementation defined:
+(when the check and name of a single Suppress pragma conform), but I will leave
+that to the rest of the ARG.
*************************************************************
Questions? Ask the ACAA Technical Agent