------------------------------------------------------------------------------ -- -- -- GNAT COMPILER COMPONENTS -- -- -- -- S E M _ C H 3 -- -- -- -- B o d y -- -- -- -- Copyright (C) 1992-2022, 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- -- -- ware Foundation; either version 3, or (at your option) any later ver- -- -- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- -- for more details. You should have received a copy of the GNU General -- -- Public License distributed with GNAT; see file COPYING3. If not, go to -- -- http://www.gnu.org/licenses for a complete copy of the license. -- -- -- -- GNAT was originally developed by the GNAT team at New York University. -- -- Extensive contributions were provided by Ada Core Technologies Inc. -- -- -- ------------------------------------------------------------------------------ with Aspects; use Aspects; with Atree; use Atree; with Checks; use Checks; with Contracts; use Contracts; with Debug; use Debug; with Elists; use Elists; with Einfo; use Einfo; with Einfo.Entities; use Einfo.Entities; with Einfo.Utils; use Einfo.Utils; with Errout; use Errout; with Eval_Fat; use Eval_Fat; with Exp_Ch3; use Exp_Ch3; with Exp_Ch9; use Exp_Ch9; with Exp_Disp; use Exp_Disp; with Exp_Dist; use Exp_Dist; with Exp_Tss; use Exp_Tss; with Exp_Util; use Exp_Util; with Freeze; use Freeze; with Ghost; use Ghost; with Itypes; use Itypes; with Layout; use Layout; with Lib; use Lib; with Lib.Xref; use Lib.Xref; with Namet; use Namet; with Nlists; use Nlists; with Nmake; use Nmake; with Opt; use Opt; with Restrict; use Restrict; with Rident; use Rident; with Rtsfind; use Rtsfind; with Sem; use Sem; with Sem_Aux; use Sem_Aux; with Sem_Case; use Sem_Case; with Sem_Cat; use Sem_Cat; with Sem_Ch6; use Sem_Ch6; with Sem_Ch7; use Sem_Ch7; with Sem_Ch8; use Sem_Ch8; with Sem_Ch13; use Sem_Ch13; with Sem_Dim; use Sem_Dim; with Sem_Disp; use Sem_Disp; with Sem_Dist; use Sem_Dist; with Sem_Elab; use Sem_Elab; with Sem_Elim; use Sem_Elim; with Sem_Eval; use Sem_Eval; with Sem_Mech; use Sem_Mech; with Sem_Res; use Sem_Res; with Sem_Smem; use Sem_Smem; with Sem_Type; use Sem_Type; with Sem_Util; use Sem_Util; with Sem_Warn; use Sem_Warn; with Stand; use Stand; with Sinfo; use Sinfo; with Sinfo.Nodes; use Sinfo.Nodes; with Sinfo.Utils; use Sinfo.Utils; with Sinput; use Sinput; with Snames; use Snames; with Strub; use Strub; with Targparm; use Targparm; with Tbuild; use Tbuild; with Ttypes; use Ttypes; with Uintp; use Uintp; with Urealp; use Urealp; package body Sem_Ch3 is ----------------------- -- Local Subprograms -- ----------------------- procedure Add_Interface_Tag_Components (N : Node_Id; Typ : Entity_Id); -- Ada 2005 (AI-251): Add the tag components corresponding to all the -- abstract interface types implemented by a record type or a derived -- record type. procedure Build_Access_Subprogram_Wrapper (Decl : Node_Id); -- When an access-to-subprogram type has pre/postconditions, we build a -- subprogram that includes these contracts and is invoked by an indirect -- call through the corresponding access type. procedure Build_Derived_Type (N : Node_Id; Parent_Type : Entity_Id; Derived_Type : Entity_Id; Is_Completion : Boolean; Derive_Subps : Boolean := True); -- Create and decorate a Derived_Type given the Parent_Type entity. N is -- the N_Full_Type_Declaration node containing the derived type definition. -- Parent_Type is the entity for the parent type in the derived type -- definition and Derived_Type the actual derived type. Is_Completion must -- be set to False if Derived_Type is the N_Defining_Identifier node in N -- (i.e. Derived_Type = Defining_Identifier (N)). In this case N is not the -- completion of a private type declaration. If Is_Completion is set to -- True, N is the completion of a private type declaration and Derived_Type -- is different from the defining identifier inside N (i.e. Derived_Type /= -- Defining_Identifier (N)). Derive_Subps indicates whether the parent -- subprograms should be derived. The only case where this parameter is -- False is when Build_Derived_Type is recursively called to process an -- implicit derived full type for a type derived from a private type (in -- that case the subprograms must only be derived for the private view of -- the type). -- -- ??? These flags need a bit of re-examination and re-documentation: -- ??? are they both necessary (both seem related to the recursion)? procedure Build_Derived_Access_Type (N : Node_Id; Parent_Type : Entity_Id; Derived_Type : Entity_Id); -- Subsidiary procedure to Build_Derived_Type. For a derived access type, -- create an implicit base if the parent type is constrained or if the -- subtype indication has a constraint. procedure Build_Derived_Array_Type (N : Node_Id; Parent_Type : Entity_Id; Derived_Type : Entity_Id); -- Subsidiary procedure to Build_Derived_Type. For a derived array type, -- create an implicit base if the parent type is constrained or if the -- subtype indication has a constraint. procedure Build_Derived_Concurrent_Type (N : Node_Id; Parent_Type : Entity_Id; Derived_Type : Entity_Id); -- Subsidiary procedure to Build_Derived_Type. For a derived task or -- protected type, inherit entries and protected subprograms, check -- legality of discriminant constraints if any. procedure Build_Derived_Enumeration_Type (N : Node_Id; Parent_Type : Entity_Id; Derived_Type : Entity_Id); -- Subsidiary procedure to Build_Derived_Type. For a derived enumeration -- type, we must create a new list of literals. Types derived from -- Character and [Wide_]Wide_Character are special-cased. procedure Build_Derived_Numeric_Type (N : Node_Id; Parent_Type : Entity_Id; Derived_Type : Entity_Id); -- Subsidiary procedure to Build_Derived_Type. For numeric types, create -- an anonymous base type, and propagate constraint to subtype if needed. procedure Build_Derived_Private_Type (N : Node_Id; Parent_Type : Entity_Id; Derived_Type : Entity_Id; Is_Completion : Boolean; Derive_Subps : Boolean := True); -- Subsidiary procedure to Build_Derived_Type. This procedure is complex -- because the parent may or may not have a completion, and the derivation -- may itself be a completion. procedure Build_Derived_Record_Type (N : Node_Id; Parent_Type : Entity_Id; Derived_Type : Entity_Id; Derive_Subps : Boolean := True); -- Subsidiary procedure used for tagged and untagged record types -- by Build_Derived_Type and Analyze_Private_Extension_Declaration. -- All parameters are as in Build_Derived_Type except that N, in -- addition to being an N_Full_Type_Declaration node, can also be an -- N_Private_Extension_Declaration node. See the definition of this routine -- for much more info. Derive_Subps indicates whether subprograms should be -- derived from the parent type. The only case where Derive_Subps is False -- is for an implicit derived full type for a type derived from a private -- type (see Build_Derived_Type). procedure Build_Discriminal (Discrim : Entity_Id); -- Create the discriminal corresponding to discriminant Discrim, that is -- the parameter corresponding to Discrim to be used in initialization -- procedures for the type where Discrim is a discriminant. Discriminals -- are not used during semantic analysis, and are not fully defined -- entities until expansion. Thus they are not given a scope until -- initialization procedures are built. function Build_Discriminant_Constraints (T : Entity_Id; Def : Node_Id; Derived_Def : Boolean := False) return Elist_Id; -- Validate discriminant constraints and return the list of the constraints -- in order of discriminant declarations, where T is the discriminated -- unconstrained type. Def is the N_Subtype_Indication node where the -- discriminants constraints for T are specified. Derived_Def is True -- when building the discriminant constraints in a derived type definition -- of the form "type D (...) is new T (xxx)". In this case T is the parent -- type and Def is the constraint "(xxx)" on T and this routine sets the -- Corresponding_Discriminant field of the discriminants in the derived -- type D to point to the corresponding discriminants in the parent type T. procedure Build_Discriminated_Subtype (T : Entity_Id; Def_Id : Entity_Id; Elist : Elist_Id; Related_Nod : Node_Id; For_Access : Boolean := False); -- Subsidiary procedure to Constrain_Discriminated_Type and to -- Process_Incomplete_Dependents. Given -- -- T (a possibly discriminated base type) -- Def_Id (a very partially built subtype for T), -- -- the call completes Def_Id to be the appropriate E_*_Subtype. -- -- The Elist is the list of discriminant constraints if any (it is set -- to No_Elist if T is not a discriminated type, and to an empty list if -- T has discriminants but there are no discriminant constraints). The -- Related_Nod is the same as Decl_Node in Create_Constrained_Components. -- The For_Access says whether or not this subtype is really constraining -- an access type. function Build_Scalar_Bound (Bound : Node_Id; Par_T : Entity_Id; Der_T : Entity_Id) return Node_Id; -- The bounds of a derived scalar type are conversions of the bounds of -- the parent type. Optimize the representation if the bounds are literals. -- Needs a more complete spec--what are the parameters exactly, and what -- exactly is the returned value, and how is Bound affected??? procedure Check_Access_Discriminant_Requires_Limited (D : Node_Id; Loc : Node_Id); -- Check the restriction that the type to which an access discriminant -- belongs must be a concurrent type or a descendant of a type with -- the reserved word 'limited' in its declaration. procedure Check_Anonymous_Access_Component (Typ_Decl : Node_Id; Typ : Entity_Id; Prev : Entity_Id; Comp_Def : Node_Id; Access_Def : Node_Id); -- Ada 2005 AI-382: an access component in a record definition can refer to -- the enclosing record, in which case it denotes the type itself, and not -- the current instance of the type. We create an anonymous access type for -- the component, and flag it as an access to a component, so accessibility -- checks are properly performed on it. The declaration of the access type -- is placed ahead of that of the record to prevent order-of-elaboration -- circularity issues in Gigi. We create an incomplete type for the record -- declaration, which is the designated type of the anonymous access. procedure Check_Anonymous_Access_Components (Typ_Decl : Node_Id; Typ : Entity_Id; Prev : Entity_Id; Comp_List : Node_Id); -- Call Check_Anonymous_Access_Component on Comp_List procedure Check_Constraining_Discriminant (New_Disc, Old_Disc : Entity_Id); -- Check that, if a new discriminant is used in a constraint defining the -- parent subtype of a derivation, its subtype is statically compatible -- with the subtype of the corresponding parent discriminant (RM 3.7(15)). procedure Check_Delta_Expression (E : Node_Id); -- Check that the expression represented by E is suitable for use as a -- delta expression, i.e. it is of real type and is static. procedure Check_Digits_Expression (E : Node_Id); -- Check that the expression represented by E is suitable for use as a -- digits expression, i.e. it is of integer type, positive and static. procedure Check_Initialization (T : Entity_Id; Exp : Node_Id); -- Validate the initialization of an object declaration. T is the required -- type, and Exp is the initialization expression. procedure Check_Interfaces (N : Node_Id; Def : Node_Id); -- Check ARM rules 3.9.4 (15/2), 9.1 (9.d/2) and 9.4 (11.d/2) procedure Check_Or_Process_Discriminants (N : Node_Id; T : Entity_Id; Prev : Entity_Id := Empty); -- If N is the full declaration of the completion T of an incomplete or -- private type, check its discriminants (which are already known to be -- conformant with those of the partial view, see Find_Type_Name), -- otherwise process them. Prev is the entity of the partial declaration, -- if any. procedure Check_Real_Bound (Bound : Node_Id); -- Check given bound for being of real type and static. If not, post an -- appropriate message, and rewrite the bound with the real literal zero. procedure Constant_Redeclaration (Id : Entity_Id; N : Node_Id; T : out Entity_Id); -- Various checks on legality of full declaration of deferred constant. -- Id is the entity for the redeclaration, N is the N_Object_Declaration, -- node. The caller has not yet set any attributes of this entity. function Contain_Interface (Iface : Entity_Id; Ifaces : Elist_Id) return Boolean; -- Ada 2005: Determine whether Iface is present in the list Ifaces procedure Convert_Scalar_Bounds (N : Node_Id; Parent_Type : Entity_Id; Derived_Type : Entity_Id; Loc : Source_Ptr); -- For derived scalar types, convert the bounds in the type definition to -- the derived type, and complete their analysis. Given a constraint of the -- form ".. new T range Lo .. Hi", Lo and Hi are analyzed and resolved with -- T'Base, the parent_type. The bounds of the derived type (the anonymous -- base) are copies of Lo and Hi. Finally, the bounds of the derived -- subtype are conversions of those bounds to the derived_type, so that -- their typing is consistent. procedure Copy_Array_Base_Type_Attributes (T1, T2 : Entity_Id); -- Copies attributes from array base type T2 to array base type T1. Copies -- only attributes that apply to base types, but not subtypes. procedure Copy_Array_Subtype_Attributes (T1, T2 : Entity_Id); -- Copies attributes from array subtype T2 to array subtype T1. Copies -- attributes that apply to both subtypes and base types. procedure Create_Constrained_Components (Subt : Entity_Id; Decl_Node : Node_Id; Typ : Entity_Id; Constraints : Elist_Id); -- Build the list of entities for a constrained discriminated record -- subtype. If a component depends on a discriminant, replace its subtype -- using the discriminant values in the discriminant constraint. Subt -- is the defining identifier for the subtype whose list of constrained -- entities we will create. Decl_Node is the type declaration node where -- we will attach all the itypes created. Typ is the base discriminated -- type for the subtype Subt. Constraints is the list of discriminant -- constraints for Typ. function Constrain_Component_Type (Comp : Entity_Id; Constrained_Typ : Entity_Id; Related_Node : Node_Id; Typ : Entity_Id; Constraints : Elist_Id) return Entity_Id; -- Given a discriminated base type Typ, a list of discriminant constraints, -- Constraints, for Typ and a component Comp of Typ, create and return the -- type corresponding to Etype (Comp) where all discriminant references -- are replaced with the corresponding constraint. If Etype (Comp) contains -- no discriminant references then it is returned as-is. Constrained_Typ -- is the final constrained subtype to which the constrained component -- belongs. Related_Node is the node where we attach all created itypes. procedure Constrain_Access (Def_Id : in out Entity_Id; S : Node_Id; Related_Nod : Node_Id); -- Apply a list of constraints to an access type. If Def_Id is empty, it is -- an anonymous type created for a subtype indication. In that case it is -- created in the procedure and attached to Related_Nod. procedure Constrain_Array (Def_Id : in out Entity_Id; SI : Node_Id; Related_Nod : Node_Id; Related_Id : Entity_Id; Suffix : Character); -- Apply a list of index constraints to an unconstrained array type. The -- first parameter is the entity for the resulting subtype. A value of -- Empty for Def_Id indicates that an implicit type must be created, but -- creation is delayed (and must be done by this procedure) because other -- subsidiary implicit types must be created first (which is why Def_Id -- is an in/out parameter). The second parameter is a subtype indication -- node for the constrained array to be created (e.g. something of the -- form string (1 .. 10)). Related_Nod gives the place where this type -- has to be inserted in the tree. The Related_Id and Suffix parameters -- are used to build the associated Implicit type name. procedure Constrain_Concurrent (Def_Id : in out Entity_Id; SI : Node_Id; Related_Nod : Node_Id; Related_Id : Entity_Id; Suffix : Character); -- Apply list of discriminant constraints to an unconstrained concurrent -- type. -- -- SI is the N_Subtype_Indication node containing the constraint and -- the unconstrained type to constrain. -- -- Def_Id is the entity for the resulting constrained subtype. A value -- of Empty for Def_Id indicates that an implicit type must be created, -- but creation is delayed (and must be done by this procedure) because -- other subsidiary implicit types must be created first (which is why -- Def_Id is an in/out parameter). -- -- Related_Nod gives the place where this type has to be inserted -- in the tree. -- -- The last two arguments are used to create its external name if needed. function Constrain_Corresponding_Record (Prot_Subt : Entity_Id; Corr_Rec : Entity_Id; Related_Nod : Node_Id) return Entity_Id; -- When constraining a protected type or task type with discriminants, -- constrain the corresponding record with the same discriminant values. procedure Constrain_Decimal (Def_Id : Entity_Id; S : Node_Id); -- Constrain a decimal fixed point type with a digits constraint and/or a -- range constraint, and build E_Decimal_Fixed_Point_Subtype entity. procedure Constrain_Discriminated_Type (Def_Id : Entity_Id; S : Node_Id; Related_Nod : Node_Id; For_Access : Boolean := False); -- Process discriminant constraints of composite type. Verify that values -- have been provided for all discriminants, that the original type is -- unconstrained, and that the types of the supplied expressions match -- the discriminant types. The first three parameters are like in routine -- Constrain_Concurrent. See Build_Discriminated_Subtype for an explanation -- of For_Access. procedure Constrain_Enumeration (Def_Id : Entity_Id; S : Node_Id); -- Constrain an enumeration type with a range constraint. This is identical -- to Constrain_Integer, but for the Ekind of the resulting subtype. procedure Constrain_Float (Def_Id : Entity_Id; S : Node_Id); -- Constrain a floating point type with either a digits constraint -- and/or a range constraint, building a E_Floating_Point_Subtype. procedure Constrain_Index (Index : Node_Id; S : Node_Id; Related_Nod : Node_Id; Related_Id : Entity_Id; Suffix : Character; Suffix_Index : Pos); -- Process an index constraint S in a constrained array declaration. The -- constraint can be a subtype name, or a range with or without an explicit -- subtype mark. The index is the corresponding index of the unconstrained -- array. The Related_Id and Suffix parameters are used to build the -- associated Implicit type name. procedure Constrain_Integer (Def_Id : Entity_Id; S : Node_Id); -- Build subtype of a signed or modular integer type procedure Constrain_Ordinary_Fixed (Def_Id : Entity_Id; S : Node_Id); -- Constrain an ordinary fixed point type with a range constraint, and -- build an E_Ordinary_Fixed_Point_Subtype entity. procedure Copy_And_Swap (Priv, Full : Entity_Id); -- Copy the Priv entity into the entity of its full declaration then swap -- the two entities in such a manner that the former private type is now -- seen as a full type. procedure Decimal_Fixed_Point_Type_Declaration (T : Entity_Id; Def : Node_Id); -- Create a new decimal fixed point type, and apply the constraint to -- obtain a subtype of this new type. procedure Complete_Private_Subtype (Priv : Entity_Id; Full : Entity_Id; Full_Base : Entity_Id; Related_Nod : Node_Id); -- Complete the implicit full view of a private subtype by setting the -- appropriate semantic fields. If the full view of the parent is a record -- type, build constrained components of subtype. procedure Derive_Progenitor_Subprograms (Parent_Type : Entity_Id; Tagged_Type : Entity_Id); -- Ada 2005 (AI-251): To complete type derivation, collect the primitive -- operations of progenitors of Tagged_Type, and replace the subsidiary -- subtypes with Tagged_Type, to build the specs of the inherited interface -- primitives. The derived primitives are aliased to those of the -- interface. This routine takes care also of transferring to the full view -- subprograms associated with the partial view of Tagged_Type that cover -- interface primitives. procedure Derived_Standard_Character (N : Node_Id; Parent_Type : Entity_Id; Derived_Type : Entity_Id); -- Subsidiary procedure to Build_Derived_Enumeration_Type which handles -- derivations from types Standard.Character and Standard.Wide_Character. procedure Derived_Type_Declaration (T : Entity_Id; N : Node_Id; Is_Completion : Boolean); -- Process a derived type declaration. Build_Derived_Type is invoked -- to process the actual derived type definition. Parameters N and -- Is_Completion have the same meaning as in Build_Derived_Type. -- T is the N_Defining_Identifier for the entity defined in the -- N_Full_Type_Declaration node N, that is T is the derived type. procedure Enumeration_Type_Declaration (T : Entity_Id; Def : Node_Id); -- Insert each literal in symbol table, as an overloadable identifier. Each -- enumeration type is mapped into a sequence of integers, and each literal -- is defined as a constant with integer value. If any of the literals are -- character literals, the type is a character type, which means that -- strings are legal aggregates for arrays of components of the type. function Expand_To_Stored_Constraint (Typ : Entity_Id; Constraint : Elist_Id) return Elist_Id; -- Given a constraint (i.e. a list of expressions) on the discriminants of -- Typ, expand it into a constraint on the stored discriminants and return -- the new list of expressions constraining the stored discriminants. function Find_Type_Of_Object (Obj_Def : Node_Id; Related_Nod : Node_Id) return Entity_Id; -- Get type entity for object referenced by Obj_Def, attaching the implicit -- types generated to Related_Nod. procedure Floating_Point_Type_Declaration (T : Entity_Id; Def : Node_Id); -- Create a new float and apply the constraint to obtain subtype of it function Has_Range_Constraint (N : Node_Id) return Boolean; -- Given an N_Subtype_Indication node N, return True if a range constraint -- is present, either directly, or as part of a digits or delta constraint. -- In addition, a digits constraint in the decimal case returns True, since -- it establishes a default range if no explicit range is present. function Inherit_Components (N : Node_Id; Parent_Base : Entity_Id; Derived_Base : Entity_Id; Is_Tagged : Boolean; Inherit_Discr : Boolean; Discs : Elist_Id) return Elist_Id; -- Called from Build_Derived_Record_Type to inherit the components of -- Parent_Base (a base type) into the Derived_Base (the derived base type). -- For more information on derived types and component inheritance please -- consult the comment above the body of Build_Derived_Record_Type. -- -- N is the original derived type declaration -- -- Is_Tagged is set if we are dealing with tagged types -- -- If Inherit_Discr is set, Derived_Base inherits its discriminants from -- Parent_Base, otherwise no discriminants are inherited. -- -- Discs gives the list of constraints that apply to Parent_Base in the -- derived type declaration. If Discs is set to No_Elist, then we have -- the following situation: -- -- type Parent (D1..Dn : ..) is [tagged] record ...; -- type Derived is new Parent [with ...]; -- -- which gets treated as -- -- type Derived (D1..Dn : ..) is new Parent (D1,..,Dn) [with ...]; -- -- For untagged types the returned value is an association list. The list -- starts from the association (Parent_Base => Derived_Base), and then it -- contains a sequence of the associations of the form -- -- (Old_Component => New_Component), -- -- where Old_Component is the Entity_Id of a component in Parent_Base and -- New_Component is the Entity_Id of the corresponding component in -- Derived_Base. For untagged records, this association list is needed when -- copying the record declaration for the derived base. In the tagged case -- the value returned is irrelevant. function Is_EVF_Procedure (Subp : Entity_Id) return Boolean; -- Subsidiary to Check_Abstract_Overriding and Derive_Subprogram. -- Determine whether subprogram Subp is a procedure subject to pragma -- Extensions_Visible with value False and has at least one controlling -- parameter of mode OUT. function Is_Private_Primitive (Prim : Entity_Id) return Boolean; -- Subsidiary to Check_Abstract_Overriding and Derive_Subprogram. -- When applied to a primitive subprogram Prim, returns True if Prim is -- declared as a private operation within a package or generic package, -- and returns False otherwise. function Is_Valid_Constraint_Kind (T_Kind : Type_Kind; Constraint_Kind : Node_Kind) return Boolean; -- Returns True if it is legal to apply the given kind of constraint to the -- given kind of type (index constraint to an array type, for example). procedure Modular_Type_Declaration (T : Entity_Id; Def : Node_Id); -- Create new modular type. Verify that modulus is in bounds procedure New_Concatenation_Op (Typ : Entity_Id); -- Create an abbreviated declaration for an operator in order to -- materialize concatenation on array types. procedure Ordinary_Fixed_Point_Type_Declaration (T : Entity_Id; Def : Node_Id); -- Create a new ordinary fixed point type, and apply the constraint to -- obtain subtype of it. procedure Preanalyze_Default_Expression (N : Node_Id; T : Entity_Id); -- Wrapper on Preanalyze_Spec_Expression for default expressions, so that -- In_Default_Expr can be properly adjusted. procedure Prepare_Private_Subtype_Completion (Id : Entity_Id; Related_Nod : Node_Id); -- Id is a subtype of some private type. Creates the full declaration -- associated with Id whenever possible, i.e. when the full declaration -- of the base type is already known. Records each subtype into -- Private_Dependents of the base type. procedure Process_Incomplete_Dependents (N : Node_Id; Full_T : Entity_Id; Inc_T : Entity_Id); -- Process all entities that depend on an incomplete type. There include -- subtypes, subprogram types that mention the incomplete type in their -- profiles, and subprogram with access parameters that designate the -- incomplete type. -- Inc_T is the defining identifier of an incomplete type declaration, its -- Ekind is E_Incomplete_Type. -- -- N is the corresponding N_Full_Type_Declaration for Inc_T. -- -- Full_T is N's defining identifier. -- -- Subtypes of incomplete types with discriminants are completed when the -- parent type is. This is simpler than private subtypes, because they can -- only appear in the same scope, and there is no need to exchange views. -- Similarly, access_to_subprogram types may have a parameter or a return -- type that is an incomplete type, and that must be replaced with the -- full type. -- -- If the full type is tagged, subprogram with access parameters that -- designated the incomplete may be primitive operations of the full type, -- and have to be processed accordingly. procedure Process_Real_Range_Specification (Def : Node_Id); -- Given the type definition for a real type, this procedure processes and -- checks the real range specification of this type definition if one is -- present. If errors are found, error messages are posted, and the -- Real_Range_Specification of Def is reset to Empty. procedure Record_Type_Declaration (T : Entity_Id; N : Node_Id; Prev : Entity_Id); -- Process a record type declaration (for both untagged and tagged -- records). Parameters T and N are exactly like in procedure -- Derived_Type_Declaration, except that no flag Is_Completion is needed -- for this routine. If this is the completion of an incomplete type -- declaration, Prev is the entity of the incomplete declaration, used for -- cross-referencing. Otherwise Prev = T. procedure Record_Type_Definition (Def : Node_Id; Prev_T : Entity_Id); -- This routine is used to process the actual record type definition (both -- for untagged and tagged records). Def is a record type definition node. -- This procedure analyzes the components in this record type definition. -- Prev_T is the entity for the enclosing record type. It is provided so -- that its Has_Task flag can be set if any of the component have Has_Task -- set. If the declaration is the completion of an incomplete type -- declaration, Prev_T is the original incomplete type, whose full view is -- the record type. procedure Replace_Discriminants (Typ : Entity_Id; Decl : Node_Id); -- Subsidiary to Build_Derived_Record_Type. For untagged record types, we -- first create the list of components for the derived type from that of -- the parent by means of Inherit_Components and then build a copy of the -- declaration tree of the parent with the help of the mapping returned by -- Inherit_Components, which will for example be used to validate record -- representation clauses given for the derived type. If the parent type -- is private and has discriminants, the ancestor discriminants used in the -- inheritance are that of the private declaration, whereas the ancestor -- discriminants present in the declaration tree of the parent are that of -- the full declaration; as a consequence, the remapping done during the -- copy will leave the references to the ancestor discriminants unchanged -- in the declaration tree and they need to be fixed up. If the derived -- type has a known discriminant part, then the remapping done during the -- copy will only create references to the stored discriminants and they -- need to be replaced with references to the non-stored discriminants. procedure Set_Fixed_Range (E : Entity_Id; Loc : Source_Ptr; Lo : Ureal; Hi : Ureal); -- Build a range node with the given bounds and set it as the Scalar_Range -- of the given fixed-point type entity. Loc is the source location used -- for the constructed range. See body for further details. procedure Set_Scalar_Range_For_Subtype (Def_Id : Entity_Id; R : Node_Id; Subt : Entity_Id); -- This routine is used to set the scalar range field for a subtype given -- Def_Id, the entity for the subtype, and R, the range expression for the -- scalar range. Subt provides the parent subtype to be used to analyze, -- resolve, and check the given range. procedure Set_Default_SSO (T : Entity_Id); -- T is the entity for an array or record being declared. This procedure -- sets the flags SSO_Set_Low_By_Default/SSO_Set_High_By_Default according -- to the setting of Opt.Default_SSO. function Should_Build_Subtype (T : Entity_Id) return Boolean; -- When analyzing components or object declarations, it is possible, in -- some cases, to build subtypes for discriminated types. This is -- worthwhile to avoid the backend allocating the maximum possible size for -- objects of the type. -- In particular, when T is limited, the discriminants and therefore the -- size of an object of type T cannot change. Furthermore, if T is definite -- with statically initialized defaulted discriminants, we are able and -- want to build a constrained subtype of the right size. procedure Signed_Integer_Type_Declaration (T : Entity_Id; Def : Node_Id); -- Create a new signed integer entity, and apply the constraint to obtain -- the required first named subtype of this type. procedure Set_Stored_Constraint_From_Discriminant_Constraint (E : Entity_Id); -- E is some record type. This routine computes E's Stored_Constraint -- from its Discriminant_Constraint. procedure Diagnose_Interface (N : Node_Id; E : Entity_Id); -- Check that an entity in a list of progenitors is an interface, -- emit error otherwise. ----------------------- -- Access_Definition -- ----------------------- function Access_Definition (Related_Nod : Node_Id; N : Node_Id) return Entity_Id is Anon_Type : Entity_Id; Anon_Scope : Entity_Id; Desig_Type : Entity_Id; Enclosing_Prot_Type : Entity_Id := Empty; begin if Is_Entry (Current_Scope) and then Is_Task_Type (Etype (Scope (Current_Scope))) then Error_Msg_N ("task entries cannot have access parameters", N); return Empty; end if; -- Ada 2005: For an object declaration the corresponding anonymous -- type is declared in the current scope. -- If the access definition is the return type of another access to -- function, scope is the current one, because it is the one of the -- current type declaration, except for the pathological case below. if Nkind (Related_Nod) in N_Object_Declaration | N_Access_Function_Definition then Anon_Scope := Current_Scope; -- A pathological case: function returning access functions that -- return access functions, etc. Each anonymous access type created -- is in the enclosing scope of the outermost function. declare Par : Node_Id; begin Par := Related_Nod; while Nkind (Par) in N_Access_Function_Definition | N_Access_Definition loop Par := Parent (Par); end loop; if Nkind (Par) = N_Function_Specification then Anon_Scope := Scope (Defining_Entity (Par)); end if; end; -- For the anonymous function result case, retrieve the scope of the -- function specification's associated entity rather than using the -- current scope. The current scope will be the function itself if the -- formal part is currently being analyzed, but will be the parent scope -- in the case of a parameterless function, and we always want to use -- the function's parent scope. Finally, if the function is a child -- unit, we must traverse the tree to retrieve the proper entity. elsif Nkind (Related_Nod) = N_Function_Specification and then Nkind (Parent (N)) /= N_Parameter_Specification then -- If the current scope is a protected type, the anonymous access -- is associated with one of the protected operations, and must -- be available in the scope that encloses the protected declaration. -- Otherwise the type is in the scope enclosing the subprogram. -- If the function has formals, the return type of a subprogram -- declaration is analyzed in the scope of the subprogram (see -- Process_Formals) and thus the protected type, if present, is -- the scope of the current function scope. if Ekind (Current_Scope) = E_Protected_Type then Enclosing_Prot_Type := Current_Scope; elsif Ekind (Current_Scope) = E_Function and then Ekind (Scope (Current_Scope)) = E_Protected_Type then Enclosing_Prot_Type := Scope (Current_Scope); end if; if Present (Enclosing_Prot_Type) then Anon_Scope := Scope (Enclosing_Prot_Type); else Anon_Scope := Scope (Defining_Entity (Related_Nod)); end if; -- For an access type definition, if the current scope is a child -- unit it is the scope of the type. elsif Is_Compilation_Unit (Current_Scope) then Anon_Scope := Current_Scope; -- For access formals, access components, and access discriminants, the -- scope is that of the enclosing declaration, else Anon_Scope := Scope (Current_Scope); end if; Anon_Type := Create_Itype (E_Anonymous_Access_Type, Related_Nod, Scope_Id => Anon_Scope); if All_Present (N) and then Ada_Version >= Ada_2005 then Error_Msg_N ("ALL not permitted for anonymous access types", N); end if; -- Ada 2005 (AI-254): In case of anonymous access to subprograms call -- the corresponding semantic routine if Present (Access_To_Subprogram_Definition (N)) then Access_Subprogram_Declaration (T_Name => Anon_Type, T_Def => Access_To_Subprogram_Definition (N)); if Ekind (Anon_Type) = E_Access_Protected_Subprogram_Type then Mutate_Ekind (Anon_Type, E_Anonymous_Access_Protected_Subprogram_Type); else Mutate_Ekind (Anon_Type, E_Anonymous_Access_Subprogram_Type); end if; Set_Can_Use_Internal_Rep (Anon_Type, not Always_Compatible_Rep_On_Target); -- If the anonymous access is associated with a protected operation, -- create a reference to it after the enclosing protected definition -- because the itype will be used in the subsequent bodies. -- If the anonymous access itself is protected, a full type -- declaratiton will be created for it, so that the equivalent -- record type can be constructed. For further details, see -- Replace_Anonymous_Access_To_Protected-Subprogram. if Ekind (Current_Scope) = E_Protected_Type and then not Protected_Present (Access_To_Subprogram_Definition (N)) then Build_Itype_Reference (Anon_Type, Parent (Current_Scope)); end if; return Anon_Type; end if; Find_Type (Subtype_Mark (N)); Desig_Type := Entity (Subtype_Mark (N)); Set_Directly_Designated_Type (Anon_Type, Desig_Type); Set_Etype (Anon_Type, Anon_Type); -- Make sure the anonymous access type has size and alignment fields -- set, as required by gigi. This is necessary in the case of the -- Task_Body_Procedure. if not Has_Private_Component (Desig_Type) then Layout_Type (Anon_Type); end if; -- Ada 2005 (AI-231): Ada 2005 semantics for anonymous access differs -- from Ada 95 semantics. In Ada 2005, anonymous access must specify if -- the null value is allowed. In Ada 95 the null value is never allowed. if Ada_Version >= Ada_2005 then Set_Can_Never_Be_Null (Anon_Type, Null_Exclusion_Present (N)); else Set_Can_Never_Be_Null (Anon_Type, True); end if; -- The anonymous access type is as public as the discriminated type or -- subprogram that defines it. It is imported (for back-end purposes) -- if the designated type is. Set_Is_Public (Anon_Type, Is_Public (Scope (Anon_Type))); -- Ada 2005 (AI-231): Propagate the access-constant attribute Set_Is_Access_Constant (Anon_Type, Constant_Present (N)); -- The context is either a subprogram declaration, object declaration, -- or an access discriminant, in a private or a full type declaration. -- In the case of a subprogram, if the designated type is incomplete, -- the operation will be a primitive operation of the full type, to be -- updated subsequently. If the type is imported through a limited_with -- clause, the subprogram is not a primitive operation of the type -- (which is declared elsewhere in some other scope). if Ekind (Desig_Type) = E_Incomplete_Type and then not From_Limited_With (Desig_Type) and then Is_Overloadable (Current_Scope) then Append_Elmt (Current_Scope, Private_Dependents (Desig_Type)); Set_Has_Delayed_Freeze (Current_Scope); end if; -- If the designated type is limited and class-wide, the object might -- contain tasks, so we create a Master entity for the declaration. This -- must be done before expansion of the full declaration, because the -- declaration may include an expression that is an allocator, whose -- expansion needs the proper Master for the created tasks. if Expander_Active and then Nkind (Related_Nod) = N_Object_Declaration then if Is_Limited_Record (Desig_Type) and then Is_Class_Wide_Type (Desig_Type) then Build_Class_Wide_Master (Anon_Type); -- Similarly, if the type is an anonymous access that designates -- tasks, create a master entity for it in the current context. elsif Has_Task (Desig_Type) and then Comes_From_Source (Related_Nod) then Build_Master_Entity (Defining_Identifier (Related_Nod)); Build_Master_Renaming (Anon_Type); end if; end if; -- For a private component of a protected type, it is imperative that -- the back-end elaborate the type immediately after the protected -- declaration, because this type will be used in the declarations -- created for the component within each protected body, so we must -- create an itype reference for it now. if Nkind (Parent (Related_Nod)) = N_Protected_Definition then Build_Itype_Reference (Anon_Type, Parent (Parent (Related_Nod))); -- Similarly, if the access definition is the return result of a -- function, create an itype reference for it because it will be used -- within the function body. For a regular function that is not a -- compilation unit, insert reference after the declaration. For a -- protected operation, insert it after the enclosing protected type -- declaration. In either case, do not create a reference for a type -- obtained through a limited_with clause, because this would introduce -- semantic dependencies. -- Similarly, do not create a reference if the designated type is a -- generic formal, because no use of it will reach the backend. elsif Nkind (Related_Nod) = N_Function_Specification and then not From_Limited_With (Desig_Type) and then not Is_Generic_Type (Desig_Type) then if Present (Enclosing_Prot_Type) then Build_Itype_Reference (Anon_Type, Parent (Enclosing_Prot_Type)); elsif Is_List_Member (Parent (Related_Nod)) and then Nkind (Parent (N)) /= N_Parameter_Specification then Build_Itype_Reference (Anon_Type, Parent (Related_Nod)); end if; -- Finally, create an itype reference for an object declaration of an -- anonymous access type. This is strictly necessary only for deferred -- constants, but in any case will avoid out-of-scope problems in the -- back-end. elsif Nkind (Related_Nod) = N_Object_Declaration then Build_Itype_Reference (Anon_Type, Related_Nod); end if; return Anon_Type; end Access_Definition; ----------------------------------- -- Access_Subprogram_Declaration -- ----------------------------------- procedure Access_Subprogram_Declaration (T_Name : Entity_Id; T_Def : Node_Id) is procedure Check_For_Premature_Usage (Def : Node_Id); -- Check that type T_Name is not used, directly or recursively, as a -- parameter or a return type in Def. Def is either a subtype, an -- access_definition, or an access_to_subprogram_definition. ------------------------------- -- Check_For_Premature_Usage -- ------------------------------- procedure Check_For_Premature_Usage (Def : Node_Id) is Param : Node_Id; begin -- Check for a subtype mark if Nkind (Def) in N_Has_Etype then if Etype (Def) = T_Name then Error_Msg_N ("type& cannot be used before the end of its declaration", Def); end if; -- If this is not a subtype, then this is an access_definition elsif Nkind (Def) = N_Access_Definition then if Present (Access_To_Subprogram_Definition (Def)) then Check_For_Premature_Usage (Access_To_Subprogram_Definition (Def)); else Check_For_Premature_Usage (Subtype_Mark (Def)); end if; -- The only cases left are N_Access_Function_Definition and -- N_Access_Procedure_Definition. else if Present (Parameter_Specifications (Def)) then Param := First (Parameter_Specifications (Def)); while Present (Param) loop Check_For_Premature_Usage (Parameter_Type (Param)); Next (Param); end loop; end if; if Nkind (Def) = N_Access_Function_Definition then Check_For_Premature_Usage (Result_Definition (Def)); end if; end if; end Check_For_Premature_Usage; -- Local variables Formals : constant List_Id := Parameter_Specifications (T_Def); Formal : Entity_Id; D_Ityp : Node_Id; Desig_Type : constant Entity_Id := Create_Itype (E_Subprogram_Type, Parent (T_Def)); -- Start of processing for Access_Subprogram_Declaration begin -- Associate the Itype node with the inner full-type declaration or -- subprogram spec or entry body. This is required to handle nested -- anonymous declarations. For example: -- procedure P -- (X : access procedure -- (Y : access procedure -- (Z : access T))) D_Ityp := Associated_Node_For_Itype (Desig_Type); while Nkind (D_Ityp) not in N_Full_Type_Declaration | N_Private_Type_Declaration | N_Private_Extension_Declaration | N_Procedure_Specification | N_Function_Specification | N_Entry_Body | N_Object_Declaration | N_Object_Renaming_Declaration | N_Formal_Object_Declaration | N_Formal_Type_Declaration | N_Task_Type_Declaration | N_Protected_Type_Declaration loop D_Ityp := Parent (D_Ityp); pragma Assert (D_Ityp /= Empty); end loop; Set_Associated_Node_For_Itype (Desig_Type, D_Ityp); if Nkind (D_Ityp) in N_Procedure_Specification | N_Function_Specification then Set_Scope (Desig_Type, Scope (Defining_Entity (D_Ityp))); elsif Nkind (D_Ityp) in N_Full_Type_Declaration | N_Object_Declaration | N_Object_Renaming_Declaration | N_Formal_Type_Declaration then Set_Scope (Desig_Type, Scope (Defining_Identifier (D_Ityp))); end if; if Nkind (T_Def) = N_Access_Function_Definition then if Nkind (Result_Definition (T_Def)) = N_Access_Definition then declare Acc : constant Node_Id := Result_Definition (T_Def); begin if Present (Access_To_Subprogram_Definition (Acc)) and then Protected_Present (Access_To_Subprogram_Definition (Acc)) then Set_Etype (Desig_Type, Replace_Anonymous_Access_To_Protected_Subprogram (T_Def)); else Set_Etype (Desig_Type, Access_Definition (T_Def, Result_Definition (T_Def))); end if; end; else Analyze (Result_Definition (T_Def)); declare Typ : constant Entity_Id := Entity (Result_Definition (T_Def)); begin -- If a null exclusion is imposed on the result type, then -- create a null-excluding itype (an access subtype) and use -- it as the function's Etype. if Is_Access_Type (Typ) and then Null_Exclusion_In_Return_Present (T_Def) then Set_Etype (Desig_Type, Create_Null_Excluding_Itype (T => Typ, Related_Nod => T_Def, Scope_Id => Current_Scope)); else if From_Limited_With (Typ) then -- AI05-151: Incomplete types are allowed in all basic -- declarations, including access to subprograms. if Ada_Version >= Ada_2012 then null; else Error_Msg_NE ("illegal use of incomplete type&", Result_Definition (T_Def), Typ); end if; elsif Ekind (Current_Scope) = E_Package and then In_Private_Part (Current_Scope) then if Ekind (Typ) = E_Incomplete_Type then Append_Elmt (Desig_Type, Private_Dependents (Typ)); elsif Is_Class_Wide_Type (Typ) and then Ekind (Etype (Typ)) = E_Incomplete_Type then Append_Elmt (Desig_Type, Private_Dependents (Etype (Typ))); end if; end if; Set_Etype (Desig_Type, Typ); end if; end; end if; if not Is_Type (Etype (Desig_Type)) then Error_Msg_N ("expect type in function specification", Result_Definition (T_Def)); end if; else Set_Etype (Desig_Type, Standard_Void_Type); end if; if Present (Formals) then Push_Scope (Desig_Type); -- Some special tests here. These special tests can be removed -- if and when Itypes always have proper parent pointers to their -- declarations??? -- Special test 1) Link defining_identifier of formals. Required by -- First_Formal to provide its functionality. declare F : Node_Id; begin F := First (Formals); while Present (F) loop if No (Parent (Defining_Identifier (F))) then Set_Parent (Defining_Identifier (F), F); end if; Next (F); end loop; end; Process_Formals (Formals, Parent (T_Def)); -- Special test 2) End_Scope requires that the parent pointer be set -- to something reasonable, but Itypes don't have parent pointers. So -- we set it and then unset it ??? Set_Parent (Desig_Type, T_Name); End_Scope; Set_Parent (Desig_Type, Empty); end if; -- Check for premature usage of the type being defined Check_For_Premature_Usage (T_Def); -- The return type and/or any parameter type may be incomplete. Mark the -- subprogram_type as depending on the incomplete type, so that it can -- be updated when the full type declaration is seen. This only applies -- to incomplete types declared in some enclosing scope, not to limited -- views from other packages. -- Prior to Ada 2012, access to functions can only have in_parameters. if Present (Formals) then Formal := First_Formal (Desig_Type); while Present (Formal) loop if Ekind (Formal) /= E_In_Parameter and then Nkind (T_Def) = N_Access_Function_Definition and then Ada_Version < Ada_2012 then Error_Msg_N ("functions can only have IN parameters", Formal); end if; if Ekind (Etype (Formal)) = E_Incomplete_Type and then In_Open_Scopes (Scope (Etype (Formal))) then Append_Elmt (Desig_Type, Private_Dependents (Etype (Formal))); Set_Has_Delayed_Freeze (Desig_Type); end if; Next_Formal (Formal); end loop; end if; -- Check whether an indirect call without actuals may be possible. This -- is used when resolving calls whose result is then indexed. May_Need_Actuals (Desig_Type); -- If the return type is incomplete, this is legal as long as the type -- is declared in the current scope and will be completed in it (rather -- than being part of limited view). if Ekind (Etype (Desig_Type)) = E_Incomplete_Type and then not Has_Delayed_Freeze (Desig_Type) and then In_Open_Scopes (Scope (Etype (Desig_Type))) then Append_Elmt (Desig_Type, Private_Dependents (Etype (Desig_Type))); Set_Has_Delayed_Freeze (Desig_Type); end if; Check_Delayed_Subprogram (Desig_Type); if Protected_Present (T_Def) then Mutate_Ekind (T_Name, E_Access_Protected_Subprogram_Type); Set_Convention (Desig_Type, Convention_Protected); else Mutate_Ekind (T_Name, E_Access_Subprogram_Type); end if; Set_Can_Use_Internal_Rep (T_Name, not Always_Compatible_Rep_On_Target); Set_Etype (T_Name, T_Name); Reinit_Size_Align (T_Name); Set_Directly_Designated_Type (T_Name, Desig_Type); -- If the access_to_subprogram is not declared at the library level, -- it can only point to subprograms that are at the same or deeper -- accessibility level. The corresponding subprogram type might -- require an activation record when compiling for C. Set_Needs_Activation_Record (Desig_Type, not Is_Library_Level_Entity (T_Name)); Generate_Reference_To_Formals (T_Name); -- Ada 2005 (AI-231): Propagate the null-excluding attribute Set_Can_Never_Be_Null (T_Name, Null_Exclusion_Present (T_Def)); Check_Restriction (No_Access_Subprograms, T_Def); Create_Extra_Formals (Desig_Type); end Access_Subprogram_Declaration; ---------------------------- -- Access_Type_Declaration -- ---------------------------- procedure Access_Type_Declaration (T : Entity_Id; Def : Node_Id) is procedure Setup_Access_Type (Desig_Typ : Entity_Id); -- After type declaration is analysed with T being an incomplete type, -- this routine will mutate the kind of T to the appropriate access type -- and set its directly designated type to Desig_Typ. ----------------------- -- Setup_Access_Type -- ----------------------- procedure Setup_Access_Type (Desig_Typ : Entity_Id) is begin if All_Present (Def) or else Constant_Present (Def) then Mutate_Ekind (T, E_General_Access_Type); else Mutate_Ekind (T, E_Access_Type); end if; Set_Directly_Designated_Type (T, Desig_Typ); end Setup_Access_Type; -- Local variables P : constant Node_Id := Parent (Def); S : constant Node_Id := Subtype_Indication (Def); Full_Desig : Entity_Id; -- Start of processing for Access_Type_Declaration begin -- Check for permissible use of incomplete type if Nkind (S) /= N_Subtype_Indication then Analyze (S); if Nkind (S) in N_Has_Entity and then Present (Entity (S)) and then Ekind (Root_Type (Entity (S))) = E_Incomplete_Type then Setup_Access_Type (Desig_Typ => Entity (S)); -- If the designated type is a limited view, we cannot tell if -- the full view contains tasks, and there is no way to handle -- that full view in a client. We create a master entity for the -- scope, which will be used when a client determines that one -- is needed. if From_Limited_With (Entity (S)) and then not Is_Class_Wide_Type (Entity (S)) then Build_Master_Entity (T); Build_Master_Renaming (T); end if; else Setup_Access_Type (Desig_Typ => Process_Subtype (S, P, T, 'P')); end if; -- If the access definition is of the form: ACCESS NOT NULL .. -- the subtype indication must be of an access type. Create -- a null-excluding subtype of it. if Null_Excluding_Subtype (Def) then if not Is_Access_Type (Entity (S)) then Error_Msg_N ("null exclusion must apply to access type", Def); else declare Loc : constant Source_Ptr := Sloc (S); Decl : Node_Id; Nam : constant Entity_Id := Make_Temporary (Loc, 'S'); begin Decl := Make_Subtype_Declaration (Loc, Defining_Identifier => Nam, Subtype_Indication => New_Occurrence_Of (Entity (S), Loc)); Set_Null_Exclusion_Present (Decl); Insert_Before (Parent (Def), Decl); Analyze (Decl); Set_Entity (S, Nam); end; end if; end if; else Setup_Access_Type (Desig_Typ => Process_Subtype (S, P, T, 'P')); end if; if not Error_Posted (T) then Full_Desig := Designated_Type (T); if Base_Type (Full_Desig) = T then Error_Msg_N ("access type cannot designate itself", S); -- In Ada 2005, the type may have a limited view through some unit in -- its own context, allowing the following circularity that cannot be -- detected earlier. elsif Is_Class_Wide_Type (Full_Desig) and then Etype (Full_Desig) = T then Error_Msg_N ("access type cannot designate its own class-wide type", S); -- Clean up indication of tagged status to prevent cascaded errors Set_Is_Tagged_Type (T, False); end if; Set_Etype (T, T); -- For SPARK, check that the designated type is compatible with -- respect to volatility with the access type. if SPARK_Mode /= Off and then Comes_From_Source (T) then -- ??? UNIMPLEMENTED -- In the case where the designated type is incomplete at this -- point, performing this check here is harmless but the check -- will need to be repeated when the designated type is complete. -- The preceding call to Comes_From_Source is needed because the -- FE sometimes introduces implicitly declared access types. See, -- for example, the expansion of nested_po.ads in OA28-015. Check_Volatility_Compatibility (Full_Desig, T, "designated type", "access type", Srcpos_Bearer => T); end if; end if; -- If the type has appeared already in a with_type clause, it is frozen -- and the pointer size is already set. Else, initialize. if not From_Limited_With (T) then Reinit_Size_Align (T); end if; -- Note that Has_Task is always false, since the access type itself -- is not a task type. See Einfo for more description on this point. -- Exactly the same consideration applies to Has_Controlled_Component -- and to Has_Protected. Set_Has_Task (T, False); Set_Has_Protected (T, False); Set_Has_Timing_Event (T, False); Set_Has_Controlled_Component (T, False); -- Initialize field Finalization_Master explicitly to Empty, to avoid -- problems where an incomplete view of this entity has been previously -- established by a limited with and an overlaid version of this field -- (Stored_Constraint) was initialized for the incomplete view. -- This reset is performed in most cases except where the access type -- has been created for the purposes of allocating or deallocating a -- build-in-place object. Such access types have explicitly set pools -- and finalization masters. if No (Associated_Storage_Pool (T)) then Set_Finalization_Master (T, Empty); end if; -- Ada 2005 (AI-231): Propagate the null-excluding and access-constant -- attributes Set_Can_Never_Be_Null (T, Null_Exclusion_Present (Def)); Set_Is_Access_Constant (T, Constant_Present (Def)); end Access_Type_Declaration; ---------------------------------- -- Add_Interface_Tag_Components -- ---------------------------------- procedure Add_Interface_Tag_Components (N : Node_Id; Typ : Entity_Id) is Loc : constant Source_Ptr := Sloc (N); L : List_Id; Last_Tag : Node_Id; procedure Add_Tag (Iface : Entity_Id); -- Add tag for one of the progenitor interfaces ------------- -- Add_Tag -- ------------- procedure Add_Tag (Iface : Entity_Id) is Decl : Node_Id; Def : Node_Id; Tag : Entity_Id; Offset : Entity_Id; begin pragma Assert (Is_Tagged_Type (Iface) and then Is_Interface (Iface)); -- This is a reasonable place to propagate predicates if Has_Predicates (Iface) then Set_Has_Predicates (Typ); end if; Def := Make_Component_Definition (Loc, Aliased_Present => True, Subtype_Indication => New_Occurrence_Of (RTE (RE_Interface_Tag), Loc)); Tag := Make_Temporary (Loc, 'V'); Decl := Make_Component_Declaration (Loc, Defining_Identifier => Tag, Component_Definition => Def); Analyze_Component_Declaration (Decl); Set_Analyzed (Decl); Mutate_Ekind (Tag, E_Component); Set_Is_Tag (Tag); Set_Is_Aliased (Tag); Set_Is_Independent (Tag); Set_Related_Type (Tag, Iface); Reinit_Component_Location (Tag); pragma Assert (Is_Frozen (Iface)); Set_DT_Entry_Count (Tag, DT_Entry_Count (First_Entity (Iface))); if No (Last_Tag) then Prepend (Decl, L); else Insert_After (Last_Tag, Decl); end if; Last_Tag := Decl; -- If the ancestor has discriminants we need to give special support -- to store the offset_to_top value of the secondary dispatch tables. -- For this purpose we add a supplementary component just after the -- field that contains the tag associated with each secondary DT. if Typ /= Etype (Typ) and then Has_Discriminants (Etype (Typ)) then Def := Make_Component_Definition (Loc, Subtype_Indication => New_Occurrence_Of (RTE (RE_Storage_Offset), Loc)); Offset := Make_Temporary (Loc, 'V'); Decl := Make_Component_Declaration (Loc, Defining_Identifier => Offset, Component_Definition => Def); Analyze_Component_Declaration (Decl); Set_Analyzed (Decl); Mutate_Ekind (Offset, E_Component); Set_Is_Aliased (Offset); Set_Is_Independent (Offset); Set_Related_Type (Offset, Iface); Reinit_Component_Location (Offset); Insert_After (Last_Tag, Decl); Last_Tag := Decl; end if; end Add_Tag; -- Local variables Elmt : Elmt_Id; Ext : Node_Id; Comp : Node_Id; -- Start of processing for Add_Interface_Tag_Components begin if not RTE_Available (RE_Interface_Tag) then Error_Msg_N ("(Ada 2005) interface types not supported by this run-time!", N); return; end if; if Ekind (Typ) /= E_Record_Type or else (Is_Concurrent_Record_Type (Typ) and then Is_Empty_List (Abstract_Interface_List (Typ))) or else (not Is_Concurrent_Record_Type (Typ) and then No (Interfaces (Typ)) and then Is_Empty_Elmt_List (Interfaces (Typ))) then return; end if; -- Find the current last tag if Nkind (Type_Definition (N)) = N_Derived_Type_Definition then Ext := Record_Extension_Part (Type_Definition (N)); else pragma Assert (Nkind (Type_Definition (N)) = N_Record_Definition); Ext := Type_Definition (N); end if; Last_Tag := Empty; if not (Present (Component_List (Ext))) then Set_Null_Present (Ext, False); L := New_List; Set_Component_List (Ext, Make_Component_List (Loc, Component_Items => L, Null_Present => False)); else if Nkind (Type_Definition (N)) = N_Derived_Type_Definition then L := Component_Items (Component_List (Record_Extension_Part (Type_Definition (N)))); else L := Component_Items (Component_List (Type_Definition (N))); end if; -- Find the last tag component Comp := First (L); while Present (Comp) loop if Nkind (Comp) = N_Component_Declaration and then Is_Tag (Defining_Identifier (Comp)) then Last_Tag := Comp; end if; Next (Comp); end loop; end if; -- At this point L references the list of components and Last_Tag -- references the current last tag (if any). Now we add the tag -- corresponding with all the interfaces that are not implemented -- by the parent. if Present (Interfaces (Typ)) then Elmt := First_Elmt (Interfaces (Typ)); while Present (Elmt) loop Add_Tag (Node (Elmt)); Next_Elmt (Elmt); end loop; end if; end Add_Interface_Tag_Components; ------------------------------------- -- Add_Internal_Interface_Entities -- ------------------------------------- procedure Add_Internal_Interface_Entities (Tagged_Type : Entity_Id) is Elmt : Elmt_Id; Iface : Entity_Id; Iface_Elmt : Elmt_Id; Iface_Prim : Entity_Id; Ifaces_List : Elist_Id; New_Subp : Entity_Id := Empty; Prim : Entity_Id; Restore_Scope : Boolean := False; begin pragma Assert (Ada_Version >= Ada_2005 and then Is_Record_Type (Tagged_Type) and then Is_Tagged_Type (Tagged_Type) and then Has_Interfaces (Tagged_Type) and then not Is_Interface (Tagged_Type)); -- Ensure that the internal entities are added to the scope of the type if Scope (Tagged_Type) /= Current_Scope then Push_Scope (Scope (Tagged_Type)); Restore_Scope := True; end if; Collect_Interfaces (Tagged_Type, Ifaces_List); Iface_Elmt := First_Elmt (Ifaces_List); while Present (Iface_Elmt) loop Iface := Node (Iface_Elmt); -- Originally we excluded here from this processing interfaces that -- are parents of Tagged_Type because their primitives are located -- in the primary dispatch table (and hence no auxiliary internal -- entities are required to handle secondary dispatch tables in such -- case). However, these auxiliary entities are also required to -- handle derivations of interfaces in formals of generics (see -- Derive_Subprograms). Elmt := First_Elmt (Primitive_Operations (Iface)); while Present (Elmt) loop Iface_Prim := Node (Elmt); if not Is_Predefined_Dispatching_Operation (Iface_Prim) then Prim := Find_Primitive_Covering_Interface (Tagged_Type => Tagged_Type, Iface_Prim => Iface_Prim); if No (Prim) and then Serious_Errors_Detected > 0 then goto Continue; end if; pragma Assert (Present (Prim)); -- Ada 2012 (AI05-0197): If the name of the covering primitive -- differs from the name of the interface primitive then it is -- a private primitive inherited from a parent type. In such -- case, given that Tagged_Type covers the interface, the -- inherited private primitive becomes visible. For such -- purpose we add a new entity that renames the inherited -- private primitive. if Chars (Prim) /= Chars (Iface_Prim) then pragma Assert (Has_Suffix (Prim, 'P')); Derive_Subprogram (New_Subp => New_Subp, Parent_Subp => Iface_Prim, Derived_Type => Tagged_Type, Parent_Type => Iface); Set_Alias (New_Subp, Prim); Set_Is_Abstract_Subprogram (New_Subp, Is_Abstract_Subprogram (Prim)); end if; Derive_Subprogram (New_Subp => New_Subp, Parent_Subp => Iface_Prim, Derived_Type => Tagged_Type, Parent_Type => Iface); declare Anc : Entity_Id; begin if Is_Inherited_Operation (Prim) and then Present (Alias (Prim)) then Anc := Alias (Prim); else Anc := Overridden_Operation (Prim); end if; -- Apply legality checks in RM 6.1.1 (10-13) concerning -- nonconforming preconditions in both an ancestor and -- a progenitor operation. -- If the operation is a primitive wrapper it is an explicit -- (overriding) operqtion and all is fine. if Present (Anc) and then Has_Non_Trivial_Precondition (Anc) and then Has_Non_Trivial_Precondition (Iface_Prim) then if Is_Abstract_Subprogram (Prim) or else (Ekind (Prim) = E_Procedure and then Nkind (Parent (Prim)) = N_Procedure_Specification and then Null_Present (Parent (Prim))) or else Is_Primitive_Wrapper (Prim) then null; -- The operation is inherited and must be overridden elsif not Comes_From_Source (Prim) then Error_Msg_NE ("&inherits non-conforming preconditions and must " & "be overridden (RM 6.1.1 (10-16))", Parent (Tagged_Type), Prim); end if; end if; end; -- Ada 2005 (AI-251): Decorate internal entity Iface_Subp -- associated with interface types. These entities are -- only registered in the list of primitives of its -- corresponding tagged type because they are only used -- to fill the contents of the secondary dispatch tables. -- Therefore they are removed from the homonym chains. Set_Is_Hidden (New_Subp); Set_Is_Internal (New_Subp); Set_Alias (New_Subp, Prim); Set_Is_Abstract_Subprogram (New_Subp, Is_Abstract_Subprogram (Prim)); Set_Interface_Alias (New_Subp, Iface_Prim); -- If the returned type is an interface then propagate it to -- the returned type. Needed by the thunk to generate the code -- which displaces "this" to reference the corresponding -- secondary dispatch table in the returned object. if Is_Interface (Etype (Iface_Prim)) then Set_Etype (New_Subp, Etype (Iface_Prim)); end if; -- Internal entities associated with interface types are only -- registered in the list of primitives of the tagged type. -- They are only used to fill the contents of the secondary -- dispatch tables. Therefore they are not needed in the -- homonym chains. Remove_Homonym (New_Subp); -- Hidden entities associated with interfaces must have set -- the Has_Delay_Freeze attribute to ensure that, in case -- of locally defined tagged types (or compiling with static -- dispatch tables generation disabled) the corresponding -- entry of the secondary dispatch table is filled when such -- an entity is frozen. Set_Has_Delayed_Freeze (New_Subp); end if; <> Next_Elmt (Elmt); end loop; Next_Elmt (Iface_Elmt); end loop; if Restore_Scope then Pop_Scope; end if; end Add_Internal_Interface_Entities; ----------------------------------- -- Analyze_Component_Declaration -- ----------------------------------- procedure Analyze_Component_Declaration (N : Node_Id) is Loc : constant Source_Ptr := Sloc (Component_Definition (N)); Id : constant Entity_Id := Defining_Identifier (N); E : constant Node_Id := Expression (N); Typ : constant Node_Id := Subtype_Indication (Component_Definition (N)); T : Entity_Id; P : Entity_Id; function Contains_POC (Constr : Node_Id) return Boolean; -- Determines whether a constraint uses the discriminant of a record -- type thus becoming a per-object constraint (POC). function Is_Known_Limited (Typ : Entity_Id) return Boolean; -- Typ is the type of the current component, check whether this type is -- a limited type. Used to validate declaration against that of -- enclosing record. ------------------ -- Contains_POC -- ------------------ function Contains_POC (Constr : Node_Id) return Boolean is begin -- Prevent cascaded errors if Error_Posted (Constr) then return False; end if; case Nkind (Constr) is when N_Attribute_Reference => return Attribute_Name (Constr) = Name_Access and then Prefix (Constr) = Scope (Entity (Prefix (Constr))); when N_Discriminant_Association => return Denotes_Discriminant (Expression (Constr)); when N_Identifier => return Denotes_Discriminant (Constr); when N_Index_Or_Discriminant_Constraint => declare IDC : Node_Id; begin IDC := First (Constraints (Constr)); while Present (IDC) loop -- One per-object constraint is sufficient if Contains_POC (IDC) then return True; end if; Next (IDC); end loop; return False; end; when N_Range => return Denotes_Discriminant (Low_Bound (Constr)) or else Denotes_Discriminant (High_Bound (Constr)); when N_Range_Constraint => return Denotes_Discriminant (Range_Expression (Constr)); when others => return False; end case; end Contains_POC; ---------------------- -- Is_Known_Limited -- ---------------------- function Is_Known_Limited (Typ : Entity_Id) return Boolean is P : constant Entity_Id := Etype (Typ); R : constant Entity_Id := Root_Type (Typ); begin if Is_Limited_Record (Typ) then return True; -- If the root type is limited (and not a limited interface) so is -- the current type. elsif Is_Limited_Record (R) and then (not Is_Interface (R) or else not Is_Limited_Interface (R)) then return True; -- Else the type may have a limited interface progenitor, but a -- limited record parent that is not an interface. elsif R /= P and then Is_Limited_Record (P) and then not Is_Interface (P) then return True; else return False; end if; end Is_Known_Limited; -- Start of processing for Analyze_Component_Declaration begin Generate_Definition (Id); Enter_Name (Id); if Present (Typ) then T := Find_Type_Of_Object (Subtype_Indication (Component_Definition (N)), N); -- Ada 2005 (AI-230): Access Definition case else pragma Assert (Present (Access_Definition (Component_Definition (N)))); T := Access_Definition (Related_Nod => N, N => Access_Definition (Component_Definition (N))); Set_Is_Local_Anonymous_Access (T); -- Ada 2005 (AI-254) if Present (Access_To_Subprogram_Definition (Access_Definition (Component_Definition (N)))) and then Protected_Present (Access_To_Subprogram_Definition (Access_Definition (Component_Definition (N)))) then T := Replace_Anonymous_Access_To_Protected_Subprogram (N); end if; end if; -- If the subtype is a constrained subtype of the enclosing record, -- (which must have a partial view) the back-end does not properly -- handle the recursion. Rewrite the component declaration with an -- explicit subtype indication, which is acceptable to Gigi. We can copy -- the tree directly because side effects have already been removed from -- discriminant constraints. if Ekind (T) = E_Access_Subtype and then Is_Entity_Name (Subtype_Indication (Component_Definition (N))) and then Comes_From_Source (T) and then Nkind (Parent (T)) = N_Subtype_Declaration and then Etype (Directly_Designated_Type (T)) = Current_Scope then Rewrite (Subtype_Indication (Component_Definition (N)), New_Copy_Tree (Subtype_Indication (Parent (T)))); T := Find_Type_Of_Object (Subtype_Indication (Component_Definition (N)), N); end if; -- If the component declaration includes a default expression, then we -- check that the component is not of a limited type (RM 3.7(5)), -- and do the special preanalysis of the expression (see section on -- "Handling of Default and Per-Object Expressions" in the spec of -- package Sem). if Present (E) then Preanalyze_Default_Expression (E, T); Check_Initialization (T, E); if Ada_Version >= Ada_2005 and then Ekind (T) = E_Anonymous_Access_Type and then Etype (E) /= Any_Type then -- Check RM 3.9.2(9): "if the expected type for an expression is -- an anonymous access-to-specific tagged type, then the object -- designated by the expression shall not be dynamically tagged -- unless it is a controlling operand in a call on a dispatching -- operation" if Is_Tagged_Type (Directly_Designated_Type (T)) and then Ekind (Directly_Designated_Type (T)) /= E_Class_Wide_Type and then Ekind (Directly_Designated_Type (Etype (E))) = E_Class_Wide_Type then Error_Msg_N ("access to specific tagged type required (RM 3.9.2(9))", E); end if; -- (Ada 2005: AI-230): Accessibility check for anonymous -- components if Type_Access_Level (Etype (E)) > Deepest_Type_Access_Level (T) then Error_Msg_N ("expression has deeper access level than component " & "(RM 3.10.2 (12.2))", E); end if; -- The initialization expression is a reference to an access -- discriminant. The type of the discriminant is always deeper -- than any access type. if Ekind (Etype (E)) = E_Anonymous_Access_Type and then Is_Entity_Name (E) and then Ekind (Entity (E)) = E_In_Parameter and then Present (Discriminal_Link (Entity (E))) then Error_Msg_N ("discriminant has deeper accessibility level than target", E); end if; end if; end if; -- The parent type may be a private view with unknown discriminants, -- and thus unconstrained. Regular components must be constrained. if not Is_Definite_Subtype (T) and then Chars (Id) /= Name_uParent then if Is_Class_Wide_Type (T) then Error_Msg_N ("class-wide subtype with unknown discriminants" & " in component declaration", Subtype_Indication (Component_Definition (N))); else Error_Msg_N ("unconstrained subtype in component declaration", Subtype_Indication (Component_Definition (N))); end if; -- Components cannot be abstract, except for the special case of -- the _Parent field (case of extending an abstract tagged type) elsif Is_Abstract_Type (T) and then Chars (Id) /= Name_uParent then Error_Msg_N ("type of a component cannot be abstract", N); end if; Set_Etype (Id, T); if Aliased_Present (Component_Definition (N)) then Set_Is_Aliased (Id); -- AI12-001: All aliased objects are considered to be specified as -- independently addressable (RM C.6(8.1/4)). Set_Is_Independent (Id); end if; -- The component declaration may have a per-object constraint, set -- the appropriate flag in the defining identifier of the subtype. if Present (Subtype_Indication (Component_Definition (N))) then declare Sindic : constant Node_Id := Subtype_Indication (Component_Definition (N)); begin if Nkind (Sindic) = N_Subtype_Indication and then Present (Constraint (Sindic)) and then Contains_POC (Constraint (Sindic)) then Set_Has_Per_Object_Constraint (Id); end if; end; end if; -- Ada 2005 (AI-231): Propagate the null-excluding attribute and carry -- out some static checks. if Ada_Version >= Ada_2005 and then Can_Never_Be_Null (T) then Null_Exclusion_Static_Checks (N); end if; -- If this component is private (or depends on a private type), flag the -- record type to indicate that some operations are not available. P := Private_Component (T); if Present (P) then -- Check for circular definitions if P = Any_Type then Set_Etype (Id, Any_Type); -- There is a gap in the visibility of operations only if the -- component type is not defined in the scope of the record type. elsif Scope (P) = Scope (Current_Scope) then null; elsif Is_Limited_Type (P) then Set_Is_Limited_Composite (Current_Scope); else Set_Is_Private_Composite (Current_Scope); end if; end if; if P /= Any_Type and then Is_Limited_Type (T) and then Chars (Id) /= Name_uParent and then Is_Tagged_Type (Current_Scope) then if Is_Derived_Type (Current_Scope) and then not Is_Known_Limited (Current_Scope) then Error_Msg_N ("extension of nonlimited type cannot have limited components", N); if Is_Interface (Root_Type (Current_Scope)) then Error_Msg_N ("\limitedness is not inherited from limited interface", N); Error_Msg_N ("\add LIMITED to type indication", N); end if; Explain_Limited_Type (T, N); Set_Etype (Id, Any_Type); Set_Is_Limited_Composite (Current_Scope, False); elsif not Is_Derived_Type (Current_Scope) and then not Is_Limited_Record (Current_Scope) and then not Is_Concurrent_Type (Current_Scope) then Error_Msg_N ("nonlimited tagged type cannot have limited components", N); Explain_Limited_Type (T, N); Set_Etype (Id, Any_Type); Set_Is_Limited_Composite (Current_Scope, False); end if; end if; -- When possible, build the default subtype if Should_Build_Subtype (T) then declare Act_T : constant Entity_Id := Build_Default_Subtype (T, N); begin Set_Etype (Id, Act_T); -- Rewrite component definition to use the constrained subtype Rewrite (Component_Definition (N), Make_Component_Definition (Loc, Subtype_Indication => New_Occurrence_Of (Act_T, Loc))); end; end if; Set_Original_Record_Component (Id, Id); if Has_Aspects (N) then Analyze_Aspect_Specifications (N, Id); end if; Analyze_Dimension (N); end Analyze_Component_Declaration; -------------------------- -- Analyze_Declarations -- -------------------------- procedure Analyze_Declarations (L : List_Id) is Decl : Node_Id; procedure Adjust_Decl; -- Adjust Decl not to include implicit label declarations, since these -- have strange Sloc values that result in elaboration check problems. -- (They have the sloc of the label as found in the source, and that -- is ahead of the current declarative part). procedure Build_Assertion_Bodies (Decls : List_Id; Context : Node_Id); -- Create the subprogram bodies which verify the run-time semantics of -- the pragmas listed below for each elibigle type found in declarative -- list Decls. The pragmas are: -- -- Default_Initial_Condition -- Invariant -- Type_Invariant -- -- Context denotes the owner of the declarative list. procedure Check_Entry_Contracts; -- Perform a preanalysis of the pre- and postconditions of an entry -- declaration. This must be done before full resolution and creation -- of the parameter block, etc. to catch illegal uses within the -- contract expression. Full analysis of the expression is done when -- the contract is processed. function Contains_Lib_Incomplete_Type (Pkg : Entity_Id) return Boolean; -- Check if a nested package has entities within it that rely on library -- level private types where the full view has not been completed for -- the purposes of checking if it is acceptable to freeze an expression -- function at the point of declaration. procedure Handle_Late_Controlled_Primitive (Body_Decl : Node_Id); -- Determine whether Body_Decl denotes the body of a late controlled -- primitive (either Initialize, Adjust or Finalize). If this is the -- case, add a proper spec if the body lacks one. The spec is inserted -- before Body_Decl and immediately analyzed. procedure Remove_Partial_Visible_Refinements (Spec_Id : Entity_Id); -- Spec_Id is the entity of a package that may define abstract states, -- and in the case of a child unit, whose ancestors may define abstract -- states. If the states have partial visible refinement, remove the -- partial visibility of each constituent at the end of the package -- spec and body declarations. procedure Remove_Visible_Refinements (Spec_Id : Entity_Id); -- Spec_Id is the entity of a package that may define abstract states. -- If the states have visible refinement, remove the visibility of each -- constituent at the end of the package body declaration. procedure Resolve_Aspects; -- Utility to resolve the expressions of aspects at the end of a list of -- declarations, or before a declaration that freezes previous entities, -- such as in a subprogram body. ----------------- -- Adjust_Decl -- ----------------- procedure Adjust_Decl is begin while Present (Prev (Decl)) and then Nkind (Decl) = N_Implicit_Label_Declaration loop Prev (Decl); end loop; end Adjust_Decl; ---------------------------- -- Build_Assertion_Bodies -- ---------------------------- procedure Build_Assertion_Bodies (Decls : List_Id; Context : Node_Id) is procedure Build_Assertion_Bodies_For_Type (Typ : Entity_Id); -- Create the subprogram bodies which verify the run-time semantics -- of the pragmas listed below for type Typ. The pragmas are: -- -- Default_Initial_Condition -- Invariant -- Type_Invariant ------------------------------------- -- Build_Assertion_Bodies_For_Type -- ------------------------------------- procedure Build_Assertion_Bodies_For_Type (Typ : Entity_Id) is begin if Nkind (Context) = N_Package_Specification then -- Preanalyze and resolve the class-wide invariants of an -- interface at the end of whichever declarative part has the -- interface type. Note that an interface may be declared in -- any non-package declarative part, but reaching the end of -- such a declarative part will always freeze the type and -- generate the invariant procedure (see Freeze_Type). if Is_Interface (Typ) then -- Interfaces are treated as the partial view of a private -- type, in order to achieve uniformity with the general -- case. As a result, an interface receives only a "partial" -- invariant procedure, which is never called. if Has_Own_Invariants (Typ) then Build_Invariant_Procedure_Body (Typ => Typ, Partial_Invariant => True); end if; elsif Decls = Visible_Declarations (Context) then -- Preanalyze and resolve the invariants of a private type -- at the end of the visible declarations to catch potential -- errors. Inherited class-wide invariants are not included -- because they have already been resolved. if Ekind (Typ) in E_Limited_Private_Type | E_Private_Type | E_Record_Type_With_Private and then Has_Own_Invariants (Typ) then Build_Invariant_Procedure_Body (Typ => Typ, Partial_Invariant => True); end if; -- Preanalyze and resolve the Default_Initial_Condition -- assertion expression at the end of the declarations to -- catch any errors. if Ekind (Typ) in E_Limited_Private_Type | E_Private_Type | E_Record_Type_With_Private and then Has_Own_DIC (Typ) then Build_DIC_Procedure_Body (Typ => Typ, Partial_DIC => True); end if; elsif Decls = Private_Declarations (Context) then -- Preanalyze and resolve the invariants of a private type's -- full view at the end of the private declarations to catch -- potential errors. if (not Is_Private_Type (Typ) or else Present (Underlying_Full_View (Typ))) and then Has_Private_Declaration (Typ) and then Has_Invariants (Typ) then Build_Invariant_Procedure_Body (Typ); end if; if (not Is_Private_Type (Typ) or else Present (Underlying_Full_View (Typ))) and then Has_Private_Declaration (Typ) and then Has_DIC (Typ) then Build_DIC_Procedure_Body (Typ); end if; end if; end if; end Build_Assertion_Bodies_For_Type; -- Local variables Decl : Node_Id; Decl_Id : Entity_Id; -- Start of processing for Build_Assertion_Bodies begin Decl := First (Decls); while Present (Decl) loop if Is_Declaration (Decl) then Decl_Id := Defining_Entity (Decl); if Is_Type (Decl_Id) then Build_Assertion_Bodies_For_Type (Decl_Id); end if; end if; Next (Decl); end loop; end Build_Assertion_Bodies; --------------------------- -- Check_Entry_Contracts -- --------------------------- procedure Check_Entry_Contracts is ASN : Node_Id; Ent : Entity_Id; Exp : Node_Id; begin Ent := First_Entity (Current_Scope); while Present (Ent) loop -- This only concerns entries with pre/postconditions if Ekind (Ent) = E_Entry and then Present (Contract (Ent)) and then Present (Pre_Post_Conditions (Contract (Ent))) then ASN := Pre_Post_Conditions (Contract (Ent)); Push_Scope (Ent); Install_Formals (Ent); -- Pre/postconditions are rewritten as Check pragmas. Analysis -- is performed on a copy of the pragma expression, to prevent -- modifying the original expression. while Present (ASN) loop if Nkind (ASN) = N_Pragma then Exp := New_Copy_Tree (Expression (First (Pragma_Argument_Associations (ASN)))); Set_Parent (Exp, ASN); Preanalyze_Assert_Expression (Exp, Standard_Boolean); end if; ASN := Next_Pragma (ASN); end loop; End_Scope; end if; Next_Entity (Ent); end loop; end Check_Entry_Contracts; ---------------------------------- -- Contains_Lib_Incomplete_Type -- ---------------------------------- function Contains_Lib_Incomplete_Type (Pkg : Entity_Id) return Boolean is Curr : Entity_Id; begin -- Avoid looking through scopes that do not meet the precondition of -- Pkg not being within a library unit spec. if not Is_Compilation_Unit (Pkg) and then not Is_Generic_Instance (Pkg) and then not In_Package_Body (Enclosing_Lib_Unit_Entity (Pkg)) then -- Loop through all entities in the current scope to identify -- an entity that depends on a private type. Curr := First_Entity (Pkg); loop if Nkind (Curr) in N_Entity and then Depends_On_Private (Curr) then return True; end if; exit when Last_Entity (Current_Scope) = Curr; Next_Entity (Curr); end loop; end if; return False; end Contains_Lib_Incomplete_Type; -------------------------------------- -- Handle_Late_Controlled_Primitive -- -------------------------------------- procedure Handle_Late_Controlled_Primitive (Body_Decl : Node_Id) is Body_Spec : constant Node_Id := Specification (Body_Decl); Body_Id : constant Entity_Id := Defining_Entity (Body_Spec); Loc : constant Source_Ptr := Sloc (Body_Id); Params : constant List_Id := Parameter_Specifications (Body_Spec); Spec : Node_Id; Spec_Id : Entity_Id; Typ : Node_Id; begin -- Consider only procedure bodies whose name matches one of the three -- controlled primitives. if Nkind (Body_Spec) /= N_Procedure_Specification or else Chars (Body_Id) not in Name_Adjust | Name_Finalize | Name_Initialize then return; -- A controlled primitive must have exactly one formal which is not -- an anonymous access type. elsif List_Length (Params) /= 1 then return; end if; Typ := Parameter_Type (First (Params)); if Nkind (Typ) = N_Access_Definition then return; end if; Find_Type (Typ); -- The type of the formal must be derived from [Limited_]Controlled if not Is_Controlled (Entity (Typ)) then return; end if; -- Check whether a specification exists for this body. We do not -- analyze the spec of the body in full, because it will be analyzed -- again when the body is properly analyzed, and we cannot create -- duplicate entries in the formals chain. We look for an explicit -- specification because the body may be an overriding operation and -- an inherited spec may be present. Spec_Id := Current_Entity (Body_Id); while Present (Spec_Id) loop if Ekind (Spec_Id) in E_Procedure | E_Generic_Procedure and then Scope (Spec_Id) = Current_Scope and then Present (First_Formal (Spec_Id)) and then No (Next_Formal (First_Formal (Spec_Id))) and then Etype (First_Formal (Spec_Id)) = Entity (Typ) and then Comes_From_Source (Spec_Id) then return; end if; Spec_Id := Homonym (Spec_Id); end loop; -- At this point the body is known to be a late controlled primitive. -- Generate a matching spec and insert it before the body. Note the -- use of Copy_Separate_Tree - we want an entirely separate semantic -- tree in this case. Spec := Copy_Separate_Tree (Body_Spec); -- Ensure that the subprogram declaration does not inherit the null -- indicator from the body as we now have a proper spec/body pair. Set_Null_Present (Spec, False); -- Ensure that the freeze node is inserted after the declaration of -- the primitive since its expansion will freeze the primitive. Decl := Make_Subprogram_Declaration (Loc, Specification => Spec); Insert_Before_And_Analyze (Body_Decl, Decl); end Handle_Late_Controlled_Primitive; ---------------------------------------- -- Remove_Partial_Visible_Refinements -- ---------------------------------------- procedure Remove_Partial_Visible_Refinements (Spec_Id : Entity_Id) is State_Elmt : Elmt_Id; begin if Present (Abstract_States (Spec_Id)) then State_Elmt := First_Elmt (Abstract_States (Spec_Id)); while Present (State_Elmt) loop Set_Has_Partial_Visible_Refinement (Node (State_Elmt), False); Next_Elmt (State_Elmt); end loop; end if; -- For a child unit, also hide the partial state refinement from -- ancestor packages. if Is_Child_Unit (Spec_Id) then Remove_Partial_Visible_Refinements (Scope (Spec_Id)); end if; end Remove_Partial_Visible_Refinements; -------------------------------- -- Remove_Visible_Refinements -- -------------------------------- procedure Remove_Visible_Refinements (Spec_Id : Entity_Id) is State_Elmt : Elmt_Id; begin if Present (Abstract_States (Spec_Id)) then State_Elmt := First_Elmt (Abstract_States (Spec_Id)); while Present (State_Elmt) loop Set_Has_Visible_Refinement (Node (State_Elmt), False); Next_Elmt (State_Elmt); end loop; end if; end Remove_Visible_Refinements; --------------------- -- Resolve_Aspects -- --------------------- procedure Resolve_Aspects is E : Entity_Id; begin E := First_Entity (Current_Scope); while Present (E) loop Resolve_Aspect_Expressions (E); -- Now that the aspect expressions have been resolved, if this is -- at the end of the visible declarations, we can set the flag -- Known_To_Have_Preelab_Init properly on types declared in the -- visible part, which is needed for checking whether full types -- in the private part satisfy the Preelaborable_Initialization -- aspect of the partial view. We can't wait for the creation of -- the pragma by Analyze_Aspects_At_Freeze_Point, because the -- freeze point may occur after the end of the package declaration -- (in the case of nested packages). if Is_Type (E) and then L = Visible_Declarations (Parent (L)) and then Has_Aspect (E, Aspect_Preelaborable_Initialization) then declare ASN : constant Node_Id := Find_Aspect (E, Aspect_Preelaborable_Initialization); Expr : constant Node_Id := Expression (ASN); begin -- Set Known_To_Have_Preelab_Init to True if aspect has no -- expression, or if the expression is True (or was folded -- to True), or if the expression is a conjunction of one or -- more Preelaborable_Initialization attributes applied to -- formal types and wasn't folded to False. (Note that -- Is_Conjunction_Of_Formal_Preelab_Init_Attributes goes to -- Original_Node if needed, hence test for Standard_False.) if not Present (Expr) or else (Is_Entity_Name (Expr) and then Entity (Expr) = Standard_True) or else (Is_Conjunction_Of_Formal_Preelab_Init_Attributes (Expr) and then not (Is_Entity_Name (Expr) and then Entity (Expr) = Standard_False)) then Set_Known_To_Have_Preelab_Init (E); end if; end; end if; Next_Entity (E); end loop; end Resolve_Aspects; -- Local variables Context : Node_Id := Empty; Ctrl_Typ : Entity_Id := Empty; Freeze_From : Entity_Id := Empty; Next_Decl : Node_Id; -- Start of processing for Analyze_Declarations begin Decl := First (L); while Present (Decl) loop -- Complete analysis of declaration Analyze (Decl); Next_Decl := Next (Decl); if No (Freeze_From) then Freeze_From := First_Entity (Current_Scope); end if; -- Remember if the declaration we just processed is the full type -- declaration of a controlled type (to handle late overriding of -- initialize, adjust or finalize). if Nkind (Decl) = N_Full_Type_Declaration and then Is_Controlled (Defining_Identifier (Decl)) then Ctrl_Typ := Defining_Identifier (Decl); end if; -- At the end of a declarative part, freeze remaining entities -- declared in it. The end of the visible declarations of package -- specification is not the end of a declarative part if private -- declarations are present. The end of a package declaration is a -- freezing point only if it a library package. A task definition or -- protected type definition is not a freeze point either. Finally, -- we do not freeze entities in generic scopes, because there is no -- code generated for them and freeze nodes will be generated for -- the instance. -- The end of a package instantiation is not a freeze point, but -- for now we make it one, because the generic body is inserted -- (currently) immediately after. Generic instantiations will not -- be a freeze point once delayed freezing of bodies is implemented. -- (This is needed in any case for early instantiations ???). if No (Next_Decl) then if Nkind (Parent (L)) = N_Component_List then null; elsif Nkind (Parent (L)) in N_Protected_Definition | N_Task_Definition then Check_Entry_Contracts; elsif Nkind (Parent (L)) /= N_Package_Specification then if Nkind (Parent (L)) = N_Package_Body then Freeze_From := First_Entity (Current_Scope); end if; -- There may have been several freezing points previously, -- for example object declarations or subprogram bodies, but -- at the end of a declarative part we check freezing from -- the beginning, even though entities may already be frozen, -- in order to perform visibility checks on delayed aspects. Adjust_Decl; -- If the current scope is a generic subprogram body. Skip the -- generic formal parameters that are not frozen here. if Is_Subprogram (Current_Scope) and then Nkind (Unit_Declaration_Node (Current_Scope)) = N_Generic_Subprogram_Declaration and then Present (First_Entity (Current_Scope)) then while Is_Generic_Formal (Freeze_From) loop Next_Entity (Freeze_From); end loop; Freeze_All (Freeze_From, Decl); Freeze_From := Last_Entity (Current_Scope); else -- For declarations in a subprogram body there is no issue -- with name resolution in aspect specifications. Freeze_All (First_Entity (Current_Scope), Decl); Freeze_From := Last_Entity (Current_Scope); end if; -- Current scope is a package specification elsif Scope (Current_Scope) /= Standard_Standard and then not Is_Child_Unit (Current_Scope) and then No (Generic_Parent (Parent (L))) then -- ARM rule 13.1.1(11/3): usage names in aspect definitions are -- resolved at the end of the immediately enclosing declaration -- list (AI05-0183-1). Resolve_Aspects; elsif L /= Visible_Declarations (Parent (L)) or else Is_Empty_List (Private_Declarations (Parent (L))) then Adjust_Decl; -- End of a package declaration -- This is a freeze point because it is the end of a -- compilation unit. Freeze_All (First_Entity (Current_Scope), Decl); Freeze_From := Last_Entity (Current_Scope); -- At the end of the visible declarations the expressions in -- aspects of all entities declared so far must be resolved. -- The entities themselves might be frozen later, and the -- generated pragmas and attribute definition clauses analyzed -- in full at that point, but name resolution must take place -- now. -- In addition to being the proper semantics, this is mandatory -- within generic units, because global name capture requires -- those expressions to be analyzed, given that the generated -- pragmas do not appear in the original generic tree. elsif Serious_Errors_Detected = 0 then Resolve_Aspects; end if; -- If next node is a body then freeze all types before the body. -- An exception occurs for some expander-generated bodies. If these -- are generated at places where in general language rules would not -- allow a freeze point, then we assume that the expander has -- explicitly checked that all required types are properly frozen, -- and we do not cause general freezing here. This special circuit -- is used when the encountered body is marked as having already -- been analyzed. -- In all other cases (bodies that come from source, and expander -- generated bodies that have not been analyzed yet), freeze all -- types now. Note that in the latter case, the expander must take -- care to attach the bodies at a proper place in the tree so as to -- not cause unwanted freezing at that point. -- It is also necessary to check for a case where both an expression -- function is used and the current scope depends on an incomplete -- private type from a library unit, otherwise premature freezing of -- the private type will occur. elsif not Analyzed (Next_Decl) and then Is_Body (Next_Decl) and then ((Nkind (Next_Decl) /= N_Subprogram_Body or else not Was_Expression_Function (Next_Decl)) or else (not Is_Ignored_Ghost_Entity (Current_Scope) and then not Contains_Lib_Incomplete_Type (Current_Scope))) then -- When a controlled type is frozen, the expander generates stream -- and controlled-type support routines. If the freeze is caused -- by the stand-alone body of Initialize, Adjust, or Finalize, the -- expander will end up using the wrong version of these routines, -- as the body has not been processed yet. To remedy this, detect -- a late controlled primitive and create a proper spec for it. -- This ensures that the primitive will override its inherited -- counterpart before the freeze takes place. -- If the declaration we just processed is a body, do not attempt -- to examine Next_Decl as the late primitive idiom can only apply -- to the first encountered body. -- ??? A cleaner approach may be possible and/or this solution -- could be extended to general-purpose late primitives. if Present (Ctrl_Typ) then -- No need to continue searching for late body overriding if -- the controlled type is already frozen. if Is_Frozen (Ctrl_Typ) then Ctrl_Typ := Empty; elsif Nkind (Next_Decl) = N_Subprogram_Body then Handle_Late_Controlled_Primitive (Next_Decl); end if; end if; Adjust_Decl; -- The generated body of an expression function does not freeze, -- unless it is a completion, in which case only the expression -- itself freezes. This is handled when the body itself is -- analyzed (see Freeze_Expr_Types, sem_ch6.adb). Freeze_All (Freeze_From, Decl); Freeze_From := Last_Entity (Current_Scope); end if; Decl := Next_Decl; end loop; -- Post-freezing actions if Present (L) then Context := Parent (L); -- Certain contract annotations have forward visibility semantics and -- must be analyzed after all declarative items have been processed. -- This timing ensures that entities referenced by such contracts are -- visible. -- Analyze the contract of an immediately enclosing package spec or -- body first because other contracts may depend on its information. if Nkind (Context) = N_Package_Body then Analyze_Package_Body_Contract (Defining_Entity (Context)); elsif Nkind (Context) = N_Package_Specification then Analyze_Package_Contract (Defining_Entity (Context)); end if; -- Analyze the contracts of various constructs in the declarative -- list. Analyze_Contracts (L); if Nkind (Context) = N_Package_Body then -- Ensure that all abstract states and objects declared in the -- state space of a package body are utilized as constituents. Check_Unused_Body_States (Defining_Entity (Context)); -- State refinements are visible up to the end of the package body -- declarations. Hide the state refinements from visibility to -- restore the original state conditions. Remove_Visible_Refinements (Corresponding_Spec (Context)); Remove_Partial_Visible_Refinements (Corresponding_Spec (Context)); elsif Nkind (Context) = N_Package_Specification then -- Partial state refinements are visible up to the end of the -- package spec declarations. Hide the partial state refinements -- from visibility to restore the original state conditions. Remove_Partial_Visible_Refinements (Defining_Entity (Context)); end if; -- Verify that all abstract states found in any package declared in -- the input declarative list have proper refinements. The check is -- performed only when the context denotes a block, entry, package, -- protected, subprogram, or task body (SPARK RM 7.2.2(3)). Check_State_Refinements (Context); -- Create the subprogram bodies which verify the run-time semantics -- of pragmas Default_Initial_Condition and [Type_]Invariant for all -- types within the current declarative list. This ensures that all -- assertion expressions are preanalyzed and resolved at the end of -- the declarative part. Note that the resolution happens even when -- freezing does not take place. Build_Assertion_Bodies (L, Context); end if; end Analyze_Declarations; ----------------------------------- -- Analyze_Full_Type_Declaration -- ----------------------------------- procedure Analyze_Full_Type_Declaration (N : Node_Id) is Def : constant Node_Id := Type_Definition (N); Def_Id : constant Entity_Id := Defining_Identifier (N); T : Entity_Id; Prev : Entity_Id; Is_Remote : constant Boolean := (Is_Remote_Types (Current_Scope) or else Is_Remote_Call_Interface (Current_Scope)) and then not (In_Private_Part (Current_Scope) or else In_Package_Body (Current_Scope)); procedure Check_Nonoverridable_Aspects; -- Apply the rule in RM 13.1.1(18.4/4) on iterator aspects that cannot -- be overridden, and can only be confirmed on derivation. procedure Check_Ops_From_Incomplete_Type; -- If there is a tagged incomplete partial view of the type, traverse -- the primitives of the incomplete view and change the type of any -- controlling formals and result to indicate the full view. The -- primitives will be added to the full type's primitive operations -- list later in Sem_Disp.Check_Operation_From_Incomplete_Type (which -- is called from Process_Incomplete_Dependents). ---------------------------------- -- Check_Nonoverridable_Aspects -- ---------------------------------- procedure Check_Nonoverridable_Aspects is function Get_Aspect_Spec (Specs : List_Id; Aspect_Name : Name_Id) return Node_Id; -- Check whether a list of aspect specifications includes an entry -- for a specific aspect. The list is either that of a partial or -- a full view. --------------------- -- Get_Aspect_Spec -- --------------------- function Get_Aspect_Spec (Specs : List_Id; Aspect_Name : Name_Id) return Node_Id is Spec : Node_Id; begin Spec := First (Specs); while Present (Spec) loop if Chars (Identifier (Spec)) = Aspect_Name then return Spec; end if; Next (Spec); end loop; return Empty; end Get_Aspect_Spec; -- Local variables Prev_Aspects : constant List_Id := Aspect_Specifications (Parent (Def_Id)); Par_Type : Entity_Id; Prev_Aspect : Node_Id; -- Start of processing for Check_Nonoverridable_Aspects begin -- Get parent type of derived type. Note that Prev is the entity in -- the partial declaration, but its contents are now those of full -- view, while Def_Id reflects the partial view. if Is_Private_Type (Def_Id) then Par_Type := Etype (Full_View (Def_Id)); else Par_Type := Etype (Def_Id); end if; -- If there is an inherited Implicit_Dereference, verify that it is -- made explicit in the partial view. if Has_Discriminants (Base_Type (Par_Type)) and then Nkind (Parent (Prev)) = N_Full_Type_Declaration and then Present (Discriminant_Specifications (Parent (Prev))) and then Present (Get_Reference_Discriminant (Par_Type)) then Prev_Aspect := Get_Aspect_Spec (Prev_Aspects, Name_Implicit_Dereference); if No (Prev_Aspect) and then Present (Discriminant_Specifications (Original_Node (Parent (Prev)))) then Error_Msg_N ("type does not inherit implicit dereference", Prev); else -- If one of the views has the aspect specified, verify that it -- is consistent with that of the parent. declare Cur_Discr : constant Entity_Id := Get_Reference_Discriminant (Prev); Par_Discr : constant Entity_Id := Get_Reference_Discriminant (Par_Type); begin if Corresponding_Discriminant (Cur_Discr) /= Par_Discr then Error_Msg_N ("aspect inconsistent with that of parent", N); end if; -- Check that specification in partial view matches the -- inherited aspect. Compare names directly because aspect -- expression may not be analyzed. if Present (Prev_Aspect) and then Nkind (Expression (Prev_Aspect)) = N_Identifier and then Chars (Expression (Prev_Aspect)) /= Chars (Cur_Discr) then Error_Msg_N ("aspect inconsistent with that of parent", N); end if; end; end if; end if; -- What about other nonoverridable aspects??? end Check_Nonoverridable_Aspects; ------------------------------------ -- Check_Ops_From_Incomplete_Type -- ------------------------------------ procedure Check_Ops_From_Incomplete_Type is Elmt : Elmt_Id; Formal : Entity_Id; Op : Entity_Id; begin if Prev /= T and then Ekind (Prev) = E_Incomplete_Type and then Is_Tagged_Type (Prev) and then Is_Tagged_Type (T) and then Present (Primitive_Operations (Prev)) then Elmt := First_Elmt (Primitive_Operations (Prev)); while Present (Elmt) loop Op := Node (Elmt); Formal := First_Formal (Op); while Present (Formal) loop if Etype (Formal) = Prev then Set_Etype (Formal, T); end if; Next_Formal (Formal); end loop; if Etype (Op) = Prev then Set_Etype (Op, T); end if; Next_Elmt (Elmt); end loop; end if; end Check_Ops_From_Incomplete_Type; -- Start of processing for Analyze_Full_Type_Declaration begin Prev := Find_Type_Name (N); -- The full view, if present, now points to the current type. If there -- is an incomplete partial view, set a link to it, to simplify the -- retrieval of primitive operations of the type. -- Ada 2005 (AI-50217): If the type was previously decorated when -- imported through a LIMITED WITH clause, it appears as incomplete -- but has no full view. if Ekind (Prev) = E_Incomplete_Type and then Present (Full_View (Prev)) then T := Full_View (Prev); Set_Incomplete_View (N, Parent (Prev)); else T := Prev; end if; Set_Is_Pure (T, Is_Pure (Current_Scope)); -- We set the flag Is_First_Subtype here. It is needed to set the -- corresponding flag for the Implicit class-wide-type created -- during tagged types processing. Set_Is_First_Subtype (T, True); -- Only composite types other than array types are allowed to have -- discriminants. case Nkind (Def) is -- For derived types, the rule will be checked once we've figured -- out the parent type. when N_Derived_Type_Definition => null; -- For record types, discriminants are allowed. when N_Record_Definition => null; when others => if Present (Discriminant_Specifications (N)) then Error_Msg_N ("elementary or array type cannot have discriminants", Defining_Identifier (First (Discriminant_Specifications (N)))); end if; end case; -- Elaborate the type definition according to kind, and generate -- subsidiary (implicit) subtypes where needed. We skip this if it was -- already done (this happens during the reanalysis that follows a call -- to the high level optimizer). if not Analyzed (T) then Set_Analyzed (T); -- Set the SPARK mode from the current context Set_SPARK_Pragma (T, SPARK_Mode_Pragma); Set_SPARK_Pragma_Inherited (T); case Nkind (Def) is when N_Access_To_Subprogram_Definition => Access_Subprogram_Declaration (T, Def); -- If this is a remote access to subprogram, we must create the -- equivalent fat pointer type, and related subprograms. if Is_Remote then Process_Remote_AST_Declaration (N); end if; -- Validate categorization rule against access type declaration -- usually a violation in Pure unit, Shared_Passive unit. Validate_Access_Type_Declaration (T, N); -- If the type has contracts, we create the corresponding -- wrapper at once, before analyzing the aspect specifications, -- so that pre/postconditions can be handled directly on the -- generated wrapper. if Ada_Version >= Ada_2022 and then Present (Aspect_Specifications (N)) then Build_Access_Subprogram_Wrapper (N); end if; when N_Access_To_Object_Definition => Access_Type_Declaration (T, Def); -- Validate categorization rule against access type declaration -- usually a violation in Pure unit, Shared_Passive unit. Validate_Access_Type_Declaration (T, N); -- If we are in a Remote_Call_Interface package and define a -- RACW, then calling stubs and specific stream attributes -- must be added. if Is_Remote and then Is_Remote_Access_To_Class_Wide_Type (Def_Id) then Add_RACW_Features (Def_Id); end if; when N_Array_Type_Definition => Array_Type_Declaration (T, Def); when N_Derived_Type_Definition => Derived_Type_Declaration (T, N, T /= Def_Id); -- Inherit predicates from parent, and protect against illegal -- derivations. if Is_Type (T) and then Has_Predicates (T) then Set_Has_Predicates (Def_Id); end if; -- Save the scenario for examination by the ABE Processing -- phase. Record_Elaboration_Scenario (N); when N_Enumeration_Type_Definition => Enumeration_Type_Declaration (T, Def); when N_Floating_Point_Definition => Floating_Point_Type_Declaration (T, Def); when N_Decimal_Fixed_Point_Definition => Decimal_Fixed_Point_Type_Declaration (T, Def); when N_Ordinary_Fixed_Point_Definition => Ordinary_Fixed_Point_Type_Declaration (T, Def); when N_Signed_Integer_Type_Definition => Signed_Integer_Type_Declaration (T, Def); when N_Modular_Type_Definition => Modular_Type_Declaration (T, Def); when N_Record_Definition => Record_Type_Declaration (T, N, Prev); -- If declaration has a parse error, nothing to elaborate. when N_Error => null; when others => raise Program_Error; end case; end if; if Etype (T) = Any_Type then return; end if; -- Set the primitives list of the full type and its base type when -- needed. T may be E_Void in cases of earlier errors, and in that -- case we bypass this. if Ekind (T) /= E_Void then if not Present (Direct_Primitive_Operations (T)) then if Etype (T) = T then Set_Direct_Primitive_Operations (T, New_Elmt_List); -- If Etype of T is the base type (as opposed to a parent type) -- and already has an associated list of primitive operations, -- then set T's primitive list to the base type's list. Otherwise, -- create a new empty primitives list and share the list between -- T and its base type. The lists need to be shared in common. elsif Etype (T) = Base_Type (T) then if not Present (Direct_Primitive_Operations (Base_Type (T))) then Set_Direct_Primitive_Operations (Base_Type (T), New_Elmt_List); end if; Set_Direct_Primitive_Operations (T, Direct_Primitive_Operations (Base_Type (T))); -- Case where the Etype is a parent type, so we need a new -- primitives list for T. else Set_Direct_Primitive_Operations (T, New_Elmt_List); end if; -- If T already has a Direct_Primitive_Operations list but its -- base type doesn't then set the base type's list to T's list. elsif not Present (Direct_Primitive_Operations (Base_Type (T))) then Set_Direct_Primitive_Operations (Base_Type (T), Direct_Primitive_Operations (T)); end if; end if; -- Some common processing for all types Set_Depends_On_Private (T, Has_Private_Component (T)); Check_Ops_From_Incomplete_Type; -- Both the declared entity, and its anonymous base type if one was -- created, need freeze nodes allocated. declare B : constant Entity_Id := Base_Type (T); begin -- In the case where the base type differs from the first subtype, we -- pre-allocate a freeze node, and set the proper link to the first -- subtype. Freeze_Entity will use this preallocated freeze node when -- it freezes the entity. -- This does not apply if the base type is a generic type, whose -- declaration is independent of the current derived definition. if B /= T and then not Is_Generic_Type (B) then Ensure_Freeze_Node (B); Set_First_Subtype_Link (Freeze_Node (B), T); end if; -- A type that is imported through a limited_with clause cannot -- generate any code, and thus need not be frozen. However, an access -- type with an imported designated type needs a finalization list, -- which may be referenced in some other package that has non-limited -- visibility on the designated type. Thus we must create the -- finalization list at the point the access type is frozen, to -- prevent unsatisfied references at link time. if not From_Limited_With (T) or else Is_Access_Type (T) then Set_Has_Delayed_Freeze (T); end if; end; -- Case where T is the full declaration of some private type which has -- been swapped in Defining_Identifier (N). if T /= Def_Id and then Is_Private_Type (Def_Id) then Process_Full_View (N, T, Def_Id); -- Record the reference. The form of this is a little strange, since -- the full declaration has been swapped in. So the first parameter -- here represents the entity to which a reference is made which is -- the "real" entity, i.e. the one swapped in, and the second -- parameter provides the reference location. -- Also, we want to kill Has_Pragma_Unreferenced temporarily here -- since we don't want a complaint about the full type being an -- unwanted reference to the private type declare B : constant Boolean := Has_Pragma_Unreferenced (T); begin Set_Has_Pragma_Unreferenced (T, False); Generate_Reference (T, T, 'c'); Set_Has_Pragma_Unreferenced (T, B); end; Set_Completion_Referenced (Def_Id); -- For completion of incomplete type, process incomplete dependents -- and always mark the full type as referenced (it is the incomplete -- type that we get for any real reference). elsif Ekind (Prev) = E_Incomplete_Type then Process_Incomplete_Dependents (N, T, Prev); Generate_Reference (Prev, Def_Id, 'c'); Set_Completion_Referenced (Def_Id); -- If not private type or incomplete type completion, this is a real -- definition of a new entity, so record it. else Generate_Definition (Def_Id); end if; -- Propagate any pending access types whose finalization masters need to -- be fully initialized from the partial to the full view. Guard against -- an illegal full view that remains unanalyzed. if Is_Type (Def_Id) and then Is_Incomplete_Or_Private_Type (Prev) then Set_Pending_Access_Types (Def_Id, Pending_Access_Types (Prev)); end if; if Chars (Scope (Def_Id)) = Name_System and then Chars (Def_Id) = Name_Address and then In_Predefined_Unit (N) then Set_Is_Descendant_Of_Address (Def_Id); Set_Is_Descendant_Of_Address (Base_Type (Def_Id)); Set_Is_Descendant_Of_Address (Prev); end if; Set_Optimize_Alignment_Flags (Def_Id); Check_Eliminated (Def_Id); -- If the declaration is a completion and aspects are present, apply -- them to the entity for the type which is currently the partial -- view, but which is the one that will be frozen. if Has_Aspects (N) then -- In most cases the partial view is a private type, and both views -- appear in different declarative parts. In the unusual case where -- the partial view is incomplete, perform the analysis on the -- full view, to prevent freezing anomalies with the corresponding -- class-wide type, which otherwise might be frozen before the -- dispatch table is built. if Prev /= Def_Id and then Ekind (Prev) /= E_Incomplete_Type then Analyze_Aspect_Specifications (N, Prev); -- Normal case else Analyze_Aspect_Specifications (N, Def_Id); end if; end if; if Is_Derived_Type (Prev) and then Def_Id /= Prev then Check_Nonoverridable_Aspects; end if; end Analyze_Full_Type_Declaration; ---------------------------------- -- Analyze_Incomplete_Type_Decl -- ---------------------------------- procedure Analyze_Incomplete_Type_Decl (N : Node_Id) is F : constant Boolean := Is_Pure (Current_Scope); T : Entity_Id; begin Generate_Definition (Defining_Identifier (N)); -- Process an incomplete declaration. The identifier must not have been -- declared already in the scope. However, an incomplete declaration may -- appear in the private part of a package, for a private type that has -- already been declared. -- In this case, the discriminants (if any) must match T := Find_Type_Name (N); Mutate_Ekind (T, E_Incomplete_Type); Set_Etype (T, T); Set_Is_First_Subtype (T); Reinit_Size_Align (T); -- Set the SPARK mode from the current context Set_SPARK_Pragma (T, SPARK_Mode_Pragma); Set_SPARK_Pragma_Inherited (T); -- Ada 2005 (AI-326): Minimum decoration to give support to tagged -- incomplete types. if Tagged_Present (N) then Set_Is_Tagged_Type (T, True); Set_No_Tagged_Streams_Pragma (T, No_Tagged_Streams); Make_Class_Wide_Type (T); end if; -- Initialize the list of primitive operations to an empty list, -- to cover tagged types as well as untagged types. For untagged -- types this is used either to analyze the call as legal when -- Extensions_Allowed is True, or to issue a better error message -- otherwise. Set_Direct_Primitive_Operations (T, New_Elmt_List); Set_Stored_Constraint (T, No_Elist); if Present (Discriminant_Specifications (N)) then Push_Scope (T); Process_Discriminants (N); End_Scope; end if; -- If the type has discriminants, nontrivial subtypes may be declared -- before the full view of the type. The full views of those subtypes -- will be built after the full view of the type. Set_Private_Dependents (T, New_Elmt_List); Set_Is_Pure (T, F); end Analyze_Incomplete_Type_Decl; ----------------------------------- -- Analyze_Interface_Declaration -- ----------------------------------- procedure Analyze_Interface_Declaration (T : Entity_Id; Def : Node_Id) is CW : constant Entity_Id := Class_Wide_Type (T); begin Set_Is_Tagged_Type (T); Set_No_Tagged_Streams_Pragma (T, No_Tagged_Streams); Set_Is_Limited_Record (T, Limited_Present (Def) or else Task_Present (Def) or else Protected_Present (Def) or else Synchronized_Present (Def)); -- Type is abstract if full declaration carries keyword, or if previous -- partial view did. Set_Is_Abstract_Type (T); Set_Is_Interface (T); -- Type is a limited interface if it includes the keyword limited, task, -- protected, or synchronized. Set_Is_Limited_Interface (T, Limited_Present (Def) or else Protected_Present (Def) or else Synchronized_Present (Def) or else Task_Present (Def)); Set_Interfaces (T, New_Elmt_List); Set_Direct_Primitive_Operations (T, New_Elmt_List); -- Complete the decoration of the class-wide entity if it was already -- built (i.e. during the creation of the limited view) if Present (CW) then Set_Is_Interface (CW); Set_Is_Limited_Interface (CW, Is_Limited_Interface (T)); end if; -- Check runtime support for synchronized interfaces if Is_Concurrent_Interface (T) and then not RTE_Available (RE_Select_Specific_Data) then Error_Msg_CRT ("synchronized interfaces", T); end if; end Analyze_Interface_Declaration; ----------------------------- -- Analyze_Itype_Reference -- ----------------------------- -- Nothing to do. This node is placed in the tree only for the benefit of -- back end processing, and has no effect on the semantic processing. procedure Analyze_Itype_Reference (N : Node_Id) is begin pragma Assert (Is_Itype (Itype (N))); null; end Analyze_Itype_Reference; -------------------------------- -- Analyze_Number_Declaration -- -------------------------------- procedure Analyze_Number_Declaration (N : Node_Id) is E : constant Node_Id := Expression (N); Id : constant Entity_Id := Defining_Identifier (N); Index : Interp_Index; It : Interp; T : Entity_Id; begin Generate_Definition (Id); Enter_Name (Id); -- This is an optimization of a common case of an integer literal if Nkind (E) = N_Integer_Literal then Set_Is_Static_Expression (E, True); Set_Etype (E, Universal_Integer); Set_Etype (Id, Universal_Integer); Mutate_Ekind (Id, E_Named_Integer); Set_Is_Frozen (Id, True); Set_Debug_Info_Needed (Id); return; end if; Set_Is_Pure (Id, Is_Pure (Current_Scope)); -- Process expression, replacing error by integer zero, to avoid -- cascaded errors or aborts further along in the processing -- Replace Error by integer zero, which seems least likely to cause -- cascaded errors. if E = Error then Rewrite (E, Make_Integer_Literal (Sloc (E), Uint_0)); Set_Error_Posted (E); end if; Analyze (E); -- Verify that the expression is static and numeric. If -- the expression is overloaded, we apply the preference -- rule that favors root numeric types. if not Is_Overloaded (E) then T := Etype (E); if Has_Dynamic_Predicate_Aspect (T) then Error_Msg_N ("subtype has dynamic predicate, " & "not allowed in number declaration", N); end if; else T := Any_Type; Get_First_Interp (E, Index, It); while Present (It.Typ) loop if (Is_Integer_Type (It.Typ) or else Is_Real_Type (It.Typ)) and then (Scope (Base_Type (It.Typ))) = Standard_Standard then if T = Any_Type then T := It.Typ; elsif Is_Universal_Numeric_Type (It.Typ) then -- Choose universal interpretation over any other T := It.Typ; exit; end if; end if; Get_Next_Interp (Index, It); end loop; end if; if Is_Integer_Type (T) then Resolve (E, T); Set_Etype (Id, Universal_Integer); Mutate_Ekind (Id, E_Named_Integer); elsif Is_Real_Type (T) then -- Because the real value is converted to universal_real, this is a -- legal context for a universal fixed expression. if T = Universal_Fixed then declare Loc : constant Source_Ptr := Sloc (N); Conv : constant Node_Id := Make_Type_Conversion (Loc, Subtype_Mark => New_Occurrence_Of (Universal_Real, Loc), Expression => Relocate_Node (E)); begin Rewrite (E, Conv); Analyze (E); end; elsif T = Any_Fixed then Error_Msg_N ("illegal context for mixed mode operation", E); -- Expression is of the form : universal_fixed * integer. Try to -- resolve as universal_real. T := Universal_Real; Set_Etype (E, T); end if; Resolve (E, T); Set_Etype (Id, Universal_Real); Mutate_Ekind (Id, E_Named_Real); else Wrong_Type (E, Any_Numeric); Resolve (E, T); Set_Etype (Id, T); Mutate_Ekind (Id, E_Constant); Set_Never_Set_In_Source (Id, True); Set_Is_True_Constant (Id, True); return; end if; if Nkind (E) in N_Integer_Literal | N_Real_Literal then Set_Etype (E, Etype (Id)); end if; if not Is_OK_Static_Expression (E) then Flag_Non_Static_Expr ("non-static expression used in number declaration!", E); Rewrite (E, Make_Integer_Literal (Sloc (N), 1)); Set_Etype (E, Any_Type); end if; Analyze_Dimension (N); end Analyze_Number_Declaration; -------------------------------- -- Analyze_Object_Declaration -- -------------------------------- -- WARNING: This routine manages Ghost regions. Return statements must be -- replaced by gotos which jump to the end of the routine and restore the -- Ghost mode. procedure Analyze_Object_Declaration (N : Node_Id) is Loc : constant Source_Ptr := Sloc (N); Id : constant Entity_Id := Defining_Identifier (N); Next_Decl : constant Node_Id := Next (N); Act_T : Entity_Id; T : Entity_Id; E : Node_Id := Expression (N); -- E is set to Expression (N) throughout this routine. When Expression -- (N) is modified, E is changed accordingly. procedure Check_Dynamic_Object (Typ : Entity_Id); -- A library-level object with nonstatic discriminant constraints may -- require dynamic allocation. The declaration is illegal if the -- profile includes the restriction No_Implicit_Heap_Allocations. procedure Check_For_Null_Excluding_Components (Obj_Typ : Entity_Id; Obj_Decl : Node_Id); -- Verify that each null-excluding component of object declaration -- Obj_Decl carrying type Obj_Typ has explicit initialization. Emit -- a compile-time warning if this is not the case. function Count_Tasks (T : Entity_Id) return Uint; -- This function is called when a non-generic library level object of a -- task type is declared. Its function is to count the static number of -- tasks declared within the type (it is only called if Has_Task is set -- for T). As a side effect, if an array of tasks with nonstatic bounds -- or a variant record type is encountered, Check_Restriction is called -- indicating the count is unknown. function Delayed_Aspect_Present return Boolean; -- If the declaration has an expression that is an aggregate, and it -- has aspects that require delayed analysis, the resolution of the -- aggregate must be deferred to the freeze point of the object. This -- special processing was created for address clauses, but it must -- also apply to address aspects. This must be done before the aspect -- specifications are analyzed because we must handle the aggregate -- before the analysis of the object declaration is complete. -- Any other relevant delayed aspects on object declarations ??? -------------------------- -- Check_Dynamic_Object -- -------------------------- procedure Check_Dynamic_Object (Typ : Entity_Id) is Comp : Entity_Id; Obj_Type : Entity_Id; begin Obj_Type := Typ; if Is_Private_Type (Obj_Type) and then Present (Full_View (Obj_Type)) then Obj_Type := Full_View (Obj_Type); end if; if Known_Static_Esize (Obj_Type) then return; end if; if Restriction_Active (No_Implicit_Heap_Allocations) and then Expander_Active and then Has_Discriminants (Obj_Type) then Comp := First_Component (Obj_Type); while Present (Comp) loop if Known_Static_Esize (Etype (Comp)) or else Size_Known_At_Compile_Time (Etype (Comp)) then null; elsif Is_Record_Type (Etype (Comp)) then Check_Dynamic_Object (Etype (Comp)); elsif not Discriminated_Size (Comp) and then Comes_From_Source (Comp) then Error_Msg_NE ("component& of non-static size will violate restriction " & "No_Implicit_Heap_Allocation?", N, Comp); end if; Next_Component (Comp); end loop; end if; end Check_Dynamic_Object; ----------------------------------------- -- Check_For_Null_Excluding_Components -- ----------------------------------------- procedure Check_For_Null_Excluding_Components (Obj_Typ : Entity_Id; Obj_Decl : Node_Id) is procedure Check_Component (Comp_Typ : Entity_Id; Comp_Decl : Node_Id := Empty; Array_Comp : Boolean := False); -- Apply a compile-time null-exclusion check on a component denoted -- by its declaration Comp_Decl and type Comp_Typ, and all of its -- subcomponents (if any). --------------------- -- Check_Component -- --------------------- procedure Check_Component (Comp_Typ : Entity_Id; Comp_Decl : Node_Id := Empty; Array_Comp : Boolean := False) is Comp : Entity_Id; T : Entity_Id; begin -- Do not consider internally-generated components or those that -- are already initialized. if Present (Comp_Decl) and then (not Comes_From_Source (Comp_Decl) or else Present (Expression (Comp_Decl))) then return; end if; if Is_Incomplete_Or_Private_Type (Comp_Typ) and then Present (Full_View (Comp_Typ)) then T := Full_View (Comp_Typ); else T := Comp_Typ; end if; -- Verify a component of a null-excluding access type if Is_Access_Type (T) and then Can_Never_Be_Null (T) then if Comp_Decl = Obj_Decl then Null_Exclusion_Static_Checks (N => Obj_Decl, Comp => Empty, Array_Comp => Array_Comp); else Null_Exclusion_Static_Checks (N => Obj_Decl, Comp => Comp_Decl, Array_Comp => Array_Comp); end if; -- Check array components elsif Is_Array_Type (T) then -- There is no suitable component when the object is of an -- array type. However, a namable component may appear at some -- point during the recursive inspection, but not at the top -- level. At the top level just indicate array component case. if Comp_Decl = Obj_Decl then Check_Component (Component_Type (T), Array_Comp => True); else Check_Component (Component_Type (T), Comp_Decl); end if; -- Verify all components of type T -- Note: No checks are performed on types with discriminants due -- to complexities involving variants. ??? elsif (Is_Concurrent_Type (T) or else Is_Incomplete_Or_Private_Type (T) or else Is_Record_Type (T)) and then not Has_Discriminants (T) then Comp := First_Component (T); while Present (Comp) loop Check_Component (Etype (Comp), Parent (Comp)); Next_Component (Comp); end loop; end if; end Check_Component; -- Start processing for Check_For_Null_Excluding_Components begin Check_Component (Obj_Typ, Obj_Decl); end Check_For_Null_Excluding_Components; ----------------- -- Count_Tasks -- ----------------- function Count_Tasks (T : Entity_Id) return Uint is C : Entity_Id; X : Node_Id; V : Uint; begin if Is_Task_Type (T) then return Uint_1; elsif Is_Record_Type (T) then if Has_Discriminants (T) then Check_Restriction (Max_Tasks, N); return Uint_0; else V := Uint_0; C := First_Component (T); while Present (C) loop V := V + Count_Tasks (Etype (C)); Next_Component (C); end loop; return V; end if; elsif Is_Array_Type (T) then X := First_Index (T); V := Count_Tasks (Component_Type (T)); while Present (X) loop C := Etype (X); if not Is_OK_Static_Subtype (C) then Check_Restriction (Max_Tasks, N); return Uint_0; else V := V * (UI_Max (Uint_0, Expr_Value (Type_High_Bound (C)) - Expr_Value (Type_Low_Bound (C)) + Uint_1)); end if; Next_Index (X); end loop; return V; else return Uint_0; end if; end Count_Tasks; ---------------------------- -- Delayed_Aspect_Present -- ---------------------------- function Delayed_Aspect_Present return Boolean is A : Node_Id; A_Id : Aspect_Id; begin if Present (Aspect_Specifications (N)) then A := First (Aspect_Specifications (N)); while Present (A) loop A_Id := Get_Aspect_Id (Chars (Identifier (A))); if A_Id = Aspect_Address then -- Set flag on object entity, for later processing at -- the freeze point. Set_Has_Delayed_Aspects (Id); return True; end if; Next (A); end loop; end if; return False; end Delayed_Aspect_Present; -- Local variables Saved_GM : constant Ghost_Mode_Type := Ghost_Mode; Saved_IGR : constant Node_Id := Ignored_Ghost_Region; -- Save the Ghost-related attributes to restore on exit Prev_Entity : Entity_Id := Empty; Related_Id : Entity_Id; Full_View_Present : Boolean := False; -- Start of processing for Analyze_Object_Declaration begin -- There are three kinds of implicit types generated by an -- object declaration: -- 1. Those generated by the original Object Definition -- 2. Those generated by the Expression -- 3. Those used to constrain the Object Definition with the -- expression constraints when the definition is unconstrained. -- They must be generated in this order to avoid order of elaboration -- issues. Thus the first step (after entering the name) is to analyze -- the object definition. if Constant_Present (N) then Prev_Entity := Current_Entity_In_Scope (Id); if Present (Prev_Entity) and then -- If the homograph is an implicit subprogram, it is overridden -- by the current declaration. ((Is_Overloadable (Prev_Entity) and then Is_Inherited_Operation (Prev_Entity)) -- The current object is a discriminal generated for an entry -- family index. Even though the index is a constant, in this -- particular context there is no true constant redeclaration. -- Enter_Name will handle the visibility. or else (Is_Discriminal (Id) and then Ekind (Discriminal_Link (Id)) = E_Entry_Index_Parameter) -- The current object is the renaming for a generic declared -- within the instance. or else (Ekind (Prev_Entity) = E_Package and then Nkind (Parent (Prev_Entity)) = N_Package_Renaming_Declaration and then not Comes_From_Source (Prev_Entity) and then Is_Generic_Instance (Renamed_Entity (Prev_Entity))) -- The entity may be a homonym of a private component of the -- enclosing protected object, for which we create a local -- renaming declaration. The declaration is legal, even if -- useless when it just captures that component. or else (Ekind (Scope (Current_Scope)) = E_Protected_Type and then Nkind (Parent (Prev_Entity)) = N_Object_Renaming_Declaration)) then Prev_Entity := Empty; end if; end if; if Present (Prev_Entity) then -- The object declaration is Ghost when it completes a deferred Ghost -- constant. Mark_And_Set_Ghost_Completion (N, Prev_Entity); Constant_Redeclaration (Id, N, T); Generate_Reference (Prev_Entity, Id, 'c'); Set_Completion_Referenced (Id); if Error_Posted (N) then -- Type mismatch or illegal redeclaration; do not analyze -- expression to avoid cascaded errors. T := Find_Type_Of_Object (Object_Definition (N), N); Set_Etype (Id, T); Mutate_Ekind (Id, E_Variable); goto Leave; end if; -- In the normal case, enter identifier at the start to catch premature -- usage in the initialization expression. else Generate_Definition (Id); Enter_Name (Id); Mark_Coextensions (N, Object_Definition (N)); T := Find_Type_Of_Object (Object_Definition (N), N); if Nkind (Object_Definition (N)) = N_Access_Definition and then Present (Access_To_Subprogram_Definition (Object_Definition (N))) and then Protected_Present (Access_To_Subprogram_Definition (Object_Definition (N))) then T := Replace_Anonymous_Access_To_Protected_Subprogram (N); end if; if Error_Posted (Id) then Set_Etype (Id, T); Mutate_Ekind (Id, E_Variable); goto Leave; end if; end if; -- Ada 2005 (AI-231): Propagate the null-excluding attribute and carry -- out some static checks. if Ada_Version >= Ada_2005 then -- In case of aggregates we must also take care of the correct -- initialization of nested aggregates bug this is done at the -- point of the analysis of the aggregate (see sem_aggr.adb) ??? if Can_Never_Be_Null (T) then if Present (Expression (N)) and then Nkind (Expression (N)) = N_Aggregate then null; elsif Comes_From_Source (Id) then declare Save_Typ : constant Entity_Id := Etype (Id); begin Set_Etype (Id, T); -- Temp. decoration for static checks Null_Exclusion_Static_Checks (N); Set_Etype (Id, Save_Typ); end; end if; -- We might be dealing with an object of a composite type containing -- null-excluding components without an aggregate, so we must verify -- that such components have default initialization. else Check_For_Null_Excluding_Components (T, N); end if; end if; -- Object is marked pure if it is in a pure scope Set_Is_Pure (Id, Is_Pure (Current_Scope)); -- If deferred constant, make sure context is appropriate. We detect -- a deferred constant as a constant declaration with no expression. -- A deferred constant can appear in a package body if its completion -- is by means of an interface pragma. if Constant_Present (N) and then No (E) then -- A deferred constant may appear in the declarative part of the -- following constructs: -- blocks -- entry bodies -- extended return statements -- package specs -- package bodies -- subprogram bodies -- task bodies -- When declared inside a package spec, a deferred constant must be -- completed by a full constant declaration or pragma Import. In all -- other cases, the only proper completion is pragma Import. Extended -- return statements are flagged as invalid contexts because they do -- not have a declarative part and so cannot accommodate the pragma. if Ekind (Current_Scope) = E_Return_Statement then Error_Msg_N ("invalid context for deferred constant declaration (RM 7.4)", N); Error_Msg_N ("\declaration requires an initialization expression", N); Set_Constant_Present (N, False); -- In Ada 83, deferred constant must be of private type elsif not Is_Private_Type (T) then if Ada_Version = Ada_83 and then Comes_From_Source (N) then Error_Msg_N ("(Ada 83) deferred constant must be private type", N); end if; end if; -- If not a deferred constant, then the object declaration freezes -- its type, unless the object is of an anonymous type and has delayed -- aspects. In that case the type is frozen when the object itself is. else Check_Fully_Declared (T, N); if Has_Delayed_Aspects (Id) and then Is_Array_Type (T) and then Is_Itype (T) then Set_Has_Delayed_Freeze (T); else Freeze_Before (N, T); end if; end if; -- If the object was created by a constrained array definition, then -- set the link in both the anonymous base type and anonymous subtype -- that are built to represent the array type to point to the object. if Nkind (Object_Definition (Declaration_Node (Id))) = N_Constrained_Array_Definition then Set_Related_Array_Object (T, Id); Set_Related_Array_Object (Base_Type (T), Id); end if; -- Check for protected objects not at library level if Has_Protected (T) and then not Is_Library_Level_Entity (Id) then Check_Restriction (No_Local_Protected_Objects, Id); end if; -- Check for violation of No_Local_Timing_Events if Has_Timing_Event (T) and then not Is_Library_Level_Entity (Id) then Check_Restriction (No_Local_Timing_Events, Id); end if; -- The actual subtype of the object is the nominal subtype, unless -- the nominal one is unconstrained and obtained from the expression. Act_T := T; if Is_Library_Level_Entity (Id) then Check_Dynamic_Object (T); end if; -- Process initialization expression if present and not in error if Present (E) and then E /= Error then -- Generate an error in case of CPP class-wide object initialization. -- Required because otherwise the expansion of the class-wide -- assignment would try to use 'size to initialize the object -- (primitive that is not available in CPP tagged types). if Is_Class_Wide_Type (Act_T) and then (Is_CPP_Class (Root_Type (Etype (Act_T))) or else (Present (Full_View (Root_Type (Etype (Act_T)))) and then Is_CPP_Class (Full_View (Root_Type (Etype (Act_T)))))) then Error_Msg_N ("predefined assignment not available for 'C'P'P tagged types", E); end if; Mark_Coextensions (N, E); Analyze (E); -- In case of errors detected in the analysis of the expression, -- decorate it with the expected type to avoid cascaded errors. if No (Etype (E)) then Set_Etype (E, T); end if; -- If an initialization expression is present, then we set the -- Is_True_Constant flag. It will be reset if this is a variable -- and it is indeed modified. Set_Is_True_Constant (Id, True); -- If we are analyzing a constant declaration, set its completion -- flag after analyzing and resolving the expression. if Constant_Present (N) then Set_Has_Completion (Id); end if; -- Set type and resolve (type may be overridden later on). Note: -- Ekind (Id) must still be E_Void at this point so that incorrect -- early usage within E is properly diagnosed. Set_Etype (Id, T); -- If the expression is an aggregate we must look ahead to detect -- the possible presence of an address clause, and defer resolution -- and expansion of the aggregate to the freeze point of the entity. -- This is not always legal because the aggregate may contain other -- references that need freezing, e.g. references to other entities -- with address clauses. In any case, when compiling with -gnatI the -- presence of the address clause must be ignored. if Comes_From_Source (N) and then Expander_Active and then Nkind (E) = N_Aggregate and then ((Present (Following_Address_Clause (N)) and then not Ignore_Rep_Clauses) or else Delayed_Aspect_Present) then Set_Etype (E, T); -- If the aggregate is limited it will be built in place, and its -- expansion is deferred until the object declaration is expanded. -- This is also required when generating C code to ensure that an -- object with an alignment or address clause can be initialized -- by means of component by component assignments. if Is_Limited_Type (T) or else Modify_Tree_For_C then Set_Expansion_Delayed (E); end if; else -- If the expression is a formal that is a "subprogram pointer" -- this is illegal in accessibility terms (see RM 3.10.2 (13.1/2) -- and AARM 3.10.2 (13.b/2)). Add an explicit conversion to force -- the corresponding check, as is done for assignments. if Is_Entity_Name (E) and then Present (Entity (E)) and then Is_Formal (Entity (E)) and then Ekind (Etype (Entity (E))) = E_Anonymous_Access_Subprogram_Type and then Ekind (T) /= E_Anonymous_Access_Subprogram_Type then Rewrite (E, Convert_To (T, Relocate_Node (E))); end if; Resolve (E, T); end if; -- No further action needed if E is a call to an inlined function -- which returns an unconstrained type and it has been expanded into -- a procedure call. In that case N has been replaced by an object -- declaration without initializing expression and it has been -- analyzed (see Expand_Inlined_Call). if Back_End_Inlining and then Expander_Active and then Nkind (E) = N_Function_Call and then Nkind (Name (E)) in N_Has_Entity and then Is_Inlined (Entity (Name (E))) and then not Is_Constrained (Etype (E)) and then Analyzed (N) and then No (Expression (N)) then goto Leave; end if; -- If E is null and has been replaced by an N_Raise_Constraint_Error -- node (which was marked already-analyzed), we need to set the type -- to something else than Universal_Access to keep gigi happy. if Etype (E) = Universal_Access then Set_Etype (E, T); end if; -- If the object is an access to variable, the initialization -- expression cannot be an access to constant. if Is_Access_Type (T) and then not Is_Access_Constant (T) and then Is_Access_Type (Etype (E)) and then Is_Access_Constant (Etype (E)) then Error_Msg_N ("access to variable cannot be initialized with an " & "access-to-constant expression", E); end if; if not Assignment_OK (N) then Check_Initialization (T, E); end if; Check_Unset_Reference (E); -- If this is a variable, then set current value. If this is a -- declared constant of a scalar type with a static expression, -- indicate that it is always valid. if not Constant_Present (N) then if Compile_Time_Known_Value (E) then Set_Current_Value (Id, E); end if; elsif Is_Scalar_Type (T) and then Is_OK_Static_Expression (E) then Set_Is_Known_Valid (Id); -- If it is a constant initialized with a valid nonstatic entity, -- the constant is known valid as well, and can inherit the subtype -- of the entity if it is a subtype of the given type. This info -- is preserved on the actual subtype of the constant. elsif Is_Scalar_Type (T) and then Is_Entity_Name (E) and then Is_Known_Valid (Entity (E)) and then In_Subrange_Of (Etype (Entity (E)), T) then Set_Is_Known_Valid (Id); Mutate_Ekind (Id, E_Constant); Set_Actual_Subtype (Id, Etype (Entity (E))); end if; -- Deal with setting of null flags if Is_Access_Type (T) then if Known_Non_Null (E) then Set_Is_Known_Non_Null (Id, True); elsif Known_Null (E) and then not Can_Never_Be_Null (Id) then Set_Is_Known_Null (Id, True); end if; end if; -- Check incorrect use of dynamically tagged expressions if Is_Tagged_Type (T) then Check_Dynamically_Tagged_Expression (Expr => E, Typ => T, Related_Nod => N); end if; Apply_Scalar_Range_Check (E, T); Apply_Static_Length_Check (E, T); -- A formal parameter of a specific tagged type whose related -- subprogram is subject to pragma Extensions_Visible with value -- "False" cannot be implicitly converted to a class-wide type by -- means of an initialization expression (SPARK RM 6.1.7(3)). Do -- not consider internally generated expressions. if Is_Class_Wide_Type (T) and then Comes_From_Source (E) and then Is_EVF_Expression (E) then Error_Msg_N ("formal parameter cannot be implicitly converted to " & "class-wide type when Extensions_Visible is False", E); end if; end if; -- If the No_Streams restriction is set, check that the type of the -- object is not, and does not contain, any subtype derived from -- Ada.Streams.Root_Stream_Type. Note that we guard the call to -- Has_Stream just for efficiency reasons. There is no point in -- spending time on a Has_Stream check if the restriction is not set. if Restriction_Check_Required (No_Streams) then if Has_Stream (T) then Check_Restriction (No_Streams, N); end if; end if; -- Deal with predicate check before we start to do major rewriting. It -- is OK to initialize and then check the initialized value, since the -- object goes out of scope if we get a predicate failure. Note that we -- do this in the analyzer and not the expander because the analyzer -- does some substantial rewriting in some cases. -- We need a predicate check if the type has predicates that are not -- ignored, and if either there is an initializing expression, or for -- default initialization when we have at least one case of an explicit -- default initial value (including via a Default_Value or -- Default_Component_Value aspect, see AI12-0301) and then this is not -- an internal declaration whose initialization comes later (as for an -- aggregate expansion) or a deferred constant. -- If expression is an aggregate it may be expanded into assignments -- and the declaration itself is marked with No_Initialization, but -- the predicate still applies. if not Suppress_Assignment_Checks (N) and then (Predicate_Enabled (T) or else Has_Static_Predicate (T)) and then (not No_Initialization (N) or else (Present (E) and then Nkind (E) = N_Aggregate)) and then (Present (E) or else Is_Partially_Initialized_Type (T, Include_Implicit => False)) and then not (Constant_Present (N) and then No (E)) then -- If the type has a static predicate and the expression is known at -- compile time, see if the expression satisfies the predicate. -- In the case of a static expression, this must be done even if -- the predicate is not enabled (as per static expression rules). if Present (E) then Check_Expression_Against_Static_Predicate (E, T); end if; -- Do not perform further predicate-related checks unless -- predicates are enabled for the subtype. if not Predicate_Enabled (T) then null; -- If the type is a null record and there is no explicit initial -- expression, no predicate check applies. elsif No (E) and then Is_Null_Record_Type (T) then null; -- Do not generate a predicate check if the initialization expression -- is a type conversion because the conversion has been subjected to -- the same check. This is a small optimization which avoid redundant -- checks. elsif Present (E) and then Nkind (E) = N_Type_Conversion then null; else -- The check must be inserted after the expanded aggregate -- expansion code, if any. declare Check : constant Node_Id := Make_Predicate_Check (T, New_Occurrence_Of (Id, Loc)); begin if No (Next_Decl) then Append_To (List_Containing (N), Check); else Insert_Before (Next_Decl, Check); end if; end; end if; end if; -- Case of unconstrained type if not Is_Definite_Subtype (T) then -- Nothing to do in deferred constant case if Constant_Present (N) and then No (E) then null; -- Case of no initialization present elsif No (E) then if No_Initialization (N) then null; elsif Is_Class_Wide_Type (T) then Error_Msg_N ("initialization required in class-wide declaration", N); else Error_Msg_N ("unconstrained subtype not allowed (need initialization)", Object_Definition (N)); if Is_Record_Type (T) and then Has_Discriminants (T) then Error_Msg_N ("\provide initial value or explicit discriminant values", Object_Definition (N)); Error_Msg_NE ("\or give default discriminant values for type&", Object_Definition (N), T); elsif Is_Array_Type (T) then Error_Msg_N ("\provide initial value or explicit array bounds", Object_Definition (N)); end if; end if; -- Case of initialization present but in error. Set initial -- expression as absent (but do not make above complaints). elsif E = Error then Set_Expression (N, Empty); E := Empty; -- Case of initialization present else -- Unconstrained variables not allowed in Ada 83 if Ada_Version = Ada_83 and then not Constant_Present (N) and then Comes_From_Source (Object_Definition (N)) then Error_Msg_N ("(Ada 83) unconstrained variable not allowed", Object_Definition (N)); end if; -- Now we constrain the variable from the initializing expression -- If the expression is an aggregate, it has been expanded into -- individual assignments. Retrieve the actual type from the -- expanded construct. if Is_Array_Type (T) and then No_Initialization (N) and then Nkind (Original_Node (E)) = N_Aggregate then Act_T := Etype (E); -- In case of class-wide interface object declarations we delay -- the generation of the equivalent record type declarations until -- its expansion because there are cases in they are not required. elsif Is_Interface (T) then null; -- If the type is an unchecked union, no subtype can be built from -- the expression. Rewrite declaration as a renaming, which the -- back-end can handle properly. This is a rather unusual case, -- because most unchecked_union declarations have default values -- for discriminants and are thus not indefinite. elsif Is_Unchecked_Union (T) then if Constant_Present (N) or else Nkind (E) = N_Function_Call then Mutate_Ekind (Id, E_Constant); else Mutate_Ekind (Id, E_Variable); end if; -- If the expression is an aggregate it contains the required -- discriminant values but it has not been resolved yet, so do -- it now, and treat it as the initial expression of an object -- declaration, rather than a renaming. if Nkind (E) = N_Aggregate then Analyze_And_Resolve (E, T); else Rewrite (N, Make_Object_Renaming_Declaration (Loc, Defining_Identifier => Id, Subtype_Mark => New_Occurrence_Of (T, Loc), Name => E)); Set_Renamed_Object (Id, E); Freeze_Before (N, T); Set_Is_Frozen (Id); goto Leave; end if; else -- Ensure that the generated subtype has a unique external name -- when the related object is public. This guarantees that the -- subtype and its bounds will not be affected by switches or -- pragmas that may offset the internal counter due to extra -- generated code. if Is_Public (Id) then Related_Id := Id; else Related_Id := Empty; end if; -- If the object has an unconstrained array subtype with fixed -- lower bound, then sliding to that bound may be needed. if Is_Fixed_Lower_Bound_Array_Subtype (T) then Expand_Sliding_Conversion (E, T); end if; Expand_Subtype_From_Expr (N => N, Unc_Type => T, Subtype_Indic => Object_Definition (N), Exp => E, Related_Id => Related_Id); Act_T := Find_Type_Of_Object (Object_Definition (N), N); end if; -- Propagate attributes to full view when needed Set_Is_Constr_Subt_For_U_Nominal (Act_T); if Is_Private_Type (Act_T) and then Present (Full_View (Act_T)) then Full_View_Present := True; end if; if Full_View_Present then Set_Is_Constr_Subt_For_U_Nominal (Full_View (Act_T)); end if; if Aliased_Present (N) then Set_Is_Constr_Subt_For_UN_Aliased (Act_T); if Full_View_Present then Set_Is_Constr_Subt_For_UN_Aliased (Full_View (Act_T)); end if; end if; Freeze_Before (N, Act_T); Freeze_Before (N, T); end if; elsif Is_Array_Type (T) and then No_Initialization (N) and then (Nkind (Original_Node (E)) = N_Aggregate or else (Nkind (Original_Node (E)) = N_Qualified_Expression and then Nkind (Original_Node (Expression (Original_Node (E)))) = N_Aggregate)) then if not Is_Entity_Name (Object_Definition (N)) then Act_T := Etype (E); Check_Compile_Time_Size (Act_T); if Aliased_Present (N) then Set_Is_Constr_Subt_For_UN_Aliased (Act_T); end if; end if; -- When the given object definition and the aggregate are specified -- independently, and their lengths might differ do a length check. -- This cannot happen if the aggregate is of the form (others =>...) if not Is_Constrained (T) then null; elsif Nkind (E) = N_Raise_Constraint_Error then -- Aggregate is statically illegal. Place back in declaration Set_Expression (N, E); Set_No_Initialization (N, False); elsif T = Etype (E) then null; elsif Nkind (E) = N_Aggregate and then Present (Component_Associations (E)) and then Present (Choice_List (First (Component_Associations (E)))) and then Nkind (First (Choice_List (First (Component_Associations (E))))) = N_Others_Choice then null; else Apply_Length_Check (E, T); end if; -- When possible, build the default subtype elsif Should_Build_Subtype (T) then if No (E) then Act_T := Build_Default_Subtype (T, N); else -- Ada 2005: A limited object may be initialized by means of an -- aggregate. If the type has default discriminants it has an -- unconstrained nominal type, Its actual subtype will be obtained -- from the aggregate, and not from the default discriminants. Act_T := Etype (E); end if; Rewrite (Object_Definition (N), New_Occurrence_Of (Act_T, Loc)); elsif Nkind (E) = N_Function_Call and then Constant_Present (N) and then Has_Unconstrained_Elements (Etype (E)) then -- The back-end has problems with constants of a discriminated type -- with defaults, if the initial value is a function call. We -- generate an intermediate temporary that will receive a reference -- to the result of the call. The initialization expression then -- becomes a dereference of that temporary. Remove_Side_Effects (E); -- If this is a constant declaration of an unconstrained type and -- the initialization is an aggregate, we can use the subtype of the -- aggregate for the declared entity because it is immutable. elsif not Is_Constrained (T) and then Has_Discriminants (T) and then Constant_Present (N) and then not Has_Unchecked_Union (T) and then Nkind (E) = N_Aggregate then Act_T := Etype (E); end if; -- Check No_Wide_Characters restriction Check_Wide_Character_Restriction (T, Object_Definition (N)); -- Indicate this is not set in source. Certainly true for constants, and -- true for variables so far (will be reset for a variable if and when -- we encounter a modification in the source). Set_Never_Set_In_Source (Id); -- Now establish the proper kind and type of the object if Ekind (Id) = E_Void then Reinit_Field_To_Zero (Id, F_Next_Inlined_Subprogram); end if; if Constant_Present (N) then Mutate_Ekind (Id, E_Constant); Set_Is_True_Constant (Id); else Mutate_Ekind (Id, E_Variable); -- A variable is set as shared passive if it appears in a shared -- passive package, and is at the outer level. This is not done for -- entities generated during expansion, because those are always -- manipulated locally. if Is_Shared_Passive (Current_Scope) and then Is_Library_Level_Entity (Id) and then Comes_From_Source (Id) then Set_Is_Shared_Passive (Id); Check_Shared_Var (Id, T, N); end if; -- Set Has_Initial_Value if initializing expression present. Note -- that if there is no initializing expression, we leave the state -- of this flag unchanged (usually it will be False, but notably in -- the case of exception choice variables, it will already be true). if Present (E) then Set_Has_Initial_Value (Id); end if; end if; -- Set the SPARK mode from the current context (may be overwritten later -- with explicit pragma). Set_SPARK_Pragma (Id, SPARK_Mode_Pragma); Set_SPARK_Pragma_Inherited (Id); -- Preserve relevant elaboration-related attributes of the context which -- are no longer available or very expensive to recompute once analysis, -- resolution, and expansion are over. Mark_Elaboration_Attributes (N_Id => Id, Checks => True, Warnings => True); -- Initialize alignment and size and capture alignment setting Reinit_Alignment (Id); Reinit_Esize (Id); Set_Optimize_Alignment_Flags (Id); -- Deal with aliased case if Aliased_Present (N) then Set_Is_Aliased (Id); -- AI12-001: All aliased objects are considered to be specified as -- independently addressable (RM C.6(8.1/4)). Set_Is_Independent (Id); -- If the object is aliased and the type is unconstrained with -- defaulted discriminants and there is no expression, then the -- object is constrained by the defaults, so it is worthwhile -- building the corresponding subtype. -- Ada 2005 (AI-363): If the aliased object is discriminated and -- unconstrained, then only establish an actual subtype if the -- nominal subtype is indefinite. In definite cases the object is -- unconstrained in Ada 2005. if No (E) and then Is_Record_Type (T) and then not Is_Constrained (T) and then Has_Discriminants (T) and then (Ada_Version < Ada_2005 or else not Is_Definite_Subtype (T)) then Set_Actual_Subtype (Id, Build_Default_Subtype (T, N)); end if; end if; -- Now we can set the type of the object Set_Etype (Id, Act_T); -- Non-constant object is marked to be treated as volatile if type is -- volatile and we clear the Current_Value setting that may have been -- set above. Doing so for constants isn't required and might interfere -- with possible uses of the object as a static expression in contexts -- incompatible with volatility (e.g. as a case-statement alternative). if Ekind (Id) /= E_Constant and then Treat_As_Volatile (Etype (Id)) then Set_Treat_As_Volatile (Id); Set_Current_Value (Id, Empty); end if; -- Deal with controlled types if Has_Controlled_Component (Etype (Id)) or else Is_Controlled (Etype (Id)) then if not Is_Library_Level_Entity (Id) then Check_Restriction (No_Nested_Finalization, N); else Validate_Controlled_Object (Id); end if; end if; if Has_Task (Etype (Id)) then Check_Restriction (No_Tasking, N); -- Deal with counting max tasks -- Nothing to do if inside a generic if Inside_A_Generic then null; -- If library level entity, then count tasks elsif Is_Library_Level_Entity (Id) then Check_Restriction (Max_Tasks, N, Count_Tasks (Etype (Id))); -- If not library level entity, then indicate we don't know max -- tasks and also check task hierarchy restriction and blocking -- operation (since starting a task is definitely blocking). else Check_Restriction (Max_Tasks, N); Check_Restriction (No_Task_Hierarchy, N); Check_Potentially_Blocking_Operation (N); end if; -- A rather specialized test. If we see two tasks being declared -- of the same type in the same object declaration, and the task -- has an entry with an address clause, we know that program error -- will be raised at run time since we can't have two tasks with -- entries at the same address. if Is_Task_Type (Etype (Id)) and then More_Ids (N) then declare E : Entity_Id; begin E := First_Entity (Etype (Id)); while Present (E) loop if Ekind (E) = E_Entry and then Present (Get_Attribute_Definition_Clause (E, Attribute_Address)) then Error_Msg_Warn := SPARK_Mode /= On; Error_Msg_N ("more than one task with same entry address<<", N); Error_Msg_N ("\Program_Error [<<", N); Insert_Action (N, Make_Raise_Program_Error (Loc, Reason => PE_Duplicated_Entry_Address)); exit; end if; Next_Entity (E); end loop; end; end if; end if; -- Some simple constant-propagation: if the expression is a constant -- string initialized with a literal, share the literal. This avoids -- a run-time copy. if Present (E) and then Is_Entity_Name (E) and then Ekind (Entity (E)) = E_Constant and then Base_Type (Etype (E)) = Standard_String then declare Val : constant Node_Id := Constant_Value (Entity (E)); begin if Present (Val) and then Nkind (Val) = N_String_Literal then Rewrite (E, New_Copy (Val)); end if; end; end if; -- Another optimization: if the nominal subtype is unconstrained and -- the expression is a function call that returns an unconstrained -- type, rewrite the declaration as a renaming of the result of the -- call. The exceptions below are cases where the copy is expected, -- either by the back end (Aliased case) or by the semantics, as for -- initializing controlled types or copying tags for class-wide types. if Present (E) and then Nkind (E) = N_Explicit_Dereference and then Nkind (Original_Node (E)) = N_Function_Call and then not Is_Library_Level_Entity (Id) and then not Is_Constrained (Underlying_Type (T)) and then not Is_Aliased (Id) and then not Is_Class_Wide_Type (T) and then not Is_Controlled (T) and then not Has_Controlled_Component (Base_Type (T)) and then Expander_Active then Rewrite (N, Make_Object_Renaming_Declaration (Loc, Defining_Identifier => Id, Access_Definition => Empty, Subtype_Mark => New_Occurrence_Of (Base_Type (Etype (Id)), Loc), Name => E)); Set_Renamed_Object (Id, E); -- Force generation of debugging information for the constant and for -- the renamed function call. Set_Debug_Info_Needed (Id); Set_Debug_Info_Needed (Entity (Prefix (E))); end if; if Present (Prev_Entity) and then Is_Frozen (Prev_Entity) and then not Error_Posted (Id) then Error_Msg_N ("full constant declaration appears too late", N); end if; Check_Eliminated (Id); -- Deal with setting In_Private_Part flag if in private part if Ekind (Scope (Id)) = E_Package and then In_Private_Part (Scope (Id)) then Set_In_Private_Part (Id); end if; <> -- Initialize the refined state of a variable here because this is a -- common destination for legal and illegal object declarations. if Ekind (Id) = E_Variable then Set_Encapsulating_State (Id, Empty); end if; if Has_Aspects (N) then Analyze_Aspect_Specifications (N, Id); end if; Analyze_Dimension (N); -- Verify whether the object declaration introduces an illegal hidden -- state within a package subject to a null abstract state. if Ekind (Id) = E_Variable then Check_No_Hidden_State (Id); end if; Restore_Ghost_Region (Saved_GM, Saved_IGR); end Analyze_Object_Declaration; --------------------------- -- Analyze_Others_Choice -- --------------------------- -- Nothing to do for the others choice node itself, the semantic analysis -- of the others choice will occur as part of the processing of the parent procedure Analyze_Others_Choice (N : Node_Id) is pragma Warnings (Off, N); begin null; end Analyze_Others_Choice; ------------------------------------------- -- Analyze_Private_Extension_Declaration -- ------------------------------------------- procedure Analyze_Private_Extension_Declaration (N : Node_Id) is Indic : constant Node_Id := Subtype_Indication (N); T : constant Entity_Id := Defining_Identifier (N); Iface : Entity_Id; Iface_Elmt : Elmt_Id; Parent_Base : Entity_Id; Parent_Type : Entity_Id; begin -- Ada 2005 (AI-251): Decorate all names in list of ancestor interfaces if Is_Non_Empty_List (Interface_List (N)) then declare Intf : Node_Id; T : Entity_Id; begin Intf := First (Interface_List (N)); while Present (Intf) loop T := Find_Type_Of_Subtype_Indic (Intf); Diagnose_Interface (Intf, T); Next (Intf); end loop; end; end if; Generate_Definition (T); -- For other than Ada 2012, just enter the name in the current scope if Ada_Version < Ada_2012 then Enter_Name (T); -- Ada 2012 (AI05-0162): Enter the name in the current scope handling -- case of private type that completes an incomplete type. else declare Prev : Entity_Id; begin Prev := Find_Type_Name (N); pragma Assert (Prev = T or else (Ekind (Prev) = E_Incomplete_Type and then Present (Full_View (Prev)) and then Full_View (Prev) = T)); end; end if; Parent_Type := Find_Type_Of_Subtype_Indic (Indic); Parent_Base := Base_Type (Parent_Type); if Parent_Type = Any_Type or else Etype (Parent_Type) = Any_Type then Mutate_Ekind (T, Ekind (Parent_Type)); Set_Etype (T, Any_Type); goto Leave; elsif not Is_Tagged_Type (Parent_Type) then Error_Msg_N ("parent of type extension must be a tagged type", Indic); goto Leave; elsif Ekind (Parent_Type) in E_Void | E_Incomplete_Type then Error_Msg_N ("premature derivation of incomplete type", Indic); goto Leave; elsif Is_Concurrent_Type (Parent_Type) then Error_Msg_N ("parent type of a private extension cannot be a synchronized " & "tagged type (RM 3.9.1 (3/1))", N); Set_Etype (T, Any_Type); Mutate_Ekind (T, E_Limited_Private_Type); Set_Private_Dependents (T, New_Elmt_List); Set_Error_Posted (T); goto Leave; end if; Check_Wide_Character_Restriction (Parent_Type, Indic); -- Perhaps the parent type should be changed to the class-wide type's -- specific type in this case to prevent cascading errors ??? if Is_Class_Wide_Type (Parent_Type) then Error_Msg_N ("parent of type extension must not be a class-wide type", Indic); goto Leave; end if; if (not Is_Package_Or_Generic_Package (Current_Scope) and then Nkind (Parent (N)) /= N_Generic_Subprogram_Declaration) or else In_Private_Part (Current_Scope) then Error_Msg_N ("invalid context for private extension", N); end if; -- Set common attributes Set_Is_Pure (T, Is_Pure (Current_Scope)); Set_Scope (T, Current_Scope); Mutate_Ekind (T, E_Record_Type_With_Private); Reinit_Size_Align (T); Set_Default_SSO (T); Set_No_Reordering (T, No_Component_Reordering); Set_Etype (T, Parent_Base); Propagate_Concurrent_Flags (T, Parent_Base); Set_Convention (T, Convention (Parent_Type)); Set_First_Rep_Item (T, First_Rep_Item (Parent_Type)); Set_Is_First_Subtype (T); Make_Class_Wide_Type (T); -- Set the SPARK mode from the current context Set_SPARK_Pragma (T, SPARK_Mode_Pragma); Set_SPARK_Pragma_Inherited (T); if Unknown_Discriminants_Present (N) then Set_Discriminant_Constraint (T, No_Elist); end if; Build_Derived_Record_Type (N, Parent_Type, T); -- A private extension inherits the Default_Initial_Condition pragma -- coming from any parent type within the derivation chain. if Has_DIC (Parent_Type) then Set_Has_Inherited_DIC (T); end if; -- A private extension inherits any class-wide invariants coming from a -- parent type or an interface. Note that the invariant procedure of the -- parent type should not be inherited because the private extension may -- define invariants of its own. if Has_Inherited_Invariants (Parent_Type) or else Has_Inheritable_Invariants (Parent_Type) then Set_Has_Inherited_Invariants (T); elsif Present (Interfaces (T)) then Iface_Elmt := First_Elmt (Interfaces (T)); while Present (Iface_Elmt) loop Iface := Node (Iface_Elmt); if Has_Inheritable_Invariants (Iface) then Set_Has_Inherited_Invariants (T); exit; end if; Next_Elmt (Iface_Elmt); end loop; end if; -- Ada 2005 (AI-443): Synchronized private extension or a rewritten -- synchronized formal derived type. if Ada_Version >= Ada_2005 and then Synchronized_Present (N) then Set_Is_Limited_Record (T); -- Formal derived type case if Is_Generic_Type (T) then -- The parent must be a tagged limited type or a synchronized -- interface. if (not Is_Tagged_Type (Parent_Type) or else not Is_Limited_Type (Parent_Type)) and then (not Is_Interface (Parent_Type) or else not Is_Synchronized_Interface (Parent_Type)) then Error_Msg_NE ("parent type of & must be tagged limited or synchronized", N, T); end if; -- The progenitors (if any) must be limited or synchronized -- interfaces. if Present (Interfaces (T)) then Iface_Elmt := First_Elmt (Interfaces (T)); while Present (Iface_Elmt) loop Iface := Node (Iface_Elmt); if not Is_Limited_Interface (Iface) and then not Is_Synchronized_Interface (Iface) then Error_Msg_NE ("progenitor & must be limited or synchronized", N, Iface); end if; Next_Elmt (Iface_Elmt); end loop; end if; -- Regular derived extension, the parent must be a limited or -- synchronized interface. else if not Is_Interface (Parent_Type) or else (not Is_Limited_Interface (Parent_Type) and then not Is_Synchronized_Interface (Parent_Type)) then Error_Msg_NE ("parent type of & must be limited interface", N, T); end if; end if; -- A consequence of 3.9.4 (6/2) and 7.3 (7.2/2) is that a private -- extension with a synchronized parent must be explicitly declared -- synchronized, because the full view will be a synchronized type. -- This must be checked before the check for limited types below, -- to ensure that types declared limited are not allowed to extend -- synchronized interfaces. elsif Is_Interface (Parent_Type) and then Is_Synchronized_Interface (Parent_Type) and then not Synchronized_Present (N) then Error_Msg_NE ("private extension of& must be explicitly synchronized", N, Parent_Type); elsif Limited_Present (N) then Set_Is_Limited_Record (T); if not Is_Limited_Type (Parent_Type) and then (not Is_Interface (Parent_Type) or else not Is_Limited_Interface (Parent_Type)) then Error_Msg_NE ("parent type& of limited extension must be limited", N, Parent_Type); end if; end if; -- Remember that its parent type has a private extension. Used to warn -- on public primitives of the parent type defined after its private -- extensions (see Check_Dispatching_Operation). Set_Has_Private_Extension (Parent_Type); <> if Has_Aspects (N) then Analyze_Aspect_Specifications (N, T); end if; end Analyze_Private_Extension_Declaration; --------------------------------- -- Analyze_Subtype_Declaration -- --------------------------------- procedure Analyze_Subtype_Declaration (N : Node_Id; Skip : Boolean := False) is Id : constant Entity_Id := Defining_Identifier (N); T : Entity_Id; begin Generate_Definition (Id); Set_Is_Pure (Id, Is_Pure (Current_Scope)); Reinit_Size_Align (Id); -- The following guard condition on Enter_Name is to handle cases where -- the defining identifier has already been entered into the scope but -- the declaration as a whole needs to be analyzed. -- This case in particular happens for derived enumeration types. The -- derived enumeration type is processed as an inserted enumeration type -- declaration followed by a rewritten subtype declaration. The defining -- identifier, however, is entered into the name scope very early in the -- processing of the original type declaration and therefore needs to be -- avoided here, when the created subtype declaration is analyzed. (See -- Build_Derived_Types) -- This also happens when the full view of a private type is derived -- type with constraints. In this case the entity has been introduced -- in the private declaration. -- Finally this happens in some complex cases when validity checks are -- enabled, where the same subtype declaration may be analyzed twice. -- This can happen if the subtype is created by the preanalysis of -- an attribute tht gives the range of a loop statement, and the loop -- itself appears within an if_statement that will be rewritten during -- expansion. if Skip or else (Present (Etype (Id)) and then (Is_Private_Type (Etype (Id)) or else Is_Task_Type (Etype (Id)) or else Is_Rewrite_Substitution (N))) then null; elsif Current_Entity (Id) = Id then null; else Enter_Name (Id); end if; T := Process_Subtype (Subtype_Indication (N), N, Id, 'P'); -- Class-wide equivalent types of records with unknown discriminants -- involve the generation of an itype which serves as the private view -- of a constrained record subtype. In such cases the base type of the -- current subtype we are processing is the private itype. Use the full -- of the private itype when decorating various attributes. if Is_Itype (T) and then Is_Private_Type (T) and then Present (Full_View (T)) then T := Full_View (T); end if; -- Inherit common attributes Set_Is_Volatile (Id, Is_Volatile (T)); Set_Treat_As_Volatile (Id, Treat_As_Volatile (T)); Set_Is_Generic_Type (Id, Is_Generic_Type (Base_Type (T))); Set_Convention (Id, Convention (T)); -- If ancestor has predicates then so does the subtype, and in addition -- we must delay the freeze to properly arrange predicate inheritance. -- The Ancestor_Type test is really unpleasant, there seem to be cases -- in which T = ID, so the above tests and assignments do nothing??? if Has_Predicates (T) or else (Present (Ancestor_Subtype (T)) and then Has_Predicates (Ancestor_Subtype (T))) then Set_Has_Predicates (Id); Set_Has_Delayed_Freeze (Id); -- Generated subtypes inherit the predicate function from the parent -- (no aspects to examine on the generated declaration). if not Comes_From_Source (N) then Mutate_Ekind (Id, Ekind (T)); if Present (Predicate_Function (Id)) then null; elsif Present (Predicate_Function (T)) then Set_Predicate_Function (Id, Predicate_Function (T)); elsif Present (Ancestor_Subtype (T)) and then Present (Predicate_Function (Ancestor_Subtype (T))) then Set_Predicate_Function (Id, Predicate_Function (Ancestor_Subtype (T))); end if; end if; end if; -- In the case where there is no constraint given in the subtype -- indication, Process_Subtype just returns the Subtype_Mark, so its -- semantic attributes must be established here. if Nkind (Subtype_Indication (N)) /= N_Subtype_Indication then Set_Etype (Id, Base_Type (T)); case Ekind (T) is when Array_Kind => Mutate_Ekind (Id, E_Array_Subtype); Copy_Array_Subtype_Attributes (Id, T); Set_Packed_Array_Impl_Type (Id, Packed_Array_Impl_Type (T)); when Decimal_Fixed_Point_Kind => Mutate_Ekind (Id, E_Decimal_Fixed_Point_Subtype); Set_Digits_Value (Id, Digits_Value (T)); Set_Delta_Value (Id, Delta_Value (T)); Set_Scale_Value (Id, Scale_Value (T)); Set_Small_Value (Id, Small_Value (T)); Set_Scalar_Range (Id, Scalar_Range (T)); Set_Machine_Radix_10 (Id, Machine_Radix_10 (T)); Set_Is_Constrained (Id, Is_Constrained (T)); Set_Is_Known_Valid (Id, Is_Known_Valid (T)); Copy_RM_Size (To => Id, From => T); when Enumeration_Kind => Mutate_Ekind (Id, E_Enumeration_Subtype); Set_First_Literal (Id, First_Literal (Base_Type (T))); Set_Scalar_Range (Id, Scalar_Range (T)); Set_Is_Character_Type (Id, Is_Character_Type (T)); Set_Is_Constrained (Id, Is_Constrained (T)); Set_Is_Known_Valid (Id, Is_Known_Valid (T)); Copy_RM_Size (To => Id, From => T); when Ordinary_Fixed_Point_Kind => Mutate_Ekind (Id, E_Ordinary_Fixed_Point_Subtype); Set_Scalar_Range (Id, Scalar_Range (T)); Set_Small_Value (Id, Small_Value (T)); Set_Delta_Value (Id, Delta_Value (T)); Set_Is_Constrained (Id, Is_Constrained (T)); Set_Is_Known_Valid (Id, Is_Known_Valid (T)); Copy_RM_Size (To => Id, From => T); when Float_Kind => Mutate_Ekind (Id, E_Floating_Point_Subtype); Set_Scalar_Range (Id, Scalar_Range (T)); Set_Digits_Value (Id, Digits_Value (T)); Set_Is_Constrained (Id, Is_Constrained (T)); -- If the floating point type has dimensions, these will be -- inherited subsequently when Analyze_Dimensions is called. when Signed_Integer_Kind => Mutate_Ekind (Id, E_Signed_Integer_Subtype); Set_Scalar_Range (Id, Scalar_Range (T)); Set_Is_Constrained (Id, Is_Constrained (T)); Set_Is_Known_Valid (Id, Is_Known_Valid (T)); Copy_RM_Size (To => Id, From => T); when Modular_Integer_Kind => Mutate_Ekind (Id, E_Modular_Integer_Subtype); Set_Scalar_Range (Id, Scalar_Range (T)); Set_Is_Constrained (Id, Is_Constrained (T)); Set_Is_Known_Valid (Id, Is_Known_Valid (T)); Copy_RM_Size (To => Id, From => T); when Class_Wide_Kind => Mutate_Ekind (Id, E_Class_Wide_Subtype); Set_Class_Wide_Type (Id, Class_Wide_Type (T)); Set_Cloned_Subtype (Id, T); Set_Is_Tagged_Type (Id, True); Set_Is_Limited_Record (Id, Is_Limited_Record (T)); Set_Has_Unknown_Discriminants (Id, True); Set_No_Tagged_Streams_Pragma (Id, No_Tagged_Streams_Pragma (T)); if Ekind (T) = E_Class_Wide_Subtype then Set_Equivalent_Type (Id, Equivalent_Type (T)); end if; when E_Record_Subtype | E_Record_Type => Mutate_Ekind (Id, E_Record_Subtype); -- Subtype declarations introduced for formal type parameters -- in generic instantiations should inherit the Size value of -- the type they rename. if Present (Generic_Parent_Type (N)) then Copy_RM_Size (To => Id, From => T); end if; if Ekind (T) = E_Record_Subtype and then Present (Cloned_Subtype (T)) then Set_Cloned_Subtype (Id, Cloned_Subtype (T)); else Set_Cloned_Subtype (Id, T); end if; Set_First_Entity (Id, First_Entity (T)); Set_Last_Entity (Id, Last_Entity (T)); Set_Has_Discriminants (Id, Has_Discriminants (T)); Set_Is_Constrained (Id, Is_Constrained (T)); Set_Is_Limited_Record (Id, Is_Limited_Record (T)); Set_Has_Implicit_Dereference (Id, Has_Implicit_Dereference (T)); Set_Has_Unknown_Discriminants (Id, Has_Unknown_Discriminants (T)); if Has_Discriminants (T) then Set_Discriminant_Constraint (Id, Discriminant_Constraint (T)); Set_Stored_Constraint_From_Discriminant_Constraint (Id); elsif Has_Unknown_Discriminants (Id) then Set_Discriminant_Constraint (Id, No_Elist); end if; if Is_Tagged_Type (T) then Set_Is_Tagged_Type (Id, True); Set_No_Tagged_Streams_Pragma (Id, No_Tagged_Streams_Pragma (T)); Set_Is_Abstract_Type (Id, Is_Abstract_Type (T)); Set_Direct_Primitive_Operations (Id, Direct_Primitive_Operations (T)); Set_Class_Wide_Type (Id, Class_Wide_Type (T)); if Is_Interface (T) then Set_Is_Interface (Id); Set_Is_Limited_Interface (Id, Is_Limited_Interface (T)); end if; end if; when Private_Kind => Mutate_Ekind (Id, Subtype_Kind (Ekind (T))); Set_Has_Discriminants (Id, Has_Discriminants (T)); Set_Is_Constrained (Id, Is_Constrained (T)); Set_First_Entity (Id, First_Entity (T)); Set_Last_Entity (Id, Last_Entity (T)); Set_Private_Dependents (Id, New_Elmt_List); Set_Is_Limited_Record (Id, Is_Limited_Record (T)); Set_Has_Implicit_Dereference (Id, Has_Implicit_Dereference (T)); Set_Has_Unknown_Discriminants (Id, Has_Unknown_Discriminants (T)); Set_Known_To_Have_Preelab_Init (Id, Known_To_Have_Preelab_Init (T)); if Is_Tagged_Type (T) then Set_Is_Tagged_Type (Id); Set_No_Tagged_Streams_Pragma (Id, No_Tagged_Streams_Pragma (T)); Set_Is_Abstract_Type (Id, Is_Abstract_Type (T)); Set_Class_Wide_Type (Id, Class_Wide_Type (T)); Set_Direct_Primitive_Operations (Id, Direct_Primitive_Operations (T)); end if; -- In general the attributes of the subtype of a private type -- are the attributes of the partial view of parent. However, -- the full view may be a discriminated type, and the subtype -- must share the discriminant constraint to generate correct -- calls to initialization procedures. if Has_Discriminants (T) then Set_Discriminant_Constraint (Id, Discriminant_Constraint (T)); Set_Stored_Constraint_From_Discriminant_Constraint (Id); elsif Present (Full_View (T)) and then Has_Discriminants (Full_View (T)) then Set_Discriminant_Constraint (Id, Discriminant_Constraint (Full_View (T))); Set_Stored_Constraint_From_Discriminant_Constraint (Id); -- This would seem semantically correct, but apparently -- generates spurious errors about missing components ??? -- Set_Has_Discriminants (Id); end if; Prepare_Private_Subtype_Completion (Id, N); -- If this is the subtype of a constrained private type with -- discriminants that has got a full view and we also have -- built a completion just above, show that the completion -- is a clone of the full view to the back-end. if Has_Discriminants (T) and then not Has_Unknown_Discriminants (T) and then not Is_Empty_Elmt_List (Discriminant_Constraint (T)) and then Present (Full_View (T)) and then Present (Full_View (Id)) then Set_Cloned_Subtype (Full_View (Id), Full_View (T)); end if; when Access_Kind => Mutate_Ekind (Id, E_Access_Subtype); Set_Is_Constrained (Id, Is_Constrained (T)); Set_Is_Access_Constant (Id, Is_Access_Constant (T)); Set_Directly_Designated_Type (Id, Designated_Type (T)); Set_Can_Never_Be_Null (Id, Can_Never_Be_Null (T)); -- A Pure library_item must not contain the declaration of a -- named access type, except within a subprogram, generic -- subprogram, task unit, or protected unit, or if it has -- a specified Storage_Size of zero (RM05-10.2.1(15.4-15.5)). if Comes_From_Source (Id) and then In_Pure_Unit and then not In_Subprogram_Task_Protected_Unit and then not No_Pool_Assigned (Id) then Error_Msg_N ("named access types not allowed in pure unit", N); end if; when Concurrent_Kind => Mutate_Ekind (Id, Subtype_Kind (Ekind (T))); Set_Corresponding_Record_Type (Id, Corresponding_Record_Type (T)); Set_First_Entity (Id, First_Entity (T)); Set_First_Private_Entity (Id, First_Private_Entity (T)); Set_Has_Discriminants (Id, Has_Discriminants (T)); Set_Is_Constrained (Id, Is_Constrained (T)); Set_Is_Tagged_Type (Id, Is_Tagged_Type (T)); Set_Last_Entity (Id, Last_Entity (T)); if Is_Tagged_Type (T) then Set_No_Tagged_Streams_Pragma (Id, No_Tagged_Streams_Pragma (T)); end if; if Has_Discriminants (T) then Set_Discriminant_Constraint (Id, Discriminant_Constraint (T)); Set_Stored_Constraint_From_Discriminant_Constraint (Id); end if; when Incomplete_Kind => if Ada_Version >= Ada_2005 then -- In Ada 2005 an incomplete type can be explicitly tagged: -- propagate indication. Note that we also have to include -- subtypes for Ada 2012 extended use of incomplete types. Mutate_Ekind (Id, E_Incomplete_Subtype); Set_Is_Tagged_Type (Id, Is_Tagged_Type (T)); Set_Private_Dependents (Id, New_Elmt_List); if Is_Tagged_Type (Id) then Set_No_Tagged_Streams_Pragma (Id, No_Tagged_Streams_Pragma (T)); end if; -- For tagged types, or when prefixed-call syntax is allowed -- for untagged types, initialize the list of primitive -- operations to an empty list. if Is_Tagged_Type (Id) or else Extensions_Allowed then Set_Direct_Primitive_Operations (Id, New_Elmt_List); end if; -- Ada 2005 (AI-412): Decorate an incomplete subtype of an -- incomplete type visible through a limited with clause. if From_Limited_With (T) and then Present (Non_Limited_View (T)) then Set_From_Limited_With (Id); Set_Non_Limited_View (Id, Non_Limited_View (T)); -- Ada 2005 (AI-412): Add the regular incomplete subtype -- to the private dependents of the original incomplete -- type for future transformation. else Append_Elmt (Id, Private_Dependents (T)); end if; -- If the subtype name denotes an incomplete type an error -- was already reported by Process_Subtype. else Set_Etype (Id, Any_Type); end if; when others => raise Program_Error; end case; -- If there is no constraint in the subtype indication, the -- declared entity inherits predicates from the parent. Inherit_Predicate_Flags (Id, T); end if; if Etype (Id) = Any_Type then goto Leave; end if; -- When prefixed calls are enabled for untagged types, the subtype -- shares the primitive operations of its base type. Do this even -- when Extensions_Allowed is False to issue better error messages. Set_Direct_Primitive_Operations (Id, Direct_Primitive_Operations (Base_Type (T))); -- Some common processing on all types Set_Size_Info (Id, T); Set_First_Rep_Item (Id, First_Rep_Item (T)); -- If the parent type is a generic actual, so is the subtype. This may -- happen in a nested instance. Why Comes_From_Source test??? if not Comes_From_Source (N) then Set_Is_Generic_Actual_Type (Id, Is_Generic_Actual_Type (T)); end if; -- If this is a subtype declaration for an actual in an instance, -- inherit static and dynamic predicates if any. -- If declaration has no aspect specifications, inherit predicate -- info as well. Unclear how to handle the case of both specified -- and inherited predicates ??? Other inherited aspects, such as -- invariants, should be OK, but the combination with later pragmas -- may also require special merging. if Has_Predicates (T) and then Present (Predicate_Function (T)) and then ((In_Instance and then not Comes_From_Source (N)) or else No (Aspect_Specifications (N))) then -- Inherit Subprograms_For_Type from the full view, if present if Present (Full_View (T)) and then Subprograms_For_Type (Full_View (T)) /= No_Elist then Set_Subprograms_For_Type (Id, Subprograms_For_Type (Full_View (T))); else Set_Subprograms_For_Type (Id, Subprograms_For_Type (T)); end if; -- If the current declaration created both a private and a full view, -- then propagate Predicate_Function to the latter as well. if Present (Full_View (Id)) and then No (Predicate_Function (Full_View (Id))) then Set_Subprograms_For_Type (Full_View (Id), Subprograms_For_Type (Id)); end if; if Has_Static_Predicate (T) then Set_Has_Static_Predicate (Id); Set_Static_Discrete_Predicate (Id, Static_Discrete_Predicate (T)); end if; end if; -- If the base type is a scalar type, or else if there is no -- constraint, the atomic flag is inherited by the subtype. -- Ditto for the Independent aspect. if Is_Scalar_Type (Id) or else Is_Entity_Name (Subtype_Indication (N)) then Set_Is_Atomic (Id, Is_Atomic (T)); Set_Is_Independent (Id, Is_Independent (T)); end if; -- Remaining processing depends on characteristics of base type T := Etype (Id); Set_Is_Immediately_Visible (Id, True); Set_Depends_On_Private (Id, Has_Private_Component (T)); Set_Is_Descendant_Of_Address (Id, Is_Descendant_Of_Address (T)); if Is_Interface (T) then Set_Is_Interface (Id); Set_Is_Limited_Interface (Id, Is_Limited_Interface (T)); end if; if Present (Generic_Parent_Type (N)) and then (Nkind (Parent (Generic_Parent_Type (N))) /= N_Formal_Type_Declaration or else Nkind (Formal_Type_Definition (Parent (Generic_Parent_Type (N)))) /= N_Formal_Private_Type_Definition) then if Is_Tagged_Type (Id) then -- If this is a generic actual subtype for a synchronized type, -- the primitive operations are those of the corresponding record -- for which there is a separate subtype declaration. if Is_Concurrent_Type (Id) then null; elsif Is_Class_Wide_Type (Id) then Derive_Subprograms (Generic_Parent_Type (N), Id, Etype (T)); else Derive_Subprograms (Generic_Parent_Type (N), Id, T); end if; elsif Scope (Etype (Id)) /= Standard_Standard then Derive_Subprograms (Generic_Parent_Type (N), Id); end if; end if; if Is_Private_Type (T) and then Present (Full_View (T)) then Conditional_Delay (Id, Full_View (T)); -- The subtypes of components or subcomponents of protected types -- do not need freeze nodes, which would otherwise appear in the -- wrong scope (before the freeze node for the protected type). The -- proper subtypes are those of the subcomponents of the corresponding -- record. elsif Ekind (Scope (Id)) /= E_Protected_Type and then Present (Scope (Scope (Id))) -- error defense and then Ekind (Scope (Scope (Id))) /= E_Protected_Type then Conditional_Delay (Id, T); end if; -- If we have a subtype of an incomplete type whose full type is a -- derived numeric type, we need to have a freeze node for the subtype. -- Otherwise gigi will complain while computing the (static) bounds of -- the subtype. if Is_Itype (T) and then Is_Elementary_Type (Id) and then Etype (Id) /= Id then declare Partial : constant Entity_Id := Incomplete_Or_Partial_View (First_Subtype (Id)); begin if Present (Partial) and then Ekind (Partial) = E_Incomplete_Type then Set_Has_Delayed_Freeze (Id); end if; end; end if; -- Check that Constraint_Error is raised for a scalar subtype indication -- when the lower or upper bound of a non-null range lies outside the -- range of the type mark. Likewise for an array subtype, but check the -- compatibility for each index. if Nkind (Subtype_Indication (N)) = N_Subtype_Indication then declare Indic_Typ : constant Entity_Id := Etype (Subtype_Mark (Subtype_Indication (N))); Subt_Index : Node_Id; Target_Index : Node_Id; begin if Is_Scalar_Type (Etype (Id)) and then Scalar_Range (Id) /= Scalar_Range (Indic_Typ) then Apply_Range_Check (Scalar_Range (Id), Indic_Typ); elsif Is_Array_Type (Etype (Id)) and then Present (First_Index (Id)) then Subt_Index := First_Index (Id); Target_Index := First_Index (Indic_Typ); while Present (Subt_Index) loop if ((Nkind (Subt_Index) in N_Expanded_Name | N_Identifier and then Is_Scalar_Type (Entity (Subt_Index))) or else Nkind (Subt_Index) = N_Subtype_Indication) and then Nkind (Scalar_Range (Etype (Subt_Index))) = N_Range then Apply_Range_Check (Scalar_Range (Etype (Subt_Index)), Etype (Target_Index), Insert_Node => N); end if; Next_Index (Subt_Index); Next_Index (Target_Index); end loop; end if; end; end if; Set_Optimize_Alignment_Flags (Id); Check_Eliminated (Id); <> if Has_Aspects (N) then Analyze_Aspect_Specifications (N, Id); end if; Analyze_Dimension (N); -- Check No_Dynamic_Sized_Objects restriction, which disallows subtype -- indications on composite types where the constraints are dynamic. -- Note that object declarations and aggregates generate implicit -- subtype declarations, which this covers. One special case is that the -- implicitly generated "=" for discriminated types includes an -- offending subtype declaration, which is harmless, so we ignore it -- here. if Nkind (Subtype_Indication (N)) = N_Subtype_Indication then declare Cstr : constant Node_Id := Constraint (Subtype_Indication (N)); begin if Nkind (Cstr) = N_Index_Or_Discriminant_Constraint and then not (Is_Internal (Id) and then Is_TSS (Scope (Id), TSS_Composite_Equality)) and then not Within_Init_Proc and then not All_Composite_Constraints_Static (Cstr) then Check_Restriction (No_Dynamic_Sized_Objects, Cstr); end if; end; end if; end Analyze_Subtype_Declaration; -------------------------------- -- Analyze_Subtype_Indication -- -------------------------------- procedure Analyze_Subtype_Indication (N : Node_Id) is T : constant Entity_Id := Subtype_Mark (N); R : constant Node_Id := Range_Expression (Constraint (N)); begin Analyze (T); if R = Error then Set_Error_Posted (R); Set_Error_Posted (T); else Analyze (R); Set_Etype (N, Etype (R)); Resolve (R, Entity (T)); end if; end Analyze_Subtype_Indication; -------------------------- -- Analyze_Variant_Part -- -------------------------- procedure Analyze_Variant_Part (N : Node_Id) is Discr_Name : Node_Id; Discr_Type : Entity_Id; procedure Process_Variant (A : Node_Id); -- Analyze declarations for a single variant package Analyze_Variant_Choices is new Generic_Analyze_Choices (Process_Variant); use Analyze_Variant_Choices; --------------------- -- Process_Variant -- --------------------- procedure Process_Variant (A : Node_Id) is CL : constant Node_Id := Component_List (A); begin if not Null_Present (CL) then Analyze_Declarations (Component_Items (CL)); if Present (Variant_Part (CL)) then Analyze (Variant_Part (CL)); end if; end if; end Process_Variant; -- Start of processing for Analyze_Variant_Part begin Discr_Name := Name (N); Analyze (Discr_Name); -- If Discr_Name bad, get out (prevent cascaded errors) if Etype (Discr_Name) = Any_Type then return; end if; -- Check invalid discriminant in variant part if Ekind (Entity (Discr_Name)) /= E_Discriminant then Error_Msg_N ("invalid discriminant name in variant part", Discr_Name); end if; Discr_Type := Etype (Entity (Discr_Name)); if not Is_Discrete_Type (Discr_Type) then Error_Msg_N ("discriminant in a variant part must be of a discrete type", Name (N)); return; end if; -- Now analyze the choices, which also analyzes the declarations that -- are associated with each choice. Analyze_Choices (Variants (N), Discr_Type); -- Note: we used to instantiate and call Check_Choices here to check -- that the choices covered the discriminant, but it's too early to do -- that because of statically predicated subtypes, whose analysis may -- be deferred to their freeze point which may be as late as the freeze -- point of the containing record. So this call is now to be found in -- Freeze_Record_Declaration. end Analyze_Variant_Part; ---------------------------- -- Array_Type_Declaration -- ---------------------------- procedure Array_Type_Declaration (T : in out Entity_Id; Def : Node_Id) is Component_Def : constant Node_Id := Component_Definition (Def); Component_Typ : constant Node_Id := Subtype_Indication (Component_Def); P : constant Node_Id := Parent (Def); Element_Type : Entity_Id; Implicit_Base : Entity_Id; Index : Node_Id; Nb_Index : Pos; Priv : Entity_Id; Related_Id : Entity_Id; Has_FLB_Index : Boolean := False; begin if Nkind (Def) = N_Constrained_Array_Definition then Index := First (Discrete_Subtype_Definitions (Def)); else Index := First (Subtype_Marks (Def)); end if; -- Find proper names for the implicit types which may be public. In case -- of anonymous arrays we use the name of the first object of that type -- as prefix. if No (T) then Related_Id := Defining_Identifier (P); else Related_Id := T; end if; Nb_Index := 1; while Present (Index) loop Analyze (Index); -- Test for odd case of trying to index a type by the type itself if Is_Entity_Name (Index) and then Entity (Index) = T then Error_Msg_N ("type& cannot be indexed by itself", Index); Set_Entity (Index, Standard_Boolean); Set_Etype (Index, Standard_Boolean); end if; -- Add a subtype declaration for each index of private array type -- declaration whose type is also private. For example: -- package Pkg is -- type Index is private; -- private -- type Table is array (Index) of ... -- end; -- This is currently required by the expander for the internally -- generated equality subprogram of records with variant parts in -- which the type of some component is such a private type. And it -- also helps semantic analysis in peculiar cases where the array -- type is referenced from an instance but not the index directly. if Is_Package_Or_Generic_Package (Current_Scope) and then In_Private_Part (Current_Scope) and then Has_Private_Declaration (Etype (Index)) and then Scope (Etype (Index)) = Current_Scope then declare Loc : constant Source_Ptr := Sloc (Def); Decl : Node_Id; New_E : Entity_Id; begin New_E := Make_Temporary (Loc, 'T'); Set_Is_Internal (New_E); Decl := Make_Subtype_Declaration (Loc, Defining_Identifier => New_E, Subtype_Indication => New_Occurrence_Of (Etype (Index), Loc)); Insert_Before (Parent (Def), Decl); Analyze (Decl); Set_Etype (Index, New_E); -- If the index is a range or a subtype indication it carries -- no entity. Example: -- package Pkg is -- type T is private; -- private -- type T is new Natural; -- Table : array (T(1) .. T(10)) of Boolean; -- end Pkg; -- Otherwise the type of the reference is its entity. if Is_Entity_Name (Index) then Set_Entity (Index, New_E); end if; end; end if; Make_Index (Index, P, Related_Id, Nb_Index); -- In the case where we have an unconstrained array with an index -- given by a subtype_indication, this is necessarily a "fixed lower -- bound" index. We change the upper bound of that index to the upper -- bound of the index's subtype (denoted by the subtype_mark), since -- that upper bound was originally set by the parser to be the same -- as the lower bound. In truth, that upper bound corresponds to -- a box ("<>"), and could be set to Empty, but it's convenient to -- set it to the upper bound to avoid needing to add special tests -- in various places for an Empty upper bound, and in any case that -- accurately characterizes the index's range of values. if Nkind (Def) = N_Unconstrained_Array_Definition and then Nkind (Index) = N_Subtype_Indication then declare Index_Subtype_High_Bound : constant Entity_Id := Type_High_Bound (Entity (Subtype_Mark (Index))); begin Set_High_Bound (Range_Expression (Constraint (Index)), Index_Subtype_High_Bound); -- Record that the array type has one or more indexes with -- a fixed lower bound. Has_FLB_Index := True; -- Mark the index as belonging to an array type with a fixed -- lower bound. Set_Is_Fixed_Lower_Bound_Index_Subtype (Etype (Index)); end; end if; -- Check error of subtype with predicate for index type Bad_Predicated_Subtype_Use ("subtype& has predicate, not allowed as index subtype", Index, Etype (Index)); -- Move to next index Next (Index); Nb_Index := Nb_Index + 1; end loop; -- Process subtype indication if one is present if Present (Component_Typ) then Element_Type := Process_Subtype (Component_Typ, P, Related_Id, 'C'); Set_Etype (Component_Typ, Element_Type); -- Ada 2005 (AI-230): Access Definition case else pragma Assert (Present (Access_Definition (Component_Def))); -- Indicate that the anonymous access type is created by the -- array type declaration. Element_Type := Access_Definition (Related_Nod => P, N => Access_Definition (Component_Def)); Set_Is_Local_Anonymous_Access (Element_Type); -- Propagate the parent. This field is needed if we have to generate -- the master_id associated with an anonymous access to task type -- component (see Expand_N_Full_Type_Declaration.Build_Master) Copy_Parent (To => Element_Type, From => T); -- Ada 2005 (AI-230): In case of components that are anonymous access -- types the level of accessibility depends on the enclosing type -- declaration Set_Scope (Element_Type, Current_Scope); -- Ada 2005 (AI-230) -- Ada 2005 (AI-254) declare CD : constant Node_Id := Access_To_Subprogram_Definition (Access_Definition (Component_Def)); begin if Present (CD) and then Protected_Present (CD) then Element_Type := Replace_Anonymous_Access_To_Protected_Subprogram (Def); end if; end; end if; -- Constrained array case if No (T) then -- We might be creating more than one itype with the same Related_Id, -- e.g. for an array object definition and its initial value. Give -- them unique suffixes, because GNATprove require distinct types to -- have different names. T := Create_Itype (E_Void, P, Related_Id, 'T', Suffix_Index => -1); end if; if Nkind (Def) = N_Constrained_Array_Definition then if Ekind (T) in Incomplete_Or_Private_Kind then Reinit_Field_To_Zero (T, F_Stored_Constraint); else pragma Assert (Ekind (T) = E_Void); end if; -- Establish Implicit_Base as unconstrained base type Implicit_Base := Create_Itype (E_Array_Type, P, Related_Id, 'B'); Set_Etype (Implicit_Base, Implicit_Base); Set_Scope (Implicit_Base, Current_Scope); Set_Has_Delayed_Freeze (Implicit_Base); Set_Default_SSO (Implicit_Base); -- The constrained array type is a subtype of the unconstrained one Mutate_Ekind (T, E_Array_Subtype); Reinit_Size_Align (T); Set_Etype (T, Implicit_Base); Set_Scope (T, Current_Scope); Set_Is_Constrained (T); Set_First_Index (T, First (Discrete_Subtype_Definitions (Def))); Set_Has_Delayed_Freeze (T); -- Complete setup of implicit base type pragma Assert (not Known_Component_Size (Implicit_Base)); Set_Component_Type (Implicit_Base, Element_Type); Set_Finalize_Storage_Only (Implicit_Base, Finalize_Storage_Only (Element_Type)); Set_First_Index (Implicit_Base, First_Index (T)); Set_Has_Controlled_Component (Implicit_Base, Has_Controlled_Component (Element_Type) or else Is_Controlled (Element_Type)); Set_Packed_Array_Impl_Type (Implicit_Base, Empty); Propagate_Concurrent_Flags (Implicit_Base, Element_Type); -- Unconstrained array case else pragma Assert (Nkind (Def) = N_Unconstrained_Array_Definition); if Ekind (T) in Incomplete_Or_Private_Kind then Reinit_Field_To_Zero (T, F_Stored_Constraint); else pragma Assert (Ekind (T) = E_Void); end if; Mutate_Ekind (T, E_Array_Type); Reinit_Size_Align (T); Set_Etype (T, T); Set_Scope (T, Current_Scope); pragma Assert (not Known_Component_Size (T)); Set_Is_Constrained (T, False); Set_Is_Fixed_Lower_Bound_Array_Subtype (T, Has_FLB_Index); Set_First_Index (T, First (Subtype_Marks (Def))); Set_Has_Delayed_Freeze (T, True); Propagate_Concurrent_Flags (T, Element_Type); Set_Has_Controlled_Component (T, Has_Controlled_Component (Element_Type) or else Is_Controlled (Element_Type)); Set_Finalize_Storage_Only (T, Finalize_Storage_Only (Element_Type)); Set_Default_SSO (T); end if; -- Common attributes for both cases Set_Component_Type (Base_Type (T), Element_Type); Set_Packed_Array_Impl_Type (T, Empty); if Aliased_Present (Component_Definition (Def)) then Set_Has_Aliased_Components (Etype (T)); -- AI12-001: All aliased objects are considered to be specified as -- independently addressable (RM C.6(8.1/4)). Set_Has_Independent_Components (Etype (T)); end if; -- Ada 2005 (AI-231): Propagate the null-excluding attribute to the -- array type to ensure that objects of this type are initialized. if Ada_Version >= Ada_2005 and then Can_Never_Be_Null (Element_Type) then Set_Can_Never_Be_Null (T); if Null_Exclusion_Present (Component_Definition (Def)) -- No need to check itypes because in their case this check was -- done at their point of creation and then not Is_Itype (Element_Type) then Error_Msg_N ("`NOT NULL` not allowed (null already excluded)", Subtype_Indication (Component_Definition (Def))); end if; end if; Priv := Private_Component (Element_Type); if Present (Priv) then -- Check for circular definitions if Priv = Any_Type then Set_Component_Type (Etype (T), Any_Type); -- There is a gap in the visibility of operations on the composite -- type only if the component type is defined in a different scope. elsif Scope (Priv) = Current_Scope then null; elsif Is_Limited_Type (Priv) then Set_Is_Limited_Composite (Etype (T)); Set_Is_Limited_Composite (T); else Set_Is_Private_Composite (Etype (T)); Set_Is_Private_Composite (T); end if; end if; -- A syntax error in the declaration itself may lead to an empty index -- list, in which case do a minimal patch. if No (First_Index (T)) then Error_Msg_N ("missing index definition in array type declaration", T); declare Indexes : constant List_Id := New_List (New_Occurrence_Of (Any_Id, Sloc (T))); begin Set_Discrete_Subtype_Definitions (Def, Indexes); Set_First_Index (T, First (Indexes)); return; end; end if; -- Create a concatenation operator for the new type. Internal array -- types created for packed entities do not need such, they are -- compatible with the user-defined type. if Number_Dimensions (T) = 1 and then not Is_Packed_Array_Impl_Type (T) then New_Concatenation_Op (T); end if; -- In the case of an unconstrained array the parser has already verified -- that all the indexes are unconstrained but we still need to make sure -- that the element type is constrained. if not Is_Definite_Subtype (Element_Type) then Error_Msg_N ("unconstrained element type in array declaration", Subtype_Indication (Component_Def)); elsif Is_Abstract_Type (Element_Type) then Error_Msg_N ("the type of a component cannot be abstract", Subtype_Indication (Component_Def)); end if; -- There may be an invariant declared for the component type, but -- the construction of the component invariant checking procedure -- takes place during expansion. end Array_Type_Declaration; ------------------------------------------------------ -- Replace_Anonymous_Access_To_Protected_Subprogram -- ------------------------------------------------------ function Replace_Anonymous_Access_To_Protected_Subprogram (N : Node_Id) return Entity_Id is Loc : constant Source_Ptr := Sloc (N); Curr_Scope : constant Scope_Stack_Entry := Scope_Stack.Table (Scope_Stack.Last); Anon : constant Entity_Id := Make_Temporary (Loc, 'S'); Acc : Node_Id; -- Access definition in declaration Comp : Node_Id; -- Object definition or formal definition with an access definition Decl : Node_Id; -- Declaration of anonymous access to subprogram type Spec : Node_Id; -- Original specification in access to subprogram P : Node_Id; begin Set_Is_Internal (Anon); case Nkind (N) is when N_Constrained_Array_Definition | N_Component_Declaration | N_Unconstrained_Array_Definition => Comp := Component_Definition (N); Acc := Access_Definition (Comp); when N_Discriminant_Specification => Comp := Discriminant_Type (N); Acc := Comp; when N_Parameter_Specification => Comp := Parameter_Type (N); Acc := Comp; when N_Access_Function_Definition => Comp := Result_Definition (N); Acc := Comp; when N_Object_Declaration => Comp := Object_Definition (N); Acc := Comp; when N_Function_Specification => Comp := Result_Definition (N); Acc := Comp; when others => raise Program_Error; end case; Spec := Access_To_Subprogram_Definition (Acc); Decl := Make_Full_Type_Declaration (Loc, Defining_Identifier => Anon, Type_Definition => Copy_Separate_Tree (Spec)); Mark_Rewrite_Insertion (Decl); -- Insert the new declaration in the nearest enclosing scope. If the -- parent is a body and N is its return type, the declaration belongs -- in the enclosing scope. Likewise if N is the type of a parameter. P := Parent (N); if Nkind (N) = N_Function_Specification and then Nkind (P) = N_Subprogram_Body then P := Parent (P); elsif Nkind (N) = N_Parameter_Specification and then Nkind (P) in N_Subprogram_Specification and then Nkind (Parent (P)) = N_Subprogram_Body then P := Parent (Parent (P)); end if; while Present (P) and then not Has_Declarations (P) loop P := Parent (P); end loop; pragma Assert (Present (P)); if Nkind (P) = N_Package_Specification then Prepend (Decl, Visible_Declarations (P)); else Prepend (Decl, Declarations (P)); end if; -- Replace the anonymous type with an occurrence of the new declaration. -- In all cases the rewritten node does not have the null-exclusion -- attribute because (if present) it was already inherited by the -- anonymous entity (Anon). Thus, in case of components we do not -- inherit this attribute. if Nkind (N) = N_Parameter_Specification then Rewrite (Comp, New_Occurrence_Of (Anon, Loc)); Set_Etype (Defining_Identifier (N), Anon); Set_Null_Exclusion_Present (N, False); elsif Nkind (N) = N_Object_Declaration then Rewrite (Comp, New_Occurrence_Of (Anon, Loc)); Set_Etype (Defining_Identifier (N), Anon); elsif Nkind (N) = N_Access_Function_Definition then Rewrite (Comp, New_Occurrence_Of (Anon, Loc)); elsif Nkind (N) = N_Function_Specification then Rewrite (Comp, New_Occurrence_Of (Anon, Loc)); Set_Etype (Defining_Unit_Name (N), Anon); else Rewrite (Comp, Make_Component_Definition (Loc, Subtype_Indication => New_Occurrence_Of (Anon, Loc))); end if; Mark_Rewrite_Insertion (Comp); if Nkind (N) in N_Object_Declaration | N_Access_Function_Definition or else (Nkind (Parent (N)) = N_Full_Type_Declaration and then not Is_Type (Current_Scope)) then -- Declaration can be analyzed in the current scope. Analyze (Decl); else -- Temporarily remove the current scope (record or subprogram) from -- the stack to add the new declarations to the enclosing scope. -- The anonymous entity is an Itype with the proper attributes. Scope_Stack.Decrement_Last; Analyze (Decl); Set_Is_Itype (Anon); Set_Associated_Node_For_Itype (Anon, N); Scope_Stack.Append (Curr_Scope); end if; Mutate_Ekind (Anon, E_Anonymous_Access_Protected_Subprogram_Type); Set_Can_Use_Internal_Rep (Anon, not Always_Compatible_Rep_On_Target); return Anon; end Replace_Anonymous_Access_To_Protected_Subprogram; ------------------------------------- -- Build_Access_Subprogram_Wrapper -- ------------------------------------- procedure Build_Access_Subprogram_Wrapper (Decl : Node_Id) is Loc : constant Source_Ptr := Sloc (Decl); Id : constant Entity_Id := Defining_Identifier (Decl); Type_Def : constant Node_Id := Type_Definition (Decl); Specs : constant List_Id := Parameter_Specifications (Type_Def); Profile : constant List_Id := New_List; Subp : constant Entity_Id := Make_Temporary (Loc, 'A'); Contracts : constant List_Id := New_List; Form_P : Node_Id; New_P : Node_Id; New_Decl : Node_Id; Spec : Node_Id; procedure Replace_Type_Name (Expr : Node_Id); -- In the expressions for contract aspects, replace occurrences of the -- access type with the name of the subprogram entity, as needed, e.g. -- for 'Result. Aspects that are not contracts, e.g. Size or Alignment) -- remain on the original access type declaration. What about expanded -- names denoting formals, whose prefix in source is the type name ??? ----------------------- -- Replace_Type_Name -- ----------------------- procedure Replace_Type_Name (Expr : Node_Id) is function Process (N : Node_Id) return Traverse_Result; function Process (N : Node_Id) return Traverse_Result is begin if Nkind (N) = N_Attribute_Reference and then Is_Entity_Name (Prefix (N)) and then Chars (Prefix (N)) = Chars (Id) then Set_Prefix (N, Make_Identifier (Sloc (N), Chars (Subp))); end if; return OK; end Process; procedure Traverse is new Traverse_Proc (Process); begin Traverse (Expr); end Replace_Type_Name; begin if Ekind (Id) in E_Access_Subprogram_Type | E_Access_Protected_Subprogram_Type | E_Anonymous_Access_Protected_Subprogram_Type | E_Anonymous_Access_Subprogram_Type then null; else Error_Msg_N ("illegal pre/postcondition on access type", Decl); return; end if; declare Asp : Node_Id; A_Id : Aspect_Id; Cond : Node_Id; Expr : Node_Id; begin Asp := First (Aspect_Specifications (Decl)); while Present (Asp) loop A_Id := Get_Aspect_Id (Chars (Identifier (Asp))); if A_Id = Aspect_Pre or else A_Id = Aspect_Post then Cond := Asp; Expr := Expression (Cond); Replace_Type_Name (Expr); Next (Asp); Remove (Cond); Append (Cond, Contracts); else Next (Asp); end if; end loop; end; -- If there are no contract aspects, no need for a wrapper. if Is_Empty_List (Contracts) then return; end if; Form_P := First (Specs); while Present (Form_P) loop New_P := New_Copy_Tree (Form_P); Set_Defining_Identifier (New_P, Make_Defining_Identifier (Loc, Chars (Defining_Identifier (Form_P)))); Append (New_P, Profile); Next (Form_P); end loop; -- Add to parameter specifications the access parameter that is passed -- in from an indirect call. Append ( Make_Parameter_Specification (Loc, Defining_Identifier => Make_Temporary (Loc, 'P'), Parameter_Type => New_Occurrence_Of (Id, Loc)), Profile); if Nkind (Type_Def) = N_Access_Procedure_Definition then Spec := Make_Procedure_Specification (Loc, Defining_Unit_Name => Subp, Parameter_Specifications => Profile); Mutate_Ekind (Subp, E_Procedure); else Spec := Make_Function_Specification (Loc, Defining_Unit_Name => Subp, Parameter_Specifications => Profile, Result_Definition => New_Copy_Tree (Result_Definition (Type_Definition (Decl)))); Mutate_Ekind (Subp, E_Function); end if; New_Decl := Make_Subprogram_Declaration (Loc, Specification => Spec); Set_Aspect_Specifications (New_Decl, Contracts); Set_Is_Wrapper (Subp); -- The wrapper is declared in the freezing actions to facilitate its -- identification and thus avoid handling it as a primitive operation -- of a tagged type (see Is_Access_To_Subprogram_Wrapper); otherwise it -- may be handled as a dispatching operation and erroneously registered -- in a dispatch table. if not GNATprove_Mode then Append_Freeze_Action (Id, New_Decl); -- Under GNATprove mode there is no such problem but we do not declare -- it in the freezing actions since they are not analyzed under this -- mode. else Insert_After (Decl, New_Decl); end if; Set_Access_Subprogram_Wrapper (Designated_Type (Id), Subp); Build_Access_Subprogram_Wrapper_Body (Decl, New_Decl); end Build_Access_Subprogram_Wrapper; ------------------------------- -- Build_Derived_Access_Type -- ------------------------------- procedure Build_Derived_Access_Type (N : Node_Id; Parent_Type : Entity_Id; Derived_Type : Entity_Id) is S : constant Node_Id := Subtype_Indication (Type_Definition (N)); Desig_Type : Entity_Id; Discr : Entity_Id; Discr_Con_Elist : Elist_Id; Discr_Con_El : Elmt_Id; Subt : Entity_Id; begin -- Set the designated type so it is available in case this is an access -- to a self-referential type, e.g. a standard list type with a next -- pointer. Will be reset after subtype is built. Set_Directly_Designated_Type (Derived_Type, Designated_Type (Parent_Type)); Subt := Process_Subtype (S, N); if Nkind (S) /= N_Subtype_Indication and then Subt /= Base_Type (Subt) then Mutate_Ekind (Derived_Type, E_Access_Subtype); end if; if Ekind (Derived_Type) = E_Access_Subtype then declare Pbase : constant Entity_Id := Base_Type (Parent_Type); Ibase : constant Entity_Id := Create_Itype (Ekind (Pbase), N, Derived_Type, 'B'); Svg_Chars : constant Name_Id := Chars (Ibase); Svg_Next_E : constant Entity_Id := Next_Entity (Ibase); Svg_Prev_E : constant Entity_Id := Prev_Entity (Ibase); begin Copy_Node (Pbase, Ibase); -- Restore Itype status after Copy_Node Set_Is_Itype (Ibase); Set_Associated_Node_For_Itype (Ibase, N); Set_Chars (Ibase, Svg_Chars); Set_Prev_Entity (Ibase, Svg_Prev_E); Set_Next_Entity (Ibase, Svg_Next_E); Set_Sloc (Ibase, Sloc (Derived_Type)); Set_Scope (Ibase, Scope (Derived_Type)); Set_Freeze_Node (Ibase, Empty); Set_Is_Frozen (Ibase, False); Set_Comes_From_Source (Ibase, False); Set_Is_First_Subtype (Ibase, False); Set_Etype (Ibase, Pbase); Set_Etype (Derived_Type, Ibase); end; end if; Set_Directly_Designated_Type (Derived_Type, Designated_Type (Subt)); Set_Is_Constrained (Derived_Type, Is_Constrained (Subt)); Set_Is_Access_Constant (Derived_Type, Is_Access_Constant (Parent_Type)); Set_Size_Info (Derived_Type, Parent_Type); Copy_RM_Size (To => Derived_Type, From => Parent_Type); Set_Depends_On_Private (Derived_Type, Has_Private_Component (Derived_Type)); Conditional_Delay (Derived_Type, Subt); if Is_Access_Subprogram_Type (Derived_Type) and then Is_Base_Type (Derived_Type) then Set_Can_Use_Internal_Rep (Derived_Type, Can_Use_Internal_Rep (Parent_Type)); end if; -- Ada 2005 (AI-231): Set the null-exclusion attribute, and verify -- that it is not redundant. if Null_Exclusion_Present (Type_Definition (N)) then Set_Can_Never_Be_Null (Derived_Type); elsif Can_Never_Be_Null (Parent_Type) then Set_Can_Never_Be_Null (Derived_Type); end if; -- Note: we do not copy the Storage_Size_Variable, since we always go to -- the root type for this information. -- Apply range checks to discriminants for derived record case -- ??? THIS CODE SHOULD NOT BE HERE REALLY. Desig_Type := Designated_Type (Derived_Type); if Is_Composite_Type (Desig_Type) and then (not Is_Array_Type (Desig_Type)) and then Has_Discriminants (Desig_Type) and then Base_Type (Desig_Type) /= Desig_Type then Discr_Con_Elist := Discriminant_Constraint (Desig_Type); Discr_Con_El := First_Elmt (Discr_Con_Elist); Discr := First_Discriminant (Base_Type (Desig_Type)); while Present (Discr_Con_El) loop Apply_Range_Check (Node (Discr_Con_El), Etype (Discr)); Next_Elmt (Discr_Con_El); Next_Discriminant (Discr); end loop; end if; end Build_Derived_Access_Type; ------------------------------ -- Build_Derived_Array_Type -- ------------------------------ procedure Build_Derived_Array_Type (N : Node_Id; Parent_Type : Entity_Id; Derived_Type : Entity_Id) is Loc : constant Source_Ptr := Sloc (N); Tdef : constant Node_Id := Type_Definition (N); Indic : constant Node_Id := Subtype_Indication (Tdef); Parent_Base : constant Entity_Id := Base_Type (Parent_Type); Implicit_Base : Entity_Id := Empty; New_Indic : Node_Id; procedure Make_Implicit_Base; -- If the parent subtype is constrained, the derived type is a subtype -- of an implicit base type derived from the parent base. ------------------------ -- Make_Implicit_Base -- ------------------------ procedure Make_Implicit_Base is begin Implicit_Base := Create_Itype (Ekind (Parent_Base), N, Derived_Type, 'B'); Mutate_Ekind (Implicit_Base, Ekind (Parent_Base)); Set_Etype (Implicit_Base, Parent_Base); Copy_Array_Subtype_Attributes (Implicit_Base, Parent_Base); Copy_Array_Base_Type_Attributes (Implicit_Base, Parent_Base); Set_Has_Delayed_Freeze (Implicit_Base, True); end Make_Implicit_Base; -- Start of processing for Build_Derived_Array_Type begin if not Is_Constrained (Parent_Type) then if Nkind (Indic) /= N_Subtype_Indication then Mutate_Ekind (Derived_Type, E_Array_Type); Copy_Array_Subtype_Attributes (Derived_Type, Parent_Type); Copy_Array_Base_Type_Attributes (Derived_Type, Parent_Type); Set_Has_Delayed_Freeze (Derived_Type, True); else Make_Implicit_Base; Set_Etype (Derived_Type, Implicit_Base); New_Indic := Make_Subtype_Declaration (Loc, Defining_Identifier => Derived_Type, Subtype_Indication => Make_Subtype_Indication (Loc, Subtype_Mark => New_Occurrence_Of (Implicit_Base, Loc), Constraint => Constraint (Indic))); Rewrite (N, New_Indic); Analyze (N); end if; else if Nkind (Indic) /= N_Subtype_Indication then Make_Implicit_Base; Mutate_Ekind (Derived_Type, Ekind (Parent_Type)); Set_Etype (Derived_Type, Implicit_Base); Copy_Array_Subtype_Attributes (Derived_Type, Parent_Type); else Error_Msg_N ("illegal constraint on constrained type", Indic); end if; end if; -- If parent type is not a derived type itself, and is declared in -- closed scope (e.g. a subprogram), then we must explicitly introduce -- the new type's concatenation operator since Derive_Subprograms -- will not inherit the parent's operator. If the parent type is -- unconstrained, the operator is of the unconstrained base type. if Number_Dimensions (Parent_Type) = 1 and then not Is_Limited_Type (Parent_Type) and then not Is_Derived_Type (Parent_Type) and then not Is_Package_Or_Generic_Package (Scope (Base_Type (Parent_Type))) then if not Is_Constrained (Parent_Type) and then Is_Constrained (Derived_Type) then New_Concatenation_Op (Implicit_Base); else New_Concatenation_Op (Derived_Type); end if; end if; end Build_Derived_Array_Type; ----------------------------------- -- Build_Derived_Concurrent_Type -- ----------------------------------- procedure Build_Derived_Concurrent_Type (N : Node_Id; Parent_Type : Entity_Id; Derived_Type : Entity_Id) is Loc : constant Source_Ptr := Sloc (N); Def : constant Node_Id := Type_Definition (N); Indic : constant Node_Id := Subtype_Indication (Def); Corr_Record : constant Entity_Id := Make_Temporary (Loc, 'C'); Corr_Decl : Node_Id := Empty; Corr_Decl_Needed : Boolean; -- If the derived type has fewer discriminants than its parent, the -- corresponding record is also a derived type, in order to account for -- the bound discriminants. We create a full type declaration for it in -- this case. Constraint_Present : constant Boolean := Nkind (Indic) = N_Subtype_Indication; D_Constraint : Node_Id; New_Constraint : Elist_Id := No_Elist; Old_Disc : Entity_Id; New_Disc : Entity_Id; New_N : Node_Id; begin Set_Stored_Constraint (Derived_Type, No_Elist); Corr_Decl_Needed := False; Old_Disc := Empty; if Present (Discriminant_Specifications (N)) and then Constraint_Present then Old_Disc := First_Discriminant (Parent_Type); New_Disc := First (Discriminant_Specifications (N)); while Present (New_Disc) and then Present (Old_Disc) loop Next_Discriminant (Old_Disc); Next (New_Disc); end loop; end if; if Present (Old_Disc) and then Expander_Active then -- The new type has fewer discriminants, so we need to create a new -- corresponding record, which is derived from the corresponding -- record of the parent, and has a stored constraint that captures -- the values of the discriminant constraints. The corresponding -- record is needed only if expander is active and code generation is -- enabled. -- The type declaration for the derived corresponding record has the -- same discriminant part and constraints as the current declaration. -- Copy the unanalyzed tree to build declaration. Corr_Decl_Needed := True; New_N := Copy_Separate_Tree (N); Corr_Decl := Make_Full_Type_Declaration (Loc, Defining_Identifier => Corr_Record, Discriminant_Specifications => Discriminant_Specifications (New_N), Type_Definition => Make_Derived_Type_Definition (Loc, Subtype_Indication => Make_Subtype_Indication (Loc, Subtype_Mark => New_Occurrence_Of (Corresponding_Record_Type (Parent_Type), Loc), Constraint => Constraint (Subtype_Indication (Type_Definition (New_N)))))); end if; -- Copy Storage_Size and Relative_Deadline variables if task case if Is_Task_Type (Parent_Type) then Set_Storage_Size_Variable (Derived_Type, Storage_Size_Variable (Parent_Type)); Set_Relative_Deadline_Variable (Derived_Type, Relative_Deadline_Variable (Parent_Type)); end if; if Present (Discriminant_Specifications (N)) then Push_Scope (Derived_Type); Check_Or_Process_Discriminants (N, Derived_Type); if Constraint_Present then New_Constraint := Expand_To_Stored_Constraint (Parent_Type, Build_Discriminant_Constraints (Parent_Type, Indic, True)); end if; End_Scope; elsif Constraint_Present then -- Build an unconstrained derived type and rewrite the derived type -- as a subtype of this new base type. declare Parent_Base : constant Entity_Id := Base_Type (Parent_Type); New_Base : Entity_Id; New_Decl : Node_Id; New_Indic : Node_Id; begin New_Base := Create_Itype (Ekind (Derived_Type), N, Derived_Type, 'B'); New_Decl := Make_Full_Type_Declaration (Loc, Defining_Identifier => New_Base, Type_Definition => Make_Derived_Type_Definition (Loc, Abstract_Present => Abstract_Present (Def), Limited_Present => Limited_Present (Def), Subtype_Indication => New_Occurrence_Of (Parent_Base, Loc))); Mark_Rewrite_Insertion (New_Decl); Insert_Before (N, New_Decl); Analyze (New_Decl); New_Indic := Make_Subtype_Indication (Loc, Subtype_Mark => New_Occurrence_Of (New_Base, Loc), Constraint => Relocate_Node (Constraint (Indic))); Rewrite (N, Make_Subtype_Declaration (Loc, Defining_Identifier => Derived_Type, Subtype_Indication => New_Indic)); Analyze (N); return; end; end if; -- By default, operations and private data are inherited from parent. -- However, in the presence of bound discriminants, a new corresponding -- record will be created, see below. Set_Has_Discriminants (Derived_Type, Has_Discriminants (Parent_Type)); Set_Corresponding_Record_Type (Derived_Type, Corresponding_Record_Type (Parent_Type)); -- Is_Constrained is set according the parent subtype, but is set to -- False if the derived type is declared with new discriminants. Set_Is_Constrained (Derived_Type, (Is_Constrained (Parent_Type) or else Constraint_Present) and then not Present (Discriminant_Specifications (N))); if Constraint_Present then if not Has_Discriminants (Parent_Type) then Error_Msg_N ("untagged parent must have discriminants", N); elsif Present (Discriminant_Specifications (N)) then -- Verify that new discriminants are used to constrain old ones D_Constraint := First (Constraints (Constraint (Indic))); Old_Disc := First_Discriminant (Parent_Type); while Present (D_Constraint) loop if Nkind (D_Constraint) /= N_Discriminant_Association then -- Positional constraint. If it is a reference to a new -- discriminant, it constrains the corresponding old one. if Nkind (D_Constraint) = N_Identifier then New_Disc := First_Discriminant (Derived_Type); while Present (New_Disc) loop exit when Chars (New_Disc) = Chars (D_Constraint); Next_Discriminant (New_Disc); end loop; if Present (New_Disc) then Set_Corresponding_Discriminant (New_Disc, Old_Disc); end if; end if; Next_Discriminant (Old_Disc); -- if this is a named constraint, search by name for the old -- discriminants constrained by the new one. elsif Nkind (Expression (D_Constraint)) = N_Identifier then -- Find new discriminant with that name New_Disc := First_Discriminant (Derived_Type); while Present (New_Disc) loop exit when Chars (New_Disc) = Chars (Expression (D_Constraint)); Next_Discriminant (New_Disc); end loop; if Present (New_Disc) then -- Verify that new discriminant renames some discriminant -- of the parent type, and associate the new discriminant -- with one or more old ones that it renames. declare Selector : Node_Id; begin Selector := First (Selector_Names (D_Constraint)); while Present (Selector) loop Old_Disc := First_Discriminant (Parent_Type); while Present (Old_Disc) loop exit when Chars (Old_Disc) = Chars (Selector); Next_Discriminant (Old_Disc); end loop; if Present (Old_Disc) then Set_Corresponding_Discriminant (New_Disc, Old_Disc); end if; Next (Selector); end loop; end; end if; end if; Next (D_Constraint); end loop; New_Disc := First_Discriminant (Derived_Type); while Present (New_Disc) loop if No (Corresponding_Discriminant (New_Disc)) then Error_Msg_NE ("new discriminant& must constrain old one", N, New_Disc); -- If a new discriminant is used in the constraint, then its -- subtype must be statically compatible with the subtype of -- the parent discriminant (RM 3.7(15)). else Check_Constraining_Discriminant (New_Disc, Corresponding_Discriminant (New_Disc)); end if; Next_Discriminant (New_Disc); end loop; end if; elsif Present (Discriminant_Specifications (N)) then Error_Msg_N ("missing discriminant constraint in untagged derivation", N); end if; -- The entity chain of the derived type includes the new discriminants -- but shares operations with the parent. if Present (Discriminant_Specifications (N)) then Old_Disc := First_Discriminant (Parent_Type); while Present (Old_Disc) loop if No (Next_Entity (Old_Disc)) or else Ekind (Next_Entity (Old_Disc)) /= E_Discriminant then Link_Entities (Last_Entity (Derived_Type), Next_Entity (Old_Disc)); exit; end if; Next_Discriminant (Old_Disc); end loop; else Set_First_Entity (Derived_Type, First_Entity (Parent_Type)); if Has_Discriminants (Parent_Type) then Set_Is_Constrained (Derived_Type, Is_Constrained (Parent_Type)); Set_Discriminant_Constraint ( Derived_Type, Discriminant_Constraint (Parent_Type)); end if; end if; Set_Last_Entity (Derived_Type, Last_Entity (Parent_Type)); Set_Has_Completion (Derived_Type); if Corr_Decl_Needed then Set_Stored_Constraint (Derived_Type, New_Constraint); Insert_After (N, Corr_Decl); Analyze (Corr_Decl); Set_Corresponding_Record_Type (Derived_Type, Corr_Record); end if; end Build_Derived_Concurrent_Type; ------------------------------------ -- Build_Derived_Enumeration_Type -- ------------------------------------ procedure Build_Derived_Enumeration_Type (N : Node_Id; Parent_Type : Entity_Id; Derived_Type : Entity_Id) is function Bound_Belongs_To_Type (B : Node_Id) return Boolean; -- When the type declaration includes a constraint, we generate -- a subtype declaration of an anonymous base type, with the constraint -- given in the original type declaration. Conceptually, the bounds -- are converted to the new base type, and this conversion freezes -- (prematurely) that base type, when the bounds are simply literals. -- As a result, a representation clause for the derived type is then -- rejected or ignored. This procedure recognizes the simple case of -- literal bounds, which allows us to indicate that the conversions -- are not freeze points, and the subsequent representation clause -- can be accepted. -- A similar approach might be used to resolve the long-standing -- problem of premature freezing of derived numeric types ??? function Bound_Belongs_To_Type (B : Node_Id) return Boolean is begin return Nkind (B) = N_Type_Conversion and then Is_Entity_Name (Expression (B)) and then Ekind (Entity (Expression (B))) = E_Enumeration_Literal; end Bound_Belongs_To_Type; Loc : constant Source_Ptr := Sloc (N); Def : constant Node_Id := Type_Definition (N); Indic : constant Node_Id := Subtype_Indication (Def); Implicit_Base : Entity_Id; Literal : Entity_Id; New_Lit : Entity_Id; Literals_List : List_Id; Type_Decl : Node_Id; Hi, Lo : Node_Id; Rang_Expr : Node_Id; begin -- Since types Standard.Character and Standard.[Wide_]Wide_Character do -- not have explicit literals lists we need to process types derived -- from them specially. This is handled by Derived_Standard_Character. -- If the parent type is a generic type, there are no literals either, -- and we construct the same skeletal representation as for the generic -- parent type. if Is_Standard_Character_Type (Parent_Type) then Derived_Standard_Character (N, Parent_Type, Derived_Type); elsif Is_Generic_Type (Root_Type (Parent_Type)) then declare Lo : Node_Id; Hi : Node_Id; begin if Nkind (Indic) /= N_Subtype_Indication then Lo := Make_Attribute_Reference (Loc, Attribute_Name => Name_First, Prefix => New_Occurrence_Of (Derived_Type, Loc)); Set_Etype (Lo, Derived_Type); Hi := Make_Attribute_Reference (Loc, Attribute_Name => Name_Last, Prefix => New_Occurrence_Of (Derived_Type, Loc)); Set_Etype (Hi, Derived_Type); Set_Scalar_Range (Derived_Type, Make_Range (Loc, Low_Bound => Lo, High_Bound => Hi)); else -- Analyze subtype indication and verify compatibility -- with parent type. if Base_Type (Process_Subtype (Indic, N)) /= Base_Type (Parent_Type) then Error_Msg_N ("illegal constraint for formal discrete type", N); end if; end if; end; else -- If a constraint is present, analyze the bounds to catch -- premature usage of the derived literals. if Nkind (Indic) = N_Subtype_Indication and then Nkind (Range_Expression (Constraint (Indic))) = N_Range then Analyze (Low_Bound (Range_Expression (Constraint (Indic)))); Analyze (High_Bound (Range_Expression (Constraint (Indic)))); end if; -- Introduce an implicit base type for the derived type even if there -- is no constraint attached to it, since this seems closer to the -- Ada semantics. Build a full type declaration tree for the derived -- type using the implicit base type as the defining identifier. Then -- build a subtype declaration tree which applies the constraint (if -- any) have it replace the derived type declaration. Literal := First_Literal (Parent_Type); Literals_List := New_List; while Present (Literal) and then Ekind (Literal) = E_Enumeration_Literal loop -- Literals of the derived type have the same representation as -- those of the parent type, but this representation can be -- overridden by an explicit representation clause. Indicate -- that there is no explicit representation given yet. These -- derived literals are implicit operations of the new type, -- and can be overridden by explicit ones. if Nkind (Literal) = N_Defining_Character_Literal then New_Lit := Make_Defining_Character_Literal (Loc, Chars (Literal)); else New_Lit := Make_Defining_Identifier (Loc, Chars (Literal)); end if; Mutate_Ekind (New_Lit, E_Enumeration_Literal); Set_Enumeration_Pos (New_Lit, Enumeration_Pos (Literal)); Set_Enumeration_Rep (New_Lit, Enumeration_Rep (Literal)); Set_Enumeration_Rep_Expr (New_Lit, Empty); Set_Alias (New_Lit, Literal); Set_Is_Known_Valid (New_Lit, True); Append (New_Lit, Literals_List); Next_Literal (Literal); end loop; Implicit_Base := Make_Defining_Identifier (Sloc (Derived_Type), Chars => New_External_Name (Chars (Derived_Type), 'B')); -- Indicate the proper nature of the derived type. This must be done -- before analysis of the literals, to recognize cases when a literal -- may be hidden by a previous explicit function definition (cf. -- c83031a). Mutate_Ekind (Derived_Type, E_Enumeration_Subtype); Set_Etype (Derived_Type, Implicit_Base); Type_Decl := Make_Full_Type_Declaration (Loc, Defining_Identifier => Implicit_Base, Discriminant_Specifications => No_List, Type_Definition => Make_Enumeration_Type_Definition (Loc, Literals_List)); Mark_Rewrite_Insertion (Type_Decl); Insert_Before (N, Type_Decl); Analyze (Type_Decl); -- The anonymous base now has a full declaration, but this base -- is not a first subtype. Set_Is_First_Subtype (Implicit_Base, False); -- After the implicit base is analyzed its Etype needs to be changed -- to reflect the fact that it is derived from the parent type which -- was ignored during analysis. We also set the size at this point. Set_Etype (Implicit_Base, Parent_Type); Set_Size_Info (Implicit_Base, Parent_Type); Set_RM_Size (Implicit_Base, RM_Size (Parent_Type)); Set_First_Rep_Item (Implicit_Base, First_Rep_Item (Parent_Type)); -- Copy other flags from parent type Set_Has_Non_Standard_Rep (Implicit_Base, Has_Non_Standard_Rep (Parent_Type)); Set_Has_Pragma_Ordered (Implicit_Base, Has_Pragma_Ordered (Parent_Type)); Set_Has_Delayed_Freeze (Implicit_Base); -- Process the subtype indication including a validation check on the -- constraint, if any. If a constraint is given, its bounds must be -- implicitly converted to the new type. if Nkind (Indic) = N_Subtype_Indication then declare R : constant Node_Id := Range_Expression (Constraint (Indic)); begin if Nkind (R) = N_Range then Hi := Build_Scalar_Bound (High_Bound (R), Parent_Type, Implicit_Base); Lo := Build_Scalar_Bound (Low_Bound (R), Parent_Type, Implicit_Base); else -- Constraint is a Range attribute. Replace with explicit -- mention of the bounds of the prefix, which must be a -- subtype. Analyze (Prefix (R)); Hi := Convert_To (Implicit_Base, Make_Attribute_Reference (Loc, Attribute_Name => Name_Last, Prefix => New_Occurrence_Of (Entity (Prefix (R)), Loc))); Lo := Convert_To (Implicit_Base, Make_Attribute_Reference (Loc, Attribute_Name => Name_First, Prefix => New_Occurrence_Of (Entity (Prefix (R)), Loc))); end if; end; else Hi := Build_Scalar_Bound (Type_High_Bound (Parent_Type), Parent_Type, Implicit_Base); Lo := Build_Scalar_Bound (Type_Low_Bound (Parent_Type), Parent_Type, Implicit_Base); end if; Rang_Expr := Make_Range (Loc, Low_Bound => Lo, High_Bound => Hi); -- If we constructed a default range for the case where no range -- was given, then the expressions in the range must not freeze -- since they do not correspond to expressions in the source. -- However, if the type inherits predicates the expressions will -- be elaborated earlier and must freeze. if (Nkind (Indic) /= N_Subtype_Indication or else (Bound_Belongs_To_Type (Lo) and then Bound_Belongs_To_Type (Hi))) and then not Has_Predicates (Derived_Type) then Set_Must_Not_Freeze (Lo); Set_Must_Not_Freeze (Hi); Set_Must_Not_Freeze (Rang_Expr); end if; Rewrite (N, Make_Subtype_Declaration (Loc, Defining_Identifier => Derived_Type, Subtype_Indication => Make_Subtype_Indication (Loc, Subtype_Mark => New_Occurrence_Of (Implicit_Base, Loc), Constraint => Make_Range_Constraint (Loc, Range_Expression => Rang_Expr)))); Analyze (N); -- Propagate the aspects from the original type declaration to the -- declaration of the implicit base. Move_Aspects (From => Original_Node (N), To => Type_Decl); -- Apply a range check. Since this range expression doesn't have an -- Etype, we have to specifically pass the Source_Typ parameter. Is -- this right??? if Nkind (Indic) = N_Subtype_Indication then Apply_Range_Check (Range_Expression (Constraint (Indic)), Parent_Type, Source_Typ => Entity (Subtype_Mark (Indic))); end if; end if; end Build_Derived_Enumeration_Type; -------------------------------- -- Build_Derived_Numeric_Type -- -------------------------------- procedure Build_Derived_Numeric_Type (N : Node_Id; Parent_Type : Entity_Id; Derived_Type : Entity_Id) is Loc : constant Source_Ptr := Sloc (N); Tdef : constant Node_Id := Type_Definition (N); Indic : constant Node_Id := Subtype_Indication (Tdef); Parent_Base : constant Entity_Id := Base_Type (Parent_Type); No_Constraint : constant Boolean := Nkind (Indic) /= N_Subtype_Indication; Implicit_Base : Entity_Id; Lo : Node_Id; Hi : Node_Id; begin -- Process the subtype indication including a validation check on -- the constraint if any. Discard_Node (Process_Subtype (Indic, N)); -- Introduce an implicit base type for the derived type even if there -- is no constraint attached to it, since this seems closer to the Ada -- semantics. Implicit_Base := Create_Itype (Ekind (Parent_Base), N, Derived_Type, 'B'); Set_Etype (Implicit_Base, Parent_Base); Mutate_Ekind (Implicit_Base, Ekind (Parent_Base)); Set_Size_Info (Implicit_Base, Parent_Base); Set_First_Rep_Item (Implicit_Base, First_Rep_Item (Parent_Base)); Set_Parent (Implicit_Base, Parent (Derived_Type)); Set_Is_Known_Valid (Implicit_Base, Is_Known_Valid (Parent_Base)); Set_Is_Volatile (Implicit_Base, Is_Volatile (Parent_Base)); -- Set RM Size for discrete type or decimal fixed-point type -- Ordinary fixed-point is excluded, why??? if Is_Discrete_Type (Parent_Base) or else Is_Decimal_Fixed_Point_Type (Parent_Base) then Set_RM_Size (Implicit_Base, RM_Size (Parent_Base)); end if; Set_Has_Delayed_Freeze (Implicit_Base); Lo := New_Copy_Tree (Type_Low_Bound (Parent_Base)); Hi := New_Copy_Tree (Type_High_Bound (Parent_Base)); Set_Scalar_Range (Implicit_Base, Make_Range (Loc, Low_Bound => Lo, High_Bound => Hi)); if Has_Infinities (Parent_Base) then Set_Includes_Infinities (Scalar_Range (Implicit_Base)); end if; -- The Derived_Type, which is the entity of the declaration, is a -- subtype of the implicit base. Its Ekind is a subtype, even in the -- absence of an explicit constraint. Set_Etype (Derived_Type, Implicit_Base); -- If we did not have a constraint, then the Ekind is set from the -- parent type (otherwise Process_Subtype has set the bounds) if No_Constraint then Mutate_Ekind (Derived_Type, Subtype_Kind (Ekind (Parent_Type))); end if; -- If we did not have a range constraint, then set the range from the -- parent type. Otherwise, the Process_Subtype call has set the bounds. if No_Constraint or else not Has_Range_Constraint (Indic) then Set_Scalar_Range (Derived_Type, Make_Range (Loc, Low_Bound => New_Copy_Tree (Type_Low_Bound (Parent_Type)), High_Bound => New_Copy_Tree (Type_High_Bound (Parent_Type)))); Set_Is_Constrained (Derived_Type, Is_Constrained (Parent_Type)); if Has_Infinities (Parent_Type) then Set_Includes_Infinities (Scalar_Range (Derived_Type)); end if; Set_Is_Known_Valid (Derived_Type, Is_Known_Valid (Parent_Type)); end if; Set_Is_Descendant_Of_Address (Derived_Type, Is_Descendant_Of_Address (Parent_Type)); Set_Is_Descendant_Of_Address (Implicit_Base, Is_Descendant_Of_Address (Parent_Type)); -- Set remaining type-specific fields, depending on numeric type if Is_Modular_Integer_Type (Parent_Type) then Set_Modulus (Implicit_Base, Modulus (Parent_Base)); Set_Non_Binary_Modulus (Implicit_Base, Non_Binary_Modulus (Parent_Base)); Set_Is_Known_Valid (Implicit_Base, Is_Known_Valid (Parent_Base)); elsif Is_Floating_Point_Type (Parent_Type) then -- Digits of base type is always copied from the digits value of -- the parent base type, but the digits of the derived type will -- already have been set if there was a constraint present. Set_Digits_Value (Implicit_Base, Digits_Value (Parent_Base)); Set_Float_Rep (Implicit_Base, Float_Rep (Parent_Base)); if No_Constraint then Set_Digits_Value (Derived_Type, Digits_Value (Parent_Type)); end if; elsif Is_Fixed_Point_Type (Parent_Type) then -- Small of base type and derived type are always copied from the -- parent base type, since smalls never change. The delta of the -- base type is also copied from the parent base type. However the -- delta of the derived type will have been set already if a -- constraint was present. Set_Small_Value (Derived_Type, Small_Value (Parent_Base)); Set_Small_Value (Implicit_Base, Small_Value (Parent_Base)); Set_Delta_Value (Implicit_Base, Delta_Value (Parent_Base)); if No_Constraint then Set_Delta_Value (Derived_Type, Delta_Value (Parent_Type)); end if; -- The scale and machine radix in the decimal case are always -- copied from the parent base type. if Is_Decimal_Fixed_Point_Type (Parent_Type) then Set_Scale_Value (Derived_Type, Scale_Value (Parent_Base)); Set_Scale_Value (Implicit_Base, Scale_Value (Parent_Base)); Set_Machine_Radix_10 (Derived_Type, Machine_Radix_10 (Parent_Base)); Set_Machine_Radix_10 (Implicit_Base, Machine_Radix_10 (Parent_Base)); Set_Digits_Value (Implicit_Base, Digits_Value (Parent_Base)); if No_Constraint then Set_Digits_Value (Derived_Type, Digits_Value (Parent_Base)); else -- the analysis of the subtype_indication sets the -- digits value of the derived type. null; end if; end if; end if; if Is_Integer_Type (Parent_Type) then Set_Has_Shift_Operator (Implicit_Base, Has_Shift_Operator (Parent_Type)); end if; -- The type of the bounds is that of the parent type, and they -- must be converted to the derived type. Convert_Scalar_Bounds (N, Parent_Type, Derived_Type, Loc); -- The implicit_base should be frozen when the derived type is frozen, -- but note that it is used in the conversions of the bounds. For fixed -- types we delay the determination of the bounds until the proper -- freezing point. For other numeric types this is rejected by GCC, for -- reasons that are currently unclear (???), so we choose to freeze the -- implicit base now. In the case of integers and floating point types -- this is harmless because subsequent representation clauses cannot -- affect anything, but it is still baffling that we cannot use the -- same mechanism for all derived numeric types. -- There is a further complication: actually some representation -- clauses can affect the implicit base type. For example, attribute -- definition clauses for stream-oriented attributes need to set the -- corresponding TSS entries on the base type, and this normally -- cannot be done after the base type is frozen, so the circuitry in -- Sem_Ch13.New_Stream_Subprogram must account for this possibility -- and not use Set_TSS in this case. -- There are also consequences for the case of delayed representation -- aspects for some cases. For example, a Size aspect is delayed and -- should not be evaluated to the freeze point. This early freezing -- means that the size attribute evaluation happens too early??? if Is_Fixed_Point_Type (Parent_Type) then Conditional_Delay (Implicit_Base, Parent_Type); else Freeze_Before (N, Implicit_Base); end if; end Build_Derived_Numeric_Type; -------------------------------- -- Build_Derived_Private_Type -- -------------------------------- procedure Build_Derived_Private_Type (N : Node_Id; Parent_Type : Entity_Id; Derived_Type : Entity_Id; Is_Completion : Boolean; Derive_Subps : Boolean := True) is Loc : constant Source_Ptr := Sloc (N); Par_Base : constant Entity_Id := Base_Type (Parent_Type); Par_Scope : constant Entity_Id := Scope (Par_Base); Full_N : constant Node_Id := New_Copy_Tree (N); Full_Der : Entity_Id := New_Copy (Derived_Type); Full_P : Entity_Id; function Available_Full_View (Typ : Entity_Id) return Entity_Id; -- Return the Full_View or Underlying_Full_View of Typ, whichever is -- present (they cannot be both present for the same type), or Empty. procedure Build_Full_Derivation; -- Build full derivation, i.e. derive from the full view procedure Copy_And_Build; -- Copy derived type declaration, replace parent with its full view, -- and build derivation ------------------------- -- Available_Full_View -- ------------------------- function Available_Full_View (Typ : Entity_Id) return Entity_Id is begin if Present (Full_View (Typ)) then return Full_View (Typ); elsif Present (Underlying_Full_View (Typ)) then -- We should be called on a type with an underlying full view -- only by means of the recursive call made in Copy_And_Build -- through the first call to Build_Derived_Type, or else if -- the parent scope is being analyzed because we are deriving -- a completion. pragma Assert (Is_Completion or else In_Private_Part (Par_Scope)); return Underlying_Full_View (Typ); else return Empty; end if; end Available_Full_View; --------------------------- -- Build_Full_Derivation -- --------------------------- procedure Build_Full_Derivation is begin -- If parent scope is not open, install the declarations if not In_Open_Scopes (Par_Scope) then Install_Private_Declarations (Par_Scope); Install_Visible_Declarations (Par_Scope); Copy_And_Build; Uninstall_Declarations (Par_Scope); -- If parent scope is open and in another unit, and parent has a -- completion, then the derivation is taking place in the visible -- part of a child unit. In that case retrieve the full view of -- the parent momentarily. elsif not In_Same_Source_Unit (N, Parent_Type) and then Present (Full_View (Parent_Type)) then Full_P := Full_View (Parent_Type); Exchange_Declarations (Parent_Type); Copy_And_Build; Exchange_Declarations (Full_P); -- Otherwise it is a local derivation else Copy_And_Build; end if; end Build_Full_Derivation; -------------------- -- Copy_And_Build -- -------------------- procedure Copy_And_Build is Full_Parent : Entity_Id := Parent_Type; begin -- If the parent is itself derived from another private type, -- installing the private declarations has not affected its -- privacy status, so use its own full view explicitly. if Is_Private_Type (Full_Parent) and then Present (Full_View (Full_Parent)) then Full_Parent := Full_View (Full_Parent); end if; -- If the full view is itself derived from another private type -- and has got an underlying full view, and this is done for a -- completion, i.e. to build the underlying full view of the type, -- then use this underlying full view. We cannot do that if this -- is not a completion, i.e. to build the full view of the type, -- because this would break the privacy of the parent type, except -- if the parent scope is being analyzed because we are deriving a -- completion. if Is_Private_Type (Full_Parent) and then Present (Underlying_Full_View (Full_Parent)) and then (Is_Completion or else In_Private_Part (Par_Scope)) then Full_Parent := Underlying_Full_View (Full_Parent); end if; -- For private, record, concurrent, access and almost all enumeration -- types, the derivation from the full view requires a fully-fledged -- declaration. In the other cases, just use an itype. if Is_Private_Type (Full_Parent) or else Is_Record_Type (Full_Parent) or else Is_Concurrent_Type (Full_Parent) or else Is_Access_Type (Full_Parent) or else (Is_Enumeration_Type (Full_Parent) and then not Is_Standard_Character_Type (Full_Parent) and then not Is_Generic_Type (Root_Type (Full_Parent))) then -- Copy and adjust declaration to provide a completion for what -- is originally a private declaration. Indicate that full view -- is internally generated. Set_Comes_From_Source (Full_N, False); Set_Comes_From_Source (Full_Der, False); Set_Parent (Full_Der, Full_N); Set_Defining_Identifier (Full_N, Full_Der); -- If there are no constraints, adjust the subtype mark if Nkind (Subtype_Indication (Type_Definition (Full_N))) /= N_Subtype_Indication then Set_Subtype_Indication (Type_Definition (Full_N), New_Occurrence_Of (Full_Parent, Sloc (Full_N))); end if; Insert_After (N, Full_N); -- Build full view of derived type from full view of parent which -- is now installed. Subprograms have been derived on the partial -- view, the completion does not derive them anew. if Is_Record_Type (Full_Parent) then -- If parent type is tagged, the completion inherits the proper -- primitive operations. if Is_Tagged_Type (Parent_Type) then Build_Derived_Record_Type (Full_N, Full_Parent, Full_Der, Derive_Subps); else Build_Derived_Record_Type (Full_N, Full_Parent, Full_Der, Derive_Subps => False); end if; else -- If the parent type is private, this is not a completion and -- we build the full derivation recursively as a completion. Build_Derived_Type (Full_N, Full_Parent, Full_Der, Is_Completion => Is_Private_Type (Full_Parent), Derive_Subps => False); end if; -- The full declaration has been introduced into the tree and -- processed in the step above. It should not be analyzed again -- (when encountered later in the current list of declarations) -- to prevent spurious name conflicts. The full entity remains -- invisible. Set_Analyzed (Full_N); else Full_Der := Make_Defining_Identifier (Sloc (Derived_Type), Chars => Chars (Derived_Type)); Set_Is_Itype (Full_Der); Set_Associated_Node_For_Itype (Full_Der, N); Set_Parent (Full_Der, N); Build_Derived_Type (N, Full_Parent, Full_Der, Is_Completion => False, Derive_Subps => False); end if; Set_Has_Private_Declaration (Full_Der); Set_Has_Private_Declaration (Derived_Type); Set_Scope (Full_Der, Scope (Derived_Type)); Set_Is_First_Subtype (Full_Der, Is_First_Subtype (Derived_Type)); Set_Has_Size_Clause (Full_Der, False); Set_Has_Alignment_Clause (Full_Der, False); Set_Has_Delayed_Freeze (Full_Der); Set_Is_Frozen (Full_Der, False); Set_Freeze_Node (Full_Der, Empty); Set_Depends_On_Private (Full_Der, Has_Private_Component (Full_Der)); Set_Is_Public (Full_Der, Is_Public (Derived_Type)); -- The convention on the base type may be set in the private part -- and not propagated to the subtype until later, so we obtain the -- convention from the base type of the parent. Set_Convention (Full_Der, Convention (Base_Type (Full_Parent))); end Copy_And_Build; -- Start of processing for Build_Derived_Private_Type begin if Is_Tagged_Type (Parent_Type) then Full_P := Full_View (Parent_Type); -- A type extension of a type with unknown discriminants is an -- indefinite type that the back-end cannot handle directly. -- We treat it as a private type, and build a completion that is -- derived from the full view of the parent, and hopefully has -- known discriminants. -- If the full view of the parent type has an underlying record view, -- use it to generate the underlying record view of this derived type -- (required for chains of derivations with unknown discriminants). -- Minor optimization: we avoid the generation of useless underlying -- record view entities if the private type declaration has unknown -- discriminants but its corresponding full view has no -- discriminants. if Has_Unknown_Discriminants (Parent_Type) and then Present (Full_P) and then (Has_Discriminants (Full_P) or else Present (Underlying_Record_View (Full_P))) and then not In_Open_Scopes (Par_Scope) and then Expander_Active then declare Full_Der : constant Entity_Id := Make_Temporary (Loc, 'T'); New_Ext : constant Node_Id := Copy_Separate_Tree (Record_Extension_Part (Type_Definition (N))); Decl : Node_Id; begin Build_Derived_Record_Type (N, Parent_Type, Derived_Type, Derive_Subps); -- Build anonymous completion, as a derivation from the full -- view of the parent. This is not a completion in the usual -- sense, because the current type is not private. Decl := Make_Full_Type_Declaration (Loc, Defining_Identifier => Full_Der, Type_Definition => Make_Derived_Type_Definition (Loc, Subtype_Indication => New_Copy_Tree (Subtype_Indication (Type_Definition (N))), Record_Extension_Part => New_Ext)); -- If the parent type has an underlying record view, use it -- here to build the new underlying record view. if Present (Underlying_Record_View (Full_P)) then pragma Assert (Nkind (Subtype_Indication (Type_Definition (Decl))) = N_Identifier); Set_Entity (Subtype_Indication (Type_Definition (Decl)), Underlying_Record_View (Full_P)); end if; Install_Private_Declarations (Par_Scope); Install_Visible_Declarations (Par_Scope); Insert_Before (N, Decl); -- Mark entity as an underlying record view before analysis, -- to avoid generating the list of its primitive operations -- (which is not really required for this entity) and thus -- prevent spurious errors associated with missing overriding -- of abstract primitives (overridden only for Derived_Type). Mutate_Ekind (Full_Der, E_Record_Type); Set_Is_Underlying_Record_View (Full_Der); Set_Default_SSO (Full_Der); Set_No_Reordering (Full_Der, No_Component_Reordering); Analyze (Decl); pragma Assert (Has_Discriminants (Full_Der) and then not Has_Unknown_Discriminants (Full_Der)); Uninstall_Declarations (Par_Scope); -- Freeze the underlying record view, to prevent generation of -- useless dispatching information, which is simply shared with -- the real derived type. Set_Is_Frozen (Full_Der); -- If the derived type has access discriminants, create -- references to their anonymous types now, to prevent -- back-end problems when their first use is in generated -- bodies of primitives. declare E : Entity_Id; begin E := First_Entity (Full_Der); while Present (E) loop if Ekind (E) = E_Discriminant and then Ekind (Etype (E)) = E_Anonymous_Access_Type then Build_Itype_Reference (Etype (E), Decl); end if; Next_Entity (E); end loop; end; -- Set up links between real entity and underlying record view Set_Underlying_Record_View (Derived_Type, Base_Type (Full_Der)); Set_Underlying_Record_View (Base_Type (Full_Der), Derived_Type); end; -- If discriminants are known, build derived record else Build_Derived_Record_Type (N, Parent_Type, Derived_Type, Derive_Subps); end if; return; elsif Has_Discriminants (Parent_Type) then -- Build partial view of derived type from partial view of parent. -- This must be done before building the full derivation because the -- second derivation will modify the discriminants of the first and -- the discriminants are chained with the rest of the components in -- the full derivation. Build_Derived_Record_Type (N, Parent_Type, Derived_Type, Derive_Subps); -- Build the full derivation if this is not the anonymous derived -- base type created by Build_Derived_Record_Type in the constrained -- case (see point 5. of its head comment) since we build it for the -- derived subtype. if Present (Available_Full_View (Parent_Type)) and then not Is_Itype (Derived_Type) then declare Der_Base : constant Entity_Id := Base_Type (Derived_Type); Discr : Entity_Id; Last_Discr : Entity_Id; begin -- If this is not a completion, construct the implicit full -- view by deriving from the full view of the parent type. -- But if this is a completion, the derived private type -- being built is a full view and the full derivation can -- only be its underlying full view. Build_Full_Derivation; if not Is_Completion then Set_Full_View (Derived_Type, Full_Der); else Set_Underlying_Full_View (Derived_Type, Full_Der); Set_Is_Underlying_Full_View (Full_Der); end if; if not Is_Base_Type (Derived_Type) then Set_Full_View (Der_Base, Base_Type (Full_Der)); end if; -- Copy the discriminant list from full view to the partial -- view (base type and its subtype). Gigi requires that the -- partial and full views have the same discriminants. -- Note that since the partial view points to discriminants -- in the full view, their scope will be that of the full -- view. This might cause some front end problems and need -- adjustment??? Discr := First_Discriminant (Base_Type (Full_Der)); Set_First_Entity (Der_Base, Discr); loop Last_Discr := Discr; Next_Discriminant (Discr); exit when No (Discr); end loop; Set_Last_Entity (Der_Base, Last_Discr); Set_First_Entity (Derived_Type, First_Entity (Der_Base)); Set_Last_Entity (Derived_Type, Last_Entity (Der_Base)); end; end if; elsif Present (Available_Full_View (Parent_Type)) and then Has_Discriminants (Available_Full_View (Parent_Type)) then if Has_Unknown_Discriminants (Parent_Type) and then Nkind (Subtype_Indication (Type_Definition (N))) = N_Subtype_Indication then Error_Msg_N ("cannot constrain type with unknown discriminants", Subtype_Indication (Type_Definition (N))); return; end if; -- If this is not a completion, construct the implicit full view by -- deriving from the full view of the parent type. But if this is a -- completion, the derived private type being built is a full view -- and the full derivation can only be its underlying full view. Build_Full_Derivation; if not Is_Completion then Set_Full_View (Derived_Type, Full_Der); else Set_Underlying_Full_View (Derived_Type, Full_Der); Set_Is_Underlying_Full_View (Full_Der); end if; -- In any case, the primitive operations are inherited from the -- parent type, not from the internal full view. Set_Etype (Base_Type (Derived_Type), Base_Type (Parent_Type)); if Derive_Subps then -- Initialize the list of primitive operations to an empty list, -- to cover tagged types as well as untagged types. For untagged -- types this is used either to analyze the call as legal when -- Extensions_Allowed is True, or to issue a better error message -- otherwise. Set_Direct_Primitive_Operations (Derived_Type, New_Elmt_List); Derive_Subprograms (Parent_Type, Derived_Type); end if; Set_Stored_Constraint (Derived_Type, No_Elist); Set_Is_Constrained (Derived_Type, Is_Constrained (Available_Full_View (Parent_Type))); else -- Untagged type, No discriminants on either view if Nkind (Subtype_Indication (Type_Definition (N))) = N_Subtype_Indication then Error_Msg_N ("illegal constraint on type without discriminants", N); end if; if Present (Discriminant_Specifications (N)) and then Present (Available_Full_View (Parent_Type)) and then not Is_Tagged_Type (Available_Full_View (Parent_Type)) then Error_Msg_N ("cannot add discriminants to untagged type", N); end if; Set_Stored_Constraint (Derived_Type, No_Elist); Set_Is_Constrained (Derived_Type, Is_Constrained (Parent_Type)); Set_Is_Controlled_Active (Derived_Type, Is_Controlled_Active (Parent_Type)); Set_Disable_Controlled (Derived_Type, Disable_Controlled (Parent_Type)); Set_Has_Controlled_Component (Derived_Type, Has_Controlled_Component (Parent_Type)); -- Direct controlled types do not inherit Finalize_Storage_Only flag if not Is_Controlled (Parent_Type) then Set_Finalize_Storage_Only (Base_Type (Derived_Type), Finalize_Storage_Only (Parent_Type)); end if; -- If this is not a completion, construct the implicit full view by -- deriving from the full view of the parent type. But if this is a -- completion, the derived private type being built is a full view -- and the full derivation can only be its underlying full view. -- ??? If the parent type is untagged private and its completion is -- tagged, this mechanism will not work because we cannot derive from -- the tagged full view unless we have an extension. if Present (Available_Full_View (Parent_Type)) and then not Is_Tagged_Type (Available_Full_View (Parent_Type)) and then not Error_Posted (N) then Build_Full_Derivation; if not Is_Completion then Set_Full_View (Derived_Type, Full_Der); else Set_Underlying_Full_View (Derived_Type, Full_Der); Set_Is_Underlying_Full_View (Full_Der); end if; end if; end if; Set_Has_Unknown_Discriminants (Derived_Type, Has_Unknown_Discriminants (Parent_Type)); if Is_Private_Type (Derived_Type) then Set_Private_Dependents (Derived_Type, New_Elmt_List); end if; -- If the parent base type is in scope, add the derived type to its -- list of private dependents, because its full view may become -- visible subsequently (in a nested private part, a body, or in a -- further child unit). if Is_Private_Type (Par_Base) and then In_Open_Scopes (Par_Scope) then Append_Elmt (Derived_Type, Private_Dependents (Parent_Type)); -- Check for unusual case where a type completed by a private -- derivation occurs within a package nested in a child unit, and -- the parent is declared in an ancestor. if Is_Child_Unit (Scope (Current_Scope)) and then Is_Completion and then In_Private_Part (Current_Scope) and then Scope (Parent_Type) /= Current_Scope -- Note that if the parent has a completion in the private part, -- (which is itself a derivation from some other private type) -- it is that completion that is visible, there is no full view -- available, and no special processing is needed. and then Present (Full_View (Parent_Type)) then -- In this case, the full view of the parent type will become -- visible in the body of the enclosing child, and only then will -- the current type be possibly non-private. Build an underlying -- full view that will be installed when the enclosing child body -- is compiled. if Present (Underlying_Full_View (Derived_Type)) then Full_Der := Underlying_Full_View (Derived_Type); else Build_Full_Derivation; Set_Underlying_Full_View (Derived_Type, Full_Der); Set_Is_Underlying_Full_View (Full_Der); end if; -- The full view will be used to swap entities on entry/exit to -- the body, and must appear in the entity list for the package. Append_Entity (Full_Der, Scope (Derived_Type)); end if; end if; end Build_Derived_Private_Type; ------------------------------- -- Build_Derived_Record_Type -- ------------------------------- -- 1. INTRODUCTION -- Ideally we would like to use the same model of type derivation for -- tagged and untagged record types. Unfortunately this is not quite -- possible because the semantics of representation clauses is different -- for tagged and untagged records under inheritance. Consider the -- following: -- type R (...) is [tagged] record ... end record; -- type T (...) is new R (...) [with ...]; -- The representation clauses for T can specify a completely different -- record layout from R's. Hence the same component can be placed in two -- very different positions in objects of type T and R. If R and T are -- tagged types, representation clauses for T can only specify the layout -- of non inherited components, thus components that are common in R and T -- have the same position in objects of type R and T. -- This has two implications. The first is that the entire tree for R's -- declaration needs to be copied for T in the untagged case, so that T -- can be viewed as a record type of its own with its own representation -- clauses. The second implication is the way we handle discriminants. -- Specifically, in the untagged case we need a way to communicate to Gigi -- what are the real discriminants in the record, while for the semantics -- we need to consider those introduced by the user to rename the -- discriminants in the parent type. This is handled by introducing the -- notion of stored discriminants. See below for more. -- Fortunately the way regular components are inherited can be handled in -- the same way in tagged and untagged types. -- To complicate things a bit more the private view of a private extension -- cannot be handled in the same way as the full view (for one thing the -- semantic rules are somewhat different). We will explain what differs -- below. -- 2. DISCRIMINANTS UNDER INHERITANCE -- The semantic rules governing the discriminants of derived types are -- quite subtle. -- type Derived_Type_Name [KNOWN_DISCRIMINANT_PART] is new -- [abstract] Parent_Type_Name [CONSTRAINT] [RECORD_EXTENSION_PART] -- If parent type has discriminants, then the discriminants that are -- declared in the derived type are [3.4 (11)]: -- o The discriminants specified by a new KNOWN_DISCRIMINANT_PART, if -- there is one; -- o Otherwise, each discriminant of the parent type (implicitly declared -- in the same order with the same specifications). In this case, the -- discriminants are said to be "inherited", or if unknown in the parent -- are also unknown in the derived type. -- Furthermore if a KNOWN_DISCRIMINANT_PART is provided, then [3.7(13-18)]: -- o The parent subtype must be constrained; -- o If the parent type is not a tagged type, then each discriminant of -- the derived type must be used in the constraint defining a parent -- subtype. [Implementation note: This ensures that the new discriminant -- can share storage with an existing discriminant.] -- For the derived type each discriminant of the parent type is either -- inherited, constrained to equal some new discriminant of the derived -- type, or constrained to the value of an expression. -- When inherited or constrained to equal some new discriminant, the -- parent discriminant and the discriminant of the derived type are said -- to "correspond". -- If a discriminant of the parent type is constrained to a specific value -- in the derived type definition, then the discriminant is said to be -- "specified" by that derived type definition. -- 3. DISCRIMINANTS IN DERIVED UNTAGGED RECORD TYPES -- We have spoken about stored discriminants in point 1 (introduction) -- above. There are two sorts of stored discriminants: implicit and -- explicit. As long as the derived type inherits the same discriminants as -- the root record type, stored discriminants are the same as regular -- discriminants, and are said to be implicit. However, if any discriminant -- in the root type was renamed in the derived type, then the derived -- type will contain explicit stored discriminants. Explicit stored -- discriminants are discriminants in addition to the semantically visible -- discriminants defined for the derived type. Stored discriminants are -- used by Gigi to figure out what are the physical discriminants in -- objects of the derived type (see precise definition in einfo.ads). -- As an example, consider the following: -- type R (D1, D2, D3 : Int) is record ... end record; -- type T1 is new R; -- type T2 (X1, X2: Int) is new T1 (X2, 88, X1); -- type T3 is new T2; -- type T4 (Y : Int) is new T3 (Y, 99); -- The following table summarizes the discriminants and stored -- discriminants in R and T1 through T4: -- Type Discrim Stored Discrim Comment -- R (D1, D2, D3) (D1, D2, D3) Stored discrims implicit in R -- T1 (D1, D2, D3) (D1, D2, D3) Stored discrims implicit in T1 -- T2 (X1, X2) (D1, D2, D3) Stored discrims EXPLICIT in T2 -- T3 (X1, X2) (D1, D2, D3) Stored discrims EXPLICIT in T3 -- T4 (Y) (D1, D2, D3) Stored discrims EXPLICIT in T4 -- Field Corresponding_Discriminant (abbreviated CD below) allows us to -- find the corresponding discriminant in the parent type, while -- Original_Record_Component (abbreviated ORC below) the actual physical -- component that is renamed. Finally the field Is_Completely_Hidden -- (abbreviated ICH below) is set for all explicit stored discriminants -- (see einfo.ads for more info). For the above example this gives: -- Discrim CD ORC ICH -- ^^^^^^^ ^^ ^^^ ^^^ -- D1 in R empty itself no -- D2 in R empty itself no -- D3 in R empty itself no -- D1 in T1 D1 in R itself no -- D2 in T1 D2 in R itself no -- D3 in T1 D3 in R itself no -- X1 in T2 D3 in T1 D3 in T2 no -- X2 in T2 D1 in T1 D1 in T2 no -- D1 in T2 empty itself yes -- D2 in T2 empty itself yes -- D3 in T2 empty itself yes -- X1 in T3 X1 in T2 D3 in T3 no -- X2 in T3 X2 in T2 D1 in T3 no -- D1 in T3 empty itself yes -- D2 in T3 empty itself yes -- D3 in T3 empty itself yes -- Y in T4 X1 in T3 D3 in T4 no -- D1 in T4 empty itself yes -- D2 in T4 empty itself yes -- D3 in T4 empty itself yes -- 4. DISCRIMINANTS IN DERIVED TAGGED RECORD TYPES -- Type derivation for tagged types is fairly straightforward. If no -- discriminants are specified by the derived type, these are inherited -- from the parent. No explicit stored discriminants are ever necessary. -- The only manipulation that is done to the tree is that of adding a -- _parent field with parent type and constrained to the same constraint -- specified for the parent in the derived type definition. For instance: -- type R (D1, D2, D3 : Int) is tagged record ... end record; -- type T1 is new R with null record; -- type T2 (X1, X2: Int) is new T1 (X2, 88, X1) with null record; -- are changed into: -- type T1 (D1, D2, D3 : Int) is new R (D1, D2, D3) with record -- _parent : R (D1, D2, D3); -- end record; -- type T2 (X1, X2: Int) is new T1 (X2, 88, X1) with record -- _parent : T1 (X2, 88, X1); -- end record; -- The discriminants actually present in R, T1 and T2 as well as their CD, -- ORC and ICH fields are: -- Discrim CD ORC ICH -- ^^^^^^^ ^^ ^^^ ^^^ -- D1 in R empty itself no -- D2 in R empty itself no -- D3 in R empty itself no -- D1 in T1 D1 in R D1 in R no -- D2 in T1 D2 in R D2 in R no -- D3 in T1 D3 in R D3 in R no -- X1 in T2 D3 in T1 D3 in R no -- X2 in T2 D1 in T1 D1 in R no -- 5. FIRST TRANSFORMATION FOR DERIVED RECORDS -- -- Regardless of whether we dealing with a tagged or untagged type -- we will transform all derived type declarations of the form -- -- type T is new R (...) [with ...]; -- or -- subtype S is R (...); -- type T is new S [with ...]; -- into -- type BT is new R [with ...]; -- subtype T is BT (...); -- -- That is, the base derived type is constrained only if it has no -- discriminants. The reason for doing this is that GNAT's semantic model -- assumes that a base type with discriminants is unconstrained. -- -- Note that, strictly speaking, the above transformation is not always -- correct. Consider for instance the following excerpt from ACVC b34011a: -- -- procedure B34011A is -- type REC (D : integer := 0) is record -- I : Integer; -- end record; -- package P is -- type T6 is new Rec; -- function F return T6; -- end P; -- use P; -- package Q6 is -- type U is new T6 (Q6.F.I); -- ERROR: Q6.F. -- end Q6; -- -- The definition of Q6.U is illegal. However transforming Q6.U into -- type BaseU is new T6; -- subtype U is BaseU (Q6.F.I) -- turns U into a legal subtype, which is incorrect. To avoid this problem -- we always analyze the constraint (in this case (Q6.F.I)) before applying -- the transformation described above. -- There is another instance where the above transformation is incorrect. -- Consider: -- package Pack is -- type Base (D : Integer) is tagged null record; -- procedure P (X : Base); -- type Der is new Base (2) with null record; -- procedure P (X : Der); -- end Pack; -- Then the above transformation turns this into -- type Der_Base is new Base with null record; -- -- procedure P (X : Base) is implicitly inherited here -- -- as procedure P (X : Der_Base). -- subtype Der is Der_Base (2); -- procedure P (X : Der); -- -- The overriding of P (X : Der_Base) is illegal since we -- -- have a parameter conformance problem. -- To get around this problem, after having semantically processed Der_Base -- and the rewritten subtype declaration for Der, we copy Der_Base field -- Discriminant_Constraint from Der so that when parameter conformance is -- checked when P is overridden, no semantic errors are flagged. -- 6. SECOND TRANSFORMATION FOR DERIVED RECORDS -- Regardless of whether we are dealing with a tagged or untagged type -- we will transform all derived type declarations of the form -- type R (D1, .., Dn : ...) is [tagged] record ...; -- type T is new R [with ...]; -- into -- type T (D1, .., Dn : ...) is new R (D1, .., Dn) [with ...]; -- The reason for such transformation is that it allows us to implement a -- very clean form of component inheritance as explained below. -- Note that this transformation is not achieved by direct tree rewriting -- and manipulation, but rather by redoing the semantic actions that the -- above transformation will entail. This is done directly in routine -- Inherit_Components. -- 7. TYPE DERIVATION AND COMPONENT INHERITANCE -- In both tagged and untagged derived types, regular non discriminant -- components are inherited in the derived type from the parent type. In -- the absence of discriminants component, inheritance is straightforward -- as components can simply be copied from the parent. -- If the parent has discriminants, inheriting components constrained with -- these discriminants requires caution. Consider the following example: -- type R (D1, D2 : Positive) is [tagged] record -- S : String (D1 .. D2); -- end record; -- type T1 is new R [with null record]; -- type T2 (X : positive) is new R (1, X) [with null record]; -- As explained in 6. above, T1 is rewritten as -- type T1 (D1, D2 : Positive) is new R (D1, D2) [with null record]; -- which makes the treatment for T1 and T2 identical. -- What we want when inheriting S, is that references to D1 and D2 in R are -- replaced with references to their correct constraints, i.e. D1 and D2 in -- T1 and 1 and X in T2. So all R's discriminant references are replaced -- with either discriminant references in the derived type or expressions. -- This replacement is achieved as follows: before inheriting R's -- components, a subtype R (D1, D2) for T1 (resp. R (1, X) for T2) is -- created in the scope of T1 (resp. scope of T2) so that discriminants D1 -- and D2 of T1 are visible (resp. discriminant X of T2 is visible). -- For T2, for instance, this has the effect of replacing String (D1 .. D2) -- by String (1 .. X). -- 8. TYPE DERIVATION IN PRIVATE TYPE EXTENSIONS -- We explain here the rules governing private type extensions relevant to -- type derivation. These rules are explained on the following example: -- type D [(...)] is new A [(...)] with private; <-- partial view -- type D [(...)] is new P [(...)] with null record; <-- full view -- Type A is called the ancestor subtype of the private extension. -- Type P is the parent type of the full view of the private extension. It -- must be A or a type derived from A. -- The rules concerning the discriminants of private type extensions are -- [7.3(10-13)]: -- o If a private extension inherits known discriminants from the ancestor -- subtype, then the full view must also inherit its discriminants from -- the ancestor subtype and the parent subtype of the full view must be -- constrained if and only if the ancestor subtype is constrained. -- o If a partial view has unknown discriminants, then the full view may -- define a definite or an indefinite subtype, with or without -- discriminants. -- o If a partial view has neither known nor unknown discriminants, then -- the full view must define a definite subtype. -- o If the ancestor subtype of a private extension has constrained -- discriminants, then the parent subtype of the full view must impose a -- statically matching constraint on those discriminants. -- This means that only the following forms of private extensions are -- allowed: -- type D is new A with private; <-- partial view -- type D is new P with null record; <-- full view -- If A has no discriminants than P has no discriminants, otherwise P must -- inherit A's discriminants. -- type D is new A (...) with private; <-- partial view -- type D is new P (:::) with null record; <-- full view -- P must inherit A's discriminants and (...) and (:::) must statically -- match. -- subtype A is R (...); -- type D is new A with private; <-- partial view -- type D is new P with null record; <-- full view -- P must have inherited R's discriminants and must be derived from A or -- any of its subtypes. -- type D (..) is new A with private; <-- partial view -- type D (..) is new P [(:::)] with null record; <-- full view -- No specific constraints on P's discriminants or constraint (:::). -- Note that A can be unconstrained, but the parent subtype P must either -- be constrained or (:::) must be present. -- type D (..) is new A [(...)] with private; <-- partial view -- type D (..) is new P [(:::)] with null record; <-- full view -- P's constraints on A's discriminants must statically match those -- imposed by (...). -- 9. IMPLEMENTATION OF TYPE DERIVATION FOR PRIVATE EXTENSIONS -- The full view of a private extension is handled exactly as described -- above. The model chose for the private view of a private extension is -- the same for what concerns discriminants (i.e. they receive the same -- treatment as in the tagged case). However, the private view of the -- private extension always inherits the components of the parent base, -- without replacing any discriminant reference. Strictly speaking this is -- incorrect. However, Gigi never uses this view to generate code so this -- is a purely semantic issue. In theory, a set of transformations similar -- to those given in 5. and 6. above could be applied to private views of -- private extensions to have the same model of component inheritance as -- for non private extensions. However, this is not done because it would -- further complicate private type processing. Semantically speaking, this -- leaves us in an uncomfortable situation. As an example consider: -- package Pack is -- type R (D : integer) is tagged record -- S : String (1 .. D); -- end record; -- procedure P (X : R); -- type T is new R (1) with private; -- private -- type T is new R (1) with null record; -- end; -- This is transformed into: -- package Pack is -- type R (D : integer) is tagged record -- S : String (1 .. D); -- end record; -- procedure P (X : R); -- type T is new R (1) with private; -- private -- type BaseT is new R with null record; -- subtype T is BaseT (1); -- end; -- (strictly speaking the above is incorrect Ada) -- From the semantic standpoint the private view of private extension T -- should be flagged as constrained since one can clearly have -- -- Obj : T; -- -- in a unit withing Pack. However, when deriving subprograms for the -- private view of private extension T, T must be seen as unconstrained -- since T has discriminants (this is a constraint of the current -- subprogram derivation model). Thus, when processing the private view of -- a private extension such as T, we first mark T as unconstrained, we -- process it, we perform program derivation and just before returning from -- Build_Derived_Record_Type we mark T as constrained. -- ??? Are there are other uncomfortable cases that we will have to -- deal with. -- 10. RECORD_TYPE_WITH_PRIVATE complications -- Types that are derived from a visible record type and have a private -- extension present other peculiarities. They behave mostly like private -- types, but if they have primitive operations defined, these will not -- have the proper signatures for further inheritance, because other -- primitive operations will use the implicit base that we define for -- private derivations below. This affect subprogram inheritance (see -- Derive_Subprograms for details). We also derive the implicit base from -- the base type of the full view, so that the implicit base is a record -- type and not another private type, This avoids infinite loops. procedure Build_Derived_Record_Type (N : Node_Id; Parent_Type : Entity_Id; Derived_Type : Entity_Id; Derive_Subps : Boolean := True) is Discriminant_Specs : constant Boolean := Present (Discriminant_Specifications (N)); Is_Tagged : constant Boolean := Is_Tagged_Type (Parent_Type); Loc : constant Source_Ptr := Sloc (N); Private_Extension : constant Boolean := Nkind (N) = N_Private_Extension_Declaration; Assoc_List : Elist_Id; Constraint_Present : Boolean; Constrs : Elist_Id; Discrim : Entity_Id; Indic : Node_Id; Inherit_Discrims : Boolean := False; Last_Discrim : Entity_Id; New_Base : Entity_Id; New_Decl : Node_Id; New_Discrs : Elist_Id; New_Indic : Node_Id; Parent_Base : Entity_Id; Save_Etype : Entity_Id; Save_Discr_Constr : Elist_Id; Save_Next_Entity : Entity_Id; Type_Def : Node_Id; Discs : Elist_Id := New_Elmt_List; -- An empty Discs list means that there were no constraints in the -- subtype indication or that there was an error processing it. procedure Check_Generic_Ancestors; -- In Ada 2005 (AI-344), the restriction that a derived tagged type -- cannot be declared at a deeper level than its parent type is -- removed. The check on derivation within a generic body is also -- relaxed, but there's a restriction that a derived tagged type -- cannot be declared in a generic body if it's derived directly -- or indirectly from a formal type of that generic. This applies -- to progenitors as well. ----------------------------- -- Check_Generic_Ancestors -- ----------------------------- procedure Check_Generic_Ancestors is Ancestor_Type : Entity_Id; Intf_List : List_Id; Intf_Name : Node_Id; procedure Check_Ancestor; -- For parent and progenitors. -------------------- -- Check_Ancestor -- -------------------- procedure Check_Ancestor is begin -- If the derived type does have a formal type as an ancestor -- then it's an error if the derived type is declared within -- the body of the generic unit that declares the formal type -- in its generic formal part. It's sufficient to check whether -- the ancestor type is declared inside the same generic body -- as the derived type (such as within a nested generic spec), -- in which case the derivation is legal. If the formal type is -- declared outside of that generic body, then it's certain -- that the derived type is declared within the generic body -- of the generic unit declaring the formal type. if Is_Generic_Type (Ancestor_Type) and then Enclosing_Generic_Body (Ancestor_Type) /= Enclosing_Generic_Body (Derived_Type) then Error_Msg_NE ("ancestor type& is formal type of enclosing" & " generic unit (RM 3.9.1 (4/2))", Indic, Ancestor_Type); end if; end Check_Ancestor; begin if Nkind (N) = N_Private_Extension_Declaration then Intf_List := Interface_List (N); else Intf_List := Interface_List (Type_Definition (N)); end if; if Present (Enclosing_Generic_Body (Derived_Type)) then Ancestor_Type := Parent_Type; while not Is_Generic_Type (Ancestor_Type) and then Etype (Ancestor_Type) /= Ancestor_Type loop Ancestor_Type := Etype (Ancestor_Type); end loop; Check_Ancestor; if Present (Intf_List) then Intf_Name := First (Intf_List); while Present (Intf_Name) loop Ancestor_Type := Entity (Intf_Name); Check_Ancestor; Next (Intf_Name); end loop; end if; end if; end Check_Generic_Ancestors; -- Start of processing for Build_Derived_Record_Type begin if Ekind (Parent_Type) = E_Record_Type_With_Private and then Present (Full_View (Parent_Type)) and then Has_Discriminants (Parent_Type) then Parent_Base := Base_Type (Full_View (Parent_Type)); else Parent_Base := Base_Type (Parent_Type); end if; -- If the parent type is declared as a subtype of another private -- type with inherited discriminants, its generated base type is -- itself a record subtype. To further inherit the constraint we -- need to use its own base to have an unconstrained type on which -- to apply the inherited constraint. if Ekind (Parent_Base) = E_Record_Subtype then Parent_Base := Base_Type (Parent_Base); end if; -- AI05-0115: if this is a derivation from a private type in some -- other scope that may lead to invisible components for the derived -- type, mark it accordingly. if Is_Private_Type (Parent_Type) then if Scope (Parent_Base) = Scope (Derived_Type) then null; elsif In_Open_Scopes (Scope (Parent_Base)) and then In_Private_Part (Scope (Parent_Base)) then null; else Set_Has_Private_Ancestor (Derived_Type); end if; else Set_Has_Private_Ancestor (Derived_Type, Has_Private_Ancestor (Parent_Type)); end if; -- Before we start the previously documented transformations, here is -- little fix for size and alignment of tagged types. Normally when we -- derive type D from type P, we copy the size and alignment of P as the -- default for D, and in the absence of explicit representation clauses -- for D, the size and alignment are indeed the same as the parent. -- But this is wrong for tagged types, since fields may be added, and -- the default size may need to be larger, and the default alignment may -- need to be larger. -- We therefore reset the size and alignment fields in the tagged case. -- Note that the size and alignment will in any case be at least as -- large as the parent type (since the derived type has a copy of the -- parent type in the _parent field) -- The type is also marked as being tagged here, which is needed when -- processing components with a self-referential anonymous access type -- in the call to Check_Anonymous_Access_Components below. Note that -- this flag is also set later on for completeness. if Is_Tagged then Set_Is_Tagged_Type (Derived_Type); Reinit_Size_Align (Derived_Type); end if; -- STEP 0a: figure out what kind of derived type declaration we have if Private_Extension then Type_Def := N; Mutate_Ekind (Derived_Type, E_Record_Type_With_Private); Set_Default_SSO (Derived_Type); Set_No_Reordering (Derived_Type, No_Component_Reordering); else Type_Def := Type_Definition (N); -- Ekind (Parent_Base) is not necessarily E_Record_Type since -- Parent_Base can be a private type or private extension. However, -- for tagged types with an extension the newly added fields are -- visible and hence the Derived_Type is always an E_Record_Type. -- (except that the parent may have its own private fields). -- For untagged types we preserve the Ekind of the Parent_Base. if Present (Record_Extension_Part (Type_Def)) then Mutate_Ekind (Derived_Type, E_Record_Type); Set_Default_SSO (Derived_Type); Set_No_Reordering (Derived_Type, No_Component_Reordering); -- Create internal access types for components with anonymous -- access types. if Ada_Version >= Ada_2005 then Check_Anonymous_Access_Components (N, Derived_Type, Derived_Type, Component_List (Record_Extension_Part (Type_Def))); end if; else Mutate_Ekind (Derived_Type, Ekind (Parent_Base)); end if; end if; -- Indic can either be an N_Identifier if the subtype indication -- contains no constraint or an N_Subtype_Indication if the subtype -- indication has a constraint. In either case it can include an -- interface list. Indic := Subtype_Indication (Type_Def); Constraint_Present := (Nkind (Indic) = N_Subtype_Indication); -- Check that the type has visible discriminants. The type may be -- a private type with unknown discriminants whose full view has -- discriminants which are invisible. if Constraint_Present then if not Has_Discriminants (Parent_Base) or else (Has_Unknown_Discriminants (Parent_Base) and then Is_Private_Type (Parent_Base)) then Error_Msg_N ("invalid constraint: type has no discriminant", Constraint (Indic)); Constraint_Present := False; Rewrite (Indic, New_Copy_Tree (Subtype_Mark (Indic))); elsif Is_Constrained (Parent_Type) then Error_Msg_N ("invalid constraint: parent type is already constrained", Constraint (Indic)); Constraint_Present := False; Rewrite (Indic, New_Copy_Tree (Subtype_Mark (Indic))); end if; end if; -- STEP 0b: If needed, apply transformation given in point 5. above if not Private_Extension and then Has_Discriminants (Parent_Type) and then not Discriminant_Specs and then (Is_Constrained (Parent_Type) or else Constraint_Present) then -- First, we must analyze the constraint (see comment in point 5.) -- The constraint may come from the subtype indication of the full -- declaration. if Constraint_Present then New_Discrs := Build_Discriminant_Constraints (Parent_Type, Indic); -- If there is no explicit constraint, there might be one that is -- inherited from a constrained parent type. In that case verify that -- it conforms to the constraint in the partial view. In perverse -- cases the parent subtypes of the partial and full view can have -- different constraints. elsif Present (Stored_Constraint (Parent_Type)) then New_Discrs := Stored_Constraint (Parent_Type); else New_Discrs := No_Elist; end if; if Has_Discriminants (Derived_Type) and then Has_Private_Declaration (Derived_Type) and then Present (Discriminant_Constraint (Derived_Type)) and then Present (New_Discrs) then -- Verify that constraints of the full view statically match -- those given in the partial view. declare C1, C2 : Elmt_Id; begin C1 := First_Elmt (New_Discrs); C2 := First_Elmt (Discriminant_Constraint (Derived_Type)); while Present (C1) and then Present (C2) loop if Fully_Conformant_Expressions (Node (C1), Node (C2)) or else (Is_OK_Static_Expression (Node (C1)) and then Is_OK_Static_Expression (Node (C2)) and then Expr_Value (Node (C1)) = Expr_Value (Node (C2))) then null; else if Constraint_Present then Error_Msg_N ("constraint not conformant to previous declaration", Node (C1)); else Error_Msg_N ("constraint of full view is incompatible " & "with partial view", N); end if; end if; Next_Elmt (C1); Next_Elmt (C2); end loop; end; end if; -- Insert and analyze the declaration for the unconstrained base type New_Base := Create_Itype (Ekind (Derived_Type), N, Derived_Type, 'B'); New_Decl := Make_Full_Type_Declaration (Loc, Defining_Identifier => New_Base, Type_Definition => Make_Derived_Type_Definition (Loc, Abstract_Present => Abstract_Present (Type_Def), Limited_Present => Limited_Present (Type_Def), Subtype_Indication => New_Occurrence_Of (Parent_Base, Loc), Record_Extension_Part => Relocate_Node (Record_Extension_Part (Type_Def)), Interface_List => Interface_List (Type_Def))); Set_Parent (New_Decl, Parent (N)); Mark_Rewrite_Insertion (New_Decl); Insert_Before (N, New_Decl); -- In the extension case, make sure ancestor is frozen appropriately -- (see also non-discriminated case below). if Present (Record_Extension_Part (Type_Def)) or else Is_Interface (Parent_Base) then Freeze_Before (New_Decl, Parent_Type); end if; -- Note that this call passes False for the Derive_Subps parameter -- because subprogram derivation is deferred until after creating -- the subtype (see below). Build_Derived_Type (New_Decl, Parent_Base, New_Base, Is_Completion => False, Derive_Subps => False); -- ??? This needs re-examination to determine whether the -- above call can simply be replaced by a call to Analyze. Set_Analyzed (New_Decl); -- Insert and analyze the declaration for the constrained subtype if Constraint_Present then New_Indic := Make_Subtype_Indication (Loc, Subtype_Mark => New_Occurrence_Of (New_Base, Loc), Constraint => Relocate_Node (Constraint (Indic))); else declare Constr_List : constant List_Id := New_List; C : Elmt_Id; Expr : Node_Id; begin C := First_Elmt (Discriminant_Constraint (Parent_Type)); while Present (C) loop Expr := Node (C); -- It is safe here to call New_Copy_Tree since we called -- Force_Evaluation on each constraint previously -- in Build_Discriminant_Constraints. Append (New_Copy_Tree (Expr), To => Constr_List); Next_Elmt (C); end loop; New_Indic := Make_Subtype_Indication (Loc, Subtype_Mark => New_Occurrence_Of (New_Base, Loc), Constraint => Make_Index_Or_Discriminant_Constraint (Loc, Constr_List)); end; end if; Rewrite (N, Make_Subtype_Declaration (Loc, Defining_Identifier => Derived_Type, Subtype_Indication => New_Indic)); Analyze (N); -- Derivation of subprograms must be delayed until the full subtype -- has been established, to ensure proper overriding of subprograms -- inherited by full types. If the derivations occurred as part of -- the call to Build_Derived_Type above, then the check for type -- conformance would fail because earlier primitive subprograms -- could still refer to the full type prior the change to the new -- subtype and hence would not match the new base type created here. -- Subprograms are not derived, however, when Derive_Subps is False -- (since otherwise there could be redundant derivations). if Derive_Subps then Derive_Subprograms (Parent_Type, Derived_Type); end if; -- For tagged types the Discriminant_Constraint of the new base itype -- is inherited from the first subtype so that no subtype conformance -- problem arise when the first subtype overrides primitive -- operations inherited by the implicit base type. if Is_Tagged then Set_Discriminant_Constraint (New_Base, Discriminant_Constraint (Derived_Type)); end if; return; end if; -- If we get here Derived_Type will have no discriminants or it will be -- a discriminated unconstrained base type. -- STEP 1a: perform preliminary actions/checks for derived tagged types if Is_Tagged then -- The parent type is frozen for non-private extensions (RM 13.14(7)) -- The declaration of a specific descendant of an interface type -- freezes the interface type (RM 13.14). if not Private_Extension or else Is_Interface (Parent_Base) then Freeze_Before (N, Parent_Type); end if; if Ada_Version >= Ada_2005 then Check_Generic_Ancestors; elsif Type_Access_Level (Derived_Type) /= Type_Access_Level (Parent_Type) and then not Is_Generic_Type (Derived_Type) then if Is_Controlled (Parent_Type) then Error_Msg_N ("controlled type must be declared at the library level", Indic); else Error_Msg_N ("type extension at deeper accessibility level than parent", Indic); end if; else declare GB : constant Node_Id := Enclosing_Generic_Body (Derived_Type); begin if Present (GB) and then GB /= Enclosing_Generic_Body (Parent_Base) then Error_Msg_NE ("parent type of& must not be outside generic body" & " (RM 3.9.1(4))", Indic, Derived_Type); end if; end; end if; end if; -- Ada 2005 (AI-251) if Ada_Version >= Ada_2005 and then Is_Tagged then -- "The declaration of a specific descendant of an interface type -- freezes the interface type" (RM 13.14). declare Iface : Node_Id; begin Iface := First (Interface_List (Type_Def)); while Present (Iface) loop Freeze_Before (N, Etype (Iface)); Next (Iface); end loop; end; end if; -- STEP 1b : preliminary cleanup of the full view of private types -- If the type is already marked as having discriminants, then it's the -- completion of a private type or private extension and we need to -- retain the discriminants from the partial view if the current -- declaration has Discriminant_Specifications so that we can verify -- conformance. However, we must remove any existing components that -- were inherited from the parent (and attached in Copy_And_Swap) -- because the full type inherits all appropriate components anyway, and -- we do not want the partial view's components interfering. if Has_Discriminants (Derived_Type) and then Discriminant_Specs then Discrim := First_Discriminant (Derived_Type); loop Last_Discrim := Discrim; Next_Discriminant (Discrim); exit when No (Discrim); end loop; Set_Last_Entity (Derived_Type, Last_Discrim); -- In all other cases wipe out the list of inherited components (even -- inherited discriminants), it will be properly rebuilt here. else Set_First_Entity (Derived_Type, Empty); Set_Last_Entity (Derived_Type, Empty); end if; -- STEP 1c: Initialize some flags for the Derived_Type -- The following flags must be initialized here so that -- Process_Discriminants can check that discriminants of tagged types do -- not have a default initial value and that access discriminants are -- only specified for limited records. For completeness, these flags are -- also initialized along with all the other flags below. -- AI-419: Limitedness is not inherited from an interface parent, so to -- be limited in that case the type must be explicitly declared as -- limited. However, task and protected interfaces are always limited. if Limited_Present (Type_Def) then Set_Is_Limited_Record (Derived_Type); elsif Is_Limited_Record (Parent_Type) or else (Present (Full_View (Parent_Type)) and then Is_Limited_Record (Full_View (Parent_Type))) then if not Is_Interface (Parent_Type) or else Is_Concurrent_Interface (Parent_Type) then Set_Is_Limited_Record (Derived_Type); end if; end if; -- STEP 2a: process discriminants of derived type if any Push_Scope (Derived_Type); if Discriminant_Specs then Set_Has_Unknown_Discriminants (Derived_Type, False); -- The following call initializes fields Has_Discriminants and -- Discriminant_Constraint, unless we are processing the completion -- of a private type declaration. Check_Or_Process_Discriminants (N, Derived_Type); -- For untagged types, the constraint on the Parent_Type must be -- present and is used to rename the discriminants. if not Is_Tagged and then not Has_Discriminants (Parent_Type) then Error_Msg_N ("untagged parent must have discriminants", Indic); elsif not Is_Tagged and then not Constraint_Present then Error_Msg_N ("discriminant constraint needed for derived untagged records", Indic); -- Otherwise the parent subtype must be constrained unless we have a -- private extension. elsif not Constraint_Present and then not Private_Extension and then not Is_Constrained (Parent_Type) then Error_Msg_N ("unconstrained type not allowed in this context", Indic); elsif Constraint_Present then -- The following call sets the field Corresponding_Discriminant -- for the discriminants in the Derived_Type. Discs := Build_Discriminant_Constraints (Parent_Type, Indic, True); -- For untagged types all new discriminants must rename -- discriminants in the parent. For private extensions new -- discriminants cannot rename old ones (implied by [7.3(13)]). Discrim := First_Discriminant (Derived_Type); while Present (Discrim) loop if not Is_Tagged and then No (Corresponding_Discriminant (Discrim)) then Error_Msg_N ("new discriminants must constrain old ones", Discrim); elsif Private_Extension and then Present (Corresponding_Discriminant (Discrim)) then Error_Msg_N ("only static constraints allowed for parent" & " discriminants in the partial view", Indic); exit; end if; -- If a new discriminant is used in the constraint, then its -- subtype must be statically compatible with the subtype of -- the parent discriminant (RM 3.7(15)). if Present (Corresponding_Discriminant (Discrim)) then Check_Constraining_Discriminant (Discrim, Corresponding_Discriminant (Discrim)); end if; Next_Discriminant (Discrim); end loop; -- Check whether the constraints of the full view statically -- match those imposed by the parent subtype [7.3(13)]. if Present (Stored_Constraint (Derived_Type)) then declare C1, C2 : Elmt_Id; begin C1 := First_Elmt (Discs); C2 := First_Elmt (Stored_Constraint (Derived_Type)); while Present (C1) and then Present (C2) loop if not Fully_Conformant_Expressions (Node (C1), Node (C2)) then Error_Msg_N ("not conformant with previous declaration", Node (C1)); end if; Next_Elmt (C1); Next_Elmt (C2); end loop; end; end if; end if; -- STEP 2b: No new discriminants, inherit discriminants if any else if Private_Extension then Set_Has_Unknown_Discriminants (Derived_Type, Has_Unknown_Discriminants (Parent_Type) or else Unknown_Discriminants_Present (N)); -- The partial view of the parent may have unknown discriminants, -- but if the full view has discriminants and the parent type is -- in scope they must be inherited. elsif Has_Unknown_Discriminants (Parent_Type) and then (not Has_Discriminants (Parent_Type) or else not In_Open_Scopes (Scope (Parent_Base))) then Set_Has_Unknown_Discriminants (Derived_Type); end if; if not Has_Unknown_Discriminants (Derived_Type) and then not Has_Unknown_Discriminants (Parent_Base) and then Has_Discriminants (Parent_Type) then Inherit_Discrims := True; Set_Has_Discriminants (Derived_Type, True); Set_Discriminant_Constraint (Derived_Type, Discriminant_Constraint (Parent_Base)); end if; -- The following test is true for private types (remember -- transformation 5. is not applied to those) and in an error -- situation. if Constraint_Present then Discs := Build_Discriminant_Constraints (Parent_Type, Indic); end if; -- For now mark a new derived type as constrained only if it has no -- discriminants. At the end of Build_Derived_Record_Type we properly -- set this flag in the case of private extensions. See comments in -- point 9. just before body of Build_Derived_Record_Type. Set_Is_Constrained (Derived_Type, not (Inherit_Discrims or else Has_Unknown_Discriminants (Derived_Type))); end if; -- STEP 3: initialize fields of derived type Set_Is_Tagged_Type (Derived_Type, Is_Tagged); Set_Stored_Constraint (Derived_Type, No_Elist); -- Ada 2005 (AI-251): Private type-declarations can implement interfaces -- but cannot be interfaces if not Private_Extension and then Ekind (Derived_Type) /= E_Private_Type and then Ekind (Derived_Type) /= E_Limited_Private_Type then if Interface_Present (Type_Def) then Analyze_Interface_Declaration (Derived_Type, Type_Def); end if; Set_Interfaces (Derived_Type, No_Elist); end if; -- Fields inherited from the Parent_Type Set_Has_Specified_Layout (Derived_Type, Has_Specified_Layout (Parent_Type)); Set_Is_Limited_Composite (Derived_Type, Is_Limited_Composite (Parent_Type)); Set_Is_Private_Composite (Derived_Type, Is_Private_Composite (Parent_Type)); if Is_Tagged_Type (Parent_Type) then Set_No_Tagged_Streams_Pragma (Derived_Type, No_Tagged_Streams_Pragma (Parent_Type)); end if; -- Fields inherited from the Parent_Base Set_Has_Controlled_Component (Derived_Type, Has_Controlled_Component (Parent_Base)); Set_Has_Non_Standard_Rep (Derived_Type, Has_Non_Standard_Rep (Parent_Base)); Set_Has_Primitive_Operations (Derived_Type, Has_Primitive_Operations (Parent_Base)); -- Set fields for private derived types if Is_Private_Type (Derived_Type) then Set_Depends_On_Private (Derived_Type, True); Set_Private_Dependents (Derived_Type, New_Elmt_List); end if; -- Inherit fields for non-private types. If this is the completion of a -- derivation from a private type, the parent itself is private and the -- attributes come from its full view, which must be present. if Is_Record_Type (Derived_Type) then declare Parent_Full : Entity_Id; begin if Is_Private_Type (Parent_Base) and then not Is_Record_Type (Parent_Base) then Parent_Full := Full_View (Parent_Base); else Parent_Full := Parent_Base; end if; Set_Component_Alignment (Derived_Type, Component_Alignment (Parent_Full)); Set_C_Pass_By_Copy (Derived_Type, C_Pass_By_Copy (Parent_Full)); Set_Has_Complex_Representation (Derived_Type, Has_Complex_Representation (Parent_Full)); -- For untagged types, inherit the layout by default to avoid -- costly changes of representation for type conversions. if not Is_Tagged then Set_Is_Packed (Derived_Type, Is_Packed (Parent_Full)); Set_No_Reordering (Derived_Type, No_Reordering (Parent_Full)); end if; end; end if; -- Initialize the list of primitive operations to an empty list, -- to cover tagged types as well as untagged types. For untagged -- types this is used either to analyze the call as legal when -- Extensions_Allowed is True, or to issue a better error message -- otherwise. Set_Direct_Primitive_Operations (Derived_Type, New_Elmt_List); -- Set fields for tagged types if Is_Tagged then -- All tagged types defined in Ada.Finalization are controlled if Chars (Scope (Derived_Type)) = Name_Finalization and then Chars (Scope (Scope (Derived_Type))) = Name_Ada and then Scope (Scope (Scope (Derived_Type))) = Standard_Standard then Set_Is_Controlled_Active (Derived_Type); else Set_Is_Controlled_Active (Derived_Type, Is_Controlled_Active (Parent_Base)); end if; -- Minor optimization: there is no need to generate the class-wide -- entity associated with an underlying record view. if not Is_Underlying_Record_View (Derived_Type) then Make_Class_Wide_Type (Derived_Type); end if; Set_Is_Abstract_Type (Derived_Type, Abstract_Present (Type_Def)); if Has_Discriminants (Derived_Type) and then Constraint_Present then Set_Stored_Constraint (Derived_Type, Expand_To_Stored_Constraint (Parent_Base, Discs)); end if; if Ada_Version >= Ada_2005 then declare Ifaces_List : Elist_Id; begin -- Checks rules 3.9.4 (13/2 and 14/2) if Comes_From_Source (Derived_Type) and then not Is_Private_Type (Derived_Type) and then Is_Interface (Parent_Type) and then not Is_Interface (Derived_Type) then if Is_Task_Interface (Parent_Type) then Error_Msg_N ("(Ada 2005) task type required (RM 3.9.4 (13.2))", Derived_Type); elsif Is_Protected_Interface (Parent_Type) then Error_Msg_N ("(Ada 2005) protected type required (RM 3.9.4 (14.2))", Derived_Type); end if; end if; -- Check ARM rules 3.9.4 (15/2), 9.1 (9.d/2) and 9.4 (11.d/2) Check_Interfaces (N, Type_Def); -- Ada 2005 (AI-251): Collect the list of progenitors that are -- not already in the parents. Collect_Interfaces (T => Derived_Type, Ifaces_List => Ifaces_List, Exclude_Parents => True); Set_Interfaces (Derived_Type, Ifaces_List); -- If the derived type is the anonymous type created for -- a declaration whose parent has a constraint, propagate -- the interface list to the source type. This must be done -- prior to the completion of the analysis of the source type -- because the components in the extension may contain current -- instances whose legality depends on some ancestor. if Is_Itype (Derived_Type) then declare Def : constant Node_Id := Associated_Node_For_Itype (Derived_Type); begin if Present (Def) and then Nkind (Def) = N_Full_Type_Declaration then Set_Interfaces (Defining_Identifier (Def), Ifaces_List); end if; end; end if; -- A type extension is automatically Ghost when one of its -- progenitors is Ghost (SPARK RM 6.9(9)). This property is -- also inherited when the parent type is Ghost, but this is -- done in Build_Derived_Type as the mechanism also handles -- untagged derivations. if Implements_Ghost_Interface (Derived_Type) then Set_Is_Ghost_Entity (Derived_Type); end if; end; end if; end if; -- STEP 4: Inherit components from the parent base and constrain them. -- Apply the second transformation described in point 6. above. if (not Is_Empty_Elmt_List (Discs) or else Inherit_Discrims) or else not Has_Discriminants (Parent_Type) or else not Is_Constrained (Parent_Type) then Constrs := Discs; else Constrs := Discriminant_Constraint (Parent_Type); end if; Assoc_List := Inherit_Components (N, Parent_Base, Derived_Type, Is_Tagged, Inherit_Discrims, Constrs); -- STEP 5a: Copy the parent record declaration for untagged types Set_Has_Implicit_Dereference (Derived_Type, Has_Implicit_Dereference (Parent_Type)); if not Is_Tagged then -- Discriminant_Constraint (Derived_Type) has been properly -- constructed. Save it and temporarily set it to Empty because we -- do not want the call to New_Copy_Tree below to mess this list. if Has_Discriminants (Derived_Type) then Save_Discr_Constr := Discriminant_Constraint (Derived_Type); Set_Discriminant_Constraint (Derived_Type, No_Elist); else Save_Discr_Constr := No_Elist; end if; -- Save the Etype field of Derived_Type. It is correctly set now, -- but the call to New_Copy tree may remap it to point to itself, -- which is not what we want. Ditto for the Next_Entity field. Save_Etype := Etype (Derived_Type); Save_Next_Entity := Next_Entity (Derived_Type); -- Assoc_List maps all stored discriminants in the Parent_Base to -- stored discriminants in the Derived_Type. It is fundamental that -- no types or itypes with discriminants other than the stored -- discriminants appear in the entities declared inside -- Derived_Type, since the back end cannot deal with it. New_Decl := New_Copy_Tree (Parent (Parent_Base), Map => Assoc_List, New_Sloc => Loc); Copy_Dimensions_Of_Components (Derived_Type); -- Restore the fields saved prior to the New_Copy_Tree call -- and compute the stored constraint. Set_Etype (Derived_Type, Save_Etype); Link_Entities (Derived_Type, Save_Next_Entity); if Has_Discriminants (Derived_Type) then Set_Discriminant_Constraint (Derived_Type, Save_Discr_Constr); Set_Stored_Constraint (Derived_Type, Expand_To_Stored_Constraint (Parent_Type, Discs)); Replace_Discriminants (Derived_Type, New_Decl); end if; -- Insert the new derived type declaration Rewrite (N, New_Decl); -- STEP 5b: Complete the processing for record extensions in generics -- There is no completion for record extensions declared in the -- parameter part of a generic, so we need to complete processing for -- these generic record extensions here. The Record_Type_Definition call -- will change the Ekind of the components from E_Void to E_Component. elsif Private_Extension and then Is_Generic_Type (Derived_Type) then Record_Type_Definition (Empty, Derived_Type); -- STEP 5c: Process the record extension for non private tagged types elsif not Private_Extension then Expand_Record_Extension (Derived_Type, Type_Def); -- Ada 2005 (AI-251): Addition of the Tag corresponding to all the -- implemented interfaces if we are in expansion mode if Expander_Active and then Has_Interfaces (Derived_Type) then Add_Interface_Tag_Components (N, Derived_Type); end if; -- Analyze the record extension Record_Type_Definition (Record_Extension_Part (Type_Def), Derived_Type); end if; End_Scope; -- Nothing else to do if there is an error in the derivation. -- An unusual case: the full view may be derived from a type in an -- instance, when the partial view was used illegally as an actual -- in that instance, leading to a circular definition. if Etype (Derived_Type) = Any_Type or else Etype (Parent_Type) = Derived_Type then return; end if; -- Set delayed freeze and then derive subprograms, we need to do -- this in this order so that derived subprograms inherit the -- derived freeze if necessary. Set_Has_Delayed_Freeze (Derived_Type); if Derive_Subps then Derive_Subprograms (Parent_Type, Derived_Type); end if; -- If we have a private extension which defines a constrained derived -- type mark as constrained here after we have derived subprograms. See -- comment on point 9. just above the body of Build_Derived_Record_Type. if Private_Extension and then Inherit_Discrims then if Constraint_Present and then not Is_Empty_Elmt_List (Discs) then Set_Is_Constrained (Derived_Type, True); Set_Discriminant_Constraint (Derived_Type, Discs); elsif Is_Constrained (Parent_Type) then Set_Is_Constrained (Derived_Type, True); Set_Discriminant_Constraint (Derived_Type, Discriminant_Constraint (Parent_Type)); end if; end if; -- Update the class-wide type, which shares the now-completed entity -- list with its specific type. In case of underlying record views, -- we do not generate the corresponding class wide entity. if Is_Tagged and then not Is_Underlying_Record_View (Derived_Type) then Set_First_Entity (Class_Wide_Type (Derived_Type), First_Entity (Derived_Type)); Set_Last_Entity (Class_Wide_Type (Derived_Type), Last_Entity (Derived_Type)); end if; Check_Function_Writable_Actuals (N); end Build_Derived_Record_Type; ------------------------ -- Build_Derived_Type -- ------------------------ procedure Build_Derived_Type (N : Node_Id; Parent_Type : Entity_Id; Derived_Type : Entity_Id; Is_Completion : Boolean; Derive_Subps : Boolean := True) is Parent_Base : constant Entity_Id := Base_Type (Parent_Type); begin -- Set common attributes if Ekind (Derived_Type) in Incomplete_Or_Private_Kind and then Ekind (Parent_Base) in Modular_Integer_Kind | Array_Kind then Reinit_Field_To_Zero (Derived_Type, F_Stored_Constraint); end if; Set_Scope (Derived_Type, Current_Scope); Set_Etype (Derived_Type, Parent_Base); Mutate_Ekind (Derived_Type, Ekind (Parent_Base)); Propagate_Concurrent_Flags (Derived_Type, Parent_Base); Set_Size_Info (Derived_Type, Parent_Type); Copy_RM_Size (To => Derived_Type, From => Parent_Type); Set_Is_Controlled_Active (Derived_Type, Is_Controlled_Active (Parent_Type)); Set_Disable_Controlled (Derived_Type, Disable_Controlled (Parent_Type)); Set_Is_Tagged_Type (Derived_Type, Is_Tagged_Type (Parent_Type)); Set_Is_Volatile (Derived_Type, Is_Volatile (Parent_Type)); if Is_Tagged_Type (Derived_Type) then Set_No_Tagged_Streams_Pragma (Derived_Type, No_Tagged_Streams_Pragma (Parent_Type)); end if; -- If the parent has primitive routines and may have not-seen-yet aspect -- specifications (e.g., a Pack pragma), then set the derived type link -- in order to later diagnose "early derivation" issues. If in different -- compilation units, then "early derivation" cannot be an issue (and we -- don't like interunit references that go in the opposite direction of -- semantic dependencies). if Has_Primitive_Operations (Parent_Type) and then Enclosing_Comp_Unit_Node (Parent_Type) = Enclosing_Comp_Unit_Node (Derived_Type) then Set_Derived_Type_Link (Parent_Base, Derived_Type); end if; -- If the parent type is a private subtype, the convention on the base -- type may be set in the private part, and not propagated to the -- subtype until later, so we obtain the convention from the base type. Set_Convention (Derived_Type, Convention (Parent_Base)); if Is_Tagged_Type (Derived_Type) and then Present (Class_Wide_Type (Derived_Type)) then Set_Convention (Class_Wide_Type (Derived_Type), Convention (Class_Wide_Type (Parent_Base))); end if; -- Set SSO default for record or array type if (Is_Array_Type (Derived_Type) or else Is_Record_Type (Derived_Type)) and then Is_Base_Type (Derived_Type) then Set_Default_SSO (Derived_Type); end if; -- A derived type inherits the Default_Initial_Condition pragma coming -- from any parent type within the derivation chain. if Has_DIC (Parent_Type) then Set_Has_Inherited_DIC (Derived_Type); end if; -- A derived type inherits any class-wide invariants coming from a -- parent type or an interface. Note that the invariant procedure of -- the parent type should not be inherited because the derived type may -- define invariants of its own. if not Is_Interface (Derived_Type) then if Has_Inherited_Invariants (Parent_Type) or else Has_Inheritable_Invariants (Parent_Type) then Set_Has_Inherited_Invariants (Derived_Type); elsif Is_Concurrent_Type (Derived_Type) or else Is_Tagged_Type (Derived_Type) then declare Iface : Entity_Id; Ifaces : Elist_Id; Iface_Elmt : Elmt_Id; begin Collect_Interfaces (T => Derived_Type, Ifaces_List => Ifaces, Exclude_Parents => True); if Present (Ifaces) then Iface_Elmt := First_Elmt (Ifaces); while Present (Iface_Elmt) loop Iface := Node (Iface_Elmt); if Has_Inheritable_Invariants (Iface) then Set_Has_Inherited_Invariants (Derived_Type); exit; end if; Next_Elmt (Iface_Elmt); end loop; end if; end; end if; end if; -- We similarly inherit predicates. Note that for scalar derived types -- the predicate is inherited from the first subtype, and not from its -- (anonymous) base type. if Has_Predicates (Parent_Type) or else Has_Predicates (First_Subtype (Parent_Type)) then Set_Has_Predicates (Derived_Type); end if; -- The derived type inherits representation clauses from the parent -- type, and from any interfaces. Inherit_Rep_Item_Chain (Derived_Type, Parent_Type); declare Iface : Node_Id := First (Abstract_Interface_List (Derived_Type)); begin while Present (Iface) loop Inherit_Rep_Item_Chain (Derived_Type, Entity (Iface)); Next (Iface); end loop; end; -- If the parent type has delayed rep aspects, then mark the derived -- type as possibly inheriting a delayed rep aspect. if Has_Delayed_Rep_Aspects (Parent_Type) then Set_May_Inherit_Delayed_Rep_Aspects (Derived_Type); end if; -- A derived type becomes Ghost when its parent type is also Ghost -- (SPARK RM 6.9(9)). Note that the Ghost-related attributes are not -- directly inherited because the Ghost policy in effect may differ. if Is_Ghost_Entity (Parent_Type) then Set_Is_Ghost_Entity (Derived_Type); end if; -- Type dependent processing case Ekind (Parent_Type) is when Numeric_Kind => Build_Derived_Numeric_Type (N, Parent_Type, Derived_Type); when Array_Kind => Build_Derived_Array_Type (N, Parent_Type, Derived_Type); when Class_Wide_Kind | E_Record_Subtype | E_Record_Type => Build_Derived_Record_Type (N, Parent_Type, Derived_Type, Derive_Subps); return; when Enumeration_Kind => Build_Derived_Enumeration_Type (N, Parent_Type, Derived_Type); when Access_Kind => Build_Derived_Access_Type (N, Parent_Type, Derived_Type); when Incomplete_Or_Private_Kind => Build_Derived_Private_Type (N, Parent_Type, Derived_Type, Is_Completion, Derive_Subps); -- For discriminated types, the derivation includes deriving -- primitive operations. For others it is done below. if Is_Tagged_Type (Parent_Type) or else Has_Discriminants (Parent_Type) or else (Present (Full_View (Parent_Type)) and then Has_Discriminants (Full_View (Parent_Type))) then return; end if; when Concurrent_Kind => Build_Derived_Concurrent_Type (N, Parent_Type, Derived_Type); when others => raise Program_Error; end case; -- Nothing more to do if some error occurred if Etype (Derived_Type) = Any_Type then return; end if; -- If not already set, initialize the derived type's list of primitive -- operations to an empty element list. if not Present (Direct_Primitive_Operations (Derived_Type)) then Set_Direct_Primitive_Operations (Derived_Type, New_Elmt_List); -- If Etype of the derived type is the base type (as opposed to -- a parent type) and doesn't have an associated list of primitive -- operations, then set the base type's primitive list to the -- derived type's list. The lists need to be shared in common -- between the two. if Etype (Derived_Type) = Base_Type (Derived_Type) and then not Present (Direct_Primitive_Operations (Etype (Derived_Type))) then Set_Direct_Primitive_Operations (Etype (Derived_Type), Direct_Primitive_Operations (Derived_Type)); end if; end if; -- Set delayed freeze and then derive subprograms, we need to do this -- in this order so that derived subprograms inherit the derived freeze -- if necessary. Set_Has_Delayed_Freeze (Derived_Type); if Derive_Subps then Derive_Subprograms (Parent_Type, Derived_Type); end if; Set_Has_Primitive_Operations (Base_Type (Derived_Type), Has_Primitive_Operations (Parent_Type)); end Build_Derived_Type; ----------------------- -- Build_Discriminal -- ----------------------- procedure Build_Discriminal (Discrim : Entity_Id) is D_Minal : Entity_Id; CR_Disc : Entity_Id; begin -- A discriminal has the same name as the discriminant D_Minal := Make_Defining_Identifier (Sloc (Discrim), Chars (Discrim)); Mutate_Ekind (D_Minal, E_In_Parameter); Set_Mechanism (D_Minal, Default_Mechanism); Set_Etype (D_Minal, Etype (Discrim)); Set_Scope (D_Minal, Current_Scope); Set_Parent (D_Minal, Parent (Discrim)); Set_Discriminal (Discrim, D_Minal); Set_Discriminal_Link (D_Minal, Discrim); -- For task types, build at once the discriminants of the corresponding -- record, which are needed if discriminants are used in entry defaults -- and in family bounds. if Is_Concurrent_Type (Current_Scope) or else Is_Limited_Type (Current_Scope) then CR_Disc := Make_Defining_Identifier (Sloc (Discrim), Chars (Discrim)); Mutate_Ekind (CR_Disc, E_In_Parameter); Set_Mechanism (CR_Disc, Default_Mechanism); Set_Etype (CR_Disc, Etype (Discrim)); Set_Scope (CR_Disc, Current_Scope); Set_Discriminal_Link (CR_Disc, Discrim); Set_CR_Discriminant (Discrim, CR_Disc); end if; end Build_Discriminal; ------------------------------------ -- Build_Discriminant_Constraints -- ------------------------------------ function Build_Discriminant_Constraints (T : Entity_Id; Def : Node_Id; Derived_Def : Boolean := False) return Elist_Id is C : constant Node_Id := Constraint (Def); Nb_Discr : constant Nat := Number_Discriminants (T); Discr_Expr : array (1 .. Nb_Discr) of Node_Id := (others => Empty); -- Saves the expression corresponding to a given discriminant in T function Pos_Of_Discr (T : Entity_Id; D : Entity_Id) return Nat; -- Return the Position number within array Discr_Expr of a discriminant -- D within the discriminant list of the discriminated type T. procedure Process_Discriminant_Expression (Expr : Node_Id; D : Entity_Id); -- If this is a discriminant constraint on a partial view, do not -- generate an overflow check on the discriminant expression. The check -- will be generated when constraining the full view. Otherwise the -- backend creates duplicate symbols for the temporaries corresponding -- to the expressions to be checked, causing spurious assembler errors. ------------------ -- Pos_Of_Discr -- ------------------ function Pos_Of_Discr (T : Entity_Id; D : Entity_Id) return Nat is Disc : Entity_Id; begin Disc := First_Discriminant (T); for J in Discr_Expr'Range loop if Disc = D then return J; end if; Next_Discriminant (Disc); end loop; -- Note: Since this function is called on discriminants that are -- known to belong to the discriminated type, falling through the -- loop with no match signals an internal compiler error. raise Program_Error; end Pos_Of_Discr; ------------------------------------- -- Process_Discriminant_Expression -- ------------------------------------- procedure Process_Discriminant_Expression (Expr : Node_Id; D : Entity_Id) is BDT : constant Entity_Id := Base_Type (Etype (D)); begin -- If this is a discriminant constraint on a partial view, do -- not generate an overflow on the discriminant expression. The -- check will be generated when constraining the full view. if Is_Private_Type (T) and then Present (Full_View (T)) then Analyze_And_Resolve (Expr, BDT, Suppress => Overflow_Check); else Analyze_And_Resolve (Expr, BDT); end if; end Process_Discriminant_Expression; -- Declarations local to Build_Discriminant_Constraints Discr : Entity_Id; E : Entity_Id; Elist : constant Elist_Id := New_Elmt_List; Constr : Node_Id; Expr : Node_Id; Id : Node_Id; Position : Nat; Found : Boolean; Discrim_Present : Boolean := False; -- Start of processing for Build_Discriminant_Constraints begin -- The following loop will process positional associations only. -- For a positional association, the (single) discriminant is -- implicitly specified by position, in textual order (RM 3.7.2). Discr := First_Discriminant (T); Constr := First (Constraints (C)); for D in Discr_Expr'Range loop exit when Nkind (Constr) = N_Discriminant_Association; if No (Constr) then Error_Msg_N ("too few discriminants given in constraint", C); return New_Elmt_List; elsif Nkind (Constr) = N_Range or else (Nkind (Constr) = N_Attribute_Reference and then Attribute_Name (Constr) = Name_Range) then Error_Msg_N ("a range is not a valid discriminant constraint", Constr); Discr_Expr (D) := Error; elsif Nkind (Constr) = N_Subtype_Indication then Error_Msg_N ("a subtype indication is not a valid discriminant constraint", Constr); Discr_Expr (D) := Error; else Process_Discriminant_Expression (Constr, Discr); Discr_Expr (D) := Constr; end if; Next_Discriminant (Discr); Next (Constr); end loop; if No (Discr) and then Present (Constr) then Error_Msg_N ("too many discriminants given in constraint", Constr); return New_Elmt_List; end if; -- Named associations can be given in any order, but if both positional -- and named associations are used in the same discriminant constraint, -- then positional associations must occur first, at their normal -- position. Hence once a named association is used, the rest of the -- discriminant constraint must use only named associations. while Present (Constr) loop -- Positional association forbidden after a named association if Nkind (Constr) /= N_Discriminant_Association then Error_Msg_N ("positional association follows named one", Constr); return New_Elmt_List; -- Otherwise it is a named association else -- E records the type of the discriminants in the named -- association. All the discriminants specified in the same name -- association must have the same type. E := Empty; -- Search the list of discriminants in T to see if the simple name -- given in the constraint matches any of them. Id := First (Selector_Names (Constr)); while Present (Id) loop Found := False; -- If Original_Discriminant is present, we are processing a -- generic instantiation and this is an instance node. We need -- to find the name of the corresponding discriminant in the -- actual record type T and not the name of the discriminant in -- the generic formal. Example: -- generic -- type G (D : int) is private; -- package P is -- subtype W is G (D => 1); -- end package; -- type Rec (X : int) is record ... end record; -- package Q is new P (G => Rec); -- At the point of the instantiation, formal type G is Rec -- and therefore when reanalyzing "subtype W is G (D => 1);" -- which really looks like "subtype W is Rec (D => 1);" at -- the point of instantiation, we want to find the discriminant -- that corresponds to D in Rec, i.e. X. if Present (Original_Discriminant (Id)) and then In_Instance then Discr := Find_Corresponding_Discriminant (Id, T); Found := True; else Discr := First_Discriminant (T); while Present (Discr) loop if Chars (Discr) = Chars (Id) then Found := True; exit; end if; Next_Discriminant (Discr); end loop; if not Found then Error_Msg_N ("& does not match any discriminant", Id); return New_Elmt_List; -- If the parent type is a generic formal, preserve the -- name of the discriminant for subsequent instances. -- see comment at the beginning of this if statement. elsif Is_Generic_Type (Root_Type (T)) then Set_Original_Discriminant (Id, Discr); end if; end if; Position := Pos_Of_Discr (T, Discr); if Present (Discr_Expr (Position)) then Error_Msg_N ("duplicate constraint for discriminant&", Id); else -- Each discriminant specified in the same named association -- must be associated with a separate copy of the -- corresponding expression. if Present (Next (Id)) then Expr := New_Copy_Tree (Expression (Constr)); Set_Parent (Expr, Parent (Expression (Constr))); else Expr := Expression (Constr); end if; Discr_Expr (Position) := Expr; Process_Discriminant_Expression (Expr, Discr); end if; -- A discriminant association with more than one discriminant -- name is only allowed if the named discriminants are all of -- the same type (RM 3.7.1(8)). if E = Empty then E := Base_Type (Etype (Discr)); elsif Base_Type (Etype (Discr)) /= E then Error_Msg_N ("all discriminants in an association " & "must have the same type", Id); end if; Next (Id); end loop; end if; Next (Constr); end loop; -- A discriminant constraint must provide exactly one value for each -- discriminant of the type (RM 3.7.1(8)). for J in Discr_Expr'Range loop if No (Discr_Expr (J)) then Error_Msg_N ("too few discriminants given in constraint", C); return New_Elmt_List; end if; end loop; -- Determine if there are discriminant expressions in the constraint for J in Discr_Expr'Range loop if Denotes_Discriminant (Discr_Expr (J), Check_Concurrent => True) then Discrim_Present := True; exit; end if; end loop; -- Build an element list consisting of the expressions given in the -- discriminant constraint and apply the appropriate checks. The list -- is constructed after resolving any named discriminant associations -- and therefore the expressions appear in the textual order of the -- discriminants. Discr := First_Discriminant (T); for J in Discr_Expr'Range loop if Discr_Expr (J) /= Error then Append_Elmt (Discr_Expr (J), Elist); -- If any of the discriminant constraints is given by a -- discriminant and we are in a derived type declaration we -- have a discriminant renaming. Establish link between new -- and old discriminant. The new discriminant has an implicit -- dereference if the old one does. if Denotes_Discriminant (Discr_Expr (J)) then if Derived_Def then declare New_Discr : constant Entity_Id := Entity (Discr_Expr (J)); begin Set_Corresponding_Discriminant (New_Discr, Discr); Set_Has_Implicit_Dereference (New_Discr, Has_Implicit_Dereference (Discr)); end; end if; -- Force the evaluation of non-discriminant expressions. -- If we have found a discriminant in the constraint 3.4(26) -- and 3.8(18) demand that no range checks are performed are -- after evaluation. If the constraint is for a component -- definition that has a per-object constraint, expressions are -- evaluated but not checked either. In all other cases perform -- a range check. else if Discrim_Present then null; elsif Parent_Kind (Parent (Def)) = N_Component_Declaration and then Has_Per_Object_Constraint (Defining_Identifier (Parent (Parent (Def)))) then null; elsif Is_Access_Type (Etype (Discr)) then Apply_Constraint_Check (Discr_Expr (J), Etype (Discr)); else Apply_Range_Check (Discr_Expr (J), Etype (Discr)); end if; -- If the value of the discriminant may be visible in -- another unit or child unit, create an external name -- for it. We use the name of the object or component -- that carries the discriminated subtype. The code -- below may generate external symbols for the discriminant -- expression when not strictly needed, which is harmless. if Expander_Active and then Comes_From_Source (Def) and then not Is_Subprogram (Current_Scope) then declare Id : Entity_Id := Empty; begin if Nkind (Parent (Def)) = N_Object_Declaration then Id := Defining_Identifier (Parent (Def)); elsif Nkind (Parent (Def)) = N_Component_Definition and then Nkind (Parent (Parent (Def))) = N_Component_Declaration then Id := Defining_Identifier (Parent (Parent (Def))); end if; if Present (Id) then Force_Evaluation ( Discr_Expr (J), Related_Id => Id, Discr_Number => J); else Force_Evaluation (Discr_Expr (J)); end if; end; else Force_Evaluation (Discr_Expr (J)); end if; end if; -- Check that the designated type of an access discriminant's -- expression is not a class-wide type unless the discriminant's -- designated type is also class-wide. if Ekind (Etype (Discr)) = E_Anonymous_Access_Type and then not Is_Class_Wide_Type (Designated_Type (Etype (Discr))) and then Etype (Discr_Expr (J)) /= Any_Type and then Is_Class_Wide_Type (Designated_Type (Etype (Discr_Expr (J)))) then Wrong_Type (Discr_Expr (J), Etype (Discr)); elsif Is_Access_Type (Etype (Discr)) and then not Is_Access_Constant (Etype (Discr)) and then Is_Access_Type (Etype (Discr_Expr (J))) and then Is_Access_Constant (Etype (Discr_Expr (J))) then Error_Msg_NE ("constraint for discriminant& must be access to variable", Def, Discr); end if; end if; Next_Discriminant (Discr); end loop; return Elist; end Build_Discriminant_Constraints; --------------------------------- -- Build_Discriminated_Subtype -- --------------------------------- procedure Build_Discriminated_Subtype (T : Entity_Id; Def_Id : Entity_Id; Elist : Elist_Id; Related_Nod : Node_Id; For_Access : Boolean := False) is Has_Discrs : constant Boolean := Has_Discriminants (T); Constrained : constant Boolean := (Has_Discrs and then not Is_Empty_Elmt_List (Elist) and then not Is_Class_Wide_Type (T)) or else Is_Constrained (T); begin if Ekind (T) = E_Record_Type then Mutate_Ekind (Def_Id, E_Record_Subtype); -- Inherit preelaboration flag from base, for types for which it -- may have been set: records, private types, protected types. Set_Known_To_Have_Preelab_Init (Def_Id, Known_To_Have_Preelab_Init (T)); elsif Ekind (T) = E_Task_Type then Mutate_Ekind (Def_Id, E_Task_Subtype); elsif Ekind (T) = E_Protected_Type then Mutate_Ekind (Def_Id, E_Protected_Subtype); Set_Known_To_Have_Preelab_Init (Def_Id, Known_To_Have_Preelab_Init (T)); elsif Is_Private_Type (T) then Mutate_Ekind (Def_Id, Subtype_Kind (Ekind (T))); Set_Known_To_Have_Preelab_Init (Def_Id, Known_To_Have_Preelab_Init (T)); -- Private subtypes may have private dependents Set_Private_Dependents (Def_Id, New_Elmt_List); elsif Is_Class_Wide_Type (T) then Mutate_Ekind (Def_Id, E_Class_Wide_Subtype); else -- Incomplete type. Attach subtype to list of dependents, to be -- completed with full view of parent type, unless is it the -- designated subtype of a record component within an init_proc. -- This last case arises for a component of an access type whose -- designated type is incomplete (e.g. a Taft Amendment type). -- The designated subtype is within an inner scope, and needs no -- elaboration, because only the access type is needed in the -- initialization procedure. if Ekind (T) = E_Incomplete_Type then Mutate_Ekind (Def_Id, E_Incomplete_Subtype); else Mutate_Ekind (Def_Id, Ekind (T)); end if; if For_Access and then Within_Init_Proc then null; else Append_Elmt (Def_Id, Private_Dependents (T)); end if; end if; Set_Etype (Def_Id, T); Reinit_Size_Align (Def_Id); Set_Has_Discriminants (Def_Id, Has_Discrs); Set_Is_Constrained (Def_Id, Constrained); Set_First_Entity (Def_Id, First_Entity (T)); Set_Last_Entity (Def_Id, Last_Entity (T)); Set_Has_Implicit_Dereference (Def_Id, Has_Implicit_Dereference (T)); Set_Has_Pragma_Unreferenced_Objects (Def_Id, Has_Pragma_Unreferenced_Objects (T)); -- If the subtype is the completion of a private declaration, there may -- have been representation clauses for the partial view, and they must -- be preserved. Build_Derived_Type chains the inherited clauses with -- the ones appearing on the extension. If this comes from a subtype -- declaration, all clauses are inherited. if No (First_Rep_Item (Def_Id)) then Set_First_Rep_Item (Def_Id, First_Rep_Item (T)); end if; if Is_Tagged_Type (T) then Set_Is_Tagged_Type (Def_Id); Set_No_Tagged_Streams_Pragma (Def_Id, No_Tagged_Streams_Pragma (T)); Make_Class_Wide_Type (Def_Id); end if; Set_Stored_Constraint (Def_Id, No_Elist); if Has_Discrs then Set_Discriminant_Constraint (Def_Id, Elist); Set_Stored_Constraint_From_Discriminant_Constraint (Def_Id); end if; if Is_Tagged_Type (T) then -- Ada 2005 (AI-251): In case of concurrent types we inherit the -- concurrent record type (which has the list of primitive -- operations). if Ada_Version >= Ada_2005 and then Is_Concurrent_Type (T) then Set_Corresponding_Record_Type (Def_Id, Corresponding_Record_Type (T)); else Set_Direct_Primitive_Operations (Def_Id, Direct_Primitive_Operations (T)); end if; Set_Is_Abstract_Type (Def_Id, Is_Abstract_Type (T)); end if; -- Subtypes introduced by component declarations do not need to be -- marked as delayed, and do not get freeze nodes, because the semantics -- verifies that the parents of the subtypes are frozen before the -- enclosing record is frozen. if not Is_Type (Scope (Def_Id)) then Set_Depends_On_Private (Def_Id, Depends_On_Private (T)); if Is_Private_Type (T) and then Present (Full_View (T)) then Conditional_Delay (Def_Id, Full_View (T)); else Conditional_Delay (Def_Id, T); end if; end if; if Is_Record_Type (T) then Set_Is_Limited_Record (Def_Id, Is_Limited_Record (T)); if Has_Discrs and then not Is_Empty_Elmt_List (Elist) and then not For_Access then Create_Constrained_Components (Def_Id, Related_Nod, T, Elist); elsif not Is_Private_Type (T) then Set_Cloned_Subtype (Def_Id, T); end if; end if; end Build_Discriminated_Subtype; --------------------------- -- Build_Itype_Reference -- --------------------------- procedure Build_Itype_Reference (Ityp : Entity_Id; Nod : Node_Id) is IR : constant Node_Id := Make_Itype_Reference (Sloc (Nod)); begin -- Itype references are only created for use by the back-end if Inside_A_Generic then return; else Set_Itype (IR, Ityp); -- If Nod is a library unit entity, then Insert_After won't work, -- because Nod is not a member of any list. Therefore, we use -- Add_Global_Declaration in this case. This can happen if we have a -- build-in-place library function, child unit or not. if (Nkind (Nod) in N_Entity and then Is_Compilation_Unit (Nod)) or else (Nkind (Nod) in N_Defining_Program_Unit_Name | N_Subprogram_Declaration and then Is_Compilation_Unit (Defining_Entity (Nod))) then Add_Global_Declaration (IR); else Insert_After (Nod, IR); end if; end if; end Build_Itype_Reference; ------------------------ -- Build_Scalar_Bound -- ------------------------ function Build_Scalar_Bound (Bound : Node_Id; Par_T : Entity_Id; Der_T : Entity_Id) return Node_Id is New_Bound : Entity_Id; begin -- Note: not clear why this is needed, how can the original bound -- be unanalyzed at this point? and if it is, what business do we -- have messing around with it? and why is the base type of the -- parent type the right type for the resolution. It probably is -- not. It is OK for the new bound we are creating, but not for -- the old one??? Still if it never happens, no problem. Analyze_And_Resolve (Bound, Base_Type (Par_T)); if Nkind (Bound) in N_Integer_Literal | N_Real_Literal then New_Bound := New_Copy (Bound); Set_Etype (New_Bound, Der_T); Set_Analyzed (New_Bound); elsif Is_Entity_Name (Bound) then New_Bound := OK_Convert_To (Der_T, New_Copy (Bound)); -- The following is almost certainly wrong. What business do we have -- relocating a node (Bound) that is presumably still attached to -- the tree elsewhere??? else New_Bound := OK_Convert_To (Der_T, Relocate_Node (Bound)); end if; Set_Etype (New_Bound, Der_T); return New_Bound; end Build_Scalar_Bound; ------------------------------- -- Check_Abstract_Overriding -- ------------------------------- procedure Check_Abstract_Overriding (T : Entity_Id) is Alias_Subp : Entity_Id; Elmt : Elmt_Id; Op_List : Elist_Id; Subp : Entity_Id; Type_Def : Node_Id; procedure Check_Pragma_Implemented (Subp : Entity_Id); -- Ada 2012 (AI05-0030): Subprogram Subp overrides an interface routine -- which has pragma Implemented already set. Check whether Subp's entity -- kind conforms to the implementation kind of the overridden routine. procedure Check_Pragma_Implemented (Subp : Entity_Id; Iface_Subp : Entity_Id); -- Ada 2012 (AI05-0030): Subprogram Subp overrides interface routine -- Iface_Subp and both entities have pragma Implemented already set on -- them. Check whether the two implementation kinds are conforming. procedure Inherit_Pragma_Implemented (Subp : Entity_Id; Iface_Subp : Entity_Id); -- Ada 2012 (AI05-0030): Interface primitive Subp overrides interface -- subprogram Iface_Subp which has been marked by pragma Implemented. -- Propagate the implementation kind of Iface_Subp to Subp. ------------------------------ -- Check_Pragma_Implemented -- ------------------------------ procedure Check_Pragma_Implemented (Subp : Entity_Id) is Iface_Alias : constant Entity_Id := Interface_Alias (Subp); Impl_Kind : constant Name_Id := Implementation_Kind (Iface_Alias); Subp_Alias : constant Entity_Id := Alias (Subp); Contr_Typ : Entity_Id; Impl_Subp : Entity_Id; begin -- Subp must have an alias since it is a hidden entity used to link -- an interface subprogram to its overriding counterpart. pragma Assert (Present (Subp_Alias)); -- Handle aliases to synchronized wrappers Impl_Subp := Subp_Alias; if Is_Primitive_Wrapper (Impl_Subp) then Impl_Subp := Wrapped_Entity (Impl_Subp); end if; -- Extract the type of the controlling formal Contr_Typ := Etype (First_Formal (Subp_Alias)); if Is_Concurrent_Record_Type (Contr_Typ) then Contr_Typ := Corresponding_Concurrent_Type (Contr_Typ); end if; -- An interface subprogram whose implementation kind is By_Entry must -- be implemented by an entry. if Impl_Kind = Name_By_Entry and then Ekind (Impl_Subp) /= E_Entry then Error_Msg_Node_2 := Iface_Alias; Error_Msg_NE ("type & must implement abstract subprogram & with an entry", Subp_Alias, Contr_Typ); elsif Impl_Kind = Name_By_Protected_Procedure then -- An interface subprogram whose implementation kind is By_ -- Protected_Procedure cannot be implemented by a primitive -- procedure of a task type. if Ekind (Contr_Typ) /= E_Protected_Type then Error_Msg_Node_2 := Contr_Typ; Error_Msg_NE ("interface subprogram & cannot be implemented by a " & "primitive procedure of task type &", Subp_Alias, Iface_Alias); -- An interface subprogram whose implementation kind is By_ -- Protected_Procedure must be implemented by a procedure. elsif Ekind (Impl_Subp) /= E_Procedure then Error_Msg_Node_2 := Iface_Alias; Error_Msg_NE ("type & must implement abstract subprogram & with a " & "procedure", Subp_Alias, Contr_Typ); elsif Present (Get_Rep_Pragma (Impl_Subp, Name_Implemented)) and then Implementation_Kind (Impl_Subp) /= Impl_Kind then Error_Msg_Name_1 := Impl_Kind; Error_Msg_N ("overriding operation& must have synchronization%", Subp_Alias); end if; -- If primitive has Optional synchronization, overriding operation -- must match if it has an explicit synchronization. elsif Present (Get_Rep_Pragma (Impl_Subp, Name_Implemented)) and then Implementation_Kind (Impl_Subp) /= Impl_Kind then Error_Msg_Name_1 := Impl_Kind; Error_Msg_N ("overriding operation& must have synchronization%", Subp_Alias); end if; end Check_Pragma_Implemented; ------------------------------ -- Check_Pragma_Implemented -- ------------------------------ procedure Check_Pragma_Implemented (Subp : Entity_Id; Iface_Subp : Entity_Id) is Iface_Kind : constant Name_Id := Implementation_Kind (Iface_Subp); Subp_Kind : constant Name_Id := Implementation_Kind (Subp); begin -- Ada 2012 (AI05-0030): The implementation kinds of an overridden -- and overriding subprogram are different. In general this is an -- error except when the implementation kind of the overridden -- subprograms is By_Any or Optional. if Iface_Kind /= Subp_Kind and then Iface_Kind /= Name_By_Any and then Iface_Kind /= Name_Optional then if Iface_Kind = Name_By_Entry then Error_Msg_N ("incompatible implementation kind, overridden subprogram " & "is marked By_Entry", Subp); else Error_Msg_N ("incompatible implementation kind, overridden subprogram " & "is marked By_Protected_Procedure", Subp); end if; end if; end Check_Pragma_Implemented; -------------------------------- -- Inherit_Pragma_Implemented -- -------------------------------- procedure Inherit_Pragma_Implemented (Subp : Entity_Id; Iface_Subp : Entity_Id) is Iface_Kind : constant Name_Id := Implementation_Kind (Iface_Subp); Loc : constant Source_Ptr := Sloc (Subp); Impl_Prag : Node_Id; begin -- Since the implementation kind is stored as a representation item -- rather than a flag, create a pragma node. Impl_Prag := Make_Pragma (Loc, Chars => Name_Implemented, Pragma_Argument_Associations => New_List ( Make_Pragma_Argument_Association (Loc, Expression => New_Occurrence_Of (Subp, Loc)), Make_Pragma_Argument_Association (Loc, Expression => Make_Identifier (Loc, Iface_Kind)))); -- The pragma doesn't need to be analyzed because it is internally -- built. It is safe to directly register it as a rep item since we -- are only interested in the characters of the implementation kind. Record_Rep_Item (Subp, Impl_Prag); end Inherit_Pragma_Implemented; -- Start of processing for Check_Abstract_Overriding begin Op_List := Primitive_Operations (T); -- Loop to check primitive operations Elmt := First_Elmt (Op_List); while Present (Elmt) loop Subp := Node (Elmt); Alias_Subp := Alias (Subp); -- Inherited subprograms are identified by the fact that they do not -- come from source, and the associated source location is the -- location of the first subtype of the derived type. -- Ada 2005 (AI-228): Apply the rules of RM-3.9.3(6/2) for -- subprograms that "require overriding". -- Special exception, do not complain about failure to override the -- stream routines _Input and _Output, as well as the primitive -- operations used in dispatching selects since we always provide -- automatic overridings for these subprograms. -- The partial view of T may have been a private extension, for -- which inherited functions dispatching on result are abstract. -- If the full view is a null extension, there is no need for -- overriding in Ada 2005, but wrappers need to be built for them -- (see exp_ch3, Build_Controlling_Function_Wrappers). if Is_Null_Extension (T) and then Has_Controlling_Result (Subp) and then Ada_Version >= Ada_2005 and then Present (Alias_Subp) and then not Comes_From_Source (Subp) and then not Is_Abstract_Subprogram (Alias_Subp) and then not Is_Access_Type (Etype (Subp)) then null; -- Ada 2005 (AI-251): Internal entities of interfaces need no -- processing because this check is done with the aliased -- entity elsif Present (Interface_Alias (Subp)) then null; -- AI12-0042: Test for rule in 7.3.2(6.1/4), that requires overriding -- of a visible private primitive inherited from an ancestor with -- the aspect Type_Invariant'Class, unless the inherited primitive -- is abstract. elsif not Is_Abstract_Subprogram (Subp) and then not Comes_From_Source (Subp) -- An inherited subprogram and then Requires_Overriding (Subp) and then Present (Alias_Subp) and then Has_Invariants (Etype (T)) and then Present (Get_Pragma (Etype (T), Pragma_Invariant)) and then Class_Present (Get_Pragma (Etype (T), Pragma_Invariant)) and then Is_Private_Primitive (Alias_Subp) then Error_Msg_NE ("inherited private primitive & must be overridden", T, Subp); Error_Msg_N ("\because ancestor type has 'Type_'Invariant''Class " & "(RM 7.3.2(6.1))", T); elsif (Is_Abstract_Subprogram (Subp) or else Requires_Overriding (Subp) or else (Has_Controlling_Result (Subp) and then Present (Alias_Subp) and then not Comes_From_Source (Subp) and then Sloc (Subp) = Sloc (First_Subtype (T)))) and then not Is_TSS (Subp, TSS_Stream_Input) and then not Is_TSS (Subp, TSS_Stream_Output) and then not Is_Abstract_Type (T) and then not Is_Predefined_Interface_Primitive (Subp) -- Ada 2005 (AI-251): Do not consider hidden entities associated -- with abstract interface types because the check will be done -- with the aliased entity (otherwise we generate a duplicated -- error message). and then not Present (Interface_Alias (Subp)) then if Present (Alias_Subp) then -- Only perform the check for a derived subprogram when the -- type has an explicit record extension. This avoids incorrect -- flagging of abstract subprograms for the case of a type -- without an extension that is derived from a formal type -- with a tagged actual (can occur within a private part). -- Ada 2005 (AI-391): In the case of an inherited function with -- a controlling result of the type, the rule does not apply if -- the type is a null extension (unless the parent function -- itself is abstract, in which case the function must still be -- be overridden). The expander will generate an overriding -- wrapper function calling the parent subprogram (see -- Exp_Ch3.Make_Controlling_Wrapper_Functions). Type_Def := Type_Definition (Parent (T)); if Nkind (Type_Def) = N_Derived_Type_Definition and then Present (Record_Extension_Part (Type_Def)) and then (Ada_Version < Ada_2005 or else not Is_Null_Extension (T) or else Ekind (Subp) = E_Procedure or else not Has_Controlling_Result (Subp) or else Is_Abstract_Subprogram (Alias_Subp) or else Requires_Overriding (Subp) or else Is_Access_Type (Etype (Subp))) then -- Avoid reporting error in case of abstract predefined -- primitive inherited from interface type because the -- body of internally generated predefined primitives -- of tagged types are generated later by Freeze_Type if Is_Interface (Root_Type (T)) and then Is_Abstract_Subprogram (Subp) and then Is_Predefined_Dispatching_Operation (Subp) and then not Comes_From_Source (Ultimate_Alias (Subp)) then null; -- A null extension is not obliged to override an inherited -- procedure subject to pragma Extensions_Visible with value -- False and at least one controlling OUT parameter -- (SPARK RM 6.1.7(6)). elsif Is_Null_Extension (T) and then Is_EVF_Procedure (Subp) then null; -- Subprogram renamings cannot be overridden elsif Comes_From_Source (Subp) and then Present (Alias (Subp)) then null; -- Skip reporting the error on Ada 2022 only subprograms -- that require overriding if we are not in Ada 2022 mode. elsif Ada_Version < Ada_2022 and then Requires_Overriding (Subp) and then Is_Ada_2022_Only (Ultimate_Alias (Subp)) then null; else Error_Msg_NE ("type must be declared abstract or & overridden", T, Subp); -- Traverse the whole chain of aliased subprograms to -- complete the error notification. This is especially -- useful for traceability of the chain of entities when -- the subprogram corresponds with an interface -- subprogram (which may be defined in another package). if Present (Alias_Subp) then declare E : Entity_Id; begin E := Subp; while Present (Alias (E)) loop -- Avoid reporting redundant errors on entities -- inherited from interfaces if Sloc (E) /= Sloc (T) then Error_Msg_Sloc := Sloc (E); Error_Msg_NE ("\& has been inherited #", T, Subp); end if; E := Alias (E); end loop; Error_Msg_Sloc := Sloc (E); -- AI05-0068: report if there is an overriding -- non-abstract subprogram that is invisible. if Is_Hidden (E) and then not Is_Abstract_Subprogram (E) then Error_Msg_NE ("\& subprogram# is not visible", T, Subp); -- Clarify the case where a non-null extension must -- override inherited procedure subject to pragma -- Extensions_Visible with value False and at least -- one controlling OUT param. elsif Is_EVF_Procedure (E) then Error_Msg_NE ("\& # is subject to Extensions_Visible False", T, Subp); else Error_Msg_NE ("\& has been inherited from subprogram #", T, Subp); end if; end; end if; end if; -- Ada 2005 (AI-345): Protected or task type implementing -- abstract interfaces. elsif Is_Concurrent_Record_Type (T) and then Present (Interfaces (T)) then -- There is no need to check here RM 9.4(11.9/3) since we -- are processing the corresponding record type and the -- mode of the overriding subprograms was verified by -- Check_Conformance when the corresponding concurrent -- type declaration was analyzed. Error_Msg_NE ("interface subprogram & must be overridden", T, Subp); -- Examine primitive operations of synchronized type to find -- homonyms that have the wrong profile. declare Prim : Entity_Id; begin Prim := First_Entity (Corresponding_Concurrent_Type (T)); while Present (Prim) loop if Chars (Prim) = Chars (Subp) then Error_Msg_NE ("profile is not type conformant with prefixed " & "view profile of inherited operation&", Prim, Subp); end if; Next_Entity (Prim); end loop; end; end if; else Error_Msg_Node_2 := T; Error_Msg_N ("abstract subprogram& not allowed for type&", Subp); -- Also post unconditional warning on the type (unconditional -- so that if there are more than one of these cases, we get -- them all, and not just the first one). Error_Msg_Node_2 := Subp; Error_Msg_N ("nonabstract type& has abstract subprogram&!", T); end if; -- A subprogram subject to pragma Extensions_Visible with value -- "True" cannot override a subprogram subject to the same pragma -- with value "False" (SPARK RM 6.1.7(5)). elsif Extensions_Visible_Status (Subp) = Extensions_Visible_True and then Present (Overridden_Operation (Subp)) and then Extensions_Visible_Status (Overridden_Operation (Subp)) = Extensions_Visible_False then Error_Msg_Sloc := Sloc (Overridden_Operation (Subp)); Error_Msg_N ("subprogram & with Extensions_Visible True cannot override " & "subprogram # with Extensions_Visible False", Subp); end if; -- Ada 2012 (AI05-0030): Perform checks related to pragma Implemented -- Subp is an expander-generated procedure which maps an interface -- alias to a protected wrapper. The interface alias is flagged by -- pragma Implemented. Ensure that Subp is a procedure when the -- implementation kind is By_Protected_Procedure or an entry when -- By_Entry. if Ada_Version >= Ada_2012 and then Is_Hidden (Subp) and then Present (Interface_Alias (Subp)) and then Has_Rep_Pragma (Interface_Alias (Subp), Name_Implemented) then Check_Pragma_Implemented (Subp); end if; -- Subp is an interface primitive which overrides another interface -- primitive marked with pragma Implemented. if Ada_Version >= Ada_2012 and then Present (Overridden_Operation (Subp)) and then Has_Rep_Pragma (Overridden_Operation (Subp), Name_Implemented) then -- If the overriding routine is also marked by Implemented, check -- that the two implementation kinds are conforming. if Has_Rep_Pragma (Subp, Name_Implemented) then Check_Pragma_Implemented (Subp => Subp, Iface_Subp => Overridden_Operation (Subp)); -- Otherwise the overriding routine inherits the implementation -- kind from the overridden subprogram. else Inherit_Pragma_Implemented (Subp => Subp, Iface_Subp => Overridden_Operation (Subp)); end if; end if; -- Ada 2005 (AI95-0414) and Ada 2022 (AI12-0269): Diagnose failure to -- match No_Return in parent, but do it unconditionally in Ada 95 too -- for procedures, since this is our pragma. if Present (Overridden_Operation (Subp)) and then No_Return (Overridden_Operation (Subp)) then -- If the subprogram is a renaming, check that the renamed -- subprogram is No_Return. if Present (Renamed_Or_Alias (Subp)) then if not No_Return (Renamed_Or_Alias (Subp)) then Error_Msg_NE ("subprogram & must be No_Return", Subp, Renamed_Or_Alias (Subp)); Error_Msg_N ("\since renaming & overrides No_Return " & "subprogram (RM 6.5.1(6/2))", Subp); end if; -- Make sure that the subprogram itself is No_Return. elsif not No_Return (Subp) then Error_Msg_N ("overriding subprogram & must be No_Return", Subp); Error_Msg_N ("\since overridden subprogram is No_Return (RM 6.5.1(6/2))", Subp); end if; end if; -- If the operation is a wrapper for a synchronized primitive, it -- may be called indirectly through a dispatching select. We assume -- that it will be referenced elsewhere indirectly, and suppress -- warnings about an unused entity. if Is_Primitive_Wrapper (Subp) and then Present (Wrapped_Entity (Subp)) then Set_Referenced (Wrapped_Entity (Subp)); end if; Next_Elmt (Elmt); end loop; end Check_Abstract_Overriding; ------------------------------------------------ -- Check_Access_Discriminant_Requires_Limited -- ------------------------------------------------ procedure Check_Access_Discriminant_Requires_Limited (D : Node_Id; Loc : Node_Id) is begin -- A discriminant_specification for an access discriminant shall appear -- only in the declaration for a task or protected type, or for a type -- with the reserved word 'limited' in its definition or in one of its -- ancestors (RM 3.7(10)). -- AI-0063: The proper condition is that type must be immutably limited, -- or else be a partial view. if Nkind (Discriminant_Type (D)) = N_Access_Definition then if Is_Limited_View (Current_Scope) or else (Nkind (Parent (Current_Scope)) = N_Private_Type_Declaration and then Limited_Present (Parent (Current_Scope))) then null; else Error_Msg_N ("access discriminants allowed only for limited types", Loc); end if; end if; end Check_Access_Discriminant_Requires_Limited; ----------------------------------- -- Check_Aliased_Component_Types -- ----------------------------------- procedure Check_Aliased_Component_Types (T : Entity_Id) is C : Entity_Id; begin -- ??? Also need to check components of record extensions, but not -- components of protected types (which are always limited). -- Ada 2005: AI-363 relaxes this rule, to allow heap objects of such -- types to be unconstrained. This is safe because it is illegal to -- create access subtypes to such types with explicit discriminant -- constraints. if not Is_Limited_Type (T) then if Ekind (T) = E_Record_Type then C := First_Component (T); while Present (C) loop if Is_Aliased (C) and then Has_Discriminants (Etype (C)) and then not Is_Constrained (Etype (C)) and then not In_Instance_Body and then Ada_Version < Ada_2005 then Error_Msg_N ("aliased component must be constrained (RM 3.6(11))", C); end if; Next_Component (C); end loop; elsif Ekind (T) = E_Array_Type then if Has_Aliased_Components (T) and then Has_Discriminants (Component_Type (T)) and then not Is_Constrained (Component_Type (T)) and then not In_Instance_Body and then Ada_Version < Ada_2005 then Error_Msg_N ("aliased component type must be constrained (RM 3.6(11))", T); end if; end if; end if; end Check_Aliased_Component_Types; -------------------------------------- -- Check_Anonymous_Access_Component -- -------------------------------------- procedure Check_Anonymous_Access_Component (Typ_Decl : Node_Id; Typ : Entity_Id; Prev : Entity_Id; Comp_Def : Node_Id; Access_Def : Node_Id) is Loc : constant Source_Ptr := Sloc (Comp_Def); Anon_Access : Entity_Id; Acc_Def : Node_Id; Decl : Node_Id; Type_Def : Node_Id; procedure Build_Incomplete_Type_Declaration; -- If the record type contains components that include an access to the -- current record, then create an incomplete type declaration for the -- record, to be used as the designated type of the anonymous access. -- This is done only once, and only if there is no previous partial -- view of the type. function Designates_T (Subt : Node_Id) return Boolean; -- Check whether a node designates the enclosing record type, or 'Class -- of that type function Mentions_T (Acc_Def : Node_Id) return Boolean; -- Check whether an access definition includes a reference to -- the enclosing record type. The reference can be a subtype mark -- in the access definition itself, a 'Class attribute reference, or -- recursively a reference appearing in a parameter specification -- or result definition of an access_to_subprogram definition. -------------------------------------- -- Build_Incomplete_Type_Declaration -- -------------------------------------- procedure Build_Incomplete_Type_Declaration is Decl : Node_Id; Inc_T : Entity_Id; H : Entity_Id; -- Is_Tagged indicates whether the type is tagged. It is tagged if -- it's "is new ... with record" or else "is tagged record ...". Typ_Def : constant Node_Id := (if Nkind (Typ_Decl) = N_Full_Type_Declaration then Type_Definition (Typ_Decl) else Empty); Is_Tagged : constant Boolean := Present (Typ_Def) and then ((Nkind (Typ_Def) = N_Derived_Type_Definition and then Present (Record_Extension_Part (Typ_Def))) or else (Nkind (Typ_Def) = N_Record_Definition and then Tagged_Present (Typ_Def))); begin -- If there is a previous partial view, no need to create a new one -- If the partial view, given by Prev, is incomplete, If Prev is -- a private declaration, full declaration is flagged accordingly. if Prev /= Typ then if Is_Tagged then Make_Class_Wide_Type (Prev); Set_Class_Wide_Type (Typ, Class_Wide_Type (Prev)); Set_Etype (Class_Wide_Type (Typ), Typ); end if; return; elsif Has_Private_Declaration (Typ) then -- If we refer to T'Class inside T, and T is the completion of a -- private type, then make sure the class-wide type exists. if Is_Tagged then Make_Class_Wide_Type (Typ); end if; return; -- If there was a previous anonymous access type, the incomplete -- type declaration will have been created already. elsif Present (Current_Entity (Typ)) and then Ekind (Current_Entity (Typ)) = E_Incomplete_Type and then Full_View (Current_Entity (Typ)) = Typ then if Is_Tagged and then Comes_From_Source (Current_Entity (Typ)) and then not Is_Tagged_Type (Current_Entity (Typ)) then Make_Class_Wide_Type (Typ); Error_Msg_N ("incomplete view of tagged type should be declared tagged??", Parent (Current_Entity (Typ))); end if; return; else Inc_T := Make_Defining_Identifier (Loc, Chars (Typ)); Decl := Make_Incomplete_Type_Declaration (Loc, Inc_T); -- Type has already been inserted into the current scope. Remove -- it, and add incomplete declaration for type, so that subsequent -- anonymous access types can use it. The entity is unchained from -- the homonym list and from immediate visibility. After analysis, -- the entity in the incomplete declaration becomes immediately -- visible in the record declaration that follows. H := Current_Entity (Typ); if H = Typ then Set_Name_Entity_Id (Chars (Typ), Homonym (Typ)); else while Present (H) and then Homonym (H) /= Typ loop H := Homonym (Typ); end loop; Set_Homonym (H, Homonym (Typ)); end if; Insert_Before (Typ_Decl, Decl); Analyze (Decl); Set_Full_View (Inc_T, Typ); if Is_Tagged then -- Create a common class-wide type for both views, and set the -- Etype of the class-wide type to the full view. Make_Class_Wide_Type (Inc_T); Set_Class_Wide_Type (Typ, Class_Wide_Type (Inc_T)); Set_Etype (Class_Wide_Type (Typ), Typ); end if; end if; end Build_Incomplete_Type_Declaration; ------------------ -- Designates_T -- ------------------ function Designates_T (Subt : Node_Id) return Boolean is Type_Id : constant Name_Id := Chars (Typ); function Names_T (Nam : Node_Id) return Boolean; -- The record type has not been introduced in the current scope -- yet, so we must examine the name of the type itself, either -- an identifier T, or an expanded name of the form P.T, where -- P denotes the current scope. ------------- -- Names_T -- ------------- function Names_T (Nam : Node_Id) return Boolean is begin if Nkind (Nam) = N_Identifier then return Chars (Nam) = Type_Id; elsif Nkind (Nam) = N_Selected_Component then if Chars (Selector_Name (Nam)) = Type_Id then if Nkind (Prefix (Nam)) = N_Identifier then return Chars (Prefix (Nam)) = Chars (Current_Scope); elsif Nkind (Prefix (Nam)) = N_Selected_Component then return Chars (Selector_Name (Prefix (Nam))) = Chars (Current_Scope); else return False; end if; else return False; end if; else return False; end if; end Names_T; -- Start of processing for Designates_T begin if Nkind (Subt) = N_Identifier then return Chars (Subt) = Type_Id; -- Reference can be through an expanded name which has not been -- analyzed yet, and which designates enclosing scopes. elsif Nkind (Subt) = N_Selected_Component then if Names_T (Subt) then return True; -- Otherwise it must denote an entity that is already visible. -- The access definition may name a subtype of the enclosing -- type, if there is a previous incomplete declaration for it. else Find_Selected_Component (Subt); return Is_Entity_Name (Subt) and then Scope (Entity (Subt)) = Current_Scope and then (Chars (Base_Type (Entity (Subt))) = Type_Id or else (Is_Class_Wide_Type (Entity (Subt)) and then Chars (Etype (Base_Type (Entity (Subt)))) = Type_Id)); end if; -- A reference to the current type may appear as the prefix of -- a 'Class attribute. elsif Nkind (Subt) = N_Attribute_Reference and then Attribute_Name (Subt) = Name_Class then return Names_T (Prefix (Subt)); else return False; end if; end Designates_T; ---------------- -- Mentions_T -- ---------------- function Mentions_T (Acc_Def : Node_Id) return Boolean is Param_Spec : Node_Id; Acc_Subprg : constant Node_Id := Access_To_Subprogram_Definition (Acc_Def); begin if No (Acc_Subprg) then return Designates_T (Subtype_Mark (Acc_Def)); end if; -- Component is an access_to_subprogram: examine its formals, -- and result definition in the case of an access_to_function. Param_Spec := First (Parameter_Specifications (Acc_Subprg)); while Present (Param_Spec) loop if Nkind (Parameter_Type (Param_Spec)) = N_Access_Definition and then Mentions_T (Parameter_Type (Param_Spec)) then return True; elsif Designates_T (Parameter_Type (Param_Spec)) then return True; end if; Next (Param_Spec); end loop; if Nkind (Acc_Subprg) = N_Access_Function_Definition then if Nkind (Result_Definition (Acc_Subprg)) = N_Access_Definition then return Mentions_T (Result_Definition (Acc_Subprg)); else return Designates_T (Result_Definition (Acc_Subprg)); end if; end if; return False; end Mentions_T; -- Start of processing for Check_Anonymous_Access_Component begin if Present (Access_Def) and then Mentions_T (Access_Def) then Acc_Def := Access_To_Subprogram_Definition (Access_Def); Build_Incomplete_Type_Declaration; Anon_Access := Make_Temporary (Loc, 'S'); -- Create a declaration for the anonymous access type: either -- an access_to_object or an access_to_subprogram. if Present (Acc_Def) then if Nkind (Acc_Def) = N_Access_Function_Definition then Type_Def := Make_Access_Function_Definition (Loc, Parameter_Specifications => Parameter_Specifications (Acc_Def), Result_Definition => Result_Definition (Acc_Def)); else Type_Def := Make_Access_Procedure_Definition (Loc, Parameter_Specifications => Parameter_Specifications (Acc_Def)); end if; else Type_Def := Make_Access_To_Object_Definition (Loc, Subtype_Indication => Relocate_Node (Subtype_Mark (Access_Def))); Set_Constant_Present (Type_Def, Constant_Present (Access_Def)); Set_All_Present (Type_Def, All_Present (Access_Def)); end if; Set_Null_Exclusion_Present (Type_Def, Null_Exclusion_Present (Access_Def)); Decl := Make_Full_Type_Declaration (Loc, Defining_Identifier => Anon_Access, Type_Definition => Type_Def); Insert_Before (Typ_Decl, Decl); Analyze (Decl); -- If an access to subprogram, create the extra formals if Present (Acc_Def) then Create_Extra_Formals (Designated_Type (Anon_Access)); end if; if Nkind (Comp_Def) = N_Component_Definition then Rewrite (Comp_Def, Make_Component_Definition (Loc, Subtype_Indication => New_Occurrence_Of (Anon_Access, Loc))); else pragma Assert (Nkind (Comp_Def) = N_Discriminant_Specification); Rewrite (Comp_Def, Make_Discriminant_Specification (Loc, Defining_Identifier => Defining_Identifier (Comp_Def), Discriminant_Type => New_Occurrence_Of (Anon_Access, Loc))); end if; if Ekind (Designated_Type (Anon_Access)) = E_Subprogram_Type then Mutate_Ekind (Anon_Access, E_Anonymous_Access_Subprogram_Type); else Mutate_Ekind (Anon_Access, E_Anonymous_Access_Type); end if; Set_Is_Local_Anonymous_Access (Anon_Access); end if; end Check_Anonymous_Access_Component; --------------------------------------- -- Check_Anonymous_Access_Components -- --------------------------------------- procedure Check_Anonymous_Access_Components (Typ_Decl : Node_Id; Typ : Entity_Id; Prev : Entity_Id; Comp_List : Node_Id) is Comp : Node_Id; begin if No (Comp_List) then return; end if; Comp := First (Component_Items (Comp_List)); while Present (Comp) loop if Nkind (Comp) = N_Component_Declaration then Check_Anonymous_Access_Component (Typ_Decl, Typ, Prev, Component_Definition (Comp), Access_Definition (Component_Definition (Comp))); end if; Next (Comp); end loop; if Present (Variant_Part (Comp_List)) then declare V : Node_Id; begin V := First_Non_Pragma (Variants (Variant_Part (Comp_List))); while Present (V) loop Check_Anonymous_Access_Components (Typ_Decl, Typ, Prev, Component_List (V)); Next_Non_Pragma (V); end loop; end; end if; end Check_Anonymous_Access_Components; ---------------------- -- Check_Completion -- ---------------------- procedure Check_Completion (Body_Id : Node_Id := Empty) is E : Entity_Id; procedure Post_Error; -- Post error message for lack of completion for entity E ---------------- -- Post_Error -- ---------------- procedure Post_Error is procedure Missing_Body; -- Output missing body message ------------------ -- Missing_Body -- ------------------ procedure Missing_Body is begin -- Spec is in same unit, so we can post on spec if In_Same_Source_Unit (Body_Id, E) then Error_Msg_N ("missing body for &", E); -- Spec is in a separate unit, so we have to post on the body else Error_Msg_NE ("missing body for & declared#!", Body_Id, E); end if; end Missing_Body; -- Start of processing for Post_Error begin if not Comes_From_Source (E) then if Ekind (E) in E_Task_Type | E_Protected_Type then -- It may be an anonymous protected type created for a -- single variable. Post error on variable, if present. declare Var : Entity_Id; begin Var := First_Entity (Current_Scope); while Present (Var) loop exit when Etype (Var) = E and then Comes_From_Source (Var); Next_Entity (Var); end loop; if Present (Var) then E := Var; end if; end; end if; end if; -- If a generated entity has no completion, then either previous -- semantic errors have disabled the expansion phase, or else we had -- missing subunits, or else we are compiling without expansion, -- or else something is very wrong. if not Comes_From_Source (E) then pragma Assert (Serious_Errors_Detected > 0 or else Configurable_Run_Time_Violations > 0 or else Subunits_Missing or else not Expander_Active); return; -- Here for source entity else -- Here if no body to post the error message, so we post the error -- on the declaration that has no completion. This is not really -- the right place to post it, think about this later ??? if No (Body_Id) then if Is_Type (E) then Error_Msg_NE ("missing full declaration for }", Parent (E), E); else Error_Msg_NE ("missing body for &", Parent (E), E); end if; -- Package body has no completion for a declaration that appears -- in the corresponding spec. Post error on the body, with a -- reference to the non-completed declaration. else Error_Msg_Sloc := Sloc (E); if Is_Type (E) then Error_Msg_NE ("missing full declaration for }!", Body_Id, E); elsif Is_Overloadable (E) and then Current_Entity_In_Scope (E) /= E then -- It may be that the completion is mistyped and appears as -- a distinct overloading of the entity. declare Candidate : constant Entity_Id := Current_Entity_In_Scope (E); Decl : constant Node_Id := Unit_Declaration_Node (Candidate); begin if Is_Overloadable (Candidate) and then Ekind (Candidate) = Ekind (E) and then Nkind (Decl) = N_Subprogram_Body and then Acts_As_Spec (Decl) then Check_Type_Conformant (Candidate, E); else Missing_Body; end if; end; else Missing_Body; end if; end if; end if; end Post_Error; -- Local variables Pack_Id : constant Entity_Id := Current_Scope; -- Start of processing for Check_Completion begin E := First_Entity (Pack_Id); while Present (E) loop if Is_Intrinsic_Subprogram (E) then null; -- The following situation requires special handling: a child unit -- that appears in the context clause of the body of its parent: -- procedure Parent.Child (...); -- with Parent.Child; -- package body Parent is -- Here Parent.Child appears as a local entity, but should not be -- flagged as requiring completion, because it is a compilation -- unit. -- Ignore missing completion for a subprogram that does not come from -- source (including the _Call primitive operation of RAS types, -- which has to have the flag Comes_From_Source for other purposes): -- we assume that the expander will provide the missing completion. -- In case of previous errors, other expansion actions that provide -- bodies for null procedures with not be invoked, so inhibit message -- in those cases. -- Note that E_Operator is not in the list that follows, because -- this kind is reserved for predefined operators, that are -- intrinsic and do not need completion. elsif Ekind (E) in E_Function | E_Procedure | E_Generic_Function | E_Generic_Procedure then if Has_Completion (E) then null; elsif Is_Subprogram (E) and then Is_Abstract_Subprogram (E) then null; elsif Is_Subprogram (E) and then (not Comes_From_Source (E) or else Chars (E) = Name_uCall) then null; elsif Nkind (Parent (Unit_Declaration_Node (E))) = N_Compilation_Unit then null; elsif Nkind (Parent (E)) = N_Procedure_Specification and then Null_Present (Parent (E)) and then Serious_Errors_Detected > 0 then null; else Post_Error; end if; elsif Is_Entry (E) then if not Has_Completion (E) and then Ekind (Scope (E)) = E_Protected_Type then Post_Error; end if; elsif Is_Package_Or_Generic_Package (E) then if Unit_Requires_Body (E) then if not Has_Completion (E) and then Nkind (Parent (Unit_Declaration_Node (E))) /= N_Compilation_Unit then Post_Error; end if; elsif not Is_Child_Unit (E) then May_Need_Implicit_Body (E); end if; -- A formal incomplete type (Ada 2012) does not require a completion; -- other incomplete type declarations do. elsif Ekind (E) = E_Incomplete_Type then if No (Underlying_Type (E)) and then not Is_Generic_Type (E) then Post_Error; end if; elsif Ekind (E) in E_Task_Type | E_Protected_Type then if not Has_Completion (E) then Post_Error; end if; -- A single task declared in the current scope is a constant, verify -- that the body of its anonymous type is in the same scope. If the -- task is defined elsewhere, this may be a renaming declaration for -- which no completion is needed. elsif Ekind (E) = E_Constant then if Ekind (Etype (E)) = E_Task_Type and then not Has_Completion (Etype (E)) and then Scope (Etype (E)) = Current_Scope then Post_Error; end if; elsif Ekind (E) = E_Record_Type then if Is_Tagged_Type (E) then Check_Abstract_Overriding (E); Check_Conventions (E); end if; Check_Aliased_Component_Types (E); elsif Ekind (E) = E_Array_Type then Check_Aliased_Component_Types (E); end if; Next_Entity (E); end loop; end Check_Completion; ------------------------------------- -- Check_Constraining_Discriminant -- ------------------------------------- procedure Check_Constraining_Discriminant (New_Disc, Old_Disc : Entity_Id) is New_Type : constant Entity_Id := Etype (New_Disc); Old_Type : Entity_Id; begin -- If the record type contains an array constrained by the discriminant -- but with some different bound, the compiler tries to create a smaller -- range for the discriminant type (see exp_ch3.Adjust_Discriminants). -- In this case, where the discriminant type is a scalar type, the check -- must use the original discriminant type in the parent declaration. if Is_Scalar_Type (New_Type) then Old_Type := Entity (Discriminant_Type (Parent (Old_Disc))); else Old_Type := Etype (Old_Disc); end if; if not Subtypes_Statically_Compatible (New_Type, Old_Type) then Error_Msg_N ("subtype must be statically compatible with parent discriminant", New_Disc); if not Predicates_Compatible (New_Type, Old_Type) then Error_Msg_N ("\subtype predicate is not compatible with parent discriminant", New_Disc); end if; end if; end Check_Constraining_Discriminant; ------------------------------------ -- Check_CPP_Type_Has_No_Defaults -- ------------------------------------ procedure Check_CPP_Type_Has_No_Defaults (T : Entity_Id) is Tdef : constant Node_Id := Type_Definition (Declaration_Node (T)); Clist : Node_Id; Comp : Node_Id; begin -- Obtain the component list if Nkind (Tdef) = N_Record_Definition then Clist := Component_List (Tdef); else pragma Assert (Nkind (Tdef) = N_Derived_Type_Definition); Clist := Component_List (Record_Extension_Part (Tdef)); end if; -- Check all components to ensure no default expressions if Present (Clist) then Comp := First (Component_Items (Clist)); while Present (Comp) loop if Present (Expression (Comp)) then Error_Msg_N ("component of imported 'C'P'P type cannot have " & "default expression", Expression (Comp)); end if; Next (Comp); end loop; end if; end Check_CPP_Type_Has_No_Defaults; ---------------------------- -- Check_Delta_Expression -- ---------------------------- procedure Check_Delta_Expression (E : Node_Id) is begin if not (Is_Real_Type (Etype (E))) then Wrong_Type (E, Any_Real); elsif not Is_OK_Static_Expression (E) then Flag_Non_Static_Expr ("non-static expression used for delta value!", E); elsif not UR_Is_Positive (Expr_Value_R (E)) then Error_Msg_N ("delta expression must be positive", E); else return; end if; -- If any of above errors occurred, then replace the incorrect -- expression by the real 0.1, which should prevent further errors. Rewrite (E, Make_Real_Literal (Sloc (E), Ureal_Tenth)); Analyze_And_Resolve (E, Standard_Float); end Check_Delta_Expression; ----------------------------- -- Check_Digits_Expression -- ----------------------------- procedure Check_Digits_Expression (E : Node_Id) is begin if not (Is_Integer_Type (Etype (E))) then Wrong_Type (E, Any_Integer); elsif not Is_OK_Static_Expression (E) then Flag_Non_Static_Expr ("non-static expression used for digits value!", E); elsif Expr_Value (E) <= 0 then Error_Msg_N ("digits value must be greater than zero", E); else return; end if; -- If any of above errors occurred, then replace the incorrect -- expression by the integer 1, which should prevent further errors. Rewrite (E, Make_Integer_Literal (Sloc (E), 1)); Analyze_And_Resolve (E, Standard_Integer); end Check_Digits_Expression; -------------------------- -- Check_Initialization -- -------------------------- procedure Check_Initialization (T : Entity_Id; Exp : Node_Id) is begin -- Special processing for limited types if Is_Limited_Type (T) and then not In_Instance and then not In_Inlined_Body then if not OK_For_Limited_Init (T, Exp) then -- In GNAT mode, this is just a warning, to allow it to be evilly -- turned off. Otherwise it is a real error. if GNAT_Mode then Error_Msg_N ("??cannot initialize entities of limited type!", Exp); elsif Ada_Version < Ada_2005 then -- The side effect removal machinery may generate illegal Ada -- code to avoid the usage of access types and 'reference in -- SPARK mode. Since this is legal code with respect to theorem -- proving, do not emit the error. if GNATprove_Mode and then Nkind (Exp) = N_Function_Call and then Nkind (Parent (Exp)) = N_Object_Declaration and then not Comes_From_Source (Defining_Identifier (Parent (Exp))) then null; else Error_Msg_N ("cannot initialize entities of limited type", Exp); Explain_Limited_Type (T, Exp); end if; else -- Specialize error message according to kind of illegal -- initial expression. We check the Original_Node to cover -- cases where the initialization expression of an object -- declaration generated by the compiler has been rewritten -- (such as for dispatching calls). if Nkind (Original_Node (Exp)) = N_Type_Conversion and then Nkind (Expression (Original_Node (Exp))) = N_Function_Call then -- No error for internally-generated object declarations, -- which can come from build-in-place assignment statements. if Nkind (Parent (Exp)) = N_Object_Declaration and then not Comes_From_Source (Defining_Identifier (Parent (Exp))) then null; else Error_Msg_N ("illegal context for call to function with limited " & "result", Exp); end if; else Error_Msg_N ("initialization of limited object requires aggregate or " & "function call", Exp); end if; end if; end if; end if; -- In gnatc or gnatprove mode, make sure set Do_Range_Check flag gets -- set unless we can be sure that no range check is required. if not Expander_Active and then Is_Scalar_Type (T) and then not Is_In_Range (Exp, T, Assume_Valid => True) then Set_Do_Range_Check (Exp); end if; end Check_Initialization; ---------------------- -- Check_Interfaces -- ---------------------- procedure Check_Interfaces (N : Node_Id; Def : Node_Id) is Parent_Type : constant Entity_Id := Etype (Defining_Identifier (N)); Iface : Node_Id; Iface_Def : Node_Id; Iface_Typ : Entity_Id; Parent_Node : Node_Id; Is_Task : Boolean := False; -- Set True if parent type or any progenitor is a task interface Is_Protected : Boolean := False; -- Set True if parent type or any progenitor is a protected interface procedure Check_Ifaces (Iface_Def : Node_Id; Error_Node : Node_Id); -- Check that a progenitor is compatible with declaration. If an error -- message is output, it is posted on Error_Node. ------------------ -- Check_Ifaces -- ------------------ procedure Check_Ifaces (Iface_Def : Node_Id; Error_Node : Node_Id) is Iface_Id : constant Entity_Id := Defining_Identifier (Parent (Iface_Def)); Type_Def : Node_Id; begin if Nkind (N) = N_Private_Extension_Declaration then Type_Def := N; else Type_Def := Type_Definition (N); end if; if Is_Task_Interface (Iface_Id) then Is_Task := True; elsif Is_Protected_Interface (Iface_Id) then Is_Protected := True; end if; if Is_Synchronized_Interface (Iface_Id) then -- A consequence of 3.9.4 (6/2) and 7.3 (7.2/2) is that a private -- extension derived from a synchronized interface must explicitly -- be declared synchronized, because the full view will be a -- synchronized type. if Nkind (N) = N_Private_Extension_Declaration then if not Synchronized_Present (N) then Error_Msg_NE ("private extension of& must be explicitly synchronized", N, Iface_Id); end if; -- However, by 3.9.4(16/2), a full type that is a record extension -- is never allowed to derive from a synchronized interface (note -- that interfaces must be excluded from this check, because those -- are represented by derived type definitions in some cases). elsif Nkind (Type_Definition (N)) = N_Derived_Type_Definition and then not Interface_Present (Type_Definition (N)) then Error_Msg_N ("record extension cannot derive from synchronized " & "interface", Error_Node); end if; end if; -- Check that the characteristics of the progenitor are compatible -- with the explicit qualifier in the declaration. -- The check only applies to qualifiers that come from source. -- Limited_Present also appears in the declaration of corresponding -- records, and the check does not apply to them. if Limited_Present (Type_Def) and then not Is_Concurrent_Record_Type (Defining_Identifier (N)) then if Is_Limited_Interface (Parent_Type) and then not Is_Limited_Interface (Iface_Id) then Error_Msg_NE ("progenitor & must be limited interface", Error_Node, Iface_Id); elsif (Task_Present (Iface_Def) or else Protected_Present (Iface_Def) or else Synchronized_Present (Iface_Def)) and then Nkind (N) /= N_Private_Extension_Declaration and then not Error_Posted (N) then Error_Msg_NE ("progenitor & must be limited interface", Error_Node, Iface_Id); end if; -- Protected interfaces can only inherit from limited, synchronized -- or protected interfaces. elsif Nkind (N) = N_Full_Type_Declaration and then Protected_Present (Type_Def) then if Limited_Present (Iface_Def) or else Synchronized_Present (Iface_Def) or else Protected_Present (Iface_Def) then null; elsif Task_Present (Iface_Def) then Error_Msg_N ("(Ada 2005) protected interface cannot inherit " & "from task interface", Error_Node); else Error_Msg_N ("(Ada 2005) protected interface cannot inherit " & "from non-limited interface", Error_Node); end if; -- Ada 2005 (AI-345): Synchronized interfaces can only inherit from -- limited and synchronized. elsif Synchronized_Present (Type_Def) then if Limited_Present (Iface_Def) or else Synchronized_Present (Iface_Def) then null; elsif Protected_Present (Iface_Def) and then Nkind (N) /= N_Private_Extension_Declaration then Error_Msg_N ("(Ada 2005) synchronized interface cannot inherit " & "from protected interface", Error_Node); elsif Task_Present (Iface_Def) and then Nkind (N) /= N_Private_Extension_Declaration then Error_Msg_N ("(Ada 2005) synchronized interface cannot inherit " & "from task interface", Error_Node); elsif not Is_Limited_Interface (Iface_Id) then Error_Msg_N ("(Ada 2005) synchronized interface cannot inherit " & "from non-limited interface", Error_Node); end if; -- Ada 2005 (AI-345): Task interfaces can only inherit from limited, -- synchronized or task interfaces. elsif Nkind (N) = N_Full_Type_Declaration and then Task_Present (Type_Def) then if Limited_Present (Iface_Def) or else Synchronized_Present (Iface_Def) or else Task_Present (Iface_Def) then null; elsif Protected_Present (Iface_Def) then Error_Msg_N ("(Ada 2005) task interface cannot inherit from " & "protected interface", Error_Node); else Error_Msg_N ("(Ada 2005) task interface cannot inherit from " & "non-limited interface", Error_Node); end if; end if; end Check_Ifaces; -- Start of processing for Check_Interfaces begin if Is_Interface (Parent_Type) then if Is_Task_Interface (Parent_Type) then Is_Task := True; elsif Is_Protected_Interface (Parent_Type) then Is_Protected := True; end if; end if; if Nkind (N) = N_Private_Extension_Declaration then -- Check that progenitors are compatible with declaration Iface := First (Interface_List (Def)); while Present (Iface) loop Iface_Typ := Find_Type_Of_Subtype_Indic (Iface); Parent_Node := Parent (Base_Type (Iface_Typ)); Iface_Def := Type_Definition (Parent_Node); if not Is_Interface (Iface_Typ) then Diagnose_Interface (Iface, Iface_Typ); else Check_Ifaces (Iface_Def, Iface); end if; Next (Iface); end loop; if Is_Task and Is_Protected then Error_Msg_N ("type cannot derive from task and protected interface", N); end if; return; end if; -- Full type declaration of derived type. -- Check compatibility with parent if it is interface type if Nkind (Type_Definition (N)) = N_Derived_Type_Definition and then Is_Interface (Parent_Type) then Parent_Node := Parent (Parent_Type); -- More detailed checks for interface varieties Check_Ifaces (Iface_Def => Type_Definition (Parent_Node), Error_Node => Subtype_Indication (Type_Definition (N))); end if; Iface := First (Interface_List (Def)); while Present (Iface) loop Iface_Typ := Find_Type_Of_Subtype_Indic (Iface); Parent_Node := Parent (Base_Type (Iface_Typ)); Iface_Def := Type_Definition (Parent_Node); if not Is_Interface (Iface_Typ) then Diagnose_Interface (Iface, Iface_Typ); else -- "The declaration of a specific descendant of an interface -- type freezes the interface type" RM 13.14 Freeze_Before (N, Iface_Typ); Check_Ifaces (Iface_Def, Error_Node => Iface); end if; Next (Iface); end loop; if Is_Task and Is_Protected then Error_Msg_N ("type cannot derive from task and protected interface", N); end if; end Check_Interfaces; ------------------------------------ -- Check_Or_Process_Discriminants -- ------------------------------------ -- If an incomplete or private type declaration was already given for the -- type, the discriminants may have already been processed if they were -- present on the incomplete declaration. In this case a full conformance -- check has been performed in Find_Type_Name, and we then recheck here -- some properties that can't be checked on the partial view alone. -- Otherwise we call Process_Discriminants. procedure Check_Or_Process_Discriminants (N : Node_Id; T : Entity_Id; Prev : Entity_Id := Empty) is begin if Has_Discriminants (T) then -- Discriminants are already set on T if they were already present -- on the partial view. Make them visible to component declarations. declare D : Entity_Id; -- Discriminant on T (full view) referencing expr on partial view Prev_D : Entity_Id; -- Entity of corresponding discriminant on partial view New_D : Node_Id; -- Discriminant specification for full view, expression is -- the syntactic copy on full view (which has been checked for -- conformance with partial view), only used here to post error -- message. begin D := First_Discriminant (T); New_D := First (Discriminant_Specifications (N)); while Present (D) loop Prev_D := Current_Entity (D); Set_Current_Entity (D); Set_Is_Immediately_Visible (D); Set_Homonym (D, Prev_D); -- Handle the case where there is an untagged partial view and -- the full view is tagged: must disallow discriminants with -- defaults, unless compiling for Ada 2012, which allows a -- limited tagged type to have defaulted discriminants (see -- AI05-0214). However, suppress error here if it was already -- reported on the default expression of the partial view. if Is_Tagged_Type (T) and then Present (Expression (Parent (D))) and then (not Is_Limited_Type (Current_Scope) or else Ada_Version < Ada_2012) and then not Error_Posted (Expression (Parent (D))) then if Ada_Version >= Ada_2012 then Error_Msg_N ("discriminants of nonlimited tagged type cannot have " & "defaults", Expression (New_D)); else Error_Msg_N ("discriminants of tagged type cannot have defaults", Expression (New_D)); end if; end if; -- Ada 2005 (AI-230): Access discriminant allowed in -- non-limited record types. if Ada_Version < Ada_2005 then -- This restriction gets applied to the full type here. It -- has already been applied earlier to the partial view. Check_Access_Discriminant_Requires_Limited (Parent (D), N); end if; Next_Discriminant (D); Next (New_D); end loop; end; elsif Present (Discriminant_Specifications (N)) then Process_Discriminants (N, Prev); end if; end Check_Or_Process_Discriminants; ---------------------- -- Check_Real_Bound -- ---------------------- procedure Check_Real_Bound (Bound : Node_Id) is begin if not Is_Real_Type (Etype (Bound)) then Error_Msg_N ("bound in real type definition must be of real type", Bound); elsif not Is_OK_Static_Expression (Bound) then Flag_Non_Static_Expr ("non-static expression used for real type bound!", Bound); else return; end if; Rewrite (Bound, Make_Real_Literal (Sloc (Bound), Ureal_0)); Analyze (Bound); Resolve (Bound, Standard_Float); end Check_Real_Bound; ------------------------------ -- Complete_Private_Subtype -- ------------------------------ procedure Complete_Private_Subtype (Priv : Entity_Id; Full : Entity_Id; Full_Base : Entity_Id; Related_Nod : Node_Id) is Save_Next_Entity : Entity_Id; Save_Homonym : Entity_Id; begin -- Set semantic attributes for (implicit) private subtype completion. -- If the full type has no discriminants, then it is a copy of the -- full view of the base. Otherwise, it is a subtype of the base with -- a possible discriminant constraint. Save and restore the original -- Next_Entity field of full to ensure that the calls to Copy_Node do -- not corrupt the entity chain. Save_Next_Entity := Next_Entity (Full); Save_Homonym := Homonym (Priv); if Is_Private_Type (Full_Base) or else Is_Record_Type (Full_Base) or else Is_Concurrent_Type (Full_Base) then Copy_Node (Priv, Full); -- Note that the Etype of the full view is the same as the Etype of -- the partial view. In this fashion, the subtype has access to the -- correct view of the parent. Set_Has_Discriminants (Full, Has_Discriminants (Full_Base)); Set_Has_Unknown_Discriminants (Full, Has_Unknown_Discriminants (Full_Base)); Set_First_Entity (Full, First_Entity (Full_Base)); Set_Last_Entity (Full, Last_Entity (Full_Base)); -- If the underlying base type is constrained, we know that the -- full view of the subtype is constrained as well (the converse -- is not necessarily true). if Is_Constrained (Full_Base) then Set_Is_Constrained (Full); end if; else Copy_Node (Full_Base, Full); -- The following subtlety with the Etype of the full view needs to be -- taken into account here. One could think that it must naturally be -- set to the base type of the full base: -- Set_Etype (Full, Base_Type (Full_Base)); -- so that the full view becomes a subtype of the full base when the -- latter is a base type, which must for example happen when the full -- base is declared as derived type. That's also correct if the full -- base is declared as an array type, or a floating-point type, or a -- fixed-point type, or a signed integer type, as these declarations -- create an implicit base type and a first subtype so the Etype of -- the full views must be the implicit base type. But that's wrong -- if the full base is declared as an access type, or an enumeration -- type, or a modular integer type, as these declarations directly -- create a base type, i.e. with Etype pointing to itself. Moreover -- the full base being declared in the private part, i.e. when the -- views are swapped, the end result is that the Etype of the full -- base is set to its private view in this case and that we need to -- propagate this setting to the full view in order for the subtype -- to be compatible with the base type. if Is_Base_Type (Full_Base) and then (Is_Derived_Type (Full_Base) or else Ekind (Full_Base) in Array_Kind or else Ekind (Full_Base) in Fixed_Point_Kind or else Ekind (Full_Base) in Float_Kind or else Ekind (Full_Base) in Signed_Integer_Kind) then Set_Etype (Full, Full_Base); end if; Set_Chars (Full, Chars (Priv)); Set_Sloc (Full, Sloc (Priv)); Conditional_Delay (Full, Priv); end if; Link_Entities (Full, Save_Next_Entity); Set_Homonym (Full, Save_Homonym); Set_Associated_Node_For_Itype (Full, Related_Nod); if Ekind (Full) in Incomplete_Or_Private_Kind then Reinit_Field_To_Zero (Full, F_Private_Dependents); end if; -- Set common attributes for all subtypes: kind, convention, etc. Mutate_Ekind (Full, Subtype_Kind (Ekind (Full_Base))); Set_Convention (Full, Convention (Full_Base)); Set_Is_First_Subtype (Full, False); Set_Scope (Full, Scope (Priv)); Set_Size_Info (Full, Full_Base); Copy_RM_Size (To => Full, From => Full_Base); Set_Is_Itype (Full); -- A subtype of a private-type-without-discriminants, whose full-view -- has discriminants with default expressions, is not constrained. if not Has_Discriminants (Priv) then Set_Is_Constrained (Full, Is_Constrained (Full_Base)); if Has_Discriminants (Full_Base) then Set_Discriminant_Constraint (Full, Discriminant_Constraint (Full_Base)); -- The partial view may have been indefinite, the full view -- might not be. Set_Has_Unknown_Discriminants (Full, Has_Unknown_Discriminants (Full_Base)); end if; end if; Set_First_Rep_Item (Full, First_Rep_Item (Full_Base)); Set_Depends_On_Private (Full, Has_Private_Component (Full)); -- Freeze the private subtype entity if its parent is delayed, and not -- already frozen. We skip this processing if the type is an anonymous -- subtype of a record component, or is the corresponding record of a -- protected type, since these are processed when the enclosing type -- is frozen. If the parent type is declared in a nested package then -- the freezing of the private and full views also happens later. if not Is_Type (Scope (Full)) then if Is_Itype (Priv) and then In_Same_Source_Unit (Full, Full_Base) and then Scope (Full_Base) /= Scope (Full) then Set_Has_Delayed_Freeze (Full); Set_Has_Delayed_Freeze (Priv); else Set_Has_Delayed_Freeze (Full, Has_Delayed_Freeze (Full_Base) and then not Is_Frozen (Full_Base)); end if; end if; Set_Freeze_Node (Full, Empty); Set_Is_Frozen (Full, False); if Has_Discriminants (Full) then Set_Stored_Constraint_From_Discriminant_Constraint (Full); Set_Stored_Constraint (Priv, Stored_Constraint (Full)); if Has_Unknown_Discriminants (Full) then Set_Discriminant_Constraint (Full, No_Elist); end if; end if; if Ekind (Full_Base) = E_Record_Type and then Has_Discriminants (Full_Base) and then Has_Discriminants (Priv) -- might not, if errors and then not Has_Unknown_Discriminants (Priv) and then not Is_Empty_Elmt_List (Discriminant_Constraint (Priv)) then Create_Constrained_Components (Full, Related_Nod, Full_Base, Discriminant_Constraint (Priv)); -- If the full base is itself derived from private, build a congruent -- subtype of its underlying full view, for use by the back end. elsif Is_Private_Type (Full_Base) and then Present (Underlying_Full_View (Full_Base)) then declare Underlying_Full_Base : constant Entity_Id := Underlying_Full_View (Full_Base); Underlying_Full : constant Entity_Id := Make_Defining_Identifier (Sloc (Priv), Chars (Priv)); begin Set_Is_Itype (Underlying_Full); Set_Associated_Node_For_Itype (Underlying_Full, Related_Nod); Complete_Private_Subtype (Priv, Underlying_Full, Underlying_Full_Base, Related_Nod); Set_Underlying_Full_View (Full, Underlying_Full); Set_Is_Underlying_Full_View (Underlying_Full); end; elsif Is_Record_Type (Full_Base) then -- Show Full is simply a renaming of Full_Base Set_Cloned_Subtype (Full, Full_Base); Set_Is_Limited_Record (Full, Is_Limited_Record (Full_Base)); -- Propagate predicates Propagate_Predicate_Attributes (Full, Full_Base); end if; -- It is unsafe to share the bounds of a scalar type, because the Itype -- is elaborated on demand, and if a bound is nonstatic, then different -- orders of elaboration in different units will lead to different -- external symbols. if Is_Scalar_Type (Full_Base) then Set_Scalar_Range (Full, Make_Range (Sloc (Related_Nod), Low_Bound => Duplicate_Subexpr_No_Checks (Type_Low_Bound (Full_Base)), High_Bound => Duplicate_Subexpr_No_Checks (Type_High_Bound (Full_Base)))); -- This completion inherits the bounds of the full parent, but if -- the parent is an unconstrained floating point type, so is the -- completion. if Is_Floating_Point_Type (Full_Base) then Set_Includes_Infinities (Scalar_Range (Full), Has_Infinities (Full_Base)); end if; end if; -- ??? It seems that a lot of fields are missing that should be copied -- from Full_Base to Full. Here are some that are introduced in a -- non-disruptive way but a cleanup is necessary. if Is_Tagged_Type (Full_Base) then Set_Is_Tagged_Type (Full); Set_Is_Limited_Record (Full, Is_Limited_Record (Full_Base)); Set_Direct_Primitive_Operations (Full, Direct_Primitive_Operations (Full_Base)); Set_No_Tagged_Streams_Pragma (Full, No_Tagged_Streams_Pragma (Full_Base)); if Is_Interface (Full_Base) then Set_Is_Interface (Full); Set_Is_Limited_Interface (Full, Is_Limited_Interface (Full_Base)); end if; -- Inherit class_wide type of full_base in case the partial view was -- not tagged. Otherwise it has already been created when the private -- subtype was analyzed. if No (Class_Wide_Type (Full)) then Set_Class_Wide_Type (Full, Class_Wide_Type (Full_Base)); end if; -- If this is a subtype of a protected or task type, constrain its -- corresponding record, unless this is a subtype without constraints, -- i.e. a simple renaming as with an actual subtype in an instance. elsif Is_Concurrent_Type (Full_Base) then if Has_Discriminants (Full) and then Present (Corresponding_Record_Type (Full_Base)) and then not Is_Empty_Elmt_List (Discriminant_Constraint (Full)) then Set_Corresponding_Record_Type (Full, Constrain_Corresponding_Record (Full, Corresponding_Record_Type (Full_Base), Related_Nod)); else Set_Corresponding_Record_Type (Full, Corresponding_Record_Type (Full_Base)); end if; end if; -- Link rep item chain, and also setting of Has_Predicates from private -- subtype to full subtype, since we will need these on the full subtype -- to create the predicate function. Note that the full subtype may -- already have rep items, inherited from the full view of the base -- type, so we must be sure not to overwrite these entries. declare Append : Boolean; Item : Node_Id; Next_Item : Node_Id; Priv_Item : Node_Id; begin Item := First_Rep_Item (Full); Priv_Item := First_Rep_Item (Priv); -- If no existing rep items on full type, we can just link directly -- to the list of items on the private type, if any exist.. Same if -- the rep items are only those inherited from the base if (No (Item) or else Nkind (Item) /= N_Aspect_Specification or else Entity (Item) = Full_Base) and then Present (First_Rep_Item (Priv)) then Set_First_Rep_Item (Full, Priv_Item); -- Otherwise, search to the end of items currently linked to the full -- subtype and append the private items to the end. However, if Priv -- and Full already have the same list of rep items, then the append -- is not done, as that would create a circularity. -- -- The partial view may have a predicate and the rep item lists of -- both views agree when inherited from the same ancestor. In that -- case, simply propagate the list from one view to the other. -- A more complex analysis needed here ??? elsif Present (Priv_Item) and then Item = Next_Rep_Item (Priv_Item) then Set_First_Rep_Item (Full, Priv_Item); elsif Item /= Priv_Item then Append := True; loop Next_Item := Next_Rep_Item (Item); exit when No (Next_Item); Item := Next_Item; -- If the private view has aspect specifications, the full view -- inherits them. Since these aspects may already have been -- attached to the full view during derivation, do not append -- them if already present. if Item = First_Rep_Item (Priv) then Append := False; exit; end if; end loop; -- And link the private type items at the end of the chain if Append then Set_Next_Rep_Item (Item, First_Rep_Item (Priv)); end if; end if; end; -- Make sure Has_Predicates is set on full type if it is set on the -- private type. Note that it may already be set on the full type and -- if so, we don't want to unset it. Similarly, propagate information -- about delayed aspects, because the corresponding pragmas must be -- analyzed when one of the views is frozen. This last step is needed -- in particular when the full type is a scalar type for which an -- anonymous base type is constructed. -- The predicate functions are generated either at the freeze point -- of the type or at the end of the visible part, and we must avoid -- generating them twice. Propagate_Predicate_Attributes (Full, Priv); if Has_Delayed_Aspects (Priv) then Set_Has_Delayed_Aspects (Full); end if; end Complete_Private_Subtype; ---------------------------- -- Constant_Redeclaration -- ---------------------------- procedure Constant_Redeclaration (Id : Entity_Id; N : Node_Id; T : out Entity_Id) is Prev : constant Entity_Id := Current_Entity_In_Scope (Id); Obj_Def : constant Node_Id := Object_Definition (N); New_T : Entity_Id; procedure Check_Possible_Deferred_Completion (Prev_Id : Entity_Id; Prev_Obj_Def : Node_Id; Curr_Obj_Def : Node_Id); -- Determine whether the two object definitions describe the partial -- and the full view of a constrained deferred constant. Generate -- a subtype for the full view and verify that it statically matches -- the subtype of the partial view. procedure Check_Recursive_Declaration (Typ : Entity_Id); -- If deferred constant is an access type initialized with an allocator, -- check whether there is an illegal recursion in the definition, -- through a default value of some record subcomponent. This is normally -- detected when generating init procs, but requires this additional -- mechanism when expansion is disabled. ---------------------------------------- -- Check_Possible_Deferred_Completion -- ---------------------------------------- procedure Check_Possible_Deferred_Completion (Prev_Id : Entity_Id; Prev_Obj_Def : Node_Id; Curr_Obj_Def : Node_Id) is begin if Nkind (Prev_Obj_Def) = N_Subtype_Indication and then Present (Constraint (Prev_Obj_Def)) and then Nkind (Curr_Obj_Def) = N_Subtype_Indication and then Present (Constraint (Curr_Obj_Def)) then declare Loc : constant Source_Ptr := Sloc (N); Def_Id : constant Entity_Id := Make_Temporary (Loc, 'S'); Decl : constant Node_Id := Make_Subtype_Declaration (Loc, Defining_Identifier => Def_Id, Subtype_Indication => Relocate_Node (Curr_Obj_Def)); begin Insert_Before_And_Analyze (N, Decl); Set_Etype (Id, Def_Id); if not Subtypes_Statically_Match (Etype (Prev_Id), Def_Id) then Error_Msg_Sloc := Sloc (Prev_Id); Error_Msg_N ("subtype does not statically match deferred " & "declaration #", N); end if; end; end if; end Check_Possible_Deferred_Completion; --------------------------------- -- Check_Recursive_Declaration -- --------------------------------- procedure Check_Recursive_Declaration (Typ : Entity_Id) is Comp : Entity_Id; begin if Is_Record_Type (Typ) then Comp := First_Component (Typ); while Present (Comp) loop if Comes_From_Source (Comp) then if Present (Expression (Parent (Comp))) and then Is_Entity_Name (Expression (Parent (Comp))) and then Entity (Expression (Parent (Comp))) = Prev then Error_Msg_Sloc := Sloc (Parent (Comp)); Error_Msg_NE ("illegal circularity with declaration for & #", N, Comp); return; elsif Is_Record_Type (Etype (Comp)) then Check_Recursive_Declaration (Etype (Comp)); end if; end if; Next_Component (Comp); end loop; end if; end Check_Recursive_Declaration; -- Start of processing for Constant_Redeclaration begin if Nkind (Parent (Prev)) = N_Object_Declaration then if Nkind (Object_Definition (Parent (Prev))) = N_Subtype_Indication then -- Find type of new declaration. The constraints of the two -- views must match statically, but there is no point in -- creating an itype for the full view. if Nkind (Obj_Def) = N_Subtype_Indication then Find_Type (Subtype_Mark (Obj_Def)); New_T := Entity (Subtype_Mark (Obj_Def)); else Find_Type (Obj_Def); New_T := Entity (Obj_Def); end if; T := Etype (Prev); else -- The full view may impose a constraint, even if the partial -- view does not, so construct the subtype. New_T := Find_Type_Of_Object (Obj_Def, N); T := New_T; end if; else -- Current declaration is illegal, diagnosed below in Enter_Name T := Empty; New_T := Any_Type; end if; -- If previous full declaration or a renaming declaration exists, or if -- a homograph is present, let Enter_Name handle it, either with an -- error or with the removal of an overridden implicit subprogram. -- The previous one is a full declaration if it has an expression -- (which in the case of an aggregate is indicated by the Init flag). if Ekind (Prev) /= E_Constant or else Nkind (Parent (Prev)) = N_Object_Renaming_Declaration or else Present (Expression (Parent (Prev))) or else Has_Init_Expression (Parent (Prev)) or else Present (Full_View (Prev)) then Enter_Name (Id); -- Verify that types of both declarations match, or else that both types -- are anonymous access types whose designated subtypes statically match -- (as allowed in Ada 2005 by AI-385). elsif Base_Type (Etype (Prev)) /= Base_Type (New_T) and then (Ekind (Etype (Prev)) /= E_Anonymous_Access_Type or else Ekind (Etype (New_T)) /= E_Anonymous_Access_Type or else Is_Access_Constant (Etype (New_T)) /= Is_Access_Constant (Etype (Prev)) or else Can_Never_Be_Null (Etype (New_T)) /= Can_Never_Be_Null (Etype (Prev)) or else Null_Exclusion_Present (Parent (Prev)) /= Null_Exclusion_Present (Parent (Id)) or else not Subtypes_Statically_Match (Designated_Type (Etype (Prev)), Designated_Type (Etype (New_T)))) then Error_Msg_Sloc := Sloc (Prev); Error_Msg_N ("type does not match declaration#", N); Set_Full_View (Prev, Id); Set_Etype (Id, Any_Type); -- A deferred constant whose type is an anonymous array is always -- illegal (unless imported). A detailed error message might be -- helpful for Ada beginners. if Nkind (Object_Definition (Parent (Prev))) = N_Constrained_Array_Definition and then Nkind (Object_Definition (N)) = N_Constrained_Array_Definition then Error_Msg_N ("\each anonymous array is a distinct type", N); Error_Msg_N ("a deferred constant must have a named type", Object_Definition (Parent (Prev))); end if; elsif Null_Exclusion_Present (Parent (Prev)) and then not Null_Exclusion_Present (N) then Error_Msg_Sloc := Sloc (Prev); Error_Msg_N ("null-exclusion does not match declaration#", N); Set_Full_View (Prev, Id); Set_Etype (Id, Any_Type); -- If so, process the full constant declaration else -- RM 7.4 (6): If the subtype defined by the subtype_indication in -- the deferred declaration is constrained, then the subtype defined -- by the subtype_indication in the full declaration shall match it -- statically. Check_Possible_Deferred_Completion (Prev_Id => Prev, Prev_Obj_Def => Object_Definition (Parent (Prev)), Curr_Obj_Def => Obj_Def); Set_Full_View (Prev, Id); Set_Is_Public (Id, Is_Public (Prev)); Set_Is_Internal (Id); Append_Entity (Id, Current_Scope); -- Check ALIASED present if present before (RM 7.4(7)) if Is_Aliased (Prev) and then not Aliased_Present (N) then Error_Msg_Sloc := Sloc (Prev); Error_Msg_N ("ALIASED required (see declaration #)", N); end if; -- Check that placement is in private part and that the incomplete -- declaration appeared in the visible part. if Ekind (Current_Scope) = E_Package and then not In_Private_Part (Current_Scope) then Error_Msg_Sloc := Sloc (Prev); Error_Msg_N ("full constant for declaration # must be in private part", N); elsif Ekind (Current_Scope) = E_Package and then List_Containing (Parent (Prev)) /= Visible_Declarations (Package_Specification (Current_Scope)) then Error_Msg_N ("deferred constant must be declared in visible part", Parent (Prev)); end if; if Is_Access_Type (T) and then Nkind (Expression (N)) = N_Allocator then Check_Recursive_Declaration (Designated_Type (T)); end if; -- A deferred constant is a visible entity. If type has invariants, -- verify that the initial value satisfies them. This is not done in -- GNATprove mode, as GNATprove handles invariant checks itself. if Has_Invariants (T) and then Present (Invariant_Procedure (T)) and then not GNATprove_Mode then Insert_After (N, Make_Invariant_Call (New_Occurrence_Of (Prev, Sloc (N)))); end if; end if; end Constant_Redeclaration; ---------------------- -- Constrain_Access -- ---------------------- procedure Constrain_Access (Def_Id : in out Entity_Id; S : Node_Id; Related_Nod : Node_Id) is T : constant Entity_Id := Entity (Subtype_Mark (S)); Desig_Type : constant Entity_Id := Designated_Type (T); Desig_Subtype : Entity_Id := Create_Itype (E_Void, Related_Nod); Constraint_OK : Boolean := True; begin if Is_Array_Type (Desig_Type) then Constrain_Array (Desig_Subtype, S, Related_Nod, Def_Id, 'P'); elsif (Is_Record_Type (Desig_Type) or else Is_Incomplete_Or_Private_Type (Desig_Type)) and then not Is_Constrained (Desig_Type) then -- If this is a constrained access definition for a record -- component, we leave the type as an unconstrained access, -- and mark the component so that its actual type is built -- at a point of use (e.g., an assignment statement). This -- is handled in Sem_Util.Build_Actual_Subtype_Of_Component. if Desig_Type = Current_Scope and then No (Def_Id) then Desig_Subtype := Create_Itype (E_Void, Related_Nod, Scope_Id => Scope (Desig_Type)); Mutate_Ekind (Desig_Subtype, E_Record_Subtype); Def_Id := Entity (Subtype_Mark (S)); -- We indicate that the component has a per-object constraint -- for treatment at a point of use, even though the constraint -- may be independent of discriminants of the enclosing type. if Nkind (Related_Nod) = N_Component_Declaration then Set_Has_Per_Object_Constraint (Defining_Identifier (Related_Nod)); end if; -- This call added to ensure that the constraint is analyzed -- (needed for a B test). Note that we still return early from -- this procedure to avoid recursive processing. Constrain_Discriminated_Type (Desig_Subtype, S, Related_Nod, For_Access => True); return; end if; -- Enforce rule that the constraint is illegal if there is an -- unconstrained view of the designated type. This means that the -- partial view (either a private type declaration or a derivation -- from a private type) has no discriminants. (Defect Report -- 8652/0008, Technical Corrigendum 1, checked by ACATS B371001). -- Rule updated for Ada 2005: The private type is said to have -- a constrained partial view, given that objects of the type -- can be declared. Furthermore, the rule applies to all access -- types, unlike the rule concerning default discriminants (see -- RM 3.7.1(7/3)) if (Ekind (T) = E_General_Access_Type or else Ada_Version >= Ada_2005) and then Has_Private_Declaration (Desig_Type) and then In_Open_Scopes (Scope (Desig_Type)) and then Has_Discriminants (Desig_Type) then declare Pack : constant Node_Id := Unit_Declaration_Node (Scope (Desig_Type)); Decls : List_Id; Decl : Node_Id; begin if Nkind (Pack) = N_Package_Declaration then Decls := Visible_Declarations (Specification (Pack)); Decl := First (Decls); while Present (Decl) loop if (Nkind (Decl) = N_Private_Type_Declaration and then Chars (Defining_Identifier (Decl)) = Chars (Desig_Type)) or else (Nkind (Decl) = N_Full_Type_Declaration and then Chars (Defining_Identifier (Decl)) = Chars (Desig_Type) and then Is_Derived_Type (Desig_Type) and then Has_Private_Declaration (Etype (Desig_Type))) then if No (Discriminant_Specifications (Decl)) then Error_Msg_N ("cannot constrain access type if designated " & "type has constrained partial view", S); end if; exit; end if; Next (Decl); end loop; end if; end; end if; Constrain_Discriminated_Type (Desig_Subtype, S, Related_Nod, For_Access => True); elsif Is_Concurrent_Type (Desig_Type) and then not Is_Constrained (Desig_Type) then Constrain_Concurrent (Desig_Subtype, S, Related_Nod, Desig_Type, ' '); else Error_Msg_N ("invalid constraint on access type", S); -- We simply ignore an invalid constraint Desig_Subtype := Desig_Type; Constraint_OK := False; end if; if No (Def_Id) then Def_Id := Create_Itype (E_Access_Subtype, Related_Nod); else Mutate_Ekind (Def_Id, E_Access_Subtype); end if; if Constraint_OK then Set_Etype (Def_Id, Base_Type (T)); if Is_Private_Type (Desig_Type) then Prepare_Private_Subtype_Completion (Desig_Subtype, Related_Nod); end if; else Set_Etype (Def_Id, Any_Type); end if; Set_Size_Info (Def_Id, T); Set_Is_Constrained (Def_Id, Constraint_OK); Set_Directly_Designated_Type (Def_Id, Desig_Subtype); Set_Depends_On_Private (Def_Id, Has_Private_Component (Def_Id)); Set_Is_Access_Constant (Def_Id, Is_Access_Constant (T)); Conditional_Delay (Def_Id, T); -- AI-363 : Subtypes of general access types whose designated types have -- default discriminants are disallowed. In instances, the rule has to -- be checked against the actual, of which T is the subtype. In a -- generic body, the rule is checked assuming that the actual type has -- defaulted discriminants. if Ada_Version >= Ada_2005 or else Warn_On_Ada_2005_Compatibility then if Ekind (Base_Type (T)) = E_General_Access_Type and then Has_Defaulted_Discriminants (Desig_Type) then if Ada_Version < Ada_2005 then Error_Msg_N ("access subtype of general access type would not " & "be allowed in Ada 2005?y?", S); else Error_Msg_N ("access subtype of general access type not allowed", S); end if; Error_Msg_N ("\discriminants have defaults", S); elsif Is_Access_Type (T) and then Is_Generic_Type (Desig_Type) and then Has_Discriminants (Desig_Type) and then In_Package_Body (Current_Scope) then if Ada_Version < Ada_2005 then Error_Msg_N ("access subtype would not be allowed in generic body " & "in Ada 2005?y?", S); else Error_Msg_N ("access subtype not allowed in generic body", S); end if; Error_Msg_N ("\designated type is a discriminated formal", S); end if; end if; end Constrain_Access; --------------------- -- Constrain_Array -- --------------------- procedure Constrain_Array (Def_Id : in out Entity_Id; SI : Node_Id; Related_Nod : Node_Id; Related_Id : Entity_Id; Suffix : Character) is C : constant Node_Id := Constraint (SI); Number_Of_Constraints : Nat := 0; Index : Node_Id; S, T : Entity_Id; Constraint_OK : Boolean := True; Is_FLB_Array_Subtype : Boolean := False; begin T := Entity (Subtype_Mark (SI)); if Is_Access_Type (T) then T := Designated_Type (T); end if; -- If an index constraint follows a subtype mark in a subtype indication -- then the type or subtype denoted by the subtype mark must not already -- impose an index constraint. The subtype mark must denote either an -- unconstrained array type or an access type whose designated type -- is such an array type... (RM 3.6.1) if Is_Constrained (T) then Error_Msg_N ("array type is already constrained", Subtype_Mark (SI)); Constraint_OK := False; else S := First (Constraints (C)); while Present (S) loop Number_Of_Constraints := Number_Of_Constraints + 1; Next (S); end loop; -- In either case, the index constraint must provide a discrete -- range for each index of the array type and the type of each -- discrete range must be the same as that of the corresponding -- index. (RM 3.6.1) if Number_Of_Constraints /= Number_Dimensions (T) then Error_Msg_NE ("incorrect number of index constraints for }", C, T); Constraint_OK := False; else S := First (Constraints (C)); Index := First_Index (T); Analyze (Index); -- Apply constraints to each index type for J in 1 .. Number_Of_Constraints loop Constrain_Index (Index, S, Related_Nod, Related_Id, Suffix, J); -- If the subtype of the index has been set to indicate that -- it has a fixed lower bound, then record that the subtype's -- entity will need to be marked as being a fixed-lower-bound -- array subtype. if S = First (Constraints (C)) then Is_FLB_Array_Subtype := Is_Fixed_Lower_Bound_Index_Subtype (Etype (S)); -- If the parent subtype (or should this be Etype of that?) -- is an FLB array subtype, we flag an error, because we -- don't currently allow subtypes of such subtypes to -- specify a fixed lower bound for any of their indexes, -- even if the index of the parent subtype is a "range <>" -- index. if Is_FLB_Array_Subtype and then Is_Fixed_Lower_Bound_Array_Subtype (T) then Error_Msg_NE ("index with fixed lower bound not allowed for subtype " & "of fixed-lower-bound }", S, T); Is_FLB_Array_Subtype := False; end if; elsif Is_FLB_Array_Subtype and then not Is_Fixed_Lower_Bound_Index_Subtype (Etype (S)) then Error_Msg_NE ("constrained index not allowed for fixed-lower-bound " & "subtype of}", S, T); elsif not Is_FLB_Array_Subtype and then Is_Fixed_Lower_Bound_Index_Subtype (Etype (S)) then Error_Msg_NE ("index with fixed lower bound not allowed for " & "constrained subtype of}", S, T); end if; Next (Index); Next (S); end loop; end if; end if; if No (Def_Id) then Def_Id := Create_Itype (E_Array_Subtype, Related_Nod, Related_Id, Suffix); Set_Parent (Def_Id, Related_Nod); else Mutate_Ekind (Def_Id, E_Array_Subtype); end if; Set_Size_Info (Def_Id, (T)); Set_First_Rep_Item (Def_Id, First_Rep_Item (T)); Set_Etype (Def_Id, Base_Type (T)); if Constraint_OK then Set_First_Index (Def_Id, First (Constraints (C))); else Set_First_Index (Def_Id, First_Index (T)); end if; Set_Is_Constrained (Def_Id, not Is_FLB_Array_Subtype); Set_Is_Fixed_Lower_Bound_Array_Subtype (Def_Id, Is_FLB_Array_Subtype); Set_Is_Aliased (Def_Id, Is_Aliased (T)); Set_Is_Independent (Def_Id, Is_Independent (T)); Set_Depends_On_Private (Def_Id, Has_Private_Component (Def_Id)); Set_Is_Private_Composite (Def_Id, Is_Private_Composite (T)); Set_Is_Limited_Composite (Def_Id, Is_Limited_Composite (T)); -- A subtype does not inherit the Packed_Array_Impl_Type of is parent. -- We need to initialize the attribute because if Def_Id is previously -- analyzed through a limited_with clause, it will have the attributes -- of an incomplete type, one of which is an Elist that overlaps the -- Packed_Array_Impl_Type field. Set_Packed_Array_Impl_Type (Def_Id, Empty); -- Build a freeze node if parent still needs one. Also make sure that -- the Depends_On_Private status is set because the subtype will need -- reprocessing at the time the base type does, and also we must set a -- conditional delay. Set_Depends_On_Private (Def_Id, Depends_On_Private (T)); Conditional_Delay (Def_Id, T); end Constrain_Array; ------------------------------ -- Constrain_Component_Type -- ------------------------------ function Constrain_Component_Type (Comp : Entity_Id; Constrained_Typ : Entity_Id; Related_Node : Node_Id; Typ : Entity_Id; Constraints : Elist_Id) return Entity_Id is Loc : constant Source_Ptr := Sloc (Constrained_Typ); Compon_Type : constant Entity_Id := Etype (Comp); function Build_Constrained_Array_Type (Old_Type : Entity_Id) return Entity_Id; -- If Old_Type is an array type, one of whose indexes is constrained -- by a discriminant, build an Itype whose constraint replaces the -- discriminant with its value in the constraint. function Build_Constrained_Discriminated_Type (Old_Type : Entity_Id) return Entity_Id; -- Ditto for record components. Handle the case where the constraint -- is a conversion of the discriminant value, introduced during -- expansion. function Build_Constrained_Access_Type (Old_Type : Entity_Id) return Entity_Id; -- Ditto for access types. Makes use of previous two functions, to -- constrain designated type. function Is_Discriminant (Expr : Node_Id) return Boolean; -- Returns True if Expr is a discriminant function Get_Discr_Value (Discr_Expr : Node_Id) return Node_Id; -- Find the value of a discriminant named by Discr_Expr in Constraints ----------------------------------- -- Build_Constrained_Access_Type -- ----------------------------------- function Build_Constrained_Access_Type (Old_Type : Entity_Id) return Entity_Id is Desig_Type : constant Entity_Id := Designated_Type (Old_Type); Itype : Entity_Id; Desig_Subtype : Entity_Id; Scop : Entity_Id; begin -- If the original access type was not embedded in the enclosing -- type definition, there is no need to produce a new access -- subtype. In fact every access type with an explicit constraint -- generates an itype whose scope is the enclosing record. if not Is_Type (Scope (Old_Type)) then return Old_Type; elsif Is_Array_Type (Desig_Type) then Desig_Subtype := Build_Constrained_Array_Type (Desig_Type); elsif Has_Discriminants (Desig_Type) then -- This may be an access type to an enclosing record type for -- which we are constructing the constrained components. Return -- the enclosing record subtype. This is not always correct, -- but avoids infinite recursion. ??? Desig_Subtype := Any_Type; for J in reverse 0 .. Scope_Stack.Last loop Scop := Scope_Stack.Table (J).Entity; if Is_Type (Scop) and then Base_Type (Scop) = Base_Type (Desig_Type) then Desig_Subtype := Scop; end if; exit when not Is_Type (Scop); end loop; if Desig_Subtype = Any_Type then Desig_Subtype := Build_Constrained_Discriminated_Type (Desig_Type); end if; else return Old_Type; end if; if Desig_Subtype /= Desig_Type then -- The Related_Node better be here or else we won't be able -- to attach new itypes to a node in the tree. pragma Assert (Present (Related_Node)); Itype := Create_Itype (E_Access_Subtype, Related_Node); Set_Etype (Itype, Base_Type (Old_Type)); Set_Size_Info (Itype, (Old_Type)); Set_Directly_Designated_Type (Itype, Desig_Subtype); Set_Depends_On_Private (Itype, Has_Private_Component (Old_Type)); Set_Is_Access_Constant (Itype, Is_Access_Constant (Old_Type)); -- The new itype needs freezing when it depends on a not frozen -- type and the enclosing subtype needs freezing. if Has_Delayed_Freeze (Constrained_Typ) and then not Is_Frozen (Constrained_Typ) then Conditional_Delay (Itype, Base_Type (Old_Type)); end if; return Itype; else return Old_Type; end if; end Build_Constrained_Access_Type; ---------------------------------- -- Build_Constrained_Array_Type -- ---------------------------------- function Build_Constrained_Array_Type (Old_Type : Entity_Id) return Entity_Id is Lo_Expr : Node_Id; Hi_Expr : Node_Id; Old_Index : Node_Id; Range_Node : Node_Id; Constr_List : List_Id; Need_To_Create_Itype : Boolean := False; begin Old_Index := First_Index (Old_Type); while Present (Old_Index) loop Get_Index_Bounds (Old_Index, Lo_Expr, Hi_Expr); if Is_Discriminant (Lo_Expr) or else Is_Discriminant (Hi_Expr) then Need_To_Create_Itype := True; exit; end if; Next_Index (Old_Index); end loop; if Need_To_Create_Itype then Constr_List := New_List; Old_Index := First_Index (Old_Type); while Present (Old_Index) loop Get_Index_Bounds (Old_Index, Lo_Expr, Hi_Expr); if Is_Discriminant (Lo_Expr) then Lo_Expr := Get_Discr_Value (Lo_Expr); end if; if Is_Discriminant (Hi_Expr) then Hi_Expr := Get_Discr_Value (Hi_Expr); end if; Range_Node := Make_Range (Loc, New_Copy_Tree (Lo_Expr), New_Copy_Tree (Hi_Expr)); Append (Range_Node, To => Constr_List); Next_Index (Old_Index); end loop; return Build_Subtype (Related_Node, Loc, Old_Type, Constr_List); else return Old_Type; end if; end Build_Constrained_Array_Type; ------------------------------------------ -- Build_Constrained_Discriminated_Type -- ------------------------------------------ function Build_Constrained_Discriminated_Type (Old_Type : Entity_Id) return Entity_Id is Expr : Node_Id; Constr_List : List_Id; Old_Constraint : Elmt_Id; Need_To_Create_Itype : Boolean := False; begin Old_Constraint := First_Elmt (Discriminant_Constraint (Old_Type)); while Present (Old_Constraint) loop Expr := Node (Old_Constraint); if Is_Discriminant (Expr) then Need_To_Create_Itype := True; exit; -- After expansion of discriminated task types, the value -- of the discriminant may be converted to a run-time type -- for restricted run-times. Propagate the value of the -- discriminant as well, so that e.g. the secondary stack -- component has a static constraint. Necessary for LLVM. elsif Nkind (Expr) = N_Type_Conversion and then Is_Discriminant (Expression (Expr)) then Need_To_Create_Itype := True; exit; end if; Next_Elmt (Old_Constraint); end loop; if Need_To_Create_Itype then Constr_List := New_List; Old_Constraint := First_Elmt (Discriminant_Constraint (Old_Type)); while Present (Old_Constraint) loop Expr := Node (Old_Constraint); if Is_Discriminant (Expr) then Expr := Get_Discr_Value (Expr); elsif Nkind (Expr) = N_Type_Conversion and then Is_Discriminant (Expression (Expr)) then Expr := New_Copy_Tree (Expr); Set_Expression (Expr, Get_Discr_Value (Expression (Expr))); end if; Append (New_Copy_Tree (Expr), To => Constr_List); Next_Elmt (Old_Constraint); end loop; return Build_Subtype (Related_Node, Loc, Old_Type, Constr_List); else return Old_Type; end if; end Build_Constrained_Discriminated_Type; --------------------- -- Get_Discr_Value -- --------------------- function Get_Discr_Value (Discr_Expr : Node_Id) return Node_Id is Discr_Id : constant Entity_Id := Entity (Discr_Expr); -- Entity of a discriminant that appear as a standalone expression in -- the constraint of a component. D : Entity_Id; E : Elmt_Id; begin -- The discriminant may be declared for the type, in which case we -- find it by iterating over the list of discriminants. If the -- discriminant is inherited from a parent type, it appears as the -- corresponding discriminant of the current type. This will be the -- case when constraining an inherited component whose constraint is -- given by a discriminant of the parent. D := First_Discriminant (Typ); E := First_Elmt (Constraints); while Present (D) loop if D = Discr_Id or else D = CR_Discriminant (Discr_Id) or else Corresponding_Discriminant (D) = Discr_Id then return Node (E); end if; Next_Discriminant (D); Next_Elmt (E); end loop; -- The Corresponding_Discriminant mechanism is incomplete, because -- the correspondence between new and old discriminants is not one -- to one: one new discriminant can constrain several old ones. In -- that case, scan sequentially the stored_constraint, the list of -- discriminants of the parents, and the constraints. -- Previous code checked for the present of the Stored_Constraint -- list for the derived type, but did not use it at all. Should it -- be present when the component is a discriminated task type? if Is_Derived_Type (Typ) and then Scope (Discr_Id) = Etype (Typ) then D := First_Discriminant (Etype (Typ)); E := First_Elmt (Constraints); while Present (D) loop if D = Discr_Id then return Node (E); end if; Next_Discriminant (D); Next_Elmt (E); end loop; end if; -- Something is wrong if we did not find the value raise Program_Error; end Get_Discr_Value; --------------------- -- Is_Discriminant -- --------------------- function Is_Discriminant (Expr : Node_Id) return Boolean is Discrim_Scope : Entity_Id; begin if Denotes_Discriminant (Expr) then Discrim_Scope := Scope (Entity (Expr)); -- Either we have a reference to one of Typ's discriminants, pragma Assert (Discrim_Scope = Typ -- or to the discriminants of the parent type, in the case -- of a derivation of a tagged type with variants. or else Discrim_Scope = Etype (Typ) or else Full_View (Discrim_Scope) = Etype (Typ) -- or same as above for the case where the discriminants -- were declared in Typ's private view. or else (Is_Private_Type (Discrim_Scope) and then Chars (Discrim_Scope) = Chars (Typ)) -- or else we are deriving from the full view and the -- discriminant is declared in the private entity. or else (Is_Private_Type (Typ) and then Chars (Discrim_Scope) = Chars (Typ)) -- Or we are constrained the corresponding record of a -- synchronized type that completes a private declaration. or else (Is_Concurrent_Record_Type (Typ) and then Corresponding_Concurrent_Type (Typ) = Discrim_Scope) -- or we have a class-wide type, in which case make sure the -- discriminant found belongs to the root type. or else (Is_Class_Wide_Type (Typ) and then Etype (Typ) = Discrim_Scope)); return True; end if; -- In all other cases we have something wrong return False; end Is_Discriminant; -- Start of processing for Constrain_Component_Type begin if Nkind (Parent (Comp)) = N_Component_Declaration and then Comes_From_Source (Parent (Comp)) and then Comes_From_Source (Subtype_Indication (Component_Definition (Parent (Comp)))) and then Is_Entity_Name (Subtype_Indication (Component_Definition (Parent (Comp)))) then return Compon_Type; elsif Is_Array_Type (Compon_Type) then return Build_Constrained_Array_Type (Compon_Type); elsif Has_Discriminants (Compon_Type) then return Build_Constrained_Discriminated_Type (Compon_Type); elsif Is_Access_Type (Compon_Type) then return Build_Constrained_Access_Type (Compon_Type); else return Compon_Type; end if; end Constrain_Component_Type; -------------------------- -- Constrain_Concurrent -- -------------------------- -- For concurrent types, the associated record value type carries the same -- discriminants, so when we constrain a concurrent type, we must constrain -- the corresponding record type as well. procedure Constrain_Concurrent (Def_Id : in out Entity_Id; SI : Node_Id; Related_Nod : Node_Id; Related_Id : Entity_Id; Suffix : Character) is -- Retrieve Base_Type to ensure getting to the concurrent type in the -- case of a private subtype (needed when only doing semantic analysis). T_Ent : Entity_Id := Base_Type (Entity (Subtype_Mark (SI))); T_Val : Entity_Id; begin if Is_Access_Type (T_Ent) then T_Ent := Designated_Type (T_Ent); end if; T_Val := Corresponding_Record_Type (T_Ent); if Present (T_Val) then if No (Def_Id) then Def_Id := Create_Itype (E_Void, Related_Nod, Related_Id, Suffix); -- Elaborate itype now, as it may be used in a subsequent -- synchronized operation in another scope. if Nkind (Related_Nod) = N_Full_Type_Declaration then Build_Itype_Reference (Def_Id, Related_Nod); end if; end if; Constrain_Discriminated_Type (Def_Id, SI, Related_Nod); Set_First_Private_Entity (Def_Id, First_Private_Entity (T_Ent)); Set_Depends_On_Private (Def_Id, Has_Private_Component (Def_Id)); Set_Corresponding_Record_Type (Def_Id, Constrain_Corresponding_Record (Def_Id, T_Val, Related_Nod)); else -- If there is no associated record, expansion is disabled and this -- is a generic context. Create a subtype in any case, so that -- semantic analysis can proceed. if No (Def_Id) then Def_Id := Create_Itype (E_Void, Related_Nod, Related_Id, Suffix); end if; Constrain_Discriminated_Type (Def_Id, SI, Related_Nod); end if; end Constrain_Concurrent; ------------------------------------ -- Constrain_Corresponding_Record -- ------------------------------------ function Constrain_Corresponding_Record (Prot_Subt : Entity_Id; Corr_Rec : Entity_Id; Related_Nod : Node_Id) return Entity_Id is T_Sub : constant Entity_Id := Create_Itype (Ekind => E_Record_Subtype, Related_Nod => Related_Nod, Related_Id => Corr_Rec, Suffix => 'C', Suffix_Index => -1); begin Set_Etype (T_Sub, Corr_Rec); Set_Has_Discriminants (T_Sub, Has_Discriminants (Prot_Subt)); Set_Is_Tagged_Type (T_Sub, Is_Tagged_Type (Corr_Rec)); Set_Is_Constrained (T_Sub, True); Set_First_Entity (T_Sub, First_Entity (Corr_Rec)); Set_Last_Entity (T_Sub, Last_Entity (Corr_Rec)); if Has_Discriminants (Prot_Subt) then -- False only if errors. Set_Discriminant_Constraint (T_Sub, Discriminant_Constraint (Prot_Subt)); Set_Stored_Constraint_From_Discriminant_Constraint (T_Sub); Create_Constrained_Components (T_Sub, Related_Nod, Corr_Rec, Discriminant_Constraint (T_Sub)); end if; Set_Depends_On_Private (T_Sub, Has_Private_Component (T_Sub)); if Ekind (Scope (Prot_Subt)) /= E_Record_Type then Conditional_Delay (T_Sub, Corr_Rec); else -- This is a component subtype: it will be frozen in the context of -- the enclosing record's init_proc, so that discriminant references -- are resolved to discriminals. (Note: we used to skip freezing -- altogether in that case, which caused errors downstream for -- components of a bit packed array type). Set_Has_Delayed_Freeze (T_Sub); end if; return T_Sub; end Constrain_Corresponding_Record; ----------------------- -- Constrain_Decimal -- ----------------------- procedure Constrain_Decimal (Def_Id : Entity_Id; S : Node_Id) is T : constant Entity_Id := Entity (Subtype_Mark (S)); C : constant Node_Id := Constraint (S); Loc : constant Source_Ptr := Sloc (C); Range_Expr : Node_Id; Digits_Expr : Node_Id; Digits_Val : Uint; Bound_Val : Ureal; begin Mutate_Ekind (Def_Id, E_Decimal_Fixed_Point_Subtype); if Nkind (C) = N_Range_Constraint then Range_Expr := Range_Expression (C); Digits_Val := Digits_Value (T); else pragma Assert (Nkind (C) = N_Digits_Constraint); Digits_Expr := Digits_Expression (C); Analyze_And_Resolve (Digits_Expr, Any_Integer); Check_Digits_Expression (Digits_Expr); Digits_Val := Expr_Value (Digits_Expr); if Digits_Val > Digits_Value (T) then Error_Msg_N ("digits expression is incompatible with subtype", C); Digits_Val := Digits_Value (T); end if; if Present (Range_Constraint (C)) then Range_Expr := Range_Expression (Range_Constraint (C)); else Range_Expr := Empty; end if; end if; Set_Etype (Def_Id, Base_Type (T)); Set_Size_Info (Def_Id, (T)); Set_First_Rep_Item (Def_Id, First_Rep_Item (T)); Set_Delta_Value (Def_Id, Delta_Value (T)); Set_Scale_Value (Def_Id, Scale_Value (T)); Set_Small_Value (Def_Id, Small_Value (T)); Set_Machine_Radix_10 (Def_Id, Machine_Radix_10 (T)); Set_Digits_Value (Def_Id, Digits_Val); -- Manufacture range from given digits value if no range present if No (Range_Expr) then Bound_Val := (Ureal_10 ** Digits_Val - Ureal_1) * Small_Value (T); Range_Expr := Make_Range (Loc, Low_Bound => Convert_To (T, Make_Real_Literal (Loc, (-Bound_Val))), High_Bound => Convert_To (T, Make_Real_Literal (Loc, Bound_Val))); end if; Set_Scalar_Range_For_Subtype (Def_Id, Range_Expr, T); Set_Discrete_RM_Size (Def_Id); -- Unconditionally delay the freeze, since we cannot set size -- information in all cases correctly until the freeze point. Set_Has_Delayed_Freeze (Def_Id); end Constrain_Decimal; ---------------------------------- -- Constrain_Discriminated_Type -- ---------------------------------- procedure Constrain_Discriminated_Type (Def_Id : Entity_Id; S : Node_Id; Related_Nod : Node_Id; For_Access : Boolean := False) is E : Entity_Id := Entity (Subtype_Mark (S)); T : Entity_Id; procedure Fixup_Bad_Constraint; -- Called after finding a bad constraint, and after having posted an -- appropriate error message. The goal is to leave type Def_Id in as -- reasonable state as possible. -------------------------- -- Fixup_Bad_Constraint -- -------------------------- procedure Fixup_Bad_Constraint is begin -- Set a reasonable Ekind for the entity, including incomplete types. Mutate_Ekind (Def_Id, Subtype_Kind (Ekind (T))); -- Set Etype to the known type, to reduce chances of cascaded errors Set_Etype (Def_Id, E); Set_Error_Posted (Def_Id); end Fixup_Bad_Constraint; -- Local variables C : Node_Id; Constr : Elist_Id := New_Elmt_List; -- Start of processing for Constrain_Discriminated_Type begin C := Constraint (S); -- A discriminant constraint is only allowed in a subtype indication, -- after a subtype mark. This subtype mark must denote either a type -- with discriminants, or an access type whose designated type is a -- type with discriminants. A discriminant constraint specifies the -- values of these discriminants (RM 3.7.2(5)). T := Base_Type (Entity (Subtype_Mark (S))); if Is_Access_Type (T) then T := Designated_Type (T); end if; -- In an instance it may be necessary to retrieve the full view of a -- type with unknown discriminants, or a full view with defaulted -- discriminants. In other contexts the constraint is illegal. if In_Instance and then Is_Private_Type (T) and then Present (Full_View (T)) and then (Has_Unknown_Discriminants (T) or else (not Has_Discriminants (T) and then Has_Defaulted_Discriminants (Full_View (T)))) then T := Full_View (T); E := Full_View (E); end if; -- Ada 2005 (AI-412): Constrained incomplete subtypes are illegal. Avoid -- generating an error for access-to-incomplete subtypes. if Ada_Version >= Ada_2005 and then Ekind (T) = E_Incomplete_Type and then Nkind (Parent (S)) = N_Subtype_Declaration and then not Is_Itype (Def_Id) then -- A little sanity check: emit an error message if the type has -- discriminants to begin with. Type T may be a regular incomplete -- type or imported via a limited with clause. if Has_Discriminants (T) or else (From_Limited_With (T) and then Present (Non_Limited_View (T)) and then Nkind (Parent (Non_Limited_View (T))) = N_Full_Type_Declaration and then Present (Discriminant_Specifications (Parent (Non_Limited_View (T))))) then Error_Msg_N ("(Ada 2005) incomplete subtype may not be constrained", C); else Error_Msg_N ("invalid constraint: type has no discriminant", C); end if; Fixup_Bad_Constraint; return; -- Check that the type has visible discriminants. The type may be -- a private type with unknown discriminants whose full view has -- discriminants which are invisible. elsif not Has_Discriminants (T) or else (Has_Unknown_Discriminants (T) and then Is_Private_Type (T)) then Error_Msg_N ("invalid constraint: type has no discriminant", C); Fixup_Bad_Constraint; return; elsif Is_Constrained (E) or else (Ekind (E) = E_Class_Wide_Subtype and then Present (Discriminant_Constraint (E))) then Error_Msg_N ("type is already constrained", Subtype_Mark (S)); Fixup_Bad_Constraint; return; end if; -- T may be an unconstrained subtype (e.g. a generic actual). Constraint -- applies to the base type. T := Base_Type (T); Constr := Build_Discriminant_Constraints (T, S); -- If the list returned was empty we had an error in building the -- discriminant constraint. We have also already signalled an error -- in the incomplete type case if Is_Empty_Elmt_List (Constr) then Fixup_Bad_Constraint; return; end if; Build_Discriminated_Subtype (T, Def_Id, Constr, Related_Nod, For_Access); end Constrain_Discriminated_Type; --------------------------- -- Constrain_Enumeration -- --------------------------- procedure Constrain_Enumeration (Def_Id : Entity_Id; S : Node_Id) is T : constant Entity_Id := Entity (Subtype_Mark (S)); C : constant Node_Id := Constraint (S); begin Mutate_Ekind (Def_Id, E_Enumeration_Subtype); Set_First_Literal (Def_Id, First_Literal (Base_Type (T))); Set_Etype (Def_Id, Base_Type (T)); Set_Size_Info (Def_Id, (T)); Set_First_Rep_Item (Def_Id, First_Rep_Item (T)); Set_Is_Character_Type (Def_Id, Is_Character_Type (T)); Set_Scalar_Range_For_Subtype (Def_Id, Range_Expression (C), T); Set_Discrete_RM_Size (Def_Id); end Constrain_Enumeration; ---------------------- -- Constrain_Float -- ---------------------- procedure Constrain_Float (Def_Id : Entity_Id; S : Node_Id) is T : constant Entity_Id := Entity (Subtype_Mark (S)); C : Node_Id; D : Node_Id; Rais : Node_Id; begin Mutate_Ekind (Def_Id, E_Floating_Point_Subtype); Set_Etype (Def_Id, Base_Type (T)); Set_Size_Info (Def_Id, (T)); Set_First_Rep_Item (Def_Id, First_Rep_Item (T)); -- Process the constraint C := Constraint (S); -- Digits constraint present if Nkind (C) = N_Digits_Constraint then Check_Restriction (No_Obsolescent_Features, C); if Warn_On_Obsolescent_Feature then Error_Msg_N ("subtype digits constraint is an " & "obsolescent feature (RM J.3(8))?j?", C); end if; D := Digits_Expression (C); Analyze_And_Resolve (D, Any_Integer); Check_Digits_Expression (D); Set_Digits_Value (Def_Id, Expr_Value (D)); -- Check that digits value is in range. Obviously we can do this -- at compile time, but it is strictly a runtime check, and of -- course there is an ACVC test that checks this. if Digits_Value (Def_Id) > Digits_Value (T) then Error_Msg_Uint_1 := Digits_Value (T); Error_Msg_N ("??digits value is too large, maximum is ^", D); Rais := Make_Raise_Constraint_Error (Sloc (D), Reason => CE_Range_Check_Failed); Insert_Action (Declaration_Node (Def_Id), Rais); end if; C := Range_Constraint (C); -- No digits constraint present else Set_Digits_Value (Def_Id, Digits_Value (T)); end if; -- Range constraint present if Nkind (C) = N_Range_Constraint then Set_Scalar_Range_For_Subtype (Def_Id, Range_Expression (C), T); -- No range constraint present else pragma Assert (No (C)); Set_Scalar_Range (Def_Id, Scalar_Range (T)); end if; Set_Is_Constrained (Def_Id); end Constrain_Float; --------------------- -- Constrain_Index -- --------------------- procedure Constrain_Index (Index : Node_Id; S : Node_Id; Related_Nod : Node_Id; Related_Id : Entity_Id; Suffix : Character; Suffix_Index : Pos) is Def_Id : Entity_Id; R : Node_Id := Empty; T : constant Entity_Id := Etype (Index); Is_FLB_Index : Boolean := False; begin Def_Id := Create_Itype (E_Void, Related_Nod, Related_Id, Suffix, Suffix_Index); Set_Etype (Def_Id, Base_Type (T)); if Nkind (S) = N_Range or else (Nkind (S) = N_Attribute_Reference and then Attribute_Name (S) = Name_Range) then -- A Range attribute will be transformed into N_Range by Resolve -- If a range has an Empty upper bound, then remember that for later -- setting of the index subtype's Is_Fixed_Lower_Bound_Index_Subtype -- flag, and also set the upper bound of the range to the index -- subtype's upper bound rather than leaving it Empty. In truth, -- that upper bound corresponds to a box ("<>"), but it's convenient -- to set it to the upper bound to avoid needing to add special tests -- in various places for an Empty upper bound, and in any case it -- accurately characterizes the index's range of values. if Nkind (S) = N_Range and then not Present (High_Bound (S)) then Is_FLB_Index := True; Set_High_Bound (S, Type_High_Bound (T)); end if; R := S; Process_Range_Expr_In_Decl (R, T); if not Error_Posted (S) and then (Nkind (S) /= N_Range or else not Covers (T, (Etype (Low_Bound (S)))) or else not Covers (T, (Etype (High_Bound (S))))) then if Base_Type (T) /= Any_Type and then Etype (Low_Bound (S)) /= Any_Type and then Etype (High_Bound (S)) /= Any_Type then Error_Msg_N ("range expected", S); end if; end if; elsif Nkind (S) = N_Subtype_Indication then -- The parser has verified that this is a discrete indication Resolve_Discrete_Subtype_Indication (S, T); Bad_Predicated_Subtype_Use ("subtype& has predicate, not allowed in index constraint", S, Entity (Subtype_Mark (S))); R := Range_Expression (Constraint (S)); -- Capture values of bounds and generate temporaries for them if -- needed, since checks may cause duplication of the expressions -- which must not be reevaluated. -- The forced evaluation removes side effects from expressions, which -- should occur also in GNATprove mode. Otherwise, we end up with -- unexpected insertions of actions at places where this is not -- supposed to occur, e.g. on default parameters of a call. if Expander_Active or GNATprove_Mode then Force_Evaluation (Low_Bound (R), Related_Id => Def_Id, Is_Low_Bound => True); Force_Evaluation (High_Bound (R), Related_Id => Def_Id, Is_High_Bound => True); end if; elsif Nkind (S) = N_Discriminant_Association then -- Syntactically valid in subtype indication Error_Msg_N ("invalid index constraint", S); Rewrite (S, New_Occurrence_Of (T, Sloc (S))); return; -- Subtype_Mark case, no anonymous subtypes to construct else Analyze (S); if Is_Entity_Name (S) then if not Is_Type (Entity (S)) then Error_Msg_N ("expect subtype mark for index constraint", S); elsif Base_Type (Entity (S)) /= Base_Type (T) then Wrong_Type (S, Base_Type (T)); -- Check error of subtype with predicate in index constraint else Bad_Predicated_Subtype_Use ("subtype& has predicate, not allowed in index constraint", S, Entity (S)); end if; return; else Error_Msg_N ("invalid index constraint", S); Rewrite (S, New_Occurrence_Of (T, Sloc (S))); return; end if; end if; -- Complete construction of the Itype if Is_Modular_Integer_Type (T) then Mutate_Ekind (Def_Id, E_Modular_Integer_Subtype); elsif Is_Integer_Type (T) then Mutate_Ekind (Def_Id, E_Signed_Integer_Subtype); else Mutate_Ekind (Def_Id, E_Enumeration_Subtype); Set_Is_Character_Type (Def_Id, Is_Character_Type (T)); Set_First_Literal (Def_Id, First_Literal (T)); end if; Set_Size_Info (Def_Id, (T)); Copy_RM_Size (To => Def_Id, From => T); Set_First_Rep_Item (Def_Id, First_Rep_Item (T)); -- If this is a range for a fixed-lower-bound subtype, then set the -- index itype's low bound to the FLB and the index itype's upper bound -- to the high bound of the parent array type's index subtype. Also, -- mark the itype as an FLB index subtype. if Nkind (S) = N_Range and then Is_FLB_Index then Set_Scalar_Range (Def_Id, Make_Range (Sloc (S), Low_Bound => Low_Bound (S), High_Bound => Type_High_Bound (T))); Set_Is_Fixed_Lower_Bound_Index_Subtype (Def_Id); else Set_Scalar_Range (Def_Id, R); end if; Set_Etype (S, Def_Id); Set_Discrete_RM_Size (Def_Id); end Constrain_Index; ----------------------- -- Constrain_Integer -- ----------------------- procedure Constrain_Integer (Def_Id : Entity_Id; S : Node_Id) is T : constant Entity_Id := Entity (Subtype_Mark (S)); C : constant Node_Id := Constraint (S); begin Set_Scalar_Range_For_Subtype (Def_Id, Range_Expression (C), T); if Is_Modular_Integer_Type (T) then Mutate_Ekind (Def_Id, E_Modular_Integer_Subtype); else Mutate_Ekind (Def_Id, E_Signed_Integer_Subtype); end if; Set_Etype (Def_Id, Base_Type (T)); Set_Size_Info (Def_Id, (T)); Set_First_Rep_Item (Def_Id, First_Rep_Item (T)); Set_Discrete_RM_Size (Def_Id); end Constrain_Integer; ------------------------------ -- Constrain_Ordinary_Fixed -- ------------------------------ procedure Constrain_Ordinary_Fixed (Def_Id : Entity_Id; S : Node_Id) is T : constant Entity_Id := Entity (Subtype_Mark (S)); C : Node_Id; D : Node_Id; Rais : Node_Id; begin Mutate_Ekind (Def_Id, E_Ordinary_Fixed_Point_Subtype); Set_Etype (Def_Id, Base_Type (T)); Set_Size_Info (Def_Id, (T)); Set_First_Rep_Item (Def_Id, First_Rep_Item (T)); Set_Small_Value (Def_Id, Small_Value (T)); -- Process the constraint C := Constraint (S); -- Delta constraint present if Nkind (C) = N_Delta_Constraint then Check_Restriction (No_Obsolescent_Features, C); if Warn_On_Obsolescent_Feature then Error_Msg_S ("subtype delta constraint is an " & "obsolescent feature (RM J.3(7))?j?"); end if; D := Delta_Expression (C); Analyze_And_Resolve (D, Any_Real); Check_Delta_Expression (D); Set_Delta_Value (Def_Id, Expr_Value_R (D)); -- Check that delta value is in range. Obviously we can do this -- at compile time, but it is strictly a runtime check, and of -- course there is an ACVC test that checks this. if Delta_Value (Def_Id) < Delta_Value (T) then Error_Msg_N ("??delta value is too small", D); Rais := Make_Raise_Constraint_Error (Sloc (D), Reason => CE_Range_Check_Failed); Insert_Action (Declaration_Node (Def_Id), Rais); end if; C := Range_Constraint (C); -- No delta constraint present else Set_Delta_Value (Def_Id, Delta_Value (T)); end if; -- Range constraint present if Nkind (C) = N_Range_Constraint then Set_Scalar_Range_For_Subtype (Def_Id, Range_Expression (C), T); -- No range constraint present else pragma Assert (No (C)); Set_Scalar_Range (Def_Id, Scalar_Range (T)); end if; Set_Discrete_RM_Size (Def_Id); -- Unconditionally delay the freeze, since we cannot set size -- information in all cases correctly until the freeze point. Set_Has_Delayed_Freeze (Def_Id); end Constrain_Ordinary_Fixed; ----------------------- -- Contain_Interface -- ----------------------- function Contain_Interface (Iface : Entity_Id; Ifaces : Elist_Id) return Boolean is Iface_Elmt : Elmt_Id; begin if Present (Ifaces) then Iface_Elmt := First_Elmt (Ifaces); while Present (Iface_Elmt) loop if Node (Iface_Elmt) = Iface then return True; end if; Next_Elmt (Iface_Elmt); end loop; end if; return False; end Contain_Interface; --------------------------- -- Convert_Scalar_Bounds -- --------------------------- procedure Convert_Scalar_Bounds (N : Node_Id; Parent_Type : Entity_Id; Derived_Type : Entity_Id; Loc : Source_Ptr) is Implicit_Base : constant Entity_Id := Base_Type (Derived_Type); Lo : Node_Id; Hi : Node_Id; Rng : Node_Id; begin -- Defend against previous errors if No (Scalar_Range (Derived_Type)) then Check_Error_Detected; return; end if; Lo := Build_Scalar_Bound (Type_Low_Bound (Derived_Type), Parent_Type, Implicit_Base); Hi := Build_Scalar_Bound (Type_High_Bound (Derived_Type), Parent_Type, Implicit_Base); Rng := Make_Range (Loc, Low_Bound => Lo, High_Bound => Hi); Set_Includes_Infinities (Rng, Has_Infinities (Derived_Type)); Set_Parent (Rng, N); Set_Scalar_Range (Derived_Type, Rng); -- Analyze the bounds Analyze_And_Resolve (Lo, Implicit_Base); Analyze_And_Resolve (Hi, Implicit_Base); -- Analyze the range itself, except that we do not analyze it if -- the bounds are real literals, and we have a fixed-point type. -- The reason for this is that we delay setting the bounds in this -- case till we know the final Small and Size values (see circuit -- in Freeze.Freeze_Fixed_Point_Type for further details). if Is_Fixed_Point_Type (Parent_Type) and then Nkind (Lo) = N_Real_Literal and then Nkind (Hi) = N_Real_Literal then return; -- Here we do the analysis of the range -- Note: we do this manually, since if we do a normal Analyze and -- Resolve call, there are problems with the conversions used for -- the derived type range. else Set_Etype (Rng, Implicit_Base); Set_Analyzed (Rng, True); end if; end Convert_Scalar_Bounds; ------------------- -- Copy_And_Swap -- ------------------- procedure Copy_And_Swap (Priv, Full : Entity_Id) is begin -- Initialize new full declaration entity by copying the pertinent -- fields of the corresponding private declaration entity. -- We temporarily set Ekind to a value appropriate for a type to -- avoid assert failures in Einfo from checking for setting type -- attributes on something that is not a type. Ekind (Priv) is an -- appropriate choice, since it allowed the attributes to be set -- in the first place. This Ekind value will be modified later. Mutate_Ekind (Full, Ekind (Priv)); -- Also set Etype temporarily to Any_Type, again, in the absence -- of errors, it will be properly reset, and if there are errors, -- then we want a value of Any_Type to remain. Set_Etype (Full, Any_Type); -- Now start copying attributes Set_Has_Discriminants (Full, Has_Discriminants (Priv)); if Has_Discriminants (Full) then Set_Discriminant_Constraint (Full, Discriminant_Constraint (Priv)); Set_Stored_Constraint (Full, Stored_Constraint (Priv)); end if; Set_First_Rep_Item (Full, First_Rep_Item (Priv)); Set_Homonym (Full, Homonym (Priv)); Set_Is_Immediately_Visible (Full, Is_Immediately_Visible (Priv)); Set_Is_Public (Full, Is_Public (Priv)); Set_Is_Pure (Full, Is_Pure (Priv)); Set_Is_Tagged_Type (Full, Is_Tagged_Type (Priv)); Set_Has_Pragma_Unmodified (Full, Has_Pragma_Unmodified (Priv)); Set_Has_Pragma_Unreferenced (Full, Has_Pragma_Unreferenced (Priv)); Set_Has_Pragma_Unreferenced_Objects (Full, Has_Pragma_Unreferenced_Objects (Priv)); Conditional_Delay (Full, Priv); if Is_Tagged_Type (Full) then Set_Direct_Primitive_Operations (Full, Direct_Primitive_Operations (Priv)); Set_No_Tagged_Streams_Pragma (Full, No_Tagged_Streams_Pragma (Priv)); if Is_Base_Type (Priv) then Set_Class_Wide_Type (Full, Class_Wide_Type (Priv)); end if; end if; Set_Is_Volatile (Full, Is_Volatile (Priv)); Set_Treat_As_Volatile (Full, Treat_As_Volatile (Priv)); Set_Scope (Full, Scope (Priv)); Set_Prev_Entity (Full, Prev_Entity (Priv)); Set_Next_Entity (Full, Next_Entity (Priv)); Set_First_Entity (Full, First_Entity (Priv)); Set_Last_Entity (Full, Last_Entity (Priv)); -- If access types have been recorded for later handling, keep them in -- the full view so that they get handled when the full view freeze -- node is expanded. if Present (Freeze_Node (Priv)) and then Present (Access_Types_To_Process (Freeze_Node (Priv))) then Ensure_Freeze_Node (Full); Set_Access_Types_To_Process (Freeze_Node (Full), Access_Types_To_Process (Freeze_Node (Priv))); end if; -- Swap the two entities. Now Private is the full type entity and Full -- is the private one. They will be swapped back at the end of the -- private part. This swapping ensures that the entity that is visible -- in the private part is the full declaration. Exchange_Entities (Priv, Full); Append_Entity (Full, Scope (Full)); end Copy_And_Swap; ------------------------------------- -- Copy_Array_Base_Type_Attributes -- ------------------------------------- procedure Copy_Array_Base_Type_Attributes (T1, T2 : Entity_Id) is begin Set_Component_Alignment (T1, Component_Alignment (T2)); Set_Component_Type (T1, Component_Type (T2)); Set_Component_Size (T1, Component_Size (T2)); Set_Has_Controlled_Component (T1, Has_Controlled_Component (T2)); Set_Has_Non_Standard_Rep (T1, Has_Non_Standard_Rep (T2)); Propagate_Concurrent_Flags (T1, T2); Set_Is_Packed (T1, Is_Packed (T2)); Set_Has_Aliased_Components (T1, Has_Aliased_Components (T2)); Set_Has_Atomic_Components (T1, Has_Atomic_Components (T2)); Set_Has_Independent_Components (T1, Has_Independent_Components (T2)); Set_Has_Volatile_Components (T1, Has_Volatile_Components (T2)); end Copy_Array_Base_Type_Attributes; ----------------------------------- -- Copy_Array_Subtype_Attributes -- ----------------------------------- -- Note that we used to copy Packed_Array_Impl_Type too here, but we now -- let it be recreated during freezing for the sake of better debug info. procedure Copy_Array_Subtype_Attributes (T1, T2 : Entity_Id) is begin Set_Size_Info (T1, T2); Set_First_Index (T1, First_Index (T2)); Set_Is_Aliased (T1, Is_Aliased (T2)); Set_Is_Atomic (T1, Is_Atomic (T2)); Set_Is_Independent (T1, Is_Independent (T2)); Set_Is_Volatile (T1, Is_Volatile (T2)); Set_Is_Volatile_Full_Access (T1, Is_Volatile_Full_Access (T2)); Set_Treat_As_Volatile (T1, Treat_As_Volatile (T2)); Set_Is_Constrained (T1, Is_Constrained (T2)); Set_Depends_On_Private (T1, Has_Private_Component (T2)); Inherit_Rep_Item_Chain (T1, T2); Set_Convention (T1, Convention (T2)); Set_Is_Limited_Composite (T1, Is_Limited_Composite (T2)); Set_Is_Private_Composite (T1, Is_Private_Composite (T2)); end Copy_Array_Subtype_Attributes; ----------------------------------- -- Create_Constrained_Components -- ----------------------------------- procedure Create_Constrained_Components (Subt : Entity_Id; Decl_Node : Node_Id; Typ : Entity_Id; Constraints : Elist_Id) is Loc : constant Source_Ptr := Sloc (Subt); Comp_List : constant Elist_Id := New_Elmt_List; Parent_Type : constant Entity_Id := Etype (Typ); Assoc_List : constant List_Id := New_List; Discr_Val : Elmt_Id; Errors : Boolean; New_C : Entity_Id; Old_C : Entity_Id; Is_Static : Boolean := True; Is_Compile_Time_Known : Boolean := True; procedure Collect_Fixed_Components (Typ : Entity_Id); -- Collect parent type components that do not appear in a variant part procedure Create_All_Components; -- Iterate over Comp_List to create the components of the subtype function Create_Component (Old_Compon : Entity_Id) return Entity_Id; -- Creates a new component from Old_Compon, copying all the fields from -- it, including its Etype, inserts the new component in the Subt entity -- chain and returns the new component. function Is_Variant_Record (T : Entity_Id) return Boolean; -- If true, and discriminants are static, collect only components from -- variants selected by discriminant values. ------------------------------ -- Collect_Fixed_Components -- ------------------------------ procedure Collect_Fixed_Components (Typ : Entity_Id) is begin -- Build association list for discriminants, and find components of the -- variant part selected by the values of the discriminants. Old_C := First_Discriminant (Typ); Discr_Val := First_Elmt (Constraints); while Present (Old_C) loop Append_To (Assoc_List, Make_Component_Association (Loc, Choices => New_List (New_Occurrence_Of (Old_C, Loc)), Expression => New_Copy (Node (Discr_Val)))); Next_Elmt (Discr_Val); Next_Discriminant (Old_C); end loop; -- The tag and the possible parent component are unconditionally in -- the subtype. if Is_Tagged_Type (Typ) or else Has_Controlled_Component (Typ) then Old_C := First_Component (Typ); while Present (Old_C) loop if Chars (Old_C) in Name_uTag | Name_uParent then Append_Elmt (Old_C, Comp_List); end if; Next_Component (Old_C); end loop; end if; end Collect_Fixed_Components; --------------------------- -- Create_All_Components -- --------------------------- procedure Create_All_Components is Comp : Elmt_Id; begin Comp := First_Elmt (Comp_List); while Present (Comp) loop Old_C := Node (Comp); New_C := Create_Component (Old_C); Set_Etype (New_C, Constrain_Component_Type (Old_C, Subt, Decl_Node, Typ, Constraints)); Set_Is_Public (New_C, Is_Public (Subt)); Next_Elmt (Comp); end loop; end Create_All_Components; ---------------------- -- Create_Component -- ---------------------- function Create_Component (Old_Compon : Entity_Id) return Entity_Id is New_Compon : constant Entity_Id := New_Copy (Old_Compon); begin if Ekind (Old_Compon) = E_Discriminant and then Is_Completely_Hidden (Old_Compon) then -- This is a shadow discriminant created for a discriminant of -- the parent type, which needs to be present in the subtype. -- Give the shadow discriminant an internal name that cannot -- conflict with that of visible components. Set_Chars (New_Compon, New_Internal_Name ('C')); end if; -- Set the parent so we have a proper link for freezing etc. This is -- not a real parent pointer, since of course our parent does not own -- up to us and reference us, we are an illegitimate child of the -- original parent. Set_Parent (New_Compon, Parent (Old_Compon)); -- We do not want this node marked as Comes_From_Source, since -- otherwise it would get first class status and a separate cross- -- reference line would be generated. Illegitimate children do not -- rate such recognition. Set_Comes_From_Source (New_Compon, False); -- But it is a real entity, and a birth certificate must be properly -- registered by entering it into the entity list, and setting its -- scope to the given subtype. This turns out to be useful for the -- LLVM code generator, but that scope is not used otherwise. Enter_Name (New_Compon); Set_Scope (New_Compon, Subt); return New_Compon; end Create_Component; ----------------------- -- Is_Variant_Record -- ----------------------- function Is_Variant_Record (T : Entity_Id) return Boolean is begin return Nkind (Parent (T)) = N_Full_Type_Declaration and then Nkind (Type_Definition (Parent (T))) = N_Record_Definition and then Present (Component_List (Type_Definition (Parent (T)))) and then Present (Variant_Part (Component_List (Type_Definition (Parent (T))))); end Is_Variant_Record; -- Start of processing for Create_Constrained_Components begin pragma Assert (Subt /= Base_Type (Subt)); pragma Assert (Typ = Base_Type (Typ)); Set_First_Entity (Subt, Empty); Set_Last_Entity (Subt, Empty); -- Check whether constraint is fully static, in which case we can -- optimize the list of components. Discr_Val := First_Elmt (Constraints); while Present (Discr_Val) loop if not Is_OK_Static_Expression (Node (Discr_Val)) then Is_Static := False; if not Compile_Time_Known_Value (Node (Discr_Val)) then Is_Compile_Time_Known := False; exit; end if; end if; Next_Elmt (Discr_Val); end loop; Set_Has_Static_Discriminants (Subt, Is_Static); Push_Scope (Subt); -- Inherit the discriminants of the parent type Add_Discriminants : declare Num_Disc : Nat; Num_Stor : Nat; begin Num_Disc := 0; Old_C := First_Discriminant (Typ); while Present (Old_C) loop Num_Disc := Num_Disc + 1; New_C := Create_Component (Old_C); Set_Is_Public (New_C, Is_Public (Subt)); Next_Discriminant (Old_C); end loop; -- For an untagged derived subtype, the number of discriminants may -- be smaller than the number of inherited discriminants, because -- several of them may be renamed by a single new discriminant or -- constrained. In this case, add the hidden discriminants back into -- the subtype, because they need to be present if the optimizer of -- the GCC 4.x back-end decides to break apart assignments between -- objects using the parent view into member-wise assignments. Num_Stor := 0; if Is_Derived_Type (Typ) and then not Is_Tagged_Type (Typ) then Old_C := First_Stored_Discriminant (Typ); while Present (Old_C) loop Num_Stor := Num_Stor + 1; Next_Stored_Discriminant (Old_C); end loop; end if; if Num_Stor > Num_Disc then -- Find out multiple uses of new discriminants, and add hidden -- components for the extra renamed discriminants. We recognize -- multiple uses through the Corresponding_Discriminant of a -- new discriminant: if it constrains several old discriminants, -- this field points to the last one in the parent type. The -- stored discriminants of the derived type have the same name -- as those of the parent. declare Constr : Elmt_Id; New_Discr : Entity_Id; Old_Discr : Entity_Id; begin Constr := First_Elmt (Stored_Constraint (Typ)); Old_Discr := First_Stored_Discriminant (Typ); while Present (Constr) loop if Is_Entity_Name (Node (Constr)) and then Ekind (Entity (Node (Constr))) = E_Discriminant then New_Discr := Entity (Node (Constr)); if Chars (Corresponding_Discriminant (New_Discr)) /= Chars (Old_Discr) then -- The new discriminant has been used to rename a -- subsequent old discriminant. Introduce a shadow -- component for the current old discriminant. New_C := Create_Component (Old_Discr); Set_Original_Record_Component (New_C, Old_Discr); end if; else -- The constraint has eliminated the old discriminant. -- Introduce a shadow component. New_C := Create_Component (Old_Discr); Set_Original_Record_Component (New_C, Old_Discr); end if; Next_Elmt (Constr); Next_Stored_Discriminant (Old_Discr); end loop; end; end if; end Add_Discriminants; if Is_Compile_Time_Known and then Is_Variant_Record (Typ) then Collect_Fixed_Components (Typ); Gather_Components (Typ, Component_List (Type_Definition (Parent (Typ))), Governed_By => Assoc_List, Into => Comp_List, Report_Errors => Errors, Allow_Compile_Time => True); pragma Assert (not Errors or else Serious_Errors_Detected > 0); Create_All_Components; -- If the subtype declaration is created for a tagged type derivation -- with constraints, we retrieve the record definition of the parent -- type to select the components of the proper variant. elsif Is_Compile_Time_Known and then Is_Tagged_Type (Typ) and then Nkind (Parent (Typ)) = N_Full_Type_Declaration and then Nkind (Type_Definition (Parent (Typ))) = N_Derived_Type_Definition and then Is_Variant_Record (Parent_Type) then Collect_Fixed_Components (Typ); Gather_Components (Typ, Component_List (Type_Definition (Parent (Parent_Type))), Governed_By => Assoc_List, Into => Comp_List, Report_Errors => Errors, Allow_Compile_Time => True); -- Note: previously there was a check at this point that no errors -- were detected. As a consequence of AI05-220 there may be an error -- if an inherited discriminant that controls a variant has a non- -- static constraint. -- If the tagged derivation has a type extension, collect all the -- new relevant components therein via Gather_Components. if Present (Record_Extension_Part (Type_Definition (Parent (Typ)))) then Gather_Components (Typ, Component_List (Record_Extension_Part (Type_Definition (Parent (Typ)))), Governed_By => Assoc_List, Into => Comp_List, Report_Errors => Errors, Allow_Compile_Time => True, Include_Interface_Tag => True); end if; Create_All_Components; else -- If discriminants are not static, or if this is a multi-level type -- extension, we have to include all components of the parent type. Old_C := First_Component (Typ); while Present (Old_C) loop New_C := Create_Component (Old_C); Set_Etype (New_C, Constrain_Component_Type (Old_C, Subt, Decl_Node, Typ, Constraints)); Set_Is_Public (New_C, Is_Public (Subt)); Next_Component (Old_C); end loop; end if; End_Scope; end Create_Constrained_Components; ------------------------------------------ -- Decimal_Fixed_Point_Type_Declaration -- ------------------------------------------ procedure Decimal_Fixed_Point_Type_Declaration (T : Entity_Id; Def : Node_Id) is Loc : constant Source_Ptr := Sloc (Def); Digs_Expr : constant Node_Id := Digits_Expression (Def); Delta_Expr : constant Node_Id := Delta_Expression (Def); Max_Digits : constant Nat := (if System_Max_Integer_Size = 128 then 38 else 18); -- Maximum number of digits that can be represented in an integer Implicit_Base : Entity_Id; Digs_Val : Uint; Delta_Val : Ureal; Scale_Val : Uint; Bound_Val : Ureal; begin Check_Restriction (No_Fixed_Point, Def); -- Create implicit base type Implicit_Base := Create_Itype (E_Decimal_Fixed_Point_Type, Parent (Def), T, 'B'); Set_Etype (Implicit_Base, Implicit_Base); -- Analyze and process delta expression Analyze_And_Resolve (Delta_Expr, Universal_Real); Check_Delta_Expression (Delta_Expr); Delta_Val := Expr_Value_R (Delta_Expr); -- Check delta is power of 10, and determine scale value from it declare Val : Ureal; begin Scale_Val := Uint_0; Val := Delta_Val; if Val < Ureal_1 then while Val < Ureal_1 loop Val := Val * Ureal_10; Scale_Val := Scale_Val + 1; end loop; if Scale_Val > Max_Digits then Error_Msg_Uint_1 := UI_From_Int (Max_Digits); Error_Msg_N ("scale exceeds maximum value of ^", Def); Scale_Val := UI_From_Int (Max_Digits); end if; else while Val > Ureal_1 loop Val := Val / Ureal_10; Scale_Val := Scale_Val - 1; end loop; if Scale_Val < -Max_Digits then Error_Msg_Uint_1 := UI_From_Int (-Max_Digits); Error_Msg_N ("scale is less than minimum value of ^", Def); Scale_Val := UI_From_Int (-Max_Digits); end if; end if; if Val /= Ureal_1 then Error_Msg_N ("delta expression must be a power of 10", Def); Delta_Val := Ureal_10 ** (-Scale_Val); end if; end; -- Set delta, scale and small (small = delta for decimal type) Set_Delta_Value (Implicit_Base, Delta_Val); Set_Scale_Value (Implicit_Base, Scale_Val); Set_Small_Value (Implicit_Base, Delta_Val); -- Analyze and process digits expression Analyze_And_Resolve (Digs_Expr, Any_Integer); Check_Digits_Expression (Digs_Expr); Digs_Val := Expr_Value (Digs_Expr); if Digs_Val > Max_Digits then Error_Msg_Uint_1 := UI_From_Int (Max_Digits); Error_Msg_N ("digits value out of range, maximum is ^", Digs_Expr); Digs_Val := UI_From_Int (Max_Digits); end if; Set_Digits_Value (Implicit_Base, Digs_Val); Bound_Val := UR_From_Uint (10 ** Digs_Val - 1) * Delta_Val; -- Set range of base type from digits value for now. This will be -- expanded to represent the true underlying base range by Freeze. Set_Fixed_Range (Implicit_Base, Loc, -Bound_Val, Bound_Val); -- Note: We leave Esize unset for now, size will be set at freeze -- time. We have to do this for ordinary fixed-point, because the size -- depends on the specified small, and we might as well do the same for -- decimal fixed-point. pragma Assert (not Known_Esize (Implicit_Base)); -- If there are bounds given in the declaration use them as the -- bounds of the first named subtype. if Present (Real_Range_Specification (Def)) then declare RRS : constant Node_Id := Real_Range_Specification (Def); Low : constant Node_Id := Low_Bound (RRS); High : constant Node_Id := High_Bound (RRS); Low_Val : Ureal; High_Val : Ureal; begin Analyze_And_Resolve (Low, Any_Real); Analyze_And_Resolve (High, Any_Real); Check_Real_Bound (Low); Check_Real_Bound (High); Low_Val := Expr_Value_R (Low); High_Val := Expr_Value_R (High); if Low_Val < (-Bound_Val) then Error_Msg_N ("range low bound too small for digits value", Low); Low_Val := -Bound_Val; end if; if High_Val > Bound_Val then Error_Msg_N ("range high bound too large for digits value", High); High_Val := Bound_Val; end if; Set_Fixed_Range (T, Loc, Low_Val, High_Val); end; -- If no explicit range, use range that corresponds to given -- digits value. This will end up as the final range for the -- first subtype. else Set_Fixed_Range (T, Loc, -Bound_Val, Bound_Val); end if; -- Complete entity for first subtype. The inheritance of the rep item -- chain ensures that SPARK-related pragmas are not clobbered when the -- decimal fixed point type acts as a full view of a private type. Mutate_Ekind (T, E_Decimal_Fixed_Point_Subtype); Set_Etype (T, Implicit_Base); Set_Size_Info (T, Implicit_Base); Inherit_Rep_Item_Chain (T, Implicit_Base); Set_Digits_Value (T, Digs_Val); Set_Delta_Value (T, Delta_Val); Set_Small_Value (T, Delta_Val); Set_Scale_Value (T, Scale_Val); Set_Is_Constrained (T); end Decimal_Fixed_Point_Type_Declaration; ----------------------------------- -- Derive_Progenitor_Subprograms -- ----------------------------------- procedure Derive_Progenitor_Subprograms (Parent_Type : Entity_Id; Tagged_Type : Entity_Id) is E : Entity_Id; Elmt : Elmt_Id; Iface : Entity_Id; Iface_Alias : Entity_Id; Iface_Elmt : Elmt_Id; Iface_Subp : Entity_Id; New_Subp : Entity_Id := Empty; Prim_Elmt : Elmt_Id; Subp : Entity_Id; Typ : Entity_Id; begin pragma Assert (Ada_Version >= Ada_2005 and then Is_Record_Type (Tagged_Type) and then Is_Tagged_Type (Tagged_Type) and then Has_Interfaces (Tagged_Type)); -- Step 1: Transfer to the full-view primitives associated with the -- partial-view that cover interface primitives. Conceptually this -- work should be done later by Process_Full_View; done here to -- simplify its implementation at later stages. It can be safely -- done here because interfaces must be visible in the partial and -- private view (RM 7.3(7.3/2)). -- Small optimization: This work is only required if the parent may -- have entities whose Alias attribute reference an interface primitive. -- Such a situation may occur if the parent is an abstract type and the -- primitive has not been yet overridden or if the parent is a generic -- formal type covering interfaces. -- If the tagged type is not abstract, it cannot have abstract -- primitives (the only entities in the list of primitives of -- non-abstract tagged types that can reference abstract primitives -- through its Alias attribute are the internal entities that have -- attribute Interface_Alias, and these entities are generated later -- by Add_Internal_Interface_Entities). if In_Private_Part (Current_Scope) and then (Is_Abstract_Type (Parent_Type) or else Is_Generic_Type (Parent_Type)) then Elmt := First_Elmt (Primitive_Operations (Tagged_Type)); while Present (Elmt) loop Subp := Node (Elmt); -- At this stage it is not possible to have entities in the list -- of primitives that have attribute Interface_Alias. pragma Assert (No (Interface_Alias (Subp))); Typ := Find_Dispatching_Type (Ultimate_Alias (Subp)); if Is_Interface (Typ) then E := Find_Primitive_Covering_Interface (Tagged_Type => Tagged_Type, Iface_Prim => Subp); if Present (E) and then Find_Dispatching_Type (Ultimate_Alias (E)) /= Typ then Replace_Elmt (Elmt, E); Remove_Homonym (Subp); end if; end if; Next_Elmt (Elmt); end loop; end if; -- Step 2: Add primitives of progenitors that are not implemented by -- parents of Tagged_Type. if Present (Interfaces (Base_Type (Tagged_Type))) then Iface_Elmt := First_Elmt (Interfaces (Base_Type (Tagged_Type))); while Present (Iface_Elmt) loop Iface := Node (Iface_Elmt); Prim_Elmt := First_Elmt (Primitive_Operations (Iface)); while Present (Prim_Elmt) loop Iface_Subp := Node (Prim_Elmt); Iface_Alias := Ultimate_Alias (Iface_Subp); -- Exclude derivation of predefined primitives except those -- that come from source, or are inherited from one that comes -- from source. Required to catch declarations of equality -- operators of interfaces. For example: -- type Iface is interface; -- function "=" (Left, Right : Iface) return Boolean; if not Is_Predefined_Dispatching_Operation (Iface_Subp) or else Comes_From_Source (Iface_Alias) then E := Find_Primitive_Covering_Interface (Tagged_Type => Tagged_Type, Iface_Prim => Iface_Subp); -- If not found we derive a new primitive leaving its alias -- attribute referencing the interface primitive. if No (E) then Derive_Subprogram (New_Subp, Iface_Subp, Tagged_Type, Iface); -- Ada 2012 (AI05-0197): If the covering primitive's name -- differs from the name of the interface primitive then it -- is a private primitive inherited from a parent type. In -- such case, given that Tagged_Type covers the interface, -- the inherited private primitive becomes visible. For such -- purpose we add a new entity that renames the inherited -- private primitive. elsif Chars (E) /= Chars (Iface_Subp) then pragma Assert (Has_Suffix (E, 'P')); Derive_Subprogram (New_Subp, Iface_Subp, Tagged_Type, Iface); Set_Alias (New_Subp, E); Set_Is_Abstract_Subprogram (New_Subp, Is_Abstract_Subprogram (E)); -- Propagate to the full view interface entities associated -- with the partial view. elsif In_Private_Part (Current_Scope) and then Present (Alias (E)) and then Alias (E) = Iface_Subp and then List_Containing (Parent (E)) /= Private_Declarations (Specification (Unit_Declaration_Node (Current_Scope))) then Append_Elmt (E, Primitive_Operations (Tagged_Type)); end if; end if; Next_Elmt (Prim_Elmt); end loop; Next_Elmt (Iface_Elmt); end loop; end if; end Derive_Progenitor_Subprograms; ----------------------- -- Derive_Subprogram -- ----------------------- procedure Derive_Subprogram (New_Subp : out Entity_Id; Parent_Subp : Entity_Id; Derived_Type : Entity_Id; Parent_Type : Entity_Id; Actual_Subp : Entity_Id := Empty) is Formal : Entity_Id; -- Formal parameter of parent primitive operation Formal_Of_Actual : Entity_Id; -- Formal parameter of actual operation, when the derivation is to -- create a renaming for a primitive operation of an actual in an -- instantiation. New_Formal : Entity_Id; -- Formal of inherited operation Visible_Subp : Entity_Id := Parent_Subp; function Is_Private_Overriding return Boolean; -- If Subp is a private overriding of a visible operation, the inherited -- operation derives from the overridden op (even though its body is the -- overriding one) and the inherited operation is visible now. See -- sem_disp to see the full details of the handling of the overridden -- subprogram, which is removed from the list of primitive operations of -- the type. The overridden subprogram is saved locally in Visible_Subp, -- and used to diagnose abstract operations that need overriding in the -- derived type. procedure Replace_Type (Id, New_Id : Entity_Id); -- When the type is an anonymous access type, create a new access type -- designating the derived type. procedure Set_Derived_Name; -- This procedure sets the appropriate Chars name for New_Subp. This -- is normally just a copy of the parent name. An exception arises for -- type support subprograms, where the name is changed to reflect the -- name of the derived type, e.g. if type foo is derived from type bar, -- then a procedure barDA is derived with a name fooDA. --------------------------- -- Is_Private_Overriding -- --------------------------- function Is_Private_Overriding return Boolean is Prev : Entity_Id; begin -- If the parent is not a dispatching operation there is no -- need to investigate overridings if not Is_Dispatching_Operation (Parent_Subp) then return False; end if; -- The visible operation that is overridden is a homonym of the -- parent subprogram. We scan the homonym chain to find the one -- whose alias is the subprogram we are deriving. Prev := Current_Entity (Parent_Subp); while Present (Prev) loop if Ekind (Prev) = Ekind (Parent_Subp) and then Alias (Prev) = Parent_Subp and then Scope (Parent_Subp) = Scope (Prev) and then not Is_Hidden (Prev) then Visible_Subp := Prev; return True; end if; Prev := Homonym (Prev); end loop; return False; end Is_Private_Overriding; ------------------ -- Replace_Type -- ------------------ procedure Replace_Type (Id, New_Id : Entity_Id) is Id_Type : constant Entity_Id := Etype (Id); Acc_Type : Entity_Id; Par : constant Node_Id := Parent (Derived_Type); begin -- When the type is an anonymous access type, create a new access -- type designating the derived type. This itype must be elaborated -- at the point of the derivation, not on subsequent calls that may -- be out of the proper scope for Gigi, so we insert a reference to -- it after the derivation. if Ekind (Id_Type) = E_Anonymous_Access_Type then declare Desig_Typ : Entity_Id := Designated_Type (Id_Type); begin if Ekind (Desig_Typ) = E_Record_Type_With_Private and then Present (Full_View (Desig_Typ)) and then not Is_Private_Type (Parent_Type) then Desig_Typ := Full_View (Desig_Typ); end if; if Base_Type (Desig_Typ) = Base_Type (Parent_Type) -- Ada 2005 (AI-251): Handle also derivations of abstract -- interface primitives. or else (Is_Interface (Desig_Typ) and then not Is_Class_Wide_Type (Desig_Typ)) then Acc_Type := New_Copy (Id_Type); Set_Etype (Acc_Type, Acc_Type); Set_Scope (Acc_Type, New_Subp); -- Set size of anonymous access type. If we have an access -- to an unconstrained array, this is a fat pointer, so it -- is sizes at twice addtress size. if Is_Array_Type (Desig_Typ) and then not Is_Constrained (Desig_Typ) then Init_Size (Acc_Type, 2 * System_Address_Size); -- Other cases use a thin pointer else Init_Size (Acc_Type, System_Address_Size); end if; -- Set remaining characterstics of anonymous access type Reinit_Alignment (Acc_Type); Set_Directly_Designated_Type (Acc_Type, Derived_Type); Set_Etype (New_Id, Acc_Type); Set_Scope (New_Id, New_Subp); -- Create a reference to it Build_Itype_Reference (Acc_Type, Parent (Derived_Type)); else Set_Etype (New_Id, Id_Type); end if; end; -- In Ada2012, a formal may have an incomplete type but the type -- derivation that inherits the primitive follows the full view. elsif Base_Type (Id_Type) = Base_Type (Parent_Type) or else (Ekind (Id_Type) = E_Record_Type_With_Private and then Present (Full_View (Id_Type)) and then Base_Type (Full_View (Id_Type)) = Base_Type (Parent_Type)) or else (Ada_Version >= Ada_2012 and then Ekind (Id_Type) = E_Incomplete_Type and then Full_View (Id_Type) = Parent_Type) then -- Constraint checks on formals are generated during expansion, -- based on the signature of the original subprogram. The bounds -- of the derived type are not relevant, and thus we can use -- the base type for the formals. However, the return type may be -- used in a context that requires that the proper static bounds -- be used (a case statement, for example) and for those cases -- we must use the derived type (first subtype), not its base. -- If the derived_type_definition has no constraints, we know that -- the derived type has the same constraints as the first subtype -- of the parent, and we can also use it rather than its base, -- which can lead to more efficient code. if Etype (Id) = Parent_Type then if Is_Scalar_Type (Parent_Type) and then Subtypes_Statically_Compatible (Parent_Type, Derived_Type) then Set_Etype (New_Id, Derived_Type); elsif Nkind (Par) = N_Full_Type_Declaration and then Nkind (Type_Definition (Par)) = N_Derived_Type_Definition and then Is_Entity_Name (Subtype_Indication (Type_Definition (Par))) then Set_Etype (New_Id, Derived_Type); else Set_Etype (New_Id, Base_Type (Derived_Type)); end if; else Set_Etype (New_Id, Base_Type (Derived_Type)); end if; else Set_Etype (New_Id, Etype (Id)); end if; end Replace_Type; ---------------------- -- Set_Derived_Name -- ---------------------- procedure Set_Derived_Name is Nm : constant TSS_Name_Type := Get_TSS_Name (Parent_Subp); begin if Nm = TSS_Null then Set_Chars (New_Subp, Chars (Parent_Subp)); else Set_Chars (New_Subp, Make_TSS_Name (Base_Type (Derived_Type), Nm)); end if; end Set_Derived_Name; -- Start of processing for Derive_Subprogram begin New_Subp := New_Entity (Nkind (Parent_Subp), Sloc (Derived_Type)); Mutate_Ekind (New_Subp, Ekind (Parent_Subp)); -- Check whether the inherited subprogram is a private operation that -- should be inherited but not yet made visible. Such subprograms can -- become visible at a later point (e.g., the private part of a public -- child unit) via Declare_Inherited_Private_Subprograms. If the -- following predicate is true, then this is not such a private -- operation and the subprogram simply inherits the name of the parent -- subprogram. Note the special check for the names of controlled -- operations, which are currently exempted from being inherited with -- a hidden name because they must be findable for generation of -- implicit run-time calls. if not Is_Hidden (Parent_Subp) or else Is_Internal (Parent_Subp) or else Is_Private_Overriding or else Is_Internal_Name (Chars (Parent_Subp)) or else (Is_Controlled (Parent_Type) and then Chars (Parent_Subp) in Name_Adjust | Name_Finalize | Name_Initialize) then Set_Derived_Name; -- An inherited dispatching equality will be overridden by an internally -- generated one, or by an explicit one, so preserve its name and thus -- its entry in the dispatch table. Otherwise, if Parent_Subp is a -- private operation it may become invisible if the full view has -- progenitors, and the dispatch table will be malformed. -- We check that the type is limited to handle the anomalous declaration -- of Limited_Controlled, which is derived from a non-limited type, and -- which is handled specially elsewhere as well. elsif Chars (Parent_Subp) = Name_Op_Eq and then Is_Dispatching_Operation (Parent_Subp) and then Etype (Parent_Subp) = Standard_Boolean and then not Is_Limited_Type (Etype (First_Formal (Parent_Subp))) and then Etype (First_Formal (Parent_Subp)) = Etype (Next_Formal (First_Formal (Parent_Subp))) then Set_Derived_Name; -- If parent is hidden, this can be a regular derivation if the -- parent is immediately visible in a non-instantiating context, -- or if we are in the private part of an instance. This test -- should still be refined ??? -- The test for In_Instance_Not_Visible avoids inheriting the derived -- operation as a non-visible operation in cases where the parent -- subprogram might not be visible now, but was visible within the -- original generic, so it would be wrong to make the inherited -- subprogram non-visible now. (Not clear if this test is fully -- correct; are there any cases where we should declare the inherited -- operation as not visible to avoid it being overridden, e.g., when -- the parent type is a generic actual with private primitives ???) -- (they should be treated the same as other private inherited -- subprograms, but it's not clear how to do this cleanly). ??? elsif (In_Open_Scopes (Scope (Base_Type (Parent_Type))) and then Is_Immediately_Visible (Parent_Subp) and then not In_Instance) or else In_Instance_Not_Visible then Set_Derived_Name; -- Ada 2005 (AI-251): Regular derivation if the parent subprogram -- overrides an interface primitive because interface primitives -- must be visible in the partial view of the parent (RM 7.3 (7.3/2)) elsif Ada_Version >= Ada_2005 and then Is_Dispatching_Operation (Parent_Subp) and then Present (Covered_Interface_Op (Parent_Subp)) then Set_Derived_Name; -- Otherwise, the type is inheriting a private operation, so enter it -- with a special name so it can't be overridden. See also below, where -- we check for this case, and if so avoid setting Requires_Overriding. else Set_Chars (New_Subp, New_External_Name (Chars (Parent_Subp), 'P')); end if; Set_Parent (New_Subp, Parent (Derived_Type)); if Present (Actual_Subp) then Replace_Type (Actual_Subp, New_Subp); else Replace_Type (Parent_Subp, New_Subp); end if; Conditional_Delay (New_Subp, Parent_Subp); -- If we are creating a renaming for a primitive operation of an -- actual of a generic derived type, we must examine the signature -- of the actual primitive, not that of the generic formal, which for -- example may be an interface. However the name and initial value -- of the inherited operation are those of the formal primitive. Formal := First_Formal (Parent_Subp); if Present (Actual_Subp) then Formal_Of_Actual := First_Formal (Actual_Subp); else Formal_Of_Actual := Empty; end if; while Present (Formal) loop New_Formal := New_Copy (Formal); -- Extra formals are not inherited from a limited interface parent -- since limitedness is not inherited in such case (AI-419) and this -- affects the extra formals. if Is_Limited_Interface (Parent_Type) then Set_Extra_Formal (New_Formal, Empty); Set_Extra_Accessibility (New_Formal, Empty); end if; -- Normally we do not go copying parents, but in the case of -- formals, we need to link up to the declaration (which is the -- parameter specification), and it is fine to link up to the -- original formal's parameter specification in this case. Set_Parent (New_Formal, Parent (Formal)); Append_Entity (New_Formal, New_Subp); if Present (Formal_Of_Actual) then Replace_Type (Formal_Of_Actual, New_Formal); Next_Formal (Formal_Of_Actual); else Replace_Type (Formal, New_Formal); end if; Next_Formal (Formal); end loop; -- Extra formals are shared between the parent subprogram and the -- derived subprogram (implicit in the above copy of formals), unless -- the parent type is a limited interface type; hence we must inherit -- also the reference to the first extra formal. When the parent type is -- an interface the extra formals will be added when the subprogram is -- frozen (see Freeze.Freeze_Subprogram). if not Is_Limited_Interface (Parent_Type) then Set_Extra_Formals (New_Subp, Extra_Formals (Parent_Subp)); if Ekind (New_Subp) = E_Function then Set_Extra_Accessibility_Of_Result (New_Subp, Extra_Accessibility_Of_Result (Parent_Subp)); end if; end if; -- If this derivation corresponds to a tagged generic actual, then -- primitive operations rename those of the actual. Otherwise the -- primitive operations rename those of the parent type, If the parent -- renames an intrinsic operator, so does the new subprogram. We except -- concatenation, which is always properly typed, and does not get -- expanded as other intrinsic operations. if No (Actual_Subp) then if Is_Intrinsic_Subprogram (Parent_Subp) then Set_Is_Intrinsic_Subprogram (New_Subp); if Present (Alias (Parent_Subp)) and then Chars (Parent_Subp) /= Name_Op_Concat then Set_Alias (New_Subp, Alias (Parent_Subp)); else Set_Alias (New_Subp, Parent_Subp); end if; else Set_Alias (New_Subp, Parent_Subp); end if; else Set_Alias (New_Subp, Actual_Subp); end if; Copy_Strub_Mode (New_Subp, Alias (New_Subp)); -- Derived subprograms of a tagged type must inherit the convention -- of the parent subprogram (a requirement of AI-117). Derived -- subprograms of untagged types simply get convention Ada by default. -- If the derived type is a tagged generic formal type with unknown -- discriminants, its convention is intrinsic (RM 6.3.1 (8)). -- However, if the type is derived from a generic formal, the further -- inherited subprogram has the convention of the non-generic ancestor. -- Otherwise there would be no way to override the operation. -- (This is subject to forthcoming ARG discussions). if Is_Tagged_Type (Derived_Type) then if Is_Generic_Type (Derived_Type) and then Has_Unknown_Discriminants (Derived_Type) then Set_Convention (New_Subp, Convention_Intrinsic); else if Is_Generic_Type (Parent_Type) and then Has_Unknown_Discriminants (Parent_Type) then Set_Convention (New_Subp, Convention (Alias (Parent_Subp))); else Set_Convention (New_Subp, Convention (Parent_Subp)); end if; end if; end if; -- Predefined controlled operations retain their name even if the parent -- is hidden (see above), but they are not primitive operations if the -- ancestor is not visible, for example if the parent is a private -- extension completed with a controlled extension. Note that a full -- type that is controlled can break privacy: the flag Is_Controlled is -- set on both views of the type. if Is_Controlled (Parent_Type) and then Chars (Parent_Subp) in Name_Initialize | Name_Adjust | Name_Finalize and then Is_Hidden (Parent_Subp) and then not Is_Visibly_Controlled (Parent_Type) then Set_Is_Hidden (New_Subp); end if; Set_Is_Imported (New_Subp, Is_Imported (Parent_Subp)); Set_Is_Exported (New_Subp, Is_Exported (Parent_Subp)); if Ekind (Parent_Subp) = E_Procedure then Set_Is_Valued_Procedure (New_Subp, Is_Valued_Procedure (Parent_Subp)); else Set_Has_Controlling_Result (New_Subp, Has_Controlling_Result (Parent_Subp)); end if; -- No_Return must be inherited properly. If this is overridden in the -- case of a dispatching operation, then the check is made later in -- Check_Abstract_Overriding that the overriding operation is also -- No_Return (no such check is required for the nondispatching case). Set_No_Return (New_Subp, No_Return (Parent_Subp)); -- If the parent subprogram is marked as Ghost, then so is the derived -- subprogram. The ghost policy for the derived subprogram is set from -- the effective ghost policy at the point of derived type declaration. if Is_Ghost_Entity (Parent_Subp) then Set_Is_Ghost_Entity (New_Subp); end if; -- A derived function with a controlling result is abstract. If the -- Derived_Type is a nonabstract formal generic derived type, then -- inherited operations are not abstract: the required check is done at -- instantiation time. If the derivation is for a generic actual, the -- function is not abstract unless the actual is. if Is_Generic_Type (Derived_Type) and then not Is_Abstract_Type (Derived_Type) then null; -- Ada 2005 (AI-228): Calculate the "require overriding" and "abstract" -- properties of the subprogram, as defined in RM-3.9.3(4/2-6/2). Note -- that functions with controlling access results of record extensions -- with a null extension part require overriding (AI95-00391/06). -- Ada 2022 (AI12-0042): Similarly, set those properties for -- implementing the rule of RM 7.3.2(6.1/4). -- A subprogram subject to pragma Extensions_Visible with value False -- requires overriding if the subprogram has at least one controlling -- OUT parameter (SPARK RM 6.1.7(6)). elsif Ada_Version >= Ada_2005 and then (Is_Abstract_Subprogram (Alias (New_Subp)) or else (Is_Tagged_Type (Derived_Type) and then Etype (New_Subp) = Derived_Type and then not Is_Null_Extension (Derived_Type)) or else (Is_Tagged_Type (Derived_Type) and then Ekind (Etype (New_Subp)) = E_Anonymous_Access_Type and then Designated_Type (Etype (New_Subp)) = Derived_Type) or else (Comes_From_Source (Alias (New_Subp)) and then Is_EVF_Procedure (Alias (New_Subp))) -- AI12-0042: Set Requires_Overriding when a type extension -- inherits a private operation that is visible at the -- point of extension (Has_Private_Ancestor is False) from -- an ancestor that has Type_Invariant'Class, and when the -- type extension is in a visible part (the latter as -- clarified by AI12-0382). or else (not Has_Private_Ancestor (Derived_Type) and then Has_Invariants (Parent_Type) and then Present (Get_Pragma (Parent_Type, Pragma_Invariant)) and then Class_Present (Get_Pragma (Parent_Type, Pragma_Invariant)) and then Is_Private_Primitive (Parent_Subp) and then In_Visible_Part (Scope (Derived_Type)))) and then No (Actual_Subp) then if not Is_Tagged_Type (Derived_Type) or else Is_Abstract_Type (Derived_Type) or else Is_Abstract_Subprogram (Alias (New_Subp)) then Set_Is_Abstract_Subprogram (New_Subp); -- If the Chars of the new subprogram is different from that of the -- parent's one, it means that we entered it with a special name so -- it can't be overridden (see above). In that case we had better not -- *require* it to be overridden. This is the case where the parent -- type inherited the operation privately, so there's no danger of -- dangling dispatching. elsif Chars (New_Subp) = Chars (Alias (New_Subp)) then Set_Requires_Overriding (New_Subp); end if; elsif Ada_Version < Ada_2005 and then (Is_Abstract_Subprogram (Alias (New_Subp)) or else (Is_Tagged_Type (Derived_Type) and then Etype (New_Subp) = Derived_Type and then No (Actual_Subp))) then Set_Is_Abstract_Subprogram (New_Subp); -- AI05-0097 : an inherited operation that dispatches on result is -- abstract if the derived type is abstract, even if the parent type -- is concrete and the derived type is a null extension. elsif Has_Controlling_Result (Alias (New_Subp)) and then Is_Abstract_Type (Etype (New_Subp)) then Set_Is_Abstract_Subprogram (New_Subp); -- Finally, if the parent type is abstract we must verify that all -- inherited operations are either non-abstract or overridden, or that -- the derived type itself is abstract (this check is performed at the -- end of a package declaration, in Check_Abstract_Overriding). A -- private overriding in the parent type will not be visible in the -- derivation if we are not in an inner package or in a child unit of -- the parent type, in which case the abstractness of the inherited -- operation is carried to the new subprogram. elsif Is_Abstract_Type (Parent_Type) and then not In_Open_Scopes (Scope (Parent_Type)) and then Is_Private_Overriding and then Is_Abstract_Subprogram (Visible_Subp) then if No (Actual_Subp) then Set_Alias (New_Subp, Visible_Subp); Set_Is_Abstract_Subprogram (New_Subp, True); else -- If this is a derivation for an instance of a formal derived -- type, abstractness comes from the primitive operation of the -- actual, not from the operation inherited from the ancestor. Set_Is_Abstract_Subprogram (New_Subp, Is_Abstract_Subprogram (Actual_Subp)); end if; end if; New_Overloaded_Entity (New_Subp, Derived_Type); -- Ada RM 6.1.1 (15): If a subprogram inherits nonconforming class-wide -- preconditions and the derived type is abstract, the derived operation -- is abstract as well if parent subprogram is not abstract or null. if Is_Abstract_Type (Derived_Type) and then Has_Non_Trivial_Precondition (Parent_Subp) and then Present (Interfaces (Derived_Type)) then -- Add useful attributes of subprogram before the freeze point, -- in case freezing is delayed or there are previous errors. Set_Is_Dispatching_Operation (New_Subp); declare Iface_Prim : constant Entity_Id := Covered_Interface_Op (New_Subp); begin if Present (Iface_Prim) and then Has_Non_Trivial_Precondition (Iface_Prim) then Set_Is_Abstract_Subprogram (New_Subp); end if; end; end if; -- Check for case of a derived subprogram for the instantiation of a -- formal derived tagged type, if so mark the subprogram as dispatching -- and inherit the dispatching attributes of the actual subprogram. The -- derived subprogram is effectively renaming of the actual subprogram, -- so it needs to have the same attributes as the actual. if Present (Actual_Subp) and then Is_Dispatching_Operation (Actual_Subp) then Set_Is_Dispatching_Operation (New_Subp); if Present (DTC_Entity (Actual_Subp)) then Set_DTC_Entity (New_Subp, DTC_Entity (Actual_Subp)); Set_DT_Position_Value (New_Subp, DT_Position (Actual_Subp)); end if; end if; -- Indicate that a derived subprogram does not require a body and that -- it does not require processing of default expressions. Set_Has_Completion (New_Subp); Set_Default_Expressions_Processed (New_Subp); if Ekind (New_Subp) = E_Function then Set_Mechanism (New_Subp, Mechanism (Parent_Subp)); end if; -- Ada 2022 (AI12-0279): If a Yield aspect is specified True for a -- primitive subprogram S of a type T, then the aspect is inherited -- by the corresponding primitive subprogram of each descendant of T. if Is_Tagged_Type (Derived_Type) and then Is_Dispatching_Operation (New_Subp) and then Has_Yield_Aspect (Alias (New_Subp)) then Set_Has_Yield_Aspect (New_Subp, Has_Yield_Aspect (Alias (New_Subp))); end if; Set_Is_Ada_2022_Only (New_Subp, Is_Ada_2022_Only (Parent_Subp)); end Derive_Subprogram; ------------------------ -- Derive_Subprograms -- ------------------------ procedure Derive_Subprograms (Parent_Type : Entity_Id; Derived_Type : Entity_Id; Generic_Actual : Entity_Id := Empty) is Op_List : constant Elist_Id := Collect_Primitive_Operations (Parent_Type); function Check_Derived_Type return Boolean; -- Check that all the entities derived from Parent_Type are found in -- the list of primitives of Derived_Type exactly in the same order. procedure Derive_Interface_Subprogram (New_Subp : out Entity_Id; Subp : Entity_Id; Actual_Subp : Entity_Id); -- Derive New_Subp from the ultimate alias of the parent subprogram Subp -- (which is an interface primitive). If Generic_Actual is present then -- Actual_Subp is the actual subprogram corresponding with the generic -- subprogram Subp. ------------------------ -- Check_Derived_Type -- ------------------------ function Check_Derived_Type return Boolean is E : Entity_Id; Derived_Elmt : Elmt_Id; Derived_Op : Entity_Id; Derived_Ops : Elist_Id; Parent_Elmt : Elmt_Id; Parent_Op : Entity_Id; begin -- Traverse list of entities in the current scope searching for -- an incomplete type whose full-view is derived type. E := First_Entity (Scope (Derived_Type)); while Present (E) and then E /= Derived_Type loop if Ekind (E) = E_Incomplete_Type and then Present (Full_View (E)) and then Full_View (E) = Derived_Type then -- Disable this test if Derived_Type completes an incomplete -- type because in such case more primitives can be added -- later to the list of primitives of Derived_Type by routine -- Process_Incomplete_Dependents. return True; end if; Next_Entity (E); end loop; Derived_Ops := Collect_Primitive_Operations (Derived_Type); Derived_Elmt := First_Elmt (Derived_Ops); Parent_Elmt := First_Elmt (Op_List); while Present (Parent_Elmt) loop Parent_Op := Node (Parent_Elmt); Derived_Op := Node (Derived_Elmt); -- At this early stage Derived_Type has no entities with attribute -- Interface_Alias. In addition, such primitives are always -- located at the end of the list of primitives of Parent_Type. -- Therefore, if found we can safely stop processing pending -- entities. exit when Present (Interface_Alias (Parent_Op)); -- Handle hidden entities if not Is_Predefined_Dispatching_Operation (Parent_Op) and then Is_Hidden (Parent_Op) then if Present (Derived_Op) and then Primitive_Names_Match (Parent_Op, Derived_Op) then Next_Elmt (Derived_Elmt); end if; else if No (Derived_Op) or else Ekind (Parent_Op) /= Ekind (Derived_Op) or else not Primitive_Names_Match (Parent_Op, Derived_Op) then return False; end if; Next_Elmt (Derived_Elmt); end if; Next_Elmt (Parent_Elmt); end loop; return True; end Check_Derived_Type; --------------------------------- -- Derive_Interface_Subprogram -- --------------------------------- procedure Derive_Interface_Subprogram (New_Subp : out Entity_Id; Subp : Entity_Id; Actual_Subp : Entity_Id) is Iface_Subp : constant Entity_Id := Ultimate_Alias (Subp); Iface_Type : constant Entity_Id := Find_Dispatching_Type (Iface_Subp); begin pragma Assert (Is_Interface (Iface_Type)); Derive_Subprogram (New_Subp => New_Subp, Parent_Subp => Iface_Subp, Derived_Type => Derived_Type, Parent_Type => Iface_Type, Actual_Subp => Actual_Subp); -- Given that this new interface entity corresponds with a primitive -- of the parent that was not overridden we must leave it associated -- with its parent primitive to ensure that it will share the same -- dispatch table slot when overridden. We must set the Alias to Subp -- (instead of Iface_Subp), and we must fix Is_Abstract_Subprogram -- (in case we inherited Subp from Iface_Type via a nonabstract -- generic formal type). if No (Actual_Subp) then Set_Alias (New_Subp, Subp); declare T : Entity_Id := Find_Dispatching_Type (Subp); begin while Etype (T) /= T loop if Is_Generic_Type (T) and then not Is_Abstract_Type (T) then Set_Is_Abstract_Subprogram (New_Subp, False); exit; end if; T := Etype (T); end loop; end; -- For instantiations this is not needed since the previous call to -- Derive_Subprogram leaves the entity well decorated. else pragma Assert (Alias (New_Subp) = Actual_Subp); null; end if; end Derive_Interface_Subprogram; -- Local variables Alias_Subp : Entity_Id; Act_List : Elist_Id; Act_Elmt : Elmt_Id; Act_Subp : Entity_Id := Empty; Elmt : Elmt_Id; Need_Search : Boolean := False; New_Subp : Entity_Id := Empty; Parent_Base : Entity_Id; Subp : Entity_Id; -- Start of processing for Derive_Subprograms begin if Ekind (Parent_Type) = E_Record_Type_With_Private and then Has_Discriminants (Parent_Type) and then Present (Full_View (Parent_Type)) then Parent_Base := Full_View (Parent_Type); else Parent_Base := Parent_Type; end if; if Present (Generic_Actual) then Act_List := Collect_Primitive_Operations (Generic_Actual); Act_Elmt := First_Elmt (Act_List); else Act_List := No_Elist; Act_Elmt := No_Elmt; end if; -- Derive primitives inherited from the parent. Note that if the generic -- actual is present, this is not really a type derivation, it is a -- completion within an instance. -- Case 1: Derived_Type does not implement interfaces if not Is_Tagged_Type (Derived_Type) or else (not Has_Interfaces (Derived_Type) and then not (Present (Generic_Actual) and then Has_Interfaces (Generic_Actual))) then Elmt := First_Elmt (Op_List); while Present (Elmt) loop Subp := Node (Elmt); -- Literals are derived earlier in the process of building the -- derived type, and are skipped here. if Ekind (Subp) = E_Enumeration_Literal then null; -- The actual is a direct descendant and the common primitive -- operations appear in the same order. -- If the generic parent type is present, the derived type is an -- instance of a formal derived type, and within the instance its -- operations are those of the actual. We derive from the formal -- type but make the inherited operations aliases of the -- corresponding operations of the actual. else pragma Assert (No (Node (Act_Elmt)) or else (Primitive_Names_Match (Subp, Node (Act_Elmt)) and then Type_Conformant (Subp, Node (Act_Elmt), Skip_Controlling_Formals => True))); Derive_Subprogram (New_Subp, Subp, Derived_Type, Parent_Base, Node (Act_Elmt)); if Present (Act_Elmt) then Next_Elmt (Act_Elmt); end if; end if; Next_Elmt (Elmt); end loop; -- Case 2: Derived_Type implements interfaces else -- If the parent type has no predefined primitives we remove -- predefined primitives from the list of primitives of generic -- actual to simplify the complexity of this algorithm. if Present (Generic_Actual) then declare Has_Predefined_Primitives : Boolean := False; begin -- Check if the parent type has predefined primitives Elmt := First_Elmt (Op_List); while Present (Elmt) loop Subp := Node (Elmt); if Is_Predefined_Dispatching_Operation (Subp) and then not Comes_From_Source (Ultimate_Alias (Subp)) then Has_Predefined_Primitives := True; exit; end if; Next_Elmt (Elmt); end loop; -- Remove predefined primitives of Generic_Actual. We must use -- an auxiliary list because in case of tagged types the value -- returned by Collect_Primitive_Operations is the value stored -- in its Primitive_Operations attribute (and we don't want to -- modify its current contents). if not Has_Predefined_Primitives then declare Aux_List : constant Elist_Id := New_Elmt_List; begin Elmt := First_Elmt (Act_List); while Present (Elmt) loop Subp := Node (Elmt); if not Is_Predefined_Dispatching_Operation (Subp) or else Comes_From_Source (Subp) then Append_Elmt (Subp, Aux_List); end if; Next_Elmt (Elmt); end loop; Act_List := Aux_List; end; end if; Act_Elmt := First_Elmt (Act_List); Act_Subp := Node (Act_Elmt); end; end if; -- Stage 1: If the generic actual is not present we derive the -- primitives inherited from the parent type. If the generic parent -- type is present, the derived type is an instance of a formal -- derived type, and within the instance its operations are those of -- the actual. We derive from the formal type but make the inherited -- operations aliases of the corresponding operations of the actual. Elmt := First_Elmt (Op_List); while Present (Elmt) loop Subp := Node (Elmt); Alias_Subp := Ultimate_Alias (Subp); -- Do not derive internal entities of the parent that link -- interface primitives with their covering primitive. These -- entities will be added to this type when frozen. if Present (Interface_Alias (Subp)) then goto Continue; end if; -- If the generic actual is present find the corresponding -- operation in the generic actual. If the parent type is a -- direct ancestor of the derived type then, even if it is an -- interface, the operations are inherited from the primary -- dispatch table and are in the proper order. If we detect here -- that primitives are not in the same order we traverse the list -- of primitive operations of the actual to find the one that -- implements the interface primitive. if Need_Search or else (Present (Generic_Actual) and then Present (Act_Subp) and then not (Primitive_Names_Match (Subp, Act_Subp) and then Type_Conformant (Subp, Act_Subp, Skip_Controlling_Formals => True))) then pragma Assert (not Is_Ancestor (Parent_Base, Generic_Actual, Use_Full_View => True)); -- Remember that we need searching for all pending primitives Need_Search := True; -- Handle entities associated with interface primitives if Present (Alias_Subp) and then Is_Interface (Find_Dispatching_Type (Alias_Subp)) and then not Is_Predefined_Dispatching_Operation (Subp) then -- Search for the primitive in the homonym chain Act_Subp := Find_Primitive_Covering_Interface (Tagged_Type => Generic_Actual, Iface_Prim => Alias_Subp); -- Previous search may not locate primitives covering -- interfaces defined in generics units or instantiations. -- (it fails if the covering primitive has formals whose -- type is also defined in generics or instantiations). -- In such case we search in the list of primitives of the -- generic actual for the internal entity that links the -- interface primitive and the covering primitive. if No (Act_Subp) and then Is_Generic_Type (Parent_Type) then -- This code has been designed to handle only generic -- formals that implement interfaces that are defined -- in a generic unit or instantiation. If this code is -- needed for other cases we must review it because -- (given that it relies on Original_Location to locate -- the primitive of Generic_Actual that covers the -- interface) it could leave linked through attribute -- Alias entities of unrelated instantiations). pragma Assert (Is_Generic_Unit (Scope (Find_Dispatching_Type (Alias_Subp))) or else Instantiation_Depth (Sloc (Find_Dispatching_Type (Alias_Subp))) > 0); declare Iface_Prim_Loc : constant Source_Ptr := Original_Location (Sloc (Alias_Subp)); Elmt : Elmt_Id; Prim : Entity_Id; begin Elmt := First_Elmt (Primitive_Operations (Generic_Actual)); Search : while Present (Elmt) loop Prim := Node (Elmt); if Present (Interface_Alias (Prim)) and then Original_Location (Sloc (Interface_Alias (Prim))) = Iface_Prim_Loc then Act_Subp := Alias (Prim); exit Search; end if; Next_Elmt (Elmt); end loop Search; end; end if; pragma Assert (Present (Act_Subp) or else Is_Abstract_Type (Generic_Actual) or else Serious_Errors_Detected > 0); -- Handle predefined primitives plus the rest of user-defined -- primitives else Act_Elmt := First_Elmt (Act_List); while Present (Act_Elmt) loop Act_Subp := Node (Act_Elmt); exit when Primitive_Names_Match (Subp, Act_Subp) and then Type_Conformant (Subp, Act_Subp, Skip_Controlling_Formals => True) and then No (Interface_Alias (Act_Subp)); Next_Elmt (Act_Elmt); end loop; if No (Act_Elmt) then Act_Subp := Empty; end if; end if; end if; -- Case 1: If the parent is a limited interface then it has the -- predefined primitives of synchronized interfaces. However, the -- actual type may be a non-limited type and hence it does not -- have such primitives. if Present (Generic_Actual) and then not Present (Act_Subp) and then Is_Limited_Interface (Parent_Base) and then Is_Predefined_Interface_Primitive (Subp) then null; -- Case 2: Inherit entities associated with interfaces that were -- not covered by the parent type. We exclude here null interface -- primitives because they do not need special management. -- We also exclude interface operations that are renamings. If the -- subprogram is an explicit renaming of an interface primitive, -- it is a regular primitive operation, and the presence of its -- alias is not relevant: it has to be derived like any other -- primitive. elsif Present (Alias (Subp)) and then Nkind (Unit_Declaration_Node (Subp)) /= N_Subprogram_Renaming_Declaration and then Is_Interface (Find_Dispatching_Type (Alias_Subp)) and then not (Nkind (Parent (Alias_Subp)) = N_Procedure_Specification and then Null_Present (Parent (Alias_Subp))) then -- If this is an abstract private type then we transfer the -- derivation of the interface primitive from the partial view -- to the full view. This is safe because all the interfaces -- must be visible in the partial view. Done to avoid adding -- a new interface derivation to the private part of the -- enclosing package; otherwise this new derivation would be -- decorated as hidden when the analysis of the enclosing -- package completes. if Is_Abstract_Type (Derived_Type) and then In_Private_Part (Current_Scope) and then Has_Private_Declaration (Derived_Type) then declare Partial_View : Entity_Id; Elmt : Elmt_Id; Ent : Entity_Id; begin Partial_View := First_Entity (Current_Scope); loop exit when No (Partial_View) or else (Has_Private_Declaration (Partial_View) and then Full_View (Partial_View) = Derived_Type); Next_Entity (Partial_View); end loop; -- If the partial view was not found then the source code -- has errors and the derivation is not needed. if Present (Partial_View) then Elmt := First_Elmt (Primitive_Operations (Partial_View)); while Present (Elmt) loop Ent := Node (Elmt); if Present (Alias (Ent)) and then Ultimate_Alias (Ent) = Alias (Subp) then Append_Elmt (Ent, Primitive_Operations (Derived_Type)); exit; end if; Next_Elmt (Elmt); end loop; -- If the interface primitive was not found in the -- partial view then this interface primitive was -- overridden. We add a derivation to activate in -- Derive_Progenitor_Subprograms the machinery to -- search for it. if No (Elmt) then Derive_Interface_Subprogram (New_Subp => New_Subp, Subp => Subp, Actual_Subp => Act_Subp); end if; end if; end; else Derive_Interface_Subprogram (New_Subp => New_Subp, Subp => Subp, Actual_Subp => Act_Subp); end if; -- Case 3: Common derivation else Derive_Subprogram (New_Subp => New_Subp, Parent_Subp => Subp, Derived_Type => Derived_Type, Parent_Type => Parent_Base, Actual_Subp => Act_Subp); end if; -- No need to update Act_Elm if we must search for the -- corresponding operation in the generic actual if not Need_Search and then Present (Act_Elmt) then Next_Elmt (Act_Elmt); Act_Subp := Node (Act_Elmt); end if; <> Next_Elmt (Elmt); end loop; -- Inherit additional operations from progenitors. If the derived -- type is a generic actual, there are not new primitive operations -- for the type because it has those of the actual, and therefore -- nothing needs to be done. The renamings generated above are not -- primitive operations, and their purpose is simply to make the -- proper operations visible within an instantiation. if No (Generic_Actual) then Derive_Progenitor_Subprograms (Parent_Base, Derived_Type); end if; end if; -- Final check: Direct descendants must have their primitives in the -- same order. We exclude from this test untagged types and instances -- of formal derived types. We skip this test if we have already -- reported serious errors in the sources. pragma Assert (not Is_Tagged_Type (Derived_Type) or else Present (Generic_Actual) or else Serious_Errors_Detected > 0 or else Check_Derived_Type); end Derive_Subprograms; -------------------------------- -- Derived_Standard_Character -- -------------------------------- procedure Derived_Standard_Character (N : Node_Id; Parent_Type : Entity_Id; Derived_Type : Entity_Id) is Loc : constant Source_Ptr := Sloc (N); Def : constant Node_Id := Type_Definition (N); Indic : constant Node_Id := Subtype_Indication (Def); Parent_Base : constant Entity_Id := Base_Type (Parent_Type); Implicit_Base : constant Entity_Id := Create_Itype (E_Enumeration_Type, N, Derived_Type, 'B'); Lo : Node_Id; Hi : Node_Id; begin Discard_Node (Process_Subtype (Indic, N)); Set_Etype (Implicit_Base, Parent_Base); Set_Size_Info (Implicit_Base, Root_Type (Parent_Type)); Set_RM_Size (Implicit_Base, RM_Size (Root_Type (Parent_Type))); Set_Is_Character_Type (Implicit_Base, True); Set_Has_Delayed_Freeze (Implicit_Base); -- The bounds of the implicit base are the bounds of the parent base. -- Note that their type is the parent base. Lo := New_Copy_Tree (Type_Low_Bound (Parent_Base)); Hi := New_Copy_Tree (Type_High_Bound (Parent_Base)); Set_Scalar_Range (Implicit_Base, Make_Range (Loc, Low_Bound => Lo, High_Bound => Hi)); Conditional_Delay (Derived_Type, Parent_Type); Mutate_Ekind (Derived_Type, E_Enumeration_Subtype); Set_Etype (Derived_Type, Implicit_Base); Set_Size_Info (Derived_Type, Parent_Type); if not Known_RM_Size (Derived_Type) then Set_RM_Size (Derived_Type, RM_Size (Parent_Type)); end if; Set_Is_Character_Type (Derived_Type, True); if Nkind (Indic) /= N_Subtype_Indication then -- If no explicit constraint, the bounds are those -- of the parent type. Lo := New_Copy_Tree (Type_Low_Bound (Parent_Type)); Hi := New_Copy_Tree (Type_High_Bound (Parent_Type)); Set_Scalar_Range (Derived_Type, Make_Range (Loc, Lo, Hi)); end if; Convert_Scalar_Bounds (N, Parent_Type, Derived_Type, Loc); -- Because the implicit base is used in the conversion of the bounds, we -- have to freeze it now. This is similar to what is done for numeric -- types, and it equally suspicious, but otherwise a nonstatic bound -- will have a reference to an unfrozen type, which is rejected by Gigi -- (???). This requires specific care for definition of stream -- attributes. For details, see comments at the end of -- Build_Derived_Numeric_Type. Freeze_Before (N, Implicit_Base); end Derived_Standard_Character; ------------------------------ -- Derived_Type_Declaration -- ------------------------------ procedure Derived_Type_Declaration (T : Entity_Id; N : Node_Id; Is_Completion : Boolean) is Parent_Type : Entity_Id; function Comes_From_Generic (Typ : Entity_Id) return Boolean; -- Check whether the parent type is a generic formal, or derives -- directly or indirectly from one. ------------------------ -- Comes_From_Generic -- ------------------------ function Comes_From_Generic (Typ : Entity_Id) return Boolean is begin if Is_Generic_Type (Typ) then return True; elsif Is_Generic_Type (Root_Type (Parent_Type)) then return True; elsif Is_Private_Type (Typ) and then Present (Full_View (Typ)) and then Is_Generic_Type (Root_Type (Full_View (Typ))) then return True; elsif Is_Generic_Actual_Type (Typ) then return True; else return False; end if; end Comes_From_Generic; -- Local variables Def : constant Node_Id := Type_Definition (N); Iface_Def : Node_Id; Indic : constant Node_Id := Subtype_Indication (Def); Extension : constant Node_Id := Record_Extension_Part (Def); Parent_Node : Node_Id; Taggd : Boolean; -- Start of processing for Derived_Type_Declaration begin Parent_Type := Find_Type_Of_Subtype_Indic (Indic); if SPARK_Mode = On and then Is_Tagged_Type (Parent_Type) then declare Partial_View : constant Entity_Id := Incomplete_Or_Partial_View (Parent_Type); begin -- If the partial view was not found then the parent type is not -- a private type. Otherwise check if the partial view is a tagged -- private type. if Present (Partial_View) and then Is_Private_Type (Partial_View) and then not Is_Tagged_Type (Partial_View) then Error_Msg_NE ("cannot derive from & declared as untagged private " & "(SPARK RM 3.4(1))", N, Partial_View); end if; end; end if; -- Ada 2005 (AI-251): In case of interface derivation check that the -- parent is also an interface. if Interface_Present (Def) then if not Is_Interface (Parent_Type) then Diagnose_Interface (Indic, Parent_Type); else Parent_Node := Parent (Base_Type (Parent_Type)); Iface_Def := Type_Definition (Parent_Node); -- Ada 2005 (AI-251): Limited interfaces can only inherit from -- other limited interfaces. if Limited_Present (Def) then if Limited_Present (Iface_Def) then null; elsif Protected_Present (Iface_Def) then Error_Msg_NE ("descendant of & must be declared as a protected " & "interface", N, Parent_Type); elsif Synchronized_Present (Iface_Def) then Error_Msg_NE ("descendant of & must be declared as a synchronized " & "interface", N, Parent_Type); elsif Task_Present (Iface_Def) then Error_Msg_NE ("descendant of & must be declared as a task interface", N, Parent_Type); else Error_Msg_N ("(Ada 2005) limited interface cannot inherit from " & "non-limited interface", Indic); end if; -- Ada 2005 (AI-345): Non-limited interfaces can only inherit -- from non-limited or limited interfaces. elsif not Protected_Present (Def) and then not Synchronized_Present (Def) and then not Task_Present (Def) then if Limited_Present (Iface_Def) then null; elsif Protected_Present (Iface_Def) then Error_Msg_NE ("descendant of & must be declared as a protected " & "interface", N, Parent_Type); elsif Synchronized_Present (Iface_Def) then Error_Msg_NE ("descendant of & must be declared as a synchronized " & "interface", N, Parent_Type); elsif Task_Present (Iface_Def) then Error_Msg_NE ("descendant of & must be declared as a task interface", N, Parent_Type); else null; end if; end if; end if; end if; if Is_Tagged_Type (Parent_Type) and then Is_Concurrent_Type (Parent_Type) and then not Is_Interface (Parent_Type) then Error_Msg_N ("parent type of a record extension cannot be a synchronized " & "tagged type (RM 3.9.1 (3/1))", N); Set_Etype (T, Any_Type); return; end if; -- Ada 2005 (AI-251): Decorate all the names in the list of ancestor -- interfaces if Is_Tagged_Type (Parent_Type) and then Is_Non_Empty_List (Interface_List (Def)) then declare Intf : Node_Id; T : Entity_Id; begin Intf := First (Interface_List (Def)); while Present (Intf) loop T := Find_Type_Of_Subtype_Indic (Intf); if not Is_Interface (T) then Diagnose_Interface (Intf, T); -- Check the rules of 3.9.4(12/2) and 7.5(2/2) that disallow -- a limited type from having a nonlimited progenitor. elsif (Limited_Present (Def) or else (not Is_Interface (Parent_Type) and then Is_Limited_Type (Parent_Type))) and then not Is_Limited_Interface (T) then Error_Msg_NE ("progenitor interface& of limited type must be limited", N, T); end if; Next (Intf); end loop; end; -- Check consistency of any nonoverridable aspects that are -- inherited from multiple sources. Check_Inherited_Nonoverridable_Aspects (Inheritor => T, Interface_List => Interface_List (Def), Parent_Type => Parent_Type); end if; if Parent_Type = Any_Type or else Etype (Parent_Type) = Any_Type or else (Is_Class_Wide_Type (Parent_Type) and then Etype (Parent_Type) = T) then -- If Parent_Type is undefined or illegal, make new type into a -- subtype of Any_Type, and set a few attributes to prevent cascaded -- errors. If this is a self-definition, emit error now. if T = Parent_Type or else T = Etype (Parent_Type) then Error_Msg_N ("type cannot be used in its own definition", Indic); end if; Mutate_Ekind (T, Ekind (Parent_Type)); Set_Etype (T, Any_Type); Set_Scalar_Range (T, Scalar_Range (Any_Type)); -- Initialize the list of primitive operations to an empty list, -- to cover tagged types as well as untagged types. For untagged -- types this is used either to analyze the call as legal when -- Extensions_Allowed is True, or to issue a better error message -- otherwise. Set_Direct_Primitive_Operations (T, New_Elmt_List); return; end if; -- Ada 2005 (AI-251): The case in which the parent of the full-view is -- an interface is special because the list of interfaces in the full -- view can be given in any order. For example: -- type A is interface; -- type B is interface and A; -- type D is new B with private; -- private -- type D is new A and B with null record; -- 1 -- -- In this case we perform the following transformation of -1-: -- type D is new B and A with null record; -- If the parent of the full-view covers the parent of the partial-view -- we have two possible cases: -- 1) They have the same parent -- 2) The parent of the full-view implements some further interfaces -- In both cases we do not need to perform the transformation. In the -- first case the source program is correct and the transformation is -- not needed; in the second case the source program does not fulfill -- the no-hidden interfaces rule (AI-396) and the error will be reported -- later. -- This transformation not only simplifies the rest of the analysis of -- this type declaration but also simplifies the correct generation of -- the object layout to the expander. if In_Private_Part (Current_Scope) and then Is_Interface (Parent_Type) then declare Partial_View : Entity_Id; Partial_View_Parent : Entity_Id; function Reorder_Interfaces return Boolean; -- Look for an interface in the full view's interface list that -- matches the parent type of the partial view, and when found, -- rewrite the full view's parent with the partial view's parent, -- append the full view's original parent to the interface list, -- recursively call Derived_Type_Definition on the full type, and -- return True. If a match is not found, return False. ------------------------ -- Reorder_Interfaces -- ------------------------ function Reorder_Interfaces return Boolean is Iface : Node_Id; New_Iface : Node_Id; begin Iface := First (Interface_List (Def)); while Present (Iface) loop if Etype (Iface) = Etype (Partial_View) then Rewrite (Subtype_Indication (Def), New_Copy (Subtype_Indication (Parent (Partial_View)))); New_Iface := Make_Identifier (Sloc (N), Chars (Parent_Type)); Rewrite (Iface, New_Iface); -- Analyze the transformed code Derived_Type_Declaration (T, N, Is_Completion); return True; end if; Next (Iface); end loop; return False; end Reorder_Interfaces; begin -- Look for the associated private type declaration Partial_View := Incomplete_Or_Partial_View (T); -- If the partial view was not found then the source code has -- errors and the transformation is not needed. if Present (Partial_View) then Partial_View_Parent := Etype (Partial_View); -- If the parent of the full-view covers the parent of the -- partial-view we have nothing else to do. if Interface_Present_In_Ancestor (Parent_Type, Partial_View_Parent) then null; -- Traverse the list of interfaces of the full view to look -- for the parent of the partial view and reorder the -- interfaces to match the order in the partial view, -- if needed. else if Reorder_Interfaces then -- Having the interfaces listed in any order is legal. -- However, the compiler does not properly handle -- different orders between partial and full views in -- generic units. We give a warning about the order -- mismatch, so the user can work around this problem. Error_Msg_N ("??full declaration does not respect " & "partial declaration order", T); Error_Msg_N ("\??consider reordering", T); return; end if; end if; end if; end; end if; -- Only composite types other than array types are allowed to have -- discriminants. if Present (Discriminant_Specifications (N)) then if (Is_Elementary_Type (Parent_Type) or else Is_Array_Type (Parent_Type)) and then not Error_Posted (N) then Error_Msg_N ("elementary or array type cannot have discriminants", Defining_Identifier (First (Discriminant_Specifications (N)))); -- Unset Has_Discriminants flag to prevent cascaded errors, but -- only if we are not already processing a malformed syntax tree. if Is_Type (T) then Set_Has_Discriminants (T, False); end if; end if; end if; -- In Ada 83, a derived type defined in a package specification cannot -- be used for further derivation until the end of its visible part. -- Note that derivation in the private part of the package is allowed. if Ada_Version = Ada_83 and then Is_Derived_Type (Parent_Type) and then In_Visible_Part (Scope (Parent_Type)) then if Ada_Version = Ada_83 and then Comes_From_Source (Indic) then Error_Msg_N ("(Ada 83) premature use of type for derivation", Indic); end if; end if; -- Check for early use of incomplete or private type if Ekind (Parent_Type) in E_Void | E_Incomplete_Type then Error_Msg_N ("premature derivation of incomplete type", Indic); return; elsif (Is_Incomplete_Or_Private_Type (Parent_Type) and then not Comes_From_Generic (Parent_Type)) or else Has_Private_Component (Parent_Type) then -- The ancestor type of a formal type can be incomplete, in which -- case only the operations of the partial view are available in the -- generic. Subsequent checks may be required when the full view is -- analyzed to verify that a derivation from a tagged type has an -- extension. if Nkind (Original_Node (N)) = N_Formal_Type_Declaration then null; elsif No (Underlying_Type (Parent_Type)) or else Has_Private_Component (Parent_Type) then Error_Msg_N ("premature derivation of derived or private type", Indic); -- Flag the type itself as being in error, this prevents some -- nasty problems with subsequent uses of the malformed type. Set_Error_Posted (T); -- Check that within the immediate scope of an untagged partial -- view it's illegal to derive from the partial view if the -- full view is tagged. (7.3(7)) -- We verify that the Parent_Type is a partial view by checking -- that it is not a Full_Type_Declaration (i.e. a private type or -- private extension declaration), to distinguish a partial view -- from a derivation from a private type which also appears as -- E_Private_Type. If the parent base type is not declared in an -- enclosing scope there is no need to check. elsif Present (Full_View (Parent_Type)) and then Nkind (Parent (Parent_Type)) /= N_Full_Type_Declaration and then not Is_Tagged_Type (Parent_Type) and then Is_Tagged_Type (Full_View (Parent_Type)) and then In_Open_Scopes (Scope (Base_Type (Parent_Type))) then Error_Msg_N ("premature derivation from type with tagged full view", Indic); end if; end if; -- Check that form of derivation is appropriate Taggd := Is_Tagged_Type (Parent_Type); -- Set the parent type to the class-wide type's specific type in this -- case to prevent cascading errors if Present (Extension) and then Is_Class_Wide_Type (Parent_Type) then Error_Msg_N ("parent type must not be a class-wide type", Indic); Set_Etype (T, Etype (Parent_Type)); return; end if; if Present (Extension) and then not Taggd then Error_Msg_N ("type derived from untagged type cannot have extension", Indic); elsif No (Extension) and then Taggd then -- If this declaration is within a private part (or body) of a -- generic instantiation then the derivation is allowed (the parent -- type can only appear tagged in this case if it's a generic actual -- type, since it would otherwise have been rejected in the analysis -- of the generic template). if not Is_Generic_Actual_Type (Parent_Type) or else In_Visible_Part (Scope (Parent_Type)) then if Is_Class_Wide_Type (Parent_Type) then Error_Msg_N ("parent type must not be a class-wide type", Indic); -- Use specific type to prevent cascaded errors. Parent_Type := Etype (Parent_Type); else Error_Msg_N ("type derived from tagged type must have extension", Indic); end if; end if; end if; -- AI-443: Synchronized formal derived types require a private -- extension. There is no point in checking the ancestor type or -- the progenitors since the construct is wrong to begin with. if Ada_Version >= Ada_2005 and then Is_Generic_Type (T) and then Present (Original_Node (N)) then declare Decl : constant Node_Id := Original_Node (N); begin if Nkind (Decl) = N_Formal_Type_Declaration and then Nkind (Formal_Type_Definition (Decl)) = N_Formal_Derived_Type_Definition and then Synchronized_Present (Formal_Type_Definition (Decl)) and then No (Extension) -- Avoid emitting a duplicate error message and then not Error_Posted (Indic) then Error_Msg_N ("synchronized derived type must have extension", N); end if; end; end if; if Null_Exclusion_Present (Def) and then not Is_Access_Type (Parent_Type) then Error_Msg_N ("null exclusion can only apply to an access type", N); end if; Check_Wide_Character_Restriction (Parent_Type, Indic); -- Avoid deriving parent primitives of underlying record views Build_Derived_Type (N, Parent_Type, T, Is_Completion, Derive_Subps => not Is_Underlying_Record_View (T)); -- AI-419: The parent type of an explicitly limited derived type must -- be a limited type or a limited interface. if Limited_Present (Def) then Set_Is_Limited_Record (T); if Is_Interface (T) then Set_Is_Limited_Interface (T); end if; if not Is_Limited_Type (Parent_Type) and then (not Is_Interface (Parent_Type) or else not Is_Limited_Interface (Parent_Type)) then -- AI05-0096: a derivation in the private part of an instance is -- legal if the generic formal is untagged limited, and the actual -- is non-limited. if Is_Generic_Actual_Type (Parent_Type) and then In_Private_Part (Current_Scope) and then not Is_Tagged_Type (Generic_Parent_Type (Parent (Parent_Type))) then null; else Error_Msg_NE ("parent type& of limited type must be limited", N, Parent_Type); end if; end if; end if; end Derived_Type_Declaration; ------------------------ -- Diagnose_Interface -- ------------------------ procedure Diagnose_Interface (N : Node_Id; E : Entity_Id) is begin if not Is_Interface (E) and then E /= Any_Type then Error_Msg_NE ("(Ada 2005) & must be an interface", N, E); end if; end Diagnose_Interface; ---------------------------------- -- Enumeration_Type_Declaration -- ---------------------------------- procedure Enumeration_Type_Declaration (T : Entity_Id; Def : Node_Id) is Ev : Uint; L : Node_Id; R_Node : Node_Id; B_Node : Node_Id; begin -- Create identifier node representing lower bound B_Node := New_Node (N_Identifier, Sloc (Def)); L := First (Literals (Def)); Set_Chars (B_Node, Chars (L)); Set_Entity (B_Node, L); Set_Etype (B_Node, T); Set_Is_Static_Expression (B_Node, True); R_Node := New_Node (N_Range, Sloc (Def)); Set_Low_Bound (R_Node, B_Node); Mutate_Ekind (T, E_Enumeration_Type); Set_First_Literal (T, L); Set_Etype (T, T); Set_Is_Constrained (T); Ev := Uint_0; -- Loop through literals of enumeration type setting pos and rep values -- except that if the Ekind is already set, then it means the literal -- was already constructed (case of a derived type declaration and we -- should not disturb the Pos and Rep values. while Present (L) loop if Ekind (L) /= E_Enumeration_Literal then Mutate_Ekind (L, E_Enumeration_Literal); Set_Enumeration_Pos (L, Ev); Set_Enumeration_Rep (L, Ev); Set_Is_Known_Valid (L, True); end if; Set_Etype (L, T); New_Overloaded_Entity (L); Generate_Definition (L); Set_Convention (L, Convention_Intrinsic); -- Case of character literal if Nkind (L) = N_Defining_Character_Literal then Set_Is_Character_Type (T, True); -- Check violation of No_Wide_Characters if Restriction_Check_Required (No_Wide_Characters) then Get_Name_String (Chars (L)); if Name_Len >= 3 and then Name_Buffer (1 .. 2) = "QW" then Check_Restriction (No_Wide_Characters, L); end if; end if; end if; Ev := Ev + 1; Next (L); end loop; -- Now create a node representing upper bound B_Node := New_Node (N_Identifier, Sloc (Def)); Set_Chars (B_Node, Chars (Last (Literals (Def)))); Set_Entity (B_Node, Last (Literals (Def))); Set_Etype (B_Node, T); Set_Is_Static_Expression (B_Node, True); Set_High_Bound (R_Node, B_Node); -- Initialize various fields of the type. Some of this information -- may be overwritten later through rep. clauses. Set_Scalar_Range (T, R_Node); Set_RM_Size (T, UI_From_Int (Minimum_Size (T))); Set_Enum_Esize (T); Set_Enum_Pos_To_Rep (T, Empty); -- Set Discard_Names if configuration pragma set, or if there is -- a parameterless pragma in the current declarative region if Global_Discard_Names or else Discard_Names (Scope (T)) then Set_Discard_Names (T); end if; -- Process end label if there is one if Present (Def) then Process_End_Label (Def, 'e', T); end if; end Enumeration_Type_Declaration; --------------------------------- -- Expand_To_Stored_Constraint -- --------------------------------- function Expand_To_Stored_Constraint (Typ : Entity_Id; Constraint : Elist_Id) return Elist_Id is Explicitly_Discriminated_Type : Entity_Id; Expansion : Elist_Id; Discriminant : Entity_Id; function Type_With_Explicit_Discrims (Id : Entity_Id) return Entity_Id; -- Find the nearest type that actually specifies discriminants --------------------------------- -- Type_With_Explicit_Discrims -- --------------------------------- function Type_With_Explicit_Discrims (Id : Entity_Id) return Entity_Id is Typ : constant E := Base_Type (Id); begin if Ekind (Typ) in Incomplete_Or_Private_Kind then if Present (Full_View (Typ)) then return Type_With_Explicit_Discrims (Full_View (Typ)); end if; else if Has_Discriminants (Typ) then return Typ; end if; end if; if Etype (Typ) = Typ then return Empty; elsif Has_Discriminants (Typ) then return Typ; else return Type_With_Explicit_Discrims (Etype (Typ)); end if; end Type_With_Explicit_Discrims; -- Start of processing for Expand_To_Stored_Constraint begin if No (Constraint) or else Is_Empty_Elmt_List (Constraint) then return No_Elist; end if; Explicitly_Discriminated_Type := Type_With_Explicit_Discrims (Typ); if No (Explicitly_Discriminated_Type) then return No_Elist; end if; Expansion := New_Elmt_List; Discriminant := First_Stored_Discriminant (Explicitly_Discriminated_Type); while Present (Discriminant) loop Append_Elmt (Get_Discriminant_Value (Discriminant, Explicitly_Discriminated_Type, Constraint), To => Expansion); Next_Stored_Discriminant (Discriminant); end loop; return Expansion; end Expand_To_Stored_Constraint; --------------------------- -- Find_Hidden_Interface -- --------------------------- function Find_Hidden_Interface (Src : Elist_Id; Dest : Elist_Id) return Entity_Id is Iface : Entity_Id; Iface_Elmt : Elmt_Id; begin if Present (Src) and then Present (Dest) then Iface_Elmt := First_Elmt (Src); while Present (Iface_Elmt) loop Iface := Node (Iface_Elmt); if Is_Interface (Iface) and then not Contain_Interface (Iface, Dest) then return Iface; end if; Next_Elmt (Iface_Elmt); end loop; end if; return Empty; end Find_Hidden_Interface; -------------------- -- Find_Type_Name -- -------------------- function Find_Type_Name (N : Node_Id) return Entity_Id is Id : constant Entity_Id := Defining_Identifier (N); New_Id : Entity_Id; Prev : Entity_Id; Prev_Par : Node_Id; procedure Check_Duplicate_Aspects; -- Check that aspects specified in a completion have not been specified -- already in the partial view. procedure Tag_Mismatch; -- Diagnose a tagged partial view whose full view is untagged. We post -- the message on the full view, with a reference to the previous -- partial view. The partial view can be private or incomplete, and -- these are handled in a different manner, so we determine the position -- of the error message from the respective slocs of both. ----------------------------- -- Check_Duplicate_Aspects -- ----------------------------- procedure Check_Duplicate_Aspects is function Get_Partial_View_Aspect (Asp : Node_Id) return Node_Id; -- Return the corresponding aspect of the partial view which matches -- the aspect id of Asp. Return Empty is no such aspect exists. ----------------------------- -- Get_Partial_View_Aspect -- ----------------------------- function Get_Partial_View_Aspect (Asp : Node_Id) return Node_Id is Asp_Id : constant Aspect_Id := Get_Aspect_Id (Asp); Prev_Asps : constant List_Id := Aspect_Specifications (Prev_Par); Prev_Asp : Node_Id; begin if Present (Prev_Asps) then Prev_Asp := First (Prev_Asps); while Present (Prev_Asp) loop if Get_Aspect_Id (Prev_Asp) = Asp_Id then return Prev_Asp; end if; Next (Prev_Asp); end loop; end if; return Empty; end Get_Partial_View_Aspect; -- Local variables Full_Asps : constant List_Id := Aspect_Specifications (N); Full_Asp : Node_Id; Part_Asp : Node_Id; -- Start of processing for Check_Duplicate_Aspects begin if Present (Full_Asps) then Full_Asp := First (Full_Asps); while Present (Full_Asp) loop Part_Asp := Get_Partial_View_Aspect (Full_Asp); -- An aspect and its class-wide counterpart are two distinct -- aspects and may apply to both views of an entity. if Present (Part_Asp) and then Class_Present (Part_Asp) = Class_Present (Full_Asp) then Error_Msg_N ("aspect already specified in private declaration", Full_Asp); Remove (Full_Asp); return; end if; if Has_Discriminants (Prev) and then not Has_Unknown_Discriminants (Prev) and then Get_Aspect_Id (Full_Asp) = Aspect_Implicit_Dereference then Error_Msg_N ("cannot specify aspect if partial view has known " & "discriminants", Full_Asp); end if; Next (Full_Asp); end loop; end if; end Check_Duplicate_Aspects; ------------------ -- Tag_Mismatch -- ------------------ procedure Tag_Mismatch is begin if Sloc (Prev) < Sloc (Id) then if Ada_Version >= Ada_2012 and then Nkind (N) = N_Private_Type_Declaration then Error_Msg_NE ("declaration of private } must be a tagged type", Id, Prev); else Error_Msg_NE ("full declaration of } must be a tagged type", Id, Prev); end if; else if Ada_Version >= Ada_2012 and then Nkind (N) = N_Private_Type_Declaration then Error_Msg_NE ("declaration of private } must be a tagged type", Prev, Id); else Error_Msg_NE ("full declaration of } must be a tagged type", Prev, Id); end if; end if; end Tag_Mismatch; -- Start of processing for Find_Type_Name begin -- Find incomplete declaration, if one was given Prev := Current_Entity_In_Scope (Id); -- New type declaration if No (Prev) then Enter_Name (Id); return Id; -- Previous declaration exists else Prev_Par := Parent (Prev); -- Error if not incomplete/private case except if previous -- declaration is implicit, etc. Enter_Name will emit error if -- appropriate. if not Is_Incomplete_Or_Private_Type (Prev) then Enter_Name (Id); New_Id := Id; -- Check invalid completion of private or incomplete type elsif Nkind (N) not in N_Full_Type_Declaration | N_Task_Type_Declaration | N_Protected_Type_Declaration and then (Ada_Version < Ada_2012 or else not Is_Incomplete_Type (Prev) or else Nkind (N) not in N_Private_Type_Declaration | N_Private_Extension_Declaration) then -- Completion must be a full type declarations (RM 7.3(4)) Error_Msg_Sloc := Sloc (Prev); Error_Msg_NE ("invalid completion of }", Id, Prev); -- Set scope of Id to avoid cascaded errors. Entity is never -- examined again, except when saving globals in generics. Set_Scope (Id, Current_Scope); New_Id := Id; -- If this is a repeated incomplete declaration, no further -- checks are possible. if Nkind (N) = N_Incomplete_Type_Declaration then return Prev; end if; -- Case of full declaration of incomplete type elsif Ekind (Prev) = E_Incomplete_Type and then (Ada_Version < Ada_2012 or else No (Full_View (Prev)) or else not Is_Private_Type (Full_View (Prev))) then -- Indicate that the incomplete declaration has a matching full -- declaration. The defining occurrence of the incomplete -- declaration remains the visible one, and the procedure -- Get_Full_View dereferences it whenever the type is used. if Present (Full_View (Prev)) then Error_Msg_NE ("invalid redeclaration of }", Id, Prev); end if; Set_Full_View (Prev, Id); Append_Entity (Id, Current_Scope); Set_Is_Public (Id, Is_Public (Prev)); Set_Is_Internal (Id); New_Id := Prev; -- If the incomplete view is tagged, a class_wide type has been -- created already. Use it for the private type as well, in order -- to prevent multiple incompatible class-wide types that may be -- created for self-referential anonymous access components. if Is_Tagged_Type (Prev) and then Present (Class_Wide_Type (Prev)) then Mutate_Ekind (Id, Ekind (Prev)); -- will be reset later Set_Class_Wide_Type (Id, Class_Wide_Type (Prev)); -- Type of the class-wide type is the current Id. Previously -- this was not done for private declarations because of order- -- of-elaboration issues in the back end, but gigi now handles -- this properly. Set_Etype (Class_Wide_Type (Id), Id); end if; -- Case of full declaration of private type else -- If the private type was a completion of an incomplete type then -- update Prev to reference the private type if Ada_Version >= Ada_2012 and then Ekind (Prev) = E_Incomplete_Type and then Present (Full_View (Prev)) and then Is_Private_Type (Full_View (Prev)) then Prev := Full_View (Prev); Prev_Par := Parent (Prev); end if; if Nkind (N) = N_Full_Type_Declaration and then Nkind (Type_Definition (N)) in N_Record_Definition | N_Derived_Type_Definition and then Interface_Present (Type_Definition (N)) then Error_Msg_N ("completion of private type cannot be an interface", N); end if; if Nkind (Parent (Prev)) /= N_Private_Extension_Declaration then if Etype (Prev) /= Prev then -- Prev is a private subtype or a derived type, and needs -- no completion. Error_Msg_NE ("invalid redeclaration of }", Id, Prev); New_Id := Id; elsif Ekind (Prev) = E_Private_Type and then Nkind (N) in N_Task_Type_Declaration | N_Protected_Type_Declaration then Error_Msg_N ("completion of nonlimited type cannot be limited", N); elsif Ekind (Prev) = E_Record_Type_With_Private and then Nkind (N) in N_Task_Type_Declaration | N_Protected_Type_Declaration then if not Is_Limited_Record (Prev) then Error_Msg_N ("completion of nonlimited type cannot be limited", N); elsif No (Interface_List (N)) then Error_Msg_N ("completion of tagged private type must be tagged", N); end if; end if; -- Ada 2005 (AI-251): Private extension declaration of a task -- type or a protected type. This case arises when covering -- interface types. elsif Nkind (N) in N_Task_Type_Declaration | N_Protected_Type_Declaration then null; elsif Nkind (N) /= N_Full_Type_Declaration or else Nkind (Type_Definition (N)) /= N_Derived_Type_Definition then Error_Msg_N ("full view of private extension must be an extension", N); elsif not (Abstract_Present (Parent (Prev))) and then Abstract_Present (Type_Definition (N)) then Error_Msg_N ("full view of non-abstract extension cannot be abstract", N); end if; if not In_Private_Part (Current_Scope) then Error_Msg_N ("declaration of full view must appear in private part", N); end if; if Ada_Version >= Ada_2012 then Check_Duplicate_Aspects; end if; Copy_And_Swap (Prev, Id); Set_Has_Private_Declaration (Prev); Set_Has_Private_Declaration (Id); -- AI12-0133: Indicate whether we have a partial view with -- unknown discriminants, in which case initialization of objects -- of the type do not receive an invariant check. Set_Partial_View_Has_Unknown_Discr (Prev, Has_Unknown_Discriminants (Id)); -- Preserve aspect and iterator flags that may have been set on -- the partial view. Set_Has_Delayed_Aspects (Prev, Has_Delayed_Aspects (Id)); Set_Has_Implicit_Dereference (Prev, Has_Implicit_Dereference (Id)); -- If no error, propagate freeze_node from private to full view. -- It may have been generated for an early operational item. if Present (Freeze_Node (Id)) and then Serious_Errors_Detected = 0 and then No (Full_View (Id)) then Set_Freeze_Node (Prev, Freeze_Node (Id)); Set_Freeze_Node (Id, Empty); Set_First_Rep_Item (Prev, First_Rep_Item (Id)); end if; Set_Full_View (Id, Prev); New_Id := Prev; end if; -- Verify that full declaration conforms to partial one if Is_Incomplete_Or_Private_Type (Prev) and then Present (Discriminant_Specifications (Prev_Par)) then if Present (Discriminant_Specifications (N)) then if Ekind (Prev) = E_Incomplete_Type then Check_Discriminant_Conformance (N, Prev, Prev); else Check_Discriminant_Conformance (N, Prev, Id); end if; else Error_Msg_N ("missing discriminants in full type declaration", N); -- To avoid cascaded errors on subsequent use, share the -- discriminants of the partial view. Set_Discriminant_Specifications (N, Discriminant_Specifications (Prev_Par)); end if; end if; -- A prior untagged partial view can have an associated class-wide -- type due to use of the class attribute, and in this case the full -- type must also be tagged. This Ada 95 usage is deprecated in favor -- of incomplete tagged declarations, but we check for it. if Is_Type (Prev) and then (Is_Tagged_Type (Prev) or else Present (Class_Wide_Type (Prev))) then -- Ada 2012 (AI05-0162): A private type may be the completion of -- an incomplete type. if Ada_Version >= Ada_2012 and then Is_Incomplete_Type (Prev) and then Nkind (N) in N_Private_Type_Declaration | N_Private_Extension_Declaration then -- No need to check private extensions since they are tagged if Nkind (N) = N_Private_Type_Declaration and then not Tagged_Present (N) then Tag_Mismatch; end if; -- The full declaration is either a tagged type (including -- a synchronized type that implements interfaces) or a -- type extension, otherwise this is an error. elsif Nkind (N) in N_Task_Type_Declaration | N_Protected_Type_Declaration then if No (Interface_List (N)) and then not Error_Posted (N) then Tag_Mismatch; end if; elsif Nkind (Type_Definition (N)) = N_Record_Definition then -- Indicate that the previous declaration (tagged incomplete -- or private declaration) requires the same on the full one. if not Tagged_Present (Type_Definition (N)) then Tag_Mismatch; Set_Is_Tagged_Type (Id); end if; elsif Nkind (Type_Definition (N)) = N_Derived_Type_Definition then if No (Record_Extension_Part (Type_Definition (N))) then Error_Msg_NE ("full declaration of } must be a record extension", Prev, Id); -- Set some attributes to produce a usable full view Set_Is_Tagged_Type (Id); end if; else Tag_Mismatch; end if; end if; if Present (Prev) and then Nkind (Parent (Prev)) = N_Incomplete_Type_Declaration and then Present (Premature_Use (Parent (Prev))) then Error_Msg_Sloc := Sloc (N); Error_Msg_N ("\full declaration #", Premature_Use (Parent (Prev))); end if; return New_Id; end if; end Find_Type_Name; ------------------------- -- Find_Type_Of_Object -- ------------------------- function Find_Type_Of_Object (Obj_Def : Node_Id; Related_Nod : Node_Id) return Entity_Id is Def_Kind : constant Node_Kind := Nkind (Obj_Def); P : Node_Id := Parent (Obj_Def); T : Entity_Id; Nam : Name_Id; begin -- If the parent is a component_definition node we climb to the -- component_declaration node if Nkind (P) = N_Component_Definition then P := Parent (P); end if; -- Case of an anonymous array subtype if Def_Kind in N_Array_Type_Definition then T := Empty; Array_Type_Declaration (T, Obj_Def); -- Create an explicit subtype whenever possible elsif Nkind (P) /= N_Component_Declaration and then Def_Kind = N_Subtype_Indication then -- Base name of subtype on object name, which will be unique in -- the current scope. -- If this is a duplicate declaration, return base type, to avoid -- generating duplicate anonymous types. if Error_Posted (P) then Analyze (Subtype_Mark (Obj_Def)); return Entity (Subtype_Mark (Obj_Def)); end if; Nam := New_External_Name (Chars (Defining_Identifier (Related_Nod)), 'S', 0, 'T'); T := Make_Defining_Identifier (Sloc (P), Nam); -- If In_Spec_Expression, for example within a pre/postcondition, -- provide enough information for use of the subtype without -- depending on full analysis and freezing, which will happen when -- building the correspondiing subprogram. if In_Spec_Expression then Analyze (Subtype_Mark (Obj_Def)); declare Base_T : constant Entity_Id := Entity (Subtype_Mark (Obj_Def)); Decl : constant Node_Id := Make_Subtype_Declaration (Sloc (P), Defining_Identifier => T, Subtype_Indication => Relocate_Node (Obj_Def)); begin Set_Etype (T, Base_T); Mutate_Ekind (T, Subtype_Kind (Ekind (Base_T))); Set_Parent (T, Obj_Def); if Ekind (T) = E_Array_Subtype then Set_First_Index (T, First_Index (Base_T)); Set_Is_Constrained (T); elsif Ekind (T) = E_Record_Subtype then Set_First_Entity (T, First_Entity (Base_T)); Set_Has_Discriminants (T, Has_Discriminants (Base_T)); Set_Is_Constrained (T); end if; Insert_Before (Related_Nod, Decl); end; return T; end if; -- When generating code, insert subtype declaration ahead of -- declaration that generated it. Insert_Action (Obj_Def, Make_Subtype_Declaration (Sloc (P), Defining_Identifier => T, Subtype_Indication => Relocate_Node (Obj_Def))); -- This subtype may need freezing, and this will not be done -- automatically if the object declaration is not in declarative -- part. Since this is an object declaration, the type cannot always -- be frozen here. Deferred constants do not freeze their type -- (which often enough will be private). if Nkind (P) = N_Object_Declaration and then Constant_Present (P) and then No (Expression (P)) then null; -- Here we freeze the base type of object type to catch premature use -- of discriminated private type without a full view. else Insert_Actions (Obj_Def, Freeze_Entity (Base_Type (T), P)); end if; -- Ada 2005 AI-406: the object definition in an object declaration -- can be an access definition. elsif Def_Kind = N_Access_Definition then T := Access_Definition (Related_Nod, Obj_Def); Set_Is_Local_Anonymous_Access (T, Ada_Version < Ada_2012 or else Nkind (P) /= N_Object_Declaration or else Is_Library_Level_Entity (Defining_Identifier (P))); -- Otherwise, the object definition is just a subtype_mark else T := Process_Subtype (Obj_Def, Related_Nod); end if; return T; end Find_Type_Of_Object; -------------------------------- -- Find_Type_Of_Subtype_Indic -- -------------------------------- function Find_Type_Of_Subtype_Indic (S : Node_Id) return Entity_Id is Typ : Entity_Id; begin -- Case of subtype mark with a constraint if Nkind (S) = N_Subtype_Indication then Find_Type (Subtype_Mark (S)); Typ := Entity (Subtype_Mark (S)); if not Is_Valid_Constraint_Kind (Ekind (Typ), Nkind (Constraint (S))) then Error_Msg_N ("incorrect constraint for this kind of type", Constraint (S)); Rewrite (S, New_Copy_Tree (Subtype_Mark (S))); end if; -- Otherwise we have a subtype mark without a constraint elsif Error_Posted (S) then Rewrite (S, New_Occurrence_Of (Any_Id, Sloc (S))); return Any_Type; else Find_Type (S); Typ := Entity (S); end if; return Typ; end Find_Type_Of_Subtype_Indic; ------------------------------------- -- Floating_Point_Type_Declaration -- ------------------------------------- procedure Floating_Point_Type_Declaration (T : Entity_Id; Def : Node_Id) is Digs : constant Node_Id := Digits_Expression (Def); Max_Digs_Val : constant Uint := Digits_Value (Standard_Long_Long_Float); Digs_Val : Uint; Base_Typ : Entity_Id; Implicit_Base : Entity_Id; function Can_Derive_From (E : Entity_Id) return Boolean; -- Find if given digits value, and possibly a specified range, allows -- derivation from specified type procedure Convert_Bound (B : Node_Id); -- If specified, the bounds must be static but may be of different -- types. They must be converted into machine numbers of the base type, -- in accordance with RM 4.9(38). function Find_Base_Type return Entity_Id; -- Find a predefined base type that Def can derive from, or generate -- an error and substitute Long_Long_Float if none exists. --------------------- -- Can_Derive_From -- --------------------- function Can_Derive_From (E : Entity_Id) return Boolean is Spec : constant Entity_Id := Real_Range_Specification (Def); begin -- Check specified "digits" constraint if Digs_Val > Digits_Value (E) then return False; end if; -- Check for matching range, if specified if Present (Spec) then if Expr_Value_R (Type_Low_Bound (E)) > Expr_Value_R (Low_Bound (Spec)) then return False; end if; if Expr_Value_R (Type_High_Bound (E)) < Expr_Value_R (High_Bound (Spec)) then return False; end if; end if; return True; end Can_Derive_From; ------------------- -- Convert_Bound -- -------------------- procedure Convert_Bound (B : Node_Id) is begin -- If the bound is not a literal it can only be static if it is -- a static constant, possibly of a specified type. if Is_Entity_Name (B) and then Ekind (Entity (B)) = E_Constant then Rewrite (B, Constant_Value (Entity (B))); end if; if Nkind (B) = N_Real_Literal then Set_Realval (B, Machine (Base_Typ, Realval (B), Round, B)); Set_Is_Machine_Number (B); Set_Etype (B, Base_Typ); end if; end Convert_Bound; -------------------- -- Find_Base_Type -- -------------------- function Find_Base_Type return Entity_Id is Choice : Elmt_Id := First_Elmt (Predefined_Float_Types); begin -- Iterate over the predefined types in order, returning the first -- one that Def can derive from. while Present (Choice) loop if Can_Derive_From (Node (Choice)) then return Node (Choice); end if; Next_Elmt (Choice); end loop; -- If we can't derive from any existing type, use Long_Long_Float -- and give appropriate message explaining the problem. if Digs_Val > Max_Digs_Val then -- It might be the case that there is a type with the requested -- range, just not the combination of digits and range. Error_Msg_N ("no predefined type has requested range and precision", Real_Range_Specification (Def)); else Error_Msg_N ("range too large for any predefined type", Real_Range_Specification (Def)); end if; return Standard_Long_Long_Float; end Find_Base_Type; -- Start of processing for Floating_Point_Type_Declaration begin Check_Restriction (No_Floating_Point, Def); -- Create an implicit base type Implicit_Base := Create_Itype (E_Floating_Point_Type, Parent (Def), T, 'B'); -- Analyze and verify digits value Analyze_And_Resolve (Digs, Any_Integer); Check_Digits_Expression (Digs); Digs_Val := Expr_Value (Digs); -- Process possible range spec and find correct type to derive from Process_Real_Range_Specification (Def); -- Check that requested number of digits is not too high. if Digs_Val > Max_Digs_Val then -- The check for Max_Base_Digits may be somewhat expensive, as it -- requires reading System, so only do it when necessary. declare Max_Base_Digits : constant Uint := Expr_Value (Expression (Parent (RTE (RE_Max_Base_Digits)))); begin if Digs_Val > Max_Base_Digits then Error_Msg_Uint_1 := Max_Base_Digits; Error_Msg_N ("digits value out of range, maximum is ^", Digs); elsif No (Real_Range_Specification (Def)) then Error_Msg_Uint_1 := Max_Digs_Val; Error_Msg_N ("types with more than ^ digits need range spec " & "(RM 3.5.7(6))", Digs); end if; end; end if; -- Find a suitable type to derive from or complain and use a substitute Base_Typ := Find_Base_Type; -- If there are bounds given in the declaration use them as the bounds -- of the type, otherwise use the bounds of the predefined base type -- that was chosen based on the Digits value. if Present (Real_Range_Specification (Def)) then Set_Scalar_Range (T, Real_Range_Specification (Def)); Set_Is_Constrained (T); Convert_Bound (Type_Low_Bound (T)); Convert_Bound (Type_High_Bound (T)); else Set_Scalar_Range (T, Scalar_Range (Base_Typ)); end if; -- Complete definition of implicit base and declared first subtype. The -- inheritance of the rep item chain ensures that SPARK-related pragmas -- are not clobbered when the floating point type acts as a full view of -- a private type. Set_Etype (Implicit_Base, Base_Typ); Set_Scalar_Range (Implicit_Base, Scalar_Range (Base_Typ)); Set_Size_Info (Implicit_Base, Base_Typ); Set_RM_Size (Implicit_Base, RM_Size (Base_Typ)); Set_First_Rep_Item (Implicit_Base, First_Rep_Item (Base_Typ)); Set_Digits_Value (Implicit_Base, Digits_Value (Base_Typ)); Set_Float_Rep (Implicit_Base, Float_Rep (Base_Typ)); Mutate_Ekind (T, E_Floating_Point_Subtype); Set_Etype (T, Implicit_Base); Set_Size_Info (T, Implicit_Base); Set_RM_Size (T, RM_Size (Implicit_Base)); Inherit_Rep_Item_Chain (T, Implicit_Base); if Digs_Val >= Uint_1 then Set_Digits_Value (T, Digs_Val); else pragma Assert (Serious_Errors_Detected > 0); null; end if; end Floating_Point_Type_Declaration; ---------------------------- -- Get_Discriminant_Value -- ---------------------------- -- This is the situation: -- There is a non-derived type -- type T0 (Dx, Dy, Dz...) -- There are zero or more levels of derivation, with each derivation -- either purely inheriting the discriminants, or defining its own. -- type Ti is new Ti-1 -- or -- type Ti (Dw) is new Ti-1(Dw, 1, X+Y) -- or -- subtype Ti is ... -- The subtype issue is avoided by the use of Original_Record_Component, -- and the fact that derived subtypes also derive the constraints. -- This chain leads back from -- Typ_For_Constraint -- Typ_For_Constraint has discriminants, and the value for each -- discriminant is given by its corresponding Elmt of Constraints. -- Discriminant is some discriminant in this hierarchy -- We need to return its value -- We do this by recursively searching each level, and looking for -- Discriminant. Once we get to the bottom, we start backing up -- returning the value for it which may in turn be a discriminant -- further up, so on the backup we continue the substitution. function Get_Discriminant_Value (Discriminant : Entity_Id; Typ_For_Constraint : Entity_Id; Constraint : Elist_Id) return Node_Id is function Root_Corresponding_Discriminant (Discr : Entity_Id) return Entity_Id; -- Given a discriminant, traverse the chain of inherited discriminants -- and return the topmost discriminant. function Search_Derivation_Levels (Ti : Entity_Id; Discrim_Values : Elist_Id; Stored_Discrim_Values : Boolean) return Node_Or_Entity_Id; -- This is the routine that performs the recursive search of levels -- as described above. ------------------------------------- -- Root_Corresponding_Discriminant -- ------------------------------------- function Root_Corresponding_Discriminant (Discr : Entity_Id) return Entity_Id is D : Entity_Id; begin D := Discr; while Present (Corresponding_Discriminant (D)) loop D := Corresponding_Discriminant (D); end loop; return D; end Root_Corresponding_Discriminant; ------------------------------ -- Search_Derivation_Levels -- ------------------------------ function Search_Derivation_Levels (Ti : Entity_Id; Discrim_Values : Elist_Id; Stored_Discrim_Values : Boolean) return Node_Or_Entity_Id is Assoc : Elmt_Id; Disc : Entity_Id; Result : Node_Or_Entity_Id; Result_Entity : Node_Id; begin -- If inappropriate type, return Error, this happens only in -- cascaded error situations, and we want to avoid a blow up. if not Is_Composite_Type (Ti) or else Is_Array_Type (Ti) then return Error; end if; -- Look deeper if possible. Use Stored_Constraints only for -- untagged types. For tagged types use the given constraint. -- This asymmetry needs explanation??? if not Stored_Discrim_Values and then Present (Stored_Constraint (Ti)) and then not Is_Tagged_Type (Ti) then Result := Search_Derivation_Levels (Ti, Stored_Constraint (Ti), True); else declare Td : Entity_Id := Etype (Ti); begin -- If the parent type is private, the full view may include -- renamed discriminants, and it is those stored values that -- may be needed (the partial view never has more information -- than the full view). if Is_Private_Type (Td) and then Present (Full_View (Td)) then Td := Full_View (Td); end if; if Td = Ti then Result := Discriminant; else if Present (Stored_Constraint (Ti)) then Result := Search_Derivation_Levels (Td, Stored_Constraint (Ti), True); else Result := Search_Derivation_Levels (Td, Discrim_Values, Stored_Discrim_Values); end if; end if; end; end if; -- Extra underlying places to search, if not found above. For -- concurrent types, the relevant discriminant appears in the -- corresponding record. For a type derived from a private type -- without discriminant, the full view inherits the discriminants -- of the full view of the parent. if Result = Discriminant then if Is_Concurrent_Type (Ti) and then Present (Corresponding_Record_Type (Ti)) then Result := Search_Derivation_Levels ( Corresponding_Record_Type (Ti), Discrim_Values, Stored_Discrim_Values); elsif Is_Private_Type (Ti) and then not Has_Discriminants (Ti) and then Present (Full_View (Ti)) and then Etype (Full_View (Ti)) /= Ti then Result := Search_Derivation_Levels ( Full_View (Ti), Discrim_Values, Stored_Discrim_Values); end if; end if; -- If Result is not a (reference to a) discriminant, return it, -- otherwise set Result_Entity to the discriminant. if Nkind (Result) = N_Defining_Identifier then pragma Assert (Result = Discriminant); Result_Entity := Result; else if not Denotes_Discriminant (Result) then return Result; end if; Result_Entity := Entity (Result); end if; -- See if this level of derivation actually has discriminants because -- tagged derivations can add them, hence the lower levels need not -- have any. if not Has_Discriminants (Ti) then return Result; end if; -- Scan Ti's discriminants for Result_Entity, and return its -- corresponding value, if any. Result_Entity := Original_Record_Component (Result_Entity); Assoc := First_Elmt (Discrim_Values); if Stored_Discrim_Values then Disc := First_Stored_Discriminant (Ti); else Disc := First_Discriminant (Ti); end if; while Present (Disc) loop -- If no further associations return the discriminant, value will -- be found on the second pass. if No (Assoc) then return Result; end if; if Original_Record_Component (Disc) = Result_Entity then return Node (Assoc); end if; Next_Elmt (Assoc); if Stored_Discrim_Values then Next_Stored_Discriminant (Disc); else Next_Discriminant (Disc); end if; end loop; -- Could not find it return Result; end Search_Derivation_Levels; -- Local Variables Result : Node_Or_Entity_Id; -- Start of processing for Get_Discriminant_Value begin -- ??? This routine is a gigantic mess and will be deleted. For the -- time being just test for the trivial case before calling recurse. -- We are now celebrating the 20th anniversary of this comment! if Base_Type (Scope (Discriminant)) = Base_Type (Typ_For_Constraint) then declare D : Entity_Id; E : Elmt_Id; begin D := First_Discriminant (Typ_For_Constraint); E := First_Elmt (Constraint); while Present (D) loop if Chars (D) = Chars (Discriminant) then return Node (E); end if; Next_Discriminant (D); Next_Elmt (E); end loop; end; end if; Result := Search_Derivation_Levels (Typ_For_Constraint, Constraint, False); -- ??? hack to disappear when this routine is gone if Nkind (Result) = N_Defining_Identifier then declare D : Entity_Id; E : Elmt_Id; begin D := First_Discriminant (Typ_For_Constraint); E := First_Elmt (Constraint); while Present (D) loop if Root_Corresponding_Discriminant (D) = Discriminant then return Node (E); end if; Next_Discriminant (D); Next_Elmt (E); end loop; end; end if; pragma Assert (Nkind (Result) /= N_Defining_Identifier); return Result; end Get_Discriminant_Value; -------------------------- -- Has_Range_Constraint -- -------------------------- function Has_Range_Constraint (N : Node_Id) return Boolean is C : constant Node_Id := Constraint (N); begin if Nkind (C) = N_Range_Constraint then return True; elsif Nkind (C) = N_Digits_Constraint then return Is_Decimal_Fixed_Point_Type (Entity (Subtype_Mark (N))) or else Present (Range_Constraint (C)); elsif Nkind (C) = N_Delta_Constraint then return Present (Range_Constraint (C)); else return False; end if; end Has_Range_Constraint; ------------------------ -- Inherit_Components -- ------------------------ function Inherit_Components (N : Node_Id; Parent_Base : Entity_Id; Derived_Base : Entity_Id; Is_Tagged : Boolean; Inherit_Discr : Boolean; Discs : Elist_Id) return Elist_Id is Assoc_List : constant Elist_Id := New_Elmt_List; procedure Inherit_Component (Old_C : Entity_Id; Plain_Discrim : Boolean := False; Stored_Discrim : Boolean := False); -- Inherits component Old_C from Parent_Base to the Derived_Base. If -- Plain_Discrim is True, Old_C is a discriminant. If Stored_Discrim is -- True, Old_C is a stored discriminant. If they are both false then -- Old_C is a regular component. ----------------------- -- Inherit_Component -- ----------------------- procedure Inherit_Component (Old_C : Entity_Id; Plain_Discrim : Boolean := False; Stored_Discrim : Boolean := False) is procedure Set_Anonymous_Type (Id : Entity_Id); -- Id denotes the entity of an access discriminant or anonymous -- access component. Set the type of Id to either the same type of -- Old_C or create a new one depending on whether the parent and -- the child types are in the same scope. ------------------------ -- Set_Anonymous_Type -- ------------------------ procedure Set_Anonymous_Type (Id : Entity_Id) is Old_Typ : constant Entity_Id := Etype (Old_C); begin if Scope (Parent_Base) = Scope (Derived_Base) then Set_Etype (Id, Old_Typ); -- The parent and the derived type are in two different scopes. -- Reuse the type of the original discriminant / component by -- copying it in order to preserve all attributes. else declare Typ : constant Entity_Id := New_Copy (Old_Typ); begin Set_Etype (Id, Typ); -- Since we do not generate component declarations for -- inherited components, associate the itype with the -- derived type. Set_Associated_Node_For_Itype (Typ, Parent (Derived_Base)); Set_Scope (Typ, Derived_Base); end; end if; end Set_Anonymous_Type; -- Local variables and constants New_C : constant Entity_Id := New_Copy (Old_C); Corr_Discrim : Entity_Id; Discrim : Entity_Id; -- Start of processing for Inherit_Component begin pragma Assert (not Is_Tagged or not Stored_Discrim); Set_Parent (New_C, Parent (Old_C)); -- Regular discriminants and components must be inserted in the scope -- of the Derived_Base. Do it here. if not Stored_Discrim then Enter_Name (New_C); end if; -- For tagged types the Original_Record_Component must point to -- whatever this field was pointing to in the parent type. This has -- already been achieved by the call to New_Copy above. if not Is_Tagged then Set_Original_Record_Component (New_C, New_C); Set_Corresponding_Record_Component (New_C, Old_C); end if; -- Set the proper type of an access discriminant if Ekind (New_C) = E_Discriminant and then Ekind (Etype (New_C)) = E_Anonymous_Access_Type then Set_Anonymous_Type (New_C); end if; -- If we have inherited a component then see if its Etype contains -- references to Parent_Base discriminants. In this case, replace -- these references with the constraints given in Discs. We do not -- do this for the partial view of private types because this is -- not needed (only the components of the full view will be used -- for code generation) and cause problem. We also avoid this -- transformation in some error situations. if Ekind (New_C) = E_Component then -- Set the proper type of an anonymous access component if Ekind (Etype (New_C)) = E_Anonymous_Access_Type then Set_Anonymous_Type (New_C); elsif (Is_Private_Type (Derived_Base) and then not Is_Generic_Type (Derived_Base)) or else (Is_Empty_Elmt_List (Discs) and then not Expander_Active) then Set_Etype (New_C, Etype (Old_C)); else -- The current component introduces a circularity of the -- following kind: -- limited with Pack_2; -- package Pack_1 is -- type T_1 is tagged record -- Comp : access Pack_2.T_2; -- ... -- end record; -- end Pack_1; -- with Pack_1; -- package Pack_2 is -- type T_2 is new Pack_1.T_1 with ...; -- end Pack_2; Set_Etype (New_C, Constrain_Component_Type (Old_C, Derived_Base, N, Parent_Base, Discs)); end if; end if; -- In derived tagged types it is illegal to reference a non -- discriminant component in the parent type. To catch this, mark -- these components with an Ekind of E_Void. This will be reset in -- Record_Type_Definition after processing the record extension of -- the derived type. -- If the declaration is a private extension, there is no further -- record extension to process, and the components retain their -- current kind, because they are visible at this point. if Is_Tagged and then Ekind (New_C) = E_Component and then Nkind (N) /= N_Private_Extension_Declaration then Mutate_Ekind (New_C, E_Void); end if; if Plain_Discrim then Set_Corresponding_Discriminant (New_C, Old_C); Build_Discriminal (New_C); -- If we are explicitly inheriting a stored discriminant it will be -- completely hidden. elsif Stored_Discrim then Set_Corresponding_Discriminant (New_C, Empty); Set_Discriminal (New_C, Empty); Set_Is_Completely_Hidden (New_C); -- Set the Original_Record_Component of each discriminant in the -- derived base to point to the corresponding stored that we just -- created. Discrim := First_Discriminant (Derived_Base); while Present (Discrim) loop Corr_Discrim := Corresponding_Discriminant (Discrim); -- Corr_Discrim could be missing in an error situation if Present (Corr_Discrim) and then Original_Record_Component (Corr_Discrim) = Old_C then Set_Original_Record_Component (Discrim, New_C); Set_Corresponding_Record_Component (Discrim, Empty); end if; Next_Discriminant (Discrim); end loop; Append_Entity (New_C, Derived_Base); end if; if not Is_Tagged then Append_Elmt (Old_C, Assoc_List); Append_Elmt (New_C, Assoc_List); end if; end Inherit_Component; -- Variables local to Inherit_Component Loc : constant Source_Ptr := Sloc (N); Parent_Discrim : Entity_Id; Stored_Discrim : Entity_Id; D : Entity_Id; Component : Entity_Id; -- Start of processing for Inherit_Components begin if not Is_Tagged then Append_Elmt (Parent_Base, Assoc_List); Append_Elmt (Derived_Base, Assoc_List); end if; -- Inherit parent discriminants if needed if Inherit_Discr then Parent_Discrim := First_Discriminant (Parent_Base); while Present (Parent_Discrim) loop Inherit_Component (Parent_Discrim, Plain_Discrim => True); Next_Discriminant (Parent_Discrim); end loop; end if; -- Create explicit stored discrims for untagged types when necessary if not Has_Unknown_Discriminants (Derived_Base) and then Has_Discriminants (Parent_Base) and then not Is_Tagged and then (not Inherit_Discr or else First_Discriminant (Parent_Base) /= First_Stored_Discriminant (Parent_Base)) then Stored_Discrim := First_Stored_Discriminant (Parent_Base); while Present (Stored_Discrim) loop Inherit_Component (Stored_Discrim, Stored_Discrim => True); Next_Stored_Discriminant (Stored_Discrim); end loop; end if; -- See if we can apply the second transformation for derived types, as -- explained in point 6. in the comments above Build_Derived_Record_Type -- This is achieved by appending Derived_Base discriminants into Discs, -- which has the side effect of returning a non empty Discs list to the -- caller of Inherit_Components, which is what we want. This must be -- done for private derived types if there are explicit stored -- discriminants, to ensure that we can retrieve the values of the -- constraints provided in the ancestors. if Inherit_Discr and then Is_Empty_Elmt_List (Discs) and then Present (First_Discriminant (Derived_Base)) and then (not Is_Private_Type (Derived_Base) or else Is_Completely_Hidden (First_Stored_Discriminant (Derived_Base)) or else Is_Generic_Type (Derived_Base)) then D := First_Discriminant (Derived_Base); while Present (D) loop Append_Elmt (New_Occurrence_Of (D, Loc), Discs); Next_Discriminant (D); end loop; end if; -- Finally, inherit non-discriminant components unless they are not -- visible because defined or inherited from the full view of the -- parent. Don't inherit the _parent field of the parent type. Component := First_Entity (Parent_Base); while Present (Component) loop -- Ada 2005 (AI-251): Do not inherit components associated with -- secondary tags of the parent. if Ekind (Component) = E_Component and then Present (Related_Type (Component)) then null; elsif Ekind (Component) /= E_Component or else Chars (Component) = Name_uParent then null; -- If the derived type is within the parent type's declarative -- region, then the components can still be inherited even though -- they aren't visible at this point. This can occur for cases -- such as within public child units where the components must -- become visible upon entering the child unit's private part. elsif not Is_Visible_Component (Component) and then not In_Open_Scopes (Scope (Parent_Base)) then null; elsif Ekind (Derived_Base) in E_Private_Type | E_Limited_Private_Type then null; else Inherit_Component (Component); end if; Next_Entity (Component); end loop; -- For tagged derived types, inherited discriminants cannot be used in -- component declarations of the record extension part. To achieve this -- we mark the inherited discriminants as not visible. if Is_Tagged and then Inherit_Discr then D := First_Discriminant (Derived_Base); while Present (D) loop Set_Is_Immediately_Visible (D, False); Next_Discriminant (D); end loop; end if; return Assoc_List; end Inherit_Components; ---------------------- -- Is_EVF_Procedure -- ---------------------- function Is_EVF_Procedure (Subp : Entity_Id) return Boolean is Formal : Entity_Id; begin -- Examine the formals of an Extensions_Visible False procedure looking -- for a controlling OUT parameter. if Ekind (Subp) = E_Procedure and then Extensions_Visible_Status (Subp) = Extensions_Visible_False then Formal := First_Formal (Subp); while Present (Formal) loop if Ekind (Formal) = E_Out_Parameter and then Is_Controlling_Formal (Formal) then return True; end if; Next_Formal (Formal); end loop; end if; return False; end Is_EVF_Procedure; -------------------------- -- Is_Private_Primitive -- -------------------------- function Is_Private_Primitive (Prim : Entity_Id) return Boolean is Prim_Scope : constant Entity_Id := Scope (Prim); Priv_Entity : Entity_Id; begin if Is_Package_Or_Generic_Package (Prim_Scope) then Priv_Entity := First_Private_Entity (Prim_Scope); while Present (Priv_Entity) loop if Priv_Entity = Prim then return True; end if; Next_Entity (Priv_Entity); end loop; end if; return False; end Is_Private_Primitive; ------------------------------ -- Is_Valid_Constraint_Kind -- ------------------------------ function Is_Valid_Constraint_Kind (T_Kind : Type_Kind; Constraint_Kind : Node_Kind) return Boolean is begin case T_Kind is when Enumeration_Kind | Integer_Kind => return Constraint_Kind = N_Range_Constraint; when Decimal_Fixed_Point_Kind => return Constraint_Kind in N_Digits_Constraint | N_Range_Constraint; when Ordinary_Fixed_Point_Kind => return Constraint_Kind in N_Delta_Constraint | N_Range_Constraint; when Float_Kind => return Constraint_Kind in N_Digits_Constraint | N_Range_Constraint; when Access_Kind | Array_Kind | Class_Wide_Kind | Concurrent_Kind | Private_Kind | E_Incomplete_Type | E_Record_Subtype | E_Record_Type => return Constraint_Kind = N_Index_Or_Discriminant_Constraint; when others => return True; -- Error will be detected later end case; end Is_Valid_Constraint_Kind; -------------------------- -- Is_Visible_Component -- -------------------------- function Is_Visible_Component (C : Entity_Id; N : Node_Id := Empty) return Boolean is Original_Comp : Entity_Id := Empty; Original_Type : Entity_Id; Type_Scope : Entity_Id; function Is_Local_Type (Typ : Entity_Id) return Boolean; -- Check whether parent type of inherited component is declared locally, -- possibly within a nested package or instance. The current scope is -- the derived record itself. ------------------- -- Is_Local_Type -- ------------------- function Is_Local_Type (Typ : Entity_Id) return Boolean is begin return Scope_Within (Inner => Typ, Outer => Scope (Current_Scope)); end Is_Local_Type; -- Start of processing for Is_Visible_Component begin if Ekind (C) in E_Component | E_Discriminant then Original_Comp := Original_Record_Component (C); end if; if No (Original_Comp) then -- Premature usage, or previous error return False; else Original_Type := Scope (Original_Comp); Type_Scope := Scope (Base_Type (Scope (C))); end if; -- This test only concerns tagged types if not Is_Tagged_Type (Original_Type) then -- Check if this is a renamed discriminant (hidden either by the -- derived type or by some ancestor), unless we are analyzing code -- generated by the expander since it may reference such components -- (for example see the expansion of Deep_Adjust). if Ekind (C) = E_Discriminant and then Present (N) then return not Comes_From_Source (N) or else not Is_Completely_Hidden (C); else return True; end if; -- If it is _Parent or _Tag, there is no visibility issue elsif not Comes_From_Source (Original_Comp) then return True; -- Discriminants are visible unless the (private) type has unknown -- discriminants. If the discriminant reference is inserted for a -- discriminant check on a full view it is also visible. elsif Ekind (Original_Comp) = E_Discriminant and then (not Has_Unknown_Discriminants (Original_Type) or else (Present (N) and then Nkind (N) = N_Selected_Component and then Nkind (Prefix (N)) = N_Type_Conversion and then not Comes_From_Source (Prefix (N)))) then return True; -- If the component has been declared in an ancestor which is currently -- a private type, then it is not visible. The same applies if the -- component's containing type is not in an open scope and the original -- component's enclosing type is a visible full view of a private type -- (which can occur in cases where an attempt is being made to reference -- a component in a sibling package that is inherited from a visible -- component of a type in an ancestor package; the component in the -- sibling package should not be visible even though the component it -- inherited from is visible), but instance bodies are not subject to -- this second case since they have the Has_Private_View mechanism to -- ensure proper visibility. This does not apply however in the case -- where the scope of the type is a private child unit, or when the -- parent comes from a local package in which the ancestor is currently -- visible. The latter suppression of visibility is needed for cases -- that are tested in B730006. elsif Is_Private_Type (Original_Type) or else (not Is_Private_Descendant (Type_Scope) and then not In_Open_Scopes (Type_Scope) and then Has_Private_Declaration (Original_Type) and then not In_Instance_Body) then -- If the type derives from an entity in a formal package, there -- are no additional visible components. if Nkind (Original_Node (Unit_Declaration_Node (Type_Scope))) = N_Formal_Package_Declaration then return False; -- if we are not in the private part of the current package, there -- are no additional visible components. elsif Ekind (Scope (Current_Scope)) = E_Package and then not In_Private_Part (Scope (Current_Scope)) then return False; else return Is_Child_Unit (Cunit_Entity (Current_Sem_Unit)) and then In_Open_Scopes (Scope (Original_Type)) and then Is_Local_Type (Type_Scope); end if; -- There is another weird way in which a component may be invisible when -- the private and the full view are not derived from the same ancestor. -- Here is an example : -- type A1 is tagged record F1 : integer; end record; -- type A2 is new A1 with record F2 : integer; end record; -- type T is new A1 with private; -- private -- type T is new A2 with null record; -- In this case, the full view of T inherits F1 and F2 but the private -- view inherits only F1 else declare Ancestor : Entity_Id := Scope (C); begin loop if Ancestor = Original_Type then return True; -- The ancestor may have a partial view of the original type, -- but if the full view is in scope, as in a child body, the -- component is visible. elsif In_Private_Part (Scope (Original_Type)) and then Full_View (Ancestor) = Original_Type then return True; elsif Ancestor = Etype (Ancestor) then -- No further ancestors to examine return False; end if; Ancestor := Etype (Ancestor); end loop; end; end if; end Is_Visible_Component; -------------------------- -- Make_Class_Wide_Type -- -------------------------- procedure Make_Class_Wide_Type (T : Entity_Id) is CW_Type : Entity_Id; CW_Name : Name_Id; Next_E : Entity_Id; Prev_E : Entity_Id; begin if Present (Class_Wide_Type (T)) then -- The class-wide type is a partially decorated entity created for a -- unanalyzed tagged type referenced through a limited with clause. -- When the tagged type is analyzed, its class-wide type needs to be -- redecorated. Note that we reuse the entity created by Decorate_ -- Tagged_Type in order to preserve all links. if Materialize_Entity (Class_Wide_Type (T)) then CW_Type := Class_Wide_Type (T); Set_Materialize_Entity (CW_Type, False); -- The class wide type can have been defined by the partial view, in -- which case everything is already done. else return; end if; -- Default case, we need to create a new class-wide type else CW_Type := New_External_Entity (E_Void, Scope (T), Sloc (T), T, 'C', 0, 'T'); end if; -- Inherit root type characteristics CW_Name := Chars (CW_Type); Next_E := Next_Entity (CW_Type); Prev_E := Prev_Entity (CW_Type); Copy_Node (T, CW_Type); Set_Comes_From_Source (CW_Type, False); Set_Chars (CW_Type, CW_Name); Set_Parent (CW_Type, Parent (T)); Set_Prev_Entity (CW_Type, Prev_E); Set_Next_Entity (CW_Type, Next_E); -- Ensure we have a new freeze node for the class-wide type. The partial -- view may have freeze action of its own, requiring a proper freeze -- node, and the same freeze node cannot be shared between the two -- types. Set_Has_Delayed_Freeze (CW_Type); Set_Freeze_Node (CW_Type, Empty); -- Customize the class-wide type: It has no prim. op., it cannot be -- abstract, its Etype points back to the specific root type, and it -- cannot have any invariants. if Ekind (CW_Type) in Incomplete_Or_Private_Kind then Reinit_Field_To_Zero (CW_Type, F_Private_Dependents); elsif Ekind (CW_Type) in Concurrent_Kind then Reinit_Field_To_Zero (CW_Type, F_First_Private_Entity); Reinit_Field_To_Zero (CW_Type, F_Scope_Depth_Value); if Ekind (CW_Type) in Task_Kind then Reinit_Field_To_Zero (CW_Type, F_Is_Elaboration_Checks_OK_Id); Reinit_Field_To_Zero (CW_Type, F_Is_Elaboration_Warnings_OK_Id); end if; if Ekind (CW_Type) in E_Task_Type | E_Protected_Type then Reinit_Field_To_Zero (CW_Type, F_SPARK_Aux_Pragma_Inherited); end if; end if; Mutate_Ekind (CW_Type, E_Class_Wide_Type); Set_Is_Tagged_Type (CW_Type, True); Set_Direct_Primitive_Operations (CW_Type, New_Elmt_List); Set_Is_Abstract_Type (CW_Type, False); Set_Is_Constrained (CW_Type, False); Set_Is_First_Subtype (CW_Type, Is_First_Subtype (T)); Set_Default_SSO (CW_Type); Set_Has_Inheritable_Invariants (CW_Type, False); Set_Has_Inherited_Invariants (CW_Type, False); Set_Has_Own_Invariants (CW_Type, False); if Ekind (T) = E_Class_Wide_Subtype then Set_Etype (CW_Type, Etype (Base_Type (T))); else Set_Etype (CW_Type, T); end if; Set_No_Tagged_Streams_Pragma (CW_Type, No_Tagged_Streams); -- If this is the class_wide type of a constrained subtype, it does -- not have discriminants. Set_Has_Discriminants (CW_Type, Has_Discriminants (T) and then not Is_Constrained (T)); Set_Has_Unknown_Discriminants (CW_Type, True); Set_Class_Wide_Type (T, CW_Type); Set_Equivalent_Type (CW_Type, Empty); -- The class-wide type of a class-wide type is itself (RM 3.9(14)) Set_Class_Wide_Type (CW_Type, CW_Type); end Make_Class_Wide_Type; ---------------- -- Make_Index -- ---------------- procedure Make_Index (N : Node_Id; Related_Nod : Node_Id; Related_Id : Entity_Id := Empty; Suffix_Index : Pos := 1) is R : Node_Id; T : Entity_Id; Def_Id : Entity_Id := Empty; Found : Boolean := False; begin -- For a discrete range used in a constrained array definition and -- defined by a range, an implicit conversion to the predefined type -- INTEGER is assumed if each bound is either a numeric literal, a named -- number, or an attribute, and the type of both bounds (prior to the -- implicit conversion) is the type universal_integer. Otherwise, both -- bounds must be of the same discrete type, other than universal -- integer; this type must be determinable independently of the -- context, but using the fact that the type must be discrete and that -- both bounds must have the same type. -- Character literals also have a universal type in the absence of -- of additional context, and are resolved to Standard_Character. if Nkind (N) = N_Range then -- The index is given by a range constraint. The bounds are known -- to be of a consistent type. if not Is_Overloaded (N) then T := Etype (N); -- For universal bounds, choose the specific predefined type if T = Universal_Integer then T := Standard_Integer; elsif T = Any_Character then Ambiguous_Character (Low_Bound (N)); T := Standard_Character; end if; -- The node may be overloaded because some user-defined operators -- are available, but if a universal interpretation exists it is -- also the selected one. elsif Universal_Interpretation (N) = Universal_Integer then T := Standard_Integer; else T := Any_Type; declare Ind : Interp_Index; It : Interp; begin Get_First_Interp (N, Ind, It); while Present (It.Typ) loop if Is_Discrete_Type (It.Typ) then if Found and then not Covers (It.Typ, T) and then not Covers (T, It.Typ) then Error_Msg_N ("ambiguous bounds in discrete range", N); exit; else T := It.Typ; Found := True; end if; end if; Get_Next_Interp (Ind, It); end loop; if T = Any_Type then Error_Msg_N ("discrete type required for range", N); Set_Etype (N, Any_Type); return; elsif T = Universal_Integer then T := Standard_Integer; end if; end; end if; if not Is_Discrete_Type (T) then Error_Msg_N ("discrete type required for range", N); Set_Etype (N, Any_Type); return; end if; -- If the range bounds are "T'First .. T'Last" where T is a name of a -- discrete type, then use T as the type of the index. if Nkind (Low_Bound (N)) = N_Attribute_Reference and then Attribute_Name (Low_Bound (N)) = Name_First and then Is_Entity_Name (Prefix (Low_Bound (N))) and then Is_Discrete_Type (Entity (Prefix (Low_Bound (N)))) and then Nkind (High_Bound (N)) = N_Attribute_Reference and then Attribute_Name (High_Bound (N)) = Name_Last and then Is_Entity_Name (Prefix (High_Bound (N))) and then Entity (Prefix (High_Bound (N))) = Def_Id then Def_Id := Entity (Prefix (Low_Bound (N))); end if; R := N; Process_Range_Expr_In_Decl (R, T); elsif Nkind (N) = N_Subtype_Indication then -- The index is given by a subtype with a range constraint T := Base_Type (Entity (Subtype_Mark (N))); if not Is_Discrete_Type (T) then Error_Msg_N ("discrete type required for range", N); Set_Etype (N, Any_Type); return; end if; R := Range_Expression (Constraint (N)); Resolve (R, T); Process_Range_Expr_In_Decl (R, Entity (Subtype_Mark (N))); elsif Nkind (N) = N_Attribute_Reference then -- Catch beginner's error (use of attribute other than 'Range) if Attribute_Name (N) /= Name_Range then Error_Msg_N ("expect attribute ''Range", N); Set_Etype (N, Any_Type); return; end if; -- If the node denotes the range of a type mark, that is also the -- resulting type, and we do not need to create an Itype for it. if Is_Entity_Name (Prefix (N)) and then Comes_From_Source (N) and then Is_Discrete_Type (Entity (Prefix (N))) then Def_Id := Entity (Prefix (N)); end if; Analyze_And_Resolve (N); T := Etype (N); R := N; -- If none of the above, must be a subtype. We convert this to a -- range attribute reference because in the case of declared first -- named subtypes, the types in the range reference can be different -- from the type of the entity. A range attribute normalizes the -- reference and obtains the correct types for the bounds. -- This transformation is in the nature of an expansion, is only -- done if expansion is active. In particular, it is not done on -- formal generic types, because we need to retain the name of the -- original index for instantiation purposes. else if not Is_Entity_Name (N) or else not Is_Type (Entity (N)) then Error_Msg_N ("invalid subtype mark in discrete range", N); Set_Etype (N, Any_Integer); return; else -- The type mark may be that of an incomplete type. It is only -- now that we can get the full view, previous analysis does -- not look specifically for a type mark. Set_Entity (N, Get_Full_View (Entity (N))); Set_Etype (N, Entity (N)); Def_Id := Entity (N); if not Is_Discrete_Type (Def_Id) then Error_Msg_N ("discrete type required for index", N); Set_Etype (N, Any_Type); return; end if; end if; if Expander_Active then Rewrite (N, Make_Attribute_Reference (Sloc (N), Attribute_Name => Name_Range, Prefix => Relocate_Node (N))); -- The original was a subtype mark that does not freeze. This -- means that the rewritten version must not freeze either. Set_Must_Not_Freeze (N); Set_Must_Not_Freeze (Prefix (N)); Analyze_And_Resolve (N); T := Etype (N); R := N; -- If expander is inactive, type is legal, nothing else to construct else return; end if; end if; if not Is_Discrete_Type (T) then Error_Msg_N ("discrete type required for range", N); Set_Etype (N, Any_Type); return; elsif T = Any_Type then Set_Etype (N, Any_Type); return; end if; -- We will now create the appropriate Itype to describe the range, but -- first a check. If we originally had a subtype, then we just label -- the range with this subtype. Not only is there no need to construct -- a new subtype, but it is wrong to do so for two reasons: -- 1. A legality concern, if we have a subtype, it must not freeze, -- and the Itype would cause freezing incorrectly -- 2. An efficiency concern, if we created an Itype, it would not be -- recognized as the same type for the purposes of eliminating -- checks in some circumstances. -- We signal this case by setting the subtype entity in Def_Id if No (Def_Id) then Def_Id := Create_Itype (E_Void, Related_Nod, Related_Id, 'D', Suffix_Index); Set_Etype (Def_Id, Base_Type (T)); if Is_Signed_Integer_Type (T) then Mutate_Ekind (Def_Id, E_Signed_Integer_Subtype); elsif Is_Modular_Integer_Type (T) then Mutate_Ekind (Def_Id, E_Modular_Integer_Subtype); else Mutate_Ekind (Def_Id, E_Enumeration_Subtype); Set_Is_Character_Type (Def_Id, Is_Character_Type (T)); Set_First_Literal (Def_Id, First_Literal (T)); end if; Set_Size_Info (Def_Id, (T)); Set_RM_Size (Def_Id, RM_Size (T)); Set_First_Rep_Item (Def_Id, First_Rep_Item (T)); Set_Scalar_Range (Def_Id, R); Conditional_Delay (Def_Id, T); -- In the subtype indication case inherit properties of the parent if Nkind (N) = N_Subtype_Indication then -- It is enough to inherit predicate flags and not the predicate -- functions, because predicates on an index type are illegal -- anyway and the flags are enough to detect them. Inherit_Predicate_Flags (Def_Id, Entity (Subtype_Mark (N))); -- If the immediate parent of the new subtype is nonstatic, then -- the subtype we create is nonstatic as well, even if its bounds -- are static. if not Is_OK_Static_Subtype (Entity (Subtype_Mark (N))) then Set_Is_Non_Static_Subtype (Def_Id); end if; end if; Set_Parent (Def_Id, N); end if; -- Final step is to label the index with this constructed type Set_Etype (N, Def_Id); end Make_Index; ------------------------------ -- Modular_Type_Declaration -- ------------------------------ procedure Modular_Type_Declaration (T : Entity_Id; Def : Node_Id) is Mod_Expr : constant Node_Id := Expression (Def); M_Val : Uint; procedure Set_Modular_Size (Bits : Int); -- Sets RM_Size to Bits, and Esize to normal word size above this ---------------------- -- Set_Modular_Size -- ---------------------- procedure Set_Modular_Size (Bits : Int) is Siz : Int; begin Set_RM_Size (T, UI_From_Int (Bits)); if Bits < System_Max_Binary_Modulus_Power then Siz := 8; while Siz < 128 loop exit when Bits <= Siz; Siz := Siz * 2; end loop; Set_Esize (T, UI_From_Int (Siz)); else Set_Esize (T, UI_From_Int (System_Max_Binary_Modulus_Power)); end if; if not Non_Binary_Modulus (T) and then Esize (T) = RM_Size (T) then Set_Is_Known_Valid (T); end if; end Set_Modular_Size; -- Start of processing for Modular_Type_Declaration begin -- If the mod expression is (exactly) 2 * literal, where literal is -- 128 or less, then almost certainly the * was meant to be **. Warn. if Warn_On_Suspicious_Modulus_Value and then Nkind (Mod_Expr) = N_Op_Multiply and then Nkind (Left_Opnd (Mod_Expr)) = N_Integer_Literal and then Intval (Left_Opnd (Mod_Expr)) = Uint_2 and then Nkind (Right_Opnd (Mod_Expr)) = N_Integer_Literal and then Intval (Right_Opnd (Mod_Expr)) <= Uint_128 then Error_Msg_N ("suspicious MOD value, was '*'* intended'??.m?", Mod_Expr); end if; -- Proceed with analysis of mod expression Analyze_And_Resolve (Mod_Expr, Any_Integer); if Ekind (T) in Incomplete_Or_Private_Kind then Reinit_Field_To_Zero (T, F_Stored_Constraint); end if; Set_Etype (T, T); Mutate_Ekind (T, E_Modular_Integer_Type); Reinit_Alignment (T); Set_Is_Constrained (T); if not Is_OK_Static_Expression (Mod_Expr) then Flag_Non_Static_Expr ("non-static expression used for modular type bound!", Mod_Expr); M_Val := 2 ** System_Max_Binary_Modulus_Power; else M_Val := Expr_Value (Mod_Expr); end if; if M_Val < 1 then Error_Msg_N ("modulus value must be positive", Mod_Expr); M_Val := 2 ** System_Max_Binary_Modulus_Power; end if; if M_Val > 2 ** Standard_Long_Integer_Size then Check_Restriction (No_Long_Long_Integers, Mod_Expr); end if; Set_Modulus (T, M_Val); -- Create bounds for the modular type based on the modulus given in -- the type declaration and then analyze and resolve those bounds. Set_Scalar_Range (T, Make_Range (Sloc (Mod_Expr), Low_Bound => Make_Integer_Literal (Sloc (Mod_Expr), 0), High_Bound => Make_Integer_Literal (Sloc (Mod_Expr), M_Val - 1))); -- Properly analyze the literals for the range. We do this manually -- because we can't go calling Resolve, since we are resolving these -- bounds with the type, and this type is certainly not complete yet. Set_Etype (Low_Bound (Scalar_Range (T)), T); Set_Etype (High_Bound (Scalar_Range (T)), T); Set_Is_Static_Expression (Low_Bound (Scalar_Range (T))); Set_Is_Static_Expression (High_Bound (Scalar_Range (T))); -- Loop through powers of two to find number of bits required for Bits in Int range 0 .. System_Max_Binary_Modulus_Power loop -- Binary case if M_Val = 2 ** Bits then Set_Modular_Size (Bits); return; -- Nonbinary case elsif M_Val < 2 ** Bits then Set_Non_Binary_Modulus (T); if Bits > System_Max_Nonbinary_Modulus_Power then Error_Msg_Uint_1 := UI_From_Int (System_Max_Nonbinary_Modulus_Power); Error_Msg_F ("nonbinary modulus exceeds limit (2 '*'*^ - 1)", Mod_Expr); Set_Modular_Size (System_Max_Binary_Modulus_Power); return; else -- In the nonbinary case, set size as per RM 13.3(55) Set_Modular_Size (Bits); return; end if; end if; end loop; -- If we fall through, then the size exceed System.Max_Binary_Modulus -- so we just signal an error and set the maximum size. Error_Msg_Uint_1 := UI_From_Int (System_Max_Binary_Modulus_Power); Error_Msg_F ("modulus exceeds limit (2 '*'*^)", Mod_Expr); Set_Modular_Size (System_Max_Binary_Modulus_Power); Reinit_Alignment (T); end Modular_Type_Declaration; -------------------------- -- New_Concatenation_Op -- -------------------------- procedure New_Concatenation_Op (Typ : Entity_Id) is Loc : constant Source_Ptr := Sloc (Typ); Op : Entity_Id; function Make_Op_Formal (Typ, Op : Entity_Id) return Entity_Id; -- Create abbreviated declaration for the formal of a predefined -- Operator 'Op' of type 'Typ' -------------------- -- Make_Op_Formal -- -------------------- function Make_Op_Formal (Typ, Op : Entity_Id) return Entity_Id is Formal : Entity_Id; begin Formal := New_Internal_Entity (E_In_Parameter, Op, Loc, 'P'); Set_Etype (Formal, Typ); Set_Mechanism (Formal, Default_Mechanism); return Formal; end Make_Op_Formal; -- Start of processing for New_Concatenation_Op begin Op := Make_Defining_Operator_Symbol (Loc, Name_Op_Concat); Mutate_Ekind (Op, E_Operator); Set_Scope (Op, Current_Scope); Set_Etype (Op, Typ); Set_Homonym (Op, Get_Name_Entity_Id (Name_Op_Concat)); Set_Is_Immediately_Visible (Op); Set_Is_Intrinsic_Subprogram (Op); Set_Has_Completion (Op); Append_Entity (Op, Current_Scope); Set_Name_Entity_Id (Name_Op_Concat, Op); Append_Entity (Make_Op_Formal (Typ, Op), Op); Append_Entity (Make_Op_Formal (Typ, Op), Op); end New_Concatenation_Op; ------------------------- -- OK_For_Limited_Init -- ------------------------- -- ???Check all calls of this, and compare the conditions under which it's -- called. function OK_For_Limited_Init (Typ : Entity_Id; Exp : Node_Id) return Boolean is begin return Is_CPP_Constructor_Call (Exp) or else (Ada_Version >= Ada_2005 and then not Debug_Flag_Dot_L and then OK_For_Limited_Init_In_05 (Typ, Exp)); end OK_For_Limited_Init; ------------------------------- -- OK_For_Limited_Init_In_05 -- ------------------------------- function OK_For_Limited_Init_In_05 (Typ : Entity_Id; Exp : Node_Id) return Boolean is begin -- An object of a limited interface type can be initialized with any -- expression of a nonlimited descendant type. However this does not -- apply if this is a view conversion of some other expression. This -- is checked below. if Is_Class_Wide_Type (Typ) and then Is_Limited_Interface (Typ) and then not Is_Limited_Type (Etype (Exp)) and then Nkind (Exp) /= N_Type_Conversion then return True; end if; -- Ada 2005 (AI-287, AI-318): Relax the strictness of the front end in -- case of limited aggregates (including extension aggregates), and -- function calls. The function call may have been given in prefixed -- notation, in which case the original node is an indexed component. -- If the function is parameterless, the original node was an explicit -- dereference. The function may also be parameterless, in which case -- the source node is just an identifier. -- A branch of a conditional expression may have been removed if the -- condition is statically known. This happens during expansion, and -- thus will not happen if previous errors were encountered. The check -- will have been performed on the chosen branch, which replaces the -- original conditional expression. if No (Exp) then return True; end if; case Nkind (Original_Node (Exp)) is when N_Aggregate | N_Extension_Aggregate | N_Function_Call | N_Op => return True; when N_Identifier => return Present (Entity (Original_Node (Exp))) and then Ekind (Entity (Original_Node (Exp))) = E_Function; when N_Qualified_Expression => return OK_For_Limited_Init_In_05 (Typ, Expression (Original_Node (Exp))); -- Ada 2005 (AI-251): If a class-wide interface object is initialized -- with a function call, the expander has rewritten the call into an -- N_Type_Conversion node to force displacement of the pointer to -- reference the component containing the secondary dispatch table. -- Otherwise a type conversion is not a legal context. -- A return statement for a build-in-place function returning a -- synchronized type also introduces an unchecked conversion. when N_Type_Conversion | N_Unchecked_Type_Conversion => return not Comes_From_Source (Exp) and then -- If the conversion has been rewritten, check Original_Node ((Original_Node (Exp) /= Exp and then OK_For_Limited_Init_In_05 (Typ, Original_Node (Exp))) -- Otherwise, check the expression of the compiler-generated -- conversion (which is a conversion that we want to ignore -- for purposes of the limited-initialization restrictions). or else (Original_Node (Exp) = Exp and then OK_For_Limited_Init_In_05 (Typ, Expression (Exp)))); when N_Explicit_Dereference | N_Indexed_Component | N_Selected_Component => return Nkind (Exp) = N_Function_Call; -- A use of 'Input is a function call, hence allowed. Normally the -- attribute will be changed to a call, but the attribute by itself -- can occur with -gnatc. when N_Attribute_Reference => return Attribute_Name (Original_Node (Exp)) = Name_Input; -- "return raise ..." is OK when N_Raise_Expression => return True; -- For a case expression, all dependent expressions must be legal when N_Case_Expression => declare Alt : Node_Id; begin Alt := First (Alternatives (Original_Node (Exp))); while Present (Alt) loop if not OK_For_Limited_Init_In_05 (Typ, Expression (Alt)) then return False; end if; Next (Alt); end loop; return True; end; -- For an if expression, all dependent expressions must be legal when N_If_Expression => declare Then_Expr : constant Node_Id := Next (First (Expressions (Original_Node (Exp)))); Else_Expr : constant Node_Id := Next (Then_Expr); begin return OK_For_Limited_Init_In_05 (Typ, Then_Expr) and then OK_For_Limited_Init_In_05 (Typ, Else_Expr); end; when others => return False; end case; end OK_For_Limited_Init_In_05; ------------------------------------------- -- Ordinary_Fixed_Point_Type_Declaration -- ------------------------------------------- procedure Ordinary_Fixed_Point_Type_Declaration (T : Entity_Id; Def : Node_Id) is Loc : constant Source_Ptr := Sloc (Def); Delta_Expr : constant Node_Id := Delta_Expression (Def); RRS : constant Node_Id := Real_Range_Specification (Def); Implicit_Base : Entity_Id; Delta_Val : Ureal; Small_Val : Ureal; Low_Val : Ureal; High_Val : Ureal; begin Check_Restriction (No_Fixed_Point, Def); -- Create implicit base type Implicit_Base := Create_Itype (E_Ordinary_Fixed_Point_Type, Parent (Def), T, 'B'); Set_Etype (Implicit_Base, Implicit_Base); -- Analyze and process delta expression Analyze_And_Resolve (Delta_Expr, Any_Real); Check_Delta_Expression (Delta_Expr); Delta_Val := Expr_Value_R (Delta_Expr); Set_Delta_Value (Implicit_Base, Delta_Val); -- Compute default small from given delta, which is the largest power -- of two that does not exceed the given delta value. declare Tmp : Ureal; Scale : Int; begin Tmp := Ureal_1; Scale := 0; if Delta_Val < Ureal_1 then while Delta_Val < Tmp loop Tmp := Tmp / Ureal_2; Scale := Scale + 1; end loop; else loop Tmp := Tmp * Ureal_2; exit when Tmp > Delta_Val; Scale := Scale - 1; end loop; end if; Small_Val := UR_From_Components (Uint_1, UI_From_Int (Scale), 2); end; Set_Small_Value (Implicit_Base, Small_Val); -- If no range was given, set a dummy range if RRS <= Empty_Or_Error then Low_Val := -Small_Val; High_Val := Small_Val; -- Otherwise analyze and process given range else declare Low : constant Node_Id := Low_Bound (RRS); High : constant Node_Id := High_Bound (RRS); begin Analyze_And_Resolve (Low, Any_Real); Analyze_And_Resolve (High, Any_Real); Check_Real_Bound (Low); Check_Real_Bound (High); -- Obtain and set the range Low_Val := Expr_Value_R (Low); High_Val := Expr_Value_R (High); if Low_Val > High_Val then Error_Msg_NE ("??fixed point type& has null range", Def, T); end if; end; end if; -- The range for both the implicit base and the declared first subtype -- cannot be set yet, so we use the special routine Set_Fixed_Range to -- set a temporary range in place. Note that the bounds of the base -- type will be widened to be symmetrical and to fill the available -- bits when the type is frozen. -- We could do this with all discrete types, and probably should, but -- we absolutely have to do it for fixed-point, since the end-points -- of the range and the size are determined by the small value, which -- could be reset before the freeze point. Set_Fixed_Range (Implicit_Base, Loc, Low_Val, High_Val); Set_Fixed_Range (T, Loc, Low_Val, High_Val); -- Complete definition of first subtype. The inheritance of the rep item -- chain ensures that SPARK-related pragmas are not clobbered when the -- ordinary fixed point type acts as a full view of a private type. Mutate_Ekind (T, E_Ordinary_Fixed_Point_Subtype); Set_Etype (T, Implicit_Base); Reinit_Size_Align (T); Inherit_Rep_Item_Chain (T, Implicit_Base); Set_Small_Value (T, Small_Val); Set_Delta_Value (T, Delta_Val); Set_Is_Constrained (T); end Ordinary_Fixed_Point_Type_Declaration; ---------------------------------- -- Preanalyze_Assert_Expression -- ---------------------------------- procedure Preanalyze_Assert_Expression (N : Node_Id; T : Entity_Id) is begin In_Assertion_Expr := In_Assertion_Expr + 1; Preanalyze_Spec_Expression (N, T); In_Assertion_Expr := In_Assertion_Expr - 1; end Preanalyze_Assert_Expression; ----------------------------------- -- Preanalyze_Default_Expression -- ----------------------------------- procedure Preanalyze_Default_Expression (N : Node_Id; T : Entity_Id) is Save_In_Default_Expr : constant Boolean := In_Default_Expr; Save_In_Spec_Expression : constant Boolean := In_Spec_Expression; begin In_Default_Expr := True; In_Spec_Expression := True; Preanalyze_With_Freezing_And_Resolve (N, T); In_Default_Expr := Save_In_Default_Expr; In_Spec_Expression := Save_In_Spec_Expression; end Preanalyze_Default_Expression; -------------------------------- -- Preanalyze_Spec_Expression -- -------------------------------- procedure Preanalyze_Spec_Expression (N : Node_Id; T : Entity_Id) is Save_In_Spec_Expression : constant Boolean := In_Spec_Expression; begin In_Spec_Expression := True; Preanalyze_And_Resolve (N, T); In_Spec_Expression := Save_In_Spec_Expression; end Preanalyze_Spec_Expression; ---------------------------------------- -- Prepare_Private_Subtype_Completion -- ---------------------------------------- procedure Prepare_Private_Subtype_Completion (Id : Entity_Id; Related_Nod : Node_Id) is Id_B : constant Entity_Id := Base_Type (Id); Full_B : constant Entity_Id := Full_View (Id_B); Full : Entity_Id; begin if Present (Full_B) then -- The Base_Type is already completed, we can complete the subtype -- now. We have to create a new entity with the same name, Thus we -- can't use Create_Itype. Full := Make_Defining_Identifier (Sloc (Id), Chars (Id)); Set_Is_Itype (Full); Set_Associated_Node_For_Itype (Full, Related_Nod); Complete_Private_Subtype (Id, Full, Full_B, Related_Nod); Set_Full_View (Id, Full); end if; -- The parent subtype may be private, but the base might not, in some -- nested instances. In that case, the subtype does not need to be -- exchanged. It would still be nice to make private subtypes and their -- bases consistent at all times ??? if Is_Private_Type (Id_B) then Append_Elmt (Id, Private_Dependents (Id_B)); end if; end Prepare_Private_Subtype_Completion; --------------------------- -- Process_Discriminants -- --------------------------- procedure Process_Discriminants (N : Node_Id; Prev : Entity_Id := Empty) is Elist : constant Elist_Id := New_Elmt_List; Id : Node_Id; Discr : Node_Id; Discr_Number : Uint; Discr_Type : Entity_Id; Default_Present : Boolean := False; Default_Not_Present : Boolean := False; begin -- A composite type other than an array type can have discriminants. -- On entry, the current scope is the composite type. -- The discriminants are initially entered into the scope of the type -- via Enter_Name with the default Ekind of E_Void to prevent premature -- use, as explained at the end of this procedure. Discr := First (Discriminant_Specifications (N)); while Present (Discr) loop Enter_Name (Defining_Identifier (Discr)); -- For navigation purposes we add a reference to the discriminant -- in the entity for the type. If the current declaration is a -- completion, place references on the partial view. Otherwise the -- type is the current scope. if Present (Prev) then -- The references go on the partial view, if present. If the -- partial view has discriminants, the references have been -- generated already. if not Has_Discriminants (Prev) then Generate_Reference (Prev, Defining_Identifier (Discr), 'd'); end if; else Generate_Reference (Current_Scope, Defining_Identifier (Discr), 'd'); end if; if Nkind (Discriminant_Type (Discr)) = N_Access_Definition then Check_Anonymous_Access_Component (Typ_Decl => N, Typ => Defining_Identifier (N), Prev => Prev, Comp_Def => Discr, Access_Def => Discriminant_Type (Discr)); -- if Check_Anonymous_Access_Component replaced Discr then -- its Original_Node points to the old Discr and the access type -- for Discr_Type has already been created. if Original_Node (Discr) /= Discr then Discr_Type := Etype (Discriminant_Type (Discr)); else Discr_Type := Access_Definition (Discr, Discriminant_Type (Discr)); -- Ada 2005 (AI-254) if Present (Access_To_Subprogram_Definition (Discriminant_Type (Discr))) and then Protected_Present (Access_To_Subprogram_Definition (Discriminant_Type (Discr))) then Discr_Type := Replace_Anonymous_Access_To_Protected_Subprogram (Discr); end if; end if; else Find_Type (Discriminant_Type (Discr)); Discr_Type := Etype (Discriminant_Type (Discr)); if Error_Posted (Discriminant_Type (Discr)) then Discr_Type := Any_Type; end if; end if; -- Handling of discriminants that are access types if Is_Access_Type (Discr_Type) then -- Ada 2005 (AI-230): Access discriminant allowed in non- -- limited record types if Ada_Version < Ada_2005 then Check_Access_Discriminant_Requires_Limited (Discr, Discriminant_Type (Discr)); end if; if Ada_Version = Ada_83 and then Comes_From_Source (Discr) then Error_Msg_N ("(Ada 83) access discriminant not allowed", Discr); end if; -- If not access type, must be a discrete type elsif not Is_Discrete_Type (Discr_Type) then Error_Msg_N ("discriminants must have a discrete or access type", Discriminant_Type (Discr)); end if; Set_Etype (Defining_Identifier (Discr), Discr_Type); -- If a discriminant specification includes the assignment compound -- delimiter followed by an expression, the expression is the default -- expression of the discriminant; the default expression must be of -- the type of the discriminant. (RM 3.7.1) Since this expression is -- a default expression, we do the special preanalysis, since this -- expression does not freeze (see section "Handling of Default and -- Per-Object Expressions" in spec of package Sem). if Present (Expression (Discr)) then Preanalyze_Default_Expression (Expression (Discr), Discr_Type); -- Legaity checks if Nkind (N) = N_Formal_Type_Declaration then Error_Msg_N ("discriminant defaults not allowed for formal type", Expression (Discr)); -- Flag an error for a tagged type with defaulted discriminants, -- excluding limited tagged types when compiling for Ada 2012 -- (see AI05-0214). elsif Is_Tagged_Type (Current_Scope) and then (not Is_Limited_Type (Current_Scope) or else Ada_Version < Ada_2012) and then Comes_From_Source (N) then -- Note: see similar test in Check_Or_Process_Discriminants, to -- handle the (illegal) case of the completion of an untagged -- view with discriminants with defaults by a tagged full view. -- We skip the check if Discr does not come from source, to -- account for the case of an untagged derived type providing -- defaults for a renamed discriminant from a private untagged -- ancestor with a tagged full view (ACATS B460006). if Ada_Version >= Ada_2012 then Error_Msg_N ("discriminants of nonlimited tagged type cannot have" & " defaults", Expression (Discr)); else Error_Msg_N ("discriminants of tagged type cannot have defaults", Expression (Discr)); end if; else Default_Present := True; Append_Elmt (Expression (Discr), Elist); -- Tag the defining identifiers for the discriminants with -- their corresponding default expressions from the tree. Set_Discriminant_Default_Value (Defining_Identifier (Discr), Expression (Discr)); end if; -- In gnatc or GNATprove mode, make sure set Do_Range_Check flag -- gets set unless we can be sure that no range check is required. if not Expander_Active and then not Is_In_Range (Expression (Discr), Discr_Type, Assume_Valid => True) then Set_Do_Range_Check (Expression (Discr)); end if; -- No default discriminant value given else Default_Not_Present := True; end if; -- Ada 2005 (AI-231): Create an Itype that is a duplicate of -- Discr_Type but with the null-exclusion attribute if Ada_Version >= Ada_2005 then -- Ada 2005 (AI-231): Static checks if Can_Never_Be_Null (Discr_Type) then Null_Exclusion_Static_Checks (Discr); elsif Is_Access_Type (Discr_Type) and then Null_Exclusion_Present (Discr) -- No need to check itypes because in their case this check -- was done at their point of creation and then not Is_Itype (Discr_Type) then if Can_Never_Be_Null (Discr_Type) then Error_Msg_NE ("`NOT NULL` not allowed (& already excludes null)", Discr, Discr_Type); end if; Set_Etype (Defining_Identifier (Discr), Create_Null_Excluding_Itype (T => Discr_Type, Related_Nod => Discr)); -- Check for improper null exclusion if the type is otherwise -- legal for a discriminant. elsif Null_Exclusion_Present (Discr) and then Is_Discrete_Type (Discr_Type) then Error_Msg_N ("null exclusion can only apply to an access type", Discr); end if; -- Ada 2005 (AI-402): access discriminants of nonlimited types -- can't have defaults. Synchronized types, or types that are -- explicitly limited are fine, but special tests apply to derived -- types in generics: in a generic body we have to assume the -- worst, and therefore defaults are not allowed if the parent is -- a generic formal private type (see ACATS B370001). if Is_Access_Type (Discr_Type) and then Default_Present then if Ekind (Discr_Type) /= E_Anonymous_Access_Type or else Is_Limited_Record (Current_Scope) or else Is_Concurrent_Type (Current_Scope) or else Is_Concurrent_Record_Type (Current_Scope) or else Ekind (Current_Scope) = E_Limited_Private_Type then if not Is_Derived_Type (Current_Scope) or else not Is_Generic_Type (Etype (Current_Scope)) or else not In_Package_Body (Scope (Etype (Current_Scope))) or else Limited_Present (Type_Definition (Parent (Current_Scope))) then null; else Error_Msg_N ("access discriminants of nonlimited types cannot " & "have defaults", Expression (Discr)); end if; elsif Present (Expression (Discr)) then Error_Msg_N ("(Ada 2005) access discriminants of nonlimited types " & "cannot have defaults", Expression (Discr)); end if; end if; end if; -- A discriminant cannot be effectively volatile (SPARK RM 7.1.3(4)). -- This check is relevant only when SPARK_Mode is on as it is not a -- standard Ada legality rule. The only way for a discriminant to be -- effectively volatile is to have an effectively volatile type, so -- we check this directly, because the Ekind of Discr might not be -- set yet (to help preventing cascaded errors on derived types). if SPARK_Mode = On and then Is_Effectively_Volatile (Discr_Type) then Error_Msg_N ("discriminant cannot be volatile", Discr); end if; Next (Discr); end loop; -- An element list consisting of the default expressions of the -- discriminants is constructed in the above loop and used to set -- the Discriminant_Constraint attribute for the type. If an object -- is declared of this (record or task) type without any explicit -- discriminant constraint given, this element list will form the -- actual parameters for the corresponding initialization procedure -- for the type. Set_Discriminant_Constraint (Current_Scope, Elist); Set_Stored_Constraint (Current_Scope, No_Elist); -- Default expressions must be provided either for all or for none -- of the discriminants of a discriminant part. (RM 3.7.1) if Default_Present and then Default_Not_Present then Error_Msg_N ("incomplete specification of defaults for discriminants", N); end if; -- The use of the name of a discriminant is not allowed in default -- expressions of a discriminant part if the specification of the -- discriminant is itself given in the discriminant part. (RM 3.7.1) -- To detect this, the discriminant names are entered initially with an -- Ekind of E_Void (which is the default Ekind given by Enter_Name). Any -- attempt to use a void entity (for example in an expression that is -- type-checked) produces the error message: premature usage. Now after -- completing the semantic analysis of the discriminant part, we can set -- the Ekind of all the discriminants appropriately. Discr := First (Discriminant_Specifications (N)); Discr_Number := Uint_1; while Present (Discr) loop Id := Defining_Identifier (Discr); if Ekind (Id) = E_In_Parameter then Reinit_Field_To_Zero (Id, F_Discriminal_Link); end if; Mutate_Ekind (Id, E_Discriminant); Reinit_Component_Location (Id); Reinit_Esize (Id); Set_Discriminant_Number (Id, Discr_Number); -- Make sure this is always set, even in illegal programs Set_Corresponding_Discriminant (Id, Empty); -- Initialize the Original_Record_Component to the entity itself. -- Inherit_Components will propagate the right value to -- discriminants in derived record types. Set_Original_Record_Component (Id, Id); -- Create the discriminal for the discriminant Build_Discriminal (Id); Next (Discr); Discr_Number := Discr_Number + 1; end loop; Set_Has_Discriminants (Current_Scope); end Process_Discriminants; ----------------------- -- Process_Full_View -- ----------------------- -- WARNING: This routine manages Ghost regions. Return statements must be -- replaced by gotos which jump to the end of the routine and restore the -- Ghost mode. procedure Process_Full_View (N : Node_Id; Full_T, Priv_T : Entity_Id) is procedure Collect_Implemented_Interfaces (Typ : Entity_Id; Ifaces : Elist_Id); -- Ada 2005: Gather all the interfaces that Typ directly or -- inherently implements. Duplicate entries are not added to -- the list Ifaces. ------------------------------------ -- Collect_Implemented_Interfaces -- ------------------------------------ procedure Collect_Implemented_Interfaces (Typ : Entity_Id; Ifaces : Elist_Id) is Iface : Entity_Id; Iface_Elmt : Elmt_Id; begin -- Abstract interfaces are only associated with tagged record types if not Is_Tagged_Type (Typ) or else not Is_Record_Type (Typ) then return; end if; -- Recursively climb to the ancestors if Etype (Typ) /= Typ -- Protect the frontend against wrong cyclic declarations like: -- type B is new A with private; -- type C is new A with private; -- private -- type B is new C with null record; -- type C is new B with null record; and then Etype (Typ) /= Priv_T and then Etype (Typ) /= Full_T then -- Keep separate the management of private type declarations if Ekind (Typ) = E_Record_Type_With_Private then -- Handle the following illegal usage: -- type Private_Type is tagged private; -- private -- type Private_Type is new Type_Implementing_Iface; if Present (Full_View (Typ)) and then Etype (Typ) /= Full_View (Typ) then if Is_Interface (Etype (Typ)) then Append_Unique_Elmt (Etype (Typ), Ifaces); end if; Collect_Implemented_Interfaces (Etype (Typ), Ifaces); end if; -- Non-private types else if Is_Interface (Etype (Typ)) then Append_Unique_Elmt (Etype (Typ), Ifaces); end if; Collect_Implemented_Interfaces (Etype (Typ), Ifaces); end if; end if; -- Handle entities in the list of abstract interfaces if Present (Interfaces (Typ)) then Iface_Elmt := First_Elmt (Interfaces (Typ)); while Present (Iface_Elmt) loop Iface := Node (Iface_Elmt); pragma Assert (Is_Interface (Iface)); if not Contain_Interface (Iface, Ifaces) then Append_Elmt (Iface, Ifaces); Collect_Implemented_Interfaces (Iface, Ifaces); end if; Next_Elmt (Iface_Elmt); end loop; end if; end Collect_Implemented_Interfaces; -- Local variables Saved_GM : constant Ghost_Mode_Type := Ghost_Mode; Saved_IGR : constant Node_Id := Ignored_Ghost_Region; -- Save the Ghost-related attributes to restore on exit Full_Indic : Node_Id; Full_Parent : Entity_Id; Priv_Parent : Entity_Id; -- Start of processing for Process_Full_View begin Mark_And_Set_Ghost_Completion (N, Priv_T); -- First some sanity checks that must be done after semantic -- decoration of the full view and thus cannot be placed with other -- similar checks in Find_Type_Name if not Is_Limited_Type (Priv_T) and then (Is_Limited_Type (Full_T) or else Is_Limited_Composite (Full_T)) then if In_Instance then null; else Error_Msg_N ("completion of nonlimited type cannot be limited", Full_T); Explain_Limited_Type (Full_T, Full_T); end if; elsif Is_Abstract_Type (Full_T) and then not Is_Abstract_Type (Priv_T) then Error_Msg_N ("completion of nonabstract type cannot be abstract", Full_T); elsif Is_Tagged_Type (Priv_T) and then Is_Limited_Type (Priv_T) and then not Is_Limited_Type (Full_T) then -- If pragma CPP_Class was applied to the private declaration -- propagate the limitedness to the full-view if Is_CPP_Class (Priv_T) then Set_Is_Limited_Record (Full_T); -- GNAT allow its own definition of Limited_Controlled to disobey -- this rule in order in ease the implementation. This test is safe -- because Root_Controlled is defined in a child of System that -- normal programs are not supposed to use. elsif Is_RTE (Etype (Full_T), RE_Root_Controlled) then Set_Is_Limited_Composite (Full_T); else Error_Msg_N ("completion of limited tagged type must be limited", Full_T); end if; elsif Is_Generic_Type (Priv_T) then Error_Msg_N ("generic type cannot have a completion", Full_T); end if; -- Check that ancestor interfaces of private and full views are -- consistent. We omit this check for synchronized types because -- they are performed on the corresponding record type when frozen. if Ada_Version >= Ada_2005 and then Is_Tagged_Type (Priv_T) and then Is_Tagged_Type (Full_T) and then not Is_Concurrent_Type (Full_T) then declare Iface : Entity_Id; Priv_T_Ifaces : constant Elist_Id := New_Elmt_List; Full_T_Ifaces : constant Elist_Id := New_Elmt_List; begin Collect_Implemented_Interfaces (Priv_T, Priv_T_Ifaces); Collect_Implemented_Interfaces (Full_T, Full_T_Ifaces); -- Ada 2005 (AI-251): The partial view shall be a descendant of -- an interface type if and only if the full type is descendant -- of the interface type (AARM 7.3 (7.3/2)). Iface := Find_Hidden_Interface (Priv_T_Ifaces, Full_T_Ifaces); if Present (Iface) then Error_Msg_NE ("interface in partial view& not implemented by full type " & "(RM-2005 7.3 (7.3/2))", Full_T, Iface); end if; Iface := Find_Hidden_Interface (Full_T_Ifaces, Priv_T_Ifaces); if Present (Iface) then Error_Msg_NE ("interface & not implemented by partial view " & "(RM-2005 7.3 (7.3/2))", Full_T, Iface); end if; end; end if; if Is_Tagged_Type (Priv_T) and then Nkind (Parent (Priv_T)) = N_Private_Extension_Declaration and then Is_Derived_Type (Full_T) then Priv_Parent := Etype (Priv_T); -- The full view of a private extension may have been transformed -- into an unconstrained derived type declaration and a subtype -- declaration (see build_derived_record_type for details). if Nkind (N) = N_Subtype_Declaration then Full_Indic := Subtype_Indication (N); Full_Parent := Etype (Base_Type (Full_T)); else Full_Indic := Subtype_Indication (Type_Definition (N)); Full_Parent := Etype (Full_T); end if; -- Check that the parent type of the full type is a descendant of -- the ancestor subtype given in the private extension. If either -- entity has an Etype equal to Any_Type then we had some previous -- error situation [7.3(8)]. if Priv_Parent = Any_Type or else Full_Parent = Any_Type then goto Leave; -- Ada 2005 (AI-251): Interfaces in the full type can be given in -- any order. Therefore we don't have to check that its parent must -- be a descendant of the parent of the private type declaration. elsif Is_Interface (Priv_Parent) and then Is_Interface (Full_Parent) then null; -- Ada 2005 (AI-251): If the parent of the private type declaration -- is an interface there is no need to check that it is an ancestor -- of the associated full type declaration. The required tests for -- this case are performed by Build_Derived_Record_Type. elsif not Is_Interface (Base_Type (Priv_Parent)) and then not Is_Ancestor (Base_Type (Priv_Parent), Full_Parent) then Error_Msg_N ("parent of full type must descend from parent of private " & "extension", Full_Indic); -- First check a formal restriction, and then proceed with checking -- Ada rules. Since the formal restriction is not a serious error, we -- don't prevent further error detection for this check, hence the -- ELSE. else -- Check the rules of 7.3(10): if the private extension inherits -- known discriminants, then the full type must also inherit those -- discriminants from the same (ancestor) type, and the parent -- subtype of the full type must be constrained if and only if -- the ancestor subtype of the private extension is constrained. if No (Discriminant_Specifications (Parent (Priv_T))) and then not Has_Unknown_Discriminants (Priv_T) and then Has_Discriminants (Base_Type (Priv_Parent)) then declare Priv_Indic : constant Node_Id := Subtype_Indication (Parent (Priv_T)); Priv_Constr : constant Boolean := Is_Constrained (Priv_Parent) or else Nkind (Priv_Indic) = N_Subtype_Indication or else Is_Constrained (Entity (Priv_Indic)); Full_Constr : constant Boolean := Is_Constrained (Full_Parent) or else Nkind (Full_Indic) = N_Subtype_Indication or else Is_Constrained (Entity (Full_Indic)); Priv_Discr : Entity_Id; Full_Discr : Entity_Id; begin Priv_Discr := First_Discriminant (Priv_Parent); Full_Discr := First_Discriminant (Full_Parent); while Present (Priv_Discr) and then Present (Full_Discr) loop if Original_Record_Component (Priv_Discr) = Original_Record_Component (Full_Discr) or else Corresponding_Discriminant (Priv_Discr) = Corresponding_Discriminant (Full_Discr) then null; else exit; end if; Next_Discriminant (Priv_Discr); Next_Discriminant (Full_Discr); end loop; if Present (Priv_Discr) or else Present (Full_Discr) then Error_Msg_N ("full view must inherit discriminants of the parent " & "type used in the private extension", Full_Indic); elsif Priv_Constr and then not Full_Constr then Error_Msg_N ("parent subtype of full type must be constrained", Full_Indic); elsif Full_Constr and then not Priv_Constr then Error_Msg_N ("parent subtype of full type must be unconstrained", Full_Indic); end if; end; -- Check the rules of 7.3(12): if a partial view has neither -- known or unknown discriminants, then the full type -- declaration shall define a definite subtype. elsif not Has_Unknown_Discriminants (Priv_T) and then not Has_Discriminants (Priv_T) and then not Is_Constrained (Full_T) then Error_Msg_N ("full view must define a constrained type if partial view " & "has no discriminants", Full_T); end if; -- Do we implement the following properly??? -- If the ancestor subtype of a private extension has constrained -- discriminants, then the parent subtype of the full view shall -- impose a statically matching constraint on those discriminants -- [7.3(13)]. end if; else -- For untagged types, verify that a type without discriminants is -- not completed with an unconstrained type. A separate error message -- is produced if the full type has defaulted discriminants. if Is_Definite_Subtype (Priv_T) and then not Is_Definite_Subtype (Full_T) then Error_Msg_Sloc := Sloc (Parent (Priv_T)); Error_Msg_NE ("full view of& not compatible with declaration#", Full_T, Priv_T); if not Is_Tagged_Type (Full_T) then Error_Msg_N ("\one is constrained, the other unconstrained", Full_T); end if; end if; end if; -- AI-419: verify that the use of "limited" is consistent declare Orig_Decl : constant Node_Id := Original_Node (N); begin if Nkind (Parent (Priv_T)) = N_Private_Extension_Declaration and then Nkind (Orig_Decl) = N_Full_Type_Declaration and then Nkind (Type_Definition (Orig_Decl)) = N_Derived_Type_Definition then if not Limited_Present (Parent (Priv_T)) and then not Synchronized_Present (Parent (Priv_T)) and then Limited_Present (Type_Definition (Orig_Decl)) then Error_Msg_N ("full view of non-limited extension cannot be limited", N); -- Conversely, if the partial view carries the limited keyword, -- the full view must as well, even if it may be redundant. elsif Limited_Present (Parent (Priv_T)) and then not Limited_Present (Type_Definition (Orig_Decl)) then Error_Msg_N ("full view of limited extension must be explicitly limited", N); end if; end if; end; -- Ada 2005 (AI-443): A synchronized private extension must be -- completed by a task or protected type. if Ada_Version >= Ada_2005 and then Nkind (Parent (Priv_T)) = N_Private_Extension_Declaration and then Synchronized_Present (Parent (Priv_T)) and then not Is_Concurrent_Type (Full_T) then Error_Msg_N ("full view of synchronized extension must " & "be synchronized type", N); end if; -- Ada 2005 AI-363: if the full view has discriminants with -- defaults, it is illegal to declare constrained access subtypes -- whose designated type is the current type. This allows objects -- of the type that are declared in the heap to be unconstrained. if not Has_Unknown_Discriminants (Priv_T) and then not Has_Discriminants (Priv_T) and then Has_Defaulted_Discriminants (Full_T) then Set_Has_Constrained_Partial_View (Base_Type (Full_T)); Set_Has_Constrained_Partial_View (Priv_T); end if; -- Create a full declaration for all its subtypes recorded in -- Private_Dependents and swap them similarly to the base type. These -- are subtypes that have been define before the full declaration of -- the private type. We also swap the entry in Private_Dependents list -- so we can properly restore the private view on exit from the scope. declare Priv_Elmt : Elmt_Id; Priv_Scop : Entity_Id; Priv : Entity_Id; Full : Entity_Id; begin Priv_Elmt := First_Elmt (Private_Dependents (Priv_T)); while Present (Priv_Elmt) loop Priv := Node (Priv_Elmt); Priv_Scop := Scope (Priv); if Ekind (Priv) in E_Private_Subtype | E_Limited_Private_Subtype | E_Record_Subtype_With_Private then Full := Make_Defining_Identifier (Sloc (Priv), Chars (Priv)); Set_Is_Itype (Full); Set_Parent (Full, Parent (Priv)); Set_Associated_Node_For_Itype (Full, N); -- Now we need to complete the private subtype, but since the -- base type has already been swapped, we must also swap the -- subtypes (and thus, reverse the arguments in the call to -- Complete_Private_Subtype). Also note that we may need to -- re-establish the scope of the private subtype. Copy_And_Swap (Priv, Full); if not In_Open_Scopes (Priv_Scop) then Push_Scope (Priv_Scop); else -- Reset Priv_Scop to Empty to indicate no scope was pushed Priv_Scop := Empty; end if; Complete_Private_Subtype (Full, Priv, Full_T, N); Set_Full_View (Full, Priv); if Present (Priv_Scop) then Pop_Scope; end if; Replace_Elmt (Priv_Elmt, Full); end if; Next_Elmt (Priv_Elmt); end loop; end; declare Disp_Typ : Entity_Id; Full_List : Elist_Id; Prim : Entity_Id; Prim_Elmt : Elmt_Id; Priv_List : Elist_Id; function Contains (E : Entity_Id; L : Elist_Id) return Boolean; -- Determine whether list L contains element E -------------- -- Contains -- -------------- function Contains (E : Entity_Id; L : Elist_Id) return Boolean is List_Elmt : Elmt_Id; begin List_Elmt := First_Elmt (L); while Present (List_Elmt) loop if Node (List_Elmt) = E then return True; end if; Next_Elmt (List_Elmt); end loop; return False; end Contains; -- Start of processing begin -- If the private view was tagged, copy the new primitive operations -- from the private view to the full view. if Is_Tagged_Type (Full_T) then if Is_Tagged_Type (Priv_T) then Priv_List := Primitive_Operations (Priv_T); Prim_Elmt := First_Elmt (Priv_List); -- In the case of a concurrent type completing a private tagged -- type, primitives may have been declared in between the two -- views. These subprograms need to be wrapped the same way -- entries and protected procedures are handled because they -- cannot be directly shared by the two views. if Is_Concurrent_Type (Full_T) then declare Conc_Typ : constant Entity_Id := Corresponding_Record_Type (Full_T); Curr_Nod : Node_Id := Parent (Conc_Typ); Wrap_Spec : Node_Id; begin while Present (Prim_Elmt) loop Prim := Node (Prim_Elmt); if Comes_From_Source (Prim) and then not Is_Abstract_Subprogram (Prim) then Wrap_Spec := Make_Subprogram_Declaration (Sloc (Prim), Specification => Build_Wrapper_Spec (Subp_Id => Prim, Obj_Typ => Conc_Typ, Formals => Parameter_Specifications (Parent (Prim)))); Insert_After (Curr_Nod, Wrap_Spec); Curr_Nod := Wrap_Spec; Analyze (Wrap_Spec); -- Remove the wrapper from visibility to avoid -- spurious conflict with the wrapped entity. Set_Is_Immediately_Visible (Defining_Entity (Specification (Wrap_Spec)), False); end if; Next_Elmt (Prim_Elmt); end loop; goto Leave; end; -- For nonconcurrent types, transfer explicit primitives, but -- omit those inherited from the parent of the private view -- since they will be re-inherited later on. else Full_List := Primitive_Operations (Full_T); while Present (Prim_Elmt) loop Prim := Node (Prim_Elmt); if Comes_From_Source (Prim) and then not Contains (Prim, Full_List) then Append_Elmt (Prim, Full_List); end if; Next_Elmt (Prim_Elmt); end loop; end if; -- Untagged private view else Full_List := Primitive_Operations (Full_T); -- In this case the partial view is untagged, so here we locate -- all of the earlier primitives that need to be treated as -- dispatching (those that appear between the two views). Note -- that these additional operations must all be new operations -- (any earlier operations that override inherited operations -- of the full view will already have been inserted in the -- primitives list, marked by Check_Operation_From_Private_View -- as dispatching. Note that implicit "/=" operators are -- excluded from being added to the primitives list since they -- shouldn't be treated as dispatching (tagged "/=" is handled -- specially). Prim := Next_Entity (Full_T); while Present (Prim) and then Prim /= Priv_T loop if Ekind (Prim) in E_Procedure | E_Function then Disp_Typ := Find_Dispatching_Type (Prim); if Disp_Typ = Full_T and then (Chars (Prim) /= Name_Op_Ne or else Comes_From_Source (Prim)) then Check_Controlling_Formals (Full_T, Prim); if Is_Suitable_Primitive (Prim) and then not Is_Dispatching_Operation (Prim) then Append_Elmt (Prim, Full_List); Set_Is_Dispatching_Operation (Prim); Set_DT_Position_Value (Prim, No_Uint); end if; elsif Is_Dispatching_Operation (Prim) and then Disp_Typ /= Full_T then -- Verify that it is not otherwise controlled by a -- formal or a return value of type T. Check_Controlling_Formals (Disp_Typ, Prim); end if; end if; Next_Entity (Prim); end loop; end if; -- For the tagged case, the two views can share the same primitive -- operations list and the same class-wide type. Update attributes -- of the class-wide type which depend on the full declaration. if Is_Tagged_Type (Priv_T) then Set_Direct_Primitive_Operations (Priv_T, Full_List); Set_Class_Wide_Type (Base_Type (Full_T), Class_Wide_Type (Priv_T)); Propagate_Concurrent_Flags (Class_Wide_Type (Priv_T), Full_T); end if; -- For untagged types, copy the primitives across from the private -- view to the full view, for support of prefixed calls when -- extensions are enabled, and better error messages otherwise. else Priv_List := Primitive_Operations (Priv_T); Prim_Elmt := First_Elmt (Priv_List); Full_List := Primitive_Operations (Full_T); while Present (Prim_Elmt) loop Prim := Node (Prim_Elmt); Append_Elmt (Prim, Full_List); Next_Elmt (Prim_Elmt); end loop; end if; end; -- Ada 2005 AI 161: Check preelaborable initialization consistency if Known_To_Have_Preelab_Init (Priv_T) then -- Case where there is a pragma Preelaborable_Initialization. We -- always allow this in predefined units, which is cheating a bit, -- but it means we don't have to struggle to meet the requirements in -- the RM for having Preelaborable Initialization. Otherwise we -- require that the type meets the RM rules. But we can't check that -- yet, because of the rule about overriding Initialize, so we simply -- set a flag that will be checked at freeze time. if not In_Predefined_Unit (Full_T) then Set_Must_Have_Preelab_Init (Full_T); end if; end if; -- If pragma CPP_Class was applied to the private type declaration, -- propagate it now to the full type declaration. if Is_CPP_Class (Priv_T) then Set_Is_CPP_Class (Full_T); Set_Convention (Full_T, Convention_CPP); -- Check that components of imported CPP types do not have default -- expressions. Check_CPP_Type_Has_No_Defaults (Full_T); end if; -- If the private view has user specified stream attributes, then so has -- the full view. -- Why the test, how could these flags be already set in Full_T ??? if Has_Specified_Stream_Read (Priv_T) then Set_Has_Specified_Stream_Read (Full_T); end if; if Has_Specified_Stream_Write (Priv_T) then Set_Has_Specified_Stream_Write (Full_T); end if; if Has_Specified_Stream_Input (Priv_T) then Set_Has_Specified_Stream_Input (Full_T); end if; if Has_Specified_Stream_Output (Priv_T) then Set_Has_Specified_Stream_Output (Full_T); end if; -- Propagate Default_Initial_Condition-related attributes from the -- partial view to the full view. Propagate_DIC_Attributes (Full_T, From_Typ => Priv_T); -- And to the underlying full view, if any if Is_Private_Type (Full_T) and then Present (Underlying_Full_View (Full_T)) then Propagate_DIC_Attributes (Underlying_Full_View (Full_T), From_Typ => Priv_T); end if; -- Propagate invariant-related attributes from the partial view to the -- full view. Propagate_Invariant_Attributes (Full_T, From_Typ => Priv_T); -- And to the underlying full view, if any if Is_Private_Type (Full_T) and then Present (Underlying_Full_View (Full_T)) then Propagate_Invariant_Attributes (Underlying_Full_View (Full_T), From_Typ => Priv_T); end if; -- AI12-0041: Detect an attempt to inherit a class-wide type invariant -- in the full view without advertising the inheritance in the partial -- view. This can only occur when the partial view has no parent type -- and the full view has an interface as a parent. Any other scenarios -- are illegal because implemented interfaces must match between the -- two views. if Is_Tagged_Type (Priv_T) and then Is_Tagged_Type (Full_T) then declare Full_Par : constant Entity_Id := Etype (Full_T); Priv_Par : constant Entity_Id := Etype (Priv_T); begin if not Is_Interface (Priv_Par) and then Is_Interface (Full_Par) and then Has_Inheritable_Invariants (Full_Par) then Error_Msg_N ("hidden inheritance of class-wide type invariants not " & "allowed", N); end if; end; end if; -- Propagate predicates to full type, and predicate function if already -- defined. It is not clear that this can actually happen? the partial -- view cannot be frozen yet, and the predicate function has not been -- built. Still it is a cheap check and seems safer to make it. Propagate_Predicate_Attributes (Full_T, Priv_T); if Is_Private_Type (Full_T) and then Present (Underlying_Full_View (Full_T)) then Propagate_Predicate_Attributes (Underlying_Full_View (Full_T), Priv_T); end if; <> Restore_Ghost_Region (Saved_GM, Saved_IGR); end Process_Full_View; ----------------------------------- -- Process_Incomplete_Dependents -- ----------------------------------- procedure Process_Incomplete_Dependents (N : Node_Id; Full_T : Entity_Id; Inc_T : Entity_Id) is Inc_Elmt : Elmt_Id; Priv_Dep : Entity_Id; New_Subt : Entity_Id; Disc_Constraint : Elist_Id; begin if No (Private_Dependents (Inc_T)) then return; end if; -- Itypes that may be generated by the completion of an incomplete -- subtype are not used by the back-end and not attached to the tree. -- They are created only for constraint-checking purposes. Inc_Elmt := First_Elmt (Private_Dependents (Inc_T)); while Present (Inc_Elmt) loop Priv_Dep := Node (Inc_Elmt); if Ekind (Priv_Dep) = E_Subprogram_Type then -- An Access_To_Subprogram type may have a return type or a -- parameter type that is incomplete. Replace with the full view. if Etype (Priv_Dep) = Inc_T then Set_Etype (Priv_Dep, Full_T); end if; declare Formal : Entity_Id; begin Formal := First_Formal (Priv_Dep); while Present (Formal) loop if Etype (Formal) = Inc_T then Set_Etype (Formal, Full_T); end if; Next_Formal (Formal); end loop; end; elsif Is_Overloadable (Priv_Dep) then -- If a subprogram in the incomplete dependents list is primitive -- for a tagged full type then mark it as a dispatching operation, -- check whether it overrides an inherited subprogram, and check -- restrictions on its controlling formals. Note that a protected -- operation is never dispatching: only its wrapper operation -- (which has convention Ada) is. if Is_Tagged_Type (Full_T) and then Is_Primitive (Priv_Dep) and then Convention (Priv_Dep) /= Convention_Protected then Check_Operation_From_Incomplete_Type (Priv_Dep, Inc_T); Set_Is_Dispatching_Operation (Priv_Dep); Check_Controlling_Formals (Full_T, Priv_Dep); end if; elsif Ekind (Priv_Dep) = E_Subprogram_Body then -- Can happen during processing of a body before the completion -- of a TA type. Ignore, because spec is also on dependent list. return; -- Ada 2005 (AI-412): Transform a regular incomplete subtype into a -- corresponding subtype of the full view. elsif Ekind (Priv_Dep) = E_Incomplete_Subtype and then Comes_From_Source (Priv_Dep) then Set_Subtype_Indication (Parent (Priv_Dep), New_Occurrence_Of (Full_T, Sloc (Priv_Dep))); Reinit_Field_To_Zero (Priv_Dep, F_Private_Dependents, Old_Ekind => E_Incomplete_Subtype); Mutate_Ekind (Priv_Dep, Subtype_Kind (Ekind (Full_T))); Set_Etype (Priv_Dep, Full_T); Set_Analyzed (Parent (Priv_Dep), False); -- Reanalyze the declaration, suppressing the call to Enter_Name -- to avoid duplicate names. Analyze_Subtype_Declaration (N => Parent (Priv_Dep), Skip => True); -- Dependent is a subtype else -- We build a new subtype indication using the full view of the -- incomplete parent. The discriminant constraints have been -- elaborated already at the point of the subtype declaration. New_Subt := Create_Itype (E_Void, N); if Has_Discriminants (Full_T) then Disc_Constraint := Discriminant_Constraint (Priv_Dep); else Disc_Constraint := No_Elist; end if; Build_Discriminated_Subtype (Full_T, New_Subt, Disc_Constraint, N); Set_Full_View (Priv_Dep, New_Subt); end if; Next_Elmt (Inc_Elmt); end loop; end Process_Incomplete_Dependents; -------------------------------- -- Process_Range_Expr_In_Decl -- -------------------------------- procedure Process_Range_Expr_In_Decl (R : Node_Id; T : Entity_Id; Subtyp : Entity_Id := Empty; Check_List : List_Id := No_List) is Lo, Hi : Node_Id; R_Checks : Check_Result; Insert_Node : Node_Id; Def_Id : Entity_Id; begin Analyze_And_Resolve (R, Base_Type (T)); if Nkind (R) = N_Range then Lo := Low_Bound (R); Hi := High_Bound (R); -- Validity checks on the range of a quantified expression are -- delayed until the construct is transformed into a loop. if Nkind (Parent (R)) = N_Loop_Parameter_Specification and then Nkind (Parent (Parent (R))) = N_Quantified_Expression then null; -- We need to ensure validity of the bounds here, because if we -- go ahead and do the expansion, then the expanded code will get -- analyzed with range checks suppressed and we miss the check. -- WARNING: The capture of the range bounds with xxx_FIRST/_LAST and -- the temporaries generated by routine Remove_Side_Effects by means -- of validity checks must use the same names. When a range appears -- in the parent of a generic, the range is processed with checks -- disabled as part of the generic context and with checks enabled -- for code generation purposes. This leads to link issues as the -- generic contains references to xxx_FIRST/_LAST, but the inlined -- template sees the temporaries generated by Remove_Side_Effects. else Validity_Check_Range (R, Subtyp); end if; -- If there were errors in the declaration, try and patch up some -- common mistakes in the bounds. The cases handled are literals -- which are Integer where the expected type is Real and vice versa. -- These corrections allow the compilation process to proceed further -- along since some basic assumptions of the format of the bounds -- are guaranteed. if Etype (R) = Any_Type then if Nkind (Lo) = N_Integer_Literal and then Is_Real_Type (T) then Rewrite (Lo, Make_Real_Literal (Sloc (Lo), UR_From_Uint (Intval (Lo)))); elsif Nkind (Hi) = N_Integer_Literal and then Is_Real_Type (T) then Rewrite (Hi, Make_Real_Literal (Sloc (Hi), UR_From_Uint (Intval (Hi)))); elsif Nkind (Lo) = N_Real_Literal and then Is_Integer_Type (T) then Rewrite (Lo, Make_Integer_Literal (Sloc (Lo), UR_To_Uint (Realval (Lo)))); elsif Nkind (Hi) = N_Real_Literal and then Is_Integer_Type (T) then Rewrite (Hi, Make_Integer_Literal (Sloc (Hi), UR_To_Uint (Realval (Hi)))); end if; Set_Etype (Lo, T); Set_Etype (Hi, T); end if; -- If the bounds of the range have been mistakenly given as string -- literals (perhaps in place of character literals), then an error -- has already been reported, but we rewrite the string literal as a -- bound of the range's type to avoid blowups in later processing -- that looks at static values. if Nkind (Lo) = N_String_Literal then Rewrite (Lo, Make_Attribute_Reference (Sloc (Lo), Prefix => New_Occurrence_Of (T, Sloc (Lo)), Attribute_Name => Name_First)); Analyze_And_Resolve (Lo); end if; if Nkind (Hi) = N_String_Literal then Rewrite (Hi, Make_Attribute_Reference (Sloc (Hi), Prefix => New_Occurrence_Of (T, Sloc (Hi)), Attribute_Name => Name_First)); Analyze_And_Resolve (Hi); end if; -- If bounds aren't scalar at this point then exit, avoiding -- problems with further processing of the range in this procedure. if not Is_Scalar_Type (Etype (Lo)) then return; end if; -- Resolve (actually Sem_Eval) has checked that the bounds are in -- then range of the base type. Here we check whether the bounds -- are in the range of the subtype itself. Note that if the bounds -- represent the null range the Constraint_Error exception should -- not be raised. -- Capture values of bounds and generate temporaries for them -- if needed, before applying checks, since checks may cause -- duplication of the expression without forcing evaluation. -- The forced evaluation removes side effects from expressions, -- which should occur also in GNATprove mode. Otherwise, we end up -- with unexpected insertions of actions at places where this is -- not supposed to occur, e.g. on default parameters of a call. if Expander_Active or GNATprove_Mode then -- Call Force_Evaluation to create declarations as needed -- to deal with side effects, and also create typ_FIRST/LAST -- entities for bounds if we have a subtype name. -- Note: we do this transformation even if expansion is not -- active if we are in GNATprove_Mode since the transformation -- is in general required to ensure that the resulting tree has -- proper Ada semantics. Force_Evaluation (Lo, Related_Id => Subtyp, Is_Low_Bound => True); Force_Evaluation (Hi, Related_Id => Subtyp, Is_High_Bound => True); end if; -- We use a flag here instead of suppressing checks on the type -- because the type we check against isn't necessarily the place -- where we put the check. R_Checks := Get_Range_Checks (R, T); -- Look up tree to find an appropriate insertion point. We can't -- just use insert_actions because later processing depends on -- the insertion node. Prior to Ada 2012 the insertion point could -- only be a declaration or a loop, but quantified expressions can -- appear within any context in an expression, and the insertion -- point can be any statement, pragma, or declaration. Insert_Node := Parent (R); while Present (Insert_Node) loop exit when Nkind (Insert_Node) in N_Declaration and then Nkind (Insert_Node) not in N_Component_Declaration | N_Loop_Parameter_Specification | N_Function_Specification | N_Procedure_Specification; exit when Nkind (Insert_Node) in N_Later_Decl_Item | N_Statement_Other_Than_Procedure_Call | N_Procedure_Call_Statement | N_Pragma; Insert_Node := Parent (Insert_Node); end loop; if Present (Insert_Node) then -- Case of loop statement. Verify that the range is part of the -- subtype indication of the iteration scheme. if Nkind (Insert_Node) = N_Loop_Statement then declare Indic : Node_Id; begin Indic := Parent (R); while Present (Indic) and then Nkind (Indic) /= N_Subtype_Indication loop Indic := Parent (Indic); end loop; if Present (Indic) then Def_Id := Etype (Subtype_Mark (Indic)); Insert_Range_Checks (R_Checks, Insert_Node, Def_Id, Sloc (Insert_Node), Do_Before => True); end if; end; -- Case of declarations. If the declaration is for a type and -- involves discriminants, the checks are premature at the -- declaration point and need to wait for the expansion of the -- initialization procedure, which will pass in the list to put -- them on; otherwise, the checks are done at the declaration -- point and there is no need to do them again in the -- initialization procedure. elsif Nkind (Insert_Node) in N_Declaration then Def_Id := Defining_Identifier (Insert_Node); if (Ekind (Def_Id) = E_Record_Type and then Depends_On_Discriminant (R)) or else (Ekind (Def_Id) = E_Protected_Type and then Has_Discriminants (Def_Id)) then if Present (Check_List) then Append_Range_Checks (R_Checks, Check_List, Def_Id, Sloc (Insert_Node)); end if; else if No (Check_List) then Insert_Range_Checks (R_Checks, Insert_Node, Def_Id, Sloc (Insert_Node)); end if; end if; -- Case of statements. Drop the checks, as the range appears in -- the context of a quantified expression. Insertion will take -- place when expression is expanded. else null; end if; end if; -- Case of other than an explicit N_Range node -- The forced evaluation removes side effects from expressions, which -- should occur also in GNATprove mode. Otherwise, we end up with -- unexpected insertions of actions at places where this is not -- supposed to occur, e.g. on default parameters of a call. elsif Expander_Active or GNATprove_Mode then Get_Index_Bounds (R, Lo, Hi); Force_Evaluation (Lo); Force_Evaluation (Hi); end if; end Process_Range_Expr_In_Decl; -------------------------------------- -- Process_Real_Range_Specification -- -------------------------------------- procedure Process_Real_Range_Specification (Def : Node_Id) is Spec : constant Node_Id := Real_Range_Specification (Def); Lo : Node_Id; Hi : Node_Id; Err : Boolean := False; procedure Analyze_Bound (N : Node_Id); -- Analyze and check one bound ------------------- -- Analyze_Bound -- ------------------- procedure Analyze_Bound (N : Node_Id) is begin Analyze_And_Resolve (N, Any_Real); if not Is_OK_Static_Expression (N) then Flag_Non_Static_Expr ("bound in real type definition is not static!", N); Err := True; end if; end Analyze_Bound; -- Start of processing for Process_Real_Range_Specification begin if Present (Spec) then Lo := Low_Bound (Spec); Hi := High_Bound (Spec); Analyze_Bound (Lo); Analyze_Bound (Hi); -- If error, clear away junk range specification if Err then Set_Real_Range_Specification (Def, Empty); end if; end if; end Process_Real_Range_Specification; --------------------- -- Process_Subtype -- --------------------- function Process_Subtype (S : Node_Id; Related_Nod : Node_Id; Related_Id : Entity_Id := Empty; Suffix : Character := ' ') return Entity_Id is procedure Check_Incomplete (T : Node_Id); -- Called to verify that an incomplete type is not used prematurely ---------------------- -- Check_Incomplete -- ---------------------- procedure Check_Incomplete (T : Node_Id) is begin -- Ada 2005 (AI-412): Incomplete subtypes are legal if Ekind (Root_Type (Entity (T))) = E_Incomplete_Type and then not (Ada_Version >= Ada_2005 and then (Nkind (Parent (T)) = N_Subtype_Declaration or else (Nkind (Parent (T)) = N_Subtype_Indication and then Nkind (Parent (Parent (T))) = N_Subtype_Declaration))) then Error_Msg_N ("invalid use of type before its full declaration", T); end if; end Check_Incomplete; -- Local variables P : Node_Id; Def_Id : Entity_Id; Error_Node : Node_Id; Full_View_Id : Entity_Id; Subtype_Mark_Id : Entity_Id; May_Have_Null_Exclusion : Boolean; -- Start of processing for Process_Subtype begin -- Case of no constraints present if Nkind (S) /= N_Subtype_Indication then Find_Type (S); -- No way to proceed if the subtype indication is malformed. This -- will happen for example when the subtype indication in an object -- declaration is missing altogether and the expression is analyzed -- as if it were that indication. if not Is_Entity_Name (S) then return Any_Type; end if; Check_Incomplete (S); P := Parent (S); -- The following mirroring of assertion in Null_Exclusion_Present is -- ugly, can't we have a range, a static predicate or even a flag??? May_Have_Null_Exclusion := Present (P) and then Nkind (P) in N_Access_Definition | N_Access_Function_Definition | N_Access_Procedure_Definition | N_Access_To_Object_Definition | N_Allocator | N_Component_Definition | N_Derived_Type_Definition | N_Discriminant_Specification | N_Formal_Object_Declaration | N_Function_Specification | N_Object_Declaration | N_Object_Renaming_Declaration | N_Parameter_Specification | N_Subtype_Declaration; -- Ada 2005 (AI-231): Static check if Ada_Version >= Ada_2005 and then May_Have_Null_Exclusion and then Null_Exclusion_Present (P) and then Nkind (P) /= N_Access_To_Object_Definition and then not Is_Access_Type (Entity (S)) then Error_Msg_N ("`NOT NULL` only allowed for an access type", S); end if; -- Create an Itype that is a duplicate of Entity (S) but with the -- null-exclusion attribute. if May_Have_Null_Exclusion and then Is_Access_Type (Entity (S)) and then Null_Exclusion_Present (P) -- No need to check the case of an access to object definition. -- It is correct to define double not-null pointers. -- Example: -- type Not_Null_Int_Ptr is not null access Integer; -- type Acc is not null access Not_Null_Int_Ptr; and then Nkind (P) /= N_Access_To_Object_Definition then if Can_Never_Be_Null (Entity (S)) then case Nkind (Related_Nod) is when N_Full_Type_Declaration => if Nkind (Type_Definition (Related_Nod)) in N_Array_Type_Definition then Error_Node := Subtype_Indication (Component_Definition (Type_Definition (Related_Nod))); else Error_Node := Subtype_Indication (Type_Definition (Related_Nod)); end if; when N_Subtype_Declaration => Error_Node := Subtype_Indication (Related_Nod); when N_Object_Declaration => Error_Node := Object_Definition (Related_Nod); when N_Component_Declaration => Error_Node := Subtype_Indication (Component_Definition (Related_Nod)); when N_Allocator => Error_Node := Expression (Related_Nod); when others => pragma Assert (False); Error_Node := Related_Nod; end case; Error_Msg_NE ("`NOT NULL` not allowed (& already excludes null)", Error_Node, Entity (S)); end if; Set_Etype (S, Create_Null_Excluding_Itype (T => Entity (S), Related_Nod => P)); Set_Entity (S, Etype (S)); end if; return Entity (S); -- Case of constraint present, so that we have an N_Subtype_Indication -- node (this node is created only if constraints are present). else Find_Type (Subtype_Mark (S)); if Nkind (Parent (S)) /= N_Access_To_Object_Definition and then not (Nkind (Parent (S)) = N_Subtype_Declaration and then Is_Itype (Defining_Identifier (Parent (S)))) then Check_Incomplete (Subtype_Mark (S)); end if; P := Parent (S); Subtype_Mark_Id := Entity (Subtype_Mark (S)); -- Explicit subtype declaration case if Nkind (P) = N_Subtype_Declaration then Def_Id := Defining_Identifier (P); -- Explicit derived type definition case elsif Nkind (P) = N_Derived_Type_Definition then Def_Id := Defining_Identifier (Parent (P)); -- Implicit case, the Def_Id must be created as an implicit type. -- The one exception arises in the case of concurrent types, array -- and access types, where other subsidiary implicit types may be -- created and must appear before the main implicit type. In these -- cases we leave Def_Id set to Empty as a signal that Create_Itype -- has not yet been called to create Def_Id. else if Is_Array_Type (Subtype_Mark_Id) or else Is_Concurrent_Type (Subtype_Mark_Id) or else Is_Access_Type (Subtype_Mark_Id) then Def_Id := Empty; -- For the other cases, we create a new unattached Itype, -- and set the indication to ensure it gets attached later. else Def_Id := Create_Itype (E_Void, Related_Nod, Related_Id, Suffix); end if; end if; -- If the kind of constraint is invalid for this kind of type, -- then give an error, and then pretend no constraint was given. if not Is_Valid_Constraint_Kind (Ekind (Subtype_Mark_Id), Nkind (Constraint (S))) then Error_Msg_N ("incorrect constraint for this kind of type", Constraint (S)); Rewrite (S, New_Copy_Tree (Subtype_Mark (S))); -- Set Ekind of orphan itype, to prevent cascaded errors if Present (Def_Id) then Mutate_Ekind (Def_Id, Ekind (Any_Type)); end if; -- Make recursive call, having got rid of the bogus constraint return Process_Subtype (S, Related_Nod, Related_Id, Suffix); end if; -- Remaining processing depends on type. Select on Base_Type kind to -- ensure getting to the concrete type kind in the case of a private -- subtype (needed when only doing semantic analysis). case Ekind (Base_Type (Subtype_Mark_Id)) is when Access_Kind => -- If this is a constraint on a class-wide type, discard it. -- There is currently no way to express a partial discriminant -- constraint on a type with unknown discriminants. This is -- a pathology that the ACATS wisely decides not to test. if Is_Class_Wide_Type (Designated_Type (Subtype_Mark_Id)) then if Comes_From_Source (S) then Error_Msg_N ("constraint on class-wide type ignored??", Constraint (S)); end if; if Nkind (P) = N_Subtype_Declaration then Set_Subtype_Indication (P, New_Occurrence_Of (Subtype_Mark_Id, Sloc (S))); end if; return Subtype_Mark_Id; end if; Constrain_Access (Def_Id, S, Related_Nod); if Expander_Active and then Is_Itype (Designated_Type (Def_Id)) and then Nkind (Related_Nod) = N_Subtype_Declaration and then not Is_Incomplete_Type (Designated_Type (Def_Id)) then Build_Itype_Reference (Designated_Type (Def_Id), Related_Nod); end if; when Array_Kind => Constrain_Array (Def_Id, S, Related_Nod, Related_Id, Suffix); when Decimal_Fixed_Point_Kind => Constrain_Decimal (Def_Id, S); when Enumeration_Kind => Constrain_Enumeration (Def_Id, S); when Ordinary_Fixed_Point_Kind => Constrain_Ordinary_Fixed (Def_Id, S); when Float_Kind => Constrain_Float (Def_Id, S); when Integer_Kind => Constrain_Integer (Def_Id, S); when Class_Wide_Kind | E_Incomplete_Type | E_Record_Subtype | E_Record_Type => Constrain_Discriminated_Type (Def_Id, S, Related_Nod); if Ekind (Def_Id) = E_Incomplete_Type then Set_Private_Dependents (Def_Id, New_Elmt_List); end if; when Private_Kind => -- A private type with unknown discriminants may be completed -- by an unconstrained array type. if Has_Unknown_Discriminants (Subtype_Mark_Id) and then Present (Full_View (Subtype_Mark_Id)) and then Is_Array_Type (Full_View (Subtype_Mark_Id)) then Constrain_Array (Def_Id, S, Related_Nod, Related_Id, Suffix); -- ... but more commonly is completed by a discriminated record -- type. else Constrain_Discriminated_Type (Def_Id, S, Related_Nod); end if; -- The base type may be private but Def_Id may be a full view -- in an instance. if Is_Private_Type (Def_Id) then Set_Private_Dependents (Def_Id, New_Elmt_List); end if; -- In case of an invalid constraint prevent further processing -- since the type constructed is missing expected fields. if Etype (Def_Id) = Any_Type then return Def_Id; end if; -- If the full view is that of a task with discriminants, -- we must constrain both the concurrent type and its -- corresponding record type. Otherwise we will just propagate -- the constraint to the full view, if available. if Present (Full_View (Subtype_Mark_Id)) and then Has_Discriminants (Subtype_Mark_Id) and then Is_Concurrent_Type (Full_View (Subtype_Mark_Id)) then Full_View_Id := Create_Itype (E_Void, Related_Nod, Related_Id, Suffix); Set_Entity (Subtype_Mark (S), Full_View (Subtype_Mark_Id)); Constrain_Concurrent (Full_View_Id, S, Related_Nod, Related_Id, Suffix); Set_Entity (Subtype_Mark (S), Subtype_Mark_Id); Set_Full_View (Def_Id, Full_View_Id); -- Introduce an explicit reference to the private subtype, -- to prevent scope anomalies in gigi if first use appears -- in a nested context, e.g. a later function body. -- Should this be generated in other contexts than a full -- type declaration? if Is_Itype (Def_Id) and then Nkind (Parent (P)) = N_Full_Type_Declaration then Build_Itype_Reference (Def_Id, Parent (P)); end if; else Prepare_Private_Subtype_Completion (Def_Id, Related_Nod); end if; when Concurrent_Kind => Constrain_Concurrent (Def_Id, S, Related_Nod, Related_Id, Suffix); when others => Error_Msg_N ("invalid subtype mark in subtype indication", S); end case; -- Size, Alignment, Representation aspects and Convention are always -- inherited from the base type. Set_Size_Info (Def_Id, (Subtype_Mark_Id)); Set_Rep_Info (Def_Id, (Subtype_Mark_Id)); Set_Convention (Def_Id, Convention (Subtype_Mark_Id)); -- The anonymous subtype created for the subtype indication -- inherits the predicates of the parent. if Has_Predicates (Subtype_Mark_Id) then Inherit_Predicate_Flags (Def_Id, Subtype_Mark_Id); -- Indicate where the predicate function may be found if No (Predicate_Function (Def_Id)) and then Is_Itype (Def_Id) then Set_Predicated_Parent (Def_Id, Subtype_Mark_Id); end if; end if; return Def_Id; end if; end Process_Subtype; ----------------------------- -- Record_Type_Declaration -- ----------------------------- procedure Record_Type_Declaration (T : Entity_Id; N : Node_Id; Prev : Entity_Id) is Def : constant Node_Id := Type_Definition (N); Is_Tagged : Boolean; Tag_Comp : Entity_Id; begin -- These flags must be initialized before calling Process_Discriminants -- because this routine makes use of them. Mutate_Ekind (T, E_Record_Type); Set_Etype (T, T); Reinit_Size_Align (T); Set_Interfaces (T, No_Elist); Set_Stored_Constraint (T, No_Elist); Set_Default_SSO (T); Set_No_Reordering (T, No_Component_Reordering); -- Normal case if Ada_Version < Ada_2005 or else not Interface_Present (Def) then -- The flag Is_Tagged_Type might have already been set by -- Find_Type_Name if it detected an error for declaration T. This -- arises in the case of private tagged types where the full view -- omits the word tagged. Is_Tagged := Tagged_Present (Def) or else (Serious_Errors_Detected > 0 and then Is_Tagged_Type (T)); Set_Is_Limited_Record (T, Limited_Present (Def)); if Is_Tagged then Set_Is_Tagged_Type (T, True); Set_No_Tagged_Streams_Pragma (T, No_Tagged_Streams); end if; -- Type is abstract if full declaration carries keyword, or if -- previous partial view did. Set_Is_Abstract_Type (T, Is_Abstract_Type (T) or else Abstract_Present (Def)); else Is_Tagged := True; Analyze_Interface_Declaration (T, Def); if Present (Discriminant_Specifications (N)) then Error_Msg_N ("interface types cannot have discriminants", Defining_Identifier (First (Discriminant_Specifications (N)))); end if; end if; -- First pass: if there are self-referential access components, -- create the required anonymous access type declarations, and if -- need be an incomplete type declaration for T itself. Check_Anonymous_Access_Components (N, T, Prev, Component_List (Def)); if Ada_Version >= Ada_2005 and then Present (Interface_List (Def)) then Check_Interfaces (N, Def); declare Ifaces_List : Elist_Id; begin -- Ada 2005 (AI-251): Collect the list of progenitors that are not -- already in the parents. Collect_Interfaces (T => T, Ifaces_List => Ifaces_List, Exclude_Parents => True); Set_Interfaces (T, Ifaces_List); end; end if; -- Records constitute a scope for the component declarations within. -- The scope is created prior to the processing of these declarations. -- Discriminants are processed first, so that they are visible when -- processing the other components. The Ekind of the record type itself -- is set to E_Record_Type (subtypes appear as E_Record_Subtype). -- Enter record scope Push_Scope (T); -- If an incomplete or private type declaration was already given for -- the type, then this scope already exists, and the discriminants have -- been declared within. We must verify that the full declaration -- matches the incomplete one. Check_Or_Process_Discriminants (N, T, Prev); Set_Is_Constrained (T, not Has_Discriminants (T)); Set_Has_Delayed_Freeze (T, True); -- For tagged types add a manually analyzed component corresponding -- to the component _tag, the corresponding piece of tree will be -- expanded as part of the freezing actions if it is not a CPP_Class. if Is_Tagged then -- Do not add the tag unless we are in expansion mode if Expander_Active then Tag_Comp := Make_Defining_Identifier (Sloc (Def), Name_uTag); Enter_Name (Tag_Comp); Mutate_Ekind (Tag_Comp, E_Component); Set_Is_Tag (Tag_Comp); Set_Is_Aliased (Tag_Comp); Set_Is_Independent (Tag_Comp); Set_Etype (Tag_Comp, RTE (RE_Tag)); Set_DT_Entry_Count (Tag_Comp, No_Uint); Set_Original_Record_Component (Tag_Comp, Tag_Comp); Reinit_Component_Location (Tag_Comp); -- Ada 2005 (AI-251): Addition of the Tag corresponding to all the -- implemented interfaces. if Has_Interfaces (T) then Add_Interface_Tag_Components (N, T); end if; end if; Make_Class_Wide_Type (T); Set_Direct_Primitive_Operations (T, New_Elmt_List); end if; -- We must suppress range checks when processing record components in -- the presence of discriminants, since we don't want spurious checks to -- be generated during their analysis, but Suppress_Range_Checks flags -- must be reset the after processing the record definition. -- Note: this is the only use of Kill_Range_Checks, and is a bit odd, -- couldn't we just use the normal range check suppression method here. -- That would seem cleaner ??? if Has_Discriminants (T) and then not Range_Checks_Suppressed (T) then Set_Kill_Range_Checks (T, True); Record_Type_Definition (Def, Prev); Set_Kill_Range_Checks (T, False); else Record_Type_Definition (Def, Prev); end if; -- Exit from record scope End_Scope; -- Ada 2005 (AI-251 and AI-345): Derive the interface subprograms of all -- the implemented interfaces and associate them an aliased entity. if Is_Tagged and then not Is_Empty_List (Interface_List (Def)) then Derive_Progenitor_Subprograms (T, T); end if; Check_Function_Writable_Actuals (N); end Record_Type_Declaration; ---------------------------- -- Record_Type_Definition -- ---------------------------- procedure Record_Type_Definition (Def : Node_Id; Prev_T : Entity_Id) is Component : Entity_Id; Ctrl_Components : Boolean := False; Final_Storage_Only : Boolean; T : Entity_Id; begin if Ekind (Prev_T) = E_Incomplete_Type then T := Full_View (Prev_T); else T := Prev_T; end if; Final_Storage_Only := not Is_Controlled (T); -- Ada 2005: Check whether an explicit "limited" is present in a derived -- type declaration. if Parent_Kind (Def) = N_Derived_Type_Definition and then Limited_Present (Parent (Def)) then Set_Is_Limited_Record (T); end if; -- If the component list of a record type is defined by the reserved -- word null and there is no discriminant part, then the record type has -- no components and all records of the type are null records (RM 3.7) -- This procedure is also called to process the extension part of a -- record extension, in which case the current scope may have inherited -- components. if Present (Def) and then Present (Component_List (Def)) and then not Null_Present (Component_List (Def)) then Analyze_Declarations (Component_Items (Component_List (Def))); if Present (Variant_Part (Component_List (Def))) then Analyze (Variant_Part (Component_List (Def))); end if; end if; -- After completing the semantic analysis of the record definition, -- record components, both new and inherited, are accessible. Set their -- kind accordingly. Exclude malformed itypes from illegal declarations, -- whose Ekind may be void. Component := First_Entity (Current_Scope); while Present (Component) loop if Ekind (Component) = E_Void and then not Is_Itype (Component) then Mutate_Ekind (Component, E_Component); Reinit_Component_Location (Component); end if; Propagate_Concurrent_Flags (T, Etype (Component)); if Ekind (Component) /= E_Component then null; -- Do not set Has_Controlled_Component on a class-wide equivalent -- type. See Make_CW_Equivalent_Type. elsif not Is_Class_Wide_Equivalent_Type (T) and then (Has_Controlled_Component (Etype (Component)) or else (Chars (Component) /= Name_uParent and then Is_Controlled (Etype (Component)))) then Set_Has_Controlled_Component (T, True); Final_Storage_Only := Final_Storage_Only and then Finalize_Storage_Only (Etype (Component)); Ctrl_Components := True; end if; Next_Entity (Component); end loop; -- A Type is Finalize_Storage_Only only if all its controlled components -- are also. if Ctrl_Components then Set_Finalize_Storage_Only (T, Final_Storage_Only); end if; -- Place reference to end record on the proper entity, which may -- be a partial view. if Present (Def) then Process_End_Label (Def, 'e', Prev_T); end if; end Record_Type_Definition; --------------------------- -- Replace_Discriminants -- --------------------------- procedure Replace_Discriminants (Typ : Entity_Id; Decl : Node_Id) is function Process (N : Node_Id) return Traverse_Result; ------------- -- Process -- ------------- function Process (N : Node_Id) return Traverse_Result is Comp : Entity_Id; begin if Nkind (N) = N_Discriminant_Specification then Comp := First_Discriminant (Typ); while Present (Comp) loop if Original_Record_Component (Comp) = Defining_Identifier (N) or else Chars (Comp) = Chars (Defining_Identifier (N)) then Set_Defining_Identifier (N, Comp); exit; end if; Next_Discriminant (Comp); end loop; elsif Nkind (N) = N_Variant_Part then Comp := First_Discriminant (Typ); while Present (Comp) loop if Original_Record_Component (Comp) = Entity (Name (N)) or else Chars (Comp) = Chars (Name (N)) then -- Make sure to preserve the type coming from the parent on -- the Name, even if the subtype of the discriminant can be -- constrained, so that discrete choices inherited from the -- parent in the variant part are not flagged as violating -- the constraints of the subtype. declare Typ : constant Entity_Id := Etype (Name (N)); begin Rewrite (Name (N), New_Occurrence_Of (Comp, Sloc (N))); Set_Etype (Name (N), Typ); end; exit; end if; Next_Discriminant (Comp); end loop; end if; return OK; end Process; procedure Replace is new Traverse_Proc (Process); -- Start of processing for Replace_Discriminants begin Replace (Decl); end Replace_Discriminants; ------------------------------- -- Set_Completion_Referenced -- ------------------------------- procedure Set_Completion_Referenced (E : Entity_Id) is begin -- If in main unit, mark entity that is a completion as referenced, -- warnings go on the partial view when needed. if In_Extended_Main_Source_Unit (E) then Set_Referenced (E); end if; end Set_Completion_Referenced; --------------------- -- Set_Default_SSO -- --------------------- procedure Set_Default_SSO (T : Entity_Id) is begin case Opt.Default_SSO is when ' ' => null; when 'L' => Set_SSO_Set_Low_By_Default (T, True); when 'H' => Set_SSO_Set_High_By_Default (T, True); when others => raise Program_Error; end case; end Set_Default_SSO; --------------------- -- Set_Fixed_Range -- --------------------- -- The range for fixed-point types is complicated by the fact that we -- do not know the exact end points at the time of the declaration. This -- is true for three reasons: -- A size clause may affect the fudging of the end-points. -- A small clause may affect the values of the end-points. -- We try to include the end-points if it does not affect the size. -- This means that the actual end-points must be established at the -- point when the type is frozen. Meanwhile, we first narrow the range -- as permitted (so that it will fit if necessary in a small specified -- size), and then build a range subtree with these narrowed bounds. -- Set_Fixed_Range constructs the range from real literal values, and -- sets the range as the Scalar_Range of the given fixed-point type entity. -- The parent of this range is set to point to the entity so that it is -- properly hooked into the tree (unlike normal Scalar_Range entries for -- other scalar types, which are just pointers to the range in the -- original tree, this would otherwise be an orphan). -- The tree is left unanalyzed. When the type is frozen, the processing -- in Freeze.Freeze_Fixed_Point_Type notices that the range is not -- analyzed, and uses this as an indication that it should complete -- work on the range (it will know the final small and size values). procedure Set_Fixed_Range (E : Entity_Id; Loc : Source_Ptr; Lo : Ureal; Hi : Ureal) is S : constant Node_Id := Make_Range (Loc, Low_Bound => Make_Real_Literal (Loc, Lo), High_Bound => Make_Real_Literal (Loc, Hi)); begin Set_Scalar_Range (E, S); Set_Parent (S, E); -- Before the freeze point, the bounds of a fixed point are universal -- and carry the corresponding type. Set_Etype (Low_Bound (S), Universal_Real); Set_Etype (High_Bound (S), Universal_Real); end Set_Fixed_Range; ---------------------------------- -- Set_Scalar_Range_For_Subtype -- ---------------------------------- procedure Set_Scalar_Range_For_Subtype (Def_Id : Entity_Id; R : Node_Id; Subt : Entity_Id) is Kind : constant Entity_Kind := Ekind (Def_Id); begin -- Defend against previous error if Nkind (R) = N_Error then return; end if; Set_Scalar_Range (Def_Id, R); -- We need to link the range into the tree before resolving it so -- that types that are referenced, including importantly the subtype -- itself, are properly frozen (Freeze_Expression requires that the -- expression be properly linked into the tree). Of course if it is -- already linked in, then we do not disturb the current link. if No (Parent (R)) then Set_Parent (R, Def_Id); end if; -- Reset the kind of the subtype during analysis of the range, to -- catch possible premature use in the bounds themselves. Mutate_Ekind (Def_Id, E_Void); Process_Range_Expr_In_Decl (R, Subt, Subtyp => Def_Id); Mutate_Ekind (Def_Id, Kind); end Set_Scalar_Range_For_Subtype; -------------------------------------------------------- -- Set_Stored_Constraint_From_Discriminant_Constraint -- -------------------------------------------------------- procedure Set_Stored_Constraint_From_Discriminant_Constraint (E : Entity_Id) is begin -- Make sure set if encountered during Expand_To_Stored_Constraint Set_Stored_Constraint (E, No_Elist); -- Give it the right value if Is_Constrained (E) and then Has_Discriminants (E) then Set_Stored_Constraint (E, Expand_To_Stored_Constraint (E, Discriminant_Constraint (E))); end if; end Set_Stored_Constraint_From_Discriminant_Constraint; -------------------------- -- Should_Build_Subtype -- -------------------------- function Should_Build_Subtype (T : Entity_Id) return Boolean is function Default_Discriminant_Values_Known_At_Compile_Time (T : Entity_Id) return Boolean; -- For an unconstrained type T, return False if the given type has a -- discriminant with default value not known at compile time. Return -- True otherwise. --------------------------------------------------------- -- Default_Discriminant_Values_Known_At_Compile_Time -- --------------------------------------------------------- function Default_Discriminant_Values_Known_At_Compile_Time (T : Entity_Id) return Boolean is Discr : Entity_Id; DDV : Node_Id; begin -- If the type has no discriminant, we know them all at compile time if not Has_Discriminants (T) then return True; end if; -- The type has discriminants, check that none of them has a default -- value not known at compile time. Discr := First_Discriminant (T); while Present (Discr) loop DDV := Discriminant_Default_Value (Discr); if Present (DDV) and then not Compile_Time_Known_Value (DDV) then return False; end if; Next_Discriminant (Discr); end loop; return True; end Default_Discriminant_Values_Known_At_Compile_Time; -- Start of processing for Should_Build_Subtype begin if Is_Constrained (T) then -- We won't build a new subtype if T is constrained return False; end if; if not Default_Discriminant_Values_Known_At_Compile_Time (T) then -- This is a special case of definite subtypes. To allocate a -- specific size to the subtype, we need to know the value at compile -- time. This might not be the case if the default value is the -- result of a function. In that case, the object might be definite -- and limited but the needed size might not be statically known or -- too tricky to obtain. In that case, we will not build the subtype. return False; end if; return Is_Definite_Subtype (T) and then Is_Limited_View (T); end Should_Build_Subtype; ------------------------------------- -- Signed_Integer_Type_Declaration -- ------------------------------------- procedure Signed_Integer_Type_Declaration (T : Entity_Id; Def : Node_Id) is Implicit_Base : Entity_Id; Base_Typ : Entity_Id; Lo_Val : Uint; Hi_Val : Uint; Errs : Boolean := False; Lo : Node_Id; Hi : Node_Id; function Can_Derive_From (E : Entity_Id) return Boolean; -- Determine whether given bounds allow derivation from specified type procedure Check_Bound (Expr : Node_Id); -- Check bound to make sure it is integral and static. If not, post -- appropriate error message and set Errs flag --------------------- -- Can_Derive_From -- --------------------- -- Note we check both bounds against both end values, to deal with -- strange types like ones with a range of 0 .. -12341234. function Can_Derive_From (E : Entity_Id) return Boolean is Lo : constant Uint := Expr_Value (Type_Low_Bound (E)); Hi : constant Uint := Expr_Value (Type_High_Bound (E)); begin return Lo <= Lo_Val and then Lo_Val <= Hi and then Lo <= Hi_Val and then Hi_Val <= Hi; end Can_Derive_From; ----------------- -- Check_Bound -- ----------------- procedure Check_Bound (Expr : Node_Id) is begin -- If a range constraint is used as an integer type definition, each -- bound of the range must be defined by a static expression of some -- integer type, but the two bounds need not have the same integer -- type (Negative bounds are allowed.) (RM 3.5.4) if not Is_Integer_Type (Etype (Expr)) then Error_Msg_N ("integer type definition bounds must be of integer type", Expr); Errs := True; elsif not Is_OK_Static_Expression (Expr) then Flag_Non_Static_Expr ("non-static expression used for integer type bound!", Expr); Errs := True; -- Otherwise the bounds are folded into literals elsif Is_Entity_Name (Expr) then Fold_Uint (Expr, Expr_Value (Expr), True); end if; end Check_Bound; -- Start of processing for Signed_Integer_Type_Declaration begin -- Create an anonymous base type Implicit_Base := Create_Itype (E_Signed_Integer_Type, Parent (Def), T, 'B'); -- Analyze and check the bounds, they can be of any integer type Lo := Low_Bound (Def); Hi := High_Bound (Def); -- Arbitrarily use Integer as the type if either bound had an error if Hi = Error or else Lo = Error then Base_Typ := Any_Integer; Set_Error_Posted (T, True); Errs := True; -- Here both bounds are OK expressions else Analyze_And_Resolve (Lo, Any_Integer); Analyze_And_Resolve (Hi, Any_Integer); Check_Bound (Lo); Check_Bound (Hi); if Errs then Hi := Type_High_Bound (Standard_Long_Long_Long_Integer); Lo := Type_Low_Bound (Standard_Long_Long_Long_Integer); end if; -- Find type to derive from Lo_Val := Expr_Value (Lo); Hi_Val := Expr_Value (Hi); if Can_Derive_From (Standard_Short_Short_Integer) then Base_Typ := Base_Type (Standard_Short_Short_Integer); elsif Can_Derive_From (Standard_Short_Integer) then Base_Typ := Base_Type (Standard_Short_Integer); elsif Can_Derive_From (Standard_Integer) then Base_Typ := Base_Type (Standard_Integer); elsif Can_Derive_From (Standard_Long_Integer) then Base_Typ := Base_Type (Standard_Long_Integer); elsif Can_Derive_From (Standard_Long_Long_Integer) then Check_Restriction (No_Long_Long_Integers, Def); Base_Typ := Base_Type (Standard_Long_Long_Integer); elsif Can_Derive_From (Standard_Long_Long_Long_Integer) then Check_Restriction (No_Long_Long_Integers, Def); Base_Typ := Base_Type (Standard_Long_Long_Long_Integer); else Base_Typ := Base_Type (Standard_Long_Long_Long_Integer); Error_Msg_N ("integer type definition bounds out of range", Def); Hi := Type_High_Bound (Standard_Long_Long_Long_Integer); Lo := Type_Low_Bound (Standard_Long_Long_Long_Integer); end if; end if; -- Set the type of the bounds to the implicit base: we cannot set it to -- the new type, because this would be a forward reference for the code -- generator and, if the original type is user-defined, this could even -- lead to spurious semantic errors. Furthermore we do not set it to be -- universal, because this could make it much larger than needed here. if not Errs then Set_Etype (Lo, Implicit_Base); Set_Etype (Hi, Implicit_Base); end if; -- Complete both implicit base and declared first subtype entities. The -- inheritance of the rep item chain ensures that SPARK-related pragmas -- are not clobbered when the signed integer type acts as a full view of -- a private type. Set_Etype (Implicit_Base, Base_Typ); Set_Size_Info (Implicit_Base, Base_Typ); Set_RM_Size (Implicit_Base, RM_Size (Base_Typ)); Set_First_Rep_Item (Implicit_Base, First_Rep_Item (Base_Typ)); Set_Scalar_Range (Implicit_Base, Scalar_Range (Base_Typ)); Mutate_Ekind (T, E_Signed_Integer_Subtype); Set_Etype (T, Implicit_Base); Set_Size_Info (T, Implicit_Base); Inherit_Rep_Item_Chain (T, Implicit_Base); Set_Scalar_Range (T, Def); Set_RM_Size (T, UI_From_Int (Minimum_Size (T))); Set_Is_Constrained (T); end Signed_Integer_Type_Declaration; end Sem_Ch3;