From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.5-pre1 (2020-06-20) on ip-172-31-74-118.ec2.internal X-Spam-Level: X-Spam-Status: No, score=-1.9 required=3.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.5-pre1 Date: 1 Sep 93 16:43:28 GMT From: dog.ee.lbl.gov!network.ucsd.edu!news.cerf.net!shrike.irvine.com!adam@ucbv ax.Berkeley.EDU (Adam Beneschan) Subject: Re: Unchecked_Conversion question Message-ID: List-Id: In article <1993Sep1.154715.10498@Rapnet.Sanders.Lockheed.Com> lvonrude@Rapnet. Sanders.Lockheed.Com (Lowell S. VonRuden x5294) writes: > I am doing something that seems to work using a Verdix compiler, but I > have not been able to determine if this is something that will be safely > transportable. Hopefully, someone here can tell me. > > I have a 32 bit value coming in from an external interface as an > integer, which I am mapping to an enumeration type. The enumeration > type has representation clauses for both size (Integer'Size) and > implementation values. Assigning the result of an unchecked conversion > from the integer to an object of the enumeration type doesn't raise any > exception if the integer is out of range for the enumeration type > representation. I found that if I do an explicit conversion of the > enumeration object to its type, then the range gets checked. > > procedure Sample (Int : Integer) is > > type Enum is (AAA, BBB, CCC, DDD); > for Enum use (AAA=> 1, > BBB=> 2, > CCC=> 13, > DDD=> 14); > for Enum'Size use Integer'Size; > > function Convert is new Unchecked_Conversion (Source => Integer, > Target => Enum); > begin > > E := Convert (Int); -- no exception raised here if Int is out of range > > E := Enum (Convert (Int)); -- this does raise constraint error if > -- Int is out of range > > end Sample; > > > So, is this a dependable thing to do? I don't think so. In fact, I'm surprised that your two statements generate different code at all. After all, Convert is a function that returns an Enum, so saying Enum(X) as a type conversion should be a no-op. I would guess that many compilers would recognize this, and not generate any constraint checking code when "converting" an object to an object of the exact same type. I don't such a check is required by the LRM, either. I believe that if you say X : Enum; ... ... Enum(X) ... the compiler is allowed to assume that "X" contains a valid Enum value, and therefore the compiler can determine that no range check is required. Similarly: type Int10 is range 1..10; type Int20 is range 1..20; X : Int10; Y : Int20; ... Y := Int20 (X); The compiler can assume that X is in the range 1..10, and therefore no checking is required to convert it to an Int20. If X happens to have an out-of-range value (due to lack of initialization, data overlays, or other tricks), tough luck. I may have my facts wrong, but I believe there's an AI that relates to this issue. Somebody please correct me if I'm wrong. Anyway, if you want a more dependable version, try this: procedure Sample (Int : Integer) is type Enum is (AAA, BBB, CCC, DDD); for Enum use (AAA=> 1, BBB=> 2, CCC=> 13, DDD=> 14); for Enum'Size use Integer'Size; function Convert is new Unchecked_Conversion (Source => Integer, Target => Enum); function Convert_To_Integer is new Unchecked_Conversion (Source => Enum, Target => Integer); Enum_Low : constant Integer := Convert_To_Integer (Enum'first); Enum_High : constant Integer := Convert_To_Integer (Enum'last); begin if Int not in Enum_Low .. Enum_High then raise Constraint_Error; -- or whatever end if; E := Convert (Int); end Sample; Or, if you want to make sure that Int is a valid Enum: Valid := False; for E in Enum loop if Int = Convert_To_Integer (E) then Valid := True; exit; end if; end loop; if not Valid then raise Constraint_Error; end if; -- Adam