Version 1.4 of acs/ac-00016.txt

Unformatted version of acs/ac-00016.txt version 1.4
Other versions for file acs/ac-00016.txt

!standard 6.3.2(3)          01-10-16 AC95-00016/01
!class amendment 01-10-16
!status received no action 01-10-10
!subject pragma Read_Only
!summary
!appendix

From: V. Santhanam (Boeing)
Sent: Wednesday, October 10, 2001 9:12 AM

Issue:

In Ada, it is awkward to create a variable in a package for read/write use
internally but read-only use by clients. To achieve this, one would have to
declare the variable either in the private part of the package spec or in
the body, and provide a visible function to read the variable.

Solution:

Provide a Read_Only pragma which can be applied to variables in the visible
part of a package so that they are treated as constants by the clients of
the package. Example:

	Error_Count : Natural := 0;
	pragma Read_Only (Error_Count);

The read-only restriction is not applicable the declaring package itself.

Reasoning:

The reader function approach incurs a significant run-time penalty. I know
of at least one program in which a decision was made to declare all such
variables in the visible part of the package, exposing them to potential
modifications by clients, in order to avoid the function call penalty.
Inlining the function call was not an option for certification reasons. The
proposed solution will avoid the run-time penalty without sacrificing
safety.

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

From: Randy Brukardt
Sent: Tuesday, October 16, 2001  7:12 PM

> The reader function approach incurs a significant run-time penalty.

It shouldn't have any runtime penalty, if combined with a pragma Inline. Why
doesn't that solve your problem without introducing any new language features?
(If your vendor doesn't Inline these properly, either pressure or change the
vendor! This is the sort of thing that Inline was designed to handle).

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

From: Craig Carey
Sent: Thursday, October 18, 2001  7:23 PM

At 2001.October.10 09:12 -0500 Wednesday, Santhanam, Vdot wrote:
 >Issue:
 >
 >In Ada, it is awkward to create a variable in a package for read/write use
 >internally but read-only use by clients. To achieve this, one would have to
 >declare the variable either in the private part of the package spec or in
 >the body, and provide a visible function to read the variable.
 >
 >Solution:
 >
 >Provide a Read_Only pragma which can be applied to variables in the visible

What about "exported constant" (etc.) ?, or "pragma Export_As_Constant(...)" ?.
'Read_Only' sounds like a description that can make the variable be constant,
even inside of the body of the package.

 >part of a package so that they are treated as constants by the clients of
 >the package. Example:
 >
 >       Error_Count : Natural := 0;
 >       pragma Read_Only (Error_Count);
 >
 >The read-only restriction is not applicable the declaring package itself.
 >

In GNAT there is this error message:

     "error: access-to-variable designates constant";

when the 'Access attribute is applied to a constant. Pointers to constants
can't be assigned and the language does not dynamically keep track of
whether a pointer is to a constant or to a variable.

I saw a comment (not public at this list) that suggested that this could be
a difficult thing for a compiler vendor to implement.

Note that there was no mention of interfacing with another language, e.g. C.

-------------------------------------------------

At 2001.October.16 19:13 -0500 Tuesday, Randy Brukardt wrote:
 >
 >> The reader function approach incurs a significant run-time penalty.
 >
 >It shouldn't have any runtime penalty, if combined with a pragma Inline.
 >Why doesn't that solve your problem without introducing any new language
 >features?

It could be bugs in the compiler that Boeing was using or a suspicion of
them.

 >          (If your vendor doesn't Inline these properly, either pressure or
 >change the vendor! This is the sort of thing that Inline was designed to
 >handle).
 >


Inlining is something that may not happen even after the compiler is told
to inline. If it is a serious suggestion, then universities could teach
students how to study Ada code in its assembly language form.

In GNAT there are restrictions on inlining: (quoting from the user guide):

        "The call appears in a body (not in a package spec).".

Also the -gnatn option must be specified and so must a -O1 or -On
optimising option.

An option could be to put the many variables of the package spec, into a
a single record and then have two of those records overlaid.

One record would be constant and exported to other packages.
The other record would be not constant, and its components could be used
inside of the package. Some trick I can't think of at the moment is
used to circumvent the prohibition against applying 'Access to a
constant.

That could be regarded as a proof that compiler vendors can implement the
feature easily. But I am not sure.

Another option might be to have a simple dummy package to get around the
safety problem. Here is an example":

generic
    Pkg_Security_ID_Code : Boolean;
package West_Coast_Consts is
    ...
    A69  : constant Boolean := East_Coast_Vars.A96;
    ...   -- 555 more lines
end West_Coast_Consts;

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

From: Tucker Taft
Sent: Thursday, October 18, 2001  9:18 PM

[Perhaps this was already suggested?]

One quite efficient way to accomplish this is to make the
variable aliased but in the private part, and then export an
access-to-constant pointing to it, as follows:

package P is
    type T is ...;

    type Acc_Const_T is access constant T;
    Read_Only_Ptr : constant Acc_Const_T;  -- Read_Only_Ptr.all is read-only
...
private
    Read_Write_Variable : aliased T;
    Read_Only_PTr : constant Acc_Const_T := Read_Write_Variable'Access;
...
end P;


I suppose one simple language change would be to allow a deferred
"constant" to be completed with a variable declaration.
However, that might mask true errors.

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

From: Pascal Leroy
Sent: Friday, October 19, 2001  1:21 AM

I believe that you can do that by completing the deferred constant by a
pragma Import, and exporting the variable with a pragma Export, both pragmas
having convention Ada.  Of course, this is assuming that your compiler
supports these pragmas, but then convention Ada is not too hard to support.

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

From: Robert Dewar
Sent: Friday, October 19, 2001 10:05 AM

But one would think that most coding standards should prohibit this usage,
since it takes you totally outside the Ada type system (it is really
amazing how much damage pragma Import/Export (Ada does to the Ada model,
for instance it also allows you to go completely outside the elaboration
model).

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

From: Robert Duff
Sent: Friday, October 19, 2001 12:13 PM

I evilly use it to put debugging printouts in pragma-Pure packages!

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

From: V. Santhanam (Boeing)
Sent: Friday, October 19, 2001 8:44 AM

I am trying to catch up on the various e-mail messages that have gone back
and forth on this subject. Let me begin by pointing out that inlining was
not an option on the programs in which I encountered the need, due to
certification reasons. If it is not immediately obvious why certification
authorities have heartburn with inlining, let me know and I will explain the
rationale.

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

From: Robert Dewar
Sent: Friday, October 19, 2001 9:43 AM

<<In GNAT there are restrictions on inlining: (quoting from the user guide):

        "The call appears in a body (not in a package spec).".

Also the -gnatn option must be specified and so must a -O1 or -On
optimising option.>>

Well in this particular case the restriction on calls in the spec could
not be an issue, since this would be an access before elaboration error.
As for requiring optimization for inlining, I see no problem with that.

It seems to me that, for GNAT at least, there is zero penalty for using
a function for this purpose, so the proposed feature adds no expressive
power, or efficiency gain.

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

From: Pascal Leroy
Sent: Sunday, October 21, 2001  3:52 AM

> If it is not immediately obvious why certification
> authorities have heartburn with inlining, let me know and I will explain
> the rationale.

But then I fail to see why the same certification authorities would not have
the same heartburn with pragma Read_Only.  If the problem with inlining is
that you don't trust the optimizers to do the right thing, then surely
pragma Read_Only would be much worse.  In essence we would have an object
which is constant when seen from certain places and variable when seen from
other places.  Now constancy is a fundamental property for optimizers, as
they use it to avoid reevaluating certain expressions.  If constancy can
vary from place to place, I am ready to bet that optimizers would
occasionally get confused, and assume constancy at the wrong place,
resulting in plague and pestilence.

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

From: Dan Eilers
Sent: Thursday, October 25, 2001  2:46 AM

I believe the certification authorities who don't trust optimizers
to do the right thing with inlining, don't trust optimizers in general.
So they insist that the optimizer be turned off.  The idea of pragma
Read_Only is that it should generate reasonable code without needing
the optimizer.  Unfortunately, this isn't the only case in Ada where
optimization is relied on to generate reasonable code.

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

From: Randy Brukardt
Sent: Thursday, October 25, 2001 12:51 PM

> But then I fail to see why the same certification authorities would not
> have the same heartburn with pragma Read_Only. ...

An even more important question is why those certification authorities would
have a problem with Tucker's suggested why to get this behavior in Ada 95
with very little extra code.

To remind, his suggestion was to export an access-to-constant type and a
constant object which points at the variable that you need to protect from
outside modification. The original example would look like:

package Stuff is
    ...
    type Access_Error_Count is access constant Natural;
    Error_Count_Access : constant Access_Error_Count;
    ...
private
    ...
    Error_Count : aliased Natural := 0;
    Error_Count_Access : constant Access_Error_Count := Error_Count'access;
    ...
end Try;

This is perfectly legal Ada 95. The overhead is only a single dereference
per use (plus a null check if the compiler is stupid). The accesses can't
fail (Error_Count_Access is not null). No dynamic allocation is involved
(one could put an empty storage pool on the type to insure this, if the
certification guys are freaked out by it).

If one of the Ada 0y proposals is adopted, we could even declare that the
object cannot be null (eliminating the check and the only realistic
objection that I can think of):

    type Access_Error_Count is access constant Natural not null;

So why do we need a complex (to implement and describe in RM language) new
feature here???

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

From: Craig Carey
Sent: Thursday, October 25, 2001 12:51 PM

At 01.10.19 08:20 +0200 Friday, Pascal Leroy wrote:
 >> I suppose one simple language change would be to allow a deferred
 >> "constant" to be completed with a variable declaration.
 >
 >I believe that you can do that by completing the deferred constant by a
 >pragma Import, and exporting the variable with a pragma Export, both pragmas
 >having convention Ada.  Of course, this is assuming that your compiler
 >supports these pragmas, but then convention Ada is not too hard to support.
 >
 >Pascal
 >

I tried that and it seems to be a solution.
[No syntax error can appear [in GNAT] when the text in the External_Name is
wrong (but that was with the imported local variable being not used).
So some of the checking could be done after the compile.]

-----

There is also this associated topic of read-only record fields!.
I guess that neither feature:
   read-only spec vars, read-only non-discrete record fields;
may arrive in Ada 0y unless the two appear together.

I found out that Ada 95 has already implemented read-only record fields,
in its own way. Research into the usage of Ada quite possibly might show
that the current syntax is not designed quite right.

Here is an example showing how to have a read-only access type.

----------------------------------------
package P is
    type TP is access all TR;
    Null_TP : aliased constant TP := new TR'(...);

    type T (Ptr : TP := Null_TP) is limited null record;

    procedure G (L : in out T);
end P;

package body P is
    procedure G (L : in out T) is
       X : TP;
       for X'Address use L.Ptr'Address;
    begin
       X := new TR'(...);
    end G;
end P;

--  The use of 'limited' makes T be passed by reference (RM 6.2)
--   whenever it is passed as a parameter.
----------------------------------------

The syntax above looks like it is one that users do not know about or
that former C programmers might want to avoid even if they do know
about it (unless they like using 'Address). I had to get information
by e-mail before I found out that Ada 95 already implements read-only
record fields.

The last Rationale on "the needs of users" said this:

 >Wherever possible, enhanced functionality in Ada 95 has been achieved by
 >seeking and eliminating such unnecessary assumptions, thereby permitting
 >the generalization of features already in Ada, and the removal of special
 >cases and restrictions.

Someone with similar views, might be noting that:
    Ada 95 implements a constant or read-only record field feature, but
    only for fields that are an access type or a discrete type.

RM 3.7 says:

 >A discriminant of an object is a component of the object, and is either
 >of a discrete type or an access type.

What about making removing the read-only feature from discriminants?.
Variants could be auto-resized as needed. While it could be opposed, it
could improve consistency inside the topic.

-----

At 01.10.21 10:51 +0200 Sunday, Pascal Leroy wrote:
 >> If it is not immediately obvious why certification
 >> authorities have heartburn with inlining, let me know and I will explain
 >> the rationale.
 >
 >But then I fail to see why the same certification authorities would not have
 >the same heartburn with pragma Read_Only.  If the problem with inlining is
 >that you don't trust the optimizers to do the right thing, then surely
 >pragma Read_Only would be much worse.  In essence we would have an object
 >which is constant when seen from certain places and variable when seen from
 >other places.  Now constancy is a fundamental property for optimizers, as
 >they use it to avoid reevaluating certain expressions.  If constancy can
 >vary from place to place, I am ready to bet that optimizers would
 >occasionally get confused


A read-only field or spec variable ought be seen as being not 'constant' if
this is feature occurs:
    procedures in the defining package can freely alter that package's
    read-only fields and exported read-only variables.

Currently seems improvable: to make a record field be read-only, this
sort technique can be used:

    package Code_Quality_Stats is
       ...
       type EC_Ptr is access constant EC_Rec;
       type Safe (
             ...
             Error_Counters : EC_Ptr;    --  lots of fields
             ...
          ) is limited null record;
       ...
    end Code_Quality_Stats is

The keyword 'aliased' is not allowed for discriminant declarations.

Can Ada be made so that users get a guarantee that the memory holding
the value of the discriminant will always be able to be written too, no
matter what the machine ?.

The rationale listed interfacing (with C, etc.) as a 1st aim (that was
in "I.3 The main user needs", Intermetrics, Jan 1995).

The use of 'private' interferes with interfacing and the finer control
of allowing specifying of a read-only property can advance a need seen
by Intermetrics years ago.

If record fields can be read-only then why not just make the package
spec variables also be able to be read-only ?. It is an indirect way
to solving that issue.

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

Questions? Ask the ACAA Technical Agent