Version 1.16 of ai12s/ai12-0003-1.txt

Unformatted version of ai12s/ai12-0003-1.txt version 1.16
Other versions for file ai12s/ai12-0003-1.txt

!standard 8.2(11)          15-01-29 AI12-0003-1/09
!standard 13.11.3(1/3)
!standard 13.11.3(3.1/3)
!standard 13.11.3(4/3)
!standard 13.11.3(4.1/3)
!standard 13.11.3(5/3)
!standard 13.11.3(6.2/3)
!standard 13.11.3(6.3/3)
!class binding interpretation 15-01-28
!status Corrigendum 2015 15-01-28
!status ARG Approved 8-0-1 15-01-28
!status work item 11-06-19
!status received 11-03-21
!priority Low
!difficulty Medium
!subject Specifying the standard storage pool
!summary
The standard storage pool can be specified in a Default_Storage_Pool pragma or aspect.
!question
If a programmer wants to specify the default storage pool as NULL through a configuration pragma, then how would one provide a user defined storage pool that does allocate a block of memory from the heap (aka the Standard storage pool as described in 13.11)? (Use storage_pool_indicator Standard.)
!recommendation
Add a new argument to the Default_Storage_Pool pragma to achieve the effect of returning to the "standard" allocation method used by the implementation, usually the use of a general heap.
!wording
Append after 8.2(11) (i.e., as a new paragraph at the end of the static semantics section):
The immediate scope of a pragma which is not used as a configuration pragma is defined to be the region extending from immediately after the pragma to end of the the declarative region immediately enclosing the pragma.
Replace the deleted 13.11.3(1/3):
Redundant[Pragma and aspect Default_Storage_Pool specify the storage pool that will be used in the absence of an explicit specification of a storage pool or size for an access type.]
Modify 13.11.3(3.1/3):
storage_pool_indicator ::= storage_pool_name | null {| Standard}
Add after 13.11.3(4/3):
The Standard storage_pool_indicator is an identifier specific to a pragma (see 2.8) and does not denote any declaration. If the storage_pool_indicator is Standard, then there shall not be a declaration with defining identifier Standard that is immediately visible at the point of the pragma, other than package Standard itself.
AARM Reason: We considering having the Standard storage_pool_indicator
resolve to package Standard rather than being an identifier specific to a pragma. That would eliminate the need for a special check. But it would be bizarre to have something that could resolve to either an object or a (single) package, and resolving to package Standard would imply that the standard pool is an object declared in that package. A storage pool object must be a variable (see 13.11), yet preelaborable packages depend on package Standard, which would require implementers to implement the standard storage pool with Preelaborable_Initialization, which is an unnecessary restriction.
No declaration of Standard can ever be use-visible, as the language-defined non-overloadable definition of Standard will hide any use-visible declarations. Thus we need only concern ourselves with immediately visible declarations with the defining identifier Standard; that eliminates any possible confusion.
End AARM Reason.
Modify 13.11.3 (4.1/3):
If the pragma is used as a configuration pragma, the storage_pool_indicator shall be {either} null {or Standard}, and it defines the default pool to be [null]{that storage_pool_indicator} within all applicable compilation units (see 10.1.5), except within the immediate scope of another pragma Default_Storage_Pool. Otherwise, Redundant[the pragma occurs immediately within a sequence of declarations, and] it defines the default pool within the immediate scope of the pragma to be [either null or the pool denoted by the storage_pool_name]{that storage_pool_indicator}, except within the immediate scope of a later pragma Default_Storage_Pool. Redundant [Thus, an inner pragma overrides an outer one.]
Modify 13.11.3(5/3):
The language-defined aspect Default_Storage_Pool may be specified for a generic instance; it defines the default pool for access types within an instance. {The Default_Storage_Pool aspect may be specified as Standard, which is an identifier specific to an aspect (see 13.1.1) and defines the default pool to be Standard. When the Default_Storage_Pool aspect is specified as Standard, then there shall not be a declaration with defining identifier Standard that is immediately visible at the point of the aspect, other than package Standard itself.
Otherwise, the} [The] expected type for the Default_Storage_Pool aspect is Root_Storage_Pool'Class[. The]{and the} aspect_definition {shall}[must] be a name that denotes a variable. This aspect overrides any Default_Storage_Pool pragma that might apply to the generic unit; if the aspect is not specified, the default pool of the instance is that defined for the generic unit.
Modify 13.11.3(6.2/3):
If the default pool is {neither} [non]null {nor Standard}, the Storage_Pool attribute is that pool.
Modify 13.11.3(6.3/3):
Otherwise {(including when the default pool is specified as Standard)}, [there is no default pool;] the standard storage pool is used for the type as described in 13.11.
<<< AI Note: the wording carefully ties into 13.11, so that it works for instances. >>>>
!discussion
We do not want to give the standard storage pool a name, since it should remain implementation-defined whether, in the absence of user-provided storage pools, the storage pool model is used by the implementation at all.
Specifically it might just go for the heap, or have a clever way of combining a general heap with pools of cached, equally-sized memory blocks.
Extending the Default_Storage_Pool pragma to allow it to cause the implementation to revert to the standard allocation method seemed best to achieve the desired capability.
!corrigendum 8.2(11)
Insert after the paragraph:
The immediate scope of a declaration is also the immediate scope of the entity or view declared by the declaration. Similarly, the scope of a declaration is also the scope of the entity or view declared by the declaration.
the new paragraph:
The immediate scope of a pragma which is not used as a configuration pragma is defined to be the region extending from immediately after the pragma to end of the declarative region immediately enclosing the pragma.
!corrigendum 13.11.3(1/3)
Replace the paragraph:
by:
Pragma and aspect Default_Storage_Pool specify the storage pool that will be used in the absence of an explicit specification of a storage pool or size for an access type.
!corrigendum 13.11.3(3.1/3)
Replace the paragraph:
storage_pool_indicator ::= storage_pool_name | null
by:
storage_pool_indicator ::= storage_pool_name | null | Standard
!corrigendum 13.11.3(4/3)
Insert after the paragraph:
The storage_pool_name shall denote a variable.
the new paragraph:
The Standard storage_pool_indicator is an identifier specific to a pragma (see 2.8) and does not denote any declaration. If the storage_pool_indicator is Standard, then there shall not be a declaration with defining identifier Standard that is immediately visible at the point of the pragma, other than package Standard itself.
!corrigendum 13.11.3(4.1/3)
Replace the paragraph:
If the pragma is used as a configuration pragma, the storage_pool_indicator shall be null, and it defines the default pool to be null within all applicable compilation units (see 10.1.5), except within the immediate scope of another pragma Default_Storage_Pool. Otherwise, the pragma occurs immediately within a sequence of declarations, and it defines the default pool within the immediate scope of the pragma to be either null or the pool denoted by the storage_pool_name, except within the immediate scope of a later pragma Default_Storage_Pool. Thus, an inner pragma overrides an outer one.
by:
If the pragma is used as a configuration pragma, the storage_pool_indicator shall be either null or Standard, and it defines the default pool to be that storage_pool_indicator within all applicable compilation units (see 10.1.5), except within the immediate scope of another pragma Default_Storage_Pool. Otherwise, the pragma occurs immediately within a sequence of declarations, and it defines the default pool within the immediate scope of the pragma to be that storage_pool_indicator, except within the immediate scope of a later pragma Default_Storage_Pool. Thus, an inner pragma overrides an outer one.
!corrigendum 13.11.3(5/3)
Replace the paragraph:
The language-defined aspect Default_Storage_Pool may be specified for a generic instance; it defines the default pool for access types within an instance. The expected type for the Default_Storage_Pool aspect is Root_Storage_Pool'Class. The aspect_definition must be a name that denotes a variable. This aspect overrides any Default_Storage_Pool pragma that might apply to the generic unit; if the aspect is not specified, the default pool of the instance is that defined for the generic unit.
by:
The language-defined aspect Default_Storage_Pool may be specified for a generic instance; it defines the default pool for access types within an instance. The Default_Storage_Pool aspect may be specified as Standard, which is an identifier specific to an aspect (see 13.1.1) and defines the default pool to be Standard. When the Default_Storage_Pool aspect is specified as Standard, then there shall not be a declaration with defining identifier Standard that is immediately visible at the point of the aspect, other than package Standard itself.
Otherwise, the expected type for the Default_Storage_Pool aspect is Root_Storage_Pool'Class and the aspect_definition shall be a name that denotes a variable. This aspect overrides any Default_Storage_Pool pragma that might apply to the generic unit; if the aspect is not specified, the default pool of the instance is that defined for the generic unit.
!corrigendum 13.11.3(6.2/3)
Replace the paragraph:
by:
!corrigendum 13.11.3(6.3/3)
Replace the paragraph:
Otherwise, there is no default pool; the standard storage pool is used for the type as described in 13.11.
by:
Otherwise (including when the default pool is specified as Standard), the standard storage pool is used for the type as described in 13.11.
!ASIS
No ASIS effect. (ASIS doesn't do anything special with pragma arguments.)
!ACATS test
An ACATS C-Test should be constructed to test this capability.
!appendix

From: Brad Moore
Sent: Monday, March 21, 2011  8:22 AM

AI05-0190-1 allows the default storage pool to be specified by a pragma.

To implement an unbounded storage pool type, the first approach that comes to
mind involves deriving a type from Root_Storage_Pool and allocating a block of
memory from the heap and then doling objects from that block of memory.

If a programmer wants to specify the default storage pool as NULL through a
configuration pragma, then how would one provide a user defined storage pool
that does allocate a block of memory from the heap?

Is it the intent that such a configuration pragma enforces only static or stack
based storage pools, and rules out any storage pools that allocate from the
heap? Or does there need to be some implementation defined magic storage pool
that does heap allocation, that can be named? Or should a storage pool object be
exempt from the configuration pragma?

with System.Storage_Pools;
with System.Storage_Elements;

package User_Defined_Pool is
   type My_Pool is new System.Storage_Pools.Root_Storage_Pool with private;
    ...

private

   type Storage_Array_Access is access System.Storage_Elements.Storage_Array;
   for Storage_Array_Access'Storage_Pool use ???;
   -- What heap based storage pool can be used for this if the default is NULL?

   type My_Pool is new System.Storage_Pools.Root_Storage_Pool with
         record
            buffer : Storage_Array_Access;
         end record;

   overriding procedure Initialize (Item : in out My_Pool);

end User_Defined_Pool;

package body User_Defined_Pool is
...

   overriding procedure Initialize (Pool : in out My_Pool) is
   begin
      Pool.Buffer := new Ada.Storage_Elements.Storage_Array (1 .. 1_000_000);
   end Initialize;

end User_Defined_Pool;

Configuration
pragma Default_Storage_Pool (Null);

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

From: Gary Dismukes
Sent: Monday, March 21, 2011  1:37 PM

> Is it the intent that such a configuration pragma enforces only static
> or stack based storage pools, and rules out any storage pools that allocate from the heap?

As I understand it, the intent is that it rules out the use of any default
storage pools.

> Or does there need to be some implementation defined magic storage
> pool that does heap allocation, that can be named?

If you need heap-based allocation in the presence of "null", then yes, I think
you'd need to use an implementation-defined storage pool (such as the global
storage pool that GNAT provides).

> Or should a storage pool object be exempt from the configuration pragma?

Not completely sure what you mean, but if the storage pool object itself needs
to be allocated and managed within a storage pool, then I believe that that
latter storage pool can't be a default storage pool (unless the storage pool
you're talking about is outside the scope of the null).  At least that's how
understand the proposal.

Bob might have some further comments here...

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

From: Bob Duff
Sent: Monday, March 21, 2011  7:35 PM

> If a programmer wants to specify the default storage pool as NULL
> through a configuration pragma, then how would one provide a user
> defined storage pool that does allocate a block of memory from the heap?

Good question!

I have suggested several times that there should be some way to denote "the
default storage pool", or "the global heap", or whatever. Some people (in
particular, Randy and Steve, I think) objected to that, because it's
unimplementable on compilers that by default separate "collections" into
different pools.

But I still don't see why it's unimplementable.  Every implementation has some
sort of global heap, and could return that.  It really doesn't matter if the
implementation wants to use local pools for some types, or whatever.

> Is it the intent that such a configuration pragma enforces only static
> or stack based storage pools, and rules out any storage pools that
> allocate from the heap?

No.  The intent is that you say "null" in a global config pragma, and that you
can then use whatever sort of pools you like for particular access types.  (And
for the new "new" syntax.)

I don't know if this discussion is "too late".  In any case, you can always
interface with VirtualAlloc on windows and mmap or malloc on Unix.  But it would
be nice to have a portable way of saying "I want the most-global pool, the one
that interfaces with the operating system (if there is one)".

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

From: Randy Brukardt
Sent: Monday, March 21, 2011  9:45 PM

...
> I have suggested several times that there should be some way to denote
> "the default storage pool", or "the global heap", or whatever.
> Some people (in particular, Randy and Steve, I think) objected to
> that, because it's unimplementable on compilers that by default
> separate "collections" into different pools.

That's a misunderstanding of my position. I agree that it would be valuable to
have some sort of named default storage pool. But that idea has been discussed
to death and nothing significant about it has changed since it was discussed.
Thus I oppose discussing it again; if the result was any different this time,
that would happen simply because the membership of the ARG has changed and I
don't think that is a good reason for making such a change. In any case, I'd
rather spend the time on topics that have a better chance of success.

The AI in question was AI95-00300-1. I suggest looking at the minutes of the
Vienna meeting (June 2020), the meeting in which that AI was discussed (there is
not much in the AI itself; perhaps the mail on this was stored in AI95-00299-1,
which is related).

Humm: since that was the only meeting at which that AI was considered and that
was the "heat stroke" meeting (at which many decisions proved to be silly,
probably from trying to work in rooms that resembled the interior of a furnace -
outside air temps were 34-36 C during the meeting, and we met in
unair-conditioned rooms), perhaps I can be convinced to reconsider. But we need
a solid proposal (we've never had one). And in any case it is too late for this
go round.

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

From: Jean-Pierre Rosen
Sent: Tuesday, March 22, 2011 12:49 PM

> Humm: since that was the only meeting at which that AI was considered
> and that was the "heat stroke" meeting (at which many decisions proved
> to be silly, probably from trying to work in rooms that resembled the
> interior of a furnace - outside air temps were 34-36 C during the
> meeting, and we met in unair-conditioned rooms), perhaps I can be
> convinced to reconsider. But we need a solid proposal (we've never had
> one). And in any case it is too late for this go round.

Not really. Nothing prevents any implementation from providing such a pool;
therefore, even if it's too late for the standard, deciding how it should be
done could help all implementations of Ada 2012 do the same thing (slightly
tongue-in-cheek about "all implementations of Ada 2012").

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

From: Randy Brukardt
Sent: Tuesday, March 22, 2011  3:57 PM

You're just repeating my point: it is too late for this standard. We could talk
about ideas for the next standard (which might get implemented early), but right
now our only goal should be to finish *this* standard. We still have important
issues to resolve, and spending any significant effort on other issues right now
is counter-productive. (I spent roughly one hour per 30 or so messages of each
e-mail discussion, although of course this value varies wildly.)

This is the same reason that we're not working on ASIS right now.

This isn't going to be a long delay on such discussions; it makes perfect sense
to start thinking of the future once we get past the NB review of the standard
(hopefully in the June/July time-frame). Until then, however, let's keep our
collective nose to the grindstone.

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

From: Bob Duff
Sent: Tuesday, March 22, 2011  4:29 PM

> The AI in question was AI95-00300-1. I suggest looking at the minutes
> of the Vienna meeting (June 2020), the meeting in which that AI was
> discussed (there is not much in the AI itself; perhaps the mail on
> this was stored in AI95-00299-1, which is related).

I'd call that 20/20 foresight.  Do we really have a meeting scheduled for Vienna
in 2020?  And have you really already finished the minutes? Wow!  ;-)

Seriously, it was meeting #16, in June 2002.

I looked at AI95-00300, AI95-00299, and the minutes for both.
300 is addressing a somewhat different issue than what I had in mind.  In any
case, it is seriously flawed in several ways.

Thanks for the historical info, anyway.

> Humm: since that was the only meeting at which that AI was considered
> and that was the "heat stroke" meeting (at which many decisions proved
> to be silly, probably from trying to work in rooms that resembled the
> interior of a furnace - outside air temps were 34-36 C during the
> meeting, and we met in unair-conditioned rooms), perhaps I can be
> convinced to reconsider. But we need a solid proposal (we've never had
> one). And in any case it is too late for this go round.

I don't know if it was heat stroke, but the minutes show that ARG misunderstood
the 300 proposal.  But never mind -- I'm not trying to revive it!

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

From: Tucker Taft
Sent: Saturday, June 25, 2011  6:11 AM

GNAT "standard" storage pools: [excerpt from GNAT documentation]

22.1 Some Useful Memory Pools

The System.Pool_Global package offers the Unbounded_No_Reclaim_Pool storage pool.
Allocations use the standard system call malloc while deallocations use the standard
system call free. No reclamation is performed when the pool goes out of scope. For
performance reasons, the standard default Ada allocators/deallocators do not use any
explicit storage pools but if they did, they could use this storage pool without any
change in behavior. That is why this storage pool is used when the user manages to make
the default implicit allocator explicit as in this example:

    type T1 is access Something;
     -- no Storage pool is defined for T2
    type T2 is access Something_Else;
    for T2'Storage_Pool use T1'Storage_Pool;
    -- the above is equivalent to
    for T2'Storage_Pool use System.Pool_Global.Global_Pool_Object;

The System.Pool_Local package offers the Unbounded_Reclaim_Pool storage pool. The
allocation strategy is similar to Pool_Local's except that the all storage allocated with
this pool is reclaimed when the pool object goes out of scope. This pool provides a
explicit mechanism similar to the implicit one provided by several Ada 83 compilers for
allocations performed through a local access type and whose purpose was to reclaim memory
when exiting the scope of a given local access. As an example, the following program does
not leak memory even though it does not perform explicit deallocation:

with System.Pool_Local;
procedure Pooloc1 is
    procedure Internal is
       type A is access Integer;
       X : System.Pool_Local.Unbounded_Reclaim_Pool;
       for A'Storage_Pool use X;
       v : A;
    begin
       for I in  1 .. 50 loop
          v := new Integer;
       end loop;
    end Internal;
begin
    for I in  1 .. 100 loop
       Internal;
    end loop;
end Pooloc1;

The System.Pool_Size package implements the Stack_Bounded_Pool used when Storage_Size is
specified for an access type. The whole storage for the pool is allocated at once, usually
on the stack at the point where the access type is elaborated. It is automatically
reclaimed when exiting the scope where the access type is defined. This package is not
intended to be used directly by the user and it is implicitly used for each such declaration:

    type T1 is access Something;
    for T1'Storage_Size use 10_000;

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

From: Randy Brukardt
Sent: Saturday, December 1, 2012  3:01 PM

[Commenting on version /02 of this AI.]

<<<<<< Aside 2: This issue of contradictory pragmas surely is not limited to the storage
pool pragmas. 2a) has anybody checked the manual for problems with other pragmas. 2b)
shouldn't this be a general rule on configuration pragmas?  >>>>>

If you're not careful, there will be an action item in your future!! :-) :-)

To actually answer your question, I know that we spent quite a bit of time looking at this
issue for Suppress and Unsuppress. So if some generalish solution is adopted, you'd have
to be careful to ensure that it didn't apply to them (or at the very least, not change
their behavior).

But I'd actually expect this to be something that has to be addressed on a case-by-case basis
(it depends on what the pragmas do as to how conflicts ought to be resolved). Feel free
to prove me wrong, though.

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

From: Bob Duff
Sent: Sunday, December 9, 2012  4:09 PM

AI12-0003-1 -- A pragma Standard_Storage_Pool is introduced.

I hope you all are happily and safely travelling to your destinations,
especially those who, like Randy, may be facing ice&snow.

I'd like to greet you on arrival with an explanation of my point of view about
this "standard storage pool" business. I think I can prove that having a name
for this variable is trivial to implement on all Ada implementations, including
any that might exist in the future. (Proof beyond a reasonable doubt, I mean --
of course I'm not talking about a maths/logic proof.)

If you think my proof is wrong, which is always a possibility I can't deny,
please explain why. You have to point to some step in the proof that you think
is bogus. In the past, I've been frustrated that people seemed not to understand
my proof and/or responded with irrelevant arguments that didn't address the
proof itself.

If you agree with my proof, please say so, even if you don't think it's the way
to go for some other reason.  Please don't JUST state the other reason.

I guess the third possibility is that you don't understand my proof.
Say that, then, and I'll try to clarify.

First, I think terms like "the standard storage pool" and "the global heap" have
been misleading some people. In an implementation that concocts a new storage
pool for each access type (which we wish to remain a valid implementation) there
is no "THE pool" -- there are many. And what about an impl that doesn't really
use storage pools at all by default -- maybe it calls 'malloc' directly? How can
it provide access to THE pool used by default, when there is no such pool?

My answer is that we are NOT trying to provide a name for "THE pool that is used
by default for all access types that don't have a Storage_Pool clause". No. That
is entirely unnecessary, and clearly impossible in some implementations. And
anyway, it's the wrong level of abstraction for language rules. It is important
that we do NOT want to force implementations to change their heap-allocation
strategy in any way. All we want to do is to provide a way to "hook into" that
strategy, explicitly.

We are trying to provide access to SOME pool that is suitable for use in a
Storage_Pool clause, and whose use invokes the implementation's default
allocation behavior. And we want to make that efficient in most cases (namely,
all the cases where the default is already efficient). I claim that the simplest
way to do that is to declare a pool variable somewhere. And I claim that that's
trivial to implement.

Now here's the proof that it's trivial to implement:

Today, I can say:

    type My_Access_Type is access all String;

    The_Standard_Storage_Pool: Root_Storage_Pool'Class
      renames My_Access_Type'Storage_Pool;

I can make The_Standard_Storage_Pool visible throughout my program, and I can
use it in Storage_Pool clauses for any access type I like. And make it the
default pool, program-wide or more locally.

If I can do that, then an Ada implementation can do it, too. And if the
implementation does it, it can know what Tag is My_Access_Type'Storage_Pool'Tag,
so it can declare The_Standard_Storage_Pool to be of a specific type, so no
dispatching is involved in allocation, and the [De]Allocate procedures can be
inlined.

An implementation that doesn't "really" use pools by default can special case
The_Standard_Storage_Pool. It can trivially recognize "for T'Storage_Pool use
The_Standard_Storage_Pool;" and just use its default mechanisms. (This only
makes sense if the default mechanisms are more efficient.) Note that it doesn't
matter at all what those default mechanisms are. That's why I can prove my
assertion even for implementations I have never seen! The default mechanisms
could involve direct calls to 'malloc', or separate pools for each access type,
or separate <non-pool gizmos> for each type, or...

In other words, an implementation can easily pretend to be using pools even if
it isn't under the hood.

Furthermore, implementations already have to support the 'Storage_Pool query. If
they can do that, they can trivially provide a name for whatever pool is
returned by one particular such query.

It is true that if we have The_Standard_Storage_Pool, users could pass it off to
someplace that doesn't know it's the standard one -- all it knows is
Root_Storage_Pool'Class. In that case, dispatching calls are needed, and the
supposedly-more-efficient default mechanisms can't be used. But so what? That's
already the case if the user does the exact same thing with
My_Access_Type'Storage_Pool.

Q.E.D.  Actually, since it's not a maths/logic proof, I should instead say "I
rest my case."  ;-)

The astute reader will have noticed that the same proof can be used to prove
that we don't really *need* this feature. The user already has a way to get at
some global pool that uses the default mechanisms, although possibly with some
run-time overhead. The_Standard_Storage_Pool as declared by the user is
class-wide. A clever compiler can know the Tag, and therefore avoid dispatching,
and allow inlining.

I can certainly live without this feature, but if we have it, I am convinced
that the best way to provide it is to declare the standard storage pool as a
variable somewhere in the predefined environment, of some impl-def pool type.
That's much simpler than providing a whole new Standard_Storage_Pool pragma. I
am opposed to adding a new pragma when it's not necessary (although I admit the
new pragma isn't particularly complicated -- it's just different, and
unnecessary).

I note again: We neither need nor want any sort of requirement that this global
pool variable actually be *used* by default -- if you look under the hood, you
might well find something entirely different going on.  Remember the "as if"
meta-rule!

During the meeting, someone asked where should this variable be declared.  If
that was meant as an honest question, then the answer is, "I don't know, and I
don't care." It's just like any other new feature added to the predefined
environment: we'll pick some existing package, or invent a new package, possibly
a child of System.Storage_Pools. OTOH, if that question was meant as a
challenge, along the lines of "If you don't know where to put it, then that's an
argument against having it", then I reject that argument as bogus. I'm quite
sure any one of us, including me, can figure out a reasonable package to put it
in.

We also need to decide on the name of the variable. I think
Standard_Storage_Pool is just fine. The only people it was confusing were
implementers, or people worrying about implementation issues. For users, it
makes perfect sense.

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

From: Robert Dewar
Sent: Sunday, December 9, 2012  5:08 PM

> AI12-0003-1 -- A pragma Standard_Storage_Pool is introduced.

The implementation difficulty in GNAT with any standard storage pool approach
has always been the issue of consistency between separate compilations. SO
whatever design is chosen needs to bear this in mind if it wants to get
implemented.

There are enough people on the ARG familiar with the GNAT implementation model
to properly consider this important point, so no need to give more technical
detail here :-)

> I can make The_Standard_Storage_Pool visible throughout my program,
> and I can use it in Storage_Pool clauses for any access type I like.
> And make it the default pool, program-wide or more locally.

> If I can do that, then an Ada implementation can do it, too.
> And if the implementation does it, it can know what Tag is
> My_Access_Type'Storage_Pool'Tag, so it can declare
> The_Standard_Storage_Pool to be of a specific type, so no dispatching
> is involved in allocation, and the [De]Allocate procedures can be inlined.

I don't think this really properly takes the consistency problem into account!

> The astute reader will have noticed that the same proof can be used to
> prove that we don't really *need* this feature. The user already has a
> way to get at some global pool that uses the default mechanisms,
> although possibly with some run-time overhead.
> The_Standard_Storage_Pool as declared by the user is class-wide. A
> clever compiler can know the Tag, and therefore avoid dispatching, and allow inlining.

Well I thought the real need was to take an existing program and change the
default storage pool that was used WITHOUT having to decorate access types
throughout the program

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

From: Bob Duff
Sent: Sunday, December 9, 2012  5:43 PM

> Well I thought the real need was to take an existing program and
> change the default storage pool that was used WITHOUT having to
> decorate access types throughout the program

That capability already exists in Ada 2012 -- see pragma Default_Storage_Pool,
which can be used as a config pragma, or more locally.  AFAIK, GNAT correctly
implements it.

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

From: Robert Dewar
Sent: Sunday, December 9, 2012  5:59 PM

I don't think so actually, since the consistency problem is not properly
addressed, I think it would not be that hard to add, but I am pretty sure it is
not done right now!

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

From: Tucker Taft
Sent: Sunday, December 9, 2012  10:04 PM

I agree that it is straightforward to create a "pseudo" storage pool which when
specified as the storage pool for an access type, has the effect of it using the
"normal" storage allocation and deallocation mechanisms.

I might suggest making it a special attribute rather than a special object,
e.g.:

    for Acc_Type'Storage_Pool use System.Storage_Pools'Standard; or
    for Acc_Type'Storage_Pool use Standard'Storage_Pool;

This would make its "magicness" quite apparent.

And the standard storage pool could be specified using the Default_Storage_Pool
pragma, perhaps as follows:

    pragma Default_Storage_Pool(Standard'Storage_Pool);

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

From: Randy Brukardt
Sent: Monday, December 10, 2012  12:53 AM

> I hope you all are happily and safely travelling to your destinations,
> especially those who, like Randy, may be facing ice&snow.

Temps were just above freezing in Detroit and here in Madison, although my car
had a couple inches of melting snow on it. No ice through, and the only problem
was that they put my luggage on the earlier flight so it arrived in Madison 90
minutes before I did. (So it didn't come out with the other luggage - it turned
out to be in the luggage office.)

...
> If you think my proof is wrong, which is always a possibility I can't
> deny, please explain why. You have to point to some step in the proof
> that you think is bogus.

It's not completely bogus, but... ;-)
...
> Now here's the proof that it's trivial to implement:
>
> Today, I can say:
>
>     type My_Access_Type is access all String;
>
>     The_Standard_Storage_Pool: Root_Storage_Pool'Class
>       renames My_Access_Type'Storage_Pool;
>
> I can make The_Standard_Storage_Pool visible throughout my program,
> and I can use it in Storage_Pool clauses for any access type I like.
> And make it the default pool, program-wide or more locally.

Here's the problem.

You can do that, but there is no guarantee that it would work. (That is, the
pool might raise an exception if you attempt to allocate some other type with
it.) It seems *likely* that it would work, but I don't think we should be
designing the language based on likelihoods.

(Aside: If you are going to do this, I'd probably suggest writing the array in
terms of storage elements rather than characters. They're not the same on some
machines, and that could matter.)

Specifically, we know that the language allows building different "standard"
pools for different kinds of types. And for such an implementation, any specific
pool is only guaranteed to work on the same sort of type. I presume (please
correct me if I am wrong) that the reason you chose this particular type is that
you can cause an allocation of essentially any size for this type. Thus one
might conclude that the pool would have to work for any type.

But that's not necessarily true. For Janus/Ada, at least, an unconstrained array
type is allocated in two parts, a fixed size descriptor (the same for any value
of the type) and an data area whose size depends upon the bounds. One could
easily imagine a pool that puts those two different parts into different parts
of memory because the different usage characteristics. Such a pool would raise
an exception if the initial allocation wasn't for a descriptor. This isn't
purely a thought experiment: I actually wrote such a pool for Windows 98, as the
heap for a number of Windows versions had a relatively small maximum size; to be
able to use all of the memory in the system, I had to manage the virtual memory
for the data areas manually (this is not needed on modern Windows). The pool
failed any calls to Allocate that were not clearly part of an array allocate. I
never used it as the standard pool -- but surely the possibility exists (and
needs to exist, IMHO, because it's hard to guess the requirements needed for
kernels, nor the requirements of future users).

> If I can do that, then an Ada implementation can do it, too.

Probably 98% of the time this is true, but not 100%, as described above.

> An implementation that doesn't "really" use pools by default can
> special case The_Standard_Storage_Pool. It can trivially recognize
> "for T'Storage_Pool use The_Standard_Storage_Pool;"
> and just use its default mechanisms. (This only makes sense if the
> default mechanisms are more efficient.)

I don't think that most implementations would actually do this - it's a lot of
extra work and it isn't absolutely necessary. Most of the Ada implementers (not
counting AdaCore) don't have large staffs and we tend to do just enough to get
by until/unless an actual customer cares a lot. This is not a case where
implementing the better mechanism is going to be *required* to get this to work.
(OTOH, I doubt much that the better mechanism would provide enough added
performance to be noticeable in most cases. The main advantage of such pools is
to reduce or eliminate fragmentation, which isn't going to be visible to most
customers.)

Anyway, this is probably irrelevant to your argument, which is in any case built
on a foundation of sand (see above).

...
> In other words, an implementation can easily pretend to be using pools
> even if it isn't under the hood.

I don't agree that it is "easy"; it's easier than dynamic accessibility checking
:-) but hardly trivial.

...
> The astute reader will have noticed that the same proof can be used to
> prove that we don't really *need* this feature.
> The user already has a way to get at some global pool that uses the
> default mechanisms, although possibly with some run-time overhead.
> The_Standard_Storage_Pool as declared by the user is class-wide. A
> clever compiler can know the Tag, and therefore avoid dispatching, and
> allow inlining.

And that's also not true, in the sense that it's impossible for the user to know
what type that they can declare which will guarantee them a globally useful
pool. Certainly, I've shown that an unconstrained array isn't *always* going to
be such a type. (For Janus/Ada, it doesn't matter ("new" is just a single pool),
but I would not want to constrain implementations as much as you are willing
to.)

> I can certainly live without this feature, but if we have it, I am
> convinced that the best way to provide it is to declare the standard
> storage pool as a variable somewhere in the predefined environment, of
> some impl-def pool type. That's much simpler than providing a whole
> new Standard_Storage_Pool pragma. I am opposed to adding a new pragma
> when it's not necessary (although I admit the new pragma isn't
> particularly complicated -- it's just different, and unnecessary).

I would rather have added a special parameter to the existing
Default_Storage_Pool pragma, as the entire point is to turn off the effect of
that pragma and return to the default. For that purpose, using a specially named
pool seems misleading (because using that pool is *not* what you want to do).
But we couldn't find a decent name for such a parameter, so we decided to define
another pragma instead.

...
> During the meeting, someone asked where should this variable be
> declared.  If that was meant as an honest question, then the answer
> is, "I don't know, and I don't care."

Which is not a helpful answer. We do need to know, because we are going to be
comparing the "weight" of the various proposed solutions. Adding a new subclause
(to define a new package), is certainly going to be "heavier" than just adding a
new pragma (or argument) to an existing clause. If, of course, you can find a
reasonable *existing* place to put it, the "weight" is less.

...
> We also need to decide on the name of the variable. I think
> Standard_Storage_Pool is just fine. The only people it was confusing
> were implementers, or people worrying about implementation issues. For
> users, it makes perfect sense.

Other than it doesn't exist. :-) We'd need to rewrite the 13.11 section to use
the term "standard storage pool" in order to call it that where you define it.
(This is not a big rewrite, probably just a few sentences, but for someone
complaining about unnecessary wording changes, I'm surprised that you are
insisting on one...)

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

From: Jean-Pierre Rosen
Sent: Monday, December 10, 2012  3:13 AM

> I agree that it is straightforward to create a "pseudo" storage pool
> which when specified as the storage pool for an access type, has the
> effect of it using the "normal" storage allocation and deallocation
> mechanisms.
> [...]
>    pragma Default_Storage_Pool(Standard'Storage_Pool);
>

OK, Bob "demonstrated" that it is possible to have a pseudo-storage pool, whose
meaning can be interpreted as "this is not a real storage pool, it implies just
use the standard allocation mechanism".

No kidding! If we want the standard allocation mechanism, which might not use a
storage pool with the conventional meaning, by all means, let's tell it!

I fail to see what the problem is with a new pragma. One more paragraph?
Certainly not more effort than the definition of the attribute that Tuck
proposes (including all the hand-waiving that this storage pool needs not be a
"real" storage pool). And the pragma simply tells the truth!

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

From: Erhard Ploedereder
Sent: Sunday, December 9, 2012  8:51 AM

I agree with the proof. In the matter, I do not feel strongly one way or the
other. In favor of the name approach is that the name can also be used in an
aspect specification.

I was very serious in asking where such a declaration would reside.

Note the user convenience aspect between:

pragma Standard_Storage_Pool;

and

pragma Default_Storage_Pool(System.Storage_Pools.Standard.Standard_Storage_Pool);

(sorry, my mailer automatically wraps long lines. Really. :-) ) This is just
plain ugly keyboard training for programmers. Or, maybe, an Ada API spelling
bee. ("Is is Standard.Storage_Pool, or Pools, or ...?")

The alternative of making a syntactic rule that would magically allow pragma
Default_Storage_Pool(Standard_Storage_Pool); I would find disgusting, even if
already present on some pragmas. It would complicate the RM writeup. And, it
would not help with aspect specifications.

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

From: Bob Duff
Sent: Sunday, December 9, 2012  4:40 PM

Here's the other issue I'd like clarify:

While working on AI12-0003-1, Erhard discovered a bug. In particular, the
wording for Default_Storage_Pool refers to "immediate scope of a pragma", which
is a concept that is not explicitly defined in the RM.

I voted against giving Erhard and Steve action items to fix this bug (Steve is
supposed to figure out how to define the term, and Erhard is supposed to figure
out how to use some other term involving "regions" or something).

In my opinion:

    - We do NOT need to fix every known bug in the RM.

    - We SHOULD fix some bugs, but we should NOT fix some others.
      We can decide on a case-by-case basis.

    - This particular bug is not worth fixing.

I realize (given the vote) that all the rest of ARG disagrees with me at least
on the last point.  I accept that, and I'm not trying to convince anyone -- just
explaining my position.

Randy seemed to interpret my words as "we should never fix RM bugs", and was
therefore shocked and appalled.  Well, I didn't say that, and I didn't mean to
imply it.

Note that the bug in question is not directly related to AI12-0003. If we fix
it, it should be under a different AI.

I don't remember for sure, but I think I put this bug in deliberately. That is,
I figured "immediate scope" is well defined for declarations, and it's pretty
obvious what it should mean for pragmas that are declarative_items, and it's
just being pedantic to fiddle with the wording in chap 8 just for this little
pragma.

I expect we will continue to find bugs in the RM, and we will continue to fix
them, and I will continue to vote against fixing them when I think it's a waste
of time and/or not worth the risk.  I don't think that should anger anyone --
it's just a difference of opinion.

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

From: Erhard Ploedereder
Sent: Tuesday, December 11, 2012  6:44 PM

> Note that the bug in question is not directly related to AI12-0003. If
> we fix it, it should be under a different AI.

Indeed.

> I don't remember for sure, but I think I put this bug in deliberately.

Shame on you ;-)

> That is, I figured "immediate scope" is well defined for declarations,
> and it's pretty obvious what it should mean for pragmas that are
> declarative_items, and it's just being pedantic to fiddle with the
> wording in chap 8 just for this little pragma.

I actually find this notion more understandable (and more commonly used) than
the "applies to a region" concept followed in the Suppress and Assertion_Policy
pragmas. I can't help but wonder whether there are subtle differences. So I
don't mind digging into this for my enlightenment.

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

From: Erhard Ploedereder
Sent: Sunday, June  9, 2013  5:48 PM

Attached is the revised version incorporating the decisions of the last meeting
and Steve's words about immediate scopes of pragmas, which Randy had already
put into the AI. [This is version /04 of the AI - Editor.]

As charged, I investigated the use of the region concept, but gladly left it
behind after Steve's simple addition, since the immediate scope notion is
vastly preferable, anyway.

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

From: Brad Moore
Sent: Saturday, January 17, 2015  1:29 PM

I'm looking at my homework relating to specifying the default storage pool,
and have a question.

At the last ARG meeting, Tucker provided some guidance and suggested that it
be illegal if (without any context) (Standard) denotes anything other than
package Standard."

This is to deal with the situation where someone specifies the default storage
pool as "Standard" which is an identifier specific to the pragma, when there
is another declaration that is directly visible having the same name.

My original approach would be to disallow any such name conflict, but I think
that may be too draconian.

eg.

    type Foo is interface;
    function Standard (Item : Foo) return Integer;

    pragma Default_Storage_Pool (Standard);  -- Legal?
    type Foo_Access is access Foo;

I think it's clear here that the Standard in the pragma is not referring to
the Standard function.

I'm thinking that it would be better to define legality such that only
conflicts with other directly visible storage pool declaration names are
disallowed.

Specifically, it would be illegal to specify the Default_Storage_Pool pragma
as Standard, if there is a directly visible storage pool declaration with the
name "Standard".

Alternatively, we could simply disallow declaring storage pools that have the
name "Standard", but that would introduce a minor backwards incompatibility.
It seems pretty minor and quite unlikely to occur in practice, but perhaps
such an incompatibility should be eliminated if there is another solution
such as what I initially proposed, that doesnt have this incompatibility.

Thoughts?

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

From: Randy Brukardt
Sent: Saturday, January 17, 2015  6:28 PM

I think this is a non-problem. I'd be happy with no check at all, but if we
have to have one, I think it should be as simple as possible.

That's mainly because "Standard" is one of those identifiers in Ada that
aren't reserved, but should be treated as if they are. You don't want to be
declaring things named "Standard" anymore than you want to declare things
named "Integer" or "Character". You *can* do that, but it's an invitation to
confusion.

So I don't really care if the check picks up things that aren't really going
to be confused. Because they're not likely to exist anyway.

Indeed, I'd probably implement this check as "if there is more than one
definition of Standard in the current symboltable, reject the pragma". That
is, I wouldn't pay any attention to visibility or what's being declared.
Most likely, that would pick up a few cases that aren't a problem, but (A)
there probably isn't going to be an ACATS test that could tell the difference;
and (B) this will never happen in practice.

In the amazingly unlikely event that that simple check causes a problem for
someone, I'd upgrade it to using identifier lookup (which does use visibility);
then "if there is more than one visible Standard, reject the pragma". This is
still rather simple, as no resolution is needed.

Your check would require bringing the entire machinery of resolution into the
picture (after all, "Standard" could be an object, but it also could be a
parameterless function call). That seems like swatting a fly with a bazooka.

To summarize, I'd prefer to stick with the original idea -- the simpler the
check, the better.

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

From: Brad Moore
Sent: Sunday, January 18, 2015 11:10 AM

OK, will do.

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

From: Brad Moore
Sent: Friday, January 23, 2015 12:26 AM

Here is my homework. [This is version /06 of the AI - ED]

The quick summary of the change is that one is not allowed to use the name
Standard in a compilation unit if it refers to something other than the package
Standard, when a Default_Storage_Pool aspect or pragma within that same
compilation unit has the default pool specified as Standard.

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

From: Randy Brukardt
Sent: Friday, January 23, 2015  4:57 PM

Humm.

Here's the actual proposed rule:

   A direct_name shall not be a homograph of the package Standard that denotes a
   declaration other than package Standard when declared within a compilation
   unit for which the Standard default pool applies.

   AARM Reason: Any use of an identifier with the name Standard resprensenting
   anything other than the package Standard would be confusing in a compilation
   unit with Standard specified as the default storage pool. Such a choice for
   an identifier is not recommended and very unlikely to occur, so a simple rule
   was chosen to prevent such confusion.

Two problems with this. First, it's incompatible because the Standard storage
pool applies by default. So this would be enforced everywhere except where there
is an explicit pragma Default_Storage_Pool. I think you only wanted it to apply
in the scope of a pragma Default_Storage_Pool.

Second, this seems backwards to me. We're concerned (OK, I'm not, but I'm going
along with the majority opinion here :-) about entities with the name Standard
that are visible at the point of a pragma Default_Storage_Pool.

That is,
   function Standard ...

   pragma Default_Storage_Pool (Standard);

That wouldn't be detected by this rule if the function is in another compilation
unit (and it seems to require retroactive enforcement within a single unit).

I would have tried something much more direct:

   If the storage_pool_indicator for a pragma or aspect Default_Storage_Pool is
   Standard, then the pragma or aspect_specification is illegal if there is any
   declaration with the direct_name Standard (other than the package Standard)
   that is visible (directly visible??) at the point of the pragma or
   aspect_specification.

   AARM Reason: Any use of an identifier with the name Standard representing
   anything other than the package Standard could be confused with the
   identifier-specific-to-a-pragma Standard specified as the default storage
   pool. Such a choice for an identifier is not recommended and very unlikely to
   occur, so a simple rule was chosen to prevent such confusion.

This probably needs some wordsmithing.

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

From: Randy Brukardt
Sent: Friday, January 23, 2015  5:07 PM

I didn't make the problem we're trying to solve very clear in my previous note.
Let me try again.

Better description:
   function Standard ...

   pragma Default_Storage_Pool (Standard); -- (1) Meaning of Standard here?

In particular, is "Standard" in (1) a call to the function Standard, or the
identifier-specific-to-a-pragma Standard?

This problem doesn't depend on where the other entity named Standard is
declared, just that it is visible (and thus is declared before the pragma).

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

From: Bob Duff
Sent: Friday, January 23, 2015  6:06 PM

>    A direct_name shall not be a homograph of the package Standard that

A direct_name cannot be a homograph.  Only declarations can.
Maybe "be" --> "denote" was intended?

I basically agree with Randy's points here, but it occurs to me that this is another example where a "soft legality" rule (or whatever we call it) would be appropriate.  We could say it is softly-illegal to declare anything anywhere called Standard.  No co
mpatibility issues (that's the whole point of soft legality), and any possible confusion gets a diagnostic message.

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

From: Tucker Taft
Sent: Friday, January 23, 2015  10:25 PM

>     ... If the storage_pool_indicator for a pragma or aspect
> Default_Storage_Pool is Standard, then the pragma or
> aspect_specification is illegal if there is any declaration with the
> direct_name Standard (other than the package
> Standard) that is visible (directly visible??) at the point of the
> pragma or aspect_specification. ...

You don't want to say merely "visible."  You definitely want to say "directly
visible." There is no problem if there is some sub-sub-package somewhere that
has a declaration with Standard as its defining identifier, unless you are in
the scope of a use clause for that sub-sub-package.

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

From: Brad Moore
Sent: Saturday, January 24, 2015  12:50 AM

> Here's the actual proposed rule:
>
>     A direct_name shall not be a homograph of the package Standard
> that denotes a
>     declaration other than package Standard when declared within a
> compilation
>     unit for which the Standard default pool applies.
>
>     AARM Reason: Any use of an identifier with the name Standard
> resprensenting
>     anything other than the package Standard would be confusing in a
> compilation
>     unit with Standard specified as the default storage pool. Such a
> choice for
>     an identifier is not recommended and very unlikely to occur, so a
> simple rule
>     was chosen to prevent such confusion.
>
> Two problems with this. First, it's incompatible because the Standard
> storage pool applies by default. So this would be enforced everywhere
> except where there is an explicit pragma Default_Storage_Pool. I think
> you only wanted it to apply in the scope of a pragma Default_Storage_Pool.

I was and still am thinking this wouldn't be incompatible because as mentioned
in 13.11.3 (6.3/3) and modified by this AI, if the "default pool" is not
specified (null, Standard, or some storage pool, then there is no default pool.
So, this effect only occurs if the default storage pool was explicitly specified
to be Standard. Or at least that is the impression I got from reading 13.11.3
(6.3/3), and that was what I was attempting to leverage to avoid compatibility
issues.

   {AI05-0190-1} [Otherwise, there is no default pool; ...]

>
> Second, this seems backwards to me. We're concerned (OK, I'm not, but
> I'm going along with the majority opinion here :-) about entities with
> the name Standard that are visible at the point of a pragma Default_Storage_Pool.
>
> That is,
>     function Standard ...
>
>     pragma Default_Storage_Pool (Standard);
>
> That wouldn't be detected by this rule if the function is in another
> compilation unit (and it seems to require retroactive enforcement
> within a single unit).

I also considered this, but if it is in another compilation unit, it would not
be directly visible, unless there was a use clause that made it directly
visible. Without a use clause, one would have to reference it with a prefix. For
that case, it is not likely to be confused with the use of Standard in the
pragma or aspect. I think the case where a use clause makes such a declaration
visible from some other package is even more remote of a possibility, and less
likely to be confusing, than the case above where a function Standard is not
only directly visible to the compiler, but also directly visible to the reader
of the source code.

>
> I would have tried something much more direct:
>
>     If the storage_pool_indicator for a pragma or aspect
> Default_Storage_Pool is Standard, then the pragma or
> aspect_specification is illegal if there is any declaration with the
> direct_name Standard (other than the package
> Standard) that is visible (directly visible??) at the point of the
> pragma or aspect_specification.

I actually started off with something like this. I was using directly visible in
my initial wording, but I later changed after receiving your email, because of
your comment that said you'd rather not bring in visibility rules.

i.e.
 > Indeed, I'd probably implement this check as "if there is more than  > one
 definition of Standard in the current symboltable, reject the  > pragma". That
 is, I wouldn't pay any attention to visibility or  > what's being declared.

I also didn't use wording that involved storage_pool_indicator, because the RM
wording suggested to me that storage_pool_indicator only applied to the pragma
and not the aspect. The aspect only talks about the values that the aspect can
have, but otherwise doesn't mention storage_pool_indicator. Also, I believe the
aspect cannot have the value null, which is another reason I avoided
storage_pool_indicator. However, the wording does talk about "default pool"
which is defined in 13.11.3 (4.1/3). And the wording for the aspect and for the
pragma both use this term, so I thought it best to use wording based on that
definition, rather than the syntax element, storage_pool_indicator.

I'd be OK with using visibility rules similar to the wording you have above, but
note that the rule above wouldn't flag;

      pragma Default_Storage_Pool (Standard);
      function Standard ...

because the function Standard isn't visible to the pragma, whereas the rule I
had would flag this. Though I do not have any big concerns about this case.

I'm still thinking I'd probably not use Storage_Pool_Indicator though....

So. I'm not clear which is the better approach. Whether to use visibility rules
or something similar to what I had. I am willing to take another stab at the
wording, but would like some guidance, after considering the above comments.

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

From: Brad Moore
Sent: Saturday, January 24, 2015  12:59 AM

>>     A direct_name shall not be a homograph of the package Standard
>> that
>
> A direct_name cannot be a homograph.  Only declarations can.
> Maybe "be" --> "denote" was intended?

Yes, I agree that better captures the intent.


>
> I basically agree with Randy's points here, but it occurs to me that
> this is another example where a "soft legality" rule (or whatever we
> call it) would be appropriate.  We could say it is softly-illegal to
> declare anything anywhere called Standard.  No compatibility issues
> (that's the whole point of soft legality), and any possible confusion
> gets a diagnostic message.

I agree with this, though I believe soft legality rules would be a feature that
would not be appropriate for the corrigenda, whereas this AI is something that
is being considered for the corrigenda. So perhaps it makes sense to apply a fix
similar to the proposal for now, and then consider relaxing the rules for this
and other such cases when and if soft legality rules make it into Ada 202x.

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

From: Robert Dewar
Sent: Saturday, January 24, 2015  5:27 AM

> I agree with this, though I believe soft legality rules would be a
> feature that would not be appropriate for the corrigenda, whereas this
> AI is something that is being considered for the corrigenda. So
> perhaps it makes sense to apply a fix similar to the proposal for now,
> and then consider relaxing the rules for this and other such cases
> when and if soft legality rules make it into Ada 202x.

For the corrigenda you could just have implementation advice saying the compiler
should issue a warning msg in this case (in IA sections you can talk about
warning messages).

If you make it illegal now, you  limit your possibilities for the future

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

From: Bob Duff
Sent: Saturday, January 24, 2015  6:15 AM

> I agree with this, though I believe soft legality rules would be a
> feature that would not be appropriate for the corrigenda, ...

I think we should use the "soft legality" concept starting in 1995.  ;-) I'm
puzzled why it's so controversial, and I don't know why it would be
inappropriate for the corrigenda.

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

From: Brad Moore
Sent: Saturday, January 24, 2015  7:50 AM

Actually, it appears we've already had them since Ada 83.

See RM 2.8 (13) "The implementation shall give a warning message for an
unrecognized pragma name."

I'm open to considering soft legality for the corrigenda. I just presumed it
wasn't a possibility because ai12-0092-1 was not mentioned as being a potential
corrigenda item in Randy's meeting agenda. Given that we already have soft
legality rules, maybe the ai12-0092-1 is not even needed.

You could think of this as a "required warning", if it appears as a
implementation requirement. If it just appears as implementation advice, then it
is a "recommended warning".

For example, if we wanted the rule I suggested to be a required warning, what
would stop us from using the following wording?

"The implementation shall give a warning message if a direct_name exists that
{blah blah blah}"

If we only wanted this to be implementation advice, we could do as Robert
suggested in the previous email.

In this particular case, I think implementation advice seems like it would be
more appropriate. The check doesn't affect portability, it just points out to
the user that his code might be confusing to other readers. That way, a compiler
vendor that didn't want to implement the check could choose not to.

[Most of the further mail in this thread is filed in AI12-0092-1, since it has
to do with "suppressible errors" or "soft errors" or whatever one calls them.
I've only filed mail here that is actually related to this pragma and/or aspect.
- Editor.]

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

From: Randy Brukardt
Sent: Saturday, January 24, 2015  4:58 PM

I think this discussion has completely jumped the shark.

The problem we're considering is the confusion that might be caused if some
happens to have something named "Standard" when the pragma uses "Standard" as a
name.

But the real issue here is that someone declared something named "Standard". Any
time a programmer uses a name that already has a well-defined Ada meaning for
some other purpose (more specifically, the name of any language-defined
non-overloadable entity), the programmer is asking for confusion. Not just with
this pragma, but potentially anywhere.

If I write
   Boolean : Integer;
I'm not expecting the compiler to give me a warning about confusion when I later
use the name Boolean somewhere.

Why this case requires any special attention is beyond me. I've been against any
check anywhere since this issue was originally brought up. If *anything*
deserves a warning, it's the use of Standard as the name of an entity. But we've
tolerated that for approximately 1 zillion years. I doubt enough has changed
about that.

I can see having a check associated with the pragma (it's new, after all, so
there is no compatibility issue), but I don't see it as necessary. But if we're
not going to have a required check, then we should say nothing at all
(implementations can have a warning if they like, but there's no reason
whatsoever for the Standard to talk about that). This case is highly unlikely
(and, as Brad noted, most of the time, the conflict would be harmless as
Standard would not be a storage pool); it's simply not worth the energy that's
already been put to it.

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

From: Randy Brukardt
Sent: Saturday, January 24, 2015  5:19 PM

...
> > Two problems with this. First, it's incompatible because the
> > Standard storage pool applies by default. So this would be enforced
> > everywhere except where there is an explicit pragma
> > Default_Storage_Pool. I think you only wanted it to apply in the
> > scope of a pragma Default_Storage_Pool.
>
> I was and still am thinking this wouldn't be incompatible because as
> mentioned in 13.11.3 (6.3/3) and modified by this AI, if the "default
> pool" is not specified (null, Standard, or some storage pool, then
> there is no default pool. So, this effect only occurs if the default
> storage pool was explicitly specified to be Standard. Or at least that
> is the impression I got from reading 13.11.3 (6.3/3), and that was
> what I was attempting to leverage to avoid compatibility issues.

If the name Standard is used, one hopes that 13.11.3(6.3/3) applies. We don't
want subtly different semantics for
    pragma Default_Storage_Pool (Standard);
and no pragma (assuming there are no other pragma Default_Storage_Pools that
apply).

In particular, the sentence you added after 13.11.3(6.1/3) is unnecessary (and
incorrect, as the reference to 13.11 in 6.3/3 is critical).

I'd just have added a parenthetical remark to 13.11.3(6.3/3) (and remove the
"redundant" brackets):

   Otherwise {(including when the default pool is specified as Standard)}, there
   is no default pool; the standard storage pool is used for the type as
   described in 13.11.

Humm, that reads funny. Probably drop the part about there being no default
pool, it doesn't have any semantics:

   Otherwise {(including when the default pool is specified as Standard)}[,
   there is no default pool;] the standard storage pool is used for the type as
   described in 13.11.

I'd have to look at the rest of the wording to be sure that works properly.

I hadn't noticed that before.

(If starting from scratch, I would have said that the default default storage
pool is "Standard", and 13.11 would talk about the default storage pool
directly. But too much change now.)

> > Second, this seems backwards to me. We're concerned (OK, I'm not,
> > but I'm going along with the majority opinion here :-) about
> > entities with the name Standard that are visible at the point of a
> > pragma Default_Storage_Pool.
> >
> > That is,
> >     function Standard ...
> >
> >     pragma Default_Storage_Pool (Standard);
> >
> > That wouldn't be detected by this rule if the function is in another
> > compilation unit (and it seems to require retroactive enforcement
> > within a single unit).
>
> I also considered this, but if it is in another compilation unit, it
> would not be directly visible, unless there was a use clause that made
> it directly visible. Without a use clause, one would have to reference
> it with a prefix. For that case, it is not likely to be confused with
> the use of Standard in the pragma or aspect. I think the case where a
> use clause makes such a declaration visible from some other package is
> even more remote of a possibility, and less likely to be confusing,
> than the case above where a function Standard is not only directly
> visible to the compiler, but also directly visible to the reader of
> the source code.

The use clause case is *far* more likely than having a name in the same scope.
Especially for those that aren't use-adverse. (Those of us that are use-adverse
tend to forget that at times.)

I don't think *any* of these cases are confusing, but that's just me. :-)

> > I would have tried something much more direct:
> >
> >     If the storage_pool_indicator for a pragma or aspect
> > Default_Storage_Pool is Standard, then the pragma or
> > aspect_specification is illegal if there is any declaration with the
> > direct_name Standard (other than the package
> > Standard) that is visible (directly visible??) at the point of the
> > pragma or aspect_specification.
>
> I actually started off with something like this. I was using directly
> visible in my initial wording, but I later changed after receiving
> your email, because of your comment that said you'd rather not bring
> in visibility rules.
>
> i.e.
>  > Indeed, I'd probably implement this check as "if there is more than
> > one definition of Standard in the current symboltable, reject the  >
> pragma". That is, I wouldn't pay any attention to visibility or  >
> what's being declared.

You misunderstood my point. I think this check is so unimportant that I won't
spend a moment implementing the rule as written, just implementing enough to
pass the (presumably simple) ACATS test. I followed that statement by saying
that if someone complained, I'd then use visibility as well, but not resolution.

The actual rule has to include visiblility, else there are ripple effects.
(More on that later.)

> I also didn't use wording that involved storage_pool_indicator,
> because the RM wording suggested to me that storage_pool_indicator
> only applied to the pragma and not the aspect. The aspect only talks
> about the values that the aspect can have, but otherwise doesn't
> mention storage_pool_indicator.

That's true. I said it needed wordsmithing. ;-)

> Also, I believe the aspect cannot
> have the value null, which is another reason I avoided
> storage_pool_indicator. However, the wording does talk about "default
> pool" which is defined in 13.11.3 (4.1/3). And the wording for the
> aspect and for the pragma both use this term, so I thought it best to
> use wording based on that definition, rather than the syntax element,
> storage_pool_indicator.
>
> I'd be OK with using visibility rules similar to the wording you have
> above, but note that the rule above wouldn't flag;
>
>       pragma Default_Storage_Pool (Standard);
>       function Standard ...
>
> because the function Standard isn't visible to the pragma, whereas the
> rule I had would flag this. Though I do not have any big concerns
> about this case.

I'd hope not. We really don't want retroactive legality rules. After all, you
can write:

     Var : Integer;
     type Integer is range 1 .. 10;

And this is of course confusing, but there is no attempt to prevent it in the
language. Moreover, every Ada programmer knows that you never have to look at
anything following a construct to determine its legality. Ada is fundamentally a
one-pass language (with a few exceptions), this case is way too unimportant to
break that.

> I'm still thinking I'd probably not use Storage_Pool_Indicator
> though....

Agreed.

> So. I'm not clear which is the better approach. Whether to use
> visibility rules or something similar to what I had. I am willing to
> take another stab at the wording, but would like some guidance, after
> considering the above comments.

Use visibility rules, but not resolution. As I said, we have to use visibility
in order to avoid ripple effects (where adding a with makes something unrelated
illegal). Tucker suggested that it be "directly visible".

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

From: Bob Duff
Sent: Saturday, January 24, 2015  5:19 PM

>...it's simply not worth the
> energy that's already been put to it.

I agree with Randy 100% on this.

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

From: Robert Dewar
Sent: Saturday, January 24, 2015  5:42 PM

> But the real issue here is that someone declared something named "Standard".
> Any time a programmer uses a name that already has a well-defined Ada
> meaning for some other purpose (more specifically, the name of any
> language-defined non-overloadable entity), the programmer is asking
> for confusion. Not just with this pragma, but potentially anywhere.

Absolutely, and any effort to protect the programmer from the bad effects of
such horrible usage is IMO misguided.

> If I write
>     Boolean : Integer;
> I'm not expecting the compiler to give me a warning about confusion
> when I later use the name Boolean somewhere.
>
> Why this case requires any special attention is beyond me. I've been
> against any check anywhere since this issue was originally brought up.
> If *anything* deserves a warning, it's the use of Standard as the name
> of an entity. But we've tolerated that for approximately 1 zillion
> years. I doubt enough has changed about that.

I definitely agree wtih that

> I can see having a check associated with the pragma (it's new, after
> all, so there is no compatibility issue), but I don't see it as
> necessary. But if we're not going to have a required check, then we
> should say nothing at all (implementations can have a warning if they
> like, but there's no reason whatsoever for the Standard to talk about
> that). This case is highly unlikely (and, as Brad noted, most of the
> time, the conflict would be harmless as Standard would not be a
> storage pool); it's simply not worth the energy that's already been put to it.

I  agree with that too!

We so often get into this sequence of events

a) find an obscure worrisome case

b) spend a huge amouint of time worrying about how to fix it

c) spend time implementing the fix

d) number of real users affected: ZERO

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

From: Jean-Pierre Rosen
Sent: Sunday, January 25, 2015  2:21 AM

> The use clause case is *far* more likely than having a name in the
> same scope. Especially for those that aren't use-adverse. (Those of us
> that are use-adverse tend to forget that at times.)

But in the presence of a use clause that makes a "Standard" visible, it would
have no effect, because the only-true Standard is always directly visible, and
therefore the name "Standard" always resolves to it.

One more reason to consider this is a non-issue...

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

From: Brad Moore
Sent: Sunday, January 25, 2015  8:27 AM

So for use-visibility, such a declaration of "Standard" would never become
directly visible.

It is only immediate-visbility where there might be an issue, but note that
immediate-visibility can occur across package boundaries, if "Standard" is
declared in a parent package and its use occurs in a child package of that
parent.

I suppose the reason we were considering this rule is to be consistent with how
Ada treats immdidate-visibility cases.

eg.

    subtype True_False is Boolean;
    type R is
       record
--       Boolean : True_False;  -- Illegal if moved here
          True : Boolean;
          Boolean : True_False;  -- legal
       end record;
       -- Illegal if you uncomment the first Boolean
       -- and comment out the second one, because True
       -- then has immediate-visibility to "Boolean" which
       -- is then no longer a type but an object

    Standard : R := (True => False,
                     Boolean => True);

    -- Assertion is not raised due to immediate-visibility
    T : Boolean := Standard.True;
    pragma Assert (T = False);

    X : Standard.Boolean; -- Illegal, immediate-visibility applies

    pragma Default_Storage_Pool (Standard);
    -- Confusion: Does Standard here have immediate-visibility?
    -- The compiler knows the answer is no.
    -- The programmer might expect the answer is yes.

I would say the only time the programmer could use the Default_Storage_Pool
pragma or aspect and get confused is if he declares a variable named Standard
that is of a type that is an ancestor of
System.Storage_Pools.Root_Storage_Pool'Class, and then wants to use that storage
pool in a Default_Storage_Pool pragma or aspect from some place that has
immediate-visibility to that declaration. He might think he is using his pool
when in fact he is using the implementations standard storage pool.

This seems like a pretty unlikely situation to deserve special wording. If he
notices his storage pool is not getting used and wonders why, he should be able
to figure this out by reading about the pragma in the RM.

But I will rewrite the clause in the proposed AI in terms of
immediate-visibility, and then we can decide if we want it or not, or whether it
should be a required warning/suppressable or a hard legality error.

I note that GNAT currently has a warning that warns about redefinition of names
in Standard, which should warn about this case, but you have to enable the
warning to see it.

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

From: Robert Dewar
Sent: Sunday, January 25, 2015  10:24 AM

> This seems like a pretty unlikely situation to deserve special wording.
> If he notices his storage pool is not getting used and wonders why, he
> should be able to figure this out by reading about the pragma in the RM.

Yes indeed, WHY this very special case should be considered worthy of a
mandatory warning when there are hundreds of more dangerous much more likely
things that do NOT warrant a mandatory warning is completely beyond me. It seems
that OCD has come to language design :-) :-)

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

From: Robert Dewar
Sent: Sunday, January 25, 2015  10:27 AM

> I note that GNAT currently has a warning that warns about redefinition
> of names in Standard, which should warn about this case, but you have
> to enable the warning to see it.

True, and surprisinngly this warning (-gnatw.k) is not included -gnatwa.
That seems like a mistake and I think I will fix it.

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

From: Bob Duff
Sent: Sunday, January 25, 2015  11:04 AM

> >> The use clause case is *far* more likely than having a name in the
> >> same scope. Especially for those that aren't use-adverse. (Those of
> >> us that are use-adverse tend to forget that at times.)
> > But in the presence of a use clause that makes a "Standard" visible,
> > it would have no effect, because the only-true Standard is always
> > directly visible, and therefore the name "Standard" always resolves to it.
> >
> > One more reason to consider this is a non-issue...

Good point, J-P.

>     subtype True_False is Boolean;
>     type R is
>        record
> --       Boolean : True_False;  -- Illegal if moved here
>           True : Boolean;
>           Boolean : True_False;  -- legal
>        end record;
>        -- Illegal if you uncomment the first Boolean
>        -- and comment out the second one, because True
>        -- then has immediate-visibility to "Boolean" which
>        -- is then no longer a type but an object
>
>     Standard : R := (True => False,
>                      Boolean => True); ...etc.

Cool example, but I think the Obfuscated C Contest is better.  ;-)

> But I will rewrite the clause in the proposed AI in terms of
> immediate-visibility, and then we can decide if we want it or not, or
> whether it should be a required warning/suppressable or a hard
> legality error.

For the record, my idea for "suppressible error" was that then the rule could be
simpler, and not deal with visibility at all -- just say you can't/shouldn't
declare ANYTHING called Standard.

But I agree with Robert; let's drop the whole idea.

> I note that GNAT currently has a warning that warns about redefinition
> of names in Standard, which should warn about this case, but you have
> to enable the warning to see it.

Probably should be on by default.

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

From: Robert Dewar
Sent: Sunday, January 25, 2015  11:36 AM

I fear that will cause too many test suite regressions, but we will see, the
most common thing for people to redeclare is Integer.

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

From: Brad Moore
Sent: Sunday, January 25, 2015  9:04 PM

> Then I didn't make myself clear.  I was saying that we could have a
> rule that forbids declaring anything anywhere with the name Standard.
> I think that's a good idea anyway, because then you're guaranteed to
> have a full expanded name for every package.
>
> Objection!  That's a gratuitous incompatibility!
>
> Answer:  Suppressible Legality Rule.

I have to say I like this more general approach much better than trying to come
up with a very specific rule for the Default_Storage_Pool pragma.

Putting in a special rule for Default_Storage_Pool feels like a band-aid
solution. It only discourages the programmer from declaring things called
Standard, if there happens to be a Default_Storage_Pool pragma specified as
Standard that has immediate visibilty. We instead should be discouraging the
programmer from using Standard for all declarations, not just this specific
case.

Given that GNAT already has a warning for redefining Standard, which hopefully
covers us against this perceived confusion problem for now until other Ada 2012
compilers become available, and that the rule is an obscure situation that
likely doesn't affect anyone anyways, I'd rather leave out this rule we've been
discussing from this AI, and wait for a suppressable legality rule AI in
whatever form, to provide a better solution that discourages using the name
Standard in any declaration.

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

From: Robert Dewar
Sent: Sunday, January 25, 2015  9:54 PM

I agree with this, and as a response I intend to experiment with making this
GNAT warning the default, at least for Standard, and maybe for all the other
entities, or at least have it included in -gnatwa.

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

From: Brad Moore
Sent: Tuesday, January 27, 2015  12:13 AM

I have included an update. [This is version /07 of the AI.]

It is unusual in that it is both written up with an attempted fix to the
paragraph, for the remote chance that we decide to keep it, while also including
some text in the discussion about why we decided to not keep it.

I have also added some comments in square brackets at both of these places
indicating that one or the other should be deleted.

So hopefully it will just be a matter of deciding which section we want to
scrap.

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

From: Randy Brukardy
Sent: Wednesday, January 28, 2015  10:13 PM

Just noticed that you didn't make a matching version of the new rule for aspect
Default_Storage_Pool. To fix that, I added the following after 13.11.3(5/3) as a
separate paragraph (the paragraph looked too long otherwise):

Standard when used aspect_definition for the Default_Storage_Pool aspect is an
identifier specific to an aspect (see 13.1.1) and does not denote any
declaration. If the aspect_definition for the Default_Storage_Pool aspect is
Standard, then there shall not be a declaration with defining identifier
Standard that is immediately visible at the point of the aspect, other than
package Standard itself.

You can do any wordsmithing as part of your Editorial Review.

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

Questions? Ask the ACAA Technical Agent