Version 1.2 of ai12s/ai12-0393-1.txt

Unformatted version of ai12s/ai12-0393-1.txt version 1.2
Other versions for file ai12s/ai12-0393-1.txt

!standard 4.9(24/5)          20-09-10 AI12-0393-1/02
!class binding interpretation 20-09-03
!status Amendment 1-2012 20-09-10
!status ARG Approved 14-0-0 20-09-09
!status work item 20-09-03
!status received 20-07-06
!priority Low
!difficulty Easy
!qualifier Omission
!subject No invalid static constants
!summary
A constant is not static if its initialization fails due to a constraint or predicate check failure.
!question
What happens if the initialization of a constant with a static expression fails because the value violates a constraint or predicate of the object. Is the object still static? (No.)
!recommendation
We addressed part of this question in AI12-0108-1, to the extent of deciding on No-Action, but agreeing the issue is a pathology. This issue has recurred in the context of a static predicate, and it seems worth re-opening, and coming to the conclusion that such a constant is not static. However, we plan to retain this as a pathology, since there was an ACATS test (ACATS test B490001) which required declaring such a constant object as static, which forced implementers to make a choice.
!wording
Modify 4.9(24/5):
A static constant is a constant view declared by a full constant declaration or an object_renaming_declaration with a static nominal subtype, having a value defined by a static scalar expression or by a static string expression {, and which satisfies any constraint or predicate that applies to the nominal subtype}.
!discussion
The main issue justifying re-opening this issue is that in various places in the RM we presume that a static constant satisfies its constraints and predicates, and can safely be used in places that require static expressions. Once you break that presumption, you might have to review many parts of the RM to see if you end up with contradictory or meaningless statements. Hence, it seems simplest to say that a constant can be static only if satisfies its constraints or its predicates.
To aid implementors, we are promising not to test this, as the RM was ambiguous before, and there was an ACATS test that required allowing such a declaration and thus required making a choice as to whether or not the object was static.
A compiler survey of Ada 95 compiler reported in AI12-0108-1 noted that implementers were almost evenly split on the question of whether this object is static, as one might expect when the RM gives no answer to the question. Moreover, as the ACATS test has been in the test suite since 1996, this split has not produced significant portability problems in practice. Additionally, this fix would be incompatible for existing implementations that treated the constant as static (making previously legal code illegal, even if it never is executed), potentially impacting their customers. Such code is very possible in conditionally compiled code; enforcement of legality rules on static expressions enforced on such code is a known problem with Ada.
Finally, in most cases, the original "static" object that did not satisfy a constraint or predicate would raise an exception at run time, so code using it would never be executed, and thus how it could be used is not relevant.
for all of these reasons, requiring implementers to expend effort on fixing this seems counter-productive.
!corrigendum 4.9(24/5)
Replace the paragraph:
A static constant is a constant view declared by a full constant declaration or an object_renaming_declaration with a static nominal subtype, having a value defined by a static scalar expression or by a static string expression.
by:
A static constant is a constant view declared by a full constant declaration or an object_renaming_declaration with a static nominal subtype, having a value defined by a static scalar expression or by a static string expression, and which satisfies any constraint or predicate that applies to the nominal subtype.
!ASIS
No ASIS effect.
!ACATS test
No ACATS test should be created for this case.
!appendix

From: Steve Baird
Sent: Monday, July 6, 2020  6:56 PM

In AI12-0108 there is discussion of a problem illustrated
by the following example:

    package Range_Check is
      subtype S is Integer range 1 .. 9;
      X : constant S := 10;
    end Range_Check;

This was an unusual AI in which the ARG confirmed
the legality of the above example but explicitly
declined to decide whether X is a static constant.

So the legality of

    with Range_Check;
    package Range_Check_Client is
       Named_Number : constant := Range_Check.X;
    end Range_Check_Client;

was left up in the air. There were good reasons for this which
can be found in the AI, but this is still not a very
satisfactory situation.

Now a related question involving static predicates
has now come up and it may be time to revisit this question.

Consider this example:

    package Predicate_Check is
      pragma Assertion_Policy (...);
      subtype S is Integer with Static_Predicate => S in 1 .. 10;
      X : constant S := 11;
    end Predicate_Check;

    with Predicate_Check;
    package Predicate_Check_Client is
       Named_Number : constant := Predicate_Check.X;
    end Predicate_Check_Client;

It is a similar situation, with the interesting difference that
the first package will elaborate successfully if the specified
Assertion_Policy is Ignore (and assuming that the first package
declaration is legal). [One point that everyone agrees on is that for
each of these two packages, we want the unit's legality to be unaffected
by changing the argument of the Assertion_Policy pragma from Ignore to
Check or vice versa.]

After discussing this with Randy, Tuck, and others, the following
proposal emerged:

    1) Explicitly clarify (in a way that is not done in AI12-0108)
       that declaring a constant of a static subtype whose value is a
       static expression that does not belong to that subtype
       is legal, but does not declare a static constant. In the
       four example units given above, this means that the two
       declarations named X are legal and the two named number
       declarations are illegal.

    2) Affirm that this situation is viewed as a pathology and
       that, in particular, no tests will be written which would
       fail if an implementation chose (incorrectly) to treat
       such a constant declaration as a static constant.

    3) Clarify that this resolution of the issue applies in
       the same way to both range checks and predicate checks,
       and that enabling or disabling a predicate (e.g., via an
       Assertion_Policy pragma) has no effect on a unit's legality.

Opinions?

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

From: Tucker Taft
Sent: Monday, July 6, 2020  8:31 PM

After our various discussions, this emerged as the only approach that 
seemed to work without undue complexities.

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

From: Arnaud Charlet
Sent: Monday, July 6, 2020  11:23 PM

Can someone clarify what are the alternatives and what are the undue 
complexities involved?

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

From: Tucker Taft
Sent: Tuesday, July 7, 2020  7:30 AM

The main issue I would say is that in various places in the RM we presume 
that a static constant satisfies its constraints and predicates, and can 
safely be used in places that require static expressions.  Once you break 
that presumption, you might have to review many parts of the RM to see if you
end up with contradictory or meaningless statements.  Hence, it seems simplest
to say that a constant can be static only if satisfies its constraints or its 
predicates.  

To aid implementors, we are promising not to test this, as we believe it is a 
bit of a corner case, and the RM was ambiguous before.

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

From: Arnaud Charlet
Sent: Tuesday, July 7, 2020  8:25 AM

OK thanks for the details.

FWIW this seems to match GNAT's behavior so that's good:

     1. package Static is
     2.
     3.      subtype S is Integer range 1 .. 9;
     4.      X : constant S := 10;
                               |
        >>> warning: value not in range of type "S" defined at line 3
        >>> warning: "Constraint_Error" will be raised at run time

     5.
     6.      Named_Number : constant := X;
                                        |
        >>> non-static expression used in number declaration
        >>> expression raises exception, cannot be static (RM 4.9(34))

     7.
     8. end Static;

     1. package Predicate_Check is
     2.    pragma Assertion_Policy (...);
     3.    subtype S is Integer with Static_Predicate => S in 1 .. 10;
     4.    X : constant S := 11;
                             |
        >>> warning: static expression fails static predicate check on "S"
        >>> warning: expression is no longer considered static

     5.
     6.    Named_Number : constant := X;
                                      |
        >>> non-static expression used in number declaration
        >>> "X" is not a static constant (RM 4.9(5))

     7.
     8. end Predicate_Check;

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

From: Tucker Taft
Sent: Tuesday, July 7, 2020  11:26 AM

Good to hear.

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

From: Randy Brukardt
Sent: Tuesday, July 7, 2020  12:48 PM

> OK thanks for the details.
>
> FWIW this seems to match GNAT's behavior so that's good:

Keep in mind that this is an Ada 95 issue at its heart, so we have to consider 
the behavior of all Ada 95 compilers, not just GNAT. That various wildly, 
based in the survey done for AI12-0108-1. (I'd suggest reading that AI for 
more details.) Moreover, there is an ACATS test requiring part of this 
behavior.

Legality Rules based on values are always dubious: they cause problems in 
conditionally compiled code as well as portability problems. Sometimes that 
cannot be helped, but given that static values really don't have ranges 
anyway, range checks are particularly dubious for static expressions.

The most compatible choice would have been to follow AdaMagic's lead and leave 
the object static, but that would have required extra work for a number of 
compilers, including GNAT. Therefore, we decided to treat it as a pathology 
since it didn't seem important which choice was made (in almost all cases, the 
original "static" object would raise an exception at runtime, so how it would 
get used further is not relevant and such code would never be executed anyway).

It seems reasonable to continue this practical solution, but Steve's example 
seems to make it necessary for the language proper to define the correct 
behavior (for the reasons Tucker noted). So we're proposing fixing the wording 
but leaving the AI as a pathology to tell the ACATS people not to test the 
ramifications.

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

Editor's note (9/10/20): I was asked to check the ACATS test that is related 
to this test. The named test (C490001) does not appear to have anything to do
with static expressions. That test was named in AI12-0108-1 and was not 
checked when this AI was created.

After investigation, it appears that the declarations

   SubInt1 : constant My_Int_Sub := -128;                             -- OK.
                                 -- But raises Constraint_Error at run-time.

   SubInt3 : constant My_Int_Sub := 115;                              -- OK.
                                 -- But raises Constraint_Error at run-time.

on lines 321 through 325 of test B490001 is what is referred to in this
AI. Note that these declarations are never used later in the test so whether
or not they are static is not determined by the test. Thus it does not require
a particular choice to the question, but rather it requires implementers to
decide the question on their own. 

A compiler survey of Ada 95 compilers reported in AI12-0108-1 showed that
implementers split almost evenly on the answer to the question. The AI text 
was updated to reflect this.

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

Questions? Ask the ACAA Technical Agent