Form G104-1092a 9X-GUIDE.TXT
Abstract
Existing software will have to be transitioned from Ada 83 to Ada 9X. This
paper explains presently known incompatibilities between the existing Ada
standard and its proposed revision. It provides guidelines to users, which
will make their Ada 83 code upward compatible with Ada 9X.
1. Introduction
Ada 9X is approaching rapidly. Initiation of the formal ANSI and ISO
standardization processes is expected in late 1993. Although attracted by the
added functionality of Ada 9X, many users are concerned about the eventual
cost of upgrading their Ada applications to the revised standard. Of
particular interest are any incompatibilities that might exist between Ada 83
and Ada 9X. The detection and analysis of such incompatibilities, and the
resulting program changes, add risk and cost to the transition to Ada 9X.
Avoiding such incompatibilities has been a central design goal of the Ada 9X
revision effort. However, in some cases, they are a necessary consequence of
changes to the semantics of existing language features, in order to correct
problems in Ada 83. In early 1992, the Ada 9X Mapping Team compiled a list of
incompatibilities [1] for the then existing Mapping Specification [2,3].
Since that time, refinements of the Mapping Specification have steadily
reduced the number of incompatibilities. Still, some incompatibilities will
remain.
In this article, we provide practical guidelines to Ada 83 programmers, so
that their Ada 83 code will be upward compatible with the Ada 9X standard.
The information presented in this paper is based on the current state (July
'92) of the revision proposal, which is widely regarded as fairly stable.
Nevertheless, it is work in progress, subject to change and all it implies for
the accuracy of the presented information.
While it is conceivable that additional incompatibilities will still be
discovered, it is reassuring to know that, since the time the cited list was
established, review of the Mapping has not revealed previously unknown
incompatibilities. Hence, adherence to the presented guidelines will help
significantly to reduce the effort of migrating to Ada 9X.
Moreover, we believe that these guidelines do not seriously constrain the use
of Ada 83; some of them could be regarded as good style guidelines in any
case. Even if continued work on Ada 9X eliminates some of the
incompatibilities, these guidelines will not have a detrimental effect on the
produced Ada code.
For ease of reference, we first enumerate the guidelines and then explain them
in more detail. We do not attempt to provide any comprehensive rationale for
the underlying language changes; for such information, we refer the reader to
[1] and its future revisions or replacements.
2. The Guidelines at a Glance
Most of the upward incompatibilities imply that some legal Ada 83 programs are
no longer legal in Ada 9X. Any Ada 9X compiler is guaranteed to identify and
reject all such incompatible situations, safeguarding users against
unrecognized changes in program behavior. However, there is also a very small
number of language changes that alter the meaning of Ada 83 programs while
retaining their legality when compiled with an Ada 9X compiler. Unless the
compiler issues friendly informational messages about such situations, these
changes could go unnoticed. They deserve special attention by the users.
Guidelines 2, 5, 9, and 12 address these particular situations.
The incompatibilities likely to be encountered with some frequency are
addressed by Guidelines 8, 10, and possibly 1.
For some of the guidelines, we have consciously preferred a simpler, more
memorable rule to a more precise, but also more complicated one. Guidelines 3
and 7 are examples, where a less encompassing rule would also suffice.
The guidelines for Ada 83 programs are:
1. Do not use the following Ada 9X keywords as Ada 83 identifiers in
your program: aliased, protected, requeue, tagged, until.
2. Do not declare the identifiers WIDE_STRING and WIDE_CHARACTER in
package specifications.
3. Do not apply use-clauses to package SYSTEM.
4. Do not declare the identifier APPEND_FILE in a package
specification. Alternatively, do not apply use-clauses to package
TEXT_IO and instantiations of SEQUENTIAL_IO.
5. For type CHARACTER, be prepared that the enumeration will comprise
256, rather than 128, literals. Similarly, for type FILE_MODE, be
prepared for the added literal APPEND_FILE.
6. Do not use accuracy constraints in subtype declarations.
7. Put representation clauses for real types immediately after the
type declaration.
8. All library unit packages must have bodies, even if such bodies
are empty.
9. Do not derive from a type declared in the same package. Or, if
you do, derive the new types before redefining any predefined
operations on the parent type.
10. Add a distinctive comment to all generic formal private types that
can be legally instantiated with unconstrained types.
11. Do not assume "too much" about the state of the computation when
exceptions are implicitly raised. Do not cause implicit
exceptions knowingly. Be prepared for the elimination of the
exception NUMERIC_ERROR.
12. Be prepared for attribute values of real types to more closely
reflect the actual hardware. Be aware that accuracy requirements
for operations combining fixed-point types with differently based
'SMALL may be lessened.
3. The Guidelines in Detail
Guideline 1:
Do not use the following Ada 9X keywords as Ada 83 identifiers in your
program: aliased, protected, requeue, tagged, until.
These reserved keywords have been added to Ada 9X. Clearly, programs
containing such identifiers will be rejected as syntactically illegal by any
Ada 9X compiler. See declaration (1) in Figure 1 for an example.
For existing programs, editor scripts can be easily written to check for the
absence of such identifiers. If they are present, consistent replacement with
a different identifier makes the code upward compatible. Note, however, that
the choice of a replacement identifier must not coincide with another name
already visible in any of the contexts, in which the conflicting identifier
occurs. A cross-reference listing of the program may greatly assist in
finding unique replacement identifiers.
------------------------------------------------------------------------------
| |
| |
| package PKG is |
| type WIDE_STRING is ....; |
| APPEND_FILE: INTEGER; |
| end PKG; |
| |
| with PKG; use PKG; |
| with TEXT_IO; use TEXT_IO; |
| package NAME_CONFLICTS is |
| |
| PROTECTED: BOOLEAN := true; -- (1) -- illegal in Ada 9X |
| -- 'protected' is now a keyword|
| |
| STR: WIDE_STRING; -- (2) -- in Ada 83, denotes PKG.WIDE_STRING |
| -- in Ada 9X, denotes STANDARD.WIDE_STRING|
| |
| X: INTEGER := APPEND_FILE; -- (3) |
| -- illegal in Ada 9X. Due to new presence |
| -- of name APPEND_FILE in TEXT_IO, the |
| -- name is no longer directly visible |
| |
| |
| end NAME_CONFLICTS; |
| |
| |
| Figure 1: Incompatibilities Caused by New Predefined Names and Keywords |
| |
------------------------------------------------------------------------------
Guideline 2:
Do not declare the identifiers WIDE_STRING and WIDE_CHARACTER in package
specifications.
These identifiers have been added to package STANDARD of Ada 9X. As a
consequence, user-defined names with the same identifier, when made directly
visible via use-clauses, will no longer denote the imported definitions but
those in package STANDARD. The rules of Ada give precedence to directly
visible names over names made directly visible by use-clauses. Theoretically,
the program will still be legal, but behave differently in execution. In
practice, however, it is likely that program illegalities will occur as a
consequence of the altered binding. See declaration (2) in Figure 1 for an
example.
For existing programs, the analysis and correction described for guideline 1
applies.
A secondary consequence of the appearance of the new types WIDE_CHARACTER and
WIDE_STRING for the support of international character sets is that operations
involving only character or string literals may become ambiguous, since the
operation could be for either the Ada 83 types or the new Ada 9X types. For
example, the equalities in
if 'a' = 'b' then ...
if "abc" = "def" then ...
are now ambiguous. The same applies, if the operands are overloaded function
calls that cannot be disambiguated by their parameters. Given that no
competent programmer would compare two string or character literals, this
situation is not worth a guideline. However, preprocessors might generate
such code. The solution is to type-qualify one of the arguments of the
expression. The appearance of a variable anywhere in the expression avoids
the ambiguity.
Guideline 3:
Do not apply use-clauses to package SYSTEM.
This is generally a good Ada 83 guideline, since implementors are free to add
additional declarations to package SYSTEM. Consequently, a new release of a
compiler may declare new names in the package, causing visibility conflicts or
ambiguities in code that already makes equally named declarations from other
packages directly visible via use-clauses. Ada 9X adds additional predefined
names in package SYSTEM and, hence, can cause this problem. Unlike the
situation discussed in Guideline 2, encountering this incompatibility will
make the Ada 83 program illegal in Ada 9X, since the Ada visibility rules will
then make the conflicting, non-overloadable declarations from neither package
directly visible. See Guideline 4 for an analogous problem and example.
Guideline 4:
Do not declare the identifier APPEND_FILE in a package specification.
Alternatively, do not apply use-clauses to package TEXT_IO and instantiations
of SEQUENTIAL_IO.
Ada 9X adds the enumeration literal APPEND_FILE to the FILE_MODE type in these
packages. As an additional name in a predefined package, this can create the
problems already described under Guideline 3. See declaration (3) in Figure 1
for an example.
For existing code, the remedies given under Guideline 1 apply.
Guideline 5:
For type CHARACTER, be prepared that the enumeration will comprise 256, rather
than 128, literals. Similarly, for type FILE_MODE, be prepared for the added
literal APPEND_FILE.
------------------------------------------------------------------------------
| |
| |
| if ASCII.DEL = CHARACTER'LAST then -- (1) |
| -- always true in Ada 83 (until recently -- see explanation)|
| -- always false in Ada 9X |
| |
| case CHAR is -- (2) |
| -- illegal in Ada 9X, since not all choices are covered |
| when CHARACTER'VAL(0) .. CHARACTER'VAL(63) => ...; |
| when CHARACTER'VAL(64) .. CHARACTER'VAL(127) => ...; |
| end case; |
| |
| subtype ASCII_CHARACTER is CHARACTER |
| range ASCII.NUL ... ASCII.DEL; -- (3) |
| |
| case ASCII_CHARACTER'(CHAR) is -- (4) |
| -- legal in both Ada 83 and Ada 9X |
| when CHARACTER'VAL(0) .. CHARACTER'VAL(63) => ...; |
| when CHARACTER'VAL(64) .. CHARACTER'VAL(127) => ...; |
| end case; |
| |
| case CHAR is -- (5) |
| -- legal in both Ada 83 and Ada 9X |
| when CHARACTER'VAL(0) .. CHARACTER'VAL(63) => ...; |
| when CHARACTER'VAL(64) .. CHARACTER'VAL(127) => ...; |
| when others => ... ; -- Ada 9X alternative |
| end case; |
| |
| type GOOD_CHAR_TABLE is array(CHARACTER) of INTEGER; |
| type BAD_CHAR_TABLE is array(0..127) of INTEGER; |
| GOOD_TT: GOOD_CHAR_TABLE; |
| BAD_TT: BAD_CHAR_TABLE; |
| |
| for CHR in GOOD_TT'RANGE loop |
| GOOD_TT(CHR) := ....; -- (6) |
| end loop; |
| |
| for CHR in CHARACTER'FIRST .. CHARACTER'LAST loop |
| BAD_TT(CHARACTER'POS(CHR)) := ....; -- (7) |
| end loop; |
| |
| |
| Figure 2: Examples of Character Set (In)compatibilities |
| |
------------------------------------------------------------------------------
These changes have two major consequences:
- The 'LAST attribute applied to type CHARACTER (or any of its
derived types) will yield a value with an encoding of 255 rather
than 127. See the example (1) in Figure 2. Similarly,
FILE_MODE'LAST will now yield APPEND_FILE. Whether this impacts
an algorithm, depends entirely on the programmer's assumptions.
If the assumption was to obtain truly the last character in the
enumeration, regardless of its encoding, the code will still
operate as intended. If the specific value is important, the
explicit literal (or a declared constant) should be used in lieu
of the attribute. An analogous reasoning applies to the 'RANGE
attribute applied to arrays with such index types or to any
implicit assumptions about the magnitude of the enumeration.
Examples (6) and (7) in Figure 2 show how Ada 83 code will (not)
be upward compatible. The loop (7) will result in a
CONSTRAINT_ERROR in Ada 9X, besides being poor style in Ada 83.
- Case statements over expressions of such types need to account for
the possible choices added by Ada 9X. Otherwise the statements
will be illegal in Ada 9X. Since a superfluous others or an empty
range choice is legal in Ada, case statements, whose choices do
not already cover all values permitted by Ada 9X should be written
with such an added choice. Alternatively, one can also qualify
the case expression with a static subtype, reflecting the Ada 83
range of types CHARACTER and FILE_MODE, respectively. Examples
(2) through (5) in Figure 2 illustrate the situation. The choice
of solution will depend on the circumstances. If the algorithm is
guaranteed to be applied only to the first 128 characters,
qualified expressions should be used, as shown by example (4).
Otherwise, the modification of example (5) should be applied after
giving thought to programming the Ada 9X branch of the case
statement. An addition of the form
when others => null;
is almost certainly the wrong solution.
ISO/IEC JTC1/SC22 WG9, the group chartered to issue interpretations of the
existing Ada standard, has recently voted to permit this definitional change
of type CHARACTER in Ada 83 implementations. Consequently, this problem could
already arise with the next release of an Ada 83 compiler, rather than with an
Ada 9X compiler, when the change becomes mandatory.
For existing programs, the necessary changes are somewhat problematic, since
they are not easily found by syntactic searches, nor is it easy to determine
whether or not the intent of the algorithms is affected by the language
change.
Fortunately, for the large class of programs that are intended and guaranteed
to deal only with the ASCII character set even after Ada 9X has been adopted,
there is a very simple guideline that prevents the incompatibility. Rather
than using the type CHARACTER, such programs should define a subtype of
CHARACTER, as shown in example (3) of figure 2, and consistently use this
subtype in lieu of type CHARACTER. In Ada 83, this subtype encompasses all
values of type CHARACTER; in Ada 9X, it will ensure the constraint to the
ASCII characters. None of the above compatibility problems arise. Similarly,
for existing such programs, a global substitution of CHARACTER by the subtype
name and the addition of suitable context-clauses to make the subtype name
visible renders the programs upward compatible with Ada 9X.
For type FILE_MODE, an analogous approach is complicated by the fact that
multiple instantiations of SEQUENTIAL_IO yield different such types. It is
probably easier to correct the few places in the code, where the expansion of
the enumeration type makes any difference.
Guideline 6:
Do not use accuracy constraints in subtype declarations.
Accuracy constraints in subtype declarations will be removed from the
language. It is surmised that all existing Ada implementations simply ignore
such subtype constraints, computing and storing results in the accuracy of the
respective type, anyhow.
In existing programs, such accuracy constraints should be removed. They can
be found via editor scripts or syntactic searches. In an example adapted from
the Ada Reference Manual [4],
type VOLT is delta 0.125 range 0.0 .. 255.0;
subtype ROUGH_VOLTAGE is VOLT delta 1.0 range 0.0 .. 100.0;
should be replaced with
type VOLT is delta 0.125 range 0.0 .. 255.0;
subtype ROUGH_VOLTAGE is VOLT range 0.0 .. 100.0;
Guideline 7:
Put representation clauses for real types immediately after the type
declaration.
Ada 9X solves an obscure problem in Ada 83 by mandating that such
representation clauses be given before any subtypes or derived types of the
given type are declared.
In existing programs, once the situation is identified, the correction is very
simple: merely move the representation clause to precede the subtype or
derived type declarations.
Guideline 8:
All library unit packages must have bodies, even if such bodies are empty.
Ada 83 allows the omission of packages bodies if none is needed to complete
the specification. A usage problem results, since library unit bodies that
are semantically optional, but vital to the functioning of the program, are
omitted from executables, when they happen to be obsolete. Ada 9X mandates
the existence of previously optional bodies for library units to eliminate
this usage problem. Users should therefore add such empty bodies, e.g.,
package body