Version 1.8 of ais/ai-00190.txt

Unformatted version of ais/ai-00190.txt version 1.8
Other versions for file ais/ai-00190.txt

!standard 13.12 (09)          99-09-15 AI95-00190/04
!standard D.7 (15)
!class binding interpretation 98-10-09
!status Corrigendum 2000 99-07-27
!status WG9 approved 99-06-12
!status ARG approved (6-0-0) 98-10-09
!status work item 98-09-26
!status received 97-08-19
!priority Medium
!difficulty Hard
!qualifier Clarification
!subject Compile-time enforcement of pragma Restrictions
!summary
Whenever enforcement of a restriction imposed by pragma Restrictions is not required by the Standard prior to execution, but left to implementation-defined behaviour of dynamic semantics, it is reasonable to interpret pre-execution enforcement as a valid implementation-defined behaviour, provided that every execution of the partition will violate the restriction.
!question
Shall we allow implementations to reject (i.e. refuse to run) programs that have run-time detected violations of pragma Restrictions, when they are detectable at compile time? (Yes.)
!recommendation
(See summary.)
!wording
Add an Implementation Permission after 13.12(9):
"Whenever enforcement of a restriction is not required prior to execution, but left to implementation-defined behaviour of dynamic semantics, an implementation may enforce the restriction prior to execution of a partition to which the restriction applies, provided that every execution of the partition would violate the restriction."
!discussion
For the particularly critical rejection of programs that violate restrictions imposed by pragma Restrictions, the Standard provides for implementation-defined behaviour in lieu of a compile- or link-time check otherwise required by 13.12(8). It is reasonable to interpret pre-execution enforcement of a configuration pragma as a valid implementation-defined behaviour, even if such enforcement is not required to occur prior to execution. This is particularly true for D.7(15), as this clause recommends the raising of a Storage_Error exception but does not specify the place where such an exception is to be raised.
!corrigendum 13.12(9)
Insert after the paragraph:
An implementation may place limitations on the values of the expression that are supported, and limitations on the supported combinations of restrictions. The consequences of violating such limitations are implementation defined.
the new paragraph:
Whenever enforcement of a restriction is not required prior to execution, but left to implementation-defined behavior of dynamic semantics, an implementation may enforce the restriction prior to execution of a partition to which the restriction applies, provided that every execution of the partition would violate the restriction.
!ACATS test
This is not testable, as is an implementation permission.
!appendix

!section 13.12(0)
!subject rejecting violations of pragma Restrictions
!reference RM95 13.12
!from Ted Baker 97-04-20
!reference 1997-15747.a Ted Baker  1997-4-20>>
!discussion

At the April 1997 ARG meeting, the issue came up of whether a
compiler that detects a violation of a restriction specified in a
Restrictions pragma may reject the input at compile time or link
time, as compared to being required to compile and link the code,
so that it can run and raise Program_Error at run time.

At issue is the treatment of those restrictions where the ARM
gives permission for a language-defined restriction to be checked
at run time, e.g.  D.7 (16-19).  There seems to be agreement that,
for example, a compiler can reject a compilation that violates the
static semantic restrictions in D.7 (2-13), or that violates an
implementation-defined restriction.

Bob Duff argued that the ARM consistently makes a strong
separation between what can cause a program to be rejected prior
to execution time, and what can cause a runtime error.  He argued
that to allow a compiler to reject a program for the violation of
the restrictions in D.7 (2-13) would be inconsistent with this
policy.

I do know know for certain that this putative strong separation
exists, but assuming it does, I question its value and
appropriateness in this case.

There are at least two reasonable lines of argument to support
allowing a compiler to reject compilations where it detects a
violation of a restriction:

1) Treatment of other implementation restrictions by the ARM95.
2) The language describing the restrictions pragma, itself.

| 13.12 Pragma Restrictions
| 1   A pragma Restrictions expresses the user's intent to abide by certain
| restrictions.  This may facilitate the construction of simpler run-time
| environments.
...
|                            Post-Compilation Rules
...
| 8   A pragma Restrictions is a configuration pragma; unless otherwise
| specified for a particular restriction, a partition shall obey the
                                                      ^^^^^
| restriction if a pragma Restrictions applies to any compilation unit included
| in the partition.
...
|                          Implementation Permissions
...
| 9   An implementation may place limitations on the values of the expression
| that are supported, and limitations on the supported combinations of
| restrictions.  The consequences of violating such limitations are
| implementation defined.

It is reasonable to interpret an occurrence of the Restrictions
pragma as (at least) giving the implementation permission to
impose the stated restrictions or (capacity limits) on the
compilation.  If those restrictions are violated, it should have
the range of options available for other implementation
restrictions and capacity limits.

Throughout the ARM, there are references to places where an
implementation may impose capacity limits or other forms of
restrictions.  The usual correct reaction to a program that violates
a capacity limit or other restriction is to reject the compilation,
if it is detected at compile time.  For example, consider the
declaration of a numeric type whose range exceeds that supported
by the implementation.

RM95 says, regarding capacity limits:

| 1.1.1 Extent
| 9   This International Standard does not specify:
| ....
|    15  The size of a program or program unit that will exceed the
|        capacity of a particular conforming implementation.
...
| 1.1.3 Conformity of an Implementation with the Standard
| 1   A conforming implementation shall:
...
|     3  Identify all programs or program units that are so large as to
|        exceed the capacity of the implementation (or raise an
|        appropriate exception at run time);

Note that the implementation is given the CHOICE here of raising an
appropriate exception at run time, or rejecting the compilation.

Some of the examples of uses of the term "restriction" for
implementation limitations are in 10.1 (4) [compilations with
multiple compilation units], 10.1.5 (9) [configuration pragmas],
10.1 (29) [main subprograms], 13.1 (20) [representation items],
13.7.2 (6) [address_to_access_conversions], 13.8 (8) [machine code
insertions], 13.9 (13) [unchecked_conversion], B.1 (42)
[interfacing pragmas].

In the most of these cases it is conventionally accepted that
violation of the restriction is grounds for rejecting of a
compilation or linkage.  (In the case of
address_to_access_conversions, it is not clear whether the
compiler might reject an instantiation at compile time or cause an
exception to be raised at the point of instantiation.)

Note that the description of the effect of the pragma restrictions
says "unless otherwise specified for a particular restriction, a
partition shall obey the restriction".  This requires a pre-runtime
check, unless specified otherwise.

Here is some of the relevant ARM95 text about pre-runtime checks:

| 1.1.5 Classification of Errors
|                          Implementation Requirements
| 1   The language definition classifies errors into several different
| categories:
|     2   Errors that are required to be detected prior to run time by
|        every Ada implementation;
|        3   These errors correspond to any violation of a rule given in
|        this International Standard, other than those listed below.  In
|        particular, violation of any rule that uses the terms shall,
                                                               ^^^^^
|        allowed, permitted, legal, or illegal belongs to this category.
|        Any program that contains such an error is not a legal Ada
|        program; on the other hand, the fact that a program is legal does
|        not mean, per se, that the program is free from other forms of
|        error.

As I read it, the qualifying phrase "unless otherwise specified
for a particular restriction" is intended to give the
implementation permission not to detect certain violations prior
to run time, not to prevent them from doing so and rejecting the
program earlier if that is possible.

[As one of the authors of the material on tasking restrictions,
I can add that that is consistent with my own understanding of the
intent behind splitting up the list of tasking restrictions.]

Note also that in D.7 (15) we have, for the "dynamic" restrictions,
the following wording:

| 15   If the following restrictions are violated, the behavior is
| implementation defined.  If an implementation chooses to detect such a
| violation, Storage_Error should be raised.

It can be argued that the phase "the behavior is implementation
defined" gives the implementation the right to reject the violation
of the restriction prior to run time.

--Ted Baker

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

Questions? Ask the ACAA Technical Agent