This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Ada subtypes and base types


On 3/16/06, Richard Guenther <richard.guenther@gmail.com> wrote:
> On 3/16/06, Laurent GUERBY <laurent@guerby.net> wrote:
> > On Thu, 2006-03-16 at 10:43 +0100, Richard Guenther wrote:
> > > On 3/16/06, Geert Bosch <bosch@adacore.com> wrote:
> > > >
> > > > On Mar 16, 2006, at 05:09, Robert Dewar wrote:
> > > > > Not quite right. If you have an uninitialized variable, the value is
> > > > > invalid and may be out of bounds, but this is a bounded error
> > > > > situation,
> > > > > not an erroneous program. So the possible effects are definitely NOT
> > > > > unbounded, and the use of such values cannot turn a program erroneous.
> > > > > (that's an Ada 95 change, this used to be erroneous in Ada 83).
> > > >
> > > > Actually, that's a good point and raises some potential issues:
> > > > if we're never establish the invariant that a value of a type is in
> > > > range, we can only use the base range for variables that might be
> > > > used uninitialized. Any read of such a variable would then involve
> > > > a range check.
> > > >
> > > >    package Uninitialized is
> > > >       N : Positive;
> > > >    end Uninitialized;
> > > >
> > > >    with Uninitialized;
> > > >    procedure Test is
> > > >       for J in 1 .. Uninitialized.N loop
> > > >          ...
> > > >       end loop;
> > > >    end Test;
> > > >
> > > > In this case, GCC might replace the loop with
> > > >     declare
> > > >        J : Integer := 1;
> > > >     begin
> > > >        while J /= Uninitialized.N loop
> > > >           ...
> > > >           J := J + 1;
> > > >        end loop;
> > > >     end;
> > > >
> > > > which would be incorrect for N = 0.
> > >
> > > Uh - what do you expect here??  Does the Ada standard require a out-of-range
> > > exception upon the first use of N?
> >
> > <<
> > 13.9.1 Data Validity
> >
> >                           Bounded (Run-Time) Errors
> >
> > 9     {invalid representation} {bounded error (cause) [partial]} If the
> > representation of a scalar object does not represent a value of the object's
> > subtype (perhaps because the object was not initialized), the object is said
> > to have an invalid representation. It is a bounded error to evaluate the value
> > of such an object. {Program_Error (raised by failure of run-time check)}
> > {Constraint_Error (raised by failure of run-time check)} If the error is
> > detected, either Constraint_Error or Program_Error is raised. Otherwise,
> > execution continues using the invalid representation. The rules of the
> > language outside this subclause assume that all objects have valid
> > representations. The semantics of operations on invalid representations are as
> > follows:
> >
> >     9.a   Discussion: The AARM is more explicit about what happens when the
> >           value of the case expression is an invalid representation.
> >
> >     9.b/2 Ramification: {AI95-00426-01} This includes the result object of
> >           functions, including the result of Unchecked_Conversion, T'Input,
> >           and imported functions.
> >
> > 10    If the representation of the object represents a value of the object's
> >       type, the value of the type is used.
> >
> > 11    If the representation of the object does not represent a value of the
> >       object's type, the semantics of operations on such representations is
> >       implementation-defined, but does not by itself lead to erroneous or
> >       unpredictable execution, or to other objects becoming abnormal.
> >
> >     11.a/2 Implementation Note: {AI95-00426-01} This means that the
> >           implementation must take care not to use an invalid representation
> >           in a way that might cause erroneous execution. For instance, the
> >           exception mandated for case_statements must be raised. Array
> >           indexing must not cause memory outside of the array to be written
> >           (and usually, not read either). These cases and similar cases may
> >           require explicit checks by the implementation.
> > >>
> >
> > So in this case the behaviour is implementation defined, from my reading
> > an infinite loop is not contrary to the standard.
> >
> > > In this case, the frontend needs
> > > to insert a proper
> > > check.  You cannot expect the middle-end to avoid the above transformation, so
> > > this is a frontend bug.
> >
> > Do the ME or the BE have a representation for potentially uninitalized
> > variables?
>
> No.
>
> > In the following case:
> >
> > procedure T2 is
> >    type R is range 1 .. 10;
> >    type T is array (R) of Integer;
> >    I : R;
> >    X : T;
> > begin
> >    X (I) := 0;
> > end T2;
> >
> > The Ada FE will insert an explicit check, as seen when using
> > gcc -c -gnatdg t2.adb:
> >
> >    [constraint_error when not (interfaces__unsigned_32!(i) >= 1 and then
> >      interfaces__unsigned_32!(i) <= 10) "invalid data"]
> >
> > Will the ME or FE remove the check?
>
> If you do the check in the base type then it will be only removed if
> the compiler
> can prove the comparisons are always true.  For instance if there is a preceding
> initialization of i to say 3.  Also if the basetype is somehow known
> to have a value
> outside of the range, the constraint error will be raised
> unconditionally (but as I
> understand there is no way the frontend can produce such knowledge).

Note that gigi needs to use VIEW_CONVERT_EXPR to create a view in the
base type for such checks (likewise for the 'Valid case).  Now for VRP
suppose we have
(sorry for the C-ish Ada code ;))

  derived uninitialized;
  if (VIEW_CONVERT_EXPR(base_type, uninitialized) < 0)
   abort();

now VRP infers a range of 1..10 for uninitialized infered from
TYPE_MIN/MAX_VALUE.
If VRP wants to propagate ranges through VIEW_CONVERT_EXPRs (which it wants,
if the above check should be optimized in case the value is
initialized), it needs to
exclude somehow range information infered from TYPE_MIN/MAX_VALUE.  So, for

  derived initialized = 1;
  if (VIEW_CONVERT_EXPR(base_type, uninitialized) < 0)
   abort();

VRP should be able to remove the test (I guess at the moment VRP simply stops
if seeing VIEW_CONVERT_EXPRs).

Richard.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]