aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/exp_ch3.adb
diff options
context:
space:
mode:
authorJavier Miranda <miranda@adacore.com>2010-08-10 14:29:36 +0000
committerArnaud Charlet <charlet@gcc.gnu.org>2010-08-10 16:29:36 +0200
commitcefce34c6701df7ddd07ece4874465f9049b812c (patch)
treec31c3b8d10a4d714d2f074e0150cd4419e5b882a /gcc/ada/exp_ch3.adb
parent774038e62efa7caa5b00101fffcbe1df01686fd9 (diff)
downloadgcc-cefce34c6701df7ddd07ece4874465f9049b812c.zip
gcc-cefce34c6701df7ddd07ece4874465f9049b812c.tar.gz
gcc-cefce34c6701df7ddd07ece4874465f9049b812c.tar.bz2
sem_aggr.adb (Resolve_Extension_Aggregate): Warn on the use of C++ constructors that leave the object partially initialized.
2010-08-10 Javier Miranda <miranda@adacore.com> * sem_aggr.adb (Resolve_Extension_Aggregate): Warn on the use of C++ constructors that leave the object partially initialized. * exp_atag.ads, exp_atags.adb (Build_Inherit_CPP_Prims): New subprogram that copies from parent of Typ the dispatch table slots of inherited C++ primitives. It handles primary and secondary dispatch tables. * einfo.adb (Related_Type): Moved from Node26 to Node27. Required to use this attribute with E_Variable entities. (Set_Is_Tag): Relax assertion to allow its use with variables that store tags. (Set_Related_Type): Relax assertion to allow its use with variables that store the tag of a C++ class. (Write_26_Field_Name): Remove Related_Type. (Write_27_Field_Name): Add Related_Type. * einfo.ads (Related_Type): Moved from Node26 to Node27. Available also with E_Variable entities. * sem_prag.adb (CPP_Constructor): Warn on duplicated occurrence of this pragma. * sem_util.adb (Search_Tag): Add missing support for CPP types. (Enclosing_CPP_Parent): New subprogram. (Has_Suffix): New subprogram. * sem_util.ads (Enclosing_CPP_Parent): New subprogram that returns the closest ancestor of a type that is a C++ type. (Has_Suffix): New subprogram. Used in assertions to check the suffix of internal entities. * sem_attr.adb (Analyze_Access_Attribute): Check wrong use of current instance in derivations of C++ types. * exp_tss.adb (CPP_Init_Proc): New subprogram. (Is_CPP_Init_Proc): New subprogram. (Set_TSS): Handle new C++ init routines. * exp_tss.ads (TSS_CPP_Init): New TSS name. For initialization of C++ dispatch tables. (CPP_Init_Proc): New subprogram. (Is_CPP_Init_Proc): New subprogram. * exp_disp.adb (CPP_Num_Prims): New subprogram. (Has_CPP_Constructors): New subprogram. (Make_Secondary_DT, Make_DT): For derivations of CPP types, do not initialize slots located in the C++ part of the dispatch table. (Make_Tags): For CPP types declare variables used by the IP routine to store the C++ tag values after the first invocation of the C++ constructor. (Build_CPP_Init_DT): New subprogram. (Set_CPP_Constructors): New implementation that builds an IP for each CPP constructor. These IP are wrappers of the C++ constructors that, after the first invocation of the constructor, read the C++ tags from the object and save them locally. These copies of the C++ tags are used by the IC routines to initialize tables of Ada derivations of CPP types. (Write_DT): Indicate what primitives are imported from C++ * exp_disp.ads (CPP_Num_Prims): New subprogram. (Has_CPP_Constructors): New subprogram. * exp_aggr.adb (Build_Record_Aggr_Code): For derivations of C++ types invoke the IC routine to inherit the slots of the parents. * sem_ch13.adb (Analyze_Freeze_Entity): Add new warnings on CPP types. * exp_ch3.adb (Is_Variable_Size_Array): New subprogram. (Is_Variable_Size_Record): Factorize code calling Is_Variable_Size_Array. (Build_CPP_Init_Procedure): New subprogram that builds the tree corresponding to the procedure that initializes the C++ part of the dispatch table of an Ada tagged type that is a derivation of a CPP type. (Build_Init_Procedure): Adding documentation plus code reorganization to leave more clear the construction of the IP with C++ types. (Expand_Freeze_Record_Type): Delay call to Set_CPP_Constructors because it cannot be called after Make_Tags has been invoked. (Inherit_CPP_Tag): Removed. (Init_Secondary_Tags): For derivations of CPP types, warn on tags located at variable offset. * freeze.ads: Minor reformating. * sem_ch8.adb (Write_Scopes): Add pragma export. Required to have it available in gdb. * gcc-interface/Make-lang.in: Update dependencies. From-SVN: r163065
Diffstat (limited to 'gcc/ada/exp_ch3.adb')
-rw-r--r--gcc/ada/exp_ch3.adb532
1 files changed, 352 insertions, 180 deletions
diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb
index e2263f3..1bfa9f2 100644
--- a/gcc/ada/exp_ch3.adb
+++ b/gcc/ada/exp_ch3.adb
@@ -214,6 +214,9 @@ package body Exp_Ch3 is
-- Check if E is defined in the RTL (in a child of Ada or System). Used
-- to avoid to bring in the overhead of _Input, _Output for tagged types.
+ function Is_Variable_Size_Array (E : Entity_Id) return Boolean;
+ -- Returns true if E has variable size components
+
function Is_Variable_Size_Record (E : Entity_Id) return Boolean;
-- Returns true if E has variable size components
@@ -1777,6 +1780,12 @@ package body Exp_Ch3 is
--
-- This function builds the call statement in this _init_proc.
+ procedure Build_CPP_Init_Procedure;
+ -- Build the tree corresponding to the procedure specification and body
+ -- of the IC procedure that initializes the C++ part of the dispatch
+ -- table of an Ada tagged type that is a derivation of a CPP type.
+ -- Install it as the CPP_Init TSS.
+
procedure Build_Init_Procedure;
-- Build the tree corresponding to the procedure specification and body
-- of the initialization procedure (by calling all the preceding
@@ -2209,6 +2218,104 @@ package body Exp_Ch3 is
end loop;
end Build_Offset_To_Top_Functions;
+ ------------------------------
+ -- Build_CPP_Init_Procedure --
+ ------------------------------
+
+ procedure Build_CPP_Init_Procedure is
+ Body_Node : Node_Id;
+ Body_Stmts : List_Id;
+ Flag_Id : Entity_Id;
+ Flag_Decl : Node_Id;
+ Handled_Stmt_Node : Node_Id;
+ Init_Tags_List : List_Id;
+ Proc_Id : Entity_Id;
+ Proc_Spec_Node : Node_Id;
+
+ begin
+ -- Check cases requiring no IC routine
+
+ if not Is_CPP_Class (Root_Type (Rec_Type))
+ or else Is_CPP_Class (Rec_Type)
+ or else CPP_Num_Prims (Rec_Type) = 0
+ or else not Tagged_Type_Expansion
+ or else No_Run_Time_Mode
+ then
+ return;
+ end if;
+
+ -- Generate:
+
+ -- Flag : Boolean := False;
+ --
+ -- procedure Typ_IC is
+ -- begin
+ -- if not Flag then
+ -- Copy C++ dispatch table slots from parent
+ -- Update C++ slots of overridden primitives
+ -- end if;
+ -- end;
+
+ Flag_Id := Make_Temporary (Loc, 'F');
+
+ Flag_Decl :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Flag_Id,
+ Object_Definition =>
+ New_Reference_To (Standard_Boolean, Loc),
+ Expression =>
+ New_Reference_To (Standard_True, Loc));
+
+ Analyze (Flag_Decl);
+ Append_Freeze_Action (Rec_Type, Flag_Decl);
+
+ Body_Stmts := New_List;
+ Body_Node := New_Node (N_Subprogram_Body, Loc);
+
+ Proc_Spec_Node := New_Node (N_Procedure_Specification, Loc);
+
+ Proc_Id :=
+ Make_Defining_Identifier (Loc,
+ Chars => Make_TSS_Name (Rec_Type, TSS_CPP_Init_Proc));
+
+ Set_Ekind (Proc_Id, E_Procedure);
+ Set_Is_Internal (Proc_Id);
+
+ Set_Defining_Unit_Name (Proc_Spec_Node, Proc_Id);
+
+ Set_Parameter_Specifications (Proc_Spec_Node, New_List);
+ Set_Specification (Body_Node, Proc_Spec_Node);
+ Set_Declarations (Body_Node, New_List);
+
+ Init_Tags_List := Build_Inherit_CPP_Prims (Rec_Type);
+
+ Append_To (Init_Tags_List,
+ Make_Assignment_Statement (Loc,
+ Name =>
+ New_Reference_To (Flag_Id, Loc),
+ Expression =>
+ New_Reference_To (Standard_False, Loc)));
+
+ Append_To (Body_Stmts,
+ Make_If_Statement (Loc,
+ Condition => New_Occurrence_Of (Flag_Id, Loc),
+ Then_Statements => Init_Tags_List));
+
+ Handled_Stmt_Node :=
+ New_Node (N_Handled_Sequence_Of_Statements, Loc);
+ Set_Statements (Handled_Stmt_Node, Body_Stmts);
+ Set_Exception_Handlers (Handled_Stmt_Node, No_List);
+ Set_Handled_Statement_Sequence (Body_Node, Handled_Stmt_Node);
+
+ if not Debug_Generated_Code then
+ Set_Debug_Info_Off (Proc_Id);
+ end if;
+
+ -- Associate CPP_Init_Proc with type
+
+ Set_Init_Proc (Rec_Type, Proc_Id);
+ end Build_CPP_Init_Procedure;
+
--------------------------
-- Build_Init_Procedure --
--------------------------
@@ -2239,9 +2346,7 @@ package body Exp_Ch3 is
-- a type extension. If the flag is false, we do not set the tag
-- because it has been set already in the extension.
- if Is_Tagged_Type (Rec_Type)
- and then not Is_CPP_Class (Rec_Type)
- then
+ if Is_Tagged_Type (Rec_Type) then
Set_Tag := Make_Temporary (Loc, 'P');
Append_To (Parameters,
@@ -2312,133 +2417,154 @@ package body Exp_Ch3 is
-- the C++ side.
if Is_Tagged_Type (Rec_Type)
- and then not Is_CPP_Class (Rec_Type)
and then Tagged_Type_Expansion
and then not No_Run_Time_Mode
then
- -- Initialize the primary tag
+ -- Case 1: Ada tagged types with no CPP ancestor. Set the tags of
+ -- the actual object and invoke the IP of the parent (in this
+ -- order). The tag must be initialized before the call to the IP
+ -- of the parent and the assignments to other components because
+ -- the initial value of the components may depend on the tag (eg.
+ -- through a dispatching operation on an access to the current
+ -- type). The tag assignment is not done when initializing the
+ -- parent component of a type extension, because in that case the
+ -- tag is set in the extension.
- Init_Tags_List := New_List (
- Make_Assignment_Statement (Loc,
- Name =>
- Make_Selected_Component (Loc,
- Prefix => Make_Identifier (Loc, Name_uInit),
- Selector_Name =>
- New_Reference_To (First_Tag_Component (Rec_Type), Loc)),
-
- Expression =>
- New_Reference_To
- (Node (First_Elmt (Access_Disp_Table (Rec_Type))), Loc)));
+ if not Is_CPP_Class (Root_Type (Rec_Type)) then
- -- Ada 2005 (AI-251): Initialize the secondary tags components
- -- located at fixed positions (tags whose position depends on
- -- variable size components are initialized later ---see below).
+ -- Initialize the primary tag component
- if Ada_Version >= Ada_05
- and then not Is_Interface (Rec_Type)
- and then Has_Interfaces (Rec_Type)
- then
- Init_Secondary_Tags
- (Typ => Rec_Type,
- Target => Make_Identifier (Loc, Name_uInit),
- Stmts_List => Init_Tags_List,
- Fixed_Comps => True,
- Variable_Comps => False);
- end if;
+ Init_Tags_List := New_List (
+ Make_Assignment_Statement (Loc,
+ Name =>
+ Make_Selected_Component (Loc,
+ Prefix => Make_Identifier (Loc, Name_uInit),
+ Selector_Name =>
+ New_Reference_To
+ (First_Tag_Component (Rec_Type), Loc)),
+ Expression =>
+ New_Reference_To
+ (Node
+ (First_Elmt (Access_Disp_Table (Rec_Type))), Loc)));
- -- The tag must be inserted before the assignments to other
- -- components, because the initial value of the component may
- -- depend on the tag (eg. through a dispatching operation on
- -- an access to the current type). The tag assignment is not done
- -- when initializing the parent component of a type extension,
- -- because in that case the tag is set in the extension.
+ -- Ada 2005 (AI-251): Initialize the secondary tags components
+ -- located at fixed positions (tags whose position depends on
+ -- variable size components are initialized later ---see below)
- -- Extensions of imported C++ classes add a final complication,
- -- because we cannot inhibit tag setting in the constructor for
- -- the parent. In that case we insert the tag initialization
- -- after the calls to initialize the parent.
+ if Ada_Version >= Ada_05
+ and then not Is_Interface (Rec_Type)
+ and then Has_Interfaces (Rec_Type)
+ then
+ Init_Secondary_Tags
+ (Typ => Rec_Type,
+ Target => Make_Identifier (Loc, Name_uInit),
+ Stmts_List => Init_Tags_List,
+ Fixed_Comps => True,
+ Variable_Comps => False);
+ end if;
- if not Is_CPP_Class (Root_Type (Rec_Type)) then
Prepend_To (Body_Stmts,
Make_If_Statement (Loc,
Condition => New_Occurrence_Of (Set_Tag, Loc),
Then_Statements => Init_Tags_List));
- -- CPP_Class derivation: In this case the dispatch table of the
- -- parent was built in the C++ side and we copy the table of the
- -- parent to initialize the new dispatch table.
+ -- Case 2: CPP type. The imported C++ constructor takes care of
+ -- tags initialization. No action needed here because the IP
+ -- is built by Set_CPP_Constructors; in this case the IP is a
+ -- wrapper that invokes the C++ constructor and copies the C++
+ -- tags locally. Done to inherit the C++ slots in Ada derivations
+ -- (see case 3).
+
+ elsif Is_CPP_Class (Rec_Type) then
+ pragma Assert (False);
+ null;
+
+ -- Case 3: Combined hierarchy containing C++ types and Ada tagged
+ -- type derivations. Derivations of imported C++ classes add a
+ -- complication, because we cannot inhibit tag setting in the
+ -- constructor for the parent. Hence we initialize the tag after
+ -- the call to the parent IP (that is, in reverse order compared
+ -- with pure Ada hierarchies ---see comment on case 1).
else
+ -- Initialize the primary tag
+
+ Init_Tags_List := New_List (
+ Make_Assignment_Statement (Loc,
+ Name =>
+ Make_Selected_Component (Loc,
+ Prefix => Make_Identifier (Loc, Name_uInit),
+ Selector_Name =>
+ New_Reference_To
+ (First_Tag_Component (Rec_Type), Loc)),
+ Expression =>
+ New_Reference_To
+ (Node
+ (First_Elmt (Access_Disp_Table (Rec_Type))), Loc)));
+
+ -- Ada 2005 (AI-251): Initialize the secondary tags components
+ -- located at fixed positions (tags whose position depends on
+ -- variable size components are initialized later ---see below)
+
+ if Ada_Version >= Ada_05
+ and then not Is_Interface (Rec_Type)
+ and then Has_Interfaces (Rec_Type)
+ then
+ Init_Secondary_Tags
+ (Typ => Rec_Type,
+ Target => Make_Identifier (Loc, Name_uInit),
+ Stmts_List => Init_Tags_List,
+ Fixed_Comps => True,
+ Variable_Comps => False);
+ end if;
+
+ -- Initialize the tag component after invocation of parent IP.
+
+ -- Generate:
+ -- parent_IP(_init.parent); // Invokes the C++ constructor
+ -- [ typIC; ] // Inherit C++ slots from parent
+ -- init_tags
+
declare
- Nod : Node_Id;
+ Ins_Nod : Node_Id;
begin
- -- We assume the first init_proc call is for the parent
+ -- Search for the call to the IP of the parent. We assume
+ -- that the first init_proc call is for the parent.
- Nod := First (Body_Stmts);
- while Present (Next (Nod))
- and then (Nkind (Nod) /= N_Procedure_Call_Statement
- or else not Is_Init_Proc (Name (Nod)))
+ Ins_Nod := First (Body_Stmts);
+ while Present (Next (Ins_Nod))
+ and then (Nkind (Ins_Nod) /= N_Procedure_Call_Statement
+ or else not Is_Init_Proc (Name (Ins_Nod)))
loop
- Nod := Next (Nod);
+ Next (Ins_Nod);
end loop;
- -- Generate:
- -- ancestor_constructor (_init.parent);
- -- if Arg2 then
- -- inherit_prim_ops (_init._tag, new_dt, num_prims);
- -- _init._tag := new_dt;
- -- end if;
-
- Prepend_To (Init_Tags_List,
- Build_Inherit_Prims (Loc,
- Typ => Rec_Type,
- Old_Tag_Node =>
- Make_Selected_Component (Loc,
- Prefix =>
- Make_Identifier (Loc,
- Chars => Name_uInit),
- Selector_Name =>
- New_Reference_To
- (First_Tag_Component (Rec_Type), Loc)),
- New_Tag_Node =>
- New_Reference_To
- (Node (First_Elmt (Access_Disp_Table (Rec_Type))),
- Loc),
- Num_Prims =>
- UI_To_Int
- (DT_Entry_Count (First_Tag_Component (Rec_Type)))));
-
- Insert_After (Nod,
- Make_If_Statement (Loc,
- Condition => New_Occurrence_Of (Set_Tag, Loc),
- Then_Statements => Init_Tags_List));
-
- -- We have inherited table of the parent from the CPP side.
- -- Now we fill the slots associated with Ada primitives.
- -- This needs more work to avoid its execution each time
- -- an object is initialized???
+ -- The IC routine copies the inherited slots of the C+ part
+ -- of the dispatch table from the parent and updates the
+ -- overridden C++ slots.
- declare
- E : Elmt_Id;
- Prim : Node_Id;
+ if CPP_Num_Prims (Rec_Type) > 0 then
+ declare
+ Init_DT : Entity_Id;
+ New_Nod : Node_Id;
- begin
- E := First_Elmt (Primitive_Operations (Rec_Type));
- while Present (E) loop
- Prim := Node (E);
+ begin
+ Init_DT := CPP_Init_Proc (Rec_Type);
+ pragma Assert (Present (Init_DT));
- if not Is_Imported (Prim)
- and then Convention (Prim) = Convention_CPP
- and then not Present (Interface_Alias (Prim))
- then
- Append_List_To (Init_Tags_List,
- Register_Primitive (Loc, Prim => Prim));
- end if;
+ New_Nod :=
+ Make_Procedure_Call_Statement (Loc,
+ New_Reference_To (Init_DT, Loc));
+ Insert_After (Ins_Nod, New_Nod);
- Next_Elmt (E);
- end loop;
- end;
+ -- Update location of init tag statements
+
+ Ins_Nod := New_Nod;
+ end;
+ end if;
+
+ Insert_List_After (Ins_Nod, Init_Tags_List);
end;
end if;
@@ -3116,7 +3242,8 @@ package body Exp_Ch3 is
-- at the other end of the call, even if it does nothing!)
-- Note: the reason we exclude the CPP_Class case is because in this
- -- case the initialization is performed in the C++ side.
+ -- case the initialization is performed by the C++ constructors, and
+ -- the IP is built by Set_CPP_Constructors.
if Is_CPP_Class (Rec_Id) then
return False;
@@ -3243,6 +3370,7 @@ package body Exp_Ch3 is
end if;
Build_Offset_To_Top_Functions;
+ Build_CPP_Init_Procedure;
Build_Init_Procedure;
Set_Is_Public (Proc_Id, Is_Public (Pe));
@@ -5720,7 +5848,6 @@ package body Exp_Ch3 is
if Is_CPP_Class (Def_Id) then
Set_All_DT_Position (Def_Id);
- Set_CPP_Constructors (Def_Id);
-- Create the tag entities with a minimum decoration
@@ -5728,6 +5855,8 @@ package body Exp_Ch3 is
Append_Freeze_Actions (Def_Id, Make_Tags (Def_Id));
end if;
+ Set_CPP_Constructors (Def_Id);
+
else
if not Has_Static_DT then
@@ -6930,11 +7059,6 @@ package body Exp_Ch3 is
is
Loc : constant Source_Ptr := Sloc (Target);
- procedure Inherit_CPP_Tag
- (Typ : Entity_Id;
- Iface : Entity_Id;
- Tag_Comp : Entity_Id;
- Iface_Tag : Node_Id);
-- Inherit the C++ tag of the secondary dispatch table of Typ associated
-- with Iface. Tag_Comp is the component of Typ that stores Iface_Tag.
@@ -6949,32 +7073,6 @@ package body Exp_Ch3 is
-- of Typ CPP tagged type we generate code to inherit the contents of
-- the dispatch table directly from the ancestor.
- ---------------------
- -- Inherit_CPP_Tag --
- ---------------------
-
- procedure Inherit_CPP_Tag
- (Typ : Entity_Id;
- Iface : Entity_Id;
- Tag_Comp : Entity_Id;
- Iface_Tag : Node_Id)
- is
- begin
- pragma Assert (Is_CPP_Class (Etype (Typ)));
-
- Append_To (Stmts_List,
- Build_Inherit_Prims (Loc,
- Typ => Iface,
- Old_Tag_Node =>
- Make_Selected_Component (Loc,
- Prefix => New_Copy_Tree (Target),
- Selector_Name => New_Reference_To (Tag_Comp, Loc)),
- New_Tag_Node =>
- New_Reference_To (Iface_Tag, Loc),
- Num_Prims =>
- UI_To_Int (DT_Entry_Count (First_Tag_Component (Iface)))));
- end Inherit_CPP_Tag;
-
--------------------
-- Initialize_Tag --
--------------------
@@ -7175,26 +7273,85 @@ package body Exp_Ch3 is
while Present (Iface_Elmt) loop
Tag_Comp := Node (Iface_Comp_Elmt);
+ -- Check if parent of record type has variable size components
+
+ In_Variable_Pos := Scope (Tag_Comp) /= Etype (Scope (Tag_Comp))
+ and then Is_Variable_Size_Record (Etype (Scope (Tag_Comp)));
+
-- If we are compiling under the CPP full ABI compatibility mode and
-- the ancestor is a CPP_Pragma tagged type then we generate code to
- -- inherit the contents of the dispatch table directly from the
- -- ancestor.
+ -- initialize the secondary tag components from tags that reference
+ -- secondary tables filled with copy of parent slots.
- if Is_CPP_Class (Etype (Full_Typ)) then
- Inherit_CPP_Tag (Full_Typ,
- Iface => Node (Iface_Elmt),
- Tag_Comp => Tag_Comp,
- Iface_Tag => Node (Iface_Tag_Elmt));
+ if Is_CPP_Class (Root_Type (Full_Typ)) then
- -- Otherwise generate code to initialize the tag
+ -- Reject interface components located at variable offset in
+ -- C++ derivations. This is currently unsupported.
- else
- -- Check if the parent of the record type has variable size
- -- components.
+ if not Fixed_Comps and then In_Variable_Pos then
+
+ -- Locate the first dynamic component of the record. Done to
+ -- improve the text of the warning.
- In_Variable_Pos := Scope (Tag_Comp) /= Etype (Scope (Tag_Comp))
- and then Is_Variable_Size_Record (Etype (Scope (Tag_Comp)));
+ declare
+ Comp : Entity_Id;
+ Comp_Typ : Entity_Id;
+
+ begin
+ Comp := First_Entity (Typ);
+ while Present (Comp) loop
+ Comp_Typ := Etype (Comp);
+
+ if Ekind (Comp) /= E_Discriminant
+ and then not Is_Tag (Comp)
+ then
+ exit when
+ (Is_Record_Type (Comp_Typ)
+ and then Is_Variable_Size_Record
+ (Base_Type (Comp_Typ)))
+ or else
+ (Is_Array_Type (Comp_Typ)
+ and then Is_Variable_Size_Array (Comp_Typ));
+ end if;
+
+ Next_Entity (Comp);
+ end loop;
+ pragma Assert (Present (Comp));
+ Error_Msg_Node_2 := Comp;
+ Error_Msg_NE
+ ("parent type & with dynamic component & cannot be parent"
+ & " of 'C'P'P derivation if new interfaces are present",
+ Typ, Scope (Original_Record_Component (Comp)));
+
+ Error_Msg_Sloc :=
+ Sloc (Scope (Original_Record_Component (Comp)));
+ Error_Msg_NE
+ ("type derived from 'C'P'P type & defined #",
+ Typ, Scope (Original_Record_Component (Comp)));
+
+ -- Avoid duplicated warnings
+
+ exit;
+ end;
+
+ -- Initialize secondary tags
+
+ else
+ Append_To (Stmts_List,
+ Make_Assignment_Statement (Loc,
+ Name =>
+ Make_Selected_Component (Loc,
+ Prefix => New_Copy_Tree (Target),
+ Selector_Name =>
+ New_Reference_To (Node (Iface_Comp_Elmt), Loc)),
+ Expression =>
+ New_Reference_To (Node (Iface_Tag_Elmt), Loc)));
+ end if;
+
+ -- Otherwise generate code to initialize the tag
+
+ else
if (In_Variable_Pos and then Variable_Comps)
or else (not In_Variable_Pos and then Fixed_Comps)
then
@@ -7211,14 +7368,11 @@ package body Exp_Ch3 is
end loop;
end Init_Secondary_Tags;
- -----------------------------
- -- Is_Variable_Size_Record --
- -----------------------------
+ ----------------------------
+ -- Is_Variable_Size_Array --
+ ----------------------------
- function Is_Variable_Size_Record (E : Entity_Id) return Boolean is
- Comp : Entity_Id;
- Comp_Typ : Entity_Id;
- Idx : Node_Id;
+ function Is_Variable_Size_Array (E : Entity_Id) return Boolean is
function Is_Constant_Bound (Exp : Node_Id) return Boolean;
-- To simplify handling of array components. Determines whether the
@@ -7244,42 +7398,60 @@ package body Exp_Ch3 is
end if;
end Is_Constant_Bound;
- -- Start of processing for Is_Variable_Sized_Record
+ -- Local variables
- begin
- pragma Assert (Is_Record_Type (E));
+ Idx : Node_Id;
- Comp := First_Entity (E);
- while Present (Comp) loop
- Comp_Typ := Etype (Comp);
+ -- Start of processing for Is_Variable_Sized_Array
- if Is_Record_Type (Comp_Typ) then
+ begin
+ pragma Assert (Is_Array_Type (E));
- -- Recursive call if the record type has discriminants
+ -- Check if some index is initialized with a non-constant value
- if Has_Discriminants (Comp_Typ)
- and then Is_Variable_Size_Record (Comp_Typ)
+ Idx := First_Index (E);
+ while Present (Idx) loop
+ if Nkind (Idx) = N_Range then
+ if not Is_Constant_Bound (Low_Bound (Idx))
+ or else not Is_Constant_Bound (High_Bound (Idx))
then
return True;
end if;
+ end if;
- elsif Is_Array_Type (Comp_Typ) then
+ Idx := Next_Index (Idx);
+ end loop;
- -- Check if some index is initialized with a non-constant value
+ return False;
+ end Is_Variable_Size_Array;
- Idx := First_Index (Comp_Typ);
- while Present (Idx) loop
- if Nkind (Idx) = N_Range then
- if not Is_Constant_Bound (Low_Bound (Idx))
- or else
- not Is_Constant_Bound (High_Bound (Idx))
- then
- return True;
- end if;
- end if;
+ -----------------------------
+ -- Is_Variable_Size_Record --
+ -----------------------------
- Idx := Next_Index (Idx);
- end loop;
+ function Is_Variable_Size_Record (E : Entity_Id) return Boolean is
+ Comp : Entity_Id;
+ Comp_Typ : Entity_Id;
+
+ begin
+ pragma Assert (Is_Record_Type (E));
+
+ Comp := First_Entity (E);
+ while Present (Comp) loop
+ Comp_Typ := Etype (Comp);
+
+ -- Recursive call if the record type has discriminants
+
+ if Is_Record_Type (Comp_Typ)
+ and then Has_Discriminants (Comp_Typ)
+ and then Is_Variable_Size_Record (Comp_Typ)
+ then
+ return True;
+
+ elsif Is_Array_Type (Comp_Typ)
+ and then Is_Variable_Size_Array (Comp_Typ)
+ then
+ return True;
end if;
Next_Entity (Comp);