Version 1.1 of acs/ac-00096.txt

Unformatted version of acs/ac-00096.txt version 1.1
Other versions for file acs/ac-00096.txt

!standard 13.1(19)          04-04-23 AC95-00096/01
!standard 13.1(20)
!class confirmation 04-04-23
!status received no action 04-04-23
!status received 04-04-15
!subject Overlaying Address clause onto constant
!summary
!appendix

From: Martin Dowie
Sent: Thursday, April 15, 2004  5:25 AM


Consider the following package specification:

package Constant_Test is
   Foo : constant Integer;
   procedure Increment;  -- "Bar := Bar + 1;"
private
   Bar : Integer := 100;
   Foo : constant Integer := Bar;
   for Foo'Address use Bar'Address;
end Constant_Test;

What should the following test program produce?

with Ada.Text_IO; use Ada.Text_IO;
with Constant_Test;

procedure Test_Constant is
begin
   Put_Line (Integer'Image (Constant_Test.Foo));
   Constant_Test.Increment;
   Put_Line (Integer'Image (Constant_Test.Foo));
end Test_Constant;

I have 2 compilers to hand and they produce...

100
100

  ...and...

100
101

Neither compiler produced even a warning.

Which is right?
Are they both right? If this is implementation dependent then what is the
section?

I can't see anything in 3.13 that forbids this and I'm not sure it should be
forbidden. The above use mimics other languages (e.g. Pascal/D80) 'read-only
variables'.

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

From: Martin Dowie
Sent: Thursday, April 15, 2004  6:14 AM

Always nice to answer your own questions!

I believe 13.1(14) (and hence also C.2) is what I was looking for.

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

From: Tucker Taft
Sent: Thursday, April 15, 2004  8:23 AM

Perhaps you mean 13.3(19).  But in any case,
if you want this to work, and you are changing the
value of a constant "behind the scenes" then you will
be wise to declare the constant "volatile."  An alternative
approach is to declare an access-to-constant type and
make the variable aliased, and and declare the constant
as a rename of acc_to_con'(var'access).all.

E.g.:

    Var : aliased T;
    type acc_to_con_T is access constant T;
    Const : T renames acc_to_con_T'(Var'Access).all;

If the constant isn't declared volatile, and is
not the result of derefencing an access-to-constant
value, then it seems likely that many compilers
will assume its value is unchanging.  It somewhat
depends on the interpretation of "optimizations
based on assumptions of no aliases."  The assumption
that the value of a stand-alone non-volatile constant
doesn't change seems like part of the core semantics
of the language, not an "optimization."

As 3.3(13) says, "the value of a constant object
cannot be changed between its initialization and
its finalization."  The only place where this
requirement is softened is for volatile constant
objects, as implied by C.6(22), which is a consequence
of C.6(16).

You could perhaps argue that 13.3(19) makes a constant
object with an address clause implicilty "volatile," but
I don't believe that was ever the intent.  And certainly
if you are trying to write portable code, I would encourage
you to put in a pragma Volatile on the constant object,
or define it as a rename of the .all, as illustrated above.

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

From: Martin Dowie
Sent: Thursday, April 15, 2004  9:32 AM

> > I believe 13.1(14) (and hence also C.2) is what I was looking for.
> > Perhaps you mean 13.3(19).

There seems to be a difference in how the RM is section
numbered depending on which IDE I'm using.

[Mental note: the numbers in the AdaGIDE version differ
from actual RM.]

So the section I meant to quote turns out to be 13.1(20):

"An implementation may interpret aspects of representation
 in an implementation-defined manner. An implementation may
 place implementation-defined restrictions on representation
 items. A recommended level of support is specified for
 representation items and related features in each
 subclause. These recommendations are changed to
 requirements for implementations that support the Systems
 Programming Annex (see C.2, ``Required Representation
 Support'')."


> But in any case,
> if you want this to work, and you are changing the
> value of a constant "behind the scenes" then you will
> be wise to declare the constant "volatile."

Can't do that:
"C.6(13), Constant volatile or atomic objects must be imported"
and a different one again if I try and Import it too.

Neither compiler likes that one.


> An alternative
> approach is to declare an access-to-constant type and
> make the variable aliased, and declare the constant > as a rename of acc_to_con'(var'access).all.
> > E.g.:
> >     Var : aliased T;
>     type acc_to_con_T is access constant T;
>     Const : T renames acc_to_con_T'(Var'Access).all;

But Var has to be made public (unless I go into child units)
which rather defeats the point of the exercise.

> As 3.3(13) says, "the value of a constant object
> cannot be changed between its initialization and
> its finalization."  The only place where this
> requirement is softened is for volatile constant > objects, as implied by C.6(22), which is a consequence
> of C.6(16).

Right, so to me that should mean Compiler-2 was just
*wrong* in giving result:

100
101


> You could perhaps argue that 13.3(19) makes a constant
> object with an address clause implicilty "volatile," but
> I don't believe that was ever the intent.  And certainly
> if you are trying to write portable code, I would encourage
> you to put in a pragma Volatile on the constant object,
> or define it as a rename of the .all, as illustrated above.

I totally agree it is a 'mad' thing to do - if read-only
variables were a really good thing, the RM would have added
them by now!

I was really just playing about to see if I could mimic
Pascal/D80 read-only variables. It was rather surprised
when the first compiler I tried this with allowed it - I
mean compiled at all - (never mind the second). I was even
more amazed that it actually "worked" on one of the compilers!

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

From: Tucker Taft
Sent: Thursday, April 15, 2004  10:07 AM

> Can't do that:
> "C.6(13), Constant volatile or atomic objects must be imported"
> and a different one again if I try and Import it too.
>
> Neither compiler likes that one.

I'm not sure what you mean.  Did you try:

      Const : constant T;

   private
      Var : aliased T := ...;

      pragma Import(Ada, Const);
      pragma Volatile(Const);
      for Const'Address use Var'Address;

I would think that would be portable and work correctly.

>>An alternative
>>approach is to declare an access-to-constant type and
>>make the variable aliased, and declare the constant
>>as a rename of acc_to_con'(var'access).all.
>>
>>E.g.:
>>
>>    Var : aliased T;
>>    type acc_to_con_T is access constant T;
>>    Const : T renames acc_to_con_T'(Var'Access).all;
>
>
> But Var has to be made public (unless I go into child units)
> which rather defeats the point of the exercise.

I had missed that part.


>>As 3.3(13) says, "the value of a constant object
>>cannot be changed between its initialization and
>>its finalization."  The only place where this
>>requirement is softened is for volatile constant
>>objects, as implied by C.6(22), which is a consequence
>>of C.6(16).
>
>
> Right, so to me that should mean Compiler-2 was just
> *wrong* in giving result:
>
> 100
> 101

Actually I would say *you* were cheating by changing the value of
the constant "behind" its back.  It didn't choose to "remember" the
value of the constant, so instead it went back to memory
to get it, and it had been changed in the interim.

> ...
> I totally agree it is a 'mad' thing to do - if read-only
> variables were a really good thing, the RM would have added
> them by now!

Well parameterless functions are essentially that.

Actually, there is a Ada 200Y proposal for implicit dereference
of functions returning an anonymous access type.  I don't
know whether it will fly, but it provides an efficient
solution to this desire for read-only views of large
variables.  E.g.:

     function Const return access constant T;
     pragma Inline(Const);

   ...

     Var : aliased T;

     function Const return access constant T is
     begin
         return Var'Access;
     end Const;

With the current proposal, "Const" would be implicitly
dereferenced as necessary, and for example could be
passed to operations taking an IN parameter of type T.

By coincidence I had thought of this usage just a day
or two ago, but hadn't yet sent the idea out to the ARG
(the group currently worrying about Ada 200Y).

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

From: Martin Dowie
Sent: Friday, April 16, 2004  4:30 AM


> > Neither compiler likes that one.
> > I'm not sure what you mean.  Did you try:

Seems that placement of the pragmas is important.

>       Const : constant T;
> >    private
>       Var : aliased T := ...;
> >       pragma Import(Ada, Const);
>       pragma Volatile(Const);
>       for Const'Address use Var'Address;
> > I would think that would be portable and work correctly.

Built but didn't work on Compiler-1

Wouldn't compiler on Compiler-2 : 13.1(22), 'Var' would have
to be placed before 'Const', and that isn't the goal.


> Actually I would say *you* were cheating by changing the value of
> the constant "behind" its back.  It didn't choose to "remember" the
> value of the constant, so instead it went back to memory
> to get it, and it had been changed in the interim.

Ok - but I'm not doing anything outside the language. Perhaps
I'd expected too much from the language and/or compilers? I
would have expected that overlaying constants would have been
treated as some sort of special case...



> Well parameterless functions are essentially that.
> Actually, there is a Ada 200Y proposal for implicit dereference
[snip]
> With the current proposal, "Const" would be implicitly
> dereferenced as necessary, and for example could be
> passed to operations taking an IN parameter of type T.
> > By coincidence I had thought of this usage just a day
> or two ago, but hadn't yet sent the idea out to the ARG

Is this AI-318? I had been led to believe that this would
also be useful in returning large arrays efficiently.

What does the call site look like? Can it cope with variable
size arrays begin returned? e.g.

 type T (Size : Natural) is ...;

 function Const (Size : Natural) return const access T;

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


Questions? Ask the ACAA Technical Agent