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
+implementation-defined.]
+
 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
+reasons.
+
+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
+needed.
+
+
+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
+cases.
+
+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?
+
+Similarly:
+
+        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.
+
+Consider:
+
+    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.
+
 !appendix
 
 *************************************************************
@@ -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