From: Ludovic Brenta on
Consider the procedure:

type T is private; -- completion elided

generic
with procedure Visit (Object : in out T);
procedure Refresh (Object : in out T; Dirty : in out T) is
begin
if Dirty then
Visit (Object);
Dirty := False;
end if;
exception
when others =>
Dirty := True; -- warnings here
raise;
end Refresh;


GNAT says:
warning: assignment to pass-by-copy formal may have no effect
warning: "raise" statement may result in abnormal return (RM
6.4.1(17))

The reason for the exception handler is to enforce a postcondition
that Dirty must be True if Visit raises an exception. However the
warnings suggest that the postcondition cannot be enforced this way.
How should I rewrite my code?

--
Ludovic Brenta.
From: Ludovic Brenta on
Ludovic Brenta wrote on comp.lang.ada:
> Consider the procedure:
>
> type T is private; -- completion elided
>
> generic
>    with procedure Visit (Object : in out T);
> procedure Refresh (Object : in out T; Dirty : in out T) is

Sorry, I meant:

procedure Refresh (Object : in out T; Dirty : in out Boolean) is

> begin
>    if Dirty then
>       Visit (Object);
>       Dirty := False;
>    end if;
> exception
>    when others =>
>       Dirty := True; -- warnings here
>       raise;
> end Refresh;
>
> GNAT says:
> warning: assignment to pass-by-copy formal may have no effect
> warning: "raise" statement may result in abnormal return (RM
> 6.4.1(17))
>
> The reason for the exception handler is to enforce a postcondition
> that Dirty must be True if Visit raises an exception. However the
> warnings suggest that the postcondition cannot be enforced this way.
> How should I rewrite my code?
>
> --
> Ludovic Brenta.

From: Niklas Holsti on
Ludovic Brenta wrote:
> Consider the procedure:
>
> type T is private; -- completion elided
>
> generic
> with procedure Visit (Object : in out T);
> procedure Refresh (Object : in out T; Dirty : in out T) is
> begin
> if Dirty then
> Visit (Object);
> Dirty := False;
> end if;
> exception
> when others =>
> Dirty := True; -- warnings here
> raise;
> end Refresh;
>
>
> GNAT says:
> warning: assignment to pass-by-copy formal may have no effect
> warning: "raise" statement may result in abnormal return (RM
> 6.4.1(17))
>
> The reason for the exception handler is to enforce a postcondition
> that Dirty must be True if Visit raises an exception. However the
> warnings suggest that the postcondition cannot be enforced this way.
> How should I rewrite my code?

Perhaps change the mode of Dirty to

Dirty : access T;

and assign

Dirty.all := True;

Or use a named access type instead of the anonymous access, as you prefer.

--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
From: Ludovic Brenta on
On Mar 12, 10:29 am, Niklas Holsti <niklas.hol...(a)tidorum.invalid>
wrote:
> Ludovic Brenta wrote:
> > Consider the procedure:
>
> > type T is private; -- completion elided
>
> > generic
> >    with procedure Visit (Object : in out T);
> > procedure Refresh (Object : in out T; Dirty : in out T) is
> > begin
> >    if Dirty then
> >       Visit (Object);
> >       Dirty := False;
> >    end if;
> > exception
> >    when others =>
> >       Dirty := True; -- warnings here
> >       raise;
> > end Refresh;
>
> > GNAT says:
> > warning: assignment to pass-by-copy formal may have no effect
> > warning: "raise" statement may result in abnormal return (RM
> > 6.4.1(17))
>
> > The reason for the exception handler is to enforce a postcondition
> > that Dirty must be True if Visit raises an exception. However the
> > warnings suggest that the postcondition cannot be enforced this way.
> > How should I rewrite my code?
>
> Perhaps change the mode of Dirty to
>
>     Dirty : access T;
>
> and assign
>
>     Dirty.all := True;
>
> Or use a named access type instead of the anonymous access, as you prefer..

Heh. I was kind of hoping you wouldn't say that :) I should have been
more specific; I think using an access type is ugly but I can't think
of a better solution.

Thanks.

--
Ludovic Brenta.
From: Jeffrey R. Carter on
Ludovic Brenta wrote:
>
> Heh. I was kind of hoping you wouldn't say that :) I should have been
> more specific; I think using an access type is ugly but I can't think
> of a better solution.

Use a limited type:

type Dirty_Info is limited record
Value : Boolean := False;
end record;

procedure Refresh (Object : in out T; Dirty : in out Dirty_Info);
....
if Dirty.Value then
....
Dirty.Value := True;

Parameters of limited types are passed by reference.

--
Jeff Carter
"What I wouldn't give for a large sock with horse manure in it."
Annie Hall
42