summaryrefslogtreecommitdiff
path: root/gcc/ada/freeze.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/freeze.adb')
-rw-r--r--gcc/ada/freeze.adb403
1 files changed, 250 insertions, 153 deletions
diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb
index e49ec85e4c6..0fe2173a093 100644
--- a/gcc/ada/freeze.adb
+++ b/gcc/ada/freeze.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2004, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2005, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -164,6 +164,11 @@ package body Freeze is
-- needed -- see body for details). Never has any effect on T if the
-- Debug_Info_Off flag is set.
+ procedure Undelay_Type (T : Entity_Id);
+ -- T is a type of a component that we know to be an Itype.
+ -- We don't want this to have a Freeze_Node, so ensure it doesn't.
+ -- Do the same for any Full_View or Corresponding_Record_Type.
+
procedure Warn_Overlay
(Expr : Node_Id;
Typ : Entity_Id;
@@ -506,9 +511,9 @@ package body Freeze is
procedure Check_Compile_Time_Size (T : Entity_Id) is
- procedure Set_Small_Size (S : Uint);
+ procedure Set_Small_Size (T : Entity_Id; S : Uint);
-- Sets the compile time known size (32 bits or less) in the Esize
- -- field, checking for a size clause that was given which attempts
+ -- field, of T checking for a size clause that was given which attempts
-- to give a smaller size.
function Size_Known (T : Entity_Id) return Boolean;
@@ -525,7 +530,7 @@ package body Freeze is
-- Set_Small_Size --
--------------------
- procedure Set_Small_Size (S : Uint) is
+ procedure Set_Small_Size (T : Entity_Id; S : Uint) is
begin
if S > 32 then
return;
@@ -576,7 +581,8 @@ package body Freeze is
elsif Is_Array_Type (T) then
if Ekind (T) = E_String_Literal_Subtype then
- Set_Small_Size (Component_Size (T) * String_Literal_Length (T));
+ Set_Small_Size (T, Component_Size (T)
+ * String_Literal_Length (T));
return True;
elsif not Is_Constrained (T) then
@@ -632,7 +638,7 @@ package body Freeze is
Next_Index (Index);
end loop;
- Set_Small_Size (Esiz);
+ Set_Small_Size (T, Esiz);
return True;
end;
@@ -864,7 +870,7 @@ package body Freeze is
end loop;
if Packed_Size_Known then
- Set_Small_Size (Packed_Size);
+ Set_Small_Size (T, Packed_Size);
end if;
return True;
@@ -1365,6 +1371,7 @@ package body Freeze is
-------------------
function Freeze_Entity (E : Entity_Id; Loc : Source_Ptr) return List_Id is
+ Test_E : Entity_Id := E;
Comp : Entity_Id;
F_Node : Node_Id;
Result : List_Id;
@@ -1460,6 +1467,7 @@ package body Freeze is
IR : Node_Id;
Junk : Boolean;
ADC : Node_Id;
+ Prev : Entity_Id;
Unplaced_Component : Boolean := False;
-- Set True if we find at least one component with no component
@@ -1537,80 +1545,14 @@ package body Freeze is
end if;
end if;
- -- Freeze components and embedded subtypes
+ -- Freeze components and embedded subtypes.
Comp := First_Entity (Rec);
- while Present (Comp) loop
- if not Is_Type (Comp) then
- Freeze_And_Append (Etype (Comp), Loc, Result);
- end if;
-
- -- If the component is an access type with an allocator
- -- as default value, the designated type will be frozen
- -- by the corresponding expression in init_proc. In order
- -- to place the freeze node for the designated type before
- -- that for the current record type, freeze it now.
-
- -- Same process if the component is an array of access types,
- -- initialized with an aggregate. If the designated type is
- -- private, it cannot contain allocators, and it is premature
- -- to freeze the type, so we check for this as well.
-
- if Is_Access_Type (Etype (Comp))
- and then Present (Parent (Comp))
- and then Present (Expression (Parent (Comp)))
- and then Nkind (Expression (Parent (Comp))) = N_Allocator
- then
- declare
- Alloc : constant Node_Id := Expression (Parent (Comp));
-
- begin
- -- If component is pointer to a classwide type, freeze
- -- the specific type in the expression being allocated.
- -- The expression may be a subtype indication, in which
- -- case freeze the subtype mark.
+ Prev := Empty;
- if Is_Class_Wide_Type (Designated_Type (Etype (Comp))) then
- if Is_Entity_Name (Expression (Alloc)) then
- Freeze_And_Append
- (Entity (Expression (Alloc)), Loc, Result);
- elsif
- Nkind (Expression (Alloc)) = N_Subtype_Indication
- then
- Freeze_And_Append
- (Entity (Subtype_Mark (Expression (Alloc))),
- Loc, Result);
- end if;
-
- elsif Is_Itype (Designated_Type (Etype (Comp))) then
- Check_Itype (Designated_Type (Etype (Comp)));
-
- else
- Freeze_And_Append
- (Designated_Type (Etype (Comp)), Loc, Result);
- end if;
- end;
-
- elsif Is_Access_Type (Etype (Comp))
- and then Is_Itype (Designated_Type (Etype (Comp)))
- then
- Check_Itype (Designated_Type (Etype (Comp)));
-
- elsif Is_Array_Type (Etype (Comp))
- and then Is_Access_Type (Component_Type (Etype (Comp)))
- and then Present (Parent (Comp))
- and then Nkind (Parent (Comp)) = N_Component_Declaration
- and then Present (Expression (Parent (Comp)))
- and then Nkind (Expression (Parent (Comp))) = N_Aggregate
- and then Is_Fully_Defined
- (Designated_Type (Component_Type (Etype (Comp))))
- then
- Freeze_And_Append
- (Designated_Type
- (Component_Type (Etype (Comp))), Loc, Result);
- end if;
+ while Present (Comp) loop
- -- Processing for real components (exclude anonymous subtypes)
+ -- First handle the (real) component case.
if Ekind (Comp) = E_Component
or else Ekind (Comp) = E_Discriminant
@@ -1619,6 +1561,23 @@ package body Freeze is
CC : constant Node_Id := Component_Clause (Comp);
begin
+ -- Freezing a record type freezes the type of each of its
+ -- components. However, if the type of the component is
+ -- part of this record, we do not want or need a separate
+ -- Freeze_Node. Note that Is_Itype is wrong because that's
+ -- also set in private type cases. We also can't check for
+ -- the Scope being exactly Rec because of private types and
+ -- record extensions.
+
+ if Is_Itype (Etype (Comp))
+ and then Is_Record_Type (Underlying_Type
+ (Scope (Etype (Comp))))
+ then
+ Undelay_Type (Etype (Comp));
+ end if;
+
+ Freeze_And_Append (Etype (Comp), Loc, Result);
+
-- Check for error of component clause given for variable
-- sized type. We have to delay this test till this point,
-- since the component type has to be frozen for us to know
@@ -1779,6 +1738,135 @@ package body Freeze is
end;
end if;
+ -- If the component is an Itype with Delayed_Freeze and is either
+ -- a record or array subtype and its base type has not yet been
+ -- frozen, we must remove this from the entity list of this
+ -- record and put it on the entity list of the scope of its base
+ -- type. Note that we know that this is not the type of a
+ -- component since we cleared Has_Delayed_Freeze for it in the
+ -- previous loop. Thus this must be the Designated_Type of an
+ -- access type, which is the type of a component.
+
+ if Is_Itype (Comp)
+ and then Is_Type (Scope (Comp))
+ and then Is_Composite_Type (Comp)
+ and then Base_Type (Comp) /= Comp
+ and then Has_Delayed_Freeze (Comp)
+ and then not Is_Frozen (Base_Type (Comp))
+ then
+ declare
+ Will_Be_Frozen : Boolean := False;
+ S : Entity_Id := Scope (Rec);
+
+ begin
+ -- We have a pretty bad kludge here. Suppose Rec is a
+ -- subtype being defined in a subprogram that's created
+ -- as part of the freezing of Rec'Base. In that case,
+ -- we know that Comp'Base must have already been frozen by
+ -- the time we get to elaborate this because Gigi doesn't
+ -- elaborate any bodies until it has elaborated all of the
+ -- declarative part. But Is_Frozen will not be set at this
+ -- point because we are processing code in lexical order.
+
+ -- We detect this case by going up the Scope chain of
+ -- Rec and seeing if we have a subprogram scope before
+ -- reaching the top of the scope chain or that of Comp'Base.
+ -- If we do, then mark that Comp'Base will actually be
+ -- frozen. If so, we merely undelay it.
+
+ while Present (S) loop
+ if Is_Subprogram (S) then
+ Will_Be_Frozen := True;
+ exit;
+ elsif S = Scope (Base_Type (Comp)) then
+ exit;
+ end if;
+
+ S := Scope (S);
+ end loop;
+
+ if Will_Be_Frozen then
+ Undelay_Type (Comp);
+ else
+ if Present (Prev) then
+ Set_Next_Entity (Prev, Next_Entity (Comp));
+ else
+ Set_First_Entity (Rec, Next_Entity (Comp));
+ end if;
+
+ -- Insert in entity list of scope of base type (which
+ -- must be an enclosing scope, because still unfrozen).
+
+ Append_Entity (Comp, Scope (Base_Type (Comp)));
+ end if;
+ end;
+
+ -- If the component is an access type with an allocator as
+ -- default value, the designated type will be frozen by the
+ -- corresponding expression in init_proc. In order to place the
+ -- freeze node for the designated type before that for the
+ -- current record type, freeze it now.
+
+ -- Same process if the component is an array of access types,
+ -- initialized with an aggregate. If the designated type is
+ -- private, it cannot contain allocators, and it is premature to
+ -- freeze the type, so we check for this as well.
+
+ elsif Is_Access_Type (Etype (Comp))
+ and then Present (Parent (Comp))
+ and then Present (Expression (Parent (Comp)))
+ and then Nkind (Expression (Parent (Comp))) = N_Allocator
+ then
+ declare
+ Alloc : constant Node_Id := Expression (Parent (Comp));
+
+ begin
+ -- If component is pointer to a classwide type, freeze
+ -- the specific type in the expression being allocated.
+ -- The expression may be a subtype indication, in which
+ -- case freeze the subtype mark.
+
+ if Is_Class_Wide_Type (Designated_Type (Etype (Comp))) then
+ if Is_Entity_Name (Expression (Alloc)) then
+ Freeze_And_Append
+ (Entity (Expression (Alloc)), Loc, Result);
+ elsif
+ Nkind (Expression (Alloc)) = N_Subtype_Indication
+ then
+ Freeze_And_Append
+ (Entity (Subtype_Mark (Expression (Alloc))),
+ Loc, Result);
+ end if;
+
+ elsif Is_Itype (Designated_Type (Etype (Comp))) then
+ Check_Itype (Designated_Type (Etype (Comp)));
+
+ else
+ Freeze_And_Append
+ (Designated_Type (Etype (Comp)), Loc, Result);
+ end if;
+ end;
+
+ elsif Is_Access_Type (Etype (Comp))
+ and then Is_Itype (Designated_Type (Etype (Comp)))
+ then
+ Check_Itype (Designated_Type (Etype (Comp)));
+
+ elsif Is_Array_Type (Etype (Comp))
+ and then Is_Access_Type (Component_Type (Etype (Comp)))
+ and then Present (Parent (Comp))
+ and then Nkind (Parent (Comp)) = N_Component_Declaration
+ and then Present (Expression (Parent (Comp)))
+ and then Nkind (Expression (Parent (Comp))) = N_Aggregate
+ and then Is_Fully_Defined
+ (Designated_Type (Component_Type (Etype (Comp))))
+ then
+ Freeze_And_Append
+ (Designated_Type
+ (Component_Type (Etype (Comp))), Loc, Result);
+ end if;
+
+ Prev := Comp;
Next_Entity (Comp);
end loop;
@@ -1882,17 +1970,28 @@ package body Freeze is
-- Start of processing for Freeze_Entity
begin
+ -- We are going to test for various reasons why this entity need not be
+ -- frozen here, but in the case of an Itype that's defined within a
+ -- record, that test actually applies to the record.
+
+ if Is_Itype (E) and then Is_Record_Type (Scope (E)) then
+ Test_E := Scope (E);
+ elsif Is_Itype (E) and then Present (Underlying_Type (Scope (E)))
+ and then Is_Record_Type (Underlying_Type (Scope (E)))
+ then
+ Test_E := Underlying_Type (Scope (E));
+ end if;
+
-- Do not freeze if already frozen since we only need one freeze node
if Is_Frozen (E) then
return No_List;
- -- It is improper to freeze an external entity within a generic
- -- because its freeze node will appear in a non-valid context.
- -- The entity will be frozen in the proper scope after the current
- -- generic is analyzed.
+ -- It is improper to freeze an external entity within a generic because
+ -- its freeze node will appear in a non-valid context. The entity will
+ -- be frozen in the proper scope after the current generic is analyzed.
- elsif Inside_A_Generic and then External_Ref_In_Generic (E) then
+ elsif Inside_A_Generic and then External_Ref_In_Generic (Test_E) then
return No_List;
-- Do not freeze a global entity within an inner scope created during
@@ -1906,9 +2005,9 @@ package body Freeze is
-- comes from source, or is a generic instance, then the freeze point
-- is the one mandated by the language. and we freze the entity.
- elsif In_Open_Scopes (Scope (E))
- and then Scope (E) /= Current_Scope
- and then Ekind (E) /= E_Constant
+ elsif In_Open_Scopes (Scope (Test_E))
+ and then Scope (Test_E) /= Current_Scope
+ and then Ekind (Test_E) /= E_Constant
then
declare
S : Entity_Id := Current_Scope;
@@ -1940,10 +2039,11 @@ package body Freeze is
elsif Front_End_Inlining
and then In_Instance_Body
- and then Present (Scope (E))
+ and then Present (Scope (Test_E))
then
declare
- S : Entity_Id := Scope (E);
+ S : Entity_Id := Scope (Test_E);
+
begin
while Present (S) loop
if Is_Generic_Instance (S) then
@@ -2694,6 +2794,12 @@ package body Freeze is
Freeze_And_Append (Comp, Loc, Result);
elsif (Ekind (Comp)) /= E_Function then
+ if Is_Itype (Etype (Comp))
+ and then Underlying_Type (Scope (Etype (Comp))) = E
+ then
+ Undelay_Type (Etype (Comp));
+ end if;
+
Freeze_And_Append (Etype (Comp), Loc, Result);
end if;
@@ -2904,66 +3010,8 @@ package body Freeze is
Check_Restriction (No_Standard_Storage_Pools, E);
end if;
- -- If the current entity is an array or record subtype and has
- -- discriminants used to constrain it, it must not freeze, because
- -- Freeze_Entity nodes force Gigi to process the frozen type.
-
if Is_Composite_Type (E) then
- if Is_Array_Type (E) then
- declare
- Index : Node_Id := First_Index (E);
- Expr1 : Node_Id;
- Expr2 : Node_Id;
-
- begin
- while Present (Index) loop
- if Etype (Index) /= Any_Type then
- Get_Index_Bounds (Index, Expr1, Expr2);
-
- for J in 1 .. 2 loop
- if Nkind (Expr1) = N_Identifier
- and then Ekind (Entity (Expr1)) = E_Discriminant
- then
- Set_Has_Delayed_Freeze (E, False);
- Set_Freeze_Node (E, Empty);
- Check_Debug_Info_Needed (E);
- return Result;
- end if;
-
- Expr1 := Expr2;
- end loop;
- end if;
-
- Next_Index (Index);
- end loop;
- end;
-
- elsif Has_Discriminants (E)
- and Is_Constrained (E)
- then
- declare
- Constraint : Elmt_Id;
- Expr : Node_Id;
-
- begin
- Constraint := First_Elmt (Discriminant_Constraint (E));
- while Present (Constraint) loop
- Expr := Node (Constraint);
- if Nkind (Expr) = N_Identifier
- and then Ekind (Entity (Expr)) = E_Discriminant
- then
- Set_Has_Delayed_Freeze (E, False);
- Set_Freeze_Node (E, Empty);
- Check_Debug_Info_Needed (E);
- return Result;
- end if;
-
- Next_Elmt (Constraint);
- end loop;
- end;
- end if;
-
-- AI-117 requires that all new primitives of a tagged type
-- must inherit the convention of the full view of the type.
-- Inherited and overriding operations are defined to inherit
@@ -3065,7 +3113,7 @@ package body Freeze is
-- in particular the size and alignment values. This processing is
-- not required for generic types, since generic types do not play
-- any part in code generation, and so the size and alignment values
- -- for suhc types are irrelevant.
+ -- for such types are irrelevant.
if Is_Generic_Type (E) then
return Result;
@@ -3242,7 +3290,7 @@ package body Freeze is
function In_Exp_Body (N : Node_Id) return Boolean;
-- Given an N_Handled_Sequence_Of_Statements node N, determines whether
- -- it is the handled statement sequence of an expander generated
+ -- it is the handled statement sequence of an expander-generated
-- subprogram (init proc, or stream subprogram). If so, it returns
-- True, otherwise False.
@@ -3607,6 +3655,11 @@ package body Freeze is
-- specification, the scope is still void. The expression can also
-- appear in the discriminant part of a private or concurrent type.
+ -- If the expression appears in a constrained subcomponent of an
+ -- enclosing record declaration, the freeze nodes must be attached
+ -- to the outer record type so they can eventually be placed in the
+ -- enclosing declaration list.
+
-- The other case requiring this special handling is if we are in
-- a default expression, since in that case we are about to freeze
-- a static type, and the freeze scope needs to be the outer scope,
@@ -3626,6 +3679,7 @@ package body Freeze is
declare
Loc : constant Source_Ptr := Sloc (Current_Scope);
Freeze_Nodes : List_Id := No_List;
+ Pos : Int := Scope_Stack.Last;
begin
if Present (Desig_Typ) then
@@ -3640,16 +3694,21 @@ package body Freeze is
Freeze_And_Append (Nam, Loc, Freeze_Nodes);
end if;
+ -- The current scope may be that of a constrained component of
+ -- an enclosing record declaration, which is above the current
+ -- scope in the scope stack.
+
+ if Is_Record_Type (Scope (Current_Scope)) then
+ Pos := Pos - 1;
+ end if;
+
if Is_Non_Empty_List (Freeze_Nodes) then
- if No (Scope_Stack.Table
- (Scope_Stack.Last).Pending_Freeze_Actions)
- then
- Scope_Stack.Table
- (Scope_Stack.Last).Pending_Freeze_Actions :=
+ if No (Scope_Stack.Table (Pos).Pending_Freeze_Actions) then
+ Scope_Stack.Table (Pos).Pending_Freeze_Actions :=
Freeze_Nodes;
else
Append_List (Freeze_Nodes, Scope_Stack.Table
- (Scope_Stack.Last).Pending_Freeze_Actions);
+ (Pos).Pending_Freeze_Actions);
end if;
end if;
end;
@@ -4728,6 +4787,44 @@ package body Freeze is
end Set_Debug_Info_Needed;
------------------
+ -- Undelay_Type --
+ ------------------
+
+ procedure Undelay_Type (T : Entity_Id) is
+ begin
+ Set_Has_Delayed_Freeze (T, False);
+ Set_Freeze_Node (T, Empty);
+
+ -- Since we don't want T to have a Freeze_Node, we don't want its
+ -- Full_View or Corresponding_Record_Type to have one either.
+
+ -- ??? Fundamentally, this whole handling is a kludge. What we really
+ -- want is to be sure that for an Itype that's part of record R and is
+ -- a subtype of type T, that it's frozen after the later of the freeze
+ -- points of R and T. We have no way of doing that directly, so what we
+ -- do is force most such Itypes to be frozen as part of freezing R via
+ -- this procedure and only delay the ones that need to be delayed
+ -- (mostly the designated types of access types that are defined as
+ -- part of the record).
+
+ if Is_Private_Type (T)
+ and then Present (Full_View (T))
+ and then Is_Itype (Full_View (T))
+ and then Is_Record_Type (Scope (Full_View (T)))
+ then
+ Undelay_Type (Full_View (T));
+ end if;
+
+ if Is_Concurrent_Type (T)
+ and then Present (Corresponding_Record_Type (T))
+ and then Is_Itype (Corresponding_Record_Type (T))
+ and then Is_Record_Type (Scope (Corresponding_Record_Type (T)))
+ then
+ Undelay_Type (Corresponding_Record_Type (T));
+ end if;
+ end Undelay_Type;
+
+ ------------------
-- Warn_Overlay --
------------------