CVS difference for ais/ai-00224.txt

Differences between 1.14 and version 1.15
Log of other versions for file ais/ai-00224.txt

--- ais/ai-00224.txt	2000/03/23 01:37:41	1.14
+++ ais/ai-00224.txt	2000/03/23 23:24:04	1.15
@@ -1,4 +1,4 @@
-!standard 11.5(1-8)                                  99-12-13  AI95-00224/02
+!standard 11.5(1-8)                                  00-03-23  AI95-00224/03
 !standard 11.5(27)
 !class amendment 99-11-19
 !status work item 99-11-19
@@ -35,8 +35,8 @@
    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.
+The identifier argument of Unsuppress is 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.
@@ -88,7 +88,7 @@
 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
+check names 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.
@@ -99,6 +99,12 @@
 given as configuration pragmas in different compilations, it is
 implementation-defined whether the check is suppressed.
+If an implementation supports the On parameter to pragma Unsuppress, the exact
+entities for which an Unsuppress pragma with an On parmameter revokes a check
+are implementation-defined. [In particular, whether checks suppressed with a
+general pragma Suppress (one without an On parameter) are revoked is
 Add an additional note after 11.5(29):
 It is possible to give both a pragma Suppress and Unsuppress for the same check
@@ -159,6 +165,7 @@
 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
@@ -193,17 +200,105 @@
 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
+requiring that. We do require that any check names 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.
+The entities which have their checks revoked by an Unsuppress pragma with an
+On parameter are implementation-defined. This is necessary both because it
+is impossible to tightly define the meaning of Suppress and for implementation
+One issue is that exactly which entit(ies) control when a check is performed
+is (purposely) not defined. In
+       A := B;
+whether the range check is performed may depend whether checks are suppressed
+on A, B, or the type of A. For check suppression, this is not critical, as
+any code that would violate the checks is erroneous anyway (11.5(26)). On
+the other hand, not making a check that the programmer is depending on can
+cause the program to fail. But what should be Unsuppressed in the above
+example? A, B, or the type of A? The answer probably varies from implementation
+to implementation, and there is little value in defining it more tightly.
+There is also an implementation issue. Implementations typically use a set
+of flags for non-specific Suppress pragmas (those without On parameters),
+and flags on individual entities for Suppress pragmas with On parameters.
+However, if something like
+       pragma Suppress (Index_Check);
+       ...
+       pragma Unsuppress (Index_Check, On => A);
+occurs, the implementation would need to support "Suppress all index checks
+except those on A". Doing so would require either getting rid of the set of
+non-specific flags (using only the entity flags, which would make non-specific
+Suppresses quite expensive, as the entire symbolable would need to be walked
+when the suppression state changed), or implementing some sort of exception
+list. This implementation burden is not worth it for a capability whose meaning
+is implementation-defined anyway.
+Notice that the inverse case does not suffer from either of these problems.
+If a non-specific Unsuppress revokes a check on a specific entity, there is
+no gray area as to whether the check is performed or not. For example, in
+        pragma Suppress (Access_Check, On => Some_Subtype);
+	...
+	Obj : Some_Subtype;
+        pragma Unsuppress (Access_Check);
+	...Obj.all...
+it does not matter if the check is made on Obj or on Some_Subtype, because
+we know the check will be performed.
+Alternative rules would likely be a surprise to users. If a user writes
+     pragma Unsuppress (All_Checks);
+in some scope, they would be very surprised to discover that any checks are
+still suppressed. Moreover, if there were any checks still suppressed, the
+value of pragma Unsuppress as a portable preventative pragma is weakened:
+whether or not the program works may depend on the compiler used.
+Finally, the implementation of the revokation of specific checks is not
+difficult. It only requires that some way exist to find all of the entities
+which have had a pragma Suppress with an On parameter applied to them. A
+list would be appropriate, as the number of such entities will usually be
+small. At the application of a pragma Unsuppress, the list would be checked,
+flags changed on any entities that need it, and the changes stacked in the
+same way that local Suppress pragmas are handled. Unlike a Unsuppress pragma
+with an On parameter, no changes to the flags or added exception lists are
+One minor surprise with checking pragmas is that an inherited pragma can
+override an explicitly given one. Checking pragmas are inherited into the
+bodies of packages when they are given in a specification. For example:
+    package My_Pack is
+        pragma Unsuppress (Access_Check);
+    end My_Pack;
+    pragma Suppress (Access_Check);
+    package body My_Pack is
+        -- pragma Unsuppress (Access_Check) inherited here.
+	-- Access_Checks are not suppressed in this body.
+    end My_Pack;
+Since the configuration pragma is outside of the package body, it is revoked
+by the inner, inherited Unsuppress pragma. While this may be momentarily
+surprising, it follows from the standard scoping rules. This case is more
+common than appears at first glance, as configuration pragmas can occur from
+compiler options.
+In the case given in the example, the result is probably what we want -- we
+do not want checks to disappear because of a compiler switch if there is an
+explicit Unsuppress somewhere. Unsuppress configuration pragmas will be rare,
+as they usually don't have any Suppresses to revoke. Thus, we don't need to
+consider its impact here. Since there is no clear advantage to a special rule
+to cover inherited pragmas, we simply use the natural interpretation.
 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
@@ -217,6 +312,83 @@
 extension in several compilers, and standardizing existing practice is
 usually better than inventing new ideas.
+An alternative definition was suggested that would eliminate the need to make
+the meaning of Unsuppress with an On parameter implementation-defined.
+The idea of the alternative definition is to have pragma Unsuppress revoke
+a particular Suppress pragma, rather than revoking a check. Doing so
+avoids the implementation dependence of what exactly is checked, because
+the pragmas involved are well-defined.
+However, this approach has a substantial impact on usability, and there is also
+difficulty in defining exactly what is revoked, especially in the On parameter
+The problems with defining what is revoked come from that fact that the check
+names are not disjoint. For instance, the check name All_Checks is defined to
+be the union of all defined checks. Does a checking pragma using All_Checks
+match a pragma using some other check? If it does, then particular pragmas
+need to be able to match sets and portions of other pragmas.
+For instance:
+	pragma Suppress (Access_Check);
+        pragma Suppress (Index_Check);
+        ....
+        pragma Unsuppress (All_Checks);
+In this case, does Unsuppress (All_Checks) revoke both pragmas?
+        pragma Suppress (All_Checks);
+        ....
+        pragma Unsuppress (Index_Check);
+In this case, does Unsuppress (Index_Check) revoke the "Index_Check" portion
+of the pragma Suppress?
+A similar problem occurs for the On parameter, as separate entities may not in
+fact have separate checks. For instance, 11.5(8) clearly states that checks
+are defined on types, not on subtypes. However, two different subtypes of the
+same type are clearly separate entities. Does an Unsuppress on one of the
+subtypes revoke a check suppressed on the other? These sort of questions
+immediately lead back into the morass that we are trying to avoid.
+This definition also suffers from a usability problem. A pragma Unsuppress
+does not revoke checks on a non-matching pragma Suppress. This greatly
+reduces the usefulness of the pragma as a preventative, as a pragma Suppress
+added elsewhere in the source of a program can leak into a supposedly
+Unsuppressed program region.
+    package Something is
+	...
+        pragma Suppress (Access_Check, On => Some_Subtype);
+    end Something;
+    with Something;
+    procedure Needs_Checks is
+        pragma Unsuppress (All_Checks);
+            -- Make sure that all checks are made in this unit.
+        Obj : Something.Some_Subtype;
+    begin
+        ... Obj.all ... -- Oops, no check made here.
+    exception
+        when Constraint_Error => ...
+    end Needs_Checks;
+Since the pragma Suppress does not "match" the pragma Unsuppress, the
+Access_Check on Obj is still suppressed, and the exception handler will
+not be invoked. Worse, the insertion of a pragma Suppress in some unit
+can break code in a unit far away. This is the sort of problem that we try to
+prevent in Ada, and the cost to do so in this case is not high.
+While this problem can be mitigated somewhat by expanding the matching rules,
+doing so adds complications, and makes the resulting solution similar
+to the one proposed.
@@ -3147,6 +3319,23 @@
 we inherit here, it is clearly required by the RM> Sure you can
 cheat (you can completely ignore suppress for example), but it  is
 clear there is no semantic issue here.
+From: Randy Brukardt [Editor]
+Sent: Thursday, March 23, 2000
+If the implementation burden of supporting non-specific Unsuppress
+canceling specific Suppress is too great, I would prefer that it be
+handled by adding an implementation permission to that effect. Doing
+so would avoid needing to define too carefully the matching rules of
+Robert's alternative rules.
+Note that I left Unsuppress(..., On => ...) defined in the standard.
+It seems to make more sense to leave the basic definition of the pragma
+intact, especially since there is already a blanket permission to not
+support any of these pragmas. And leaving the parameter defined makes it
+a lot easier to describe exactly what is implementation defined.

Questions? Ask the ACAA Technical Agent