comp.lang.ada
 help / color / mirror / Atom feed
* Re: Unchecked_Conversion question
@ 1993-09-04  0:13 Robert Dewar
  0 siblings, 0 replies; 10+ messages in thread
From: Robert Dewar @ 1993-09-04  0:13 UTC (permalink / raw)


Wes makes an incorrect assumption that a compiler is not free to assume
that the output of unchecked conversion is valid. Since a program execution
is erroneous if the value is not valid, the compiler is free to do anything
it wants in this case, and in particular it can skip the check which seems
to be otherwise required.

It is this same freedom which allows A:= B to skip a check if A and B
are the same subtype. The check is required by the RM even in the case
of the values being the same subtype (that's because the value of B is
just a value of the base type, and assignment to A always requires a 
check that the value of the base type meets its constraints).

The only case however if the subtypes are the same, where the check could
really be needed is if B is uninitialized, but then the program is erroneous
anyway, so the compiler can omit the check (and most all compilers do in this
case, maybe all).

Ada 9X cleans up a lot of these issues with its introduction of the notion of
a bounded error. This is an error which is not necesssarily detected, but 
unlike the erronoues case, there are a limited set of consequences.

^ permalink raw reply	[flat|nested] 10+ messages in thread
* Re: Unchecked_Conversion question
@ 1993-09-03 21:55 Robert Parkhill
  0 siblings, 0 replies; 10+ messages in thread
From: Robert Parkhill @ 1993-09-03 21:55 UTC (permalink / raw)


adam@irvine.com (Adam Beneschan) writes:
> In article <2684k7$2hc@sun_tzu.sp.paramax.com> parkhill@sun_tzu.sp.paramax.co
m (Robert Parkhill) writes:
> 
> >   adam@irvine.com (Adam Beneschan) writes:
> >   > In article <1993Sep1.154715.10498@Rapnet.Sanders.Lockheed.Com> lvonrude
@Rapnet.Sanders.Lockheed.Com (Lowell S. VonRuden x5294) writes:
> >
> >   To it asking whether an enum was between the first legal value
> >   and the last legal value was like asking if an integer object
> >   had a value between integer'First and integer'Last.  The answer
> >   was always yes. 
> 
> Yes, that was my point exactly. Which is why I DIDN'T ask whether an
> enumeration was between the first legal value and the last legal value.  In
> my example above, Int is still an integer;  it hasn't been converted
> to an enumeration yet.  My point, and Tucker's also, was that the
> checking should be done on the *integer* before it's converted.
> 
>                                 -- Adam

Pardon Me. I obviously did not read the code carefully. :(


>    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;


I would not have used the "in" construct because there are holes
in the data (You or someone else may already have said this).
On many systems it is not enough to check whether it doesn't hit
the high or low bound.  You must check whether it it not one of
the four and only four values. So as you have stated I would have
checked the integer value to see that it was or was not 1,2,13,14.
This would be done differently depending upon the size of the field
holding the value (lookup table, if's, etc) and how easy it was to
access the field.  Meaning some old machines have weird allignment
for example:

bits 29 27 26 26 25 24 23 ... 0

          |              | five bit field to hold value.

We interface with hardware with only 30 bits with the top 2 on
our 32 bit system being noise..

^ permalink raw reply	[flat|nested] 10+ messages in thread
* Re: Unchecked_Conversion question
@ 1993-09-03 20:14 Wes Groleau x1240 C73-8
  0 siblings, 0 replies; 10+ messages in thread
From: Wes Groleau x1240 C73-8 @ 1993-09-03 20:14 UTC (permalink / raw)


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.

>   [unchecked conversion does not raise constraint_error, but type conversion
>   does.]

LRM requires type conversions to do constraint checks.  This could
understandably (IMHO) be skipped if the compiler could be certain that the
check is guaranteed to pass.  Obviously, there is no such guarantee for the
output of an unchecked conversion.  If you are using the type conversion to
force the constraint check, I would say that putting  both conversions together
would guarantee that a compliant compiler would do the check at one point or
another.  If you'd like me to try it on VAX Ada, Janus (PC) Ada, Telesoft, or
GNAT, send me enough source code...

A warning about unchecked conversion with Verdix.  We have demonstrated in at
least one case on my current project that an out-of-range value did NOT raise
constraint error when it was assigned to an object.  Although we contended that
LRM 5.2(3) required the constraint check, Verdix claimed that since the value
came from an unchecked conversion (if you traced the logic back to a separately
compiled subprogram) LRM 13.10.2(3) says no check is required.

Wes Groleau

^ permalink raw reply	[flat|nested] 10+ messages in thread
* Re: Unchecked_Conversion question
@ 1993-09-03 19:51 dog.ee.lbl.gov!agate!howland.reston.ans.net!spool.mu.edu!sdd.hp.com!netwo
  0 siblings, 0 replies; 10+ messages in thread
From: dog.ee.lbl.gov!agate!howland.reston.ans.net!spool.mu.edu!sdd.hp.com!netwo @ 1993-09-03 19:51 UTC (permalink / raw)


In article <2684k7$2hc@sun_tzu.sp.paramax.com> parkhill@sun_tzu.sp.paramax.com 
(Robert Parkhill) writes:

>   adam@irvine.com (Adam Beneschan) writes:
>   > In article <1993Sep1.154715.10498@Rapnet.Sanders.Lockheed.Com> lvonrude@R
apnet.Sanders.Lockheed.Com (Lowell S. VonRuden x5294) writes:
>   > 
>   > Anyway, if you want a more dependable version, try this:
>   > 
>     -- Deleted text
>   > 
>   >     if Int not in Enum_Low .. Enum_High then
>   >       raise Constraint_Error;   -- or whatever
>   >     end if;
>   >     E := Convert (Int);  
>   > 
>   >   end Sample;
>
>
>   I would not count on this being dependable, please refer to Tucker
>   Taft's post.  I can tell you that people I have worked with tried
>   this with the TeleSoft Ada compiler and found there code optimized
>   away.  The compiler assumed that anything it does is correct and
>   therefore it need not check for things that are obviously true. ;)
>
>   To it asking whether an enum was between the first legal value
>   and the last legal value was like asking if an integer object
>   had a value between integer'First and integer'Last.  The answer
>   was always yes. 

Yes, that was my point exactly.  Which is why I DIDN'T ask whether an
enumeration was between the first legal value and the last legal value.  In
my example above, Int is still an integer;  it hasn't been converted
to an enumeration yet.  My point, and Tucker's also, was that the
checking should be done on the *integer* before it's converted.

                                -- Adam

^ permalink raw reply	[flat|nested] 10+ messages in thread
* Re: Unchecked_Conversion question
@ 1993-09-03 19:06 dog.ee.lbl.gov!agate!spool.mu.edu!umn.edu!email.sp.paramax.com!not-for-ma
  0 siblings, 0 replies; 10+ messages in thread
From: dog.ee.lbl.gov!agate!spool.mu.edu!umn.edu!email.sp.paramax.com!not-for-ma @ 1993-09-03 19:06 UTC (permalink / raw)


adam@irvine.com (Adam Beneschan) writes:
> In article <1993Sep1.154715.10498@Rapnet.Sanders.Lockheed.Com> lvonrude@Rapne
t.Sanders.Lockheed.Com (Lowell S. VonRuden x5294) writes:
> 
> Anyway, if you want a more dependable version, try this:
> 
  -- Deleted text
> 
>     if Int not in Enum_Low .. Enum_High then
>       raise Constraint_Error;   -- or whatever
>     end if;
>     E := Convert (Int);  
> 
>   end Sample;


I would not count on this being dependable, please refer to Tucker
Taft's post.  I can tell you that people I have worked with tried
this with the TeleSoft Ada compiler and found there code optimized
away.  The compiler assumed that anything it does is correct and
therefore it need not check for things that are obviously true. ;)

To it asking whether an enum was between the first legal value
and the last legal value was like asking if an integer object
had a value between integer'First and integer'Last.  The answer
was always yes. 

We found that on our system we must always make explict legalty
checks on the integer representations of data words/registers,etc
(stuff gotten from non-ada, not this Ada program sources). The
way the checks were made depended upon the often weird aspects
of the external devices and how fast something had to be done.

Robert Parkhill

^ permalink raw reply	[flat|nested] 10+ messages in thread
* Re: Unchecked_Conversion question
@ 1993-09-02 15:43 dog.ee.lbl.gov!overload.lbl.gov!agate!howland.reston.ans.net!noc.near.net
  0 siblings, 0 replies; 10+ messages in thread
From: dog.ee.lbl.gov!overload.lbl.gov!agate!howland.reston.ans.net!noc.near.net @ 1993-09-02 15:43 UTC (permalink / raw)


In article <1993Sep2.133859.26958@Rapnet.Sanders.Lockheed.Com> 
  lvonrude@Rapnet.Sanders.Lockheed.Com (Lowell S. VonRuden x5294) writes:

>In article <CCop4H.Hz8@irvine.com> 
>  adam@irvine.com (Adam Beneschan) writes:

>>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.

In my view, it is generally unwise to rely on type conversions (checked
or unchecked) to perform data validation.  It is easy enough
(if a bit tedious) to perform data validation yourself.  

Because this has been a common problem, we have proposed a standard
object attribute in Ada 9X called "Valid" which checks whether
the current contents of an object corresponds to the representation
for a valid value of its subtype.

Hence, after "E := Unchecked_Convert(Int);" one will be able
to write:
   if not E'Valid then 
      <complain appropriately>
   else
      <use E with confidence>
   end if;

(Note that the 'Valid attribute is only proposed for scalar types,
since checking "validity" for access types and composite types
was felt to be too difficult to define in any semantically formal way.)

>>>   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....

I agree with this assessment

>That's what I'm concerned about.  The Verdix compiler I'm using
>generates the check for the seemingly unnecessary conversion both with
>and without the optimizer turned on, but I still feel funny trusting
>this in all situations.
>
>I saw someone else's attempt at trying to catch bad values for X.  They
>passed the Enum resulting from the unchecked conversion into a procedure,
>which did some unrelated thing, but they had a local block with an exception
>handler for Constraint_Error surrounding the call.  This would assume
>that the constraints of the Enum type would always be checked when the
>object is passed to another procedure.
>
>  E := Convert (Int);
>
>  begin
>    Do_Something_Unrelated (E);
>  exception
>    when Constraint_Error =>
>      -- assume Int must not have been a valid Enum representation
>  end;
>
>Would this be a safe assumption?

If you are going to all this trouble, you might be better off
checking the validity of the value before you convert it from an
integer type.  There are various ways to do this, depending
on your time/space tradeoffs.  You might want to start by
defining the enumeration representation using named numbers, e.g:

    type Enum is (AAA, BBB, CCC, DDD);
    AAA_Rep : constant := 1;
    BBB_Rep : constant := 2;
    CCC_Rep : constant := 13;
    DDD_Rep : constant := 14;
    for Enum use (AAA=>AAA_Rep, BBB=>BBB_Rep, CCC=>CCC_Rep, DDD=>DDD_Rep);

    Enum_Min_Rep : constant := AAA_Rep;
    Enum_Max_Rep : constant := DDD_Rep;

Given the above, you can now pretty easily
write whatever kind of validation routine you want.
For example, you could create a boolean array:

    type Validity_Array is array(Enum_Min_Rep .. Enum_Max_Rep) of Boolean;

    Is_Valid : constant Validity_Array := 
      Validity_Array'(AAA_Rep|BBB_Rep|CCC_Rep|DDD_Rep => True, 
         others => False);

    function Is_Valid_Rep(Rep : Integer) return Boolean;
    pragma Inline(Is_Valid_Rep);

    function Is_Valid_Rep(Rep : Integer) return Boolean is
    begin
       return Rep in Is_Valid'Range and then Is_Valid(Rep);
    end Is_Valid_Rep;

My general rule would be to do things the obvious, explicit way, rather
than try to use features of the language in a way that is not guaranteed
to work, with a hope that the compiler will figure out what you mean,
and "do the right thing."

Of course, as indicated above, the obvious, explicit way is pretty
tedious if you have to do this for every enumeration type, which
is one reason why we have proposed the 'Valid attribute.
But if you only have one or two such enumeration types in you
program, you would be wise, at least until "'Valid" shows up in 
your local Ada compiler, to use an explicit, if tedious, validity 
test before any conversions.

P.S. My own view of enumeration representation clauses is that
they should be used only when really necessary.  The problem is that
the attributes 'Pos, 'Val, 'Succ, 'Pred, 'Image, and 'Value,
for-loops over the enumeration type, array indexing with the enumeration
type, etc. have to do some hidden (and potentially inefficient) stuff to work 
with "holey" enumeration types.

Anytime there is a simple-looking feature with hidden
implementation overhead, one should be careful in use of the feature.
In most applications I have seen, the only reason for
a "holey" enumeration type was that there was just no
name for some of the intermediate values; there was generally
no requirement to be able to iterate over the named enumeration
values, automatically skipping the unnamed values (the automatic
"skipping" is what makes for-loops a pain).  
For example, one might be tempted to define EBCDIC as a "holey"
enumeration type, since some of the 8-bit codes have no corresponding
graphic character.  However, this would be a big mistake (the reason
is left as an exercise for the reader).

Given the above, it is often more straightforward to either 
specify "fillers" for the gaps in the enumeration type (that's
essentially what is done for the predefined enumeration type Character),
or stick with an integer type (perhaps visibly "private")
while providing named constants corresponding to the interesting 
values.  Which approach is best depends on how sparse is the type.  
Any of these approaches makes many things more straightforward, 
including data validity tests, and eliminates the hidden 
baggage from 'Pos, 'Val, for-loops, array indexing, etc.

For example, in your case, the type is sparse enough that 
an integer type with named constants might be best:

    type Enum is range 1..14;
    AAA : constant Enum := 1;
    BBB : constant Enum := 2
    CCC : constant Enum := 13;
    DDD : constant Enum := 14;

Note that because Ada has strong type checking for user-defined
integer types (unlike C or C++), there are no implicit conversions
from other named integer types to Enum, so you get some amount
of protection.  If you want to enforce further privacy, then 
you could put the above in a private part, and make only the 
following visible:

    type Enum is private;
    AAA : constant Enum;
    BBB : constant Enum;
    CCC : constant Enum;
    DDD : constant Enum;

    function Convert(Rep : Integer) return Enum;
      -- raises Invalid_Rep if Integer not a valid value
    Invalid_Rep : exception;
private
    type Enum is range 1..14;
    ...etc... See above

So the bottom line might be, you should consider an alternative
to using "holey" enumeration types.

>-- Usual disclaimers apply...               Lowell Von Ruden      --
>-- lvonrude@rapnet.sanders.lockheed.com     Lockheed Sanders, Inc --

S. Tucker Taft   stt@inmet.com
Intermetrics, Inc.
Cambridge, MA  02138

^ permalink raw reply	[flat|nested] 10+ messages in thread
* Re: Unchecked_Conversion question
@ 1993-09-02 13:38 Lowell S. VonRuden x5294
  0 siblings, 0 replies; 10+ messages in thread
From: Lowell S. VonRuden x5294 @ 1993-09-02 13:38 UTC (permalink / raw)


In article <CCop4H.Hz8@irvine.com> adam@irvine.com (Adam Beneschan) writes:
>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.

That's what I'm concerned about.  The Verdix compiler I'm using
generates the check for the seemingly unnecessary conversion both with
and without the optimizer turned on, but I still feel funny trusting
this in all situations.

I saw someone else's attempt at trying to catch bad values for X.  They
passed the Enum resulting from the unchecked conversion into a procedure,
which did some unrelated thing, but they had a local block with an exception
handler for Constraint_Error surrounding the call.  This would assume
that the constraints of the Enum type would always be checked when the
object is passed to another procedure.

  E := Convert (Int);

  begin
    Do_Something_Unrelated (E);
  exception
    when Constraint_Error =>
      -- assume Int must not have been a valid Enum representation
  end;

Would this be a safe assumption?

-- 
--------------------------------------------------------------------
-- Usual disclaimers apply...               Lowell Von Ruden      --
-- lvonrude@rapnet.sanders.lockheed.com     Lockheed Sanders, Inc --
--------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 10+ messages in thread
* Re: Unchecked_Conversion question
@ 1993-09-02  3:00 Robert Dewar
  0 siblings, 0 replies; 10+ messages in thread
From: Robert Dewar @ 1993-09-02  3:00 UTC (permalink / raw)


You cannot rely on unchecked conversion not raising a constraint error
if the value is out of range. In fact you cannot rely on the compiler
not generating code to erase your system disk if the value is out of
range, since the program execution is erroneous at that point!

It is in fact possible to construct an example where it is not beyond the
bounds of belief that an optimizing compiler WOULD do something drastic
like wipeout your system disk if your program was erroneous in this way.

9X tries where possible to limit the effects of erroneousness of this type,
but in Ada 83, there are no such limitations.

That being said, I think that in practice you will find this code to be
fairly portable. Just isolate this use of unchecked conversion with
clear comments as to what you are expecting from the compiler. One should
never be to worried by writing code at this level when that is what is
needed!

^ permalink raw reply	[flat|nested] 10+ messages in thread
* Re: Unchecked_Conversion question
@ 1993-09-01 16:43 dog.ee.lbl.gov!network.ucsd.edu!news.cerf.net!shrike.irvine.com!adam
  0 siblings, 0 replies; 10+ messages in thread
From: dog.ee.lbl.gov!network.ucsd.edu!news.cerf.net!shrike.irvine.com!adam @ 1993-09-01 16:43 UTC (permalink / raw)


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

^ permalink raw reply	[flat|nested] 10+ messages in thread
* Unchecked_Conversion question
@ 1993-09-01 15:47 Lowell S. VonRuden x5294
  0 siblings, 0 replies; 10+ messages in thread
From: Lowell S. VonRuden x5294 @ 1993-09-01 15:47 UTC (permalink / raw)


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?

-- 
--------------------------------------------------------------------
-- Usual disclaimers apply...               Lowell Von Ruden      --
-- lvonrude@rapnet.sanders.lockheed.com     Lockheed Sanders, Inc --
--------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~1993-09-04  0:13 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1993-09-04  0:13 Unchecked_Conversion question Robert Dewar
  -- strict thread matches above, loose matches on Subject: below --
1993-09-03 21:55 Robert Parkhill
1993-09-03 20:14 Wes Groleau x1240 C73-8
1993-09-03 19:51 dog.ee.lbl.gov!agate!howland.reston.ans.net!spool.mu.edu!sdd.hp.com!netwo
1993-09-03 19:06 dog.ee.lbl.gov!agate!spool.mu.edu!umn.edu!email.sp.paramax.com!not-for-ma
1993-09-02 15:43 dog.ee.lbl.gov!overload.lbl.gov!agate!howland.reston.ans.net!noc.near.net
1993-09-02 13:38 Lowell S. VonRuden x5294
1993-09-02  3:00 Robert Dewar
1993-09-01 16:43 dog.ee.lbl.gov!network.ucsd.edu!news.cerf.net!shrike.irvine.com!adam
1993-09-01 15:47 Lowell S. VonRuden x5294

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox