Go to the first, previous, next, last section, table of contents.
This chapter contains sections that describe compatibility issues between
GNAT and other Ada 83 and Ada 95 compilation systems, to aid in porting
applications developed in other Ada environments.
Ada 95 is designed to be highly upwards compatible with Ada 83. In
particular, the design intention is that the difficulties associated
with moving from Ada 83 to Ada 95 should be no greater than those
that occur when moving from one Ada 83 system to another.
However, there are a number of points at which there are minor
incompatibilities. The Ada 95 Annotated Reference Manual contains
full details of these issues,
and should be consulted for a complete treatment.
In practice the
following are the most likely issues to be encountered.
- Character range
-
The range of Standard.Character is now the full 256 characters of Latin-1,
whereas in most Ada 83 implementations it was restricted to 128 characters.
This may show up as compile time or runtime errors. The desirable fix is to
adapt the program to accommodate the full character set, but in some cases
it may be convenient to define a subtype or derived type of Character that
covers only the restricted range.
- New reserved words
-
The identifiers
abstract
, aliased
, protected
,
requeue
, tagged
, and until
are reserved in Ada 95.
Existing Ada 83 code using any of these identifiers must be edited to
use some alternative name.
- Freezing rules
-
The rules in Ada 95 are slightly different with regard to the point at
which entities are frozen, and representation pragmas and clauses are
not permitted past the freeze point. This shows up most typically in
the form of an error message complaining that a representation item
appears too late, and the appropriate corrective action is to move
the item nearer to the declaration of the entity to which it refers.
A particular case is that representation pragmas (including the
extended DEC Ada 83 compatibility pragmas such as Export_Procedure), cannot
be applied to a subprogram body. If necessary, a separate subprogram
declaration must be introduced to which the pragma can be applied.
- Optional bodies for library packages
-
In Ada 83, a package that did not require a package body was nevertheless
allowed to have one. This lead to certain surprises in compiling large
systems (situations in which the body could be unexpectedly ignored). In
Ada 95, if a package does not require a body then it is not permitted to
have a body. To fix this problem, simply remove a redundant body if it
is empty, or, if it is non-empty, introduce a dummy declaration into the
spec that makes the body required. One approach is to add a private part
to the package declaration (if necessary), and define a parameterless
procedure called Requires_Body, which must then be given a dummy
procedure body in the package body, which then becomes required.
- Numeric_Error is now the same as Constraint_Error
-
In Ada 95, the exception Numeric_Error is a renaming of Constraint_Error.
This means that it is illegal to have separate exception handlers for
the two exceptions. The fix is simply to remove the handler for the
Numeric_Error case (since even in Ada 83, a compiler was free to raise
Constraint_Error in place of Numeric_Error in all cases).
- Indefinite subtypes in generics
-
In Ada 83, it was permissible to pass an indefinite type (e.g. String) as
the actual for a generic formal private type, but then the instantiation
would be illegal if there were any instances of declarations of variables
of this type in the generic body. In Ada 95, to avoid this clear violation
of the contract model, the generic declaration clearly indicates whether
or not such instantiations are permitted. If a generic formal parameter
has explicit unknown discriminants, indicated by using (<>) after the
type name, then it can be instantiated with indefinite types, but no
variables can be declared of this type. Any attempt to declare a variable
will result in an illegality at the time the generic is declared. If the
(<>) notation is not used, then it is illegal to instantiate the generic
with an indefinite type. This will show up as a compile time error, and
the fix is usually simply to add the (<>) to the generic declaration.
All implementations of GNAT provide a switch that causes GNAT to operate
in Ada 83 mode. In this mode, some but not all compatibility problems
of the type described above are handled automatically. For example, the
new Ada 95 protected keywords are not recognized in this mode. However,
in practice, it is usually advisable to make the necessary modifications
to the program to remove the need for using this switch.
Providing that programs avoid the use of implementation dependent and
implementation defined features of Ada 95, as documented in the Ada 95
reference manual, there should be a high degree of portability between
GNAT and other Ada 95 systems. The following are specific items which
have proved troublesome in moving GNAT programs to other Ada 95
compilers, but do not affect porting code to GNAT.
- Ada 83 Pragmas and Attributes
-
Ada 95 compilers are allowed, but not required, to implement the missing
Ada 83 pragmas and attributes that are no longer defined in Ada 95.
GNAT implements all such pragmas and attributes, eliminating this as
a compatibility concern, but some other Ada 95 compilers reject these
pragmas and attributes.
- Special-needs Annexes
-
GNAT implements the full set of special needs annexes. At the
current time, it is the only Ada 95 compiler to do so. This means that
programs making use of these features may not be portable to other Ada
95 compilation systems.
- Representation Clauses
-
Some other Ada 95 compilers implement only the minimal set of
representation clauses required by the Ada 95 reference manual. GNAT goes
far beyond this minimal set, as described in the next section.
The Ada 83 reference manual was quite vague in describing both the minimal
required implementation of representation clauses, and also their precise
effects. The Ada 95 reference manual is much more explicit, but the minimal
set of capabilities required in Ada 95 is quite limited.
GNAT implements the full required set of capabilities described in the
Ada 95 reference manual, but also goes much beyond this, and in particular
an effort has been made to be compatible with existing Ada 83 usage to the
greatest extent possible.
A few cases exist in which Ada 83 compiler behavior is incompatible with
requirements in the Ada 95 reference manual. These are instances of
intentional or accidental dependence on specific implementation dependent
characteristics of these Ada 83 compilers. The following is a list of
the cases most likely to arise in existing legacy Ada 83 code.
- Implicit Packing
-
Some Ada 83 compilers allowed a Size specification to cause implicit
packing of an array or record. This is specifically disallowed by
implementation advice in the Ada 83 reference manual (for good reason,
this usage can cause expensive implicit conversions to occur in the
code). The problem will show up as an error message rejecting the
size clause. The fix is simply to provide the explicit pragma Pack.
- Meaning of Size Attribute
-
The Size attribute in Ada 95 for discrete types is defined as being the
minimal number of bits required to hold values of the type. For example,
on a 32-bit machine, the size of Natural will typically be 31 and not
32 (since no sign bit is required). Some Ada 83 compilers gave 31, and
some 32 in this situation. This problem will usually show up as a compile
time error, but not always. It is a good idea to check all uses of the
'Size attribute when porting Ada 83 code. The GNAT specific attribute
Object_Size can provide a useful way of duplicating the behavior of
some Ada 83 compiler systems.
- Size of Access Types
-
A common assumption in Ada 83 code is that an access type is in fact a pointer,
and that therefore it will be the same size as a System.Address value. This
assumption is true for GNAT in most cases with one exception. For the case of
a pointer to an unconstrained array type (where the bounds may vary from one
value of the access type to another), the default is to use a "fat pointer",
which is represented as two separate pointers, one to the bounds, and one to
the array. This representation has a number of advantages, including improved
efficiency. However, it may cause some difficulties in porting existing Ada 83
code which makes the assumption that, for example, pointers fit in 32 bits on
a machine with 32-bit addressing.
To get around this problem, GNAT also permits the use of "thin pointers" for
access types in this case (where the designated type is an unconstrained array
type). These thin pointers are indeed the same size as a System.Address value.
To specify a thin pointer, use a size clause for the type, for example:
type X is access all String;
for X'Size use System.Address'Size;
which will cause the type X to be represented using a single pointer. When using
this representation, the bounds are right behind the array. This representation
is slightly less efficient, and does not allow quite such flexibility in the
use of foreign pointers or in using the Unrestricted_Access attribute to create
pointers to non-aliased objects. But for any standard portable use of the access
type it will work in a functionally correct manner and allow porting of existing
code. Note that another way of forcing a thin pointer representation is to use
a component size clause for the element size in an array, or a record
representation clause for an access field in a record.
The VMS version of GNAT fully implements all the pragmas and attributes
provided by DEC Ada 83, as well as providing the standard DEC Ada 83
libraries, including Starlet. In addition, data layouts and parameter
passing conventions are highly compatible. This means that porting
existing DEC Ada 83 code to GNAT in VMS systems should be easier than
most other porting efforts. The following are some of the most
significant differences between GNAT and DEC Ada 83.
- Default floating-point representation
-
In GNAT, the default floating-point format is IEEE, whereas in DEC Ada 83,
it is VMS format. GNAT does implement the necessary pragmas
(Long_Float, Float_Representation) for changing this default.
- System
-
The package System in GNAT exactly corresponds to the definition in the
Ada 95 reference manual, which means that it excludes many of the
DEC Ada 83 extensions. However, a separate package Aux_DEC is provided
that contains the additional definitions, and a special pragma,
Extend_System allows this package to be treated transparently as an
extension of package System.
- To_Address
-
The definitions provided by Aux_DEC are exactly compatible with those
in the DEC Ada 83 version of System, with one exception. DEC Ada provides
the following declarations:
TO_ADDRESS(INTEGER)
TO_ADDRESS(UNSIGNED_LONGWORD)
TO_ADDRESS(universal_integer)
The version of TO_ADDRESS taking a universal integer argument is in fact
an extension to Ada 83 not strictly compatible with the reference manual.
In GNAT, we are constrained to be exactly compatible with the standard,
and this means we cannot provide this capability. In DEC Ada 83, the
point of this definition is to deal with a call like:
TO_ADDRESS (16#12777#);
Normally, according to the Ada 83 standard, one would expect this to be
ambiguous, since it matches both the INTEGER and UNSIGNED_LONGWORD forms
of TO_ADDRESS. However, in DEC Ada 83, there is no ambiguity, since the
definition using universal_integer takes precedence.
In GNAT, since the version with universal_integer cannot be supplied, it is
not possible to be 100% compatible. Since there are many programs using
numeric constants for the argument to TO_ADDRESS, the decision in GNAT was
to change the name of the function in the UNSIGNED_LONGWORD case, so the
declarations provided in the GNAT version of AUX_Dec are:
function To_Address (X : Integer) return Address;
pragma Pure_Function (To_Address);
function To_Address_Long (X : Unsigned_Longword) return Address;
pragma Pure_Function (To_Address_Long);
This means that programs using TO_ADDRESS for UNSIGNED_LONGWORD must
change the name to TO_ADDRESS_LONG.
- Task_Id values
-
The Task_Id values assigned will be different in the two systems, and GNAT
does not provide a specified value for the Task_Id of the environment task,
which in GNAT is treated like any other declared task.
For full details on these and other less significant compatibility issues,
see appendix E of the Digital publication entitled "DEC Ada, Technical
Overview and Comparison on DIGITAL Platforms".
For GNAT running on other than VMS systems, all the DEC Ada 83 pragmas and
attributes are recognized, although only a subset of them can sensibly
be implemented. The description of pragmas in this reference manual
indicates whether or not they are applicable to non-VMS systems.
Go to the first, previous, next, last section, table of contents.