From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,45a9122ddf5fcf5 X-Google-Attributes: gid103376,public From: bobduff@world.std.com (Robert A Duff) Subject: Re: Rules for Representation of Subtypes Date: 1996/09/30 Message-ID: #1/1 X-Deja-AN: 186287742 references: <1996Sep26.191257.1@eisner> <52hnvh$li0@wdl1.wdl.lmco.com> organization: The World Public Access UNIX, Brookline, MA newsgroups: comp.lang.ada Date: 1996-09-30T00:00:00+00:00 List-Id: In article <52hnvh$li0@wdl1.wdl.lmco.com>, Mark A Biggar wrote: >I'm not sure about this as I always thought that the RM was pretty clear >that only the USE of an abnormal value was erroneous, but that simply >assigning it was safe, at least I'm sure that was the intent, otherwise >X'VALID after an unchecked conversion is useless, but that is one of the >explisit examples of its intended use in the RM. Well, assignment is a USE -- you can't assign from an abnormal object without going erroneous. But that's beside the point -- the case I was talking about is defined as erroneous, not as abnormal. 13.9.1(12) says: 12 {erroneous execution} A call to an imported function or an instance of Unchecked_Conversion is erroneous if the result is scalar, and the result object has an invalid representation. The AARM gives an example: 12.c Consider the following example: 12.d type My_Int is range 0..99; function Safe_Convert is new Unchecked_Conversion(My_Int, Integer); function Unsafe_Convert is new Unchecked_Conversion(My_Int, Positiv\ e); X : Positive := Safe_Convert(0); -- Raises Constraint_Error. Y : Positive := Unsafe_Convert(0); -- Erroneous. 12.e The call to Unsafe_Convert causes erroneous execution. The call to Safe_Convert is not erroneous. The result object is an object of subtype Integer containing the value 0. The assignment to X is required to do a constraint check; the fact that the conversion is unchecked does not obviate the need for subsequent checks required by the language rules. The point is that you should convert to a type that "fills all the bits". That is, there are no possible bit patterns that don't represent valid data. Then, *after* the unchecked conversion, you can do an assignment that does a constraint check. Checking Y'Valid in the above example would not help, since the program is already erroneous. The 'Valid feature is just like anything else -- it won't work as advertised if the execution is already erroneous. Or you can use an if statement: Z: Integer := Safe_Convert(0); ... if Z not in My_Int then raise Horrible_Bug; The same applies to imported functions. So, for example, if you have a C function that returns 'int', and the documentation says this 'int' will be in the range 1..10, it's best to use Interfaces.C.int as the result subtype, and do some checking *after* it returns. This is because Interfaces.C.int matches the type 'int' in C. Unless you really, really trust that documentation. - Bob