-- Build a specification for a function implementing the protected entry
-- barrier of the specified entry body.
+ procedure Build_Contract_Wrapper (E : Entity_Id; Decl : Node_Id);
+ -- Build the body of a wrapper procedure for an entry or entry family that
+ -- has contract cases, preconditions, or postconditions. The body gathers
+ -- the executable contract items and expands them in the usual way, and
+ -- performs the entry call itself. This way preconditions are evaluated
+ -- before the call is queued. E is the entry in question, and Decl is the
+ -- enclosing synchronized type declaration at whose freeze point the
+ -- generated body is analyzed.
+
function Build_Corresponding_Record
(N : Node_Id;
Ctyp : Node_Id;
-- <formalN> : AnnN;
-- end record;
- procedure Build_PPC_Wrapper (E : Entity_Id; Decl : Node_Id);
- -- Build body of wrapper procedure for an entry or entry family that has
- -- pre/postconditions. The body gathers the PPC's and expands them in the
- -- usual way, and performs the entry call itself. This way preconditions
- -- are evaluated before the call is queued. E is the entry in question,
- -- and Decl is the enclosing synchronized type declaration at whose freeze
- -- point the generated body is analyzed.
-
function Build_Protected_Entry
(N : Node_Id;
Ent : Entity_Id;
Context_Decls : out List_Id);
-- Subsidiary routine to procedures Build_Activation_Chain_Entity and
-- Build_Master_Entity. Given an arbitrary node in the tree, find the
- -- nearest enclosing body, block, package or return statement and return
+ -- nearest enclosing body, block, package, or return statement and return
-- its constituents. Context is the enclosing construct, Context_Id is
-- the scope of Context_Id and Context_Decls is the declarative list of
-- Context.
Set_Master_Id (Typ, Master_Id);
end Build_Class_Wide_Master;
+ ----------------------------
+ -- Build_Contract_Wrapper --
+ ----------------------------
+
+ procedure Build_Contract_Wrapper (E : Entity_Id; Decl : Node_Id) is
+ Conc_Typ : constant Entity_Id := Scope (E);
+ Loc : constant Source_Ptr := Sloc (E);
+
+ procedure Add_Discriminant_Renamings
+ (Obj_Id : Entity_Id;
+ Decls : List_Id);
+ -- Add renaming declarations for all discriminants of concurrent type
+ -- Conc_Typ. Obj_Id is the entity of the wrapper formal parameter which
+ -- represents the concurrent object.
+
+ procedure Add_Matching_Formals (Formals : List_Id; Actuals : List_Id);
+ -- Add formal parameters that match those of entry E to list Formals.
+ -- The routine also adds matching actuals for the new formals to list
+ -- Actuals.
+
+ procedure Transfer_Pragma (Prag : Node_Id; To : in out List_Id);
+ -- Relocate pragma Prag to list To. The routine creates a new list if
+ -- To does not exist.
+
+ --------------------------------
+ -- Add_Discriminant_Renamings --
+ --------------------------------
+
+ procedure Add_Discriminant_Renamings
+ (Obj_Id : Entity_Id;
+ Decls : List_Id)
+ is
+ Discr : Entity_Id;
+
+ begin
+ -- Inspect the discriminants of the concurrent type and generate a
+ -- renaming for each one.
+
+ if Has_Discriminants (Conc_Typ) then
+ Discr := First_Discriminant (Conc_Typ);
+ while Present (Discr) loop
+ Prepend_To (Decls,
+ Make_Object_Renaming_Declaration (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Loc, Chars (Discr)),
+ Subtype_Mark =>
+ New_Occurrence_Of (Etype (Discr), Loc),
+ Name =>
+ Make_Selected_Component (Loc,
+ Prefix => New_Occurrence_Of (Obj_Id, Loc),
+ Selector_Name =>
+ Make_Identifier (Loc, Chars (Discr)))));
+
+ Next_Discriminant (Discr);
+ end loop;
+ end if;
+ end Add_Discriminant_Renamings;
+
+ --------------------------
+ -- Add_Matching_Formals --
+ --------------------------
+
+ procedure Add_Matching_Formals (Formals : List_Id; Actuals : List_Id) is
+ Formal : Entity_Id;
+ New_Formal : Entity_Id;
+
+ begin
+ -- Inspect the formal parameters of the entry and generate a new
+ -- matching formal with the same name for the wrapper. A reference
+ -- to the new formal becomes an actual in the entry call.
+
+ Formal := First_Formal (E);
+ while Present (Formal) loop
+ New_Formal := Make_Defining_Identifier (Loc, Chars (Formal));
+ Append_To (Formals,
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier => New_Formal,
+ In_Present => In_Present (Parent (Formal)),
+ Out_Present => Out_Present (Parent (Formal)),
+ Parameter_Type =>
+ New_Occurrence_Of (Etype (Formal), Loc)));
+
+ Append_To (Actuals, New_Occurrence_Of (New_Formal, Loc));
+ Next_Formal (Formal);
+ end loop;
+ end Add_Matching_Formals;
+
+ ---------------------
+ -- Transfer_Pragma --
+ ---------------------
+
+ procedure Transfer_Pragma (Prag : Node_Id; To : in out List_Id) is
+ New_Prag : Node_Id;
+
+ begin
+ if No (To) then
+ To := New_List;
+ end if;
+
+ New_Prag := Relocate_Node (Prag);
+
+ Set_Analyzed (New_Prag, False);
+ Append (New_Prag, To);
+ end Transfer_Pragma;
+
+ -- Local variables
+
+ Items : constant Node_Id := Contract (E);
+ Actuals : List_Id;
+ Call : Node_Id;
+ Call_Nam : Node_Id;
+ Decls : List_Id := No_List;
+ Formals : List_Id;
+ Has_Pragma : Boolean := False;
+ Index_Id : Entity_Id;
+ Obj_Id : Entity_Id;
+ Prag : Node_Id;
+ Wrapper_Id : Entity_Id;
+
+ -- Start of processing for Build_Contract_Wrapper
+
+ begin
+ -- This routine generates a specialized wrapper for a protected or task
+ -- entry [family] which implements precondition/postcondition semantics.
+ -- Preconditions and case guards of contract cases are checked before
+ -- the protected action or rendezvous takes place. Postconditions and
+ -- consequences of contract cases are checked after the protected action
+ -- or rendezvous takes place. The structure of the generated wrapper is
+ -- as follows:
+
+ -- procedure Wrapper
+ -- (Obj_Id : Conc_Typ; -- concurrent object
+ -- [Index : Index_Typ;] -- index of entry family
+ -- [Formal_1 : ...; -- parameters of original entry
+ -- Formal_N : ...])
+ -- is
+ -- [Discr_1 : ... renames Obj_Id.Discr_1; -- discriminant
+ -- Discr_N : ... renames Obj_Id.Discr_N;] -- renamings
+
+ -- <precondition checks>
+ -- <case guard checks>
+
+ -- procedure _Postconditions is
+ -- begin
+ -- <postcondition checks>
+ -- <consequence checks>
+ -- end _Postconditions;
+
+ -- begin
+ -- Entry_Call (Obj_Id, [Index,] [Formal_1, Formal_N]);
+ -- _Postconditions;
+ -- end Wrapper;
+
+ -- Create the wrapper only when the entry has at least one executable
+ -- contract item such as contract cases, precondition or postcondition.
+
+ if Present (Items) then
+
+ -- Inspect the list of pre/postconditions and transfer all available
+ -- pragmas to the declarative list of the wrapper.
+
+ Prag := Pre_Post_Conditions (Items);
+ while Present (Prag) loop
+ if Nam_In (Pragma_Name (Prag), Name_Postcondition,
+ Name_Precondition)
+ then
+ Has_Pragma := True;
+ Transfer_Pragma (Prag, To => Decls);
+ end if;
+
+ Prag := Next_Pragma (Prag);
+ end loop;
+
+ -- Inspect the list of test/contract cases and transfer only contract
+ -- cases pragmas to the declarative part of the wrapper.
+
+ Prag := Contract_Test_Cases (Items);
+ while Present (Prag) loop
+ if Pragma_Name (Prag) = Name_Contract_Cases then
+ Has_Pragma := True;
+ Transfer_Pragma (Prag, To => Decls);
+ end if;
+
+ Prag := Next_Pragma (Prag);
+ end loop;
+ end if;
+
+ -- The entry lacks executable contract items and a wrapper is not needed
+
+ if not Has_Pragma then
+ return;
+ end if;
+
+ -- Create the profile of the wrapper. The first formal parameter is the
+ -- concurrent object.
+
+ Obj_Id :=
+ Make_Defining_Identifier (Loc,
+ Chars => New_External_Name (Chars (Conc_Typ), 'A'));
+
+ Formals := New_List (
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier => Obj_Id,
+ Out_Present => True,
+ In_Present => True,
+ Parameter_Type => New_Occurrence_Of (Conc_Typ, Loc)));
+
+ -- Construct the call to the original entry. The call will be gradually
+ -- augmented with an optional entry index and extra parameters.
+
+ Call_Nam :=
+ Make_Selected_Component (Loc,
+ Prefix => New_Occurrence_Of (Obj_Id, Loc),
+ Selector_Name => New_Occurrence_Of (E, Loc));
+
+ -- When creating a wrapper for an entry family, the second formal is the
+ -- entry index.
+
+ if Ekind (E) = E_Entry_Family then
+ Index_Id := Make_Defining_Identifier (Loc, Name_I);
+
+ Append_To (Formals,
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier => Index_Id,
+ Parameter_Type =>
+ New_Occurrence_Of (Entry_Index_Type (E), Loc)));
+
+ -- The call to the original entry becomes an indexed component to
+ -- accommodate the entry index.
+
+ Call_Nam :=
+ Make_Indexed_Component (Loc,
+ Prefix => Call_Nam,
+ Expressions => New_List (New_Occurrence_Of (Index_Id, Loc)));
+ end if;
+
+ Actuals := New_List;
+ Call :=
+ Make_Procedure_Call_Statement (Loc,
+ Name => Call_Nam,
+ Parameter_Associations => Actuals);
+
+ -- Add formal parameters to match those of the entry and build actuals
+ -- for the entry call.
+
+ Add_Matching_Formals (Formals, Actuals);
+
+ -- Add renaming declarations for the discriminants of the enclosing type
+ -- as the various contract items may reference them.
+
+ Add_Discriminant_Renamings (Obj_Id, Decls);
+
+ Wrapper_Id :=
+ Make_Defining_Identifier (Loc, New_External_Name (Chars (E), 'E'));
+ Set_Contract_Wrapper (E, Wrapper_Id);
+
+ -- The wrapper body is analyzed when the enclosing type is frozen
+
+ Append_Freeze_Action (Defining_Entity (Decl),
+ Make_Subprogram_Body (Loc,
+ Specification =>
+ Make_Procedure_Specification (Loc,
+ Defining_Unit_Name => Wrapper_Id,
+ Parameter_Specifications => Formals),
+ Declarations => Decls,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (Call))));
+ end Build_Contract_Wrapper;
+
--------------------------------
-- Build_Corresponding_Record --
--------------------------------
return Decl;
end Build_Renamed_Formal_Declaration;
- -----------------------
- -- Build_PPC_Wrapper --
- -----------------------
-
- procedure Build_PPC_Wrapper (E : Entity_Id; Decl : Node_Id) is
- Items : constant Node_Id := Contract (E);
- Loc : constant Source_Ptr := Sloc (E);
- Synch_Type : constant Entity_Id := Scope (E);
- Actuals : List_Id;
- Decls : List_Id;
- Entry_Call : Node_Id;
- Entry_Name : Node_Id;
- Params : List_Id;
- Prag : Node_Id;
- Synch_Id : Entity_Id;
- Wrapper_Id : Entity_Id;
-
- begin
- -- Only build the wrapper if entry has pre/postconditions
- -- Should this be done unconditionally instead ???
-
- if Present (Items) then
- Prag := Pre_Post_Conditions (Items);
-
- if No (Prag) then
- return;
- end if;
-
- -- Transfer ppc pragmas to the declarations of the wrapper
-
- Decls := New_List;
-
- while Present (Prag) loop
- if Nam_In (Pragma_Name (Prag), Name_Precondition,
- Name_Postcondition)
- then
- Append (Relocate_Node (Prag), Decls);
- Set_Analyzed (Last (Decls), False);
- end if;
-
- Prag := Next_Pragma (Prag);
- end loop;
- else
- return;
- end if;
-
- Actuals := New_List;
- Synch_Id :=
- Make_Defining_Identifier (Loc,
- Chars => New_External_Name (Chars (Scope (E)), 'A'));
-
- -- First formal is synchronized object
-
- Params := New_List (
- Make_Parameter_Specification (Loc,
- Defining_Identifier => Synch_Id,
- Out_Present => True,
- In_Present => True,
- Parameter_Type => New_Occurrence_Of (Scope (E), Loc)));
-
- Entry_Name :=
- Make_Selected_Component (Loc,
- Prefix => New_Occurrence_Of (Synch_Id, Loc),
- Selector_Name => New_Occurrence_Of (E, Loc));
-
- -- If entity is entry family, second formal is the corresponding index,
- -- and entry name is an indexed component.
-
- if Ekind (E) = E_Entry_Family then
- declare
- Index : constant Entity_Id :=
- Make_Defining_Identifier (Loc, Name_I);
- begin
- Append_To (Params,
- Make_Parameter_Specification (Loc,
- Defining_Identifier => Index,
- Parameter_Type =>
- New_Occurrence_Of (Entry_Index_Type (E), Loc)));
-
- Entry_Name :=
- Make_Indexed_Component (Loc,
- Prefix => Entry_Name,
- Expressions => New_List (New_Occurrence_Of (Index, Loc)));
- end;
- end if;
-
- Entry_Call :=
- Make_Procedure_Call_Statement (Loc,
- Name => Entry_Name,
- Parameter_Associations => Actuals);
-
- -- Now add formals that match those of the entry, and build actuals for
- -- the nested entry call.
-
- declare
- Form : Entity_Id;
- New_Form : Entity_Id;
- Parm_Spec : Node_Id;
-
- begin
- Form := First_Formal (E);
- while Present (Form) loop
- New_Form := Make_Defining_Identifier (Loc, Chars (Form));
- Parm_Spec :=
- Make_Parameter_Specification (Loc,
- Defining_Identifier => New_Form,
- Out_Present => Out_Present (Parent (Form)),
- In_Present => In_Present (Parent (Form)),
- Parameter_Type => New_Occurrence_Of (Etype (Form), Loc));
-
- Append (Parm_Spec, Params);
- Append (New_Occurrence_Of (New_Form, Loc), Actuals);
- Next_Formal (Form);
- end loop;
- end;
-
- -- Add renaming declarations for the discriminants of the enclosing
- -- type, which may be visible in the preconditions.
-
- if Has_Discriminants (Synch_Type) then
- declare
- D : Entity_Id;
- Decl : Node_Id;
-
- begin
- D := First_Discriminant (Synch_Type);
- while Present (D) loop
- Decl :=
- Make_Object_Renaming_Declaration (Loc,
- Defining_Identifier =>
- Make_Defining_Identifier (Loc, Chars (D)),
- Subtype_Mark => New_Occurrence_Of (Etype (D), Loc),
- Name =>
- Make_Selected_Component (Loc,
- Prefix => New_Occurrence_Of (Synch_Id, Loc),
- Selector_Name => Make_Identifier (Loc, Chars (D))));
- Prepend (Decl, Decls);
- Next_Discriminant (D);
- end loop;
- end;
- end if;
-
- Wrapper_Id :=
- Make_Defining_Identifier (Loc, New_External_Name (Chars (E), 'E'));
- Set_PPC_Wrapper (E, Wrapper_Id);
-
- -- The wrapper body is analyzed when the enclosing type is frozen
-
- Append_Freeze_Action (Defining_Entity (Decl),
- Make_Subprogram_Body (Loc,
- Specification =>
- Make_Procedure_Specification (Loc,
- Defining_Unit_Name => Wrapper_Id,
- Parameter_Specifications => Params),
- Declarations => Decls,
- Handled_Statement_Sequence =>
- Make_Handled_Sequence_Of_Statements (Loc,
- Statements => New_List (Entry_Call))));
- end Build_PPC_Wrapper;
-
--------------------------
-- Build_Wrapper_Bodies --
--------------------------
-- Start of processing for Build_Lock_Free_Unprotected_Subprogram_Body
begin
- -- Add renamings for the protection object, discriminals, privals and
+ -- Add renamings for the protection object, discriminals, privals, and
-- the entry index constant for use by debugger.
Debug_Private_Data_Declarations (Decls);
Decls := List_Containing (Context);
-- Default case for object declarations and access types. Note that the
- -- context is updated to the nearest enclosing body, block, package or
+ -- context is updated to the nearest enclosing body, block, package, or
-- return statement.
else
Ent : Entity_Id;
Pid : Node_Id) return Node_Id
is
+ Bod_Decls : constant List_Id := New_List;
+ Decls : constant List_Id := Declarations (N);
+ End_Lab : constant Node_Id :=
+ End_Label (Handled_Statement_Sequence (N));
+ End_Loc : constant Source_Ptr :=
+ Sloc (Last (Statements (Handled_Statement_Sequence (N))));
+ -- Used for the generated call to Complete_Entry_Body
+
Loc : constant Source_Ptr := Sloc (N);
- Decls : constant List_Id := Declarations (N);
- End_Lab : constant Node_Id :=
- End_Label (Handled_Statement_Sequence (N));
- End_Loc : constant Source_Ptr :=
- Sloc (Last (Statements (Handled_Statement_Sequence (N))));
- -- Used for the generated call to Complete_Entry_Body
+ Bod_Id : Entity_Id;
+ Bod_Spec : Node_Id;
+ Bod_Stmts : List_Id;
+ Complete : Node_Id;
+ Ohandle : Node_Id;
- Han_Loc : Source_Ptr;
+ EH_Loc : Source_Ptr;
-- Used for the exception handler, inserted at end of the body
- Op_Decls : constant List_Id := New_List;
- Complete : Node_Id;
- Edef : Entity_Id;
- Espec : Node_Id;
- Ohandle : Node_Id;
- Op_Stats : List_Id;
-
begin
-- Set the source location on the exception handler only when debugging
-- the expanded code (see Make_Implicit_Exception_Handler).
if Debug_Generated_Code then
- Han_Loc := End_Loc;
+ EH_Loc := End_Loc;
-- Otherwise the inserted code should not be visible to the debugger
else
- Han_Loc := No_Location;
+ EH_Loc := No_Location;
end if;
- Edef :=
+ Bod_Id :=
Make_Defining_Identifier (Loc,
Chars => Chars (Protected_Body_Subprogram (Ent)));
- Espec :=
- Build_Protected_Entry_Specification (Loc, Edef, Empty);
+ Bod_Spec := Build_Protected_Entry_Specification (Loc, Bod_Id, Empty);
-- Add the following declarations:
-- where _O is the formal parameter associated with the concurrent
-- object. These declarations are needed for Complete_Entry_Body.
- Add_Object_Pointer (Loc, Pid, Op_Decls);
+ Add_Object_Pointer (Loc, Pid, Bod_Decls);
-- Add renamings for all formals, the Protection object, discriminals,
-- privals and the entry index constant for use by debugger.
- Add_Formal_Renamings (Espec, Op_Decls, Ent, Loc);
+ Add_Formal_Renamings (Bod_Spec, Bod_Decls, Ent, Loc);
Debug_Private_Data_Declarations (Decls);
-- Put the declarations and the statements from the entry
- Op_Stats :=
+ Bod_Stmts :=
New_List (
Make_Block_Statement (Loc,
- Declarations => Decls,
- Handled_Statement_Sequence =>
- Handled_Statement_Sequence (N)));
+ Declarations => Decls,
+ Handled_Statement_Sequence => Handled_Statement_Sequence (N)));
case Corresponding_Runtime_Package (Pid) is
when System_Tasking_Protected_Objects_Entries =>
- Append_To (Op_Stats,
+ Append_To (Bod_Stmts,
Make_Procedure_Call_Statement (End_Loc,
Name =>
New_Occurrence_Of (RTE (RE_Complete_Entry_Body), Loc),
end case;
-- When exceptions can not be propagated, we never need to call
- -- Exception_Complete_Entry_Body
+ -- Exception_Complete_Entry_Body.
if No_Exception_Handlers_Set then
return
Make_Subprogram_Body (Loc,
- Specification => Espec,
- Declarations => Op_Decls,
+ Specification => Bod_Spec,
+ Declarations => Bod_Decls,
Handled_Statement_Sequence =>
Make_Handled_Sequence_Of_Statements (Loc,
- Statements => Op_Stats,
+ Statements => Bod_Stmts,
End_Label => End_Lab));
else
-- Establish link between subprogram body entity and source entry
- Set_Corresponding_Protected_Entry (Edef, Ent);
+ Set_Corresponding_Protected_Entry (Bod_Id, Ent);
-- Create body of entry procedure. The renaming declarations are
-- placed ahead of the block that contains the actual entry body.
return
Make_Subprogram_Body (Loc,
- Specification => Espec,
- Declarations => Op_Decls,
+ Specification => Bod_Spec,
+ Declarations => Bod_Decls,
Handled_Statement_Sequence =>
Make_Handled_Sequence_Of_Statements (Loc,
- Statements => Op_Stats,
- End_Label => End_Lab,
+ Statements => Bod_Stmts,
+ End_Label => End_Lab,
Exception_Handlers => New_List (
- Make_Implicit_Exception_Handler (Han_Loc,
+ Make_Implicit_Exception_Handler (EH_Loc,
Exception_Choices => New_List (Ohandle),
- Statements => New_List (
- Make_Procedure_Call_Statement (Han_Loc,
- Name => Complete,
+ Statements => New_List (
+ Make_Procedure_Call_Statement (EH_Loc,
+ Name => Complete,
Parameter_Associations => New_List (
- Make_Attribute_Reference (Han_Loc,
- Prefix =>
- Make_Selected_Component (Han_Loc,
+ Make_Attribute_Reference (EH_Loc,
+ Prefix =>
+ Make_Selected_Component (EH_Loc,
Prefix =>
- Make_Identifier (Han_Loc, Name_uObject),
+ Make_Identifier (EH_Loc, Name_uObject),
Selector_Name =>
- Make_Identifier (Han_Loc, Name_uObject)),
- Attribute_Name => Name_Unchecked_Access),
+ Make_Identifier (EH_Loc, Name_uObject)),
+ Attribute_Name => Name_Unchecked_Access),
- Make_Function_Call (Han_Loc,
- Name => New_Occurrence_Of (
- RTE (RE_Get_GNAT_Exception), Loc)))))))));
+ Make_Function_Call (EH_Loc,
+ Name =>
+ New_Occurrence_Of
+ (RTE (RE_Get_GNAT_Exception), Loc)))))))));
end if;
end Build_Protected_Entry;
Decls : constant List_Id := Declarations (N);
begin
- -- Add renamings for the Protection object, discriminals, privals and
+ -- Add renamings for the Protection object, discriminals, privals, and
-- the entry index constant for use by debugger.
Debug_Private_Data_Declarations (Decls);
if Nkind_In (Decl, N_Full_Type_Declaration, N_Object_Declaration) then
Set_Debug_Info_Needed (Defining_Identifier (Decl));
- -- Declaration for the Protection object, discriminals, privals and
+ -- Declaration for the Protection object, discriminals, privals, and
-- entry index constant:
-- conc_typR : protection_typ renames _object._object;
-- discr_nameD : discr_typ renames _object.discr_name;
Insert_After (Current_Node, Sub);
Analyze (Sub);
- -- Build wrapper procedure for pre/postconditions
+ -- Build a wrapper procedure to handle contract cases, preconditions,
+ -- and postconditions.
- Build_PPC_Wrapper (Comp_Id, N);
+ Build_Contract_Wrapper (Comp_Id, N);
Set_Protected_Body_Subprogram
(Defining_Identifier (Comp),
Expand_Previous_Access_Type (Tasktyp);
- -- Create wrappers for entries that have pre/postconditions
+ -- Create wrappers for entries that have contract cases, preconditions
+ -- and postconditions.
declare
Ent : Entity_Id;
begin
Ent := First_Entity (Tasktyp);
while Present (Ent) loop
- if Ekind_In (Ent, E_Entry, E_Entry_Family)
- and then Present (Contract (Ent))
- and then Present (Pre_Post_Conditions (Contract (Ent)))
- then
- Build_PPC_Wrapper (Ent, N);
+ if Ekind_In (Ent, E_Entry, E_Entry_Family) then
+ Build_Contract_Wrapper (Ent, N);
end if;
Next_Entity (Ent);