From: Hibou57 (Yannick Duchêne) on
procedure C is
-- Variation from B : the Limited_Type
-- is now made tagged limited (instead
-- of just limited as so far).
-- Observations : still OK.

package P is
type Limited_Type is tagged limited null record;
function New_Limited return Limited_Type;
end P;

package body P is
function Pre_New_Limited return Limited_Type is
begin
return R : Limited_Type do
null;
end return;
end;

function New_Limited return Limited_Type is
begin
return R : Limited_Type := Pre_New_Limited do
null;
end return;
end;
end P;

Entity : P.Limited_Type := P.New_Limited;

begin
null;
end C;
From: Hibou57 (Yannick Duchêne) on
procedure D is
-- Variation from C : the returned type
-- is now a derived type.
-- Observations : all is nice (be patient,
-- troubles will comes soon enough).

package P is
type Limited_Type is tagged limited null record;
subtype Limited_Class is Limited_Type'Class;
function New_Limited return Limited_Class;
end P;

package body P is
type Derived_Limited_Type is
new Limited_Type with null record;

function New_Derived return Derived_Limited_Type is
begin
return R : Derived_Limited_Type do
null;
end return;
end;

function New_Limited return Limited_Class is
begin
return R : Limited_Class := New_Derived do
null;
end return;
end;
end P;

Entity : P.Limited_Class := P.New_Limited;

begin
null;
end D;
From: Hibou57 (Yannick Duchêne) on
procedure E is
-- Variation from D : Limited_Type is
-- now made a limited interface (instead
-- of a limited tagged) and the
-- derived type is made limited too
-- Note : although the interface is limited,
-- the derived type will not be automatically
-- limited if this was not explicitly
-- specify.
-- Observations : mmmh... that's good
-- (but not for long : have look at F).

package P is
type Limited_Type is limited interface;
subtype Limited_Class is Limited_Type'Class;
function New_Limited return Limited_Class;
end P;

package body P is
type Derived_Limited_Type is limited
new Limited_Type with null record;

function New_Derived return Derived_Limited_Type is
begin
return R : Derived_Limited_Type do
null;
end return;
end;

function New_Limited return Limited_Class is
begin
return R : Limited_Class := New_Derived do
null;
end return;
end;
end P;

Entity : P.Limited_Class := P.New_Limited;

begin
null;
end E;
From: Hibou57 (Yannick Duchêne) on
procedure F is
-- Variation from E : the derived
-- limited type is now made a protected
-- type (which is still limited, implicitly).
-- Observations : Arghh! Finalzation occurs
-- right after Initialization.
-- Conclusion : so fat, every thing was
-- working as expected, but breaks as
-- soon as the derived limited type
-- is made a protected type.
-- Should there be a different handling
-- of Initialization and Finalization when
-- the type is a protected type instead of
-- simply a tagged limited type ? To be
-- continued ...

package P is
type Limited_Type is limited interface;
subtype Limited_Class is Limited_Type'Class;
function New_Limited return Limited_Class;
end P;

package body P is
protected type Derived_Limited_Type is
new Limited_Type with end;

protected body Derived_Limited_Type is end;

function New_Derived return Derived_Limited_Type is
begin
return R : Derived_Limited_Type do
null;
end return;
end;

function New_Limited return Limited_Class is
begin
return R: Limited_Class := New_Derived do
null;
end return;
end;
end P;

Entity : P.Limited_Class := P.New_Limited;

begin
null;
end F;
From: Hibou57 (Yannick Duchêne) on
Back here (I was busy at some intermediate things).

It seems to me, there is indeed a GNAT bug here, as this next sample
which solve the trouble shows. With G, initialization and finalization
are done just like I was expecting.

procedure G is
-- Variation from G : the protected
-- type is wrapped in a limited record
-- which is handle the derivation of
-- the Limited_Type.
-- Observations : Entity is initialized
-- and Finalized as expected (like in A),
-- and its component of Protected_Type is
-- initialized before Entity is Initialized
-- (as expected) and Finalized after
-- Entity is Finalized (also as expected).
-- It seems to me (unless there are contradictory
-- interpretation of these observations), that
-- a bug is confirmed here, and the construct
-- provided here is a possible workaround.

package P is
type Limited_Type is limited interface;
subtype Limited_Class is Limited_Type'Class;
function New_Limited return Limited_Class;
end P;

package body P is
protected type Protected_Type is end;

protected body Protected_Type is end;

type Derived_Limited_Type is
limited new Limited_Type with
record
Wrapped_Protected_Item : Protected_Type;
end record;

function New_Derived return Derived_Limited_Type is
begin
return R : Derived_Limited_Type do
null;
end return;
end;

function New_Limited return Limited_Class is
begin
return R: Limited_Class := New_Derived do
null;
end return;
end;
end P;

Entity : P.Limited_Class := P.New_Limited;

begin
null;
end G;