Rationale for Ada 2012
1.3.5 Overview: General improvements
As well as the major features discussed above there
are also a number of improvements in various other areas.
We start with some
gentle stuff. Ada 95 introduced the package Ada
package Ada is
However, a close reading of the RM revealed that
poor Ada is illegal since the pragma Pure
is not in one of the allowed places for a pragma. Pragmas are allowed
in the places where certain categories are allowed but not in place
of them. In the case of a package specification the constructs are
basic declarative items, but "items" were not one of the allowed
things. This has been changed to keep Ada
A related change concerns
a sequence of statements. In a construction such as
if B then
there must be at least
one statement in each branch so if we don't want any statements then
we have to put a null statement. If we want a branch that is just a pragma
Assert then we have to put a null statement
as well thus
if B then
pragma Assert(...); null;
This is really irritating and so the rules have been
changed to permit a pragma in place of a statement in a sequence of statements.
This and the problem with the package Ada
are treated as Binding Interpretations which means that they apply to
Ada 2005 as well.
A similar change concerns the position of labels.
It is said that gotos are bad for you. However, gotos are useful for
quitting an execution of a loop and going to the end in order to try
the next iteration. Thus
for I in
if this-one-no-good then goto End_Of_Loop; end if;
-- try another iteration
Ada provides no convenient way of doing this other
than by using a goto statement. Remember that exit transfers control
out of the loop. The possibility of a continue statement as in some other
languages was discussed but it was concluded that this would obscure
the transfer of control. The great thing about goto is that the
label sticks out like a sore thumb. Indeed, a survey of the code in a
well known compiler revealed an orgy of uses of this handy construction.
However, it was decided that having to put null
was an ugly nuisance and so the syntax of Ada 2012 has been changed to
permit the label to come right at the end.
There is a significant
extension to the syntax of loops used for iteration. This arose out of
a requirement to make iteration over containers easier (as outlined in
) but the general ideas can
be illustrated with an array. Consider
for K in Table'Range loop
Table(K) := Table(K) + 1;
This can now be written
for T of Table loop
T := T + 1;
The entity T is a sort
of generalized reference and hides the indexing. This mechanism can also
be used with multidimensional arrays in which case just one loop replaces
a nested set of loops.
A minor problem has arisen with the use of tags and
Generic_Dispatching_Constructor. There is
no way of discovering whether a tag represents an abstract type other
than by attempting to create an object of the type which then raises
Tag_Error; this is disgusting. Accordingly,
a new function
function Is_Abstract(T: Tag) return Boolean;
is added to the package Ada.Tags.
There were many changes to access types in Ada 2005
including the wide introduction of anonymous access types. Inevitably
some problems have arisen.
The first problem is
with the accessibility of stand-alone objects of anonymous access types
A: access T;
Without going into details, it turns out that such
objects are not very useful unless they carry the accessibility level
of their value in much the same way that access parameters carry the
accessibility level of the actual parameter. They are therefore modified
to do this.
Programmers have always moaned about the need for
many explicit conversions in Ada. Accordingly, implicit conversions from
anonymous access types to named access types are now permitted provided
the explicit conversion is legal. The idea is that the need for an explicit
conversion with access types should only arise if the conversion could
fail. A curious consequence of this change is that a preference rule
is needed for the equality of anonymous access types.
An issue regarding allocators concerns their alignment.
It will be recalled that when implementing a storage pool, the attribute
Max_Size_In_Storage_Units is useful since
it indicates the maximum size that could be requested by a call of Allocate.
Similarly, the new attribute Max_Alignment_For_Allocation
indicates the maximum alignment that could be requested.
Another problem is
that allocators for anonymous access types cause difficulties in some
areas. Rather than forbidding them completely a new restriction identifier
is added so that we can write
Another new restriction
This can be used to ensure that once the main subprogram
has started no further allocation from standard storage pools is permitted.
This prevents a long lived program suffering from rampant heap growth.
However, this does not prevent allocation from user-defined
storage pools. To enable users to monitor such allocation, additional
functions are provided in Ada.Task_Identification
(returns the Task_Id
of the environment task) and Activation_Is_Complete
(returns a Boolean result indicating whether a particular task has finished
A new facility is the ability to define subpools
using a new package System.Storage_Pools.Subpools
A subpool is a separately reclaimable part of a storage pool and is identified
by a subpool handle name. On allocation, a handle name can be given.
Further control over
the use of storage pools is provided by the ability to define our own
default storage pool.
and then all allocation
within the scope of the pragma will be from My_Pool
unless a different specific pool is given for a type.
could be done using the aspect Storage_Pool
type Cell_Ptr is access Cell
with Storage_Pool => Cell_Ptr_Pool;
A pragma Default_Storage_Pool
can be overridden by another one so that for example all allocation in
a package (and its children) is from another pool. The default pool can
be specified as null thus
and this prevents any allocation from standard pools.
Note that coextensions and allocators as access parameters
may nevertheless be allocated on the stack. This can be prevented (somewhat
brutally) by the following restrictions
A number of other restrictions
have also been added. The introduction of aspects logically requires
some new restrictions to control their use. Thus by analogy with No_Implementation_Pragmas
we can write
and this prevents the
use of any implementation-defined aspect specifications. The use of individual
aspects such as Default_Value
can be prevented
pragma Restrictions(No_Specification_of_Aspect => Default_Value);
indeed users are permitted to add descendant units of Ada
such as another child of Ada.Containers
can be confusing for maintainers since they may be not aware that they
are using non-standard packages. The new restriction
prevents the use of such units.
In a similar vein,
there is also
and this prevents the use of additional identifiers
declared in packages such as System.
A blanket restriction
can be imposed by writing
and this is equivalent
to the following five restrictions
Finally, the issue of composability of equality has
been revisited. In Ada 2005, tagged record types compose but untagged
record types do not. If we define a new type (a record type, array type
or a derived type) then equality is defined in terms of equality for
its various components. However, the behaviour of components which are
records is different in Ada 2005 according to whether they are tagged
or not. If a component is tagged then the primitive operation is used
(which might have been redefined), whereas for an untagged type, predefined
equality is used even though it might have been overridden. This is a
bit surprising and so has been changed in Ada 2012 so that all record
types behave the same way and use the primitive operation. This is often
called composability of equality so that we can say that in Ada 2012,
record types always compose for equality. Remember that this only applies
to records; components which are of array types and elementary types
always use predefined equality.
© 2011, 2012, 2013 John Barnes Informatics.
Sponsored in part by: