Version 1.13 of ais/ai-00224.txt

Unformatted version of ais/ai-00224.txt version 1.13
Other versions for file ais/ai-00224.txt

!standard 11.5(1-8)          99-12-13 AI95-00224/02
!standard 11.5(27)
!class amendment 99-11-19
!status work item 99-11-19
!status received 99-11-19
!priority Medium
!difficulty Medium
!subject pragma Unsuppress
!summary
A pragma is introduced to require checking in a declarative region, irrespective of the use of pragma Suppress.
!problem
Ada code sometimes depends on the canonical checking semantics of the language. Consider, for instance, an integer saturation arithmetic package. The multiply operation might look like:
function "*" (Left, Right : Saturation_Type) return Saturation_Type is begin
return Integer(Left) * Integer(Right);
exception
when Constraint_Error =>
return Saturation_Type'Last;
end "*";
This function will not work properly without overflow checking. Ada 95 does not provide a way to indicate this to the compiler and programmers.
!proposal
A new pragma Unsuppress is defined.
pragma Unsuppress (identifier [, [On =>] name]);
The arguments of Unsuppress are the same as Suppress. Unsuppress can be used in the same places as Suppress, with the same scoping rules.
Pragma Unsuppress revokes the permission to suppress a check, that is, it means that the given check must be performed.
!wording
Define "Checking pragmas" and add pragma Suppress to 11.5(1) ("Checking pragmas" is in italics):
Checking pragmas give an implementation instructions on handling language-defined checks. A pragma Suppress gives permission to an implementation to omit certain language-defined checks, while a pragma Unsuppress revokes the permission to omit checks.
Add pragma Unsuppress to 11.5(3-4):
The forms of checking pragmas are as follows:
pragma Suppress(identifier [, [On =>] name]); pragma Unsuppress(identifier [, [On =>] name]);
Change 11.5(5) to apply to checking pragmas:
A checking pragma is allowed only immediately within a declarative_part, immediately within a package_specification, or as a configuration pragma.
Change 11.5(7) to apply to checking pragmas:
For a checking pragma that is immediately within a package_specification and includes a name, the name shall denote an entity (or several overloaded subprograms) declared immediately within the package_specification.
Change 11.5(8) to define the meaning of pragma UnSuppress:
A checking pragma applies to the named check from the place of the pragma to the end of the innermost enclosing declarative region, or, if the pragma is given in a package_specification and includes a name, to the end of the scope of the named entity. If the pragma includes a name, the pragma applies only to the named entity, or, for a subtype, on objects and values of its type. Otherwise, the pragma applies to all entities. A pragma Suppress gives permission to an implementation to omit the named check for any entities to which it applies. A pragma Unsuppress revokes the permission to omit the named check for any entities to which it applies. If there is no such permission at the point of a pragma Unsuppress, then the pragma has no effect. If permission has been given to suppress a given check, the check is said to be suppressed.
Change 11.5(27) to apply to checking pragmas:
An implementation is allowed to place restrictions on checking pragmas, subject only to the requirement that pragma Unsuppress shall allow any arguments supported by pragma Suppress. An implementation is allowed to add additional check names, with implementation-defined semantics. When Overflow_Check has been suppressed, an implementation may also suppress an unspecified subset of the Range_Checks.
Add after 11.5(27):
If more than one checking pragma which apply to the same check are given as configuration pragmas in different compilations, it is implementation-defined whether the check is suppressed.
Add an additional note after 11.5(29):
It is possible to give both a pragma Suppress and Unsuppress for the same check in the same declarative region. In that case, the last pragma given determines whether or not the check is suppressed. Similarly, it is possible to resuppress a check which has been unsuppressed by giving a pragma Suppress in an inner declarative region.
!example
We can use pragma Unsuppress to insure that checking occurs in the saturation multiply function given earlier:
function "*" (Left, Right : Saturation_Type) return Saturation_Type is
pragma Unsuppress (Overflow_Check);
begin return Integer(Left) * Integer(Right); exception when Constraint_Error => return Saturation_Type'Last; end "*";
If there is a pragma Suppress for Overflow_Check effective in "*", the Unsuppress will revoke the permission to omit the checks, thus requiring the checks to be made. If there is no pragma Suppress, then the pragma Unsuppress is ignored.
!discussion
Ada 95 provides an easy way to suppress checking over large areas of program text. Pragma Suppress can be used in a package specification to apply to an entire package, or even as a configuration pragma to apply to the entire program.
It is common for production versions of applications to be delivered with checking suppressed (perhaps for better performance or smaller code size). If pragma Suppress is applied to an entire package or program, code that requires checking will start to fail. Ada code that depends on the canonical checking semantics is not common, but it occurs frequently enough that most Ada programmers have been bitten by this problem at one time or another.
The problem is made worse by the fact that Ada 95 does not provide any way to turn off pragma Suppress over a smaller, inner region of the program. Therefore, fixing the problem requires moving the pragma Suppresses to individual packages and/or subprograms, which is clearly error-prone.
The pragma proposed here can be used both as a preventative measure (to insure that the code continues to work if a later programmer applies Suppress to the unit) and as a repair when checks are suppressed where they are required.
Note that the pragma Suppress that causes problems may not be explicit; many compilers include an option switch that effectively adds pragma Suppress to the start of each compilation unit.
The presence of pragma Unsuppress has no effect on compiler optimization of checks. A compiler is still allowed to remove checks that it can prove will not fail. This is why the wording is expressed in terms of "revoking the permission to omit" rather than "requiring" checks.
This proposal allows nested suppression of checks. That is, checks can be "resuppressed" inside of a region where checks are "unsuppressed" (required). This is necessary to prevent problems with code where the correctness depends on suppression of checks. (While such code is technically erroneous, in actual practice such does exist. We do not want to break it by being pedantic.) Such code would include a pragma Suppress. If checks could not be resuppressed, this code would fail if it was nested inside of a construct that contains an Unsuppress pragma, or if a Unsuppress configuration pragma was used. This would essentially be the current problem all over again, so the model where Unsuppress has precedence over Suppress was rejected.
Both pragmas Suppress and Unsuppress can be used as configuration pragmas. While it may it may seems that Unsuppress would be useless as a configuration pragma, it can be useful in conjunction with a Suppress pragma. For instance, the following pragmas would suppress all checks except storage checks in the entire program:
pragma Suppress (All_Checks); pragma Unsuppress (Storage_Check);
The exact meaning of a checking pragma when there is more than one in a particular declarative region depends on the order that it is given in. For example, reversing the order of the pragmas in the above example would simply suppress all checks. This poses a problem for configuration pragmas, though, as the order of configuration pragmas depends on the compilation model of the implementation. Of course, pragmas given in a single compilation have a well-defined order, so this gives us a solution which both allows the portable use of the pragmas without adding implementation burden. That is, we say that the meaning of conflicting checking pragmas given as configuration pragmas is implementation-defined unless the pragmas are given in the same compilation.
Restrictions can be placed on pragma Unsuppress. This is necessary to avoid burdening implementations. For instance, some implementations cannot support fine-grained suppression of single objects, and we don't want to start requiring that. We do require that anything supported for Suppress is also supported for Unsuppress, because it is important to be able to unsuppress checks suppressed over a larger area. Note that the reverse is not true; implementations can support more of Unsuppress than of Suppress if they desire.
Implementations should not produce warnings for usages of pragma Unsuppress which have no effect. (This is varies from common practice for other pragmas.) It is not an error to use a pragma Unsuppress where nothing is suppressed. Such a usage may very well be a "preventative" pragma, inserted to insure that checks are made in a unit that requires checks.
Alternative names (in particular "Require") were considered for this pragma. The name Unsuppress has two problems: First, it is a dubious English word; Ada pragmas are usually English words or phrases. Secondly, the preventative use of this pragma is very important, but "Unsuppress" appears to denote something that can only be used when checks actually are suppressed. This would likely lead to the under-use of the pragma as a preventative.
Irregardless, we use "Unsuppress" as the name of the pragma. There were two main factors for this. First, Unsuppress implies a relationship with Suppress, which other names cannot do. Second, Unsuppress is in current use as an extension in several compilers, and standardizing existing practice is usually better than inventing new ideas.
!appendix

*************************************************************

From: Randy Brukardt
Sent: Friday, November 19, 1999 7:34 PM

I've created this AI based on the discussion at the last ARG meeting.

I made one major change: based on the problem statement, the name "Unsuppress"
is the wrong name. In its intended use, we do not necessarily know that a
pragma Suppress has been applied to a region. Therefore, I renamed the pragma
to the more meaningful name "Require". I expect to catch some flak for this.

I find the preventative use of Require quite important, and quite in keeping
with the philosophy of Ada (make sure problems don't happen in the first
place).

It seems wrong to use a hypothetical pragma Unsuppress as a preventative: it
isn't undoing anything! Indeed, Ada users could imagine that it isn't allowed
unless there is a Suppress pragma to undo, and in that case, they would not
use it as a preventative.

I wonder if this entire clause shouldn't be renamed; it now is more about
controlling checks than about suppressing them.

One interesting issue: should pragma Require be allowed as a configuration
pragma? I have left it in, as that would allow effectively preventing the
adding of any pragma Suppresses to a program. That might be useful to some
paranoid organization. It also takes more words to disallow it than to allow
it.

Another interesting issue: should we allow "resuppression" of checks? I don't
feel strongly either way, but selected the current write-up because it was
more natural for pragma Require. The only way I see to support "resuppression"
is to write paragraph 8 in terms of "revoking the permission" to suppress
checks, which would complicate the description and would fit a pragma named
Unsuppress much better. It would also mean that a pragma Require would be
meaningless as a configuration pragma, as it would have no effect.

Having the pragma have no effect in some circumstances might be a impediment
to using it as a preventive, as a naive implementation of Ada might spew out
a warning everytime such a pragma occurs. I don't think we can say "don't warn
about this" in the reference manual, but without some guidance in this area,
I can see implementors going through the RM and implementing each pragma in
the "obvious" way [Janus/Ada, for instance, warns on any pragma that has no
effect], which would be the wrong thing to do in this case.

                        Randy.

*************************************************************

From: Robert Dewar
Sent: Monday, November 22, 1999 1:58 PM

This is as far as I can tell exactly the same semantics as pragma
Unsuppress in GNAT, and indeed these are the obvious semantics,
since they derive directly from Suppress.

I see no point whatsoever in changing the name

a) People are used to pragma Unsuppress and are using it now

b) the name is FAR more obvious, Require?? Require what? Sure you could
make the same question for Suppress, but we know suppress already.

I would strongly oppose changing the name, and most certainly we will not
implement it under the name Require in GNAT, because this would be unnecessary
duplication.

*************************************************************

From: Randy Brukardt
Sent: Monday, November 22, 1999 7:16 PM

> This is as far as I can tell exactly the same semantics as pragma
> Unsuppress in GNAT, and indeed these are the obvious semantics,
> since they derive directly from Suppress.

No, not exactly. The GNAT documentation that Ed handed out says "If there is no
corresponding pragma Suppress in effect, it [Unsuppress] has no effect." The
natural (to me) wording changes ended up with slightly different semantics, that
is that Suppress has no effect in a region where Require is given. The
difference is that Require can be given first -- it essentially is which is
given precedence.

> I see no point whatsoever in changing the name
>
> a) People are used to pragma Unsuppress and are using it now
>
> b) the name is FAR more obvious, Require?? Require what? Sure you could
> make the same question for Suppress, but we know suppress already.

Require the argument, just like Suppress is "Suppress the argument". I.e.

     pragma Require (Overflow_Check);

> I would strongly oppose changing the name.

OK, fair enough. In that case, I think that the answers to the two questions I
posed (does the pragma have an effect if no Suppress has been given, and should
"resuppression" be supported) should be different. And the pragma then has no
use as a preventative measure (both because it makes no sense to "Unsuppress" if
nothing is "Suppress"ed, and because a normally correct implementation of Ada 95
will complain about such pragmas).

> and most certainly we will not implement it under the name Require in GNAT,
> because this would be unnecessary duplication.

Well, this sounds very much like a Jean Ishbiah temper-tantrum: "If I can't have
my way, I'm going to take my ball and go home." I don't think this attitude is a
way to get useful work done (or to sway technical differences of opinion,
either). In any case, GNAT /= Ada. We want new features in Ada to be as useful
as possible to all users of Ada, not just to the customers of one particular
compiler.

			Randy.

*************************************************************

From: Robert Dewar
Sent: Monday, November 22, 1999 9:40 PM

<<No, not exactly. The GNAT documentation that Ed handed out says "If there is
no corresponding pragma Suppress in effect, it [Unsuppress] has no effect."
The natural (to me) wording changes ended up with slightly different semantics,
that is that Suppress has no effect in a region where Require is given. The
difference is that Require can be given first -- it essentially is which is
given precedence.>>

I think this is a bad choice, I prefer everything to nest, so that you
can nest Suppress/Unsuppress to any depth, and the innermost one is
what has the effect. This is the way GNAT works.

*************************************************************

From: Robert Dewar
Sent: Monday, November 22, 1999 9:41 PM

incidentally, although I would argue for the more natural semantics that
Suppress can undo Unsuppress and vice versa to any depth, I don't really
care. It is obviously more work to implement Randy's suggested semantics,
but in practice it is completely unimportant, the probability of ever
having more than one level of these pragmas is zero in any case.

*************************************************************

From: Randy Brukardt
Sent: Monday, November 22, 1999 10:12 PM

I agree that it doesn't matter much (the AI says as much).

I'm surprised that you say it would "obviously" take more work. I can see it
taking the same amount of work, but I don't see how it could take more. Indeed,
I would think it could take less work, because a stack isn't necessary to handle
it.

If others think it would take more work in their compilers, I'll junk the whole
AI and start over (the wording and discussion would have to be totally rewritten
to use a stacking semantics).

				Randy.

*************************************************************

From: John Barnes
Sent: Tuesday, November 23, 1999 4:37 AM

I don't  like the word Require either. It's a perfectly good word that
might be useful elsewhere whereas Unsuppress is a nasty word that is
most unlikely to be confused with anything else.

I would like to feel that the words have some symmetry.

John

*************************************************************

From: Stephen Michell
Sent: Tuesday, November 23, 1999 7:19 AM

John Barnes wrote:

> I don't like the word Require either. It's a perfectly good word that
> might be useful elsewhere whereas Unsuppress is a nasty word that is
> most unlikely to be confused with anything else.
>

An excellent point. Then Ada could be the language with the nastiest keywords
in town. No one would DARE critisize us then (at least - not to our faces).

> I would like to feel that the words have some symmetry.
>

It does seem clear that "unsuppress" is now in current usage and in the
lexicon of the community, so that is the way it must remain. It is also clear
to me that one can never permanently override the effects of the other, once
it has been selected.

It may be reasonable, however, to create a pragma "require" that is a
configuration pragma. Such a pragma couldn't override pragma suppress in code,
it would just fail the compile. That could be a useful way of ensuring that
there are no checks suppressed in your 5 million line program.

  ...stephen

*************************************************************

From: Robert Dewar
Sent: Tuesday, November 23, 1999 8:28 AM

Obviously the non-nesting semantics would take more work in GNAT, since it
is already done using stacking semantics. That was what I meant. We
implemented the stacking semantics because it seems clearly preferable.

*************************************************************

From: Robert Dewar
Sent: Tuesday, November 23, 1999 8:27 AM

I find a stacking semantics far more natural here, and in fact the more
I think about it, the more I think your non-stacking semantics is
fundamentally flawed.

If I write a little section of code which depends on correctness on the
fact that checks are suppressed, say for performance reasons in the
context of a particular compiler, it should not be possible to destroy
the correctness of this code by nesting it within a construct that contains
an Unsuppress and knows nothing about the code nested within it.

*************************************************************

From: Robert Dewar
Sent: Tuesday, November 23, 1999 8:38 AM

One more point on stacking semantics

It seems clear to me that Suppress and Unsuppress should be symmetrical
in their semantics. Anything else would be a surprise.

Given that it seems clear that a higher level Suppress cannot mask a lower
level Unsuppress, indeed in some sense that's the whole point of Unsuppress
(to undo a higher level Suppress).

So it would indeed seem odd if a Suppress cannot undo the effect of a higher
level Unsuppress.

I think part of the problem here is that Randy may have been trying to solve
a problem that Unsuppress is definitely NOT intended to address, and one
which to me is a non-problem, namely trying to ensure that checks are not
suppressed anywhere in your program.

Why do I think that is a non-problem? Simply because I have never run into
a customer requirement or an internal requirement for such a feature.

Unsuppress was put there solely for local control in situations which need
local control. Thus the stacking semantics seems much more natural to me.

*************************************************************

From: Robert Dewar
Sent: Tuesday, November 23, 1999 8:18 AM

<<It may be reasonable, however, to create a pragma "require" that is a
configuration pragma. Such a pragma couldn't override pragma suppress in code,
it would just fail the compile. That could be a useful way of ensuring that
there are no checks suppressed in your 5 million line program.
>>

This seems overkill to me, I am really not aware of any requirements here.
After all Ada is full of deliberate loopholes to get around "checks",
most notably unchecked conversion and address clauses, why get all
upset about some local use of Suppress?

*************************************************************

From: Stephen Michell
Sent: Tuesday, November 23, 1999 11:33 AM

  Sure, and the first thing that real projects do is write coding standards that
break peoples' fingers if they dare use one of those. Just ask me - I came back
Sunday from a week in the UK where those were some of the project's major
topics, and some people walked away with bandaged fingers :). Incidently, this
project does extremely heavy numeric calculations, numerical integrations of
transcendental functions, we do not suppress any checks, and performance is not
an issue.

The point is that Ada's loopholes are a real problem for real projects. We have
to do a lot of work to make sure that they are not used. Sure one can build
external tools to check for such things, but then one could code on C and rely
on external tools - right? Our community believes that the compilation
environment is the best line of defence for these issue, so let's seriously
consider ones that provide a real benefit.

A thought - The Annex H "pragma Restrictions" is helpful for many of the
significant issues, such as No_Allocation, No_Unchecked_Conversion, but
"no_pragma_suppress" is not one of the restrictions. Maybe that is the solution.

*************************************************************

From: Randy Brukardt
Sent: Tuesday, November 23, 1999 2:02 PM

> I find a stacking semantics far more natural here, and in fact the
> more I think about it, the more I think your non-stacking semantics
> is fundamentally flawed.
>
> If I write a little section of code which depends on correctness on
> the fact that checks are suppressed, say for performance reasons in
> the context of a particular compiler, it should not be possible to
> destroy the correctness of this code by nesting it within a construct
> that contains an Unsuppress and knows nothing about the code nested
> within it.

I find this a pretty compelling argument in practice (even though a
"correct" program can't depend on Suppress). I couldn't think of a case
where it would matter when I wrote the AI.

I've thought about it some more, and while the "stacking" semantics is easy to
describe informally, a formal description seems difficult. I don't think that
any of the existing Ada pragmas work this way (can anyone think of a
counter-example)? Any suggestions of how to word this? All I can think of is
"revoking the permission to suppress checks", but that is a double negative.

I'll rewrite the AI and repost it sometime after Thanksgiving.

				Randy.

*************************************************************

From: Randy Brukardt
Sent: Tuesday, November 23, 1999 2:45 PM

> I think part of the problem here is that Randy may have been trying to solve
> a problem that Unsuppress is definitely NOT intended to address, and one
> which to me is a non-problem, namely trying to ensure that checks are not
> suppressed anywhere in your program.

Well, actually, I was trying to provide a way to insure (typically in a local
section of code) that checking *is* done. That's because the person who writes
the code is lot more likely to know the requirements of the code. That has to
work no matter what configuration pragmas, compiler options, or whatever happen.
"Unsuppress" seems to be the wrong name for this purpose, because it does not
necessarily have anything to do with a Suppress. (I can live with it though).

The non-stacking part came from two issues: the difficulty of writing wording to
explain stacking formally, and to give meaning to the pragma when given as a
configuration pragma. (Remember that Suppress can be a configuration pragma).
The GNAT Unsuppress appears to be always ignored when given as a configuration
pragma. I'm not very excited about requiring compilers to implement a pragma
that will always be ignored.

An interesting question: if both a Suppress and Unsuppress are given in the same
scope, what happens? Does the order matter. For instance,

       procedure ...
           pragma Suppress (All_Checks);
           pragma Unsuppress (Storage_Check);

Does this Suppress all checks except Storage_Check?

       procedure ...
           pragma Unsuppress (Storage_Check);
           pragma Suppress (All_Checks);

Does this Suppress all checks including Storage_Check?

The problem is that configuration pragmas really don't have an order, so we
can't tell which came first. If the meaning depends in the order that they're
seen in, then using both Suppress and Unsuppress as configuration pragmas is
implementation-dependent. Ugh.

			Randy.

*************************************************************

From: Jean-Pierre Rosen
Sent: Wednesday, November 24, 1999 1:44 AM

> I've thought about it some more, and while the "stacking" semantics is easy
> to describe informally, a formal description seems difficult. I don't think
> that any of the existing Ada pragmas work this way (can anyone think of a
> counter-example)? Any suggestions of how to word this? All I can think of is
> "revoking the permission to suppress checks", but that is a double negative.
>
What's the problem ? The pragma applies to the declarative region where it
appears. In the case of nesting, the innermost wins.
Just state that you cannot have a suppress and an unsuppress in the same
declarative region for the same check (on the same object).
This is the natural Ada semantics.

*************************************************************

From: Robert I. Eachus
Sent: Friday, November 26, 1999 4:24 PM

I personally would find a non-stacking version of Unsuppress to be a problem,
even if it is never used in a stacking situation.  This is for code verification
reasons.  With the GNAT version, you just have to look at the closest nested
pragma, and if it matters to the logic of the code, the author will located it
as close as possible to the affected code to make verification easy.

Also, in the case of generics and in-line code, the fact that the code depended
on exceptions would need to be made visible to the user.

                                        Robert I. Eachus

*************************************************************

From: Robert Dewar
Sent: Monday, November 29, 1999 5:09 AM

<<In the case of nesting, the innermost wins.
Just state that you cannot have a suppress and an unsuppress in the same
declarative region for the same check (on the same object).
This is the natural Ada semantics.
>>

We don't have any such restriction in GNAT, and

a) I see no reason for such a restriction, the semantics is natural, a
suppress cancels a previous unsuppress and vice versa.

b) This is used in practice sometimes to just unsuppress checks for an
individual statement or suppress them for an individual statement. Yes
you could declare a block for this, but why require this.

It would require extra mechanism to enforce such a restriction, since
it would mean that you not only have to have a flag indicating the
restriction, but also another flag indicating whether it was explicitly
set in the current scope.

*************************************************************

From: Randy Brukardt
Sent: Monday, November 29, 1999 9:55 AM

>Jean-Pierre says:

> What's the problem ? The pragma applies to the declarative region where it
> appears.

How do you describe what Unsuppress does??? In this semantics, it doesn't do
anything by itself. It can only be described in terms of some (outer?) Suppress;
which leads to the double negative wording.

> In the case of nesting, the innermost wins.
> Just state that you cannot have a suppress and an unsuppress in the same
> declarative region for the same check (on the same object).

Given that the language-defined checks include some that overlap (the obvious
one is All_Checks and everything else), this could be quite difficult to do.

> This is the natural Ada semantics.

Yes, if you make that restriction. But the restriction isn't natural, and it
isn't easy to describe.

---

>Robert Dewar says:

>We don't have any such restriction in GNAT, and

>a) I see no reason for such a restriction, the semantics is natural, a
>suppress cancels a previous unsuppress and vice versa.

I agree, except that the "order" of the pragmas is not well-defined when they
are used as configuration pragmas. We could prevent the use of Unsuppress as a
configuration pragma, but this seems like an unnatural restriction.

>b) This is used in practice sometimes to just unsuppress checks for an
>individual statement or suppress them for an individual statement. Yes
>you could declare a block for this, but why require this.

Something is wrong with this. By 11.5(5), Suppress (and presumably Unsuppress) is
only allowed in a declarative_part, package specification, or as a configuration
pragma. That makes it impossible to use "around a statement" without an
enclosing block.

>It would require extra mechanism to enforce such a restriction, since
>it would mean that you not only have to have a flag indicating the
>restriction, but also another flag indicating whether it was explicitly
>set in the current scope.

Right. Plus you would have to deal with overlapping checks like All_Checks.

But without the restriction, it takes a lot more words to describe what happens.
This appears to be a case of "we know what we want, but we don't know how to
describe it".

			Randy.

*************************************************************

From: Tucker Taft
Sent: Monday, November 29, 1999 10:48 AM

Randy mentioned some concern about Unsuppress used as a configuration
pragma, as it seemed useless with the "stacking" interpretation.
However, if we consider a command-line parameter as the "outermost"
level, then a library-wide configuration pragma, then a compilation-wide
configuration pragma, then a scope-specific pragma, it seems like
configuration pragmas would fit into the "stacking" hierarchy in
a reasonable way.

For example, if you gave a "suppress-all" on the command line, but
had an Unsuppress for tag check in a library-wide configuration pragma,
that would seem meaningful and perhaps useful.

*************************************************************

From: Robert Dewar
Sent: Monday, November 29, 1999 9:12 PM

I definitely agree, we have seen this standard and useful application of
Unsuppress used, and use it ourselves sometimes.

*************************************************************

From: Randy Brukardt
Sent: Monday, November 29, 1999 1:31 PM

Tucker says:

> For example, if you gave a "suppress-all" on the command line, but
> had an Unsuppress for tag check in a library-wide
> configuration pragma, that would seem meaningful and perhaps useful.

Yes, but the problem is that it has been suggested that the order that
Suppress and Unsuppress pragmas is significant. That is,

   pragma Suppress (All_Checks);
   pragma UnSuppress (Overflow_Check);

(which suppresses all but Overflow_Check) means something different than

   pragma UnSuppress (Overflow_Check);
   pragma Suppress (All_Checks);

(which suppresses all checks), the UnSuppress being ignored.

The problem is that configuration pragmas are not given in a clearly defined
order. Since they can be compiled separately, and compilation order is not an
Ada 95 concept, the pragmas could occur in either order or simultaneously.
Similarly, we cannot say that compiler options occur before or after "real"
configuration pragmas. So how do we determine which of these are meant?

This means that the definition of configuration pragmas cannot depend on the
order of appearance. Yet, I've been told to write wording for UnSuppress which
*does* depend on the order that the pragmas appear. So, we have a problem.

If we get rid of the significance of the order (at least within a single scope),
we get rid of the problem, but that the cost of complicating things (and I
suspect that Robert won't go along with any such semantics). [That is, in a
scope, UnSuppress has precedence over Suppress.] We could also prevent multiple
pragmas in the same scope, but that is a problem because of overlapping sets of
checks. Or we could simply eliminate UnSuppress as a configuration pragma, which
would prevent the problem from occurring. None of these look like particularly
good choices.

			Randy.

*************************************************************

From: Robert A Duff
Sent: Monday, November 29, 1999 4:03 PM

> The problem is that configuration pragmas are not given in a clearly defined
> order.

Have you considered making it implementation defined in that case?

- Bob

*************************************************************

From: Robert Dewar
Sent: Monday, November 29, 1999 9:45 PM

<<Have you considered making it implementation defined in that case?
>>

Sounds reasonable to me, it depends on which is processed last, which
is indeed impl defined.

*************************************************************

From: Randy Brukardt
Sent: Monday, November 29, 1999 6:48 PM

Not seriously. That seems like a last resort: punt! Such a definition would
not be useful to people who need portable code, and of course would be
untestable.

*************************************************************

From: Robert Dewar
Sent: Monday, November 29, 1999 10:16 PM

Don't dance on pin heads :-)

Who cares if there are multiple conflicting pragmas in the configuration
pragmas, this simply won't happen in practice. Don't undermiune the
utility of USEFUL applications by worrying about things that are useless!

*************************************************************

From: Randy Brukardt
Sent: Tuesday, November 30, 1999 11:10 AM

I would agree, except that multiple conflicting pragmas are USEFUL: they provide
an easy way to turn off all but one check:

    pragma Suppress (All_Checks);
    pragma Unsuppress (Storage_Check);

(But of course the order is significant). This is what I use in release code
where size is an issue: the only check that I find critical is Stack and Heap
checking (because the results are so catastrophic if they are omitted).

I want to have a way to do this as a configuration pragma/option in any
implementation that I'm using. Making it implementation-defined eliminates that
possibility (unless all of the vendors support it in the same way, which is very
unlikely).

			Randy.

*************************************************************

From: Tucker Taft
Sent: Tuesday, November 30, 1999 3:59 PM

Randy Brukardt wrote:
>
> > > The problem is that configuration pragmas are not given in a clearly defined
> > > order.
> >
> > Have you considered making it implementation defined in that case?
>
> Not seriously. That seems like a last resort: punt! Such a definition would
> not be useful to people who need portable code, and of course would be
> untestable.

I would make it well defined if the configuration pragmas are all
in the same file (i.e., the last one applies).  If the
configuration pragmas are in separate files, then it is implementation-defined
what order these end up in when conceptually combined.  They
will be combined in some order, so there are a finite number of
distinct orders possible, and so it is testable.

If a programmer wants portability, they would put all the
configuration pragmas in the same file.

Hence, if they wanted to suppress everything but tag_check, they
could write:

    pragma Suppress(All_Checks);
    pragma Unsuppress(Tag_Check);

That seems pretty intuitive.

*************************************************************

From: Ted Baker
Sent: Tuesday, November 30, 1999 7:07 PM

After hearing a lot of talk on this one, I believe that as a user I would
view the nesting of Suppress and Unsuppress pragmas as unwise,
and so would  prefer for an implementation to at least give a
warning when this occurs.

However, if nesting is allowed, the innermost nested region should
certainly retain the effect of the pragma given for that region.

*************************************************************

From: Robert Dewar [dewar@GNAT.COM]
Sent: Tuesday, November 30, 1999 7:30 PM

YOu don't want a warning for all cases of nesting, otherwise every use
of Unsuppress in a typically suppressed region would generate a warning.
Since this kind of use is the principle utility o Unsuppress, it seems
wrong to warn unconditionally.

For example, we generally compile the GNAT runtim elibrary with checks off
(i.e. the equivalent of a pragma Suppress at the configuration level).

Individual little sections of the runtime that rely on checks (e.g. converting
Constraint_Error into Time_Error in Calendar) do an Unsuppress.

*************************************************************

From: Robert Dewar
Sent: Tuesday, November 30, 1999 5:40 PM

<<I would make it well defined if the configuration pragmas are all
in the same file (i.e., the last one applies).  If the
configuration pragmas are in separate files, then it is implementation-defined
what order these end up in when conceptually combined.  They
will be combined in some order, so there are a finite number of
distinct orders possible, and so it is testable.
>>

I agree with this, and cannot imagine that it in fact does not hold already
for all existing compilers.

*************************************************************

From: Tucker Taft
Sent: Thursday, December 02, 1999 10:23 AM

Randy Brukardt wrote:
> I would agree, except that multiple conflicting pragmas are USEFUL: they
> provide an easy way to turn off all but one check:
>
>     pragma Suppress (All_Checks);
>     pragma Unsuppress (Storage_Check);
>
> (But of course the order is significant). This is what I use in release code
> where size is an issue: the only check that I find critical is Stack and
> Heap checking (because the results are so catastrophic if they are omitted).
>
> I want to have a way to do this as a configuration pragma/option in any
> implementation that I'm using. Making it implementation-defined eliminates
> that possibility (unless all of the vendors support it in the same way,
> which is very unlikely).

I trust you received the earlier message where this would be well-defined
if they are all in the same compilation.  If the configuration pragmas
are in separate (unit-less) compilations, then the order in which the
configuration pragmas are combined is implementation-defined (or perhaps
even "unspecified").  That would seem to address your concern.
In general, having multiple unit-less compilations with configuration
pragmas is a bit confusing anyway, I would say (though our front end
supports it ;-).

*************************************************************

From: Tucker Taft
Sent: Monday, December 13, 1999 2:38 PM

Randy Brukardt wrote:
>
> Here is a complete rewrite of this AI. I don't much like the wording, but I
> think it is correct (if a bit subtle).

Looks good.  I noticed one typo (see below).

One typo:

>
> ...
> Checking pragmas give an implementation instructions on handling
> language-defined checks. A pragma Suppress gives permission to an
> implementation
> to omit certain language-defined checks, while a pragma Unsuppress revokes
> the
> permission to make omit checks.
                XXXX

> ...

*************************************************************

From: Jean-Pierre Rosen
Sent: Tuesday, December 14, 1999 12:38 PM

> Here is a complete rewrite of this AI. I don't much like the wording, but
I
> think it is correct (if a bit subtle).
>
[...]
> Consider, for instance, an integer saturation arithmetic package. The
> multiply
> operation might look like:
>
>      function "*" (Left, Right : Saturation_Type) return Saturation_Type
is
>      begin
>          return Integer(Left) * Integer(Right);
>      exception
>          when Constraint_Error =>
>              return Saturation_Type'Last;
>      end "*";
>
> This function will not work properly without overflow checking. Ada 95
does
> not provide a way to indicate this to the compiler and programmers.
>
[...]
> Pragma Unsuppress revokes the permission to suppress a check, that is, it
> means
> that the given check must be performed.
>
Given the example and the wording, I am afraid that it may be interpreted to
mean that if, for example, Float'Machine_Overflows is False, the check be
performed anyway. I'm pretty sure it is not the intent, but maybe some
additionnal wording could be added for this.

*************************************************************

From: Randy Brukardt
Sent: Tuesday, December 14, 1999 4:48 PM

I specifically selected an Integer example to avoid any question of whether the
check has to be performed in the normal case. Also, the wording you are
objecting to is used only in the informal description of the pragma. I used that
to make it clearer what is meant. The formal wording never says anything about a
check being required; it only talks about revoking the permission granted by a
Suppress pragma.

Obviously, I could add a paragraph in the discussion saying that Unsuppress
"obviously" doesn't add any requirements beyond those that would exist anyway
(in the absence of any checking pragmas), but this seems obvious enough. Would
anyone seriously think otherwise??

*************************************************************

From: Robert I. Eachus
Sent: Friday, December 17, 1999 5:53 PM

At 04:48 PM 12/14/1999 -0600, Randy Brukardt wrote:
>Obviously, I could add a paragraph in the discussion saying that Unsuppress
>"obviously" doesn't add any requirements beyond those that would exist
>anyway (in the absence of any checking pragmas), but this seems obvious
>enough. Would anyone seriously think otherwise??

    Why not just change the sentence:

> A pragma Unsuppress revokes the permission to omit the named check for any
> entities to which it applies.

    To:

> A pragma Unsuppress revokes any permissions given by pragma Suppress to omit
> the named check for any entities to which it applies.

    Or if this is still too verbose, you could go with:

> A pragma Unsuppress revokes such permissions to omit the named check for any
> entities to which it applies.

*************************************************************

From: Randy Brukardt
Sent: Thursday, December 23, 1999 1:44 PM

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).

I don't see any reason to add the redundancy to the RM wording, because such
things tend to get us in trouble down the road. There aren't any other
permissions to omit checks in the RM (and implementation-defined permissions
aren't our business). There are cases where the RM says that the checks don't
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 :-)

*************************************************************

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.

*************************************************************

From: Erhard Ploedereder
Sent: Monday, March 13, 2000 7:33 PM

Let me throw in a suggestion. Why not simply define Unsuppress without
the On parameter? That way, all these nasty issues seem to be avoided.
Yes, it's not quite so convenient, expressive, etc, etc, but it seems
to avoid all the nastiness that you've been discussing.

*************************************************************

From: Robert Dewar
Sent: Tuesday, March 14, 2000 6:58 AM

<<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?
>>

Since people are trying to copy a well established and frequently used
feature in GNAT, it may be useful to say what GNAT does :-)

The way GNAT works is that a check is suppressed if

EITHER it is scope suppressed OR (for some "appropriate" choice of entities
to test) it is suppressed on a relevant entity.

This means that the sequence above is well defined to suppress access checks
on Some_Type in GNAT. I am not necessarily saying that is the way things
should work, but this has a clear implementation model, and is also easy
to describe.

In other words, my suggestion is precisely, as in my previous message,
that a pragma Unsuppress has ONLY the effect of cancelling the effects
(whatever they migfht be) of a previous Suppress with the same entity.

Thus the sequence above is equivalent to just the first pragma, and so
the check is indeed suppressed.

In fact as I think about it, I would recommend that this in fact be the
defined semantics.

*************************************************************

From: Robert Dewar
Sent: Tuesday, March 14, 2000 7:12 AM

<<Let me throw in a suggestion. Why not simply define Unsuppress without
the On parameter? That way, all these nasty issues seem to be avoided.
Yes, it's not quite so convenient, expressive, etc, etc, but it seems
to avoid all the nastiness that you've been discussing.
>>

I could buy this approach.

I also think that my definition is viable. I will repeat it again.

pragma Unsuppress with an entity has ONLY the effect of cancelling a
previous Suppress applying to this same entity.

If there is no such previous Suppress, then the pragma Unsuppress has
no effect at all.

*************************************************************

From: Tucker Taft
Sent: Tuesday, March 14, 2000 9:16 AM

This seems odd to me.  I would expect an Unsuppress...On to ensure
that (unless overridden by a Suppress...On) the specified check
would not be suppressed, even if there is a suppress-all somewhere
in scope.

But I also agree with Randy that we should try to find something
we can all agree on.

If we abandon the "Unsuppress...On" we will still need to define
how Unsuppress relates to Suppress...On.

Also, noone has addressed my concern about spec/body inheritance
and stub/subunit inheritance, as it relates to source-wide
configuration pragmas.

*************************************************************

From: Robert Dewar
Sent: Tuesday, March 14, 2000 9:30 AM

<<This seems odd to me.  I would expect an Unsuppress...On to ensure
that (unless overridden by a Suppress...On) the specified check
would not be suppressed, even if there is a suppress-all somewhere
in scope.
>>

I explained why this is inherently non-portable. Let me try again.

The RM has nothing to say, nothing at all, about WHICH entities are
involved for consideration when considering whether to remove a given
check.

This means that the set of possibly erroneous programs is not very
well defined, and is in fact implementation dependent. Trying to define
this more specifically would be a horrible nightmare in my opinion.
But in the case of Suppress it really does not matter, since if a given
suppress has no effect, that is really not critically important, and
programs should not rely on executing erroneous code (working correctly
is an acceptable behavior for erroneous code in this case).

But in the Unsuppress case, if you follow the semantics suggested by Tuck
above, it then becomes critically important to determine which entities
get tested (see my previous message for an example showing why this is
hard to do).

Yes, the above idea makes sense. No, it is not practical.

If people share Tuck's reaction that my suggestion is odd, then the best
remedy is to follow Erhard's idea and only allow pragma Unsuppress with
no Entity argument (GNAT will of course continue to implement the full
form, since we are not about to make incompatible changes here!)

*************************************************************

From: Randy Brukardt
Sent: Tuesday, March 14, 2000 11:19 AM

Robert said:

> > I also think that my definition is viable. I will repeat it again
> >
> > pragma Unsuppress with an entity has ONLY the effect of canceling a
> > previous Suppress applying to this same entity.
> >
> > If there is no such previous Suppress, then the pragma Unsuppress has
> > no effect at all.

and Tucker replied:

> This seems odd to me.  I would expect an Unsuppress...On to ensure
> that (unless overridden by a Suppress...On) the specified check
> would not be suppressed, even if there is a suppress-all somewhere
> in scope.

I discussed this in detail last night. (So much detail that most everyone seems
to have glossed over it.) Robert's semantics are the only possible semantics
that can be defined in a fully-implementation independent fashion.

However, I objected to this semantics on a usage basis, as it makes it very
difficult to write a bullet-proof subprogram that depends on checks being made
(and exceptions raised).

Thus, I proposed only defining Unsuppress without the On parameter, and
including an implementation permission to allow implementations (such as GNAT)
to support Unsuppress with an On parameter with implementation-defined
semantics.

> If we abandon the "Unsuppress...On" we will still need to define
> how Unsuppress relates to Suppress...On.

The only way for it to be useful is if it revokes the permissions on all
Suppress...On. Otherwise, it can't be used to idiot-proof code that needs
checking, and that is the use that needs to be defined portably. (I gave a
concrete example of this last night.)

> Also, no one has addressed my concern about spec/body inheritance
> and stub/subunit inheritance, as it relates to source-wide
> configuration pragmas.

Not true. I commented on it originally, suggesting that we determine what
existing implementations do here. (And opening a separate AI on the topic if
people feel it is important enough, as it has little to do with Unsuppress.)
Forcing implementations to inherit Suppress in bodies would be very bad *if*
compilers aren't already doing it. I know Janus/Ada doesn't do it, but I don't
know what other compilers do (which is more important).

*************************************************************

From: Ada Rapporteur Group of WG9; managing the Ada issues [ARG@ACM.ORG]
on behalf of Tucker Taft [stt@averstar.com]
Sent: Tuesday, March 14, 2000 10:39 AM
To: ARG@ACM.ORG
Subject: Re: AI 224 suppress/unsuppress details

Robert Dewar wrote:
>
> <<This seems odd to me.  I would expect an Unsuppress...On to ensure
> that (unless overridden by a Suppress...On) the specified check
> would not be suppressed, even if there is a suppress-all somewhere
> in scope.
> >>
>
> I explained why this is inherently non-portable. Let me try again.

I accept that it is harder to define the semantics.  By saying it is "odd"
I meant that it would be unintuitive and potentially misleading for the
user if Unsuppress...On did not in fact unsuppress a check.

Given that, and your argument that the semantics are difficult to define,
one could argue for discouraging the use of Unsuppress...On.  However,
if GNAT continues to support it, then does that mean we should all feel free
to support it in various non-portable ways?  My sense is that we should either
*all* drop support for it, or include it with specifically implementation-defined
semantics (perhaps deserving a warning?).

*************************************************************

From: Tucker Taft
Sent: Tuesday, March 14, 2000 12:51 PM

Randy Brukardt wrote:
>
> 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.

I don't agree with the distinction between Suppress...On and
Unsuppress...On as far as semantics (see below).

>
> 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.

I don't understand this logic either.  Should a specific Suppress...On
be able to override a non-specific Unsuppress?  If so, then the converse
should work as well, in my view.

> ...
> 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.

I don't see why Suppress...On need not be "well defined" whereas
Unsuppress...On does need to be.  Suppress...On is stating "I know
I never fail Blah_Check on blah object/subtype."  If this is misinterpreted
to apply to some other object/subtype, where Blah_Check failures do
occur and where exceptions should be raised, then this affects semantics
just as much as a misinterpreted Unsuppress...On.

I don't see any need to be more or less precise in Unsuppress...On than
in Suppress...On (the problems that can occur seem to be essentially
the same if the pragma is misinterpreted -- a check might get suppressed
that in fact would fail in the given program).

> ... 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.

I'm not sure why you talk about "conforming" here.  We are talking about
entities, not expressions, so either they denote the same entity, or
they don't.

*************************************************************

From: Robert Dewar
Sent: Tuesday, March 14, 2000 1:41 PM

<<I accept that it is harder to define the semantics.  By saying it is "odd"
I meant that it would be unintuitive and potentially misleading for the
user if
Unsuppress...On did not in fact unsuppress a check.
>>

No more unintuitive than doing a Suppress on a given entity and finding
out that it does not suppress the check. For example, in

  A := B;

where there is a tag check, GNAT checks the type involved, but not the
class type, or any parent type, or the objects A and B, and indeed one
customer recently was surprised that suppressing checks on A did not work.

<<Given that, and your argument that the semantics are difficult to define,
one could argue for discouraging the use of Unsuppress...On.  However,
if GNAT continues to support it, then does that mean we should all feel free to
support it in various non-portable ways?  My sense is that we should either
*all* drop support for it, or include it with specifically
implementation-defined semantics (perhaps deserving a warning?).
>>

Well I think it is a bit unrealistic to ask GNAT to unimplement anything.
Why should we cause our customers incompatibility problems. I would
certainly be willing to have this case included in the

pragma Restrictions (No_Implementation_Pragmas)

P.S. it would be nice to pseudo-standardize this restriction identifier

The only time that GNAT unimplemented anything in the name of conformity
was the handling of Call_By_Copy. This caused customers a LOT of problems,
and if we knew what we did now, we would not repeat that experience.

Yes, I know it is nice to be conformant, but I think this urge should be
restricted to defining a subset that everyone will implement, not agitation
to unimplement allowed extensions.

*************************************************************

From: Robert Dewar
Sent: Tuesday, March 14, 2000 1:59 PM

<<However, I objected to this semantics on a usage basis, as it makes it very
difficult to write a bullet-proof subprogram that depends on checks being
made (and exceptions raised).
>>

Now this must be wrong, *adding* a facility cannot make it harder to do
something!

Sure, to write bulletproof subprograms, you either

a) know what the compiler does, and use the specific entity form, e.g. this
is perfectly reasonable in the GNAT runtime, which has ZERO interest in
running on other compilers, and is entirely GNAT specific.

or (and we in fact prefer this in the GNAT runtime always :-)

b) use the form with only a scope suppress

I am not sure what you mean about "inherit suppress in bodies", but if
it means what I think it means, I would consider a compiler that does not
do this to be broken ... but perhaps I misunderstand.

*************************************************************

From: Robert Dewar
Sent: Tuesday, March 14, 2000 2:12 PM

I find Tuck's answer here insufficiently pragmatic, and it just does not
seem worth the work to try to tune up this ill-advised, ill-defined
feature in the RM (what precise entities are tested).

I have no problem with deciding not to standardize the entity form of
unsuppress. As I said before, GNAT does implement this form with very
well defined semantics, as I noted. Yes, they are not as well defined
as they might be, since the effect of the suppress is not well defined.

I find it surprising that Tuck does not see the difference between
suppress and unsuppress here!

A suppress is never critical. Any code that relies on a suppress actually
suppressing checks is clealry incorrect.

An unsuppress is very often critical. Code very often relies on a check that
is guaranteed to occur, regardless of compiler options, as a reuslt of
ensuring that the check is not suppressed.

That's a VERY big difference in practice.

The point is that you cannot simply borrow the Suppress semantics (which are
ill defined and non-portable, but it does not matter that much) for
Unsuppress in a manner that leaves them as ill defined and non-portable
(since it could matter a lot!)

*************************************************************

From: Randy Brukardt
Sent: Tuesday, March 14, 2000 3:32 PM

> I'm not sure why you talk about "conforming" here.  We are talking about
> entities, not expressions, so either they denote the same entity, or
> they don't.

Not really, there are whole can of worms here I would rather leave the lid on.
For instance, are two subtypes of the same type the same or different entities
for the purpose of suppressing checks? I'd just as soon let compilers do
whatever they're going to do here.

*************************************************************

From: Randy Brukardt
Sent: Tuesday, March 14, 2000 3:53 PM

> <<However, I objected to this semantics on a usage basis, as it makes it very
> difficult to write a bullet-proof subprogram that depends on checks being
> made (and exceptions raised). >>
>
> Now this must be wrong, *adding* a facility cannot make it
> harder to do something!

Robert, it's clear to me from your mail to Tucker that you understand the
problem, so I think we're a lot closer together on this than is obvious.

> Sure, to write bulletproof subprograms, you either
>
> a) know what the compiler does, and use the specific entity form, e.g. this
> is perfectly reasonable in the GNAT runtime, which has ZERO interest in
> running on other compilers, and is entirely GNAT specific.
>
> or (and we in fact prefer this in the GNAT runtime always :-)
>
> b) use the form with only a scope suppress

Well, what I want to do is to bullet-proof my code against anything that a
ham-handed maintenance programmer (which might be me!) or end-user (of Claw, for
instance) might do.

I certainly can't assume a specific compiler (rules out (a)), and I don't have
any way to prevent someone from using Suppress (..., On => ...). I could imagine
a compiler option that Suppressed checks on all entities whose names started
with 'A'. (OK, I'm reaching here). But certainly a maintenance programmer could
insert a Suppress (..., On => ...) for some reason, and my bullet-proof
subprogram isn't bullet-proof anymore.

The best way to support bullet-proof routines is for non-specific Suppress to
force *all* of the appropriate checks on. This also has the least surprise for
the user (because they actually get what they said -- does GNAT warn if a
non-specific unsuppress is leaving some checks suppressed??). But I do see the
definitional problem (although I really don't see why it is a problem to
Unsuppress everything -- there can be no confusion as to what is unsuppressed in
that case). [BTW, I don't think that changing GNAT to do just that (no other
changes) would break user programs -- at worst they would get a bit more
checking than expected in some subprogram.]

I suppose another way out of this problem would be to adopt the GNAT semantics
and to provide a Restictions identifier "No_Specific_Suppress" that I could use
as a configuration pragma in Claw (or any other code that I needed to
bullet-proof). The restriction would make any specific Suppress that reached a
unit with the restriction illegal, as well as the use of it. (If the maintenance
programmer then went ahead and removed that, well, there is only so much
bullet-proofing that is possible...)

> I am not sure what you mean about "inherit suppress in bodies", but if
> it means what I think it means, I would consider a compiler that does not
> do this to be broken ... but perhaps I misunderstand.

Janus/Ada uses a purely textual model for controlling checks, inherited from our
CP/M compilers. Anything that doesn't map cleanly into that is rejected, and
many suppresses are in fact rejected (well, ignored with a warning). This area
really deserves a rewrite (especially since the back-end will support a less
restrictive model), but since we don't have any customers who've complained
about that, it doesn't have much priority. And there would be compatibility
problems with the old Janus/Ada specific check control pragmas...

*************************************************************

From: Tucker Taft
Sent: Tuesday, March 14, 2000 3:02 PM

Robert Dewar wrote:
> ...
> I find it surprising that Tuck does not see the difference between
> suppress and unsuppress here!
>
> A suppress is never critical. Any code that relies on a suppress actually
> suppressing checks is clealry incorrect.
>
> An unsuppress is very often critical. Code very often relies on a check that
> is guaranteed to occur, regardless of compiler options, as a reuslt of
> ensuring that the check is not suppressed.
>
> That's a VERY big difference in practice.

I still don't see this.  Consider the following:

    A := B;  -- check cannot fail, would like to suppress it
    C := D;  -- check failure possible at run-time; need to catch it

Now if we use a Suppress...On to suppress the check on "A := B" and due
to lack of precision it "spills over" into "C := D" then we have a
serious problem.

Similarly, if we use an Unsuppress...On to unsuppress the check on "C :=
D" and due to lack of precision it doesn't override some more global Suppress,
then we have a serious problem.

These kinds of imprecision both seem just as bad.  An overeager Suppress...On
is just as bad as a too-timid Unsuppress...On.  What am I missing?

> The point is that you cannot simply borrow the Suppress semantics (which are
> ill defined and non-portable, but it does not matter that much) for
> Unsuppress in a manner that leaves them as ill defined and non-portable
> (since it could matter a lot!)

I suppose you could say that we need a portable *lower bound* on how
much Unsuppress...On affects, and a portable *upper bound* on how much
Suppress...On affects. Both bounds seem just as important.

*************************************************************

From: Robert A Duff
Sent: Tuesday, March 14, 2000 4:37 PM

> I suppose you could say that we need a portable *lower bound* on how
> much Unsuppress...On affects, and a portable *upper bound* on how much
> Suppress...On affects. Both bounds seem just as important.

Perhaps, but neither one is terribly important.  I wrote the section on
Suppress, and I spent some energy trying to nail down the rules, before
I finally decided it was impractical, as Robert has pointed out.  Note
that the Ada 83 RM didn't nail down the rules, either, but that fact was
less clear.

I would like to disallow Unsuppress...On, but Robert says GNAT will keep
it (and I agree that ACT would be foolish to remove it at this point).
Therefore, no matter what the ARG does, there *will* be Unsuppress...On,
and it *will* be non-portable.  We should just live with that fact.

The average user isn't going to understand some complicated set of rules
about On=> (which leads to the same sort of bugs you mention above).  So
why don't we just give up and say it's impl-def?  Is that so horrible?

By the way, I don't really understand Randy's concern:

> 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.

Are you worried that *you* might put an outer Suppress...On in the code?
Or are you worried that the customer might insert one?  If the former,
my answer is, "Don't do that."  If the latter, my answer is that of
course if users edit the sources they might break things.

You're correct that Suppress...On is the tool of the devil.  It
shouldn't be in the language in the first place.  But obviously we can't
get rid of it now.  So just don't use it.

*************************************************************

From: Robert Dewar
Sent: Tuesday, March 14, 2000 4:26 PM

<<These kinds of imprecision both seem just as bad.  An overeager Suppress...On
is just as bad as a too-timid Unsuppress...On.  What am I missing?
>>

You are inventing bugs, we are not talking about an over-eager suppress here,
that would be a bug, bugs are a BAD THING, and must be avoided.

We are talking about under-eager suppresses. For example:

  A := B;

if you suppress constraint check on A (or B) that might or might not
suppress this check, it certainly WILL NOT suppress a check on C := D.

But your code can never count on a suppress being effective anyway.

On the other hand, if you have a scope suppress set, and you unsuppress
on A and B, and expect this to make

  A := B;

not raise an exception, then the under-eager unsuppress WILL cause a
problem.

<<These kinds of imprecision both seem just as bad.  An overeager Suppress...On
is just as bad as a too-timid Unsuppress...On.  What am I missing?
>>

The overeager Suppress is a pure invention, and nothing to do with anything
we are discussing here.

*************************************************************

From: Robert Dewar
Sent: Tuesday, March 14, 2000 4:41 PM

<<I would like to disallow Unsuppress...On, but Robert says GNAT will keep
it (and I agree that ACT would be foolish to remove it at this point).
Therefore, no matter what the ARG does, there *will* be Unsuppress...On,
and it *will* be non-portable.  We should just live with that fact.
>>

Seems reasonable to me ...

<<The average user isn't going to understand some complicated set of rules
about On=> (which leads to the same sort of bugs you mention above).  So
why don't we just give up and say it's impl-def?  Is that so horrible?
>>

Incidentally, note that the GNAT rule is *very* easy to explain and for
people to understand (the On form of Unsuppress does nothing but cancel
the effects of an identical active Suppress ON, and if there is none,
does nothing at all).

<<Are you worried that *you* might put an outer Suppress...On in the code?
Or are you worried that the customer might insert one?  If the former,
my answer is, "Don't do that."  If the latter, my answer is that of
>>

I understand perfectly the concern here, and we have exactly the same
effect in the GNAT runtime. You want to write code that can be compiled
with checks on or checks off (compiler option) and stlil be functionally
correct. This was the motivation for Unsuppress in the first place.

Telling people "don't do that" is not an acceptable solution, and in any
case it makes very good sense to suppress checks on the GNAT runtime, it
removes almost all the checks (all but the very few that are functionally
necessary and which are assured by Unsuppress).

*************************************************************

From: Robert Dewar
Sent: Tuesday, March 14, 2000 5:46 PM
Subject: RE: AI 224 suppress/unsuppress details

<<Well, what I want to do is to bullet-proof my code against anything that a
ham-handed maintenance programmer (which might be me!) or end-user (of Claw,
for instance) might do.
>>

Well your maintenance programmer could be incompetent in many other ways,
I don't see this as very convincing, but I understand your point.

*************************************************************

From: Robert Dewar
Sent: Tuesday, March 14, 2000 5:47 PM

<<Not really, there are whole can of worms here I would rather leave the lid
on. For instance, are two subtypes of the same type the same or different
entities for the purpose of suppressing checks? I'd just as soon let
compilers do whatever they're going to do here.
>>

They are different entities, that's quite clear from the RM.

*************************************************************

From: Robert A Duff
Sent: Tuesday, March 14, 2000 6:16 PM

> Well, what I want to do is to bullet-proof my code against anything that a
> ham-handed maintenance programmer (which might be me!) or end-user (of Claw,
> for instance) might do.

That's easy: a coding convention that says "don't use On =>".

It seems sort of like you're worrying that somebody, somewhere, might do
an Unchecked_Conversion that would violate the invariants of my package,
and I want to protect my package from that.  Well, you can't, in Ada.

*************************************************************

From: Robert A Duff
Sent: Tuesday, March 14, 2000 6:27 PM

> Incidentally, note that the GNAT rule is *very* easy to explain and for
> people to understand (the On form of Unsuppress does nothing but cancel
> the effects of an identical active Suppress ON, and if there is none,
> does nothing at all).

And if it's also easy to implement, then I'm for it.

My main concern here is that we don't cause a lot of implementation
effort for these "On =>"'s, which are very close to being totally
useless.

> <<Are you worried that *you* might put an outer Suppress...On in the code?
> Or are you worried that the customer might insert one?  If the former,
> my answer is, "Don't do that."  If the latter, my answer is that of
> >>
>
> I understand perfectly the concern here, and we have exactly the same
> effect in the GNAT runtime. You want to write code that can be compiled
> with checks on or checks off (compiler option) and stlil be functionally
> correct. This was the motivation for Unsuppress in the first place.
>
> Telling people "don't do that" is not an acceptable solution, and in any
> case it makes very good sense to suppress checks on the GNAT runtime, it
> removes almost all the checks (all but the very few that are functionally
> necessary and which are assured by Unsuppress).

No, I think you miss Randy's point (as do I).  I agree with the above --
that's exactly how I use pragma Unsuppress -- I want to have a run-time
system that can be compiled with checks on or off (a global setting) and
work either way.  So I mark parts of the code with pragma Unsuppress
that I know really need the checks.  But I never seem to need "On =>".

Randy, on the other hand, seems to be worried about an outer
Suppress...On versus an inner Unsupress without On.  I'm not worried
about customers who secretly add Suppress...On pragmas to key variables
inside the run-time system, any more than I'm worried about customers
who add any other kind of bug.

You say, "it makes very good sense to suppress checks on the GNAT
runtime", which I agree with.  But it doesn't make sense to add "pragma
Suppress(Overflow_Check, On => The_Result_Of_The_Exponentiation_Op);" to
some random part of the GNAT runtime.

*************************************************************

From: Robert Dewar
Sent: Tuesday, March 14, 2000 7:16 PM

<<You say, "it makes very good sense to suppress checks on the GNAT
runtime", which I agree with.  But it doesn't make sense to add "pragma
Suppress(Overflow_Check, On => The_Result_Of_The_Exponentiation_Op);" to
some random part of the GNAT runtime.
>>

No, definitely not, and I am in agreement with the rest of Bob's coments as
well here.

*************************************************************

From: Robert Dewar
Sent: Wednesday, March 15, 2000 2:18 PM

<<That's not helpful. Five years from now, I am not likely to remember that
I'm not supposed to use Suppress...On for  some obscure reason. And other
programmers who might work on the source don't know about this discussion in
the first place.
>>

I find this argument *very* weak, and would not take it into
consideration. If you are saying that the standard must enforce
your particular coding standards that seems unreasonable.

*************************************************************

From: Randy Brukardt
Sent: Wednesday, March 15, 2000 6:59 PM

> <<That's not helpful. Five years from now, I am not likely to remember that
> I'm not supposed to use Suppress...On for  some obscure reason. And other
> programmers who might work on the source don't know about this discussion in
> the first place.
> >>
>
> I find this argument *very* weak, and would not take it into
> consideration. If you are saying that the standard must enforce
> your particular coding standards that seems unreasonable.

I'm pretty tired of this discussion, and we've agreed on all of the other
points, but I'll make one last try here.

I would agree with your comment on coding standards. The problem is, the only
reason coding standards are involved at all is that non-specific Unsuppress is
defined not to affect Suppress...On. If

    pragma Unsuppress (All_Checks);

insisted that all checks are performed (no matter how they were suppressed),
then the subject of "coding standards" would not come up.

I offered a compromise position of having the language enforce the "coding
standard" of no Suppress...On pragmas, but people consider that "weak".

Well, fine. I withdraw that compromise.

I have heard no technical argument as to why pragma Unsuppress (without an "On")
cannot revoke checks suppressed by any kind of Suppress pragma. The arguments
against Unsuppress...On do not apply here: "Make all checks" is unambiguous and
certainly not implementation-dependent.

I haven't heard any implementation-related arguments against this, either. I
suppose there might be some, but I'd like to hear them.

The only arguments I've heard against it are (1) it makes the semantics of
Unsuppress...On confusing; and (2) GNAT doesn't do it that way.

(1) is a red herring now, as we've decided that the RM will not contain
Unsuppress...On (other than a permission for GNAT and other compilers to include
it with implementation-defined semantics). What an implementation-defined pragma
means to some compiler is entirely up to that implementor. And anyone that wants
portable code certainly won't use it.

(2) doesn't seem real either. Robert has said that he considers any program that
depends on a specific check being suppressed is broken. If GNAT was changed to
"do it this way" (that is, having the RM-defined Unsuppress revoke checks on any
Suppress with the same check name, including Suppress...On), it certainly could
not break any existing code. The only harm it could possibly do is cause some
check to be made that was not made before. And Robert has said that any program
which failed as a result would be broken. Thus I find the GNAT argument -- in
this one specific case -- to be "very weak", as Robert put it.

Certainly, this would be a far less disruptive change than forcing GNAT to
"unimplement" something, or changing the meaning of Unsuppress...On. And it
makes the meaning of Unsuppress far more intuitive, and makes it useful in the
*absence* of coding standards. And it has simpler RM wording as well (because we
don't have discuss Suppress...On separately when defining Unsuppress).

So I await any technical or implementation arguments against this.

			Randy.

*************************************************************

From: Robert Dewar
Sent: Wednesday, March 15, 2000 7:13 PM

<<(2) doesn't seem real either. Robert has said that he considers any program
that depends on a specific check being suppressed is broken. If GNAT was
changed to "do it this way" (that is, having the RM-defined Unsuppress
revoke checks on any Suppress with the same check name, including
Suppress...On), it certainly could not break any existing code. The only
harm it could possibly do is cause some check to be made that was not made
before. And Robert has said that any program which failed as a result would
be broken. Thus I find the GNAT argument -- in this one specific case -- to
be "very weak", as Robert put it.
>>

I find that a possibility, and do not strongly object to this idea.

However, in practice I find the only useful use of Unsuppress to be
to undo a compiler option that suppresses checks.

I find it a big bogus to worry about a program that uses a suppress on
a specific entity and in a nested range needs to unsuppress it without
knowing that it is there.

Remember we are only talking static nesting here, i.e. the suppress
and unsuppress would have to be in the same package for Randy's worry
to apply.

It seems *awfully* theoretical to me ...


*************************************************************

From: Randy Brukardt
Sent: Wednesday, March 15, 2000 7:35 PM

> I find it a big bogus to worry about a program that uses a suppress on
> a specific entity and in a nested range needs to unsuppress it without
> knowing that it is there.

A Suppress...On can be used in a package specification, and would apply to that
entity anywhere it is used. (It applies to the entire scope of the entity, which
essentially is the whole program).

That's the case I'm worried about. I don't find that all that unlikely; it
certainly doesn't have to be in the same source file.

*************************************************************

From: Robert Dewar
Sent: Wednesday, March 15, 2000 8:58 PM

<<A Suppress...On can be used in a package specification, and would apply to
that entity anywhere it is used. (It applies to the entire scope of the
entity, which essentially is the whole program).

That's the case I'm worried about. I don't find that all that unlikely; it
certainly doesn't have to be in the same source file.
>>

I find this level of worry completely and utterly unconvincing. This is
simply not what Unsuppress is useful for in practice.

*************************************************************

From: Jean-Pierre Rosen
Sent: Thursday, March 16, 2000 2:39 AM

I must confess that I'm getting lost in this discussion, but it seems clear
to me that the difficulty is in the definition of Unsuppress in relation to
Suppress.
Why not abandon the idea of "unsuppressing", and rather have a pragma Force,
with a simpler semantics, something like:

pragma Force (identifier[, [On =>] name]);
The values of "identifier" are as defined for pragma Suppress. When in the
scope of a pragma Force, the corresponding checks are always in effect. Any
inner pragma Suppress will have no effect on entities to which a pragma
Force applies".

There is no contradiction, since a pragma Suppress can always be ignored.
There is no incompatibility, since existing implementation can still provide
pragma Unsuppress if they wish.

*************************************************************

From: Randy Brukardt
Sent: Thursday, March 16, 2000 11:02 AM

> Why not abandon the idea of "unsuppressing", and rather have
> a pragma Force,
> with a simpler semantics, something like:
>
> pragma Force (identifier[, [On =>] name]);

This is *exactly* where I started with pragma "Require". With exactly the
definition that Jean-Pierre recommends.

Of course, I was shouted down on that one. I think it would be pretty crazy to
revert the entire thing to the original version.

As it stands, I plan to write it up only with non-specific Unsuppress, an
implementation permission to support Unsuppress...On with implementation-defined
semantics, and the rule I outlined earlier (because it is easier to describe and
use). If it turns out that there are substantial implementation concerns, we can
revisit that detail.

*************************************************************

From: Robert A Duff
Sent: Thursday, March 16, 2000 8:06 AM

> I'm pretty tired of this discussion, and we've agreed on all of the other
> points, but I'll make one last try here.

As usual, we spend the most energy arguing about the least important
issues.  ;-)

I can go along with Randy's idea, so long as we agree that it's not
harder to implement.  I don't have evidence that it *is* harder.
I just think implementation difficulty should be the overriding concern,
given that "On=>" is so rarely used, and ill-defined anyway.

We have implemented pragma Unsuppress at AverStar, and I *think* we did
this "On=>" stuff the same way as GNAT.

So: I could agree to any of (1) the GNAT way, (2) Randy's way, or (3)
implementation defined.

*************************************************************


Questions? Ask the ACAA Technical Agent