HTTP/1.1 200 OK Date: Thu, 23 Aug 2012 08:46:58 GMT Server: Apache/2.2.21 (Unix) mod_ssl/2.2.21 OpenSSL/0.9.8e-fips-rhel5 mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635 mod_fcgid/2.3.5 X-Powered-By: PHP/5.2.17 Expires: Fri, 24 Aug 2012 00:00:00 GMT Cache-Control: no-cache, must-revalidate Pragma: no-cache Last-Modified: Tue, 21 Aug 2012 00:00:00 GMT Content-Length: 24371 Keep-Alive: timeout=5, max=99 Connection: Keep-Alive Content-Type: text/html;charset=windows-1251 Compatibility

Rationale for Ada 2005: 7. Epilogue

RUSTOP
BACKNEXT

ENG

1. Compatibility

@ There are two main sorts of problems regarding compatibility. These are termed Incompatibilities and Inconsistencies.

@ An incompatibility is a situation where a legal Ada 95 program is illegal in Ada 2005. These can be annoying but not a disaster since the compiler automatically detects such situations.

@ An inconsistency is where a legal Ada 95 program is also a legal Ada 2005 program but might have a different effect at execution time. These can in principle be really nasty but typically the program is actually wrong anyway (in the sense that it does not do what the programmer intended) or its behaviour depends upon the raising of a predefined exception (which is generally considered poor style) or the situation is extremely unlikely to occur.

@ As mentioned below in Section 2, during the development of Ada 2005 a number of corrections were made to Ada 95 and these resulted in some incompatibilities and inconsistencies with the original Ada 95 standard. These are not considered to be incompatibilities or inconsistencies between Ada 95 and Ada 2005 and so are not covered in this section.

1.1 Incompatibilities with Ada 95

@ Each incompatibility listed below gives the AI concerned and the paragraph in the AARM which in some cases will give more information. Where relevant, the section in this rationale where the topic is discussed is also given. Where appropriate the incompatibilities are grouped together. 1 – The words interface, overriding and synchronized are now reserved. Programs using them as identifiers will need to be changed. (AI-284, 2.9(3.c)) This is perhaps the most important incompatibility in terms of visibility to the average programmer. It is discussed in paper 1 section 2. 2 – If a predefined package has additional entities then incompatibilities can arise. Thus suppose the predefined package Ada.Stuff has an additional entity More added to it. Then if an Ada 95 program has a package P containing an entity More then a program with a use clause for both Ada.Stuff and P will become illegal in Ada 2005 because the reference to More will become ambiguous. This also applies if further overloadings of an existing entity are added.

@ Because of this there has been reluctance to extend existing packages but a preference to add child packages. Nevertheless in some cases extending a package seemed more appropriate especially if the identifiers concerned are unlikely to have been used by programmers.

@ The following packages have been extended with additional entities as listed.

@ Ada.Exceptions – Wide_Exception_Name, Wide_Wide_Exception_Name. (AI-400, 11.4.1(19.bb)) Ada.Real_Time – Seconds, Minutes. (AI-386, D.8(51.a)) Ada.Strings – Wide_Wide_Space. (AI-285, A.4.1(6.a)) Ada.Strings.Fixed – Index, Index_Non_Blank. (AI-301, A.4.3(109.a)) Ada.Strings.Bounded – Set_Bounded_String, Bounded_Slice, Index, Index_Non_Blank. (AI-301, A.4.4(106.f)) Ada.Strings.Unbounded – Set_Unbounded_String, Unbounded_Slice, Index, Index_Non_Blank. (AI-301, A.4.5(88.c)) There are similar additions to Ada.Strings.Wide_Fixed, Ada.Strings.Wide_Bounded and Ada.Strings.Wide_Unbounded. (AI-301, A.4.7(48.a)) Ada.Tags – No_Tag, Parent_Tag, Interface_Ancestor_Tags, Descendant_Tag, Is_Descendant_ At_Same_Level, Wide_Expanded_Name, Wide_Wide_Expanded_Name. (AI-260, 344, 400, 405, 3.9(33.d)) Ada.Text_IO – Get_Line. (AI-301, A.10.7(26.a)) Interfaces.C – char16_t, char32_t and related types and operations. (AI-285, B.3(84.a)) It seems unlikely that existing programs will be affected by these potential incompatibilities. 3 – If a subprogram has an access parameter (without a null exclusion) and is not a dispatching operation then it cannot be renamed as a dispatching operation in Ada 2005 although it can be so renamed in Ada 95. See paper 2, section 2 for an example. (AI-404, 3.9.2(24.b)) 4 – As discussed in paper 2 section 5, there are many awkward situations in Ada 95 regarding access types, discriminants and constraints. One problem is that some components can change shape or disappear. The rules in Ada generally aim to prevent such components from being accessed or renamed. However, in Ada 95, some entities don't look constrained but actually are constrained. The consequence is that it is difficult to prevent some constrained objects from having their constraints changed and this can cause components to change or disappear even though they might be accessed or renamed.

@ A key rule in Ada 95 was that aliased variables were always constrained with the intent that that would solve the problems. But loopholes remained and so the rules have been changed considerably. Aliased variables are not necessarily constrained in Ada 2005 and other rules now disallow certain constructions that were permitted in Ada 95 and this gives rise to a number of minor incompatibilities.

@ If a general access subtype refers to a type with default discriminants then that access subtype cannot have constraints in Ada 2005. Consider

  1        type T (Disc : Boolean := False) is
  2                record
  3                        ...
  4                end record;

@ The discriminated type T has a default and so unconstrained objects of type T are mutable. Suppose we now have

  1        type T_Ptr is access all T;
  2        subtype Sub_True_T_Ptr is T_Ptr (Disc => True); -- subtype illegal in Ada 2005

@ The type T_Ptr is legal in both Ada 95 and Ada 2005 of course, but the subtype Sub_True_T_Ptr is only legal in Ada 95 and not in Ada 2005. The reason why the subtype cannot be permitted is illustrated by the following

  1        Some_T : aliased T := (Disc => True, ...);
  2        A_True_T : Sub_True_T_Ptr := Some_T'Access;
  3        ...
  4        Some_T := (Disc => False, ...);

@ When Some_T'Access is evaluated there is a check that the discriminant has the correct value so that A_True_T is assigned a valid value. But the second assignment to Some_T means that the discriminant changes and so A_True_T would no longer have a valid value.

@ In Ada 95, all aliased variables were considered constrained and so the second assignment would not have been permitted anyway. But, as mentioned above, aliased variables are not considered to be constrained in Ada 2005 just because they are aliased.

@ Note that there is no similar restriction on types; thus we can still write

  1        type True_T_Ptr is access all T(Disc => True);

@ because any conversion which might cause difficulties is forbidden as explained in one of the examples below.

@ The restriction on subtypes does not apply if the discriminants do not have defaults, nor to pool-specific types. (AI-363, 3.7.1(15.c)) Since aliased variables are not necessarily constrained in Ada 2005 there are situations where components might change shape or disappear in Ada 2005 that could not happen in Ada 95. Applying the Access attribute to such components is thus illegal in Ada 2005. Suppose the example above has components as follows

  1        type T (Disc : Boolean := False) is
  2                record
  3                        case Disc is
  4                                when False => Comp: aliased Integer;
  5                                when True  => null;
  6                        end case;
  7                end record;

@ Since objects of type T might be mutable, the component Comp might disappear.

  1        type Int_Ptr is access all Integer;
  2        Obj : aliased T; -- mutable object
  3        Dodgy : Int_Ptr := Obj.Comp'Access; -- take care
  4        ...
  5        Obj := (Disc => True); -- Comp gone

@ In Ada 95, the assignment to Dodgy is permitted but then the assignment to Obj raises Constraint_Error because there might be dodgy pointers.

@ In Ada 2005, the assignment statement to Dodgy is illegal since we cannot write Obj.Comp'Access. The assignment to Obj is itself permitted because we now know that there cannot be any dodgy pointers.

@ See (AI-363, 3.10.2(41.b)). Similarly, renaming an aliased component such as Comp is also illegal. (AI-363, 8.5.1(8.b)) There are related situations regarding discriminated private types where type conversions and the Access attribute are forbidden. Suppose we have a private type and an access type and that the full type is in fact the discriminated type above thus

  1        package P is type T is private;
  2                type T_Ptr is access all T;
  3                function Evil return T_Ptr;
  4                function Flip (Obj : T) return T;
  5                private type T (Disc : Boolean := False) is
  6                        record
  7                                ...
  8                        end record;
  9                ...
 10        end P;
 11        package body P is
 12                type True_T_Ptr is access all T (Disc => True);
 13                subtype Sub_True_T_Ptr is T_Ptr (Disc => True); -- legal in Ada 95, illegal in Ada 2005
 14                True_Obj : aliased T (Disc => True);
 15                TTP : True_T_Ptr := True_Obj'Access;
 16                STTP : Sub_True_T_Ptr := True_Obj'Access;
 17                function Evil return T_Ptr is
 18                begin
 19                        if ... then
 20                                return T_Ptr (TTP); -- OK in 95, not in 2005
 21                        elsif ... then
 22                                return True_Obj'Access; -- OK in 95, not in 2005
 23                        else
 24                                return STTP;
 25                        end if;
 26                end Evil;
 27                function Flip (Obj : T) return T is
 28                begin
 29                        case Obj.Disc is
 30                                when True  => return (Disc => False, ...);
 31                                when False => return (Disc => True, ...);
 32                        end case;
 33                end Flip;
 34        end P;

@ The function Evil has three branches illustrating various possible ways of returning a value of the type T. The function Flip just returns a value of the type T with opposite discriminants to the parameter. Now consider

  1        with P; use P;
  2        procedure Do_It is
  3                A : T;
  4                B : T_Ptr := new T;
  5                C : T_Ptr := Evil;
  6        begin
  7                A := Flip (A);
  8                B.all := Flip (B.all);
  9                C.all := Flip (C.all);
 10        end Do_It;

@ This declares an object A of type T and then two objects B and C of the access type T_Ptr and initializes them in different ways. Finally it attempts to change the discriminant of the three objects by calling the function Flip.

@ In Ada 95 all objects on the heap are constrained. This means that clients cannot change the discriminants even if they do not know that they exist. So the assignment to B.all raises Constraint_Error since B.all is on the heap and thus constrained whereas the assignment to A is fine since A is not constrained. However, from the client's point of view they both really do the same thing and so the behaviour is very curious. Remember that the client doesn't know about the discriminants and so both operations look the same in the abstract. This is unfortunate and breaks privacy which is sinful. There is a similar example in paper 2, section 5 where we try to change Chris but do not know that the new value has a beard and this fails because Chris is female.

@ To prevent such privacy breaking the rules are changed in Ada 2005 so that objects on the heap are unconstrained in this one case. So the assignments to B.all and C.all do not have checks on the discriminant. As a consequence Evil must not return an object which is constrained otherwise the assignment to C would result in True_Obj having its discriminant turned to False.

@ All three possible branches in Evil are prevented in Ada 2005. The conversion in the first branch is forbidden and the Access attribute in the second branch is forbidden. In the case of the third branch the return itself is acceptable in principle because STTP is of the correct type. However, this is prevented by the rule mentioned above since the subtype Sub_True_T_Ptr is itself forbidden and so the object STTP could not be declared in the first place.

@ See (AI-363, 3.10.2(41.e) and 4.6(71.k)). 5 – Aggregates of limited types are permitted in Ada 2005 as discussed in paper 3, section 5. This means that in obscure situations an aggregate might be ambiguous in Ada 2005 and thus illegal. Consider

  1        type Lim is limited
  2                record
  3                        Comp : Integer;
  4                end record;
  5        type Not_Lim is
  6                record
  7                        Comp : Integer;
  8                end record;
  9        procedure P (X : LIm);
 10        procedure P (X : Not_Lim);
 11        P ((Comp => 123)); -- illegal in Ada 2005

@ In Ada 95, the aggregate cannot be of a limited type and so the type Lim is not considered for resolution. But Ada 2005 permits aggregates of limited types and so the aggregate is ambiguous. (AI-287, 4.3(6.e)) Another similar situation with limited types and nonlimited types concerns assignment. Again this relates to the fact that limitedness is no longer considered for name resolution. Consider

  1        type Acc_Not_Lim is access Not_Lim;
  2        function F (X : Integer) return Acc_Not_Lim;
  3        type Acc_Lim is access Lim;
  4        function F (X : Integer) return Acc_Lim;
  5        F (1).all := F (2).all; -- illegal in Ada 2005

@ In Ada 95, only the first F is considered for name resolution and the program is valid. In Ada 2005, there is an ambiguity because both functions are considered. Note of course that the assignment for the limited function is still illegal anyway but the compiler meets the ambiguity first. Clearly this is an obscure situation. (AI-287. 5.2(28.d)) 6 – Because of the changes to the fixed-fixed multiplication and division rules there are situations where a legal program in Ada 95 becomes illegal in Ada 2005. Consider

  1        package P is
  2                type My_Fixed is delta ... ;
  3                function "*" (L, R : My_Fixed) return My_Fixed;
  4        end P;
  5        use P;
  6        A, B : My_Fixed;
  7        D : Duration := A * B; -- illegal in Ada 2005

@ Although this is legal in Ada 95, the new rule in Ada 2005 says that if there is a user-defined operation involving the type concerned then the predefined operation cannot be used unless there is a type conversion or we write Standard."*"( ... ).

@ So in Ada 2005 a conversion can be used thus

  1        D: Duration := Duration(A * B);

@ See paper 5, section 3. (AI-364, 4.5.5(35.d)) 7 – The concept of return by reference types has gone. Instead the user has to explicitly declare a function with an anonymous access type as the return type. This only affects functions that return an existing limited object such as choosing a task from among a pool of tasks. See paper 3 section 5 for an example. (AI-318, 6.5(27.g)) 8 – There is a very curious situation regarding exporting multiple homographs from an instantiation that is now illegal. This is a side effect of adding interfaces to the language. (AI-251, 8.3(29.s)) 9 – The introduction of more forms of access types has changed the rules regarding name resolution. Consider the following contrived example

  1        type Cacc is access constant Integer;
  2        procedure Proc (Acc : access Integer);
  3        procedure Proc (Acc : Cacc);
  4        List : Cacc := ... ;
  5        ...
  6        Proc (List); -- illegal in Ada 2005

@ In Ada 95 the call of Proc is resolved because the parameters Acc are anonymous access to variable in one case and access to constant in the other. In Ada 2005, the name resolution rules do not take this into account so it becomes ambiguous and thus illegal which is a good thing because it is likely that the Ada 95 programmer made a mistake anyway. (AI-409, 8.6(34.n)) 10 – In Ada 2005, a procedure call that might be an entry is permitted in timed and conditional entry calls. See paper 4, section 3. In Ada 95, a procedure could not be so used and this fact is used in name resolution in Ada 95 but does not apply in Ada 2005. Hence if a procedure and an entry have the same profile then an ambiguity can exist in Ada 2005. (AI-345, 9.7.2(7.b)) 11 – It is now illegal to have an allocator for an access type with Storage_Size equal to zero whereas in Ada 95 it raised Storage_Error on execution. It is always better to detect errors at compile time wherever possible. The reason for the change is to allow Pure units to use access types provided they do not use allocators. If the storage size is zero then this is now known at compile time. (AI-366, 4.8(20.g)) 12 – The requirement that a partial view with available stream attributes be externally streamable can cause an incompatibility in extremely rare cases. This also relates to pragma Pure. (AI-366, 10.2.1(28.e)) 13 – It is now illegal to use an incomplete view as a parameter or result of an access to subprogram type or as an access parameter of a primitive operation if the completion is deferred to the package body. See paper 3, section 2 for examples. (AI-326, 3.10.1(23.h, i)) 14 – The specification of System.RPC can now be tailored for an implementation by adding further operations or by changing the profile of existing operations. If it is tailored in this way then an existing program might not compile in Ada 2005. See paper 6, section 7. (AI-273, E.5(30.a))

. .