!standard RM-4.6 (47) 00-01-25 AI95-00097/07 !class confirmation 95-09-29 !status Response 2000 00-01-25 !status WG9 approved 96-12-07 !status ARG approved 10-0-2 96-10-07 !status ARG approved 6-1-1 (subject to editorial review) 96-06-17 !status work item 95-11-01 !status received 95-09-29 !priority High !difficulty Medium !qualifier Omission !subject Conversions between access types with different representations. !summary If the Convention (other than Ada) of an access type has been specified by the user, then the semantics of type conversions involving that access type are implementation defined. !question It is possible to declare types that are normally convertible, but that have a pragma Convention that makes some such conversions impossible or impractical. For instance, type Ada_Ptr is access Integer; -- Integer is C-compatible in this -- implementation. type C_Ptr is new Ada_Ptr; pragma Convention (C, C_Ptr); The value sets of such convertible types may not completely overlap. For example, on a machine that is not 8-bit-byte addressable, an Ada_Ptr might be represented as a normal address, whereas a C_Ptr might be represented as a bit-field pointer of some sort. What should happen when a value of C_Ptr has no corresponding value in Ada_Ptr? !response The semantics of such conversions are implementation defined. This follows from the fact that pragma Convention is a representation pragma (B.1(29)), and implementations can interpret representation pragmas however they want and place restrictions on them (13.1(20)), except when there are explicit rules to the contrary. This is also stated in the NOTE of B.1(43). So it's perfectly acceptable to raise an exception when a given operation doesn't make sense. This is clearly desirable, since the goal of interfacing to another language is to match the representations chosen by the implementation of the other language, and doing so can make it impossible or impractical to obey the "normal" (non-interfaced) Ada semantics. !ACATS test No test is possible. This AI gives a permission for implementation-defined semantics, which of course cannot be tested in a portable way. !appendix !section RM-4.6(47) !subject Conversions between access types with different representations. !reference RM95-4.6(47-50) !reference RM95-B.1(12-20) !from Randy Brukardt 95-09-19 !reference as: 95-5302.a rbrukardt@BIX.com 95-9-19>> !discussion The introduction of the Convention pragma makes it possible, and in some cases necessary, for an implementation to support multiple representations for access types. Two examples are the long/short pointers of the 8086, and the many different kinds of pointer found on the Unisys 2200s. It is possible to declare types such that the compiler will generate the needed conversions between them. For instance, Type Ada_Ptr Is Access Integer; -- Integer is C-compatible in this -- implementation. Type C_Ptr Is New Ada_Ptr; Pragma Convention (C, C_Ptr); The value sets of such convertable types may not completely overlap. What should happen when a value of C_Ptr has no corresponding value in Ada_Ptr? That is, given: A : A_Ptr; C : C_Ptr; C := C_Malloc(10); A := Ada_Ptr(C); -- What happens here if A cannot point at what C points at? The answers seem to be: 1) Constraint_Error. But 4.6(47-50) does not given any permission to raise Constraint_Error on a access type conversion. 2) Program_Error. However, the program is not erroneous (the value of C is initialized, and is a valid value of that type). Using A after the conversion would be erroneous, but the conversion itself seems to be legal. 3) No error can be raised. That means the value of A will not access the same object as C. It is likely to be much harder to detect the error afterwards, and seems to be counter to the Ada philosophy to ignore an easily checked error. 4) The conversion is illegal because the type declarations are illegal. This would mean that there would be no way within Ada to convert between various access representations. A series of unchecked_conversions and implementation-defined functions would have to be used, damaging portability and making code much harder to read. (Side note: Of course, all such errors cannot be cheaply detected. However many such errors can be cheaply detected, and a compiler that wants to do so certainly should be allowed to do so.) In the specific case of the Unisys 2200 compiler, we are using different representations for access types and C pointer simply because the C pointers are expensive, since they have to be able to point into the middle of a word. (Characters are packed 4 to a word on this machine; C of course must be able to point at an individual character; Ada does not need this capability). While this sort of conversion is not common, it does happen in practice. For instance, the default storage pool is written in C; the returned pointers are known to be aligned (at least, they are supported to be aligned!), and need to be converted into the Ada representation. For the moment, we are raising Program_Error; the check can be suppressed if need be. **************************************************************** !section 4.6(47) !subject Conversions between access types with different representations. !reference RM95-4.6(47-50) !reference RM95-B.1(12-20) !reference 95-5302.a rbrukardt@BIX.com 95-9-19 !from Bob Duff !reference as: 95-5308.a Robert A Duff 95-9-29>> !discussion > It is possible to declare types such that the compiler will generate the > needed conversions between them. For instance, > > Type Ada_Ptr Is Access Integer; -- Integer is C-compatible in this > -- implementation. > Type C_Ptr Is New Ada_Ptr; > Pragma Convention (C, C_Ptr); > > The value sets of such convertable types may not completely overlap. > > What should happen when a value of C_Ptr has no corresponding value in Ada_Ptr? It seems to me that this is implementation defined. This follows from the fact that pragma Convention is a representation pragma (RM95-B.1(29)), and implementations can interpret representation pragmas however they want and place restrictions on them (13.1(20)), except when there are explicit rules to the contrary. This is also stated in the NOTE of B.1(43). So, I think it's perfectly acceptable to raise an exception when a given operation doesn't make sense. I suggest that in the case you mention, you raise Program_Error. - Bob ****************************************************************