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. 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.
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
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 <name> is end <name>;
in the source files after the package specification.
For existing programs, simple Ada library queries provide the necessary
information to produce these bodies.
Guideline 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.
package DERIVATIONS is
type BYTE is array (0..7) of BOOLEAN;
function "and"(L,R: BYTE) return BYTE;
redefine "and" for whatever reason
type CHAR is new BYTE;
in Ada 83, this type inherits the predefined "and"
in Ada 9X, this type inherits the redefined "and" of Byte
end DERIVATIONS;
Figure 3: Inheritance of Operations for Derived Types
In Ada 83, subprograms become derivable only at the end of the visible part of
the package in which the type is declared. In Ada 9X, they are immediately derivable.
As shown in Figure 3, a sequence of declarations, interspersing redefinitions of
pre defined operations with derived type declarations yields different definitions
of these operations for the derived type. The guideline avoids this situation,
which has surprised many first time Ada users. (Note that deriving from a
derived type in the same package is already illegal in Ada 83. The situation
therefore arises only if the parent type is declared by means of a type definition.)
In existing programs, these situations can best be identified by searching for
redefinitions of pre defined operations, which should be relatively rare, and
inspecting the context of these redefinitions for subsequent derived type
declarations. If such situations are found, a simple reordering of the
declarations makes the programs upward compatible.
Guideline 10:
Add a distinctive comment to all generic formal private types that can be legally
instantiated with unconstrained types. In Ada 83, the instantiation of a generic
with an unconstrained type can be illegal, depending on the use of the type in
the generic unit, e.g., in an object declaration. In Ada 9X, this instantiation
will always be illegal, unless the formal type is identified as one that can be
instantiated with an unconstrained type (in which case, the instantiation will
always be legal, and the generic must not contain conflicting uses of the type).
Ada 9X uses the box notation for this purpose. See Figure 4 for an example.
The legality of the instantiation (1) will depend on the use of type X in the
body of 'Ada_83'.
This is the single instance, where Ada 83 code cannot be written to be upward
compatible with Ada 9X. Consequently, we recommend the use of a distinctive
comment convention, as shown at the beginning of the example, so that, upon
transition to Ada 9X, the necessary source changes are easily located and made.
generic
type X is private; Ada 9X: add (<>)
procedure Ada_83;
type SHORT_STRING is new STRING(1..8);
procedure GOOD_ONE is new Ada_83(SHORT_STRING);
procedure DUBIOUS_ONE is new Ada_83(STRING);
may be illegal in Ada 83, depending on generic body in Ada_83
will always be illegal in Ada 9X
generic
type X(<>) is private; Ada 9X notation; illegal in Ada 83
procedure Ada_9X;
procedure BETTER_ONE is new Ada_9X(STRING); always legal
Figure 4: Instantiations with Unconstrained Types
For existing programs, there is a mechanical method of establishing whether or
not such a comment should be added: Identify all generic units with formal
private types and instantiate them with unconstrained types. All such
instantiations not rejected by the Ada 83 compilation system (possibly at link
time) are candidates to be commented as indicated.
Guideline 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.
Software engineers generally agree that knowingly utilizing implicitly raised
exceptions as a control flow mechanism is a highly dubious practice. The
interpretation of Ada 83 regarding the execution order in the presence of
implicitly raised exceptions is far from clear. Efficient support of RISC,
pipe lined, super scalar, and massively parallel architectures makes it
necessary to deviate from a purely sequential execution model. Ada 9X is
likely to better codify permission for such support by compilers.
Consequently, users should not rely in their algorithms on the specific point
in the sequential execution order where an implicit exception may get raised.
A good, although over conservative, guideline is to assume that, in any exception
frame, the raising of implicit exceptions may occur as early as the beginning of
the frame or as late as the end of the frame, regardless of where the exception
occurs in the sequential execution order.
This guideline applies already to Ada 83 code, regardless of Ada 9X. Yet, it
will avoid additional surprises when upgrading the code to Ada 9X.
In some situations, where Ada 83 mandates the raising of CONSTRAINT_ERROR, the
semantics of Ada 9X will cause the "expected" result, rather than an exception.
Since all these (three) cases are at the fringes of the language usage, and since
programmers should not cause CONSTRAINT_ERROR intentionally, they are not worth a
guideline.
Ada 9X is very likely to eliminate the exception NUMERIC_ERROR from the language
definition. An official Ada 83 interpretation advises non bindingly that Ada 83
implementations should use CONSTRAINT_ERROR instead of NUMERIC_ERROR. Users
whose compilers already adhere to this interpretation, should cease to reference
NUMERIC_ERROR. In existing programs, the name should be deleted from exception
choices or replaced by CONSTRAINT_ERROR, as appropriate. For users, whose
Ada 83 compilers do not adhere to this non binding interpretation, the situation
is more difficult. It would be best to apply the above source modification at
the time of transition to Ada 9X. (There is an upward compatible alternative
described in [1], involving the introduction of a superfluous user defined
NUMERIC_ERROR exception in a separate package to be imported into all contexts
that reference NUMERIC_ERROR. However, we hesitate to recommend this approach,
since it certainly is confusing to the reader of the program.)
Guideline 12 (Numerics):
Be prepared for attribute values of real types to more closely reflect the actual
type representation. Be aware that accuracy requirements for operations combining
fixed point types with differently based 'SMALL may be lessened.
For the casual user of real types, these language changes are most unlikely to
have any impact. In particular, users of the predefined floating point types
should have no problems in upgrading to Ada 9X. For numeric applications that
parameterize algorithms by means of real type attributes, however, the changes
to attribute values may have some effect, albeit a positive one, since such
applications are presumably interested in more accurate attribute values.
(For example, it is proposed that the attribute 'SMALL return the actual
smallest representation increment, rather than the increment between model
numbers.) Such code is typically written by numerical analysts, who as a group
have requested these changes to be made to Ada 83. The reduced accuracy
requirements for operations combining fixed point types with differently based
scales is unlikely to have any significant impact, because such operations are
exceedingly rare. Also, many Ada 83 compilers support only binary and decimal
'SMALLs, thereby making it rather unlikely that existing code applies such
operations and rely on the accuracy required in Ada 83.