!standard 11.5(1-8) 99-11-19 AI95-00224/01 !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 Require !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 Require is defined. pragma Require (identifier [, [On =>] name]); The arguments of Require are the same as Suppress. Require can be used in the same places as Suppress, with the same scoping rules. Pragma Require means that the given check must be performed. !wording Define "Checking pragmas" and add pragma Require 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 Require requires an implementation to make certain language-defined checks. Add pragma Require to 11.5(3-4): The forms of checking pragmas are as follows: pragma Require(identifier [, [On =>] name]); pragma Suppress(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 Require: 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, but not for any entity to which a pragma Require applies. 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 Require 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. !example We can use pragma Require to insure that checking occurs in the saturation multiply function given earlier: function "*" (Left, Right : Saturation_Type) return Saturation_Type is pragma Require (Overflow_Check); begin return Integer(Left) * Integer(Right); exception when Constraint_Error => return Saturation_Type'Last; end "*"; !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 Require has no effect on compiler optimization of checks. A compiler is still allowed to remove checks that it can prove will not fail. An early proposal called this pragma "Unsuppress". This name 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. This proposal does not allow suppressing checks inside of a checking required region. Such "resuppression" of checks could be supported, but does not seem important and would add implementation complexity (an implementation would need a stack of suppress and require pragmas). While it is possible for a programmer to require checks over an entire program, this is not the intended use of pragma Require. It is intended to be used in subprograms and blocks where checking is required. An implementation ought to display a warning if an attempt to give a pragma Suppress occurs in a region governed by a pragma Require for the same check, as the Suppress can have no effect. Restrictions can be placed on pragma Require. 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 Require, 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 Require than of Suppress if they desire. !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 guideance 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 Supress. 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. *************************************************************