!standard 8.2(11) 15-03-25 AI12-0003-1/13 !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 by Letter Ballot (11-1-2) 15-02-23 !status work item 15-02-03 !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 that is not used as a configuration pragma is defined to be the region extending from immediately after the pragma to the end of 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 storage 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 considered 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 eliminating any possible confusion with regard to immediately visible declarations with the defining_identifier Standard. 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]{the given 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]{the given 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. In this case, there shall not be a declaration with defining_identifier Standard that is immediately visible at the point of the aspect specification, 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) @dinsa 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. @dinst The immediate scope of a pragma that is not used as a configuration pragma is defined to be the region extending from immediately after the pragma to the end of the declarative region immediately enclosing the pragma. !corrigendum 13.11.3(1/3) @drepl @dby 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 storage size for an access type. !corrigendum 13.11.3(3.1/3) @drepl @xindent<@fa ::= @i@fa | @b> @dby @xindent<@fa ::= @i@fa | @b | Standard> !corrigendum 13.11.3(4/3) @dinsa The @i@fa shall denote a variable. @dinst The Standard @fa is an identifier specific to a pragma (see 2.8) and does not denote any declaration. If the @fa is Standard, then there shall not be a declaration with @fa Standard that is immediately visible at the point of the pragma, other than package Standard itself. !corrigendum 13.11.3(4.1/3) @drepl If the @fa is used as a configuration pragma, the @fa shall be @b, and it defines the @i to be @b within all applicable compilation units (see 10.1.5), except within the immediate scope of another @fa 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 @b or the pool denoted by the @i@fa, except within the immediate scope of a later pragma Default_Storage_Pool. Thus, an inner pragma overrides an outer one. @dby If the @fa is used as a configuration pragma, the @fa shall be either @b or Standard, and it defines the @i to be the given @fa within all applicable compilation units (see 10.1.5), except within the immediate scope of another @fa 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 the given @fa, 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) @drepl 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 @fa 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. @dby 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. In this case, there shall not be a declaration with @fa Standard that is immediately visible at the point of the aspect specification, other than package Standard itself. Otherwise, the expected type for the Default_Storage_Pool aspect is Root_Storage_Pool'Class and the @fa shall be a @fa 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) @drepl @xbullet @dby @xbullet nor Standard, the Storage_Pool attribute is that pool.> !corrigendum 13.11.3(6.3/3) @drepl Otherwise, there is no default pool; the standard storage pool is used for the type as described in 13.11. @dby 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 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 compatibility 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 Brukardt 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. **************************************************************** From: Randy Brukardt Sent: Wednesday, January 28, 2015 11:06 PM Just found another problem with this AI. The syntax change is described as: storage_pool_indicator ::= storage_pool_name | null {| Standard} I was trying to figure out what font "Standard" should be in, and discovered that none of the other pragmas I checked use this sort of syntax. Rather an "identifier specific to a pragma" are syntactally described as "identifier" along with a textual rule stating which identifiers are allowed. (See pragma List in 2.8, pragma Suppress in 11.5 (check names), pragma Convention (now in J.15.5), etc.) So the syntax should be storage_pool_indicator ::= storage_pool_name | null {| identifier} And the we have to add something like the following to 13.11.3(4/3): If the storage_pool_indicator is an identifier, the identifier shall be Standard. Or maybe in the Syntax section, The only identifier that can be used in a storage_pool_indicator is Standard. But in both cases, that sounds like it's talking about the name as well as the identifier specific to a pragma. It would be better to put this in Static Semantics and say something similar to what pragma List says: A pragma Default_Storage_Pool takes the identifier Standard, the reserved word *null*, or the name of a storage pool as the single argument. but that would either require two static semantics sections, or a wholesale rearrangement of the subclause. And it repeats most of the separate syntax item. Humm... Maybe a wholesale rearrangement wouldn't be a bad idea. There's never any text in this clause that explains what this silly pragma is for. We don't find out what it does until 11 paragraphs in! And we could hang the meaning of "identifier" in the 13.11.3(4.2/3) wording. Paragraph 1 is unused. Maybe we should start the whole thing with something like: Redundant[Pragma and aspect Default_Storage_Pool specify the pool that will be used in the absence of an explicit specification for an access type.] Bah. This AI is getting to be like the piece of paper stuck to your shoe on the street. You think you've gotten rid of it, and a little while later you realize it is still there!!! I'm going to try this again tomorrow. I just realized that I've been doing this for most of the last 12 hours (our phone meeting started exactly 12 hours ago as I write this), and that's more than enough for one day. **************************************************************** From: Robert Dewar Sent: Thursday, January 29, 2015 5:54 AM > 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. I would be perfectly happy instead with simply a rule saying that if there is such a declaration, the Standard referenced is resolved as meaning the (context sensitive keyword) Standard. In practice, the above legality rule is 100.00000% useless. This case will never arise. All it does is make implementations waste time implementing a completely useless legality rule, which if it is ever triggered will only be triggered in an annoying(*) ACATS test. (*) I hereby declare that I use annoying as a term of art here, to mean a test that tests something that will never ever occur in real programs :-) In this case, the legality rule is easy to implement, so no big deal, but my aesthetics are sort of diametrically opposite to those of many of those on the ARG. To me, the legality rule makes a nasty wart in the implementation, which I find unaesthetic, whereas I don't have any problem at all with a rule in the language resolving the ambiguity. As I mentioned in a previous note, GNAT has a few of these anyway. So working to avoid such ambiguities in the official theological document, which talks about a language (strict Standard Ad) which no one uses, seems a bit of a waste of effort. If you DO add a rule, I would prefer it be more specific, disallowing ONLY a declaration of a "Standard" storage pool, and not making other perfectly reasonable uses of Standard illegal (and such uses could even be in a separate parent unit, which would be quite annoying!) **************************************************************** From: Jean-Pierre Rosen Sent: Thursday, January 29, 2015 10:08 AM > In practice, the above legality rule is 100.00000% useless. This case > will never arise. Hmmm... I think that's what I suggested, but a previous incarnation of RBKD popped up and said that it would suddenly change the meaning of zillions of programs that had a visible storage pool called Standard, and that it was an unbearable incompatibility... **************************************************************** From: Randy Brukardt Sent: Thursday, January 29, 2015 6:21 PM ... > I would be perfectly happy instead with simply a rule saying that if > there is such a declaration, the Standard referenced is resolved as > meaning the (context sensitive keyword) Standard. We of course have that - it's the definition of what "Standard" means in the pragma. But Tucker insisted that we go further, and we agreed to the wording I gave; we just forgot the aspect version. I thought you were on the call yesterday when we decided that?? I believe Tucker's argument is that this pragma is different than the others with identifiers-specific-to-a-pragma, as it also allows user-defined names of entities. So there is a chance for confusion. > In practice, the above legality rule is 100.00000% useless. > This case will never arise. All it does is make implementations waste > time implementing a completely useless legality rule, which if it is > ever triggered will only be triggered in an annoying(*) ACATS test. > > (*) I hereby declare that I use annoying as a term of art here, to > mean a test that tests something that will never ever occur in real > programs :-) Yes, I know that and completely agree with you. But not everyone does...sometimes one has to take compromise positions to get things done. And this is rather unimportant in the grand scheme of things, especially as it will never happen. ... > If you DO add a rule, I would prefer it be more specific, disallowing > ONLY a declaration of a "Standard" storage pool, and not making other > perfectly reasonable uses of Standard illegal (and such uses could > even be in a separate parent unit, which would be quite annoying!) (1) There are no "perfectly reasonable uses of Standard"! There are legal uses of Standard, but as we all seemed to agree, redefining non-overloadable entities defined in Standard and Standard itself is a bad practice. There is nothing "reasonable" about bad practice. (2) If you are right about "This case will never arise", then arguing about the exact form of the rule is pointless. Why make a rule that will never happen more complex? (And a lot more complex to implement.) (3) I'd argue the above is overly specific. There are a number of ways to write something confusing named Standard related to a storage pool, and if we're going to catch any of them, we ought to catch them all. Besides objects of a storage pool named Standard, you could have a function (parameterless or with all defaulted parameters). You could also have an object or function returning an access-to-storage-pool. That would require .all to be legal (so the exact case wouldn't hit), but I for one leave out .all in such contexts all of the time (thinking that it is implicit when in fact it isn't). I expect the compiler to flag such bugs, but in this case it would not (it would just do something different than intended). Specifically, I might write something like: type Pools is access all Root_Storage_Pool'Class; function The_Pool return Pools; pragma Default_Storage_Pool (The_Pool); -- Illegal, .all is missing. But if you were to change The_Pool to Standard, the error would disappear and a misinterpretation would happen. So I think the simpler rule is better; it's easier to check, it covers all of the confusing cases without complication, and the exact rule we chose is going to matter to someone other than an implementer approximately 0.0% of the time. And while I'd prefer no rule at all, that last fact tells me that arguing about the content/absence of a rule for this particular corner is rather silly. Hopefully end of story. **************************************************************** From: Bob Duff Sent: Thursday, January 29, 2015 11:00 AM > Just found another problem with this AI. The syntax change is described as: > > storage_pool_indicator ::= storage_pool_name | null {| Standard} > > I was trying to figure out what font "Standard" should be in, ... Really?! Seriously, Randy, I think you've got a lot more important ways to spend your time. ;-) The above syntax is crystal clear. Put Standard in the usual font for identifiers in the text. This is one of the few cases in language design where "A foolish consistency is the hobgoblin of little minds" applies. All of the suggestions below make it less clear, purely for a foolish consistency. (I don't mind adding an explanatory introductory Redundant, as you suggest. But a "wholesale rearrangement" seems like a waste of your valuable time.) >...and discovered > that none of the other pragmas I checked use this sort of syntax. >Rather an "identifier specific to a pragma" are syntactally described as "identifier" > along with a textual rule stating which identifiers are allowed. (See >pragma List in 2.8, pragma Suppress in 11.5 (check names), pragma >Convention (now in J.15.5), etc.) > > So the syntax should be > > storage_pool_indicator ::= storage_pool_name | null {| identifier} Forcing the reader to rummage around to find out what "identifier" is allowed in this case is unhelpful. The other pragmas are different, because they allow more than one identifier, so the apparent inconsistency doesn't bother me. **************************************************************** From: Randy Brukardt Sent: Thursday, January 28, 2015 6:39 PM > > Just found another problem with this AI. The syntax change > is described as: > > > > storage_pool_indicator ::= storage_pool_name | null {| Standard} > > > > I was trying to figure out what font "Standard" should be in, ... > > Really?! Seriously, Randy, I think you've got a lot more important > ways to spend your time. ;-) Seriously. See below. > The above syntax is crystal clear. Put Standard in the usual font for > identifiers in the text. > > This is one of the few cases in language design where "A foolish > consistency is the hobgoblin of little minds" > applies. All of the suggestions below make it less clear, purely for > a foolish consistency. Sorry, an editor's primary job is enforcing consistency. I've had to spend time on a lot more foolish things than this. (For example, making sure that "nonabstract" is spelled without a hyphen everywhere - thanks, Gary. ;-) Secondly, the suggestions below are what happens if it is not rearranged. If we put the wording into the paragraph that already says that Standard is an identifier specific to a pragma, and hoist that, I think it will become much clearer. (If not, I won't do it.) The "hoisting" is a good idea anyway, as the proposed wording uses "Standard" for multiple paragraphs before it explains what it is. That should come first. I think this whole clause got inside-out somehow (the most important stuff comes last). Thirdly, you're probably forgotten the crazy markup of the syntax in the RM generator. The Ada 9x team foisted that on me (I believe it was foisted on you, too, so I don't blame you so much as pity you...). Since the syntax is automatically processed to make the Annex P tables and cross-references, and the automatically generated cross-links in the HTML version, what can be put into it is very strictly limited. For that reason, I don't ever create new RM syntax markup, I always find some existing rule to copy. My problem here is I couldn't do that. Fourthly, this grammar could work for the pragma, but it doesn't work for the aspect (for which there is no syntax change; as Brad points out, null is not allowed there so the above syntax isn't used in its wording). So I still need to make the wording fix for that one. > (I don't mind adding an explanatory introductory Redundant, as you > suggest. But a "wholesale rearrangement" seems like a waste of your > valuable time.) Well, at the moment, still have a lot of my Corrigendum budget left, so it's not clear how valuable that time is. One never wants to have budgeted money left over at the end of a fiscal year. :-) Anyway, I still have to put this wording in the RM; it'll take about the same amount of time to rearrange it now as it would to do it later once people look at it in context. I think I'm spending more time answering this message than I'd save by not doing anything. :-) And it should be remembered that I sent the note you're replying to after 11 hours of straight ARG work. My brain pretty much wasn't working, or I would have just sent a proposal and not a list of ramblings. ... > > I'm going to try this again tomorrow. I just realized that I've been > > doing this for most of the last 12 hours (our phone meeting started > > exactly 12 hours ago as I write this), and that's more than enough > > for one day. **************************************************************** From: Randy Brukardt Sent: Thursday, January 29, 2015 7:57 PM OK, below is the RM Text for entire clause, is it will look after applying AI12-0003-1 and my proposed redo. This doesn't show any change marks; it's intended for maximum readability. Ultimately, I left the syntax for the pragma alone because I can't find any decent way to word the "correct" text. I hope that the syntax of "digit" can be copied for this purpose (there is no instance of a complete non-reserved identifier in the RM). My intent is that the semantics are exactly as we approved yesterday, just with less verbiage and no holes. I rearranged the text so that we define "Standard" before we start talking about it and cleaned out a bunch of redundant rules (in particular 4.2/4 was redone to eliminate any talk about what the default pool is; that's defined formally in 6-6.3/4 and it had gotten very complex). Note that the rearrangement changes the paragraph numbers in some cases (can't be helped, since we can't insert between inserted paragraphs). And (horrors!) the existing wording for paragraph 5/3 has a "must" in it -- changed to "shall". (The paragraphs marked /4 are changed by this AI or by previously approved AI12-0136-1. All paragraphs marked /3 are unchanged.) Comments welcome (but only until Monday). The introductory sentence in particular could use some improvement. We'll letter ballot the resulting AI, since I changed it so heavily. Randy. ================ 13.11.3 Default Storage Pools 1/4 Redundant[Pragma and aspect Default_Storage_Pool specify the pool that will be used in the absence of an explicit specification for an access type.] Syntax 2/3 The form of a pragma Default_Storage_Pool is as follows: pragma Default_Storage_Pool (storage_pool_indicator); 3.1/3 storage_pool_indicator ::= storage_pool_name | null | Standard 3.2/3 A pragma Default_Storage_Pool is allowed immediately within the visible part of a package_specification, immediately within a declarative_part, or as a configuration pragma. Name Resolution Rules 3.3/3 The storage_pool_name is expected to be of type Root_Storage_Pool'Class. Legality Rules 4/3 The storage_pool_name shall denote a variable. 4.1/4 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. 4.2/4 -- number changed 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 as 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 as that storage_pool_indicator within the immediate scope of the pragma, except within the immediate scope of a later pragma Default_Storage_Pool. Redundant[Thus, an inner pragma overrides an outer one.] 4.3/4 -- only number changed A pragma Default_Storage_Pool shall not be used as a configuration pragma that applies to a compilation unit that is within the immediate scope of another pragma Default_Storage_Pool. Static Semantics 5/4 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. 5.1/4 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. 5.2/4 The effect of specifying the aspect Default_Storage_Pool on an instance of a language-defined generic unit is implementation-defined. 6/3 For nonderived access types declared in places where the default pool is defined by the pragma or aspect, their Storage_Pool or Storage_Size attribute is determined as follows, unless Storage_Pool or Storage_Size is specified for the type: 6.1/3 If the default pool is null, the Storage_Size attribute is defined by the language to be zero. [Therefore, an allocator for such a type is illegal.] 6.2/4 If the default pool is neither null nor Standard, the Storage_Pool attribute is that pool. 6.3/4 Otherwise {(including when the default pool is specified as Standard)}, the standard storage pool is used for the type as described in 13.11. [There is no paragraph 7] Implementation Permissions 8/3 An object created by an allocator that is passed as the actual parameter to an access parameter may be allocated on the stack, and automatically reclaimed, regardless of the default pool. **************************************************************** From: Tucker Taft Sent: Saturday, January 31, 2015 9:16 AM > ... > > Static Semantics > 5/4 > 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. ... This should probably say "at the point of the aspect specification" -- "aspects" are abstract notions and don't have locations. **************************************************************** From: Bob Duff Sent: Saturday, January 31, 2015 12:54 PM > This should probably say "at the point of the aspect specification" -- > "aspects" are abstract notions and don't have locations. Speaking of foolish consistencies... ;-) The RM usually uses "place" rather than "point" to talk about some location in the program text. **************************************************************** From: Randy Brukardt Sent: Monday, February 2, 2015 9:26 PM I'm dubious about that. Perhaps it was true in the Ada 95 RM, but not now. It looks to me like almost all of the Ada 2012 wording uses "at the point of", and even some older wording; I found 42 pages with occurrences in the draft 5 AARM, including 6.1.1(19/3), 3.2.4(29.1/4), 5.5.2(6.3/4), 6.5(24.2/3), 3.10.1(2.6/3), 3.10.1(2.7/3), 4.1.3(9.2/3), 6.4(11/2), 7.3.2(21/4), 9.5.2(13.1/2), 9.5.3(21), 11.5(8.1/2), 12.6(9.1/3), 13.1.1(11/3), 13.1.1(35/3), 13.11(25.2/3), 3.9(12.3/3), ... I quit after 18 items, but there's still a page and a half of additional search results that I didn't look through. There are only 26 pages with occurrences of "at the place of" in the draft 5 AARM. All of the normative rules: 2.8(12), 3.4(17/2), 3.4(23/2), 4.1.3(12), 8.3(25), 8.3(26/2), 10.1.6(1), 10.1.6(5), 10.1.6(6/2), 8.3.1(5/2), 10.1.5(4), 10.1.5(6), 7.2(5/3), 8.5.4(8/3), 9.4(20), 11.4.2(18/3), 12.3(12), 13.13.2(49/4), B.1(9), D.10.1(12/3). That's 20. I ignored AARM notes and user notes for these listings. It looks pretty even to me, with "at the point of" winning now. I didn't check any other forms of the phrase, which probably would change the numbers somewhat. Anyway, I didn't make a change here because it seems to fall directly into the "foolish consistency" category -- since it wouldn't be that consistent either way. **************************************************************** From: Tucker Taft Sent: Monday, February 2, 2015 10:10 PM Interesting consistent inconsistency! ;-) **************************************************************** From: Tucker Taft Sent: Wednesday, February 4, 2015 11:40 AM For what it is worth, some of the earlier implementation concerns about this pragma might be reduced by the current formulation, where using "Standard" is essentially merely canceling any outer Default_Storage_Pool specification, rather than implying that there is a single "standard" storage pool object. **************************************************************** From: Randy Brukardt Sent: Monday, February 23, 2015 7:22 PM Here's the final vote on the Letter Ballot for AI12-0003-1: Approve: 11 (Baird, Barnes, Brukardt, Cousins, Dismukes, Moore, Ploedereder, Rosen, Schonberg, Taft, Vardanega) Reject: 1 (Duff) Abstain: 2 (Burns, Dewar) Not voting: (Leroy) This clearly has been approved. Randy Brukardt, ARG Editor ****************************************************************