summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>2005-06-16 08:32:47 +0000
committercharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>2005-06-16 08:32:47 +0000
commitaad6babd3202684e69d09d60051b89b59092cc2d (patch)
tree59a6d971ec99b14088954383ecddf8339a1c0e07
parent970e0382740ebed49eea06020812dcc57ffdbd71 (diff)
downloadgcc-aad6babd3202684e69d09d60051b89b59092cc2d.tar.gz
2005-06-14 Gary Dismukes <dismukes@adacore.com>
Javier Miranda <miranda@adacore.com> Ed Schonberg <schonberg@adacore.com> Hristian Kirtchev <kirtchev@adacore.com> * exp_ch4.adb (Expand_Allocator_Expression): When an initialized allocator's designated type is a class-wide type, and compiling for Ada 2005, emit a run-time check that the accessibility level of the type given in the allocator's expression is not deeper than the level of the allocator's access type. (Tagged_Membership): Modified to gives support to abstract interface types. * a-tags.ads, a-tags.adb (type Type_Specific_Data): Add component Access_Level. (Descendant_Tag): New predefined function (Is_Descendant_At_Same_Level): New predefined function (Get_Access_Level): New private function (Set_Access_Level): New private procedure (IW_Membership): New function. Given the tag of an object and the tag associated with an interface, evaluate if the object implements the interface. (Register_Interface_Tag): New procedure used to initialize the table of interfaces used by the IW_Membership function. (Set_Offset_To_Top): Initialize the Offset_To_Top field in the prologue of the dispatch table. (Inherit_TSD): Modified to copy the table of ancestor tags plus the table of interfaces of the parent. (Expanded_Name): Raise Tag_Error if the passed tag equals No_Tag. (External_Tag): Raise Tag_Error if the passed tag equals No_Tag. (Parent_Tag): Return No_Tag in the case of a root-level tagged type, and raise Tag_Error if the passed tag equalis No_Tag, to conform with Ada 2005 semantics for the new predefined function. * exp_attr.adb (Expand_N_Attribute, case Attribute_Input): Generate call to Descendant_Tag rather than Internal_Tag. (Expand_N_Attribute, case Attribute_Output): Emit a check to ensure that the accessibility level of the attribute's Item parameter is not deeper than the level of the attribute's prefix type. Tag_Error is raised if the check fails. The check is only emitted for Ada_05. (Find_Stream_Subprogram): If a TSS exists on the type itself for the requested stream attribute, use it. (Expand_N_Attribute_Reference): If the designated type is an interface then rewrite the referenced object as a conversion to force the displacement of the pointer to the secondary dispatch table. (Expand_N_Attribute_Reference, case 'Constrained): Return false if this is a dereference of an object with a constrained partial view. * exp_ch5.adb (Expand_N_Return_Statement): When a function's result type is a class-wide type, emit a run-time check that the accessibility level of the returned object is not deeper than the level of the function's master (only when compiling for Ada 2005). * exp_disp.ads, exp_disp.adb (Ada_Actions, Action_Is_Proc, Action_Nb_Arg): Add entries for new Get_Access_Level and Set_Access_Level routines in these tables. (Make_DT): Generate a call to set the accessibility level of the tagged type in its TSD. (Make_DT): Code cleanup. The functionality of generating all the secondary dispatch tables has been moved to freeze_record_type. (Make_Abstract_Interface_DT): Minor code cleanup. (Set_All_DT_Position): Code cleanup. As part of the code cleanup this subprogram implements a new algorithm that provides the same functionality and it is more clear in case of primitives associated with abstract interfaces. (Set_All_Interfaces_DTC_Entity): Removed. As part of the code clean up, the functionality of this subprogram is now provided by Set_All_DT_Position. (Write_DT): New subprogram: a debugging procedure designed to be called within gdb to display the dispatch tables associated with a tagged type. (Collect_All_Interfaces): New subprogram that collects the whole list of interfaces that are directly or indirectly implemented by a tagged type. (Default_Prim_Op_Position): New subprogram that returns the fixed position in the dispatch table of the default primitive operations. (Expand_Interface_Actuals): New subprogram to generate code that displaces all the actuals corresponding to class-wide interfaces to reference the interface tag of the actual object. (Expand_Interface_Conversion): New subprogram. Reference the base of the object to give access to the interface tag associated with the secondary dispatch table. (Expand_Interface_Thunk): New subprogram that generates the code of the thunk. This is required for compatibility with the C+ ABI. (Make_Abstract_Interface_DT): New subprogram that generate the declarations for the secondary dispatch tables associated with an abstract interface. (Set_All_Interfaces_DTC_Entity): New subprogram that sets the DTC_Entity attribute for each primitive operation covering interface subprograms (Expand_Dispatching_Call, Fill_DT_Entry, Make_DT, Set_All_DT_Position): These subprograms were upgraded to give support to abstract interfaces * rtsfind.ads (type RE_Id): Add RE_Descendant_Tag, RE_Is_Descendant_At_Same_Level, RE_Get_Access_Level, and RE_Set_Access_Level. (RE_Unit_Table): Add entries for new Ada.Tags operations. Add support to call the followig new run-time subprograms: IW_Membership, Register_Interface_Tag, and Set_Offset_To_Top * sem_ch3.adb (Constant_Redeclaration): Allow a deferred constant to match its full declaration when both have an access definition with statically matching designated subtypes. (Analyze_Component_Declaration): Delete commented out code that was incorrectly setting the scope of an anonymous access component's type. (Process_Discriminants): Set Is_Local_Anonymous_Access for the type of an access discriminant when the containing type is nonlimited. (Make_Incomplete_Type_Declaration): Create an incomplete type declaration for a record type that includes self-referential access components. (Check_Anonymous_Access_Types): Before full analysis of a record type declaration, create anonymous access types for each self-referential access component. (Analyze_Component_Declaration, Array_Type_Declaration): Indicate that an access component in this context is a Local_Anonymous_Access, for proper accessibility checks. (Access_Definition): Set properly the scope of the anonymous access type created for a stand-alone access object. (Find_Type_Of_Object): An object declaration may be given with an access definition. (Complete_Subprograms_Derivation): New subprogram used to complete type derivation of private tagged types implementing interfaces. In this case some interface primitives may have been overriden with the partial-view and, instead of re-calculating them, they are included in the list of primitive operations of the full-view. (Build_Derived_Record_Type): Modified to give support to private types implemening interfaces. (Access_Definition): Reject ALL on anonymous access types. (Build_Derived_Record_Type): In the case of Ada 2005, allow a tagged type derivation to occur at a deeper accessibility level than the parent type. For the case of derivation within a generic body however, disallow the derivation if the derived type has an ancestor that is a formal type declared in the formal part of an enclosing generic. (Analyze_Object_Declaration): For protected objects, remove the check that they cannot contain interrupt handlers if not declared at library level. (Add_Interface_Tag_Components): New subprogram to add the tag components corresponding to all the abstract interface types implemented by a record type or a derived record type. (Analyze_Private_Extension_Declaration, Build_Derived_Record_Type, Derived_Type_Declaration, Find_Type_Name, Inherit_Components, Process_Full_View, Record_Type_Declaration): Modified to give support to abstract interface types (Collect_Interfaces): New subprogram that collects the list of interfaces that are not already implemented by the ancestors (Process_Full_View): Set flag Has_Partial_Constrained_View appropriately when partial view has no discriminants and full view has defaults. (Constrain_Access): Reject a constraint on a general access type if the discriminants of the designated type have defaults. (Access_Subprogram_Declaration): Associate the Itype node with the inner full-type declaration or subprogram spec. This is required to handle nested anonymous declarations. (Analyze_Private_Extension_Declaration, Build_Derived_Record_Type, Derived_Type_Declaration, Find_Type_Name, Inherit_Components, Process_Full_View, Record_Type_Declaration): Modified to give support to abstract interface types (Derive_Subprograms): Addition of a new formal to indicate if we are in the case of an abstact-interface derivation (Find_Type_Of_Subtype_Indic): Moved from the body of the package to the specification because it is requied to analyze all the identifiers found in a list of interfaces * debug.adb: Complete documentation of flag "-gnatdZ" * exp_ch3.adb: Implement config version of persistent_bss pragma (Check_Stream_Attributes): Use Stream_Attribute_Available instead of testing for TSS presence to properly enforce visibility rules. (Freeze_Record_Type): Code cleanup. Modified to call the subprogram Make_Abstract_Interfaces_DT to generate the secondary tables associated with abstract interfaces. (Build_Init_Procedure): Modified to initialize all the tags corresponding. (Component_Needs_Simple_Initialization): Similar to other tags, interface tags do not need initialization. (Freeze_Record_Type): Modified to give support to abstract interface types. (Expand_N_Object_Declaration): Do not generate an initialization for a scalar temporary marked as internal. * exp_ch6.adb (Add_Simple_Call_By_Copy_Code): Handle properly an in-out parameter that is a component in an initialization procedure, whose constraint might depend on discriminants, and that may be misaligned because of packing or representation clauses. (Is_Legal_Copy): New predicate to determine whether a possibly misaligned in-out actual can actually be passed by copy/return. This is an error in case the type is by_reference, and a warning if this is the consequence of a DEC import pragma on the subprogram. (Expand_Call, Freeze_Subprogram): Modified to give support to abstract interface types (Expand_Inlined_Call): Mark temporary generated for the return value as internal, so that no useless scalar normalization is generated for it. (Expand_N_Subprogram_Declaration): Save unanalyzed body so calls to null procedure can always be inlined. (Expand_N_Subprogram_Declaration): If this is the declaration of a null procedure, generate an explicit empty body for it. * exp_util.ads, exp_util.adb (Find_Interface_ADT): New subprogram. Given a type implementing an interface, returns the corresponding access_disp_table value. (Find_Interface_Tag): New subprogram. Given a type implementing an interface, returns the record component containing the tag of the interface. (Find_Interface_Tag): New overloaded subprogram. Subsidiary to the previous ones that return the corresponding tag and access_disp_table entities. (Is_Predefined_Dispatching_Operation): Determines if a subprogram is a predefined primitive operation. (Expand_Subtype_From_Expr): If the expression is a selected component within an initialization procedure, compute its actual subtype, because the component may depend on the discriminants of the enclosing record. * i-cpp.ads, i-cpp.adb: This package has been left available for compatibility with previous versions of the frontend. As part of the new layout this is now a dummy package that uses declarations available at a-tags.ads * par-ch3.adb (P_Identifier_Declarations): Give an error for use of "constant access" and "aliased [constant] access" when not compiling with -gnat05. Suppress Ada 2005 keyword warning if -gnatwY used (P_Identifier_Declarations): Add support for object declarations with access definitions. (Private_Extension_Declaration): Complete the documentation (P_Derived_Type_Def_Or_Private_Ext_Decl): Fill the inteface_list attribute in case of private extension declaration (P_Type_Declaration): Mark as "abstract" the type declarations corresponding with protected, synchronized and task interfaces (P_Declarative_Items): "not" and "overriding" are overriding indicators for a subprogram or instance declaration. * sem_ch12.adb (Analyze_Subprogram_Instantiation): Verify that an instantiation that is a dispatching operation has controlling access parameters that are null excluding. Save and restore Ada_Version_Explicit, for implementation of AI-362 (Validate_Derived_Type_Instance): Add check for abstract interface types. (Analyze_Formal_Package): Establish Instantiation source for the copy of the generic that is created to represent the formal package. (Analyze_Package_Instantiation): Instantiate body immediately if the package is a predefined unit that contains inlined subprograms, and we are compiling for a Configurable_Run_Time. (Instantiate_Formal_Subprogram): Indicate that null default subprogram If the program has a null default, generate an empty body for it. * sem_ch6.adb, sem_ch9.adb (Analyze_Subprograms_Declaration): Update error message condition, null procedures are correctly detected now. (New_Overloaded_Entity): Bypass trivial overriding indicator check for subprograms in the context of protected types. Instead, the indicator is examined in Sem_Ch9 while analysing the subprogram declaration. (Check_Overriding_Indicator): Check consistency of overriding indicator on subprogram stubs as well. (Analyze_Subprogram_Declaration): Diagnose null procedures declared at the library level. (Analize_Subprogram_Specification): When analyzing a subprogram in which the type of the first formal is a concurrent type, replace this type by the corresponding record type. (Analyze_Subprogram_Body): Undo the previous work. (Analyze_Procedure_Call): If the call has the form Object.Op, the analysis of the prefix ends up analyzing the call itself, after which we are done. (Has_Interface_Formals): New subprogram subsidiary to analyze subprogram_specification that returns true if some non class-wide interface subprogram is found (New_Overloaded_Entity): Modified to give support to abstract interface types (Conforming_Types): In Ada 2005 mode, conformance checking of anonymous access to subprograms must be recursive. (Is_Unchecked_Conversion): Improve the test that recognizes instantiations of Unchecked_Conversion, and allows them in bodies that are to be inlined by the front-end. When the body comes from an instantiation, a reference to Unchecked_Conversion will be an Expanded_Name, even though the body has not been analyzed yet. Replace Is_Overriding and Not_Overriding in subprogram_indication with Must_Override and Must_Not_Override, to better express intent of AI. (Analyze_Subprogram_Body): If an overriding indicator is given, check that it is consistent with the overrinding status of the subprogram at this point. (Analyze_Subprogram_Declaration): Indicate that a null procedure is always inlined. If the subprogram is a null procedure, indicate that it does not need a completion. * sem_disp.adb (Check_Controlling_Type): Give support to entities available through limited-with clauses. (Check_Dispatching_Operation): A stub acts like a body, and therefore is allowed as the last primitive of a tagged type if it has no previous spec. (Override_Dispatching_Operation, Check_Dispatching_Operation): Modified to give support to abstract interface types * sem_res.adb (Valid_Conversion): Perform an accessibility level check in the case where the target type is an anonymous access type of an object or component (that is, when Is_Local_Anonymous_Access is true). Prevent the special checks for conversions of access discriminants in the case where the discriminant belongs to a nonlimited type, since such discriminants have their accessibility level defined in the same way as a normal component of an anonymous access type. (Resolve_Allocator): When an allocator's designated type is a class-wide type, check that the accessibility level of type given in the allocator's expression or subtype indication is not statically deeper than the level of the allocator's access type. (Check_Discriminant_Use): Diagnose discriminant given by an expanded name in a discriminant constraint of a record component. (Resolve_Explicit_Dereference): Do not check whether the type is incomplete when the dereference is a use of an access discriminant in an initialization procedure. (Resolve_Type_Conversion): Handle conversions to abstract interface types. (Valid_Tagged_Conversion): The conversion of a tagged type to an abstract interface type is always valid. (Valid_Conversion): Modified to give support to abstract interface types (Resolve_Actuals): Enable full error reporting on view conversions between unrelated by_reference array types. The rule for view conversions of arrays with aliased components is weakened in Ada 2005. Call to obsolescent subprogram is now considered to be a violation of pragma Restrictions (No_Obsolescent_Features). (Check_Direct_Boolean_Operator): If the boolean operation has been constant-folded, there is nothing to check. (Resolve_Comparison_Op, Resolve_Equality_Op, Resolve_Boolean_Op): Defer check on possible violation of restriction No_Direct_Boolean_Operators until after expansion of operands, to prevent spurious errors when operation is constant-folded. * sem_type.ads, sem_type.adb (Covers, Intersect_Types, Specific_Type, Has_Compatible_Type): Modified to give support to abstract interface types. (Interface_Present_In_Ancestor): New function to theck if some ancestor of a given type implements a given interface * sem_ch4.adb (Analyze_Call): Handle properly an indirect call whose prefix is a parameterless function that returns an access_to_procedure. (Transform_Object_Operation): Handle properly function calls of the form Obj.Op (X), which prior to analysis appear as indexed components. (Analyze_One_Call): Complete the error notification to help new Ada 2005 users. (Analyze_Allocator): For an allocator without an initial value, where the designated type has a constrained partial view, a discriminant constraint is illegal. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@101024 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ada/a-tags.adb313
-rw-r--r--gcc/ada/a-tags.ads75
-rw-r--r--gcc/ada/debug.adb2
-rw-r--r--gcc/ada/exp_attr.adb277
-rw-r--r--gcc/ada/exp_ch3.adb157
-rw-r--r--gcc/ada/exp_ch4.adb85
-rw-r--r--gcc/ada/exp_ch5.adb27
-rw-r--r--gcc/ada/exp_ch6.adb205
-rw-r--r--gcc/ada/exp_disp.adb1599
-rw-r--r--gcc/ada/exp_disp.ads50
-rw-r--r--gcc/ada/exp_util.adb276
-rw-r--r--gcc/ada/exp_util.ads421
-rw-r--r--gcc/ada/i-cpp.adb354
-rw-r--r--gcc/ada/i-cpp.ads171
-rw-r--r--gcc/ada/par-ch3.adb116
-rw-r--r--gcc/ada/rtsfind.ads20
-rw-r--r--gcc/ada/sem_ch12.adb138
-rw-r--r--gcc/ada/sem_ch3.adb1609
-rw-r--r--gcc/ada/sem_ch4.adb77
-rw-r--r--gcc/ada/sem_ch6.adb403
-rw-r--r--gcc/ada/sem_ch9.adb414
-rw-r--r--gcc/ada/sem_disp.adb115
-rw-r--r--gcc/ada/sem_res.adb581
-rw-r--r--gcc/ada/sem_type.adb183
-rw-r--r--gcc/ada/sem_type.ads9
25 files changed, 5998 insertions, 1679 deletions
diff --git a/gcc/ada/a-tags.adb b/gcc/ada/a-tags.adb
index df4e58e81f6..1899c6c3024 100644
--- a/gcc/ada/a-tags.adb
+++ b/gcc/ada/a-tags.adb
@@ -1,6 +1,6 @@
------------------------------------------------------------------------------
-- --
--- GNAT RUNTIME COMPONENTS --
+-- GNAT RUN-TIME COMPONENTS --
-- --
-- A D A . T A G S --
-- --
@@ -33,6 +33,7 @@
with Ada.Exceptions;
with System.HTable;
+with System.Storage_Elements; use System.Storage_Elements;
pragma Elaborate_All (System.HTable);
@@ -57,10 +58,16 @@ package body Ada.Tags is
-- +-------------------+
-- | Rec Ctrler offset |
-- +-------------------+
+-- | Num_Interfaces |
+-- +-------------------+
-- | table of |
-- : ancestor :
-- | tags |
-- +-------------------+
+-- | table of |
+-- | interface |
+-- | tags |
+-- +-------------------+
subtype Cstring is String (Positive);
type Cstring_Ptr is access all Cstring;
@@ -71,32 +78,34 @@ package body Ada.Tags is
-- We suppress index checks because the declared size in the record below
-- is a dummy size of one (see below).
- type Wide_Boolean is new Boolean;
- -- This name should probably be changed sometime ??? and indeed probably
- -- this field could simply be of type Standard.Boolean.
-
type Type_Specific_Data is record
- Idepth : Natural;
- Expanded_Name : Cstring_Ptr;
- External_Tag : Cstring_Ptr;
- HT_Link : Tag;
- Remotely_Callable : Wide_Boolean;
- RC_Offset : SSE.Storage_Offset;
- Ancestor_Tags : Tag_Table (0 .. 1);
+ Idepth : Natural;
+ Access_Level : Natural;
+ Expanded_Name : Cstring_Ptr;
+ External_Tag : Cstring_Ptr;
+ HT_Link : Tag;
+ Remotely_Callable : Boolean;
+ RC_Offset : SSE.Storage_Offset;
+ Num_Interfaces : Natural;
+ Tags_Table : Tag_Table (Natural);
+
+ -- The size of the Tags_Table array actually depends on the tagged type
+ -- to which it applies. The compiler ensures that has enough space to
+ -- store all the entries of the two tables phisically stored there: the
+ -- "table of ancestor tags" and the "table of interface tags". For this
+ -- purpose we are using the same mechanism as for the Prims_Ptr array in
+ -- the Dispatch_Table record. See comments below for more details.
+
end record;
- -- The size of the Ancestor_Tags array actually depends on the tagged type
- -- to which it applies. We are using the same mechanism as for the
- -- Prims_Ptr array in the Dispatch_Table record. See comments below for
- -- more details.
type Dispatch_Table is record
- -- Offset_To_Top : Integer := 0;
+ -- Offset_To_Top : Natural;
-- Typeinfo_Ptr : System.Address; -- Currently TSD is also here???
- Prims_Ptr : Address_Array (Positive);
+ Prims_Ptr : Address_Array (Positive);
end record;
-- Note on the commented out fields of the Dispatch_Table
- -- ------------------------------------------------------
+ --
-- According to the C++ ABI the components Offset_To_Top and Typeinfo_Ptr
-- are stored just "before" the dispatch table (that is, the Prims_Ptr
-- table), and they are referenced with negative offsets referring to the
@@ -106,7 +115,6 @@ package body Ada.Tags is
-- expander generates a Prims_Ptr table that has enough space for these
-- additional components, and generates code that displaces the _Tag to
-- point after these components.
- -- -----------------------------------------------------------------------
-- The size of the Prims_Ptr array actually depends on the tagged type to
-- which it applies. For each tagged type, the expander computes the
@@ -131,20 +139,20 @@ package body Ada.Tags is
-- Unchecked Conversions for String Fields --
---------------------------------------------
- function To_Cstring_Ptr is
- new Unchecked_Conversion (System.Address, Cstring_Ptr);
-
function To_Address is
new Unchecked_Conversion (Cstring_Ptr, System.Address);
- -----------------------------------------------------------
- -- Unchecked Conversions for the component offset_to_top --
- -----------------------------------------------------------
+ function To_Cstring_Ptr is
+ new Unchecked_Conversion (System.Address, Cstring_Ptr);
+
+ ------------------------------------------------
+ -- Unchecked Conversions for other components --
+ ------------------------------------------------
- type Int_Ptr is access Integer;
+ type Storage_Offset_Ptr is access System.Storage_Elements.Storage_Offset;
- function To_Int_Ptr is
- new Unchecked_Conversion (System.Address, Int_Ptr);
+ function To_Storage_Offset_Ptr is
+ new Unchecked_Conversion (System.Address, Storage_Offset_Ptr);
-----------------------
-- Local Subprograms --
@@ -154,7 +162,8 @@ package body Ada.Tags is
-- Length of string represented by the given pointer (treating the string
-- as a C-style string, which is Nul terminated).
- function Offset_To_Top (T : Tag) return Integer;
+ function Offset_To_Top
+ (T : Tag) return System.Storage_Elements.Storage_Offset;
-- Returns the current value of the offset_to_top component available in
-- the prologue of the dispatch table.
@@ -162,7 +171,6 @@ package body Ada.Tags is
-- Returns the current value of the typeinfo_ptr component available in
-- the prologue of the dispatch table.
- pragma Unreferenced (Offset_To_Top);
pragma Unreferenced (Typeinfo_Ptr);
-- These functions will be used for full compatibility with the C++ ABI
@@ -266,8 +274,9 @@ package body Ada.Tags is
-- Obj in Typ'Class
- -- Each dispatch table contains a reference to a table of ancestors
- -- (Ancestor_Tags) and a count of the level of inheritance "Idepth" .
+ -- Each dispatch table contains a reference to a table of ancestors (stored
+ -- in the first part of the Tags_Table) and a count of the level of
+ -- inheritance "Idepth".
-- Obj is in Typ'Class if Typ'Tag is in the table of ancestors that are
-- contained in the dispatch table referenced by Obj'Tag . Knowing the
@@ -280,16 +289,79 @@ package body Ada.Tags is
function CW_Membership (Obj_Tag : Tag; Typ_Tag : Tag) return Boolean is
Pos : constant Integer := TSD (Obj_Tag).Idepth - TSD (Typ_Tag).Idepth;
begin
- return Pos >= 0 and then TSD (Obj_Tag).Ancestor_Tags (Pos) = Typ_Tag;
+ return Pos >= 0 and then TSD (Obj_Tag).Tags_Table (Pos) = Typ_Tag;
end CW_Membership;
-------------------
+ -- IW_Membership --
+ -------------------
+
+ -- Canonical implementation of Classwide Membership corresponding to:
+
+ -- Obj in Iface'Class
+
+ -- Each dispatch table contains a table with the tags of all the
+ -- implemented interfaces.
+
+ -- Obj is in Iface'Class if Iface'Tag is found in the table of interfaces
+ -- that are contained in the dispatch table referenced by Obj'Tag.
+
+ function IW_Membership
+ (This : System.Address;
+ Iface_Tag : Tag) return Boolean
+ is
+ T : constant Tag := To_Tag_Ptr (This).all;
+ Obj_Base : constant System.Address := This - Offset_To_Top (T);
+ T_Base : constant Tag := To_Tag_Ptr (Obj_Base).all;
+
+ Obj_TSD : constant Type_Specific_Data_Ptr := TSD (T_Base);
+ Last_Id : constant Natural := Obj_TSD.Idepth + Obj_TSD.Num_Interfaces;
+ Id : Natural;
+
+ begin
+ if Obj_TSD.Num_Interfaces > 0 then
+ Id := Obj_TSD.Idepth + 1;
+ loop
+ if Obj_TSD.Tags_Table (Id) = Iface_Tag then
+ return True;
+ end if;
+
+ Id := Id + 1;
+ exit when Id > Last_Id;
+ end loop;
+ end if;
+
+ return False;
+ end IW_Membership;
+
+ --------------------
+ -- Descendant_Tag --
+ --------------------
+
+ function Descendant_Tag (External : String; Ancestor : Tag) return Tag is
+ Int_Tag : constant Tag := Internal_Tag (External);
+
+ begin
+ if not Is_Descendant_At_Same_Level (Int_Tag, Ancestor) then
+ raise Tag_Error;
+ end if;
+
+ return Int_Tag;
+ end Descendant_Tag;
+
+ -------------------
-- Expanded_Name --
-------------------
function Expanded_Name (T : Tag) return String is
- Result : constant Cstring_Ptr := TSD (T).Expanded_Name;
+ Result : Cstring_Ptr;
+
begin
+ if T = No_Tag then
+ raise Tag_Error;
+ end if;
+
+ Result := TSD (T).Expanded_Name;
return Result (1 .. Length (Result));
end Expanded_Name;
@@ -298,12 +370,27 @@ package body Ada.Tags is
------------------
function External_Tag (T : Tag) return String is
- Result : constant Cstring_Ptr := TSD (T).External_Tag;
+ Result : Cstring_Ptr;
begin
+ if T = No_Tag then
+ raise Tag_Error;
+ end if;
+
+ Result := TSD (T).External_Tag;
+
return Result (1 .. Length (Result));
end External_Tag;
----------------------
+ -- Get_Access_Level --
+ ----------------------
+
+ function Get_Access_Level (T : Tag) return Natural is
+ begin
+ return TSD (T).Access_Level;
+ end Get_Access_Level;
+
+ ----------------------
-- Get_External_Tag --
----------------------
@@ -318,8 +405,7 @@ package body Ada.Tags is
function Get_Prim_Op_Address
(T : Tag;
- Position : Positive) return System.Address
- is
+ Position : Positive) return System.Address is
begin
return T.Prims_Ptr (Position);
end Get_Prim_Op_Address;
@@ -339,7 +425,7 @@ package body Ada.Tags is
function Get_Remotely_Callable (T : Tag) return Boolean is
begin
- return TSD (T).Remotely_Callable = True;
+ return TSD (T).Remotely_Callable;
end Get_Remotely_Callable;
----------------
@@ -368,15 +454,23 @@ package body Ada.Tags is
begin
if Old_Tag /= null then
- Old_TSD_Ptr := TSD (Old_Tag);
+ Old_TSD_Ptr := TSD (Old_Tag);
New_TSD_Ptr.Idepth := Old_TSD_Ptr.Idepth + 1;
- New_TSD_Ptr.Ancestor_Tags (1 .. New_TSD_Ptr.Idepth) :=
- Old_TSD_Ptr.Ancestor_Tags (0 .. Old_TSD_Ptr.Idepth);
+ New_TSD_Ptr.Num_Interfaces := Old_TSD_Ptr.Num_Interfaces;
+
+ -- Copy the "table of ancestor tags" plus the "table of interfaces"
+ -- of the parent
+
+ New_TSD_Ptr.Tags_Table
+ (1 .. New_TSD_Ptr.Idepth + New_TSD_Ptr.Num_Interfaces)
+ := Old_TSD_Ptr.Tags_Table
+ (0 .. Old_TSD_Ptr.Idepth + Old_TSD_Ptr.Num_Interfaces);
else
- New_TSD_Ptr.Idepth := 0;
+ New_TSD_Ptr.Idepth := 0;
+ New_TSD_Ptr.Num_Interfaces := 0;
end if;
- New_TSD_Ptr.Ancestor_Tags (0) := New_Tag;
+ New_TSD_Ptr.Tags_Table (0) := New_Tag;
end Inherit_TSD;
------------------
@@ -410,6 +504,19 @@ package body Ada.Tags is
return Res;
end Internal_Tag;
+ ---------------------------------
+ -- Is_Descendant_At_Same_Level --
+ ---------------------------------
+
+ function Is_Descendant_At_Same_Level
+ (Descendant : Tag;
+ Ancestor : Tag) return Boolean
+ is
+ begin
+ return CW_Membership (Descendant, Ancestor)
+ and then TSD (Descendant).Access_Level = TSD (Ancestor).Access_Level;
+ end Is_Descendant_At_Same_Level;
+
------------
-- Length --
------------
@@ -425,6 +532,21 @@ package body Ada.Tags is
return Len - 1;
end Length;
+ -------------------
+ -- Offset_To_Top --
+ -------------------
+
+ function Offset_To_Top
+ (T : Tag) return System.Storage_Elements.Storage_Offset
+ is
+ Offset_To_Top_Ptr : constant Storage_Offset_Ptr :=
+ To_Storage_Offset_Ptr (To_Address (T)
+ - DT_Typeinfo_Ptr_Size
+ - DT_Offset_To_Top_Size);
+ begin
+ return Offset_To_Top_Ptr.all;
+ end Offset_To_Top;
+
-----------------
-- Parent_Size --
-----------------
@@ -439,12 +561,12 @@ package body Ada.Tags is
(Obj : System.Address;
T : Tag) return SSE.Storage_Count
is
- Parent_Tag : constant Tag := TSD (T).Ancestor_Tags (1);
+ Parent_Tag : constant Tag := TSD (T).Tags_Table (1);
-- The tag of the parent type through the dispatch table
F : constant Acc_Size := To_Acc_Size (Parent_Tag.Prims_Ptr (1));
-- Access to the _size primitive of the parent. We assume that
- -- it is always in the first slot of the distatch table
+ -- it is always in the first slot of the dispatch table
begin
-- Here we compute the size of the _parent field of the object
@@ -458,9 +580,57 @@ package body Ada.Tags is
function Parent_Tag (T : Tag) return Tag is
begin
- return TSD (T).Ancestor_Tags (1);
+ if T = No_Tag then
+ raise Tag_Error;
+ end if;
+
+ -- The Parent_Tag of a root-level tagged type is defined to be No_Tag.
+ -- The first entry in the Ancestors_Tags array will be null for such
+ -- a type, but it's better to be explicit about returning No_Tag in
+ -- this case.
+
+ if TSD (T).Idepth = 0 then
+ return No_Tag;
+ else
+ return TSD (T).Tags_Table (1);
+ end if;
end Parent_Tag;
+ ----------------------------
+ -- Register_Interface_Tag --
+ ----------------------------
+
+ procedure Register_Interface_Tag
+ (T : Tag;
+ Interface_T : Tag)
+ is
+ New_T_TSD : constant Type_Specific_Data_Ptr := TSD (T);
+ Index : Natural;
+ begin
+ -- Check if the interface is already registered
+
+ if New_T_TSD.Num_Interfaces > 0 then
+ declare
+ Id : Natural := New_T_TSD.Idepth + 1;
+ Last_Id : constant Natural := New_T_TSD.Idepth
+ + New_T_TSD.Num_Interfaces;
+ begin
+ loop
+ if New_T_TSD.Tags_Table (Id) = Interface_T then
+ return;
+ end if;
+
+ Id := Id + 1;
+ exit when Id > Last_Id;
+ end loop;
+ end;
+ end if;
+
+ New_T_TSD.Num_Interfaces := New_T_TSD.Num_Interfaces + 1;
+ Index := New_T_TSD.Idepth + New_T_TSD.Num_Interfaces;
+ New_T_TSD.Tags_Table (Index) := Interface_T;
+ end Register_Interface_Tag;
+
------------------
-- Register_Tag --
------------------
@@ -470,6 +640,15 @@ package body Ada.Tags is
External_Tag_HTable.Set (T);
end Register_Tag;
+ ----------------------
+ -- Set_Access_Level --
+ ----------------------
+
+ procedure Set_Access_Level (T : Tag; Value : Natural) is
+ begin
+ TSD (T).Access_Level := Value;
+ end Set_Access_Level;
+
-----------------------
-- Set_Expanded_Name --
-----------------------
@@ -488,6 +667,22 @@ package body Ada.Tags is
TSD (T).External_Tag := To_Cstring_Ptr (Value);
end Set_External_Tag;
+ -----------------------
+ -- Set_Offset_To_Top --
+ -----------------------
+
+ procedure Set_Offset_To_Top
+ (T : Tag;
+ Value : System.Storage_Elements.Storage_Offset)
+ is
+ Offset_To_Top_Ptr : constant Storage_Offset_Ptr :=
+ To_Storage_Offset_Ptr (To_Address (T)
+ - DT_Typeinfo_Ptr_Size
+ - DT_Offset_To_Top_Size);
+ begin
+ Offset_To_Top_Ptr.all := Value;
+ end Set_Offset_To_Top;
+
-------------------------
-- Set_Prim_Op_Address --
-------------------------
@@ -495,8 +690,7 @@ package body Ada.Tags is
procedure Set_Prim_Op_Address
(T : Tag;
Position : Positive;
- Value : System.Address)
- is
+ Value : System.Address) is
begin
T.Prims_Ptr (Position) := Value;
end Set_Prim_Op_Address;
@@ -516,11 +710,7 @@ package body Ada.Tags is
procedure Set_Remotely_Callable (T : Tag; Value : Boolean) is
begin
- if Value then
- TSD (T).Remotely_Callable := True;
- else
- TSD (T).Remotely_Callable := False;
- end if;
+ TSD (T).Remotely_Callable := Value;
end Set_Remotely_Callable;
-------------
@@ -528,31 +718,17 @@ package body Ada.Tags is
-------------
procedure Set_TSD (T : Tag; Value : System.Address) is
- use type System.Storage_Elements.Storage_Offset;
TSD_Ptr : constant Addr_Ptr :=
To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
begin
TSD_Ptr.all := Value;
end Set_TSD;
- -------------------
- -- Offset_To_Top --
- -------------------
-
- function Offset_To_Top (T : Tag) return Integer is
- use type System.Storage_Elements.Storage_Offset;
- TSD_Ptr : constant Int_Ptr :=
- To_Int_Ptr (To_Address (T) - DT_Prologue_Size);
- begin
- return TSD_Ptr.all;
- end Offset_To_Top;
-
------------------
-- Typeinfo_Ptr --
------------------
function Typeinfo_Ptr (T : Tag) return System.Address is
- use type System.Storage_Elements.Storage_Offset;
TSD_Ptr : constant Addr_Ptr :=
To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
begin
@@ -564,7 +740,6 @@ package body Ada.Tags is
---------
function TSD (T : Tag) return Type_Specific_Data_Ptr is
- use type System.Storage_Elements.Storage_Offset;
TSD_Ptr : constant Addr_Ptr :=
To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
begin
diff --git a/gcc/ada/a-tags.ads b/gcc/ada/a-tags.ads
index 0d517a0ac07..6532c1a7e32 100644
--- a/gcc/ada/a-tags.ads
+++ b/gcc/ada/a-tags.ads
@@ -40,17 +40,30 @@ with System.Storage_Elements;
with Unchecked_Conversion;
package Ada.Tags is
+pragma Preelaborate_05 (Tags);
+-- In accordance with Ada 2005 AI-362
pragma Elaborate_Body;
+ -- We need a dummy body to solve bootstrap path issues (why ???)
type Tag is private;
+ No_Tag : constant Tag;
+
function Expanded_Name (T : Tag) return String;
function External_Tag (T : Tag) return String;
function Internal_Tag (External : String) return Tag;
+ function Descendant_Tag (External : String; Ancestor : Tag) return Tag;
+
+ function Is_Descendant_At_Same_Level
+ (Descendant : Tag;
+ Ancestor : Tag) return Boolean;
+
+ function Parent_Tag (T : Tag) return Tag;
+
Tag_Error : exception;
private
@@ -81,6 +94,9 @@ private
type Dispatch_Table;
type Tag is access all Dispatch_Table;
+ type Interface_Tag is access all Dispatch_Table;
+
+ No_Tag : constant Tag := null;
type Type_Specific_Data;
type Type_Specific_Data_Ptr is access all Type_Specific_Data;
@@ -91,6 +107,16 @@ private
-- Given the tag of an object and the tag associated to a type, return
-- true if Obj is in Typ'Class.
+ function IW_Membership
+ (This : System.Address;
+ Iface_Tag : Tag) return Boolean;
+ -- Ada 2005 (AI-251): Given the tag of an object and the tag associated
+ -- with an interface, return true if Obj is in Iface'Class.
+
+ function Get_Access_Level (T : Tag) return Natural;
+ -- Given the tag associated with a type, returns the accessibility level
+ -- of the type.
+
function Get_External_Tag (T : Tag) return System.Address;
-- Retrieve the address of a null terminated string containing
-- the external name
@@ -115,8 +141,8 @@ private
-- Return the value previously set by Set_Remotely_Callable
procedure Inherit_DT
- (Old_T : Tag;
- New_T : Tag;
+ (Old_T : Tag;
+ New_T : Tag;
Entry_Count : Natural);
-- Entry point used to initialize the DT of a type knowing the tag
-- of the direct ancestor and the number of primitive ops that are
@@ -137,17 +163,24 @@ private
pragma Export (Ada, Parent_Size, "ada__tags__parent_size");
-- This procedure is used in s-finimp and is thus exported manually
- function Parent_Tag (T : Tag) return Tag;
- -- Obj is the address of a tagged object. Parent_Tag fetch the tag of the
- -- immediate ancestor (parent) of the type associated with Obj.
-
- pragma Export (Ada, Parent_Tag, "ada__tags__parent_tag");
- -- This procedure is used in s-finimp and is thus exported manually
+ procedure Register_Interface_Tag
+ (T : Tag;
+ Interface_T : Tag);
+ -- Ada 2005 (AI-251): Used to initialize the table of interfaces
+ -- implemented by a type. Required to give support to IW_Membership.
procedure Register_Tag (T : Tag);
-- Insert the Tag and its associated external_tag in a table for the
-- sake of Internal_Tag
+ procedure Set_Offset_To_Top
+ (T : Tag;
+ Value : System.Storage_Elements.Storage_Offset);
+ -- Ada 2005 (AI-251): Initialize the Offset_To_Top field in the prologue of
+ -- the dispatch table. In primary dispatch tables the value of this field
+ -- is always 0; in secondary dispatch tables this is the offset to the base
+ -- of the enclosing type.
+
procedure Set_Prim_Op_Address
(T : Tag;
Position : Positive;
@@ -160,6 +193,10 @@ private
-- Given a pointer T to a dispatch Table, stores the address of the record
-- containing the Type Specific Data generated by GNAT
+ procedure Set_Access_Level (T : Tag; Value : Natural);
+ -- Sets the accessibility level of the tagged type associated with T
+ -- in its TSD.
+
procedure Set_Expanded_Name (T : Tag; Value : System.Address);
-- Set the address of the string containing the expanded name
-- in the Dispatch table
@@ -185,19 +222,24 @@ private
(2 * (Standard'Address_Size / System.Storage_Unit));
-- Size of the first part of the dispatch table
+ DT_Offset_To_Top_Size : constant SSE.Storage_Count :=
+ SSE.Storage_Count
+ (Standard'Address_Size / System.Storage_Unit);
+ -- Size of the Offset_To_Top field of the Dispatch Table
+
DT_Typeinfo_Ptr_Size : constant SSE.Storage_Count :=
SSE.Storage_Count
(Standard'Address_Size / System.Storage_Unit);
- -- Size of the Typeinfo_Ptr field of the Dispatch Table.
+ -- Size of the Typeinfo_Ptr field of the Dispatch Table
DT_Entry_Size : constant SSE.Storage_Count :=
SSE.Storage_Count
(1 * (Standard'Address_Size / System.Storage_Unit));
- -- Size of each primitive operation entry in the Dispatch Table.
+ -- Size of each primitive operation entry in the Dispatch Table
TSD_Prologue_Size : constant SSE.Storage_Count :=
SSE.Storage_Count
- (6 * Standard'Address_Size / System.Storage_Unit);
+ (8 * (Standard'Address_Size / System.Storage_Unit));
-- Size of the first part of the type specific data
TSD_Entry_Size : constant SSE.Storage_Count :=
@@ -210,6 +252,8 @@ private
-- of this type are declared with a dummy size of 1, the actual size
-- depending on the number of primitive operations.
+ -- Unchecked Conversions for Tag and TSD
+
function To_Type_Specific_Data_Ptr is
new Unchecked_Conversion (System.Address, Type_Specific_Data_Ptr);
@@ -220,22 +264,31 @@ private
new Unchecked_Conversion (Tag, System.Address);
type Addr_Ptr is access System.Address;
+ type Tag_Ptr is access Tag;
function To_Addr_Ptr is
new Unchecked_Conversion (System.Address, Addr_Ptr);
+ function To_Tag_Ptr is
+ new Unchecked_Conversion (System.Address, Tag_Ptr);
+
-- Primitive dispatching operations are always inlined, to facilitate
-- use in a minimal/no run-time environment for high integrity use.
pragma Inline_Always (CW_Membership);
+ pragma Inline_Always (IW_Membership);
+ pragma Inline_Always (Get_Access_Level);
pragma Inline_Always (Get_Prim_Op_Address);
pragma Inline_Always (Get_RC_Offset);
pragma Inline_Always (Get_Remotely_Callable);
pragma Inline_Always (Inherit_DT);
pragma Inline_Always (Inherit_TSD);
+ pragma Inline_Always (Register_Interface_Tag);
pragma Inline_Always (Register_Tag);
+ pragma Inline_Always (Set_Access_Level);
pragma Inline_Always (Set_Expanded_Name);
pragma Inline_Always (Set_External_Tag);
+ pragma Inline_Always (Set_Offset_To_Top);
pragma Inline_Always (Set_Prim_Op_Address);
pragma Inline_Always (Set_RC_Offset);
pragma Inline_Always (Set_Remotely_Callable);
diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb
index a0cc0fbf031..56baf47c794 100644
--- a/gcc/ada/debug.adb
+++ b/gcc/ada/debug.adb
@@ -91,7 +91,7 @@ package body Debug is
-- dW Disable warnings on calls for IN OUT parameters
-- dX Enable Frontend ZCX even when it is not supported
-- dY Enable configurable run-time mode
- -- dZ
+ -- dZ Generate listing showing the contents of the dispatch tables
-- d.a
-- d.b
diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb
index e832c5a5457..dc20de9660a 100644
--- a/gcc/ada/exp_attr.adb
+++ b/gcc/ada/exp_attr.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2005, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2005 Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -626,6 +626,16 @@ package body Exp_Attr is
Rewrite (N, Conversion);
Analyze_And_Resolve (N, Typ);
end if;
+
+ -- Ada 2005 (AI-251): If the designated type is an interface,
+ -- then rewrite the referenced object as a conversion to force
+ -- the displacement of the pointer to the secondary dispatch
+ -- table.
+
+ elsif Is_Interface (Directly_Designated_Type (Btyp)) then
+ Conversion := Convert_To (Typ, New_Copy_Tree (Ref_Object));
+ Rewrite (N, Conversion);
+ Analyze_And_Resolve (N, Typ);
end if;
end;
@@ -996,7 +1006,7 @@ package body Exp_Attr is
-- Callable --
--------------
- -- Transforms 'Callable attribute into a call to the Callable function.
+ -- Transforms 'Callable attribute into a call to the Callable function
when Attribute_Callable => Callable :
begin
@@ -1106,6 +1116,7 @@ package body Exp_Attr is
when Attribute_Constrained => Constrained : declare
Formal_Ent : constant Entity_Id := Param_Entity (Pref);
+ Typ : constant Entity_Id := Etype (Pref);
begin
-- Reference to a parameter where the value is passed as an extra
@@ -1189,15 +1200,20 @@ package body Exp_Attr is
-- Prefix is not an entity name. These are also cases where
-- we can always tell at compile time by looking at the form
- -- and type of the prefix.
+ -- and type of the prefix. If an explicit dereference of an
+ -- object with constrained partial view, this is unconstrained
+ -- (Ada 2005 AI-363).
else
Rewrite (N,
New_Reference_To (
Boolean_Literals (
not Is_Variable (Pref)
- or else Nkind (Pref) = N_Explicit_Dereference
- or else Is_Constrained (Etype (Pref))),
+ or else
+ (Nkind (Pref) = N_Explicit_Dereference
+ and then
+ not Has_Constrained_Partial_View (Base_Type (Typ)))
+ or else Is_Constrained (Typ)),
Loc));
end if;
@@ -1665,7 +1681,7 @@ package body Exp_Attr is
-- taskV!(Prefix)._Task_Id, converted to the type Task_Id defined
- -- in Ada.Task_Identification.
+ -- in Ada.Task_Identification
when Attribute_Identity => Identity : declare
Id_Kind : Entity_Id;
@@ -1865,10 +1881,16 @@ package body Exp_Attr is
-- initialize a dummy tag object:
-- Dnn : Ada.Tags.Tag
- -- := Internal_Tag (String'Input (Strm));
+ -- := Descendant_Tag (String'Input (Strm), P_Type);
-- This dummy object is used only to provide a controlling
- -- argument for the eventual _Input call.
+ -- argument for the eventual _Input call. Descendant_Tag is
+ -- called rather than Internal_Tag to ensure that we have a
+ -- tag for a type that is descended from the prefix type and
+ -- declared at the same accessibility level (the exception
+ -- Tag_Error will be raised otherwise). The level check is
+ -- required for Ada 2005 because tagged types can be
+ -- extended in nested scopes (AI-344).
Dnn :=
Make_Defining_Identifier (Loc,
@@ -1882,7 +1904,7 @@ package body Exp_Attr is
Expression =>
Make_Function_Call (Loc,
Name =>
- New_Occurrence_Of (RTE (RE_Internal_Tag), Loc),
+ New_Occurrence_Of (RTE (RE_Descendant_Tag), Loc),
Parameter_Associations => New_List (
Make_Attribute_Reference (Loc,
Prefix =>
@@ -1890,15 +1912,18 @@ package body Exp_Attr is
Attribute_Name => Name_Input,
Expressions => New_List (
Relocate_Node
- (Duplicate_Subexpr (Strm)))))));
+ (Duplicate_Subexpr (Strm)))),
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (P_Type, Loc),
+ Attribute_Name => Name_Tag))));
Insert_Action (N, Decl);
-- Now we need to get the entity for the call, and construct
-- a function call node, where we preset a reference to Dnn
- -- as the controlling argument (doing an unchecked
- -- conversion to the class-wide tagged type to make it
- -- look like a real tagged object).
+ -- as the controlling argument (doing an unchecked convert
+ -- to the class-wide tagged type to make it look like a real
+ -- tagged object).
Fname := Find_Prim_Op (Rtyp, TSS_Stream_Input);
Cntrl := Unchecked_Convert_To (P_Type,
@@ -1912,9 +1937,9 @@ package body Exp_Attr is
elsif Is_Tagged_Type (U_Type) then
Fname := Find_Prim_Op (U_Type, TSS_Stream_Input);
- -- All other record type cases, including protected records.
- -- The latter only arise for expander generated code for
- -- handling shared passive partition access.
+ -- All other record type cases, including protected records. The
+ -- latter only arise for expander generated code for handling
+ -- shared passive partition access.
else
pragma Assert
@@ -1967,9 +1992,9 @@ package body Exp_Attr is
end if;
end if;
- -- If we fall through, Fname is the function to be called. The
- -- result is obtained by calling the appropriate function, then
- -- converting the result. The conversion does a subtype check.
+ -- If we fall through, Fname is the function to be called. The result
+ -- is obtained by calling the appropriate function, then converting
+ -- the result. The conversion does a subtype check.
Call :=
Make_Function_Call (Loc,
@@ -2081,10 +2106,10 @@ package body Exp_Attr is
-- function Leading_Part in Fat_xxx (where xxx is the root type)
-- Note: strictly, we should have special case code to deal with
- -- absurdly large positive arguments (greater than Integer'Last),
- -- which result in returning the first argument unchanged, but it
- -- hardly seems worth the effort. We raise constraint error for
- -- absurdly negative arguments which is fine.
+ -- absurdly large positive arguments (greater than Integer'Last), which
+ -- result in returning the first argument unchanged, but it hardly seems
+ -- worth the effort. We raise constraint error for absurdly negative
+ -- arguments which is fine.
when Attribute_Leading_Part =>
Expand_Fpt_Attribute_RI (N);
@@ -2276,9 +2301,9 @@ package body Exp_Attr is
-- Mantissa --
--------------
- -- The only case that can get this far is the dynamic case of the
- -- old Ada 83 Mantissa attribute for the fixed-point case. For this
- -- case, we expand:
+ -- The only case that can get this far is the dynamic case of the old
+ -- Ada 83 Mantissa attribute for the fixed-point case. For this case, we
+ -- expand:
-- typ'Mantissa
@@ -2352,12 +2377,11 @@ package body Exp_Attr is
-- a) The integer value is non-negative. In this case, it is
-- returned as the result (since it is less than the modulus).
- -- b) The integer value is negative. In this case, we know that
- -- the result is modulus + value, where the value might be as
- -- small as -modulus. The trouble is what type do we use to do
- -- this subtraction. No type will do, since modulus can be as
- -- big as 2**64, and no integer type accomodates this value.
- -- Let's do a bit of algebra
+ -- b) The integer value is negative. In this case, we know that the
+ -- result is modulus + value, where the value might be as small as
+ -- -modulus. The trouble is what type do we use to do the subtract.
+ -- No type will do, since modulus can be as big as 2**64, and no
+ -- integer type accomodates this value. Let's do bit of algebra
-- modulus + value
-- = modulus - (-value)
@@ -2452,10 +2476,10 @@ package body Exp_Attr is
-- strmtyp'Output (Stream, strmwrite (acttyp (Item)));
- -- where strmwrite is the given Write function that converts
- -- an argument of type sourcetyp or a type acctyp, from which
- -- it is derived to type strmtyp. The conversion to acttyp is
- -- required for the derived case.
+ -- where strmwrite is the given Write function that converts an
+ -- argument of type sourcetyp or a type acctyp, from which it is
+ -- derived to type strmtyp. The conversion to acttyp is required
+ -- for the derived case.
Prag := Get_Stream_Convert_Pragma (P_Type);
@@ -2518,7 +2542,43 @@ package body Exp_Attr is
begin
-- The code is:
- -- String'Output (Strm, External_Tag (Item'Tag))
+ -- if Get_Access_Level (Item'Tag)
+ -- /= Get_Access_Level (P_Type'Tag)
+ -- then
+ -- raise Tag_Error;
+ -- end if;
+ -- String'Output (Strm, External_Tag (Item'Tag));
+
+ -- Ada 2005 (AI-344): Check that the accessibility level
+ -- of the type of the output object is not deeper than
+ -- that of the attribute's prefix type.
+
+ if Ada_Version >= Ada_05 then
+ Insert_Action (N,
+ Make_Implicit_If_Statement (N,
+ Condition =>
+ Make_Op_Ne (Loc,
+ Left_Opnd =>
+ Make_Function_Call (Loc,
+ Name =>
+ New_Reference_To
+ (RTE (RE_Get_Access_Level), Loc),
+ Parameter_Associations =>
+ New_List (Make_Attribute_Reference (Loc,
+ Prefix =>
+ Relocate_Node (
+ Duplicate_Subexpr (Item,
+ Name_Req => True)),
+ Attribute_Name =>
+ Name_Tag))),
+ Right_Opnd =>
+ Make_Integer_Literal
+ (Loc, Type_Access_Level (P_Type))),
+ Then_Statements =>
+ New_List (Make_Raise_Statement (Loc,
+ New_Occurrence_Of (
+ RTE (RE_Tag_Error), Loc)))));
+ end if;
Insert_Action (N,
Make_Attribute_Reference (Loc,
@@ -2544,9 +2604,9 @@ package body Exp_Attr is
elsif Is_Tagged_Type (U_Type) then
Pname := Find_Prim_Op (U_Type, TSS_Stream_Output);
- -- All other record type cases, including protected records.
- -- The latter only arise for expander generated code for
- -- handling shared passive partition access.
+-- -- All other record type cases, including protected records.
+-- -- The latter only arise for expander generated code for
+-- -- handling shared passive partition access.
else
pragma Assert
@@ -2857,10 +2917,10 @@ package body Exp_Attr is
-- Item := sourcetyp (strmread (strmtyp'Input (Stream)));
- -- where strmread is the given Read function that converts
- -- an argument of type strmtyp to type sourcetyp or a type
- -- from which it is derived. The conversion to sourcetyp
- -- is required in the latter case.
+ -- where strmread is the given Read function that converts an
+ -- argument of type strmtyp to type sourcetyp or a type from which
+ -- it is derived. The conversion to sourcetyp is required in the
+ -- latter case.
-- A special case arises if Item is a type conversion in which
-- case, we have to expand to:
@@ -2943,9 +3003,9 @@ package body Exp_Attr is
elsif Is_Tagged_Type (U_Type) then
Pname := Find_Prim_Op (U_Type, TSS_Stream_Read);
- -- All other record type cases, including protected records.
- -- The latter only arise for expander generated code for
- -- handling shared passive partition access.
+ -- All other record type cases, including protected records. The
+ -- latter only arise for expander generated code for handling
+ -- shared passive partition access.
else
pragma Assert
@@ -2997,36 +3057,35 @@ package body Exp_Attr is
-- Round --
-----------
- -- The handling of the Round attribute is quite delicate. The
- -- processing in Sem_Attr introduced a conversion to universal
- -- real, reflecting the semantics of Round, but we do not want
- -- anything to do with universal real at runtime, since this
- -- corresponds to using floating-point arithmetic.
-
- -- What we have now is that the Etype of the Round attribute
- -- correctly indicates the final result type. The operand of
- -- the Round is the conversion to universal real, described
- -- above, and the operand of this conversion is the actual
- -- operand of Round, which may be the special case of a fixed
- -- point multiplication or division (Etype = universal fixed)
-
- -- The exapander will expand first the operand of the conversion,
- -- then the conversion, and finally the round attribute itself,
- -- since we always work inside out. But we cannot simply process
- -- naively in this order. In the semantic world where universal
- -- fixed and real really exist and have infinite precision, there
- -- is no problem, but in the implementation world, where universal
- -- real is a floating-point type, we would get the wrong result.
-
- -- So the approach is as follows. First, when expanding a multiply
- -- or divide whose type is universal fixed, we do nothing at all,
- -- instead deferring the operation till later.
+ -- The handling of the Round attribute is quite delicate. The processing
+ -- in Sem_Attr introduced a conversion to universal real, reflecting the
+ -- semantics of Round, but we do not want anything to do with universal
+ -- real at runtime, since this corresponds to using floating-point
+ -- arithmetic.
+
+ -- What we have now is that the Etype of the Round attribute correctly
+ -- indicates the final result type. The operand of the Round is the
+ -- conversion to universal real, described above, and the operand of
+ -- this conversion is the actual operand of Round, which may be the
+ -- special case of a fixed point multiplication or division (Etype =
+ -- universal fixed)
+
+ -- The exapander will expand first the operand of the conversion, then
+ -- the conversion, and finally the round attribute itself, since we
+ -- always work inside out. But we cannot simply process naively in this
+ -- order. In the semantic world where universal fixed and real really
+ -- exist and have infinite precision, there is no problem, but in the
+ -- implementation world, where universal real is a floating-point type,
+ -- we would get the wrong result.
+
+ -- So the approach is as follows. First, when expanding a multiply or
+ -- divide whose type is universal fixed, we do nothing at all, instead
+ -- deferring the operation till later.
-- The actual processing is done in Expand_N_Type_Conversion which
- -- handles the special case of Round by looking at its parent to
- -- see if it is a Round attribute, and if it is, handling the
- -- conversion (or its fixed multiply/divide child) in an appropriate
- -- manner.
+ -- handles the special case of Round by looking at its parent to see if
+ -- it is a Round attribute, and if it is, handling the conversion (or
+ -- its fixed multiply/divide child) in an appropriate manner.
-- This means that by the time we get to expanding the Round attribute
-- itself, the Round is nothing more than a type conversion (and will
@@ -3120,9 +3179,9 @@ package body Exp_Attr is
Rewrite (Pref, New_Occurrence_Of (Etype (Pref), Loc));
end if;
- -- For a scalar type for which no size was
- -- explicitly given, VADS_Size means Object_Size. This is the
- -- other respect in which VADS_Size differs from Size.
+ -- For a scalar type for which no size was explicitly given,
+ -- VADS_Size means Object_Size. This is the other respect in
+ -- which VADS_Size differs from Size.
if Is_Scalar_Type (Etype (Pref))
and then No (Size_Clause (Etype (Pref)))
@@ -3177,9 +3236,9 @@ package body Exp_Attr is
elsif Nkind (Pref) = N_Indexed_Component then
Siz := Component_Size (Etype (Prefix (Pref)));
- -- For a record component, we can do Size in the front end
- -- if there is a component clause, or if the record is packed
- -- and the component's size is known at compile time.
+ -- For a record component, we can do Size in the front end if there
+ -- is a component clause, or if the record is packed and the
+ -- component's size is known at compile time.
elsif Nkind (Pref) = N_Selected_Component then
declare
@@ -3522,7 +3581,7 @@ package body Exp_Attr is
-- Terminated --
----------------
- -- Transforms 'Terminated attribute into a call to Terminated function.
+ -- Transforms 'Terminated attribute into a call to Terminated function
when Attribute_Terminated => Terminated :
begin
@@ -3881,9 +3940,9 @@ package body Exp_Attr is
Rewrite (N, New_Occurrence_Of (Standard_True, Loc));
-- For biased representations, we will be doing an unchecked
- -- conversion without unbiasing the result. That means that
- -- the range test has to take this into account, and the
- -- proper form of the test is:
+ -- conversion without unbiasing the result. That means that the range
+ -- test has to take this into account, and the proper form of the
+ -- test is:
-- Btyp!(Pref) < Btyp!(Ptyp'Range_Length)
@@ -3924,18 +3983,18 @@ package body Exp_Attr is
-- Unsigned types. Note: it is safe to consider only whether the
-- subtype is unsigned, since we will in that case be doing all
- -- unsigned comparisons based on the subtype range. Since we use
- -- the actual subtype object size, this is appropriate.
+ -- unsigned comparisons based on the subtype range. Since we use the
+ -- actual subtype object size, this is appropriate.
-- For example, if we have
-- subtype x is integer range 1 .. 200;
-- for x'Object_Size use 8;
- -- Now the base type is signed, but objects of this type are 8
- -- bits unsigned, and doing an unsigned test of the range 1 to
- -- 200 is correct, even though a value greater than 127 looks
- -- signed to a signed comparison.
+ -- Now the base type is signed, but objects of this type are bits
+ -- unsigned, and doing an unsigned test of the range 1 to 200 is
+ -- correct, even though a value greater than 127 looks signed to a
+ -- signed comparison.
elsif Is_Unsigned_Type (Ptyp) then
if Esize (Ptyp) <= 32 then
@@ -4188,10 +4247,10 @@ package body Exp_Attr is
-- strmtyp'Output (Stream, strmwrite (acttyp (Item)));
- -- where strmwrite is the given Write function that converts
- -- an argument of type sourcetyp or a type acctyp, from which
- -- it is derived to type strmtyp. The conversion to acttyp is
- -- required for the derived case.
+ -- where strmwrite is the given Write function that converts an
+ -- argument of type sourcetyp or a type acctyp, from which it is
+ -- derived to type strmtyp. The conversion to acttyp is required
+ -- for the derived case.
Prag := Get_Stream_Convert_Pragma (P_Type);
@@ -4272,22 +4331,22 @@ package body Exp_Attr is
Rewrite_Stream_Proc_Call (Pname);
end Write;
- -- Component_Size is handled by Gigi, unless the component size is
- -- known at compile time, which is always true in the packed array
- -- case. It is important that the packed array case is handled in
- -- the front end (see Eval_Attribute) since Gigi would otherwise
- -- get confused by the equivalent packed array type.
+ -- Component_Size is handled by Gigi, unless the component size is known
+ -- at compile time, which is always true in the packed array case. It is
+ -- important that the packed array case is handled in the front end (see
+ -- Eval_Attribute) since Gigi would otherwise get confused by the
+ -- equivalent packed array type.
when Attribute_Component_Size =>
null;
-- The following attributes are handled by Gigi (except that static
- -- cases have already been evaluated by the semantics, but in any
- -- case Gigi should not count on that).
+ -- cases have already been evaluated by the semantics, but in any case
+ -- Gigi should not count on that).
- -- In addition Gigi handles the non-floating-point cases of Pred
- -- and Succ (including the fixed-point cases, which can just be
- -- treated as integer increment/decrement operations)
+ -- In addition Gigi handles the non-floating-point cases of Pred and
+ -- Succ (including the fixed-point cases, which can just be treated as
+ -- integer increment/decrement operations)
-- Gigi also handles the non-class-wide cases of Size
@@ -4423,8 +4482,14 @@ package body Exp_Attr is
function Find_Stream_Subprogram
(Typ : Entity_Id;
- Nam : TSS_Name_Type) return Entity_Id is
+ Nam : TSS_Name_Type) return Entity_Id
+ is
+ Ent : constant Entity_Id := TSS (Typ, Nam);
begin
+ if Present (Ent) then
+ return Ent;
+ end if;
+
if Is_Tagged_Type (Typ)
and then Is_Derived_Type (Typ)
then
diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb
index 9aa83aa51dd..fc8463d71b4 100644
--- a/gcc/ada/exp_ch3.adb
+++ b/gcc/ada/exp_ch3.adb
@@ -49,6 +49,7 @@ with Restrict; use Restrict;
with Rident; use Rident;
with Rtsfind; use Rtsfind;
with Sem; use Sem;
+with Sem_Attr; use Sem_Attr;
with Sem_Ch3; use Sem_Ch3;
with Sem_Ch8; use Sem_Ch8;
with Sem_Eval; use Sem_Eval;
@@ -124,8 +125,9 @@ package body Exp_Ch3 is
procedure Check_Stream_Attributes (Typ : Entity_Id);
-- Check that if a limited extension has a parent with user-defined
- -- stream attributes, any limited component of the extension also has
- -- the corresponding user-defined stream attributes.
+ -- stream attributes, and does not itself have user-definer
+ -- stream-attributes, then any limited component of the extension also
+ -- has the corresponding user-defined stream attributes.
procedure Expand_Tagged_Root (T : Entity_Id);
-- Add a field _Tag at the beginning of the record. This field carries
@@ -1359,6 +1361,10 @@ package body Exp_Ch3 is
Rec_Type : Entity_Id;
Set_Tag : Entity_Id := Empty;
+ ADT : Elmt_Id;
+ Aux_N : Node_Id;
+ Aux_Comp : Node_Id;
+
function Build_Assignment (Id : Entity_Id; N : Node_Id) return List_Id;
-- Build a assignment statement node which assigns to record
-- component its default expression if defined. The left hand side
@@ -1405,12 +1411,12 @@ package body Exp_Ch3 is
function Component_Needs_Simple_Initialization
(T : Entity_Id) return Boolean;
- -- Determines if a component needs simple initialization, given its
- -- type T. This is the same as Needs_Simple_Initialization except
- -- for the following difference: the types Tag and Vtable_Ptr, which
- -- are access types which would normally require simple initialization
- -- to null, do not require initialization as components, since they
- -- are explicitly initialized by other means.
+ -- Determines if a component needs simple initialization, given its type
+ -- T. This is the same as Needs_Simple_Initialization except for the
+ -- following difference: the types Tag, Interface_Tag, and Vtable_Ptr
+ -- which are access types which would normally require simple
+ -- initialization to null, do not require initialization as components,
+ -- since they are explicitly initialized by other means.
procedure Constrain_Array
(SI : Node_Id;
@@ -1855,6 +1861,60 @@ package body Exp_Ch3 is
if not Is_CPP_Class (Etype (Rec_Type)) then
Prepend_To (Body_Stmts, Init_Tag);
+ -- Ada 2005 (AI-251): Initialization of all the tags
+ -- corresponding with abstract interfaces
+
+ if Present (First_Tag_Component (Rec_Type)) then
+
+ -- Skip the first _Tag, which is the main tag of the
+ -- tagged type. Following tags correspond with abstract
+ -- interfaces.
+
+ Aux_Comp :=
+ Next_Tag_Component (First_Tag_Component (Rec_Type));
+
+ ADT := Next_Elmt (First_Elmt (Access_Disp_Table (Rec_Type)));
+ while Present (ADT) loop
+ Aux_N := Node (ADT);
+
+ -- Initialize the pointer to the secondary DT associated
+ -- with the interface
+
+ Append_To (Body_Stmts,
+ Make_Assignment_Statement (Loc,
+ Name =>
+ Make_Selected_Component (Loc,
+ Prefix => Make_Identifier (Loc, Name_uInit),
+ Selector_Name =>
+ New_Reference_To (Aux_Comp, Loc)),
+ Expression =>
+ New_Reference_To (Aux_N, Loc)));
+
+ -- Generate:
+ -- Set_Offset_To_Top (DT_Ptr, n);
+
+ Append_To (Body_Stmts,
+ Make_Procedure_Call_Statement (Loc,
+ Name => New_Reference_To (RTE (RE_Set_Offset_To_Top),
+ Loc),
+ Parameter_Associations => New_List (
+ Unchecked_Convert_To (RTE (RE_Tag),
+ New_Reference_To (Aux_N, Loc)),
+ Unchecked_Convert_To (RTE (RE_Storage_Offset),
+ Make_Attribute_Reference (Loc,
+ Prefix =>
+ Make_Selected_Component (Loc,
+ Prefix => Make_Identifier (Loc,
+ Name_uInit),
+ Selector_Name => New_Reference_To
+ (Aux_Comp, Loc)),
+ Attribute_Name => Name_Position)))));
+
+ Aux_Comp := Next_Tag_Component (Aux_Comp);
+ Next_Elmt (ADT);
+ end loop;
+ end if;
+
else
declare
Nod : Node_Id := First (Body_Stmts);
@@ -2236,7 +2296,8 @@ package body Exp_Ch3 is
return
Needs_Simple_Initialization (T)
and then not Is_RTE (T, RE_Tag)
- and then not Is_RTE (T, RE_Vtable_Ptr);
+ and then not Is_RTE (T, RE_Vtable_Ptr)
+ and then not Is_RTE (T, RE_Interface_Tag); -- Ada 2005 (AI-251)
end Component_Needs_Simple_Initialization;
---------------------
@@ -2388,7 +2449,7 @@ package body Exp_Ch3 is
-- 6. One or more components is a type that requires simple
-- initialization (see Needs_Simple_Initialization), except
- -- that types Tag and Vtable_Ptr are excluded, since fields
+ -- that types Tag and Interface_Tag are excluded, since fields
-- of these types are initialized by other means.
-- 7. The type is the record type built for a task type (since at
@@ -3012,22 +3073,31 @@ package body Exp_Ch3 is
procedure Check_Stream_Attributes (Typ : Entity_Id) is
Comp : Entity_Id;
- Par : constant Entity_Id := Root_Type (Base_Type (Typ));
- Par_Read : constant Boolean := Present (TSS (Par, TSS_Stream_Read));
- Par_Write : constant Boolean := Present (TSS (Par, TSS_Stream_Write));
+ Par_Read : constant Boolean :=
+ Stream_Attribute_Available (Typ, TSS_Stream_Read)
+ and then not Has_Specified_Stream_Read (Typ);
+ Par_Write : constant Boolean :=
+ Stream_Attribute_Available (Typ, TSS_Stream_Write)
+ and then not Has_Specified_Stream_Write (Typ);
procedure Check_Attr (Nam : Name_Id; TSS_Nam : TSS_Name_Type);
-- Check that Comp has a user-specified Nam stream attribute
+ ----------------
+ -- Check_Attr --
+ ----------------
+
procedure Check_Attr (Nam : Name_Id; TSS_Nam : TSS_Name_Type) is
begin
- if No (TSS (Base_Type (Etype (Comp)), TSS_Nam)) then
+ if not Stream_Attribute_Available (Etype (Comp), TSS_Nam) then
Error_Msg_Name_1 := Nam;
Error_Msg_N
("|component& in limited extension must have% attribute", Comp);
end if;
end Check_Attr;
+ -- Start of processing for Check_Stream_Attributes
+
begin
if Par_Read or else Par_Write then
Comp := First_Component (Typ);
@@ -3422,12 +3492,36 @@ package body Exp_Ch3 is
-- simple initialization expression in place. This special
-- initialization is required even though No_Init_Flag is present.
- elsif Needs_Simple_Initialization (Typ) then
+ -- An internally generated temporary needs no initialization because
+ -- it will be assigned subsequently. In particular, there is no
+ -- point in applying Initialize_Scalars to such a temporary.
+
+ elsif Needs_Simple_Initialization (Typ)
+ and then not Is_Internal (Def_Id)
+ then
Set_No_Initialization (N, False);
Set_Expression (N, Get_Simple_Init_Val (Typ, Loc, Esize (Def_Id)));
Analyze_And_Resolve (Expression (N), Typ);
end if;
+ -- Generate attribute for Persistent_BSS if needed
+
+ declare
+ Prag : Node_Id;
+ begin
+ if Persistent_BSS_Mode
+ and then Comes_From_Source (N)
+ and then Is_Potentially_Persistent_Type (Typ)
+ and then Is_Library_Level_Entity (Def_Id)
+ then
+ Prag :=
+ Make_Linker_Section_Pragma
+ (Def_Id, Sloc (N), ".persistent.bss");
+ Insert_After (N, Prag);
+ Analyze (Prag);
+ end if;
+ end;
+
-- Explicit initialization present
else
@@ -4340,6 +4434,7 @@ package body Exp_Ch3 is
-- created in the C++ side and we just use it.
if Is_Tagged_Type (Def_Id) then
+
if Is_CPP_Class (Def_Id) then
Set_All_DT_Position (Def_Id);
Set_Default_Constructor (Def_Id);
@@ -4385,6 +4480,36 @@ package body Exp_Ch3 is
Expand_Tagged_Root (Def_Id);
end if;
+ -- Build the secondary tables
+
+ if not Java_VM
+ and then Present (Abstract_Interfaces (Def_Id))
+ and then not Is_Empty_Elmt_List (Abstract_Interfaces (Def_Id))
+ then
+ declare
+ E : Entity_Id;
+ Result : List_Id;
+ ADT : Elist_Id := Access_Disp_Table (Def_Id);
+
+ begin
+ E := First_Entity (Def_Id);
+ while Present (E) loop
+ if Is_Tag (E) and then Chars (E) /= Name_uTag then
+ Make_Abstract_Interface_DT
+ (AI_Tag => E,
+ Acc_Disp_Tables => ADT,
+ Result => Result);
+
+ Append_Freeze_Actions (Def_Id, Result);
+ end if;
+
+ Next_Entity (E);
+ end loop;
+
+ Set_Access_Disp_Table (Def_Id, ADT);
+ end;
+ end if;
+
-- Unfreeze momentarily the type to add the predefined primitives
-- operations. The reason we unfreeze is so that these predefined
-- operations will indeed end up as primitive operations (which
@@ -4556,7 +4681,7 @@ package body Exp_Ch3 is
-- Full type declarations are expanded at the point at which the type is
-- frozen. The formal N is the Freeze_Node for the type. Any statements or
-- declarations generated by the freezing (e.g. the procedure generated
- -- for initialization) are chained in the Acions field list of the freeze
+ -- for initialization) are chained in the Actions field list of the freeze
-- node using Append_Freeze_Actions.
function Freeze_Type (N : Node_Id) return Boolean is
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index e817156267c..ea615edead1 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2005, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2005 Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -33,7 +33,6 @@ with Exp_Aggr; use Exp_Aggr;
with Exp_Ch3; use Exp_Ch3;
with Exp_Ch7; use Exp_Ch7;
with Exp_Ch9; use Exp_Ch9;
-with Exp_Disp; use Exp_Disp;
with Exp_Fixd; use Exp_Fixd;
with Exp_Pakd; use Exp_Pakd;
with Exp_Tss; use Exp_Tss;
@@ -445,6 +444,41 @@ package body Exp_Ch4 is
Expression => Node));
end if;
+ -- Ada 2005 (AI-344):
+ -- For an allocator with a class-wide designated type, generate an
+ -- accessibility check to verify that the level of the type of the
+ -- created object is not deeper than the level of the access type.
+ -- If the type of the qualified expression is class-wide, then
+ -- always generate the check. Otherwise, only generate the check
+ -- if the level of the qualified expression type is statically deeper
+ -- than the access type. Although the static accessibility will
+ -- generally have been performed as a legality check, it won't have
+ -- been done in cases where the allocator appears in a generic body,
+ -- so the run-time check is needed in general. (Not yet doing the
+ -- optimization to suppress the check for the static level case.???)
+
+ if Ada_Version >= Ada_05
+ and then Is_Class_Wide_Type (Designated_Type (PtrT))
+ then
+ Insert_Action (N,
+ Make_Raise_Program_Error (Loc,
+ Condition =>
+ Make_Op_Gt (Loc,
+ Left_Opnd =>
+ Make_Function_Call (Loc,
+ Name =>
+ New_Reference_To (RTE (RE_Get_Access_Level), Loc),
+ Parameter_Associations =>
+ New_List (Make_Attribute_Reference (Loc,
+ Prefix =>
+ New_Reference_To (Temp, Loc),
+ Attribute_Name =>
+ Name_Tag))),
+ Right_Opnd =>
+ Make_Integer_Literal (Loc, Type_Access_Level (PtrT))),
+ Reason => PE_Accessibility_Check_Failed));
+ end if;
+
-- Suppress the tag assignment when Java_VM because JVM tags
-- are represented implicitly in objects.
@@ -8015,22 +8049,43 @@ package body Exp_Ch4 is
New_Reference_To (First_Tag_Component (Left_Type), Loc));
if Is_Class_Wide_Type (Right_Type) then
- return
- Make_DT_Access_Action (Left_Type,
- Action => CW_Membership,
- Args => New_List (
- Obj_Tag,
- New_Reference_To
- (Node (First_Elmt
- (Access_Disp_Table (Root_Type (Right_Type)))),
- Loc)));
+
+ -- Ada 2005 (AI-251): Class-wide applied to interfaces
+
+ if Is_Interface (Etype (Class_Wide_Type (Right_Type))) then
+ return
+ Make_Function_Call (Loc,
+ Name => New_Occurrence_Of (RTE (RE_IW_Membership), Loc),
+ Parameter_Associations => New_List (
+ Make_Attribute_Reference (Loc,
+ Prefix => Obj_Tag,
+ Attribute_Name => Name_Address),
+ New_Reference_To (
+ Node (First_Elmt
+ (Access_Disp_Table (Root_Type (Right_Type)))),
+ Loc)));
+
+ -- Ada 95: Normal case
+
+ else
+ return
+ Make_Function_Call (Loc,
+ Name => New_Occurrence_Of (RTE (RE_CW_Membership), Loc),
+ Parameter_Associations => New_List (
+ Obj_Tag,
+ New_Reference_To (
+ Node (First_Elmt
+ (Access_Disp_Table (Root_Type (Right_Type)))),
+ Loc)));
+ end if;
+
else
return
Make_Op_Eq (Loc,
- Left_Opnd => Obj_Tag,
- Right_Opnd =>
- New_Reference_To
- (Node (First_Elmt (Access_Disp_Table (Right_Type))), Loc));
+ Left_Opnd => Obj_Tag,
+ Right_Opnd =>
+ New_Reference_To
+ (Node (First_Elmt (Access_Disp_Table (Right_Type))), Loc));
end if;
end Tagged_Membership;
diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb
index d78da78dbcb..6224d17f54a 100644
--- a/gcc/ada/exp_ch5.adb
+++ b/gcc/ada/exp_ch5.adb
@@ -2829,6 +2829,33 @@ package body Exp_Ch5 is
Rewrite (Exp, Result_Exp);
Analyze_And_Resolve (Exp, Return_Type);
end if;
+
+ -- Ada 2005 (AI-344): If the result type is class-wide, then insert
+ -- a check that the level of the return expression's underlying type
+ -- is not deeper than the level of the master enclosing the function.
+
+ elsif Ada_Version >= Ada_05
+ and then Is_Class_Wide_Type (Return_Type)
+ then
+ Insert_Action (Exp,
+ Make_Raise_Program_Error (Loc,
+ Condition =>
+ Make_Op_Gt (Loc,
+ Left_Opnd =>
+ Make_Function_Call (Loc,
+ Name =>
+ New_Reference_To
+ (RTE (RE_Get_Access_Level), Loc),
+ Parameter_Associations =>
+ New_List (Make_Attribute_Reference (Loc,
+ Prefix =>
+ Duplicate_Subexpr (Exp),
+ Attribute_Name =>
+ Name_Tag))),
+ Right_Opnd =>
+ Make_Integer_Literal (Loc,
+ Scope_Depth (Enclosing_Dynamic_Scope (Scope_Id)))),
+ Reason => PE_Accessibility_Check_Failed));
end if;
-- Deal with returning variable length objects and controlled types
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index c4fc454ab1c..e23e12881c1 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2005, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2005 Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -60,6 +60,7 @@ with Sem_Ch12; use Sem_Ch12;
with Sem_Ch13; use Sem_Ch13;
with Sem_Disp; use Sem_Disp;
with Sem_Dist; use Sem_Dist;
+with Sem_Mech; use Sem_Mech;
with Sem_Res; use Sem_Res;
with Sem_Util; use Sem_Util;
with Sinfo; use Sinfo;
@@ -515,6 +516,14 @@ package body Exp_Ch6 is
-- representation as True. We assume that .FALSE. = False = 0.
-- What about functions that return a logical type ???
+ function Is_Legal_Copy return Boolean;
+ -- Check that an actual can be copied before generating the temporary
+ -- to be used in the call. If the actual is of a by_reference type then
+ -- the program is illegal (this can only happen in the presence of
+ -- rep. clauses that force an incorrect alignment). If the formal is
+ -- a by_reference parameter imposed by a DEC pragma, emit a warning to
+ -- the effect that this might lead to unaligned arguments.
+
function Make_Var (Actual : Node_Id) return Entity_Id;
-- Returns an entity that refers to the given actual parameter,
-- Actual (not including any type conversion). If Actual is an
@@ -541,11 +550,15 @@ package body Exp_Ch6 is
Crep : Boolean;
begin
+ if not Is_Legal_Copy then
+ return;
+ end if;
+
Temp := Make_Defining_Identifier (Loc, New_Internal_Name ('T'));
-- Use formal type for temp, unless formal type is an unconstrained
-- array, in which case we don't have to worry about bounds checks,
- -- and we use the actual type, since that has appropriate bonds.
+ -- and we use the actual type, since that has appropriate bounds.
if Is_Array_Type (F_Typ) and then not Is_Constrained (F_Typ) then
Indic := New_Occurrence_Of (Etype (Actual), Loc);
@@ -715,6 +728,7 @@ package body Exp_Ch6 is
procedure Add_Simple_Call_By_Copy_Code is
Temp : Entity_Id;
+ Decl : Node_Id;
Incod : Node_Id;
Outcod : Node_Id;
Lhs : Node_Id;
@@ -723,9 +737,13 @@ package body Exp_Ch6 is
F_Typ : constant Entity_Id := Etype (Formal);
begin
+ if not Is_Legal_Copy then
+ return;
+ end if;
+
-- Use formal type for temp, unless formal type is an unconstrained
-- array, in which case we don't have to worry about bounds checks,
- -- and we use the actual type, since that has appropriate bonds.
+ -- and we use the actual type, since that has appropriate bounds.
if Is_Array_Type (F_Typ) and then not Is_Constrained (F_Typ) then
Indic := New_Occurrence_Of (Etype (Actual), Loc);
@@ -742,17 +760,53 @@ package body Exp_Ch6 is
Outcod := New_Copy_Tree (Incod);
-- Generate declaration of temporary variable, initializing it
- -- with the input parameter unless we have an OUT variable.
+ -- with the input parameter unless we have an OUT variable or
+ -- this is an initialization call.
if Ekind (Formal) = E_Out_Parameter then
Incod := Empty;
+
+ elsif Inside_Init_Proc then
+ if Nkind (Actual) /= N_Selected_Component
+ or else
+ not Has_Discriminant_Dependent_Constraint
+ (Entity (Selector_Name (Actual)))
+ then
+ Incod := Empty;
+
+ else
+ -- We need the component in order to generate the proper
+ -- actual subtype, that depends on enclosing discriminants.
+ -- What is the comment for, given code below is null ???
+
+ null;
+ end if;
end if;
- Insert_Action (N,
+ Decl :=
Make_Object_Declaration (Loc,
Defining_Identifier => Temp,
Object_Definition => Indic,
- Expression => Incod));
+ Expression => Incod);
+
+ if Inside_Init_Proc
+ and then No (Incod)
+ then
+ -- If the call is to initialize a component of a composite type,
+ -- and the component does not depend on discriminants, use the
+ -- actual type of the component. This is required in case the
+ -- component is constrained, because in general the formal of the
+ -- initialization procedure will be unconstrained. Note that if
+ -- the component being initialized is constrained by an enclosing
+ -- discriminant, the presence of the initialization in the
+ -- declaration will generate an expression for the actual subtype.
+
+ Set_No_Initialization (Decl);
+ Set_Object_Definition (Decl,
+ New_Occurrence_Of (Etype (Actual), Loc));
+ end if;
+
+ Insert_Action (N, Decl);
-- The actual is simply a reference to the temporary
@@ -811,6 +865,38 @@ package body Exp_Ch6 is
end if;
end Check_Fortran_Logical;
+ -------------------
+ -- Is_Legal_Copy --
+ -------------------
+
+ function Is_Legal_Copy return Boolean is
+ begin
+ -- An attempt to copy a value of such a type can only occur if
+ -- representation clauses give the actual a misaligned address.
+
+ if Is_By_Reference_Type (Etype (Formal)) then
+ Error_Msg_N
+ ("misaligned actual cannot be passed by reference", Actual);
+ return False;
+
+ -- For users of Starlet, we assume that the specification of by-
+ -- reference mechanism is mandatory. This may lead to unligned
+ -- objects but at least for DEC legacy code it is known to work.
+ -- The warning will alert users of this code that a problem may
+ -- be lurking.
+
+ elsif Mechanism (Formal) = By_Reference
+ and then Is_Valued_Procedure (Scope (Formal))
+ then
+ Error_Msg_N
+ ("by_reference actual may be misaligned?", Actual);
+ return False;
+
+ else
+ return True;
+ end if;
+ end Is_Legal_Copy;
+
--------------
-- Make_Var --
--------------
@@ -1127,6 +1213,8 @@ package body Exp_Ch6 is
Extra_Actuals : List_Id := No_List;
Cond : Node_Id;
+ CW_Interface_Formals_Present : Boolean := False;
+
procedure Add_Actual_Parameter (Insert_Param : Node_Id);
-- Adds one entry to the end of the actual parameter list. Used for
-- default parameters and for extra actuals (for Extra_Formals).
@@ -1391,16 +1479,28 @@ package body Exp_Ch6 is
Prev := Actual;
Prev_Orig := Original_Node (Prev);
- -- Create possible extra actual for constrained case. Usually,
- -- the extra actual is of the form actual'constrained, but since
- -- this attribute is only available for unconstrained records,
- -- TRUE is expanded if the type of the formal happens to be
- -- constrained (for instance when this procedure is inherited
- -- from an unconstrained record to a constrained one) or if the
- -- actual has no discriminant (its type is constrained). An
- -- exception to this is the case of a private type without
- -- discriminants. In this case we pass FALSE because the
- -- object has underlying discriminants with defaults.
+ -- Ada 2005 (AI-251): Check if any formal is a class-wide interface
+ -- to expand it in a further round
+
+ CW_Interface_Formals_Present :=
+ CW_Interface_Formals_Present
+ or else
+ (Ekind (Etype (Formal)) = E_Class_Wide_Type
+ and then Is_Interface (Etype (Etype (Formal))))
+ or else
+ (Ekind (Etype (Formal)) = E_Anonymous_Access_Type
+ and then Is_Interface (Directly_Designated_Type
+ (Etype (Etype (Formal)))));
+
+ -- Create possible extra actual for constrained case. Usually, the
+ -- extra actual is of the form actual'constrained, but since this
+ -- attribute is only available for unconstrained records, TRUE is
+ -- expanded if the type of the formal happens to be constrained (for
+ -- instance when this procedure is inherited from an unconstrained
+ -- record to a constrained one) or if the actual has no discriminant
+ -- (its type is constrained). An exception to this is the case of a
+ -- private type without discriminants. In this case we pass FALSE
+ -- because the object has underlying discriminants with defaults.
if Present (Extra_Constrained (Formal)) then
if Ekind (Etype (Prev)) in Private_Kind
@@ -1756,6 +1856,16 @@ package body Exp_Ch6 is
end;
end if;
+ -- Ada 2005 (AI-251): If some formal is a class-wide interface, expand
+ -- it to point to the correct secondary virtual table
+
+ if (Nkind (N) = N_Function_Call
+ or else Nkind (N) = N_Procedure_Call_Statement)
+ and then CW_Interface_Formals_Present
+ then
+ Expand_Interface_Actuals (N);
+ end if;
+
-- Deals with Dispatch_Call if we still have a call, before expanding
-- extra actuals since this will be done on the re-analysis of the
-- dispatching call. Note that we do not try to shorten the actual
@@ -2858,6 +2968,7 @@ package body Exp_Ch6 is
Temp :=
Make_Defining_Identifier (Loc, New_Internal_Name ('C'));
+ Set_Is_Internal (Temp);
Decl :=
Make_Object_Declaration (Loc,
@@ -3685,6 +3796,8 @@ package body Exp_Ch6 is
-- protected subprogram an associated formals. For a normal protected
-- operation, this is done when expanding the protected type declaration.
+ -- If the declaration is for a null procedure, emit null body
+
procedure Expand_N_Subprogram_Declaration (N : Node_Id) is
Loc : constant Source_Ptr := Sloc (N);
Subp : constant Entity_Id := Defining_Entity (N);
@@ -3732,6 +3845,24 @@ package body Exp_Ch6 is
Set_Protected_Body_Subprogram (Subp, Prot_Id);
Pop_Scope;
end if;
+
+ elsif Nkind (Specification (N)) = N_Procedure_Specification
+ and then Null_Present (Specification (N))
+ then
+ declare
+ Bod : constant Node_Id :=
+ Make_Subprogram_Body (Loc,
+ Specification =>
+ New_Copy_Tree (Specification (N)),
+ Declarations => New_List,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (Make_Null_Statement (Loc))));
+ begin
+ Set_Body_To_Inline (N, New_Copy_Tree (Bod));
+ Insert_After (N, Bod);
+ Analyze (Bod);
+ end;
end if;
end Expand_N_Subprogram_Declaration;
@@ -3907,7 +4038,11 @@ package body Exp_Ch6 is
-----------------------
procedure Freeze_Subprogram (N : Node_Id) is
- E : constant Entity_Id := Entity (N);
+ Loc : constant Source_Ptr := Sloc (N);
+ E : constant Entity_Id := Entity (N);
+ Thunk_Id : Entity_Id;
+ Iface_Tag : Entity_Id;
+ New_Thunk : Node_Id;
begin
-- When a primitive is frozen, enter its name in the corresponding
@@ -3923,7 +4058,41 @@ package body Exp_Ch6 is
and then not Java_VM
then
Check_Overriding_Operation (E);
- Insert_After (N, Fill_DT_Entry (Sloc (N), E));
+
+ -- Common case: Primitive subprogram
+
+ if not Present (Abstract_Interface_Alias (E)) then
+ Insert_After (N, Fill_DT_Entry (Sloc (N), E));
+
+ -- Ada 2005 (AI-251): Primitive subprogram that covers an interface
+
+ else
+ Iface_Tag :=
+ Find_Interface_Tag
+ (T => Scope (DTC_Entity (Alias (E))), -- Formal Type
+ Iface => Scope (DTC_Entity (Abstract_Interface_Alias (E))));
+
+ -- Generate the thunk only if the associated tag is an interface
+ -- tag. The case in which the associated tag is the primary tag
+ -- occurs when a tagged type is a direct derivation of an
+ -- interface. For example:
+
+ -- type I is interface;
+ -- ...
+ -- type T is new I with ...
+
+ if Etype (Iface_Tag) = RTE (RE_Interface_Tag) then
+ Thunk_Id := Make_Defining_Identifier (Loc,
+ New_Internal_Name ('T'));
+
+ New_Thunk := Expand_Interface_Thunk (N, Thunk_Id, Iface_Tag);
+
+ Insert_After (New_Thunk,
+ Fill_DT_Entry (Sloc (N),
+ Prim => E,
+ Thunk_Id => Thunk_Id));
+ end if;
+ end if;
end if;
-- Mark functions that return by reference. Note that it cannot be
diff --git a/gcc/ada/exp_disp.adb b/gcc/ada/exp_disp.adb
index 8bb0cac38db..ea82dd339f4 100644
--- a/gcc/ada/exp_disp.adb
+++ b/gcc/ada/exp_disp.adb
@@ -26,41 +26,49 @@
with Atree; use Atree;
with Checks; use Checks;
+with Debug; use Debug;
with Einfo; use Einfo;
with Elists; use Elists;
with Errout; use Errout;
with Exp_Ch7; use Exp_Ch7;
with Exp_Tss; use Exp_Tss;
with Exp_Util; use Exp_Util;
-with Fname; use Fname;
with Itypes; use Itypes;
-with Lib; use Lib;
with Nlists; use Nlists;
with Nmake; use Nmake;
+with Namet; use Namet;
with Opt; use Opt;
+with Output; use Output;
with Rtsfind; use Rtsfind;
+with Sem; use Sem;
with Sem_Disp; use Sem_Disp;
with Sem_Res; use Sem_Res;
+with Sem_Type; use Sem_Type;
with Sem_Util; use Sem_Util;
with Sinfo; use Sinfo;
with Snames; use Snames;
with Stand; use Stand;
with Tbuild; use Tbuild;
+with Ttypes; use Ttypes;
with Uintp; use Uintp;
package body Exp_Disp is
Ada_Actions : constant array (DT_Access_Action) of RE_Id :=
(CW_Membership => RE_CW_Membership,
+ IW_Membership => RE_IW_Membership,
DT_Entry_Size => RE_DT_Entry_Size,
DT_Prologue_Size => RE_DT_Prologue_Size,
+ Get_Access_Level => RE_Get_Access_Level,
Get_External_Tag => RE_Get_External_Tag,
Get_Prim_Op_Address => RE_Get_Prim_Op_Address,
Get_RC_Offset => RE_Get_RC_Offset,
Get_Remotely_Callable => RE_Get_Remotely_Callable,
Inherit_DT => RE_Inherit_DT,
Inherit_TSD => RE_Inherit_TSD,
+ Register_Interface_Tag => RE_Register_Interface_Tag,
Register_Tag => RE_Register_Tag,
+ Set_Access_Level => RE_Set_Access_Level,
Set_Expanded_Name => RE_Set_Expanded_Name,
Set_External_Tag => RE_Set_External_Tag,
Set_Prim_Op_Address => RE_Set_Prim_Op_Address,
@@ -70,37 +78,21 @@ package body Exp_Disp is
TSD_Entry_Size => RE_TSD_Entry_Size,
TSD_Prologue_Size => RE_TSD_Prologue_Size);
- CPP_Actions : constant array (DT_Access_Action) of RE_Id :=
- (CW_Membership => RE_CPP_CW_Membership,
- DT_Entry_Size => RE_CPP_DT_Entry_Size,
- DT_Prologue_Size => RE_CPP_DT_Prologue_Size,
- Get_External_Tag => RE_CPP_Get_External_Tag,
- Get_Prim_Op_Address => RE_CPP_Get_Prim_Op_Address,
- Get_RC_Offset => RE_CPP_Get_RC_Offset,
- Get_Remotely_Callable => RE_CPP_Get_Remotely_Callable,
- Inherit_DT => RE_CPP_Inherit_DT,
- Inherit_TSD => RE_CPP_Inherit_TSD,
- Register_Tag => RE_CPP_Register_Tag,
- Set_Expanded_Name => RE_CPP_Set_Expanded_Name,
- Set_External_Tag => RE_CPP_Set_External_Tag,
- Set_Prim_Op_Address => RE_CPP_Set_Prim_Op_Address,
- Set_RC_Offset => RE_CPP_Set_RC_Offset,
- Set_Remotely_Callable => RE_CPP_Set_Remotely_Callable,
- Set_TSD => RE_CPP_Set_TSD,
- TSD_Entry_Size => RE_CPP_TSD_Entry_Size,
- TSD_Prologue_Size => RE_CPP_TSD_Prologue_Size);
-
Action_Is_Proc : constant array (DT_Access_Action) of Boolean :=
(CW_Membership => False,
+ IW_Membership => False,
DT_Entry_Size => False,
DT_Prologue_Size => False,
+ Get_Access_Level => False,
Get_External_Tag => False,
Get_Prim_Op_Address => False,
Get_Remotely_Callable => False,
Get_RC_Offset => False,
Inherit_DT => True,
Inherit_TSD => True,
+ Register_Interface_Tag => True,
Register_Tag => True,
+ Set_Access_Level => True,
Set_Expanded_Name => True,
Set_External_Tag => True,
Set_Prim_Op_Address => True,
@@ -112,15 +104,19 @@ package body Exp_Disp is
Action_Nb_Arg : constant array (DT_Access_Action) of Int :=
(CW_Membership => 2,
+ IW_Membership => 2,
DT_Entry_Size => 0,
DT_Prologue_Size => 0,
+ Get_Access_Level => 1,
Get_External_Tag => 1,
Get_Prim_Op_Address => 2,
Get_RC_Offset => 1,
Get_Remotely_Callable => 1,
Inherit_DT => 3,
Inherit_TSD => 2,
+ Register_Interface_Tag => 2,
Register_Tag => 1,
+ Set_Access_Level => 2,
Set_Expanded_Name => 2,
Set_External_Tag => 2,
Set_Prim_Op_Address => 3,
@@ -130,10 +126,194 @@ package body Exp_Disp is
TSD_Entry_Size => 0,
TSD_Prologue_Size => 0);
+ function Build_Anonymous_Access_Type
+ (Directly_Designated_Type : Entity_Id;
+ Related_Nod : Node_Id) return Entity_Id;
+ -- Returns a decorated entity corresponding with an anonymous access type.
+ -- Used to generate unchecked type conversion of an address.
+
+ procedure Collect_All_Interfaces (T : Entity_Id);
+ -- Ada 2005 (AI-251): Collect the whole list of interfaces that are
+ -- directly or indirectly implemented by T. Used to compute the size
+ -- of the table of interfaces.
+
+ function Default_Prim_Op_Position (Subp : Entity_Id) return Uint;
+ -- Ada 2005 (AI-251): Returns the fixed position in the dispatch table
+ -- of the default primitive operations.
+
function Original_View_In_Visible_Part (Typ : Entity_Id) return Boolean;
-- Check if the type has a private view or if the public view appears
-- in the visible part of a package spec.
+ ----------------------------------
+ -- Build_Anonymous_Access_Type --
+ ----------------------------------
+
+ function Build_Anonymous_Access_Type
+ (Directly_Designated_Type : Entity_Id;
+ Related_Nod : Node_Id) return Entity_Id
+ is
+ New_E : Entity_Id;
+
+ begin
+ New_E := Create_Itype (Ekind => E_Anonymous_Access_Type,
+ Related_Nod => Related_Nod,
+ Scope_Id => Current_Scope);
+
+ Set_Etype (New_E, New_E);
+ Init_Size_Align (New_E);
+ Init_Size (New_E, System_Address_Size);
+ Set_Directly_Designated_Type (New_E, Directly_Designated_Type);
+ Set_Is_First_Subtype (New_E);
+
+ return New_E;
+ end Build_Anonymous_Access_Type;
+
+ ----------------------------
+ -- Collect_All_Interfaces --
+ ----------------------------
+
+ procedure Collect_All_Interfaces (T : Entity_Id) is
+
+ procedure Add_Interface (Iface : Entity_Id);
+ -- Add the interface it if is not already in the list
+
+ procedure Collect (Typ : Entity_Id);
+ -- Subsidiary subprogram used to traverse the whole list
+ -- of directly and indirectly implemented interfaces
+
+ -------------------
+ -- Add_Interface --
+ -------------------
+
+ procedure Add_Interface (Iface : Entity_Id) is
+ Elmt : Elmt_Id := First_Elmt (Abstract_Interfaces (T));
+
+ begin
+ while Present (Elmt) and then Node (Elmt) /= Iface loop
+ Next_Elmt (Elmt);
+ end loop;
+
+ if not Present (Elmt) then
+ Append_Elmt (Iface, Abstract_Interfaces (T));
+ end if;
+ end Add_Interface;
+
+ -------------
+ -- Collect --
+ -------------
+
+ procedure Collect (Typ : Entity_Id) is
+ Nod : constant Node_Id := Type_Definition (Parent (Typ));
+ Id : Node_Id;
+ Iface : Entity_Id;
+ Ancestor : Entity_Id;
+
+ begin
+ pragma Assert (False
+ or else Nkind (Nod) = N_Derived_Type_Definition
+ or else Nkind (Nod) = N_Record_Definition);
+
+ if Nkind (Nod) = N_Record_Definition then
+ return;
+ end if;
+
+ -- Include the ancestor if we are generating the whole list
+ -- of interfaces. This is used to know the size of the table
+ -- that stores the tag of all the ancestor interfaces.
+
+ Ancestor := Etype (Typ);
+
+ if Is_Interface (Ancestor) then
+ Add_Interface (Ancestor);
+ end if;
+
+ if Ancestor /= Typ
+ and then Ekind (Ancestor) /= E_Record_Type_With_Private
+ then
+ Collect (Ancestor);
+ end if;
+
+ -- Traverse the graph of ancestor interfaces
+
+ if Is_Non_Empty_List (Interface_List (Nod)) then
+ Id := First (Interface_List (Nod));
+
+ while Present (Id) loop
+
+ Iface := Etype (Id);
+
+ if Is_Interface (Iface) then
+ Add_Interface (Iface);
+ Collect (Iface);
+ end if;
+
+ Next (Id);
+ end loop;
+ end if;
+ end Collect;
+
+ -- Start of processing for Collect_All_Interfaces
+
+ begin
+ Collect (T);
+ end Collect_All_Interfaces;
+
+ ------------------------------
+ -- Default_Prim_Op_Position --
+ ------------------------------
+
+ function Default_Prim_Op_Position (Subp : Entity_Id) return Uint is
+ TSS_Name : TSS_Name_Type;
+ E : Entity_Id := Subp;
+
+ begin
+ -- Handle overriden subprograms
+
+ while Present (Alias (E)) loop
+ E := Alias (E);
+ end loop;
+
+ Get_Name_String (Chars (E));
+ TSS_Name :=
+ TSS_Name_Type
+ (Name_Buffer (Name_Len - TSS_Name'Length + 1 .. Name_Len));
+
+ if Chars (E) = Name_uSize then
+ return Uint_1;
+
+ elsif Chars (E) = Name_uAlignment then
+ return Uint_2;
+
+ elsif TSS_Name = TSS_Stream_Read then
+ return Uint_3;
+
+ elsif TSS_Name = TSS_Stream_Write then
+ return Uint_4;
+
+ elsif TSS_Name = TSS_Stream_Input then
+ return Uint_5;
+
+ elsif TSS_Name = TSS_Stream_Output then
+ return Uint_6;
+
+ elsif Chars (E) = Name_Op_Eq then
+ return Uint_7;
+
+ elsif Chars (E) = Name_uAssign then
+ return Uint_8;
+
+ elsif TSS_Name = TSS_Deep_Adjust then
+ return Uint_9;
+
+ elsif TSS_Name = TSS_Deep_Finalize then
+ return Uint_10;
+
+ else
+ raise Program_Error;
+ end if;
+ end Default_Prim_Op_Position;
+
-----------------------------
-- Expand_Dispatching_Call --
-----------------------------
@@ -247,7 +427,9 @@ package body Exp_Disp is
-- This capability of dispatching directly by tag is also needed by the
-- implementation of AI-260 (for the generic dispatching constructors).
- if Etype (Ctrl_Arg) = RTE (RE_Tag) then
+ if Etype (Ctrl_Arg) = RTE (RE_Tag)
+ or else Etype (Ctrl_Arg) = RTE (RE_Interface_Tag)
+ then
CW_Typ := Class_Wide_Type (Controlling_Type (Subp));
elsif Is_Access_Type (Etype (Ctrl_Arg)) then
@@ -270,47 +452,7 @@ package body Exp_Disp is
New_Params := New_List;
Param := First_Actual (Call_Node);
while Present (Param) loop
-
- -- We assume that dispatching through the main dispatch table
- -- (referenced by Tag_Component) doesn't require a displacement
- -- so the expansion below is only done when dispatching on
- -- another vtable pointer, in which case the first argument
- -- is expanded into :
-
- -- typ!(Displaced_This (Address!(Param)))
-
- if Param = Ctrl_Arg
- and then DTC_Entity (Subp) /= First_Tag_Component (Typ)
- then
- Append_To (New_Params,
-
- Unchecked_Convert_To (Etype (Param),
- Make_Function_Call (Loc,
- Name => New_Reference_To (RTE (RE_Displaced_This), Loc),
- Parameter_Associations => New_List (
-
- -- Current_This
-
- Make_Unchecked_Type_Conversion (Loc,
- Subtype_Mark =>
- New_Reference_To (RTE (RE_Address), Loc),
- Expression => Relocate_Node (Param)),
-
- -- Vptr
-
- Make_Selected_Component (Loc,
- Prefix => Duplicate_Subexpr (Ctrl_Arg),
- Selector_Name =>
- New_Reference_To (DTC_Entity (Subp), Loc)),
-
- -- Position
-
- Make_Integer_Literal (Loc, DT_Position (Subp))))));
-
- else
- Append_To (New_Params, Relocate_Node (Param));
- end if;
-
+ Append_To (New_Params, Relocate_Node (Param));
Next_Actual (Param);
end loop;
@@ -493,7 +635,9 @@ package body Exp_Disp is
-- use it directly. Otherwise, the tag must be extracted from
-- the controlling object.
- if Etype (Ctrl_Arg) = RTE (RE_Tag) then
+ if Etype (Ctrl_Arg) = RTE (RE_Tag)
+ or else Etype (Ctrl_Arg) = RTE (RE_Interface_Tag)
+ then
Controlling_Tag := Duplicate_Subexpr (Ctrl_Arg);
else
@@ -521,37 +665,64 @@ package body Exp_Disp is
Make_Integer_Literal (Loc, DT_Position (Subp)))));
if Nkind (Call_Node) = N_Function_Call then
- New_Call :=
- Make_Function_Call (Loc,
- Name => New_Call_Name,
- Parameter_Associations => New_Params);
- -- If this is a dispatching "=", we must first compare the tags so
- -- we generate: x.tag = y.tag and then x = y
+ -- Ada 2005 (AI-251): A dispatching "=" with an abstract interface
+ -- just requires the comparison of the tags.
- if Subp = Eq_Prim_Op then
+ if Ekind (Etype (Ctrl_Arg)) = E_Class_Wide_Type
+ and then Is_Interface (Etype (Ctrl_Arg))
+ and then Subp = Eq_Prim_Op
+ then
Param := First_Actual (Call_Node);
- New_Call :=
- Make_And_Then (Loc,
- Left_Opnd =>
- Make_Op_Eq (Loc,
- Left_Opnd =>
- Make_Selected_Component (Loc,
- Prefix => New_Value (Param),
- Selector_Name =>
- New_Reference_To
- (First_Tag_Component (Typ), Loc)),
- Right_Opnd =>
- Make_Selected_Component (Loc,
- Prefix =>
- Unchecked_Convert_To (Typ,
- New_Value (Next_Actual (Param))),
- Selector_Name =>
- New_Reference_To
- (First_Tag_Component (Typ), Loc))),
+ New_Call :=
+ Make_Op_Eq (Loc,
+ Left_Opnd =>
+ Make_Selected_Component (Loc,
+ Prefix => New_Value (Param),
+ Selector_Name =>
+ New_Reference_To (First_Tag_Component (Typ), Loc)),
+
+ Right_Opnd =>
+ Make_Selected_Component (Loc,
+ Prefix =>
+ Unchecked_Convert_To (Typ,
+ New_Value (Next_Actual (Param))),
+ Selector_Name =>
+ New_Reference_To (First_Tag_Component (Typ), Loc)));
- Right_Opnd => New_Call);
+ else
+ New_Call :=
+ Make_Function_Call (Loc,
+ Name => New_Call_Name,
+ Parameter_Associations => New_Params);
+
+ -- If this is a dispatching "=", we must first compare the tags so
+ -- we generate: x.tag = y.tag and then x = y
+
+ if Subp = Eq_Prim_Op then
+ Param := First_Actual (Call_Node);
+ New_Call :=
+ Make_And_Then (Loc,
+ Left_Opnd =>
+ Make_Op_Eq (Loc,
+ Left_Opnd =>
+ Make_Selected_Component (Loc,
+ Prefix => New_Value (Param),
+ Selector_Name =>
+ New_Reference_To (First_Tag_Component (Typ),
+ Loc)),
+
+ Right_Opnd =>
+ Make_Selected_Component (Loc,
+ Prefix =>
+ Unchecked_Convert_To (Typ,
+ New_Value (Next_Actual (Param))),
+ Selector_Name =>
+ New_Reference_To (First_Tag_Component (Typ),
+ Loc))),
+ Right_Opnd => New_Call);
+ end if;
end if;
else
@@ -565,30 +736,478 @@ package body Exp_Disp is
Analyze_And_Resolve (Call_Node, Call_Typ);
end Expand_Dispatching_Call;
+ ---------------------------------
+ -- Expand_Interface_Conversion --
+ ---------------------------------
+
+ procedure Expand_Interface_Conversion (N : Node_Id) is
+ Loc : constant Source_Ptr := Sloc (N);
+ Operand : constant Node_Id := Expression (N);
+ Operand_Typ : Entity_Id := Etype (Operand);
+ Target_Type : Entity_Id := Etype (N);
+ Iface_Tag : Entity_Id;
+
+ begin
+ pragma Assert (Nkind (Operand) /= N_Attribute_Reference);
+
+ -- Ada 2005 (AI-345): Set Operand_Typ and Handle task interfaces
+
+ if Ekind (Operand_Typ) = E_Task_Type
+ or else Ekind (Operand_Typ) = E_Protected_Type
+ then
+ Operand_Typ := Corresponding_Record_Type (Operand_Typ);
+ end if;
+
+ if Is_Access_Type (Target_Type) then
+ Target_Type := Etype (Directly_Designated_Type (Target_Type));
+
+ elsif Is_Class_Wide_Type (Target_Type) then
+ Target_Type := Etype (Target_Type);
+ end if;
+
+ pragma Assert (not Is_Class_Wide_Type (Target_Type)
+ and then Is_Interface (Target_Type));
+
+ Iface_Tag := Find_Interface_Tag (Operand_Typ, Target_Type);
+
+ pragma Assert (Iface_Tag /= Empty);
+
+ Rewrite (N,
+ Unchecked_Convert_To (Etype (N),
+ Make_Attribute_Reference (Loc,
+ Prefix => Make_Selected_Component (Loc,
+ Prefix => Relocate_Node (Expression (N)),
+ Selector_Name => New_Occurrence_Of (Iface_Tag, Loc)),
+ Attribute_Name => Name_Address)));
+
+ Analyze (N);
+ end Expand_Interface_Conversion;
+
+ ------------------------------
+ -- Expand_Interface_Actuals --
+ ------------------------------
+
+ procedure Expand_Interface_Actuals (Call_Node : Node_Id) is
+ Loc : constant Source_Ptr := Sloc (Call_Node);
+ Actual : Node_Id;
+ Actual_Typ : Entity_Id;
+ Conversion : Node_Id;
+ Formal : Entity_Id;
+ Formal_Typ : Entity_Id;
+ Subp : Entity_Id;
+ Nam : Name_Id;
+
+ begin
+ -- This subprogram is called directly from the semantics, so we need a
+ -- check to see whether expansion is active before proceeding.
+
+ if not Expander_Active then
+ return;
+ end if;
+
+ -- Call using access to subprogram with explicit dereference
+
+ if Nkind (Name (Call_Node)) = N_Explicit_Dereference then
+ Subp := Etype (Name (Call_Node));
+
+ -- Normal case
+
+ else
+ Subp := Entity (Name (Call_Node));
+ end if;
+
+ Formal := First_Formal (Subp);
+ Actual := First_Actual (Call_Node);
+
+ while Present (Formal) loop
+
+ pragma Assert (Ekind (Etype (Etype (Formal)))
+ /= E_Record_Type_With_Private);
+
+ -- Ada 2005 (AI-251): Conversion to interface to force "this"
+ -- displacement
+
+ Formal_Typ := Etype (Etype (Formal));
+ Actual_Typ := Etype (Actual);
+
+ if Is_Interface (Formal_Typ) then
+
+ Conversion := Convert_To (Formal_Typ, New_Copy_Tree (Actual));
+ Rewrite (Actual, Conversion);
+ Analyze_And_Resolve (Actual, Formal_Typ);
+
+ Rewrite (Actual,
+ Make_Explicit_Dereference (Loc,
+ Unchecked_Convert_To
+ (Build_Anonymous_Access_Type (Formal_Typ, Call_Node),
+ Relocate_Node (Expression (Actual)))));
+
+ Analyze_And_Resolve (Actual, Formal_Typ);
+
+ -- Anonymous access type
+
+ elsif Is_Access_Type (Formal_Typ)
+ and then Is_Interface (Etype
+ (Directly_Designated_Type
+ (Formal_Typ)))
+ and then Interface_Present_In_Ancestor
+ (Typ => Etype (Directly_Designated_Type
+ (Actual_Typ)),
+ Iface => Etype (Directly_Designated_Type
+ (Formal_Typ)))
+ then
+
+ if Nkind (Actual) = N_Attribute_Reference
+ and then
+ (Attribute_Name (Actual) = Name_Access
+ or else Attribute_Name (Actual) = Name_Unchecked_Access)
+ then
+ Nam := Attribute_Name (Actual);
+
+ Conversion :=
+ Convert_To
+ (Etype (Directly_Designated_Type (Formal_Typ)),
+ Prefix (Actual));
+
+ Rewrite (Actual, Conversion);
+
+ Analyze_And_Resolve (Actual,
+ Etype (Directly_Designated_Type (Formal_Typ)));
+
+ Rewrite (Actual,
+ Unchecked_Convert_To (Formal_Typ,
+ Make_Attribute_Reference (Loc,
+ Prefix =>
+ Relocate_Node (Prefix (Expression (Actual))),
+ Attribute_Name => Nam)));
+
+ Analyze_And_Resolve (Actual, Formal_Typ);
+
+ else
+ Conversion :=
+ Convert_To (Formal_Typ, New_Copy_Tree (Actual));
+ Rewrite (Actual, Conversion);
+ Analyze_And_Resolve (Actual, Formal_Typ);
+ end if;
+ end if;
+
+ Next_Actual (Actual);
+ Next_Formal (Formal);
+ end loop;
+ end Expand_Interface_Actuals;
+
+ ----------------------------
+ -- Expand_Interface_Thunk --
+ ----------------------------
+
+ function Expand_Interface_Thunk
+ (N : Node_Id;
+ Thunk_Id : Entity_Id;
+ Iface_Tag : Entity_Id) return Node_Id
+ is
+ Loc : constant Source_Ptr := Sloc (N);
+ Actuals : constant List_Id := New_List;
+ Decl : constant List_Id := New_List;
+ Formals : constant List_Id := New_List;
+ Thunk_Tag : constant Node_Id := Iface_Tag;
+ Thunk_Alias : constant Entity_Id := Alias (Entity (N));
+ Target : Entity_Id;
+ New_Code : Node_Id;
+ Formal : Node_Id;
+ New_Formal : Node_Id;
+ Decl_1 : Node_Id;
+ Decl_2 : Node_Id;
+ Subtyp_Mark : Node_Id;
+
+ begin
+
+ -- Traverse the list of alias to find the final target
+
+ Target := Thunk_Alias;
+
+ while Present (Alias (Target)) loop
+ Target := Alias (Target);
+ end loop;
+
+ -- Duplicate the formals
+
+ Formal := First_Formal (Thunk_Alias);
+
+ while Present (Formal) loop
+ New_Formal := Copy_Separate_Tree (Parent (Formal));
+
+ -- Handle the case in which the subprogram covering
+ -- the interface has been inherited:
+
+ -- Example:
+ -- type I is interface;
+ -- procedure P (X : in I) is abstract;
+
+ -- type T is tagged null record;
+ -- procedure P (X : T);
+
+ -- type DT is new T and I with ...
+
+ if Is_Controlling_Formal (Formal) then
+ Set_Parameter_Type (New_Formal,
+ New_Reference_To (Etype (First_Entity (Entity (N))), Loc));
+
+ -- Why is this line silently commented out ???
+
+ -- New_Reference_To (Etype (Formal), Loc));
+ end if;
+
+ Append_To (Formals, New_Formal);
+ Next_Formal (Formal);
+ end loop;
+
+ if Ekind (First_Formal (Thunk_Alias)) = E_In_Parameter
+ and then Ekind (Etype (First_Formal (Thunk_Alias)))
+ = E_Anonymous_Access_Type
+ then
+
+ -- Generate:
+
+ -- type T is access all <<type of the first formal>>
+ -- S1 := Storage_Offset!(First_formal)
+ -- - Storage_Offset!(First_Formal.Thunk_Tag'Position)
+
+ -- ... and the first actual of the call is generated as T!(S1)
+
+ Decl_2 :=
+ Make_Full_Type_Declaration (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Loc,
+ New_Internal_Name ('T')),
+ Type_Definition =>
+ Make_Access_To_Object_Definition (Loc,
+ All_Present => True,
+ Null_Exclusion_Present => False,
+ Constant_Present => False,
+ Subtype_Indication =>
+ New_Reference_To
+ (Directly_Designated_Type
+ (Etype (First_Formal (Thunk_Alias))), Loc)
+ ));
+
+ Decl_1 :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Loc,
+ New_Internal_Name ('S')),
+ Constant_Present => True,
+ Object_Definition =>
+ New_Reference_To (RTE (RE_Storage_Offset), Loc),
+ Expression =>
+ Make_Op_Subtract (Loc,
+ Left_Opnd =>
+ Unchecked_Convert_To
+ (RTE (RE_Storage_Offset),
+ New_Reference_To
+ (Defining_Identifier (First (Formals)), Loc)),
+ Right_Opnd =>
+ Unchecked_Convert_To
+ (RTE (RE_Storage_Offset),
+ Make_Attribute_Reference (Loc,
+ Prefix =>
+ Make_Selected_Component (Loc,
+ Prefix =>
+ New_Reference_To
+ (Defining_Identifier (First (Formals)), Loc),
+ Selector_Name =>
+ New_Occurrence_Of (Thunk_Tag, Loc)),
+ Attribute_Name => Name_Position))));
+
+ Append_To (Decl, Decl_2);
+ Append_To (Decl, Decl_1);
+
+ -- Reference the new first actual
+
+ Append_To (Actuals,
+ Unchecked_Convert_To
+ (Defining_Identifier (Decl_2),
+ New_Reference_To (Defining_Identifier (Decl_1), Loc)));
+
+ -- Side note: The reverse order of declarations is just to ensure
+ -- that the call to RE_Print is correct.
+
+ else
+ -- Generate:
+ --
+ -- S1 := Storage_Offset!(First_formal'Address)
+ -- - Storage_Offset!(First_Formal.Thunk_Tag'Position)
+ -- S2 := Tag_Ptr!(S3)
+
+ Decl_1 :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Loc, New_Internal_Name ('S')),
+ Constant_Present => True,
+ Object_Definition =>
+ New_Reference_To (RTE (RE_Storage_Offset), Loc),
+ Expression =>
+ Make_Op_Subtract (Loc,
+ Left_Opnd =>
+ Unchecked_Convert_To
+ (RTE (RE_Storage_Offset),
+ Make_Attribute_Reference (Loc,
+ Prefix =>
+ New_Reference_To
+ (Defining_Identifier (First (Formals)), Loc),
+ Attribute_Name => Name_Address)),
+ Right_Opnd =>
+ Unchecked_Convert_To
+ (RTE (RE_Storage_Offset),
+ Make_Attribute_Reference (Loc,
+ Prefix =>
+ Make_Selected_Component (Loc,
+ Prefix =>
+ New_Reference_To
+ (Defining_Identifier (First (Formals)), Loc),
+ Selector_Name =>
+ New_Occurrence_Of (Thunk_Tag, Loc)),
+ Attribute_Name => Name_Position))));
+
+ Decl_2 :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Loc, New_Internal_Name ('S')),
+ Constant_Present => True,
+ Object_Definition => New_Reference_To (RTE (RE_Addr_Ptr), Loc),
+ Expression =>
+ Unchecked_Convert_To
+ (RTE (RE_Addr_Ptr),
+ New_Reference_To (Defining_Identifier (Decl_1), Loc)));
+
+ Append_To (Decl, Decl_1);
+ Append_To (Decl, Decl_2);
+
+ -- Reference the new first actual
+
+ Append_To (Actuals,
+ Unchecked_Convert_To
+ (Etype (First_Entity (Target)),
+ Make_Explicit_Dereference (Loc,
+ New_Reference_To (Defining_Identifier (Decl_2), Loc))));
+
+ end if;
+
+ Formal := Next (First (Formals));
+ while Present (Formal) loop
+ Append_To (Actuals,
+ New_Reference_To (Defining_Identifier (Formal), Loc));
+ Next (Formal);
+ end loop;
+
+ if Ekind (Thunk_Alias) = E_Procedure then
+ New_Code :=
+ Make_Subprogram_Body (Loc,
+ Specification =>
+ Make_Procedure_Specification (Loc,
+ Defining_Unit_Name => Thunk_Id,
+ Parameter_Specifications => Formals),
+ Declarations => Decl,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (
+ Make_Procedure_Call_Statement (Loc,
+ Name => New_Occurrence_Of (Target, Loc),
+ Parameter_Associations => Actuals))));
+
+ else pragma Assert (Ekind (Thunk_Alias) = E_Function);
+
+ if not Present (Alias (Thunk_Alias)) then
+ Subtyp_Mark := Subtype_Mark (Parent (Thunk_Alias));
+ else
+ -- The last element in the alias list has the correct subtype_mark
+ -- of the function result
+
+ declare
+ E : Entity_Id := Alias (Thunk_Alias);
+ begin
+ while Present (Alias (E)) loop
+ E := Alias (E);
+ end loop;
+ Subtyp_Mark := Subtype_Mark (Parent (E));
+ end;
+ end if;
+
+ New_Code :=
+ Make_Subprogram_Body (Loc,
+ Specification =>
+ Make_Function_Specification (Loc,
+ Defining_Unit_Name => Thunk_Id,
+ Parameter_Specifications => Formals,
+ Subtype_Mark => New_Copy (Subtyp_Mark)),
+ Declarations => Decl,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (
+ Make_Return_Statement (Loc,
+ Make_Function_Call (Loc,
+ Name => New_Occurrence_Of (Target, Loc),
+ Parameter_Associations => Actuals)))));
+ end if;
+
+ Analyze (New_Code);
+ Insert_After (N, New_Code);
+ return New_Code;
+ end Expand_Interface_Thunk;
+
-------------
-- Fill_DT --
-------------
function Fill_DT_Entry
- (Loc : Source_Ptr;
- Prim : Entity_Id)
- return Node_Id
+ (Loc : Source_Ptr;
+ Prim : Entity_Id;
+ Thunk_Id : Entity_Id := Empty) return Node_Id
is
- Typ : constant Entity_Id := Scope (DTC_Entity (Prim));
- DT_Ptr : constant Entity_Id := Node (First_Elmt
- (Access_Disp_Table (Typ)));
+ Typ : constant Entity_Id := Scope (DTC_Entity (Prim));
+ DT_Ptr : Entity_Id := Node (First_Elmt (Access_Disp_Table (Typ)));
+ Target : Entity_Id;
+ Tag : Entity_Id := First_Tag_Component (Typ);
+ Prim_Op : Entity_Id := Prim;
begin
+ -- Ada 2005 (AI-251): If we have a thunk available then generate code
+ -- that saves its address in the secondary dispatch table of its
+ -- abstract interface; otherwise save the address of the primitive
+ -- subprogram in the main virtual table.
+
+ if Thunk_Id /= Empty then
+ Target := Thunk_Id;
+ else
+ Target := Prim;
+ end if;
+
+ -- Ada 2005 (AI-251): If the subprogram is the alias of an abstract
+ -- interface subprogram then find the correct dispatch table pointer
+
+ if Present (Abstract_Interface_Alias (Prim)) then
+ Prim_Op := Abstract_Interface_Alias (Prim);
+
+ DT_Ptr := Find_Interface_ADT
+ (T => Typ,
+ Iface => Scope (DTC_Entity (Prim_Op)));
+
+ Tag := First_Tag_Component (Scope (DTC_Entity (Prim_Op)));
+ end if;
+
+ pragma Assert (DT_Position (Prim_Op) <= DT_Entry_Count (Tag));
+ pragma Assert (DT_Position (Prim_Op) > Uint_0);
+
return
Make_DT_Access_Action (Typ,
Action => Set_Prim_Op_Address,
Args => New_List (
- New_Reference_To (DT_Ptr, Loc), -- DTptr
+ Unchecked_Convert_To (RTE (RE_Tag),
+ New_Reference_To (DT_Ptr, Loc)), -- DTptr
- Make_Integer_Literal (Loc, DT_Position (Prim)), -- Position
+ Make_Integer_Literal (Loc, DT_Position (Prim_Op)), -- Position
Make_Attribute_Reference (Loc, -- Value
- Prefix => New_Reference_To (Prim, Loc),
+ Prefix => New_Reference_To (Target, Loc),
Attribute_Name => Name_Address)));
end Fill_DT_Entry;
@@ -614,11 +1233,9 @@ package body Exp_Disp is
-------------
function Make_DT (Typ : Entity_Id) return List_Id is
- Loc : constant Source_Ptr := Sloc (Typ);
-
- ADT_List : constant Elist_Id := New_Elmt_List;
- Result : constant List_Id := New_List;
- Elab_Code : constant List_Id := New_List;
+ Loc : constant Source_Ptr := Sloc (Typ);
+ Result : constant List_Id := New_List;
+ Elab_Code : constant List_Id := New_List;
Tname : constant Name_Id := Chars (Typ);
Name_DT : constant Name_Id := New_External_Name (Tname, 'T');
@@ -633,11 +1250,16 @@ package body Exp_Disp is
Exname : constant Node_Id := Make_Defining_Identifier (Loc, Name_Exname);
No_Reg : constant Node_Id := Make_Defining_Identifier (Loc, Name_No_Reg);
+ Generalized_Tag : constant Entity_Id := RTE (RE_Tag);
I_Depth : Int;
- Generalized_Tag : Entity_Id;
Size_Expr_Node : Node_Id;
Old_Tag1 : Node_Id;
Old_Tag2 : Node_Id;
+ Num_Ifaces : Int;
+ Nb_Prim : Int;
+ TSD_Num_Entries : Int;
+ Typ_Copy : constant Entity_Id := New_Copy (Typ);
+ AI : Elmt_Id;
begin
if not RTE_Available (RE_Tag) then
@@ -645,11 +1267,52 @@ package body Exp_Disp is
return New_List;
end if;
- if Is_CPP_Class (Root_Type (Typ)) then
- Generalized_Tag := RTE (RE_Vtable_Ptr);
- else
- Generalized_Tag := RTE (RE_Tag);
- end if;
+ -- Collect the full list of directly and indirectly implemented
+ -- interfaces
+
+ Set_Parent (Typ_Copy, Parent (Typ));
+ Set_Abstract_Interfaces (Typ_Copy, New_Elmt_List);
+ Collect_All_Interfaces (Typ_Copy);
+
+ -- Calculate the number of entries required in the table of interfaces
+
+ Num_Ifaces := 0;
+ AI := First_Elmt (Abstract_Interfaces (Typ_Copy));
+
+ while Present (AI) loop
+ Num_Ifaces := Num_Ifaces + 1;
+ Next_Elmt (AI);
+ end loop;
+
+ -- Count ancestors to compute the inheritance depth. For private
+ -- extensions, always go to the full view in order to compute the real
+ -- inheritance depth.
+
+ declare
+ Parent_Type : Entity_Id := Typ;
+ P : Entity_Id;
+
+ begin
+ I_Depth := 0;
+
+ loop
+ P := Etype (Parent_Type);
+
+ if Is_Private_Type (P) then
+ P := Full_View (Base_Type (P));
+ end if;
+
+ exit when P = Parent_Type;
+
+ I_Depth := I_Depth + 1;
+ Parent_Type := P;
+ end loop;
+ end;
+
+ TSD_Num_Entries := I_Depth + Num_Ifaces + 1;
+ Nb_Prim := UI_To_Int (DT_Entry_Count (First_Tag_Component (Typ)));
+
+ -- ----------------------------------------------------------------
-- Dispatch table and related entities are allocated statically
@@ -681,8 +1344,7 @@ package body Exp_Disp is
Left_Opnd =>
Make_DT_Access_Action (Typ, DT_Entry_Size, No_List),
Right_Opnd =>
- Make_Integer_Literal (Loc,
- DT_Entry_Count (First_Tag_Component (Typ)))));
+ Make_Integer_Literal (Loc, Nb_Prim)));
Append_To (Result,
Make_Object_Declaration (Loc,
@@ -708,14 +1370,11 @@ package body Exp_Disp is
-- Generate code to create the pointer to the dispatch table
- -- DT_Ptr : Tag := Tag!(DT'Address); Ada case
- -- or
- -- DT_Ptr : Vtable_Ptr := Vtable_Ptr!(DT'Address); CPP case
+ -- DT_Ptr : Tag := Tag!(DT'Address);
- -- According to the C++ ABI, the base of the vtable is located
- -- after the following prologue: Offset_To_Top, Typeinfo_Ptr.
- -- Hence, move the pointer to the base of the vtable down, after
- -- this prologue.
+ -- According to the C++ ABI, the base of the vtable is located after a
+ -- prologue containing Offset_To_Top, and Typeinfo_Ptr. Hence, we move
+ -- down the pointer to the real base of the vtable
Append_To (Result,
Make_Object_Declaration (Loc,
@@ -746,37 +1405,18 @@ package body Exp_Disp is
-- Set Access_Disp_Table field to be the dispatch table pointer
- Append_Elmt (DT_Ptr, ADT_List);
- Set_Access_Disp_Table (Typ, ADT_List);
-
- -- Count ancestors to compute the inheritance depth. For private
- -- extensions, always go to the full view in order to compute the real
- -- inheritance depth.
-
- declare
- Parent_Type : Entity_Id := Typ;
- P : Entity_Id;
-
- begin
- I_Depth := 0;
-
- loop
- P := Etype (Parent_Type);
-
- if Is_Private_Type (P) then
- P := Full_View (Base_Type (P));
- end if;
-
- exit when P = Parent_Type;
+ if not Present (Access_Disp_Table (Typ)) then
+ Set_Access_Disp_Table (Typ, New_Elmt_List);
+ end if;
- I_Depth := I_Depth + 1;
- Parent_Type := P;
- end loop;
- end;
+ Prepend_Elmt (DT_Ptr, Access_Disp_Table (Typ));
-- Generate code to create the storage for the type specific data object
-
- -- TSD: Storage_Array (1..TSD_Prologue_Size+(1+Idepth)*TSD_Entry_Size);
+ -- with enough space to store the tags of the ancestors plus the tags
+ -- of all the implemented interfaces (as described in a-tags.adb)
+ --
+ -- TSD: Storage_Array
+ -- (1..TSD_Prologue_Size+TSD_Num_Entries*TSD_Entry_Size);
-- for TSD'Alignment use Address'Alignment
Size_Expr_Node :=
@@ -788,10 +1428,7 @@ package body Exp_Disp is
Left_Opnd =>
Make_DT_Access_Action (Typ, TSD_Entry_Size, No_List),
Right_Opnd =>
- Make_Op_Add (Loc,
- Left_Opnd => Make_Integer_Literal (Loc, 1),
- Right_Opnd =>
- Make_Integer_Literal (Loc, I_Depth))));
+ Make_Integer_Literal (Loc, TSD_Num_Entries)));
Append_To (Result,
Make_Object_Declaration (Loc,
@@ -827,6 +1464,50 @@ package body Exp_Disp is
Prefix => New_Reference_To (TSD, Loc),
Attribute_Name => Name_Address))));
+ -- Generate: Exname : constant String := full_qualified_name (typ);
+ -- The type itself may be an anonymous parent type, so use the first
+ -- subtype to have a user-recognizable name.
+
+ Append_To (Result,
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Exname,
+ Constant_Present => True,
+ Object_Definition => New_Reference_To (Standard_String, Loc),
+ Expression =>
+ Make_String_Literal (Loc,
+ Full_Qualified_Name (First_Subtype (Typ)))));
+
+ -- Generate: Set_Expanded_Name (DT_Ptr, exname'Address);
+
+ Append_To (Elab_Code,
+ Make_DT_Access_Action (Typ,
+ Action => Set_Expanded_Name,
+ Args => New_List (
+ Node1 => New_Reference_To (DT_Ptr, Loc),
+ Node2 =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (Exname, Loc),
+ Attribute_Name => Name_Address))));
+
+ -- Generate: Set_Access_Level (DT_Ptr, <type's accessibility level>);
+
+ Append_To (Elab_Code,
+ Make_DT_Access_Action (Typ,
+ Action => Set_Access_Level,
+ Args => New_List (
+ Node1 => New_Reference_To (DT_Ptr, Loc),
+ Node2 => Make_Integer_Literal (Loc, Type_Access_Level (Typ)))));
+
+ -- Generate:
+ -- Set_Offset_To_Top (DT_Ptr, 0);
+
+ Append_To (Elab_Code,
+ Make_Procedure_Call_Statement (Loc,
+ Name => New_Reference_To (RTE (RE_Set_Offset_To_Top), Loc),
+ Parameter_Associations => New_List (
+ New_Reference_To (DT_Ptr, Loc),
+ Make_Integer_Literal (Loc, Uint_0))));
+
if Typ = Etype (Typ)
or else Is_CPP_Class (Etype (Typ))
then
@@ -866,31 +1547,6 @@ package body Exp_Disp is
Node1 => Old_Tag2,
Node2 => New_Reference_To (DT_Ptr, Loc))));
- -- Generate: Exname : constant String := full_qualified_name (typ);
- -- The type itself may be an anonymous parent type, so use the first
- -- subtype to have a user-recognizable name.
-
- Append_To (Result,
- Make_Object_Declaration (Loc,
- Defining_Identifier => Exname,
- Constant_Present => True,
- Object_Definition => New_Reference_To (Standard_String, Loc),
- Expression =>
- Make_String_Literal (Loc,
- Full_Qualified_Name (First_Subtype (Typ)))));
-
- -- Generate: Set_Expanded_Name (DT_Ptr, exname'Address);
-
- Append_To (Elab_Code,
- Make_DT_Access_Action (Typ,
- Action => Set_Expanded_Name,
- Args => New_List (
- Node1 => New_Reference_To (DT_Ptr, Loc),
- Node2 =>
- Make_Attribute_Reference (Loc,
- Prefix => New_Reference_To (Exname, Loc),
- Attribute_Name => Name_Address))));
-
-- for types with no controlled components
-- Generate: Set_RC_Offset (DT_Ptr, 0);
-- for simple types with controlled components
@@ -1022,9 +1678,179 @@ package body Exp_Disp is
Condition => New_Reference_To (No_Reg, Loc),
Then_Statements => Elab_Code));
+ -- Ada 2005 (AI-251): Register the tag of the interfaces into
+ -- the table of implemented interfaces
+
+ if Present (Abstract_Interfaces (Typ))
+ and then not Is_Empty_Elmt_List (Abstract_Interfaces (Typ))
+ then
+ AI := First_Elmt (Abstract_Interfaces (Typ_Copy));
+ while Present (AI) loop
+
+ -- Generate:
+ -- Register_Interface (DT_Ptr, Interface'Tag);
+
+ Append_To (Result,
+ Make_DT_Access_Action (Typ,
+ Action => Register_Interface_Tag,
+ Args => New_List (
+ Node1 => New_Reference_To (DT_Ptr, Loc),
+ Node2 => New_Reference_To
+ (Node
+ (First_Elmt
+ (Access_Disp_Table (Node (AI)))),
+ Loc))));
+
+ Next_Elmt (AI);
+ end loop;
+ end if;
+
return Result;
end Make_DT;
+ --------------------------------
+ -- Make_Abstract_Interface_DT --
+ --------------------------------
+
+ procedure Make_Abstract_Interface_DT
+ (AI_Tag : Entity_Id;
+ Acc_Disp_Tables : in out Elist_Id;
+ Result : out List_Id)
+ is
+ Loc : constant Source_Ptr := Sloc (AI_Tag);
+ Tname : constant Name_Id := Chars (AI_Tag);
+ Name_DT : constant Name_Id := New_External_Name (Tname, 'T');
+ Name_DT_Ptr : constant Name_Id := New_External_Name (Tname, 'P');
+
+ Iface_DT : constant Node_Id :=
+ Make_Defining_Identifier (Loc, Name_DT);
+ Iface_DT_Ptr : constant Node_Id :=
+ Make_Defining_Identifier (Loc, Name_DT_Ptr);
+
+ Generalized_Tag : constant Entity_Id := RTE (RE_Interface_Tag);
+ Size_Expr_Node : Node_Id;
+ Nb_Prim : Int;
+
+ begin
+ Result := New_List;
+
+ -- Dispatch table and related entities are allocated statically
+
+ Set_Ekind (Iface_DT, E_Variable);
+ Set_Is_Statically_Allocated (Iface_DT);
+
+ Set_Ekind (Iface_DT_Ptr, E_Variable);
+ Set_Is_Statically_Allocated (Iface_DT_Ptr);
+
+ -- Generate code to create the storage for the Dispatch_Table object
+
+ -- DT : Storage_Array (1..DT_Prologue_Size+nb_prim*DT_Entry_Size);
+ -- for DT'Alignment use Address'Alignment
+
+ Nb_Prim := UI_To_Int (DT_Entry_Count (AI_Tag));
+
+ Size_Expr_Node :=
+ Make_Op_Add (Loc,
+ Left_Opnd => Make_DT_Access_Action (Etype (AI_Tag),
+ DT_Prologue_Size,
+ No_List),
+ Right_Opnd =>
+ Make_Op_Multiply (Loc,
+ Left_Opnd =>
+ Make_DT_Access_Action (Etype (AI_Tag),
+ DT_Entry_Size,
+ No_List),
+ Right_Opnd =>
+ Make_Integer_Literal (Loc, Nb_Prim)));
+
+ Append_To (Result,
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Iface_DT,
+ Aliased_Present => True,
+ Object_Definition =>
+ Make_Subtype_Indication (Loc,
+ Subtype_Mark => New_Reference_To (RTE (RE_Storage_Array), Loc),
+ Constraint => Make_Index_Or_Discriminant_Constraint (Loc,
+ Constraints => New_List (
+ Make_Range (Loc,
+ Low_Bound => Make_Integer_Literal (Loc, 1),
+ High_Bound => Size_Expr_Node)))),
+
+ -- Initialize the signature of the interface tag. It is currently
+ -- a sequence of four bytes located in the unused Typeinfo_Ptr
+ -- field of the prologue). Its current value is the following
+ -- sequence: (80, Nb_Prim, 0, 80)
+
+ Expression =>
+ Make_Aggregate (Loc,
+ Component_Associations => New_List (
+ Make_Component_Association (Loc,
+
+ -- -80, 0, 0, -80
+
+ Choices => New_List (
+ Make_Integer_Literal (Loc, Uint_5),
+ Make_Integer_Literal (Loc, Uint_8)),
+ Expression =>
+ Make_Integer_Literal (Loc, Uint_80)),
+
+ Make_Component_Association (Loc,
+ Choices => New_List (
+ Make_Integer_Literal (Loc, Uint_2)),
+ Expression =>
+ Make_Integer_Literal (Loc, Nb_Prim)),
+
+ Make_Component_Association (Loc,
+ Choices => New_List (
+ Make_Others_Choice (Loc)),
+ Expression => Make_Integer_Literal (Loc, Uint_0))))));
+
+ Append_To (Result,
+ Make_Attribute_Definition_Clause (Loc,
+ Name => New_Reference_To (Iface_DT, Loc),
+ Chars => Name_Alignment,
+ Expression =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (RTE (RE_Integer_Address), Loc),
+ Attribute_Name => Name_Alignment)));
+
+ -- Generate code to create the pointer to the dispatch table
+
+ -- Iface_DT_Ptr : Tag := Tag!(DT'Address);
+
+ -- According to the C++ ABI, the base of the vtable is located
+ -- after the following prologue: Offset_To_Top, and Typeinfo_Ptr.
+ -- Hence, move the pointer down to the real base of the vtable.
+
+ Append_To (Result,
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Iface_DT_Ptr,
+ Constant_Present => True,
+ Object_Definition => New_Reference_To (Generalized_Tag, Loc),
+ Expression =>
+ Unchecked_Convert_To (Generalized_Tag,
+ Make_Op_Add (Loc,
+ Left_Opnd =>
+ Unchecked_Convert_To (RTE (RE_Storage_Offset),
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (Iface_DT, Loc),
+ Attribute_Name => Name_Address)),
+ Right_Opnd =>
+ Make_DT_Access_Action (Etype (AI_Tag),
+ DT_Prologue_Size, No_List)))));
+
+ -- Note: Offset_To_Top will be initialized by the init subprogram
+
+ -- Set Access_Disp_Table field to be the dispatch table pointer
+
+ if not (Present (Acc_Disp_Tables)) then
+ Acc_Disp_Tables := New_Elmt_List;
+ end if;
+
+ Append_Elmt (Iface_DT_Ptr, Acc_Disp_Tables);
+
+ end Make_Abstract_Interface_DT;
+
---------------------------
-- Make_DT_Access_Action --
---------------------------
@@ -1032,19 +1858,12 @@ package body Exp_Disp is
function Make_DT_Access_Action
(Typ : Entity_Id;
Action : DT_Access_Action;
- Args : List_Id)
- return Node_Id
+ Args : List_Id) return Node_Id
is
- Action_Name : Entity_Id;
+ Action_Name : constant Entity_Id := RTE (Ada_Actions (Action));
Loc : Source_Ptr;
begin
- if Is_CPP_Class (Root_Type (Typ)) then
- Action_Name := RTE (CPP_Actions (Action));
- else
- Action_Name := RTE (Ada_Actions (Action));
- end if;
-
if No (Args) then
-- This is a constant
@@ -1106,15 +1925,61 @@ package body Exp_Disp is
Root_Typ : constant Entity_Id := Root_Type (Typ);
First_Prim : constant Elmt_Id := First_Elmt (Primitive_Operations (Typ));
The_Tag : constant Entity_Id := First_Tag_Component (Typ);
+
Adjusted : Boolean := False;
Finalized : Boolean := False;
- Parent_EC : Int;
+
+ Count_Prim : Int;
+ DT_Length : Int;
Nb_Prim : Int;
+ Parent_EC : Int;
Prim : Entity_Id;
Prim_Elmt : Elmt_Id;
- begin
+ procedure Validate_Position (Prim : Entity_Id);
+ -- Check that the position assignated to Prim is completely safe
+ -- (it has not been assigned to a previously defined primitive
+ -- operation of Typ)
+
+ -----------------------
+ -- Validate_Position --
+ -----------------------
+ procedure Validate_Position (Prim : Entity_Id) is
+ Prim_Elmt : Elmt_Id;
+ begin
+ Prim_Elmt := First_Elmt (Primitive_Operations (Typ));
+ while Present (Prim_Elmt)
+ and then Node (Prim_Elmt) /= Prim
+ loop
+ -- Primitive operations covering abstract interfaces are
+ -- allocated later
+
+ if Present (Abstract_Interface_Alias (Node (Prim_Elmt))) then
+ null;
+
+ -- Predefined dispatching operations are completely safe.
+ -- They are allocated at fixed positions.
+
+ elsif Is_Predefined_Dispatching_Operation (Node (Prim_Elmt)) then
+ null;
+
+ -- Aliased subprograms are safe
+
+ elsif Present (Alias (Prim)) then
+ null;
+
+ elsif DT_Position (Node (Prim_Elmt)) = DT_Position (Prim) then
+ raise Program_Error;
+ end if;
+
+ Next_Elmt (Prim_Elmt);
+ end loop;
+ end Validate_Position;
+
+ -- Start of processing for Set_All_DT_Position
+
+ begin
-- Get Entry_Count of the parent
if Parent_Typ /= Typ
@@ -1246,26 +2111,218 @@ package body Exp_Disp is
-- in a-tags.ad?)
else
- Nb_Prim := 1;
- Prim_Elmt := First_Prim;
+ -- First stage: Set the DTC entity of all the primitive operations
+ -- This is required to properly read the DT_Position attribute in
+ -- the latter stages.
+
+ Prim_Elmt := First_Prim;
+ Count_Prim := 0;
while Present (Prim_Elmt) loop
- Nb_Prim := Nb_Prim + 1;
- Prim := Node (Prim_Elmt);
- Set_DTC_Entity (Prim, The_Tag);
+ Count_Prim := Count_Prim + 1;
+ Prim := Node (Prim_Elmt);
+
+ -- Ada 2005 (AI-251)
+
+ if Present (Abstract_Interface_Alias (Prim)) then
+ Set_DTC_Entity (Prim,
+ Find_Interface_Tag
+ (T => Typ,
+ Iface => Scope (DTC_Entity
+ (Abstract_Interface_Alias (Prim)))));
- if Chars (Prim) = Name_uSize then
- Set_DT_Position (Prim, Uint_1);
- Nb_Prim := Nb_Prim - 1;
else
- Set_DT_Position (Prim, UI_From_Int (Nb_Prim));
+ Set_DTC_Entity (Prim, The_Tag);
end if;
- if Chars (Prim) = Name_Finalize
- and then
- (Is_Predefined_File_Name (Unit_File_Name (Current_Sem_Unit))
- or else not Is_Predefined_File_Name
- (Unit_File_Name (Get_Source_Unit (Prim))))
+ -- Clear any previous value of the DT_Position attribute. In this
+ -- way we ensure that the final position of all the primitives is
+ -- stablished by the following stages of this algorithm.
+
+ Set_DT_Position (Prim, No_Uint);
+
+ Next_Elmt (Prim_Elmt);
+ end loop;
+
+ declare
+ Fixed_Prim : array (Int range 0 .. 10 + Parent_EC + Count_Prim)
+ of Boolean := (others => False);
+ E : Entity_Id;
+
+ begin
+ -- Second stage: Register fixed entries
+
+ Nb_Prim := 10;
+ Prim_Elmt := First_Prim;
+
+ while Present (Prim_Elmt) loop
+ Prim := Node (Prim_Elmt);
+
+ -- Predefined primitives have a fixed position in all the
+ -- dispatch tables
+
+ if Is_Predefined_Dispatching_Operation (Prim) then
+ Set_DT_Position (Prim, Default_Prim_Op_Position (Prim));
+ Fixed_Prim (UI_To_Int (DT_Position (Prim))) := True;
+
+ -- Overriding interface primitives of an ancestor
+
+ elsif DT_Position (Prim) = No_Uint
+ and then Present (Abstract_Interface_Alias (Prim))
+ and then Present (DTC_Entity
+ (Abstract_Interface_Alias (Prim)))
+ and then DT_Position (Abstract_Interface_Alias (Prim))
+ /= No_Uint
+ and then Is_Inherited_Operation (Prim)
+ and then Is_Ancestor (Scope
+ (DTC_Entity
+ (Abstract_Interface_Alias (Prim))),
+ Typ)
+ then
+ Set_DT_Position (Prim,
+ DT_Position (Abstract_Interface_Alias (Prim)));
+ Set_DT_Position (Alias (Prim),
+ DT_Position (Abstract_Interface_Alias (Prim)));
+ Fixed_Prim (UI_To_Int (DT_Position (Prim))) := True;
+
+ -- Overriding primitives must use the same entry as the
+ -- overriden primitive
+
+ elsif DT_Position (Prim) = No_Uint
+ and then Present (Alias (Prim))
+ and then Present (DTC_Entity (Alias (Prim)))
+ and then DT_Position (Alias (Prim)) /= No_Uint
+ and then Is_Inherited_Operation (Prim)
+ and then Is_Ancestor (Scope (DTC_Entity (Alias (Prim))), Typ)
+ then
+ E := Alias (Prim);
+ while not (Present (DTC_Entity (E))
+ or else DT_Position (E) = No_Uint)
+ and then Present (Alias (E))
+ loop
+ E := Alias (E);
+ end loop;
+
+ pragma Assert (Present (DTC_Entity (E))
+ and then
+ DT_Position (E) /= No_Uint);
+
+ Set_DT_Position (Prim, DT_Position (E));
+ Fixed_Prim (UI_To_Int (DT_Position (E))) := True;
+
+ -- If this is not the last element in the chain continue
+ -- traversing the chain. This is required to properly
+ -- handling renamed primitives
+
+ if Present (Alias (E)) then
+ while Present (Alias (E)) loop
+ E := Alias (E);
+ Fixed_Prim (UI_To_Int (DT_Position (E))) := True;
+ end loop;
+ end if;
+ end if;
+
+ Next_Elmt (Prim_Elmt);
+ end loop;
+
+ -- Third stage: Fix the position of all the new primitives
+ -- Entries associated with primitives covering interfaces
+ -- are handled in a latter round.
+
+ Prim_Elmt := First_Prim;
+ while Present (Prim_Elmt) loop
+ Prim := Node (Prim_Elmt);
+
+ -- Skip primitives previously set entries
+
+ if DT_Position (Prim) /= No_Uint then
+ null;
+
+ elsif Etype (DTC_Entity (Prim)) /= RTE (RE_Tag) then
+ null;
+
+ -- Primitives covering interface primitives are
+ -- handled later
+
+ elsif Present (Abstract_Interface_Alias (Prim)) then
+ null;
+
+ else
+ -- Take the next available position in the DT
+
+ loop
+ Nb_Prim := Nb_Prim + 1;
+ exit when not Fixed_Prim (Nb_Prim);
+ end loop;
+
+ Set_DT_Position (Prim, UI_From_Int (Nb_Prim));
+ Fixed_Prim (Nb_Prim) := True;
+ end if;
+
+ Next_Elmt (Prim_Elmt);
+ end loop;
+ end;
+
+ -- Fourth stage: Complete the decoration of primitives covering
+ -- interfaces (that is, propagate the DT_Position attribute
+ -- from the aliased primitive)
+
+ Prim_Elmt := First_Prim;
+ while Present (Prim_Elmt) loop
+ Prim := Node (Prim_Elmt);
+
+ if DT_Position (Prim) = No_Uint
+ and then Present (Abstract_Interface_Alias (Prim))
then
+ -- Check if this entry will be placed in the primary DT
+
+ if Etype (DTC_Entity (Abstract_Interface_Alias (Prim)))
+ = RTE (RE_Tag)
+ then
+ pragma Assert (DT_Position (Alias (Prim)) /= No_Uint);
+ Set_DT_Position (Prim, DT_Position (Alias (Prim)));
+
+ -- Otherwise it will be placed in the secondary DT
+
+ else
+ pragma Assert
+ (DT_Position (Abstract_Interface_Alias (Prim)) /= No_Uint);
+
+ Set_DT_Position (Prim,
+ DT_Position (Abstract_Interface_Alias (Prim)));
+ end if;
+ end if;
+
+ Next_Elmt (Prim_Elmt);
+ end loop;
+
+ -- Final stage: Ensure that the table is correct plus some further
+ -- verifications concerning the primitives.
+
+ Prim_Elmt := First_Prim;
+ DT_Length := 0;
+
+ while Present (Prim_Elmt) loop
+ Prim := Node (Prim_Elmt);
+
+ -- At this point all the primitives MUST have a position
+ -- in the dispatch table
+
+ if DT_Position (Prim) = No_Uint then
+ raise Program_Error;
+ end if;
+
+ -- Calculate real size of the dispatch table
+
+ if UI_To_Int (DT_Position (Prim)) > DT_Length then
+ DT_Length := UI_To_Int (DT_Position (Prim));
+ end if;
+
+ -- Ensure that the asignated position in the dispatch
+ -- table is correct
+
+ Validate_Position (Prim);
+
+ if Chars (Prim) = Name_Finalize then
Finalized := True;
end if;
@@ -1275,17 +2332,19 @@ package body Exp_Disp is
-- An abstract operation cannot be declared in the private part
-- for a visible abstract type, because it could never be over-
- -- ridden. For explicit declarations this is checked at the point
- -- of declaration, but for inherited operations it must be done
- -- when building the dispatch table. Input is excluded because
+ -- ridden. For explicit declarations this is checked at the
+ -- point of declaration, but for inherited operations it must
+ -- be done when building the dispatch table. Input is excluded
+ -- because
if Is_Abstract (Typ)
and then Is_Abstract (Prim)
and then Present (Alias (Prim))
and then Is_Derived_Type (Typ)
and then In_Private_Part (Current_Scope)
- and then List_Containing (Parent (Prim))
- = Private_Declarations
+ and then
+ List_Containing (Parent (Prim)) =
+ Private_Declarations
(Specification (Unit_Declaration_Node (Current_Scope)))
and then Original_View_In_Visible_Part (Typ)
then
@@ -1301,12 +2360,15 @@ package body Exp_Disp is
Error_Msg_NE
("abstract inherited private operation&" &
" must be overridden ('R'M 3.9.3(10))",
- Parent (Typ), Prim);
+ Parent (Typ), Prim);
end if;
end if;
+
Next_Elmt (Prim_Elmt);
end loop;
+ -- Additional check
+
if Is_Controlled (Typ) then
if not Finalized then
Error_Msg_N
@@ -1318,15 +2380,28 @@ package body Exp_Disp is
end if;
end if;
- Set_DT_Entry_Count (The_Tag, UI_From_Int (Nb_Prim));
+ -- Set the final size of the Dispatch Table
+
+ Set_DT_Entry_Count (The_Tag, UI_From_Int (DT_Length));
-- The derived type must have at least as many components as its
-- parent (for root types, the Etype points back to itself
-- and the test should not fail)
- pragma Assert (
- DT_Entry_Count (The_Tag) >=
- DT_Entry_Count (First_Tag_Component (Parent_Typ)));
+ -- This test fails compiling the partial view of a tagged type
+ -- derived from an interface which defines the overriding subprogram
+ -- in the private part. This needs further investigation???
+
+ if not Has_Private_Declaration (Typ) then
+ pragma Assert (
+ DT_Entry_Count (The_Tag) >=
+ DT_Entry_Count (First_Tag_Component (Parent_Typ)));
+ null;
+ end if;
+ end if;
+
+ if Debug_Flag_ZZ then
+ Write_DT (Typ);
end if;
end Set_All_DT_Position;
@@ -1382,4 +2457,104 @@ package body Exp_Disp is
end if;
end Set_Default_Constructor;
+ --------------
+ -- Write_DT --
+ --------------
+
+ procedure Write_DT (Typ : Entity_Id) is
+ Elmt : Elmt_Id;
+ Prim : Node_Id;
+
+ begin
+ -- Protect this procedure against wrong usage. Required because it will
+ -- be used directly from GDB
+
+ if not (Typ in First_Node_Id .. Last_Node_Id)
+ or else not Is_Tagged_Type (Typ)
+ then
+ Write_Str ("wrong usage: write_dt must be used with tagged types");
+ Write_Eol;
+ return;
+ end if;
+
+ Write_Int (Int (Typ));
+ Write_Str (": ");
+ Write_Name (Chars (Typ));
+
+ if Is_Interface (Typ) then
+ Write_Str (" is interface");
+ end if;
+
+ Write_Eol;
+
+ Elmt := First_Elmt (Primitive_Operations (Typ));
+ while Present (Elmt) loop
+ Prim := Node (Elmt);
+ Write_Str (" - ");
+
+ -- Indicate if this primitive will be allocated in the primary
+ -- dispatch table or in a secondary dispatch table associated
+ -- with an abstract interface type
+
+ if Present (DTC_Entity (Prim)) then
+ if Etype (DTC_Entity (Prim)) = RTE (RE_Tag) then
+ Write_Str ("[P] ");
+ else
+ Write_Str ("[s] ");
+ end if;
+ end if;
+
+ -- Output the node of this primitive operation and its name
+
+ Write_Int (Int (Prim));
+ Write_Str (": ");
+ Write_Name (Chars (Prim));
+
+ -- Indicate if this primitive has an aliased primitive
+
+ if Present (Alias (Prim)) then
+ Write_Str (" (alias = ");
+ Write_Int (Int (Alias (Prim)));
+
+ -- If the DTC_Entity attribute is already set we can also output
+ -- the name of the interface covered by this primitive (if any)
+
+ if Present (DTC_Entity (Alias (Prim)))
+ and then Is_Interface (Scope (DTC_Entity (Alias (Prim))))
+ then
+ Write_Str (" from interface ");
+ Write_Name (Chars (Scope (DTC_Entity (Alias (Prim)))));
+ end if;
+
+ if Present (Abstract_Interface_Alias (Prim)) then
+ Write_Str (", AI_Alias of ");
+ Write_Name (Chars (Scope (DTC_Entity
+ (Abstract_Interface_Alias (Prim)))));
+ Write_Char (':');
+ Write_Int (Int (Abstract_Interface_Alias (Prim)));
+ end if;
+
+ Write_Str (")");
+ end if;
+
+ -- Display the final position of this primitive in its associated
+ -- (primary or secondary) dispatch table
+
+ if Present (DTC_Entity (Prim))
+ and then DT_Position (Prim) /= No_Uint
+ then
+ Write_Str (" at #");
+ Write_Int (UI_To_Int (DT_Position (Prim)));
+ end if;
+
+ if Is_Abstract (Prim) then
+ Write_Str (" is abstract;");
+ end if;
+
+ Write_Eol;
+
+ Next_Elmt (Elmt);
+ end loop;
+ end Write_DT;
+
end Exp_Disp;
diff --git a/gcc/ada/exp_disp.ads b/gcc/ada/exp_disp.ads
index d942c3f514b..a60a43d470d 100644
--- a/gcc/ada/exp_disp.ads
+++ b/gcc/ada/exp_disp.ads
@@ -25,22 +25,26 @@
------------------------------------------------------------------------------
-- This package contains routines involved in tagged types and dynamic
--- dispatching expansion
+-- dispatching expansion.
with Types; use Types;
package Exp_Disp is
type DT_Access_Action is
(CW_Membership,
+ IW_Membership,
DT_Entry_Size,
DT_Prologue_Size,
+ Get_Access_Level,
Get_External_Tag,
Get_Prim_Op_Address,
Get_RC_Offset,
Get_Remotely_Callable,
Inherit_DT,
Inherit_TSD,
+ Register_Interface_Tag,
Register_Tag,
+ Set_Access_Level,
Set_Expanded_Name,
Set_External_Tag,
Set_Prim_Op_Address,
@@ -51,17 +55,26 @@ package Exp_Disp is
TSD_Prologue_Size);
function Fill_DT_Entry
- (Loc : Source_Ptr;
- Prim : Entity_Id)
- return Node_Id;
+ (Loc : Source_Ptr;
+ Prim : Entity_Id;
+ Thunk_Id : Entity_Id := Empty) return Node_Id;
-- Generate the code necessary to fill the appropriate entry of the
-- dispatch table of Prim's controlling type with Prim's address.
+ procedure Make_Abstract_Interface_DT
+ (AI_Tag : Entity_Id;
+ Acc_Disp_Tables : in out Elist_Id;
+ Result : out List_Id);
+ -- Ada 2005 (AI-251): Expand the declarations for the secondary Dispatch
+ -- Tables corresponding with an abstract interface. The reference to the
+ -- dispatch table is appended at the end of Acc_Disp_Tables; it will be
+ -- are later used to generate the corresponding initialization statement
+ -- (see Exp_Ch3.Build_Init_Procedure).
+
function Make_DT_Access_Action
(Typ : Entity_Id;
Action : DT_Access_Action;
- Args : List_Id)
- return Node_Id;
+ Args : List_Id) return Node_Id;
-- Generate a call to one of the Dispatch Table Access Subprograms defined
-- in Ada.Tags or in Interfaces.Cpp
@@ -71,7 +84,7 @@ package Exp_Disp is
procedure Set_All_DT_Position (Typ : Entity_Id);
-- Set the DT_Position field for each primitive operation. In the CPP
- -- Class case check that no pragma CPP_Virtual is missing and that the
+ -- Class case check that no pragma CPP_Virtual is missing and that the
-- DT_Position are coherent
procedure Expand_Dispatching_Call (Call_Node : Node_Id);
@@ -79,6 +92,25 @@ package Exp_Disp is
-- the required tag checks when appropriate. For CPP types the call is
-- done through the Vtable (tag checks are not relevant)
+ procedure Expand_Interface_Actuals (Call_Node : Node_Id);
+ -- Ada 2005 (AI-251): Displace all the actuals corresponding to class-wide
+ -- interfaces to reference the interface tag of the actual object
+
+ procedure Expand_Interface_Conversion (N : Node_Id);
+ -- Ada 2005 (AI-251): N is a type-conversion node. Reference the base of
+ -- the object to give access to the interface tag associated with the
+ -- secondary dispatch table
+
+ function Expand_Interface_Thunk
+ (N : Node_Id;
+ Thunk_Id : Entity_Id;
+ Iface_Tag : Entity_Id) return Node_Id;
+ -- Ada 2005 (AI-251): When a tagged type implements abstract interfaces we
+ -- generate additional subprograms (thunks) to have a layout compatible
+ -- with the C++ ABI. The thunk modifies the value of the first actual of
+ -- the call (that is, the pointer to the object) before transferring
+ -- control to the target function.
+
procedure Set_Default_Constructor (Typ : Entity_Id);
-- Typ is a CPP_Class type. Create the Init procedure of that type to
-- be the default constructor (i.e. the function returning this type,
@@ -88,4 +120,8 @@ package Exp_Disp is
-- Return an expression that holds True if the object can be transmitted
-- onto another partition according to E.4 (18)
+ procedure Write_DT (Typ : Entity_Id);
+ pragma Export (Ada, Write_DT);
+ -- Debugging procedure (to be called within gdb)
+
end Exp_Disp;
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index 4868dc1286e..eda4383e276 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2005, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2005 Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -47,6 +47,7 @@ with Sem; use Sem;
with Sem_Ch8; use Sem_Ch8;
with Sem_Eval; use Sem_Eval;
with Sem_Res; use Sem_Res;
+with Sem_Type; use Sem_Type;
with Sem_Util; use Sem_Util;
with Sinfo; use Sinfo;
with Snames; use Snames;
@@ -107,6 +108,15 @@ package body Exp_Util is
-- procedure of record with task components, or for a dynamically
-- created task that is assigned to a selected component.
+ procedure Find_Interface_Tag
+ (T : Entity_Id;
+ Iface : Entity_Id;
+ Iface_Tag : out Entity_Id;
+ Iface_ADT : out Entity_Id);
+ -- Ada 2005 (AI-251): Subsidiary procedure to Find_Interface_ADT and
+ -- Find_Interface_Tag. Given a type T implementing the interface,
+ -- returns the corresponding Tag and Access_Disp_Table entities.
+
function Make_CW_Equivalent_Type
(T : Entity_Id;
E : Node_Id) return Entity_Id;
@@ -1219,9 +1229,32 @@ package body Exp_Util is
then
if Is_Itype (Exp_Typ) then
- -- No need to generate a new one
+ -- Within an initialization procedure, a selected component
+ -- denotes a component of the enclosing record, and it appears
+ -- as an actual in a call to its own initialization procedure.
+ -- If this component depends on the outer discriminant, we must
+ -- generate the proper actual subtype for it.
- T := Exp_Typ;
+ if Nkind (Exp) = N_Selected_Component
+ and then Within_Init_Proc
+ then
+ declare
+ Decl : constant Node_Id :=
+ Build_Actual_Subtype_Of_Component (Exp_Typ, Exp);
+ begin
+ if Present (Decl) then
+ Insert_Action (N, Decl);
+ T := Defining_Identifier (Decl);
+ else
+ T := Exp_Typ;
+ end if;
+ end;
+
+ -- No need to generate a new one (new what???)
+
+ else
+ T := Exp_Typ;
+ end if;
else
T :=
@@ -1261,6 +1294,145 @@ package body Exp_Util is
end if;
end Expand_Subtype_From_Expr;
+ ------------------------
+ -- Find_Interface_Tag --
+ ------------------------
+
+ procedure Find_Interface_Tag
+ (T : Entity_Id;
+ Iface : Entity_Id;
+ Iface_Tag : out Entity_Id;
+ Iface_ADT : out Entity_Id)
+ is
+ AI_Tag : Entity_Id;
+ ADT_Elmt : Elmt_Id;
+ Found : Boolean := False;
+
+ procedure Find_AI_Tag (Typ : in Entity_Id; Found : in out Boolean);
+ -- This must be commented ???
+
+ -----------------
+ -- Find_AI_Tag --
+ -----------------
+
+ procedure Find_AI_Tag (Typ : in Entity_Id; Found : in out Boolean) is
+ T : Entity_Id := Typ;
+ Etyp : Entity_Id; -- := Etype (Typ); -- why is this commented ???
+ AI_Elmt : Elmt_Id;
+ AI : Node_Id;
+
+ begin
+ -- Check if the interface is an immediate ancestor of the type and
+ -- therefore shares the main tag.
+
+ if Typ = Iface then
+ AI_Tag := First_Tag_Component (Typ);
+ ADT_Elmt := First_Elmt (Access_Disp_Table (Typ));
+ Found := True;
+ return;
+ end if;
+
+ -- Handle private types
+
+ if Has_Private_Declaration (T)
+ and then Present (Full_View (T))
+ then
+ T := Full_View (T);
+ end if;
+
+ if Is_Access_Type (Typ) then
+ T := Directly_Designated_Type (T);
+
+ elsif Ekind (T) = E_Protected_Type
+ or else Ekind (T) = E_Task_Type
+ then
+ T := Corresponding_Record_Type (T);
+ end if;
+
+ Etyp := Etype (T);
+
+ -- Climb to the root type
+
+ if Etyp /= Typ then
+ Find_AI_Tag (Etyp, Found);
+ end if;
+
+ -- Traverse the list of interfaces implemented by the type
+
+ if not Found
+ and then Present (Abstract_Interfaces (T))
+ and then not Is_Empty_Elmt_List (Abstract_Interfaces (T))
+ then
+ -- Skip the tag associated with the primary table (if
+ -- already placed in the record)
+
+ if Etype (Node (First_Elmt
+ (Access_Disp_Table (T)))) = RTE (RE_Tag)
+ then
+ AI_Tag := Next_Tag_Component (First_Tag_Component (T));
+ ADT_Elmt := Next_Elmt (First_Elmt (Access_Disp_Table (T)));
+ else
+ AI_Tag := First_Tag_Component (T);
+ ADT_Elmt := First_Elmt (Access_Disp_Table (T));
+ end if;
+
+ pragma Assert (Present (AI_Tag));
+ pragma Assert (Present (Node (ADT_Elmt)));
+
+ AI_Elmt := First_Elmt (Abstract_Interfaces (T));
+ while Present (AI_Elmt) loop
+ AI := Node (AI_Elmt);
+
+ if AI = Iface or else Is_Ancestor (Iface, AI) then
+ Found := True;
+ return;
+ end if;
+
+ AI_Tag := Next_Tag_Component (AI_Tag);
+ Next_Elmt (AI_Elmt);
+ Next_Elmt (ADT_Elmt);
+ end loop;
+ end if;
+ end Find_AI_Tag;
+
+ begin
+ Find_AI_Tag (T, Found);
+ pragma Assert (Found);
+
+ Iface_Tag := AI_Tag;
+ Iface_ADT := Node (ADT_Elmt);
+ end Find_Interface_Tag;
+
+ ------------------------
+ -- Find_Interface_Tag --
+ ------------------------
+
+ function Find_Interface_ADT
+ (T : Entity_Id;
+ Iface : Entity_Id) return Entity_Id
+ is
+ Iface_Tag : Entity_Id := Empty;
+ Iface_ADT : Entity_Id := Empty;
+ begin
+ Find_Interface_Tag (T, Iface, Iface_Tag, Iface_ADT);
+ return Iface_ADT;
+ end Find_Interface_ADT;
+
+ ------------------------
+ -- Find_Interface_Tag --
+ ------------------------
+
+ function Find_Interface_Tag
+ (T : Entity_Id;
+ Iface : Entity_Id) return Entity_Id
+ is
+ Iface_Tag : Entity_Id := Empty;
+ Iface_ADT : Entity_Id := Empty;
+ begin
+ Find_Interface_Tag (T, Iface, Iface_Tag, Iface_ADT);
+ return Iface_Tag;
+ end Find_Interface_Tag;
+
------------------
-- Find_Prim_Op --
------------------
@@ -1317,10 +1489,9 @@ package body Exp_Util is
Par : Node_Id;
begin
- -- Loop to determine whether there is a component reference in
- -- the left hand side if Exp appears on the left side of an
- -- assignment statement. Needed to determine if form of result
- -- must be a variable.
+ -- Loop to determine whether there is a component reference in the left
+ -- hand side if Exp appears on the left side of an assignment statement.
+ -- Needed to determine if form of result must be a variable.
Par := Exp;
while Present (Par)
@@ -1339,15 +1510,15 @@ package body Exp_Util is
end if;
end loop;
- -- If the expression is a selected component, it is being evaluated
- -- as part of a discriminant check. If it is part of a left-hand
- -- side, this is the last use of its value and it is safe to create
- -- a renaming for it, rather than a temporary. In addition, if it
- -- is not an addressable field, creating a temporary may be a problem
- -- for gigi, or might drop the value of the assignment. Therefore,
- -- if the expression is on the lhs of an assignment, remove side
- -- effects without requiring a temporary, and create a renaming.
- -- (See remove_side_effects for details).
+ -- If the expression is a selected component, it is being evaluated as
+ -- part of a discriminant check. If it is part of a left-hand side, this
+ -- is the last use of its value and it is safe to create a renaming for
+ -- it, rather than a temporary. In addition, if it is not an addressable
+ -- field, creating a temporary may be a problem for gigi, or might drop
+ -- the value of the assignment. Therefore, if the expression is on the
+ -- lhs of an assignment, remove side effects without requiring a
+ -- temporary, and create a renaming. (See remove_side_effects for
+ -- details).
Remove_Side_Effects
(Exp, Name_Req, Variable_Ref => not Component_In_Lhs);
@@ -1423,9 +1594,9 @@ package body Exp_Util is
-- If we fall off the top of the tree, then that's odd, but
-- perhaps it could occur in some error situation, and the
- -- safest response is simply to assume that the outcome of
- -- the condition is unknown. No point in bombing during an
- -- attempt to optimize things.
+ -- safest response is simply to assume that the outcome of the
+ -- condition is unknown. No point in bombing during an attempt
+ -- to optimize things.
if No (N) then
return;
@@ -1448,9 +1619,9 @@ package body Exp_Util is
end if;
end;
- -- ELSIF part. Condition is known true within the referenced
- -- ELSIF, known False in any subsequent ELSIF or ELSE part,
- -- and unknown before the ELSE part or after the IF statement.
+ -- ELSIF part. Condition is known true within the referenced ELSIF,
+ -- known False in any subsequent ELSIF or ELSE part, and unknown before
+ -- the ELSE part or after the IF statement.
elsif Nkind (CV) = N_Elsif_Part then
Stm := Parent (CV);
@@ -1468,8 +1639,8 @@ package body Exp_Util is
return;
end if;
- -- Again we lack the SLOC of the ELSE, so we need to climb the
- -- tree to see if we are within the ELSIF part in question.
+ -- Again we lack the SLOC of the ELSE, so we need to climb the tree
+ -- to see if we are within the ELSIF part in question.
declare
N : Node_Id;
@@ -1481,9 +1652,9 @@ package body Exp_Util is
-- If we fall off the top of the tree, then that's odd, but
-- perhaps it could occur in some error situation, and the
- -- safest response is simply to assume that the outcome of
- -- the condition is unknown. No point in bombing during an
- -- attempt to optimize things.
+ -- safest response is simply to assume that the outcome of the
+ -- condition is unknown. No point in bombing during an attempt
+ -- to optimize things.
if No (N) then
return;
@@ -1510,9 +1681,8 @@ package body Exp_Util is
return;
end if;
- -- If we fall through here, then we have a reportable
- -- condition, Sens is True if the condition is true and
- -- False if it needs inverting.
+ -- If we fall through here, then we have a reportable condition, Sens is
+ -- True if the condition is true and False if it needs inverting.
-- Deal with NOT operators, inverting sense
@@ -2320,6 +2490,47 @@ package body Exp_Util is
return True;
end Is_All_Null_Statements;
+ ------------------------
+ -- Is_Default_Prim_Op --
+ ------------------------
+
+ function Is_Predefined_Dispatching_Operation
+ (Subp : Entity_Id) return Boolean
+ is
+ TSS_Name : TSS_Name_Type;
+ E : Entity_Id := Subp;
+ begin
+ pragma Assert (Is_Dispatching_Operation (Subp));
+
+ -- Handle overriden subprograms
+
+ while Present (Alias (E)) loop
+ E := Alias (E);
+ end loop;
+
+ Get_Name_String (Chars (E));
+
+ if Name_Len > TSS_Name_Type'Last then
+ TSS_Name := TSS_Name_Type (Name_Buffer (Name_Len - TSS_Name'Length + 1
+ .. Name_Len));
+ if Chars (E) = Name_uSize
+ or else Chars (E) = Name_uAlignment
+ or else TSS_Name = TSS_Stream_Read
+ or else TSS_Name = TSS_Stream_Write
+ or else TSS_Name = TSS_Stream_Input
+ or else TSS_Name = TSS_Stream_Output
+ or else Chars (E) = Name_Op_Eq
+ or else Chars (E) = Name_uAssign
+ or else TSS_Name = TSS_Deep_Adjust
+ or else TSS_Name = TSS_Deep_Finalize
+ then
+ return True;
+ end if;
+ end if;
+
+ return False;
+ end Is_Predefined_Dispatching_Operation;
+
----------------------------------
-- Is_Possibly_Unaligned_Object --
----------------------------------
@@ -2366,8 +2577,9 @@ package body Exp_Util is
begin
-- If component reference is for an array with non-static bounds,
- -- then it is always aligned, we can only unaligned arrays with
- -- static bounds (more accurately bounds known at compile time)
+ -- then it is always aligned: we can only process unaligned
+ -- arrays with static bounds (more accurately bounds known at
+ -- compile time).
if Is_Array_Type (T)
and then not Compile_Time_Known_Bounds (T)
diff --git a/gcc/ada/exp_util.ads b/gcc/ada/exp_util.ads
index da3b1335b7d..711949c3dc6 100644
--- a/gcc/ada/exp_util.ads
+++ b/gcc/ada/exp_util.ads
@@ -135,7 +135,7 @@ package Exp_Util is
-- Actions field of the N_Compilation_Aux node for the main unit).
procedure Insert_Library_Level_Actions (L : List_Id);
- -- Similar, but inserts a list of actions.
+ -- Similar, but inserts a list of actions
-----------------------
-- Other Subprograms --
@@ -145,47 +145,46 @@ package Exp_Util is
-- The node N is an expression whose root-type is Boolean, and which
-- represents a boolean value used as a condition (i.e. a True/False
-- value). This routine handles the case of C and Fortran convention
- -- boolean types, which have zero/non-zero semantics rather than the
- -- normal 0/1 semantics, and also the case of an enumeration rep
- -- clause that specifies a non-standard representation. On return,
- -- node N always has the type Standard.Boolean, with a value that
- -- is a standard Boolean values of 0/1 for False/True. This procedure
- -- is used in two situations. First, the processing for a condition
- -- field always calls Adjust_Condition, so that the boolean value
- -- presented to the backend is a standard value. Second, for the
- -- code for boolean operations such as AND, Adjust_Condition is
- -- called on both operands, and then the operation is done in the
- -- domain of Standard_Boolean, then Adjust_Result_Type is called
- -- on the result to possibly reset the original type. This procedure
+ -- boolean types, which have zero/non-zero semantics rather than the normal
+ -- 0/1 semantics, and also the case of an enumeration rep clause that
+ -- specifies a non-standard representation. On return, node N always has
+ -- the type Standard.Boolean, with a value that is a standard Boolean
+ -- values of 0/1 for False/True. This procedure is used in two situations.
+ -- First, the processing for a condition field always calls
+ -- Adjust_Condition, so that the boolean value presented to the backend is
+ -- a standard value. Second, for the code for boolean operations such as
+ -- AND, Adjust_Condition is called on both operands, and then the operation
+ -- is done in the domain of Standard_Boolean, then Adjust_Result_Type is
+ -- called on the result to possibly reset the original type. This procedure
-- also takes care of validity checking if Validity_Checks = Tests.
procedure Adjust_Result_Type (N : Node_Id; T : Entity_Id);
-- The processing of boolean operations like AND uses the procedure
- -- Adjust_Condition so that it can operate on Standard.Boolean, which
- -- is the only boolean type on which the backend needs to be able to
- -- implement such operators. This means that the result is also of
- -- type Standard.Boolean. In general the type must be reset back to
- -- the original type to get proper semantics, and that is the purpose
- -- of this procedure. N is the node (of type Standard.Boolean), and
- -- T is the desired type. As an optimization, this procedure leaves
- -- the type as Standard.Boolean in contexts where this is permissible
- -- (in particular for Condition fields, and for operands of other
- -- logical operations higher up the tree). The call to this procedure
- -- is completely ignored if the argument N is not of type Boolean.
+ -- Adjust_Condition so that it can operate on Standard.Boolean, which is
+ -- the only boolean type on which the backend needs to be able to implement
+ -- such operators. This means that the result is also of type
+ -- Standard.Boolean. In general the type must be reset back to the original
+ -- type to get proper semantics, and that is the purpose of this procedure.
+ -- N is the node (of type Standard.Boolean), and T is the desired type. As
+ -- an optimization, this procedure leaves the type as Standard.Boolean in
+ -- contexts where this is permissible (in particular for Condition fields,
+ -- and for operands of other logical operations higher up the tree). The
+ -- call to this procedure is completely ignored if the argument N is not of
+ -- type Boolean.
procedure Append_Freeze_Action (T : Entity_Id; N : Node_Id);
-- Add a new freeze action for the given type. The freeze action is
- -- attached to the freeze node for the type. Actions will be elaborated
- -- in the order in which they are added. Note that the added node is not
+ -- attached to the freeze node for the type. Actions will be elaborated in
+ -- the order in which they are added. Note that the added node is not
-- analyzed. The analyze call is found in Sem_Ch13.Expand_N_Freeze_Entity.
procedure Append_Freeze_Actions (T : Entity_Id; L : List_Id);
- -- Adds the given list of freeze actions (declarations or statements)
- -- for the given type. The freeze actions are attached to the freeze
- -- node for the type. Actions will be elaborated in the order in which
- -- they are added, and the actions within the list will be elaborated in
- -- list order. Note that the added nodes are not analyzed. The analyze
- -- call is found in Sem_Ch13.Expand_N_Freeze_Entity.
+ -- Adds the given list of freeze actions (declarations or statements) for
+ -- the given type. The freeze actions are attached to the freeze node for
+ -- the type. Actions will be elaborated in the order in which they are
+ -- added, and the actions within the list will be elaborated in list order.
+ -- Note that the added nodes are not analyzed. The analyze call is found in
+ -- Sem_Ch13.Expand_N_Freeze_Entity.
function Build_Runtime_Call (Loc : Source_Ptr; RE : RE_Id) return Node_Id;
-- Build an N_Procedure_Call_Statement calling the given runtime entity.
@@ -198,55 +197,52 @@ package Exp_Util is
Id_Ref : Node_Id;
A_Type : Entity_Id)
return List_Id;
- -- Build declaration for a variable that holds an identifying string
- -- to be used as a task name. Id_Ref is an identifier if the task is
- -- a variable, and a selected or indexed component if the task is a
- -- component of an object. If it is an indexed component, A_Type is
- -- the corresponding array type. Its index types are used to build the
- -- string as an image of the index values. For composite types, the
- -- result includes two declarations: one for a generated function that
- -- computes the image without using concatenation, and one for the
- -- variable that holds the result.
+ -- Build declaration for a variable that holds an identifying string to be
+ -- used as a task name. Id_Ref is an identifier if the task is a variable,
+ -- and a selected or indexed component if the task is component of an
+ -- object. If it is an indexed component, A_Type is the corresponding array
+ -- type. Its index types are used to build the string as an image of the
+ -- index values. For composite types, the result includes two declarations:
+ -- one for a generated function that computes the image without using
+ -- concatenation, and one for the variable that holds the result.
function Component_May_Be_Bit_Aligned (Comp : Entity_Id) return Boolean;
- -- This function is in charge of detecting record components that may
- -- cause trouble in the back end if an attempt is made to assign the
- -- component. The back end can handle such assignments with no problem
- -- if the components involved are small (64-bits or less) records or
- -- scalar items (including bit-packed arrays represented with modular
- -- types) or are both aligned on a byte boundary (starting on a byte
- -- boundary, and occupying an integral number of bytes).
+ -- This function is in charge of detecting record components that may cause
+ -- trouble in the back end if an attempt is made to assign the component.
+ -- The back end can handle such assignments with no problem if the
+ -- components involved are small (64-bits or less) records or scalar items
+ -- (including bit-packed arrays represented with modular types) or are both
+ -- aligned on a byte boundary (starting on a byte boundary, and occupying
+ -- an integral number of bytes).
--
- -- However, problems arise for records larger than 64 bits, or for
- -- arrays (other than bit-packed arrays represented with a modular
- -- type) if the component starts on a non-byte boundary, or does
- -- not occupy an integral number of bytes (i.e. there are some bits
- -- possibly shared with fields at the start or beginning of the
- -- component). The back end cannot handle loading and storing such
- -- components in a single operation.
+ -- However, problems arise for records larger than 64 bits, or for arrays
+ -- (other than bit-packed arrays represented with a modular type) if the
+ -- component starts on a non-byte boundary, or does not occupy an integral
+ -- number of bytes (i.e. there are some bits possibly shared with fields at
+ -- the start or beginning of the component). The back end cannot handle
+ -- loading and storing such components in a single operation.
--
-- This function is used to detect the troublesome situation. it is
- -- conservative in the sense that it produces True unless it knows
- -- for sure that the component is safe (as outlined in the first
- -- paragraph above). The code generation for record and array
- -- assignment checks for trouble using this function, and if so
- -- the assignment is generated component-wise, which the back end
- -- is required to handle correctly.
+ -- conservative in the sense that it produces True unless it knows for sure
+ -- that the component is safe (as outlined in the first paragraph above).
+ -- The code generation for record and array assignment checks for trouble
+ -- using this function, and if so the assignment is generated
+ -- component-wise, which the back end is required to handle correctly.
--
- -- Note that in GNAT 3, the back end will reject such components
- -- anyway, so the hard work in checking for this case is wasted
- -- in GNAT 3, but it's harmless, so it is easier to do it in
- -- all cases, rather than conditionalize it in GNAT 5 or beyond.
+ -- Note that in GNAT 3, the back end will reject such components anyway, so
+ -- the hard work in checking for this case is wasted in GNAT 3, but it's
+ -- harmless, so it is easier to do it in all cases, rather than
+ -- conditionalize it in GNAT 5 or beyond.
procedure Convert_To_Actual_Subtype (Exp : Node_Id);
- -- The Etype of an expression is the nominal type of the expression,
- -- not the actual subtype. Often these are the same, but not always.
- -- For example, a reference to a formal of unconstrained type has the
- -- unconstrained type as its Etype, but the actual subtype is obtained
- -- by applying the actual bounds. This routine is given an expression,
- -- Exp, and (if necessary), replaces it using Rewrite, with a conversion
- -- to the actual subtype, building the actual subtype if necessary. If
- -- the expression is already of the requested type, then it is unchanged.
+ -- The Etype of an expression is the nominal type of the expression, not
+ -- the actual subtype. Often these are the same, but not always. For
+ -- example, a reference to a formal of unconstrained type has the
+ -- unconstrained type as its Etype, but the actual subtype is obtained by
+ -- applying the actual bounds. This routine is given an expression, Exp,
+ -- and (if necessary), replaces it using Rewrite, with a conversion to the
+ -- actual subtype, building the actual subtype if necessary. If the
+ -- expression is already of the requested type, then it is unchanged.
function Current_Sem_Unit_Declarations return List_Id;
-- Return the a place where it is fine to insert declarations for the
@@ -258,20 +254,20 @@ package Exp_Util is
function Duplicate_Subexpr
(Exp : Node_Id;
Name_Req : Boolean := False) return Node_Id;
- -- Given the node for a subexpression, this function makes a logical
- -- copy of the subexpression, and returns it. This is intended for use
- -- when the expansion of an expression needs to repeat part of it. For
- -- example, replacing a**2 by a*a requires two references to a which
- -- may be a complex subexpression. Duplicate_Subexpr guarantees not
- -- to duplicate side effects. If necessary, it generates actions to
- -- save the expression value in a temporary, inserting these actions
- -- into the tree using Insert_Actions with Exp as the insertion location.
- -- The original expression and the returned result then become references
- -- to this saved value. Exp must be analyzed on entry. On return, Exp
- -- is analyzed, but the caller is responsible for analyzing the returned
- -- copy after it is attached to the tree. The Name_Req flag is set to
- -- ensure that the result is suitable for use in a context requiring a
- -- name (e.g. the prefix of an attribute reference).
+ -- Given the node for a subexpression, this function makes a logical copy
+ -- of the subexpression, and returns it. This is intended for use when the
+ -- expansion of an expression needs to repeat part of it. For example,
+ -- replacing a**2 by a*a requires two references to a which may be a
+ -- complex subexpression. Duplicate_Subexpr guarantees not to duplicate
+ -- side effects. If necessary, it generates actions to save the expression
+ -- value in a temporary, inserting these actions into the tree using
+ -- Insert_Actions with Exp as the insertion location. The original
+ -- expression and the returned result then become references to this saved
+ -- value. Exp must be analyzed on entry. On return, Exp is analyzed, but
+ -- the caller is responsible for analyzing the returned copy after it is
+ -- attached to the tree. The Name_Req flag is set to ensure that the result
+ -- is suitable for use in a context requiring name (e.g. the prefix of an
+ -- attribute reference).
--
-- Note that if there are any run time checks in Exp, these same checks
-- will be duplicated in the returned duplicated expression. The two
@@ -289,13 +285,13 @@ package Exp_Util is
function Duplicate_Subexpr_Move_Checks
(Exp : Node_Id;
Name_Req : Boolean := False) return Node_Id;
- -- Identical in effect to Duplicate_Subexpr, except that Remove_Checks
- -- is called on Exp after the duplication is complete, so that the
- -- original expression does not include checks. In this case the result
- -- returned (the duplicated expression) will retain the original checks.
- -- This is appropriate for use when the duplicated expression is sure
- -- to be elaborated before the original expression Exp, so that there
- -- is no need to repeat the checks.
+ -- Identical in effect to Duplicate_Subexpr, except that Remove_Checks is
+ -- called on Exp after the duplication is complete, so that the original
+ -- expression does not include checks. In this case the result returned
+ -- (the duplicated expression) will retain the original checks. This is
+ -- appropriate for use when the duplicated expression is sure to be
+ -- elaborated before the original expression Exp, so that there is no need
+ -- to repeat the checks.
procedure Ensure_Defined (Typ : Entity_Id; N : Node_Id);
-- This procedure ensures that type referenced by Typ is defined. For the
@@ -309,15 +305,15 @@ package Exp_Util is
-- Rewrites Cond with the expression: Cond and then Cond1. If Cond is
-- Empty, then simply returns Cond1 (this allows the use of Empty to
-- initialize a series of checks evolved by this routine, with a final
- -- result of Empty indicating that no checks were required). The Sloc
- -- field of the constructed N_And_Then node is copied from Cond1.
+ -- result of Empty indicating that no checks were required). The Sloc field
+ -- of the constructed N_And_Then node is copied from Cond1.
procedure Evolve_Or_Else (Cond : in out Node_Id; Cond1 : Node_Id);
- -- Rewrites Cond with the expression: Cond or else Cond1. If Cond is
- -- Empty, then simply returns Cond1 (this allows the use of Empty to
- -- initialize a series of checks evolved by this routine, with a final
- -- result of Empty indicating that no checks were required). The Sloc
- -- field of the constructed N_Or_Else node is copied from Cond1.
+ -- Rewrites Cond with the expression: Cond or else Cond1. If Cond is Empty,
+ -- then simply returns Cond1 (this allows the use of Empty to initialize a
+ -- series of checks evolved by this routine, with a final result of Empty
+ -- indicating that no checks were required). The Sloc field of the
+ -- constructed N_Or_Else node is copied from Cond1.
procedure Expand_Subtype_From_Expr
(N : Node_Id;
@@ -328,6 +324,18 @@ package Exp_Util is
-- declarations and/or allocations when the type is indefinite (including
-- class-wide).
+ function Find_Interface_ADT
+ (T : Entity_Id;
+ Iface : Entity_Id) return Entity_Id;
+ -- Ada 2005 (AI-251): Given a type T implementing the interface Iface,
+ -- return the Access_Disp_Table value of the interface.
+
+ function Find_Interface_Tag
+ (T : Entity_Id;
+ Iface : Entity_Id) return Entity_Id;
+ -- Ada 2005 (AI-251): Given a type T implementing the interface Iface,
+ -- return the record component containing the tag of Iface.
+
function Find_Prim_Op (T : Entity_Id; Name : Name_Id) return Entity_Id;
-- Find the first primitive operation of type T whose name is 'Name'.
-- This function allows the use of a primitive operation which is not
@@ -362,73 +370,76 @@ package Exp_Util is
(Var : Node_Id;
Op : out Node_Kind;
Val : out Node_Id);
- -- This routine processes the Current_Value field of the variable Var.
- -- If the Current_Value field is null or if it represents a known value,
- -- then on return Cond is set to N_Empty, and Val is set to Empty.
+ -- This routine processes the Current_Value field of the variable Var. If
+ -- the Current_Value field is null or if it represents a known value, then
+ -- on return Cond is set to N_Empty, and Val is set to Empty.
--
- -- The other case is when Current_Value points to an N_If_Statement
- -- or an N_Elsif_Part (while statement). Such a setting only occurs
- -- if the condition of an IF or ELSIF is of the form X op Y, where X
- -- is the variable in question, Y is a compile-time known value, and
- -- op is one of the six possible relational operators.
+ -- The other case is when Current_Value points to an N_If_Statement or an
+ -- N_Elsif_Part (while statement). Such a setting only occurs if the
+ -- condition of an IF or ELSIF is of the form X op Y, where is the variable
+ -- in question, Y is a compile-time known value, and op is one of the six
+ -- possible relational operators.
--
- -- In this case, Get_Current_Condition digs out the condition, and
- -- then checks if the condition is known false, known true, or not
- -- known at all. In the first two cases, Get_Current_Condition will
- -- return with Op set to the appropriate conditional operator (inverted
- -- if the condition is known false), and Val set to the constant value.
- -- If the condition is not known, then Cond and Val are set for the
- -- empty case (N_Empty and Empty).
+ -- In this case, Get_Current_Condition digs out the condition, and then
+ -- checks if the condition is known false, known true, or not known at all.
+ -- In the first two cases, Get_Current_Condition will return with Op set to
+ -- the appropriate conditional operator (inverted if the condition is known
+ -- false), and Val set to the constant value. If the condition is not
+ -- known, then Cond and Val are set for the empty case (N_Empty and Empty).
--
-- The check for whether the condition is true/false unknown depends
-- on the case:
--
- -- For an IF, the condition is known true in the THEN part, known
- -- false in any ELSIF or ELSE part, and not known outside the IF
- -- statement in question.
+ -- For an IF, the condition is known true in the THEN part, known false
+ -- in any ELSIF or ELSE part, and not known outside the IF statement in
+ -- question.
--
- -- For an ELSIF, the condition is known true in the ELSIF part,
- -- known FALSE in any subsequent ELSIF, or ELSE part, and not
- -- known before the ELSIF, or after the end of the IF statement.
+ -- For an ELSIF, the condition is known true in the ELSIF part, known
+ -- FALSE in any subsequent ELSIF, or ELSE part, and not known before the
+ -- ELSIF, or after the end of the IF statement.
--
- -- The caller can use this result to determine the value (for the
- -- case of N_Op_Eq), or to determine the result of some other test
- -- in other cases (e.g. no access check required if N_Op_Ne Null).
+ -- The caller can use this result to determine the value (for the case of
+ -- N_Op_Eq), or to determine the result of some other test in other cases
+ -- (e.g. no access check required if N_Op_Ne Null).
function Homonym_Number (Subp : Entity_Id) return Nat;
-- Here subp is the entity for a subprogram. This routine returns the
- -- homonym number used to disambiguate overloaded subprograms in the
- -- same scope (the number is used as part of constructed names to make
- -- sure that they are unique). The number is the ordinal position on
- -- the Homonym chain, counting only entries in the curren scope. If
- -- an entity is not overloaded, the returned number will be one.
+ -- homonym number used to disambiguate overloaded subprograms in the same
+ -- scope (the number is used as part of constructed names to make sure that
+ -- they are unique). The number is the ordinal position on the Homonym
+ -- chain, counting only entries in the curren scope. If an entity is not
+ -- overloaded, the returned number will be one.
function Inside_Init_Proc return Boolean;
-- Returns True if current scope is within an init proc
function In_Unconditional_Context (Node : Node_Id) return Boolean;
- -- Node is the node for a statement or a component of a statement.
- -- This function deteermines if the statement appears in a context
- -- that is unconditionally executed, i.e. it is not within a loop
- -- or a conditional or a case statement etc.
+ -- Node is the node for a statement or a component of a statement. This
+ -- function deteermines if the statement appears in a context that is
+ -- unconditionally executed, i.e. it is not within a loop or a conditional
+ -- or a case statement etc.
function Is_All_Null_Statements (L : List_Id) return Boolean;
- -- Return True if all the items of the list are N_Null_Statement
- -- nodes. False otherwise. True for an empty list. It is an error
- -- to call this routine with No_List as the argument.
+ -- Return True if all the items of the list are N_Null_Statement nodes.
+ -- False otherwise. True for an empty list. It is an error to call this
+ -- routine with No_List as the argument.
+
+ function Is_Predefined_Dispatching_Operation
+ (Subp : Entity_Id) return Boolean;
+ -- Ada 2005 (AI-251): Determines if Subp is a predefined primitive
+ -- operation.
function Is_Ref_To_Bit_Packed_Array (N : Node_Id) return Boolean;
- -- Determine whether the node P is a reference to a bit packed
- -- array, i.e. whether the designated object is a component of
- -- a bit packed array, or a subcomponent of such a component.
- -- If so, then all subscripts in P are evaluated with a call
- -- to Force_Evaluation, and True is returned. Otherwise False
- -- is returned, and P is not affected.
+ -- Determine whether the node P is a reference to a bit packed array, i.e.
+ -- whether the designated object is a component of a bit packed array, or a
+ -- subcomponent of such a component. If so, then all subscripts in P are
+ -- evaluated with a call to Force_Evaluation, and True is returned.
+ -- Otherwise False is returned, and P is not affected.
function Is_Ref_To_Bit_Packed_Slice (N : Node_Id) return Boolean;
- -- Determine whether the node P is a reference to a bit packed
- -- slice, i.e. whether the designated object is bit packed slice
- -- or a component of a bit packed slice. Return True if so.
+ -- Determine whether the node P is a reference to a bit packed slice, i.e.
+ -- whether the designated object is bit packed slice or a component of a
+ -- bit packed slice. Return True if so.
function Is_Possibly_Unaligned_Slice (N : Node_Id) return Boolean;
-- Determine whether the node P is a slice of an array where the slice
@@ -436,31 +447,30 @@ package Exp_Util is
-- is not compatible with the type. Return True if so.
function Is_Possibly_Unaligned_Object (N : Node_Id) return Boolean;
- -- Node N is an object reference. This function returns True if it
- -- is possible that the object may not be aligned according to the
- -- normal default alignment requirement for its type (e.g. if it
- -- appears in a packed record, or as part of a component that has
- -- a component clause.
+ -- Node N is an object reference. This function returns True if it is
+ -- possible that the object may not be aligned according to the normal
+ -- default alignment requirement for its type (e.g. if it appears in a
+ -- packed record, or as part of a component that has a component clause.
function Is_Renamed_Object (N : Node_Id) return Boolean;
- -- Returns True if the node N is a renamed object. An expression
- -- is considered to be a renamed object if either it is the Name
- -- of an object renaming declaration, or is the prefix of a name
- -- which is a renamed object. For example, in:
+ -- Returns True if the node N is a renamed object. An expression is
+ -- considered to be a renamed object if either it is the Name of an object
+ -- renaming declaration, or is the prefix of a name which is a renamed
+ -- object. For example, in:
--
-- x : r renames a (1 .. 2) (1);
--
- -- We consider that a (1 .. 2) is a renamed object since it is the
- -- prefix of the name in the renaming declaration.
+ -- We consider that a (1 .. 2) is a renamed object since it is the prefix
+ -- of the name in the renaming declaration.
function Is_Untagged_Derivation (T : Entity_Id) return Boolean;
-- Returns true if type T is not tagged and is a derived type,
-- or is a private type whose completion is such a type.
procedure Kill_Dead_Code (N : Node_Id);
- -- N represents a node for a section of code that is known to be
- -- dead. The node is deleted, and any exception handler references
- -- and warning messages relating to this code are removed.
+ -- N represents a node for a section of code that is known to be dead. The
+ -- node is deleted, and any exception handler references and warning
+ -- messages relating to this code are removed.
procedure Kill_Dead_Code (L : List_Id);
-- Like the above procedure, but applies to every element in the given
@@ -485,31 +495,30 @@ package Exp_Util is
-- a classwide type.
function May_Generate_Large_Temp (Typ : Entity_Id) return Boolean;
- -- Determines if the given type, Typ, may require a large temporary
- -- of the kind that causes back-end trouble if stack checking is enabled.
- -- The result is True only the size of the type is known at compile time
- -- and large, where large is defined heuristically by the body of this
- -- routine. The purpose of this routine is to help avoid generating
- -- troublesome temporaries that interfere with stack checking mechanism.
- -- Note that the caller has to check whether stack checking is actually
- -- enabled in order to guide the expansion (typically of a function call).
+ -- Determines if the given type, Typ, may require a large temporary of the
+ -- kind that causes back-end trouble if stack checking is enabled. The
+ -- result is True only the size of the type is known at compile time and
+ -- large, where large is defined heuristically by the body of this routine.
+ -- The purpose of this routine is to help avoid generating troublesome
+ -- temporaries that interfere with stack checking mechanism. Note that the
+ -- caller has to check whether stack checking is actually enabled in order
+ -- to guide the expansion (typically of a function call).
procedure Remove_Side_Effects
(Exp : Node_Id;
Name_Req : Boolean := False;
Variable_Ref : Boolean := False);
- -- Given the node for a subexpression, this function replaces the node
- -- if necessary by an equivalent subexpression that is guaranteed to be
- -- side effect free. This is done by extracting any actions that could
- -- cause side effects, and inserting them using Insert_Actions into the
- -- tree to which Exp is attached. Exp must be analyzed and resolved
- -- before the call and is analyzed and resolved on return. The Name_Req
- -- may only be set to True if Exp has the form of a name, and the
- -- effect is to guarantee that any replacement maintains the form of a
- -- name. If Variable_Ref is set to TRUE, a variable is considered as a
- -- side effect (used in implementing Force_Evaluation). Note: after a
- -- call to Remove_Side_Effects, it is safe to call New_Copy_Tree to
- -- obtain a copy of the resulting expression.
+ -- Given the node for a subexpression, this function replaces the node if
+ -- necessary by an equivalent subexpression that is guaranteed to be side
+ -- effect free. This is done by extracting any actions that could cause
+ -- side effects, and inserting them using Insert_Actions into the tree to
+ -- which Exp is attached. Exp must be analyzed and resolved before the call
+ -- and is analyzed and resolved on return. The Name_Req may only be set to
+ -- True if Exp has the form of a name, and the effect is to guarantee that
+ -- any replacement maintains the form of name. If Variable_Ref is set to
+ -- TRUE, a variable is considered as side effect (used in implementing
+ -- Force_Evaluation). Note: after call to Remove_Side_Effects, it is safe
+ -- to call New_Copy_Tree to obtain a copy of the resulting expression.
function Represented_As_Scalar (T : Entity_Id) return Boolean;
-- Returns True iff the implementation of this type in code generation
@@ -517,22 +526,22 @@ package Exp_Util is
-- packed arrays which are represented by a scalar (modular) type.
function Safe_Unchecked_Type_Conversion (Exp : Node_Id) return Boolean;
- -- Given the node for an N_Unchecked_Type_Conversion, return True
- -- if this is an unchecked conversion that Gigi can handle directly.
- -- Otherwise return False if it is one for which the front end must
- -- provide a temporary. Note that the node need not be analyzed, and
- -- thus the Etype field may not be set, but in that case it must be
- -- the case that the Subtype_Mark field of the node is set/analyzed.
+ -- Given the node for an N_Unchecked_Type_Conversion, return True if this
+ -- is an unchecked conversion that Gigi can handle directly. Otherwise
+ -- return False if it is one for which the front end must provide a
+ -- temporary. Note that the node need not be analyzed, and thus the Etype
+ -- field may not be set, but in that case it must be the case that the
+ -- Subtype_Mark field of the node is set/analyzed.
procedure Set_Elaboration_Flag (N : Node_Id; Spec_Id : Entity_Id);
- -- N is the node for a subprogram or generic body, and Spec_Id
- -- is the entity for the corresponding spec. If an elaboration
- -- entity is defined, then this procedure generates an assignment
- -- statement to set it True, immediately after the body is elaborated.
- -- However, no assignment is generated in the case of library level
- -- procedures, since the setting of the flag in this case is generated
- -- in the binder. We do that so that we can detect cases where this is
- -- the only elaboration action that is required.
+ -- N is the node for a subprogram or generic body, and Spec_Id is the
+ -- entity for the corresponding spec. If an elaboration entity is defined,
+ -- then this procedure generates an assignment statement to set it True,
+ -- immediately after the body is elaborated. However, no assignment is
+ -- generated in the case of library level procedures, since the setting of
+ -- the flag in this case is generated in the binder. We do that so that we
+ -- can detect cases where this is the only elaboration action that is
+ -- required.
function Target_Has_Fixed_Ops
(Left_Typ : Entity_Id;
@@ -545,20 +554,20 @@ package Exp_Util is
function Type_May_Have_Bit_Aligned_Components
(Typ : Entity_Id) return Boolean;
- -- Determines if Typ is a composite type that has within it (looking
- -- down recursively at any subcomponents), a record type which has a
- -- component that may be bit aligned (see Possible_Bit_Aligned_Component).
- -- The result is conservative, in that a result of False is decisive.
- -- A result of True means that such a component may or may not be present.
+ -- Determines if Typ is a composite type that has within it (looking down
+ -- recursively at any subcomponents), a record type which has component
+ -- that may be bit aligned (see Possible_Bit_Aligned_Component). The result
+ -- is conservative, in that a result of False is decisive. A result of True
+ -- means that such a component may or may not be present.
procedure Wrap_Cleanup_Procedure (N : Node_Id);
- -- Given an N_Subprogram_Body node, this procedure adds an Abort_Defer
- -- call at the start of the statement sequence, and an Abort_Undefer call
- -- at the end of the statement sequence. All cleanup routines (i.e. those
- -- that are called from "at end" handlers) must defer abort on entry and
- -- undefer abort on exit. Note that it is assumed that the code for the
- -- procedure does not contain any return statements which would allow the
- -- flow of control to escape doing the undefer call.
+ -- Given an N_Subprogram_Body node, this procedure adds an Abort_Defer call
+ -- at the start of the statement sequence, and an Abort_Undefer call at the
+ -- end of the statement sequence. All cleanup routines (i.e. those that are
+ -- called from "at end" handlers) must defer abort on entry and undefer
+ -- abort on exit. Note that it is assumed that the code for the procedure
+ -- does not contain any return statements which would allow the flow of
+ -- control to escape doing the undefer call.
private
pragma Inline (Force_Evaluation);
diff --git a/gcc/ada/i-cpp.adb b/gcc/ada/i-cpp.adb
index ca872c2544d..85efcea6fcd 100644
--- a/gcc/ada/i-cpp.adb
+++ b/gcc/ada/i-cpp.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2005, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2005 Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -31,357 +31,7 @@
-- --
------------------------------------------------------------------------------
-with Ada.Tags; use Ada.Tags;
-with System; use System;
-with System.Storage_Elements; use System.Storage_Elements;
+-- Dummy body to deal with bootstrap issues (there used to be a real body)
package body Interfaces.CPP is
-
--- Structure of the Dispatch Table
-
--- +-----------------------+
--- | Offset_To_Top |
--- +-----------------------+
--- | Typeinfo_Ptr/TSD_Ptr |----> Type Specific Data
--- Tag ---> +-----------------------+ +-------------------+
--- | table of | | inheritance depth |
--- : primitive ops : +-------------------+
--- | pointers | | expanded name |
--- +-----------------------+ +-------------------+
--- | external tag |
--- +-------------------+
--- | Hash table link |
--- +-------------------+
--- | Remotely Callable |
--- +-------------------+
--- | Rec Ctrler offset |
--- +-------------------+
--- | table of |
--- : ancestor :
--- | tags |
--- +-------------------+
-
- -- The declarations below need (extensive) comments ???
-
- subtype Cstring is String (Positive);
- type Cstring_Ptr is access all Cstring;
- type Tag_Table is array (Natural range <>) of Vtable_Ptr;
- pragma Suppress_Initialization (Tag_Table);
-
- type Type_Specific_Data is record
- Idepth : Natural;
- Expanded_Name : Cstring_Ptr;
- External_Tag : Cstring_Ptr;
- HT_Link : Tag;
- Ancestor_Tags : Tag_Table (Natural);
- end record;
-
- type Vtable_Entry is record
- Pfn : System.Address;
- end record;
-
- type Vtable_Entry_Array is array (Positive range <>) of Vtable_Entry;
-
- type VTable is record
- -- Offset_To_Top : Integer;
- -- Typeinfo_Ptr : System.Address; -- TSD is currently also here???
- Prims_Ptr : Vtable_Entry_Array (Positive);
- end record;
- -- Note: See comment in a-tags.adb explaining why the components
- -- Offset_To_Top and Typeinfo_Ptr have been commented out.
- -- -----------------------------------------------------------------------
- -- The size of the Prims_Ptr array actually depends on the tagged type to
- -- which it applies. For each tagged type, the expander computes the
- -- actual array size, allocates the Dispatch_Table record accordingly, and
- -- generates code that displaces the base of the record after the
- -- Typeinfo_Ptr component. For this reason the first two components have
- -- been commented in the previous declaration. The access to these
- -- components is done by means of local functions.
-
- ---------------------------
- -- Unchecked Conversions --
- ---------------------------
-
- type Int_Ptr is access Integer;
-
- function To_Int_Ptr is
- new Unchecked_Conversion (System.Address, Int_Ptr);
-
- function To_Cstring_Ptr is
- new Unchecked_Conversion (Address, Cstring_Ptr);
-
- function To_Address is
- new Unchecked_Conversion (Cstring_Ptr, Address);
-
- -----------------------
- -- Local Subprograms --
- -----------------------
-
- function Length (Str : Cstring_Ptr) return Natural;
- -- Length of string represented by the given pointer (treating the string
- -- as a C-style string, which is Nul terminated).
-
- function Offset_To_Top (T : Vtable_Ptr) return Integer;
- -- Returns the current value of the offset_to_top component available in
- -- the prologue of the dispatch table.
-
- function Typeinfo_Ptr (T : Vtable_Ptr) return System.Address;
- -- Returns the current value of the typeinfo_ptr component available in
- -- the prologue of the dispatch table.
-
- pragma Unreferenced (Offset_To_Top);
- pragma Unreferenced (Typeinfo_Ptr);
- -- These functions will be used for full compatibility with the C++ ABI
-
- -----------------------
- -- CPP_CW_Membership --
- -----------------------
-
- function CPP_CW_Membership
- (Obj_Tag : Vtable_Ptr;
- Typ_Tag : Vtable_Ptr) return Boolean
- is
- Pos : constant Integer := TSD (Obj_Tag).Idepth - TSD (Typ_Tag).Idepth;
- begin
- return Pos >= 0 and then TSD (Obj_Tag).Ancestor_Tags (Pos) = Typ_Tag;
- end CPP_CW_Membership;
-
- --------------------------
- -- CPP_Get_External_Tag --
- --------------------------
-
- function CPP_Get_External_Tag (T : Vtable_Ptr) return Address is
- begin
- return To_Address (TSD (T).External_Tag);
- end CPP_Get_External_Tag;
-
- -------------------------
- -- CPP_Get_Prim_Op_Address --
- -------------------------
-
- function CPP_Get_Prim_Op_Address
- (T : Vtable_Ptr;
- Position : Positive) return Address
- is
- begin
- return T.Prims_Ptr (Position).Pfn;
- end CPP_Get_Prim_Op_Address;
-
- -----------------------
- -- CPP_Get_RC_Offset --
- -----------------------
-
- function CPP_Get_RC_Offset (T : Vtable_Ptr) return SSE.Storage_Offset is
- pragma Warnings (Off, T);
- begin
- return 0;
- end CPP_Get_RC_Offset;
-
- -------------------------------
- -- CPP_Get_Remotely_Callable --
- -------------------------------
-
- function CPP_Get_Remotely_Callable (T : Vtable_Ptr) return Boolean is
- pragma Warnings (Off, T);
- begin
- return True;
- end CPP_Get_Remotely_Callable;
-
- --------------------
- -- CPP_Inherit_DT --
- --------------------
-
- procedure CPP_Inherit_DT
- (Old_T : Vtable_Ptr;
- New_T : Vtable_Ptr;
- Entry_Count : Natural)
- is
- begin
- if Old_T /= null then
- New_T.Prims_Ptr (1 .. Entry_Count)
- := Old_T.Prims_Ptr (1 .. Entry_Count);
- end if;
- end CPP_Inherit_DT;
-
- ---------------------
- -- CPP_Inherit_TSD --
- ---------------------
-
- procedure CPP_Inherit_TSD
- (Old_Tag : Vtable_Ptr;
- New_Tag : Vtable_Ptr)
- is
- New_TSD_Ptr : constant Type_Specific_Data_Ptr := TSD (New_Tag);
- Old_TSD_Ptr : Type_Specific_Data_Ptr;
-
- begin
- if Old_Tag /= null then
- Old_TSD_Ptr := TSD (Old_Tag);
- New_TSD_Ptr.Idepth := Old_TSD_Ptr.Idepth + 1;
- New_TSD_Ptr.Ancestor_Tags (1 .. New_TSD_Ptr.Idepth) :=
- Old_TSD_Ptr.Ancestor_Tags (0 .. Old_TSD_Ptr.Idepth);
- else
- New_TSD_Ptr.Idepth := 0;
- end if;
-
- New_TSD_Ptr.Ancestor_Tags (0) := New_Tag;
- end CPP_Inherit_TSD;
-
- ---------------------------
- -- CPP_Set_Expanded_Name --
- ---------------------------
-
- procedure CPP_Set_Expanded_Name (T : Vtable_Ptr; Value : Address) is
- begin
- TSD (T).Expanded_Name := To_Cstring_Ptr (Value);
- end CPP_Set_Expanded_Name;
-
- --------------------------
- -- CPP_Set_External_Tag --
- --------------------------
-
- procedure CPP_Set_External_Tag (T : Vtable_Ptr; Value : Address) is
- begin
- TSD (T).External_Tag := To_Cstring_Ptr (Value);
- end CPP_Set_External_Tag;
-
- -----------------------------
- -- CPP_Set_Prim_Op_Address --
- -----------------------------
-
- procedure CPP_Set_Prim_Op_Address
- (T : Vtable_Ptr;
- Position : Positive;
- Value : Address)
- is
- begin
- T.Prims_Ptr (Position).Pfn := Value;
- end CPP_Set_Prim_Op_Address;
-
- -----------------------
- -- CPP_Set_RC_Offset --
- -----------------------
-
- procedure CPP_Set_RC_Offset (T : Vtable_Ptr; Value : SSE.Storage_Offset) is
- pragma Warnings (Off, T);
- pragma Warnings (Off, Value);
- begin
- null;
- end CPP_Set_RC_Offset;
-
- -------------------------------
- -- CPP_Set_Remotely_Callable --
- -------------------------------
-
- procedure CPP_Set_Remotely_Callable (T : Vtable_Ptr; Value : Boolean) is
- pragma Warnings (Off, T);
- pragma Warnings (Off, Value);
- begin
- null;
- end CPP_Set_Remotely_Callable;
-
- -----------------
- -- CPP_Set_TSD --
- -----------------
-
- procedure CPP_Set_TSD (T : Vtable_Ptr; Value : Address) is
- use type System.Storage_Elements.Storage_Offset;
- TSD_Ptr : constant Addr_Ptr :=
- To_Addr_Ptr (To_Address (T) - CPP_DT_Typeinfo_Ptr_Size);
- begin
- TSD_Ptr.all := Value;
- end CPP_Set_TSD;
-
- --------------------
- -- Displaced_This --
- --------------------
-
- function Displaced_This
- (Current_This : System.Address;
- Vptr : Vtable_Ptr;
- Position : Positive)
- return System.Address
- is
- pragma Warnings (Off, Vptr);
- pragma Warnings (Off, Position);
-
- begin
- return Current_This;
-
- -- why is the following here commented out ???
- -- + Storage_Offset (Vptr.Prims_Ptr (Position).Delta1);
- end Displaced_This;
-
- -------------------
- -- Expanded_Name --
- -------------------
-
- function Expanded_Name (T : Vtable_Ptr) return String is
- Result : constant Cstring_Ptr := TSD (T).Expanded_Name;
- begin
- return Result (1 .. Length (Result));
- end Expanded_Name;
-
- ------------------
- -- External_Tag --
- ------------------
-
- function External_Tag (T : Vtable_Ptr) return String is
- Result : constant Cstring_Ptr := TSD (T).External_Tag;
- begin
- return Result (1 .. Length (Result));
- end External_Tag;
-
- ------------
- -- Length --
- ------------
-
- function Length (Str : Cstring_Ptr) return Natural is
- Len : Integer := 1;
-
- begin
- while Str (Len) /= ASCII.Nul loop
- Len := Len + 1;
- end loop;
-
- return Len - 1;
- end Length;
-
- ------------------
- -- Offset_To_Top --
- ------------------
-
- function Offset_To_Top (T : Vtable_Ptr) return Integer is
- use type System.Storage_Elements.Storage_Offset;
-
- TSD_Ptr : constant Int_Ptr
- := To_Int_Ptr (To_Address (T) - CPP_DT_Prologue_Size);
- begin
- return TSD_Ptr.all;
- end Offset_To_Top;
-
- ------------------
- -- Typeinfo_Ptr --
- ------------------
-
- function Typeinfo_Ptr (T : Vtable_Ptr) return System.Address is
- use type System.Storage_Elements.Storage_Offset;
- TSD_Ptr : constant Addr_Ptr :=
- To_Addr_Ptr (To_Address (T) - CPP_DT_Typeinfo_Ptr_Size);
- begin
- return TSD_Ptr.all;
- end Typeinfo_Ptr;
-
- ---------
- -- TSD --
- ---------
-
- function TSD (T : Vtable_Ptr) return Type_Specific_Data_Ptr is
- use type System.Storage_Elements.Storage_Offset;
- TSD_Ptr : constant Addr_Ptr :=
- To_Addr_Ptr (To_Address (T) - CPP_DT_Typeinfo_Ptr_Size);
- begin
- return To_Type_Specific_Data_Ptr (TSD_Ptr.all);
- end TSD;
-
end Interfaces.CPP;
diff --git a/gcc/ada/i-cpp.ads b/gcc/ada/i-cpp.ads
index 99922cf56ee..6dbed5f481f 100644
--- a/gcc/ada/i-cpp.ads
+++ b/gcc/ada/i-cpp.ads
@@ -1,12 +1,12 @@
------------------------------------------------------------------------------
-- --
--- GNAT RUNTIME COMPONENTS --
+-- GNAT RUN-TIME COMPONENTS --
-- --
-- I N T E R F A C E S . C P P --
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2005, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2005 Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -31,168 +31,21 @@
-- --
------------------------------------------------------------------------------
--- Definitions for interfacing to C++ classes
-
--- This package corresponds to Ada.Tags but applied to tagged types which are
--- are imported from C++ and correspond exactly to a C++ Class. The code that
--- the GNAT front end generates does not know about the structure of the C++
--- dispatch table (Vtable) but always accesses it through the procedural
--- interface defined in this package, thus the implementation of this package
--- (the body) can be customized to another C++ compiler without any change in
--- the compiler code itself as long as this procedural interface is respected.
--- Note that Ada.Tags defines a very similar procedural interface to the
--- regular Ada Dispatch Table.
-
-with System;
-with System.Storage_Elements;
-with Unchecked_Conversion;
+-- Missing package comment ???
+with Ada.Tags;
package Interfaces.CPP is
+pragma Elaborate_Body;
+-- We have a dummy body to deal with bootstrap path issues
- type Vtable_Ptr is private;
-
- function Expanded_Name (T : Vtable_Ptr) return String;
- function External_Tag (T : Vtable_Ptr) return String;
-
-private
- package S renames System;
- package SSE renames System.Storage_Elements;
-
- type Vtable;
- type Vtable_Ptr is access all Vtable;
-
- type Type_Specific_Data;
- type Type_Specific_Data_Ptr is access all Type_Specific_Data;
-
- -- These subprograms are in the private part. They are never accessed
- -- directly except from compiler generated code, which has access to
- -- private components of packages via the Rtsfind interface.
-
- procedure CPP_Set_Prim_Op_Address
- (T : Vtable_Ptr;
- Position : Positive;
- Value : S.Address);
- -- Given a pointer to a dispatch Table (T) and a position in the
- -- dispatch Table put the address of the virtual function in it
- -- (used for overriding)
-
- function CPP_Get_Prim_Op_Address
- (T : Vtable_Ptr;
- Position : Positive)
- return S.Address;
- -- Given a pointer to a dispatch Table (T) and a position in the DT
- -- this function returns the address of the virtual function stored
- -- in it (used for dispatching calls)
-
- procedure CPP_Set_TSD (T : Vtable_Ptr; Value : S.Address);
- -- Given a pointer T to a dispatch Table, stores the address of the
- -- record containing the Type Specific Data generated by GNAT
-
- CPP_DT_Prologue_Size : constant SSE.Storage_Count :=
- SSE.Storage_Count
- (2 * (Standard'Address_Size / S.Storage_Unit));
- -- Size of the first part of the dispatch table
-
- CPP_DT_Typeinfo_Ptr_Size : constant SSE.Storage_Count :=
- SSE.Storage_Count
- (Standard'Address_Size / System.Storage_Unit);
- -- Size of the Typeinfo_Ptr field of the Dispatch Table.
-
- CPP_DT_Entry_Size : constant SSE.Storage_Count :=
- SSE.Storage_Count
- (1 * (Standard'Address_Size / S.Storage_Unit));
- -- Size of each primitive operation entry in the Dispatch Table.
-
- CPP_TSD_Prologue_Size : constant SSE.Storage_Count :=
- SSE.Storage_Count
- (4 * (Standard'Address_Size / S.Storage_Unit));
- -- Size of the first part of the type specific data
-
- CPP_TSD_Entry_Size : constant SSE.Storage_Count :=
- SSE.Storage_Count
- (1 * (Standard'Address_Size / S.Storage_Unit));
- -- Size of each ancestor tag entry in the TSD
-
- procedure CPP_Inherit_DT
- (Old_T : Vtable_Ptr;
- New_T : Vtable_Ptr;
- Entry_Count : Natural);
- -- Entry point used to initialize the DT of a type knowing the
- -- tag of the direct ancestor and the number of primitive ops that are
- -- inherited (Entry_Count).
-
- procedure CPP_Inherit_TSD
- (Old_Tag : Vtable_Ptr;
- New_Tag : Vtable_Ptr);
- -- Entry point used to initialize the TSD of a type knowing the
- -- TSD of the direct ancestor.
-
- function CPP_CW_Membership (Obj_Tag, Typ_Tag : Vtable_Ptr) return Boolean;
- -- Given the tag of an object and the tag associated to a type, return
- -- true if Obj is in Typ'Class.
-
- procedure CPP_Set_External_Tag (T : Vtable_Ptr; Value : S.Address);
- -- Set the address of the string containing the external tag
- -- in the Dispatch table
-
- function CPP_Get_External_Tag (T : Vtable_Ptr) return S.Address;
- -- Retrieve the address of a null terminated string containing
- -- the external name
-
- procedure CPP_Set_Expanded_Name (T : Vtable_Ptr; Value : S.Address);
- -- Set the address of the string containing the expanded name
- -- in the Dispatch table
-
- procedure CPP_Set_Remotely_Callable (T : Vtable_Ptr; Value : Boolean);
- -- Since the notions of spec/body distinction and categorized packages
- -- do not exist in C, this procedure will do nothing
-
- function CPP_Get_Remotely_Callable (T : Vtable_Ptr) return Boolean;
- -- This function will always return True for the reason explained above
-
- procedure CPP_Set_RC_Offset (T : Vtable_Ptr; Value : SSE.Storage_Offset);
- -- Sets the Offset of the implicit record controller when the object
- -- has controlled components. Set to O otherwise.
-
- function CPP_Get_RC_Offset (T : Vtable_Ptr) return SSE.Storage_Offset;
- -- Return the Offset of the implicit record controller when the object
- -- has controlled components. O otherwise.
-
- function Displaced_This
- (Current_This : S.Address;
- Vptr : Vtable_Ptr;
- Position : Positive)
- return S.Address;
- -- Compute the displacement on the "this" pointer in order to be
- -- compatible with MI.
- -- (used for virtual function calls)
-
- function TSD (T : Vtable_Ptr) return Type_Specific_Data_Ptr;
- -- Given a pointer T to a dispatch Table, retreives the address of the
- -- record containing the Type Specific Data generated by GNAT
-
- type Addr_Ptr is access System.Address;
-
- function To_Address is
- new Unchecked_Conversion (Vtable_Ptr, System.Address);
+ subtype Vtable_Ptr is Ada.Tags.Tag;
- function To_Addr_Ptr is
- new Unchecked_Conversion (System.Address, Addr_Ptr);
+ -- These need commenting (this is not an RM package!)
- function To_Type_Specific_Data_Ptr is
- new Unchecked_Conversion (System.Address, Type_Specific_Data_Ptr);
+ function Expanded_Name (T : Vtable_Ptr) return String
+ renames Ada.Tags.Expanded_Name;
- pragma Inline (CPP_Set_Prim_Op_Address);
- pragma Inline (CPP_Get_Prim_Op_Address);
- pragma Inline (CPP_Set_TSD);
- pragma Inline (CPP_Inherit_DT);
- pragma Inline (CPP_CW_Membership);
- pragma Inline (CPP_Set_External_Tag);
- pragma Inline (CPP_Get_External_Tag);
- pragma Inline (CPP_Set_Expanded_Name);
- pragma Inline (CPP_Set_Remotely_Callable);
- pragma Inline (CPP_Get_Remotely_Callable);
- pragma Inline (Displaced_This);
- pragma Inline (TSD);
+ function External_Tag (T : Vtable_Ptr) return String
+ renames Ada.Tags.External_Tag;
end Interfaces.CPP;
diff --git a/gcc/ada/par-ch3.adb b/gcc/ada/par-ch3.adb
index 0c02ff7d035..b86058801ce 100644
--- a/gcc/ada/par-ch3.adb
+++ b/gcc/ada/par-ch3.adb
@@ -175,11 +175,12 @@ package body Ch3 is
if Token = Tok_Identifier then
- -- Ada 2005 (AI-284): Compiling in Ada95 mode we notify
- -- that interface, overriding, and synchronized are
- -- new reserved words
+ -- Ada 2005 (AI-284): Compiling in Ada95 mode we warn that INTERFACE,
+ -- OVERRIDING, and SYNCHRONIZED are new reserved words.
- if Ada_Version = Ada_95 then
+ if Ada_Version = Ada_95
+ and then Warn_On_Ada_2005_Compatibility
+ then
if Token_Name = Name_Overriding
or else Token_Name = Name_Synchronized
or else (Token_Name = Name_Interface
@@ -235,7 +236,8 @@ package body Ch3 is
-- PRIVATE_EXTENSION_DECLARATION ::=
-- type DEFINING_IDENTIFIER [DISCRIMINANT_PART] is
- -- [abstract] new ancestor_SUBTYPE_INDICATION with private;
+ -- [abstract] new ancestor_SUBTYPE_INDICATION
+ -- [and INTERFACE_LIST] with private;
-- TYPE_DEFINITION ::=
-- ENUMERATION_TYPE_DEFINITION | INTEGER_TYPE_DEFINITION
@@ -702,6 +704,7 @@ package body Ch3 is
Typedef_Node := P_Interface_Type_Definition
(Is_Synchronized => True);
+ Abstract_Present := True;
case Saved_Token is
when Tok_Task =>
@@ -1120,6 +1123,8 @@ package body Ch3 is
-- DEFINING_IDENTIFIER_LIST : [aliased] [constant]
-- [NULL_EXCLUSION] SUBTYPE_INDICATION [:= EXPRESSION];
-- | DEFINING_IDENTIFIER_LIST : [aliased] [constant]
+ -- ACCESS_DEFINITION [:= EXPRESSION];
+ -- | DEFINING_IDENTIFIER_LIST : [aliased] [constant]
-- ARRAY_TYPE_DEFINITION [:= EXPRESSION];
-- NUMBER_DECLARATION ::=
@@ -1414,8 +1419,21 @@ package body Ch3 is
Not_Null_Present := P_Null_Exclusion; -- Ada 2005 (AI-231)
Set_Null_Exclusion_Present (Decl_Node, Not_Null_Present);
- Set_Object_Definition (Decl_Node,
- P_Subtype_Indication (Not_Null_Present));
+ if Token = Tok_Access then
+ if Ada_Version < Ada_05 then
+ Error_Msg_SP
+ ("generalized use of anonymous access types " &
+ "is an Ada 2005 extension");
+ Error_Msg_SP
+ ("\unit must be compiled with -gnat05 switch");
+ end if;
+
+ Set_Object_Definition
+ (Decl_Node, P_Access_Definition (Not_Null_Present));
+ else
+ Set_Object_Definition
+ (Decl_Node, P_Subtype_Indication (Not_Null_Present));
+ end if;
end if;
if Token = Tok_Renames then
@@ -1461,8 +1479,24 @@ package body Ch3 is
else
Not_Null_Present := P_Null_Exclusion; -- Ada 2005 (AI-231)
Set_Null_Exclusion_Present (Decl_Node, Not_Null_Present);
- Set_Object_Definition (Decl_Node,
- P_Subtype_Indication (Not_Null_Present));
+
+ -- Access definition (AI-406) or subtype indication.
+
+ if Token = Tok_Access then
+ if Ada_Version < Ada_05 then
+ Error_Msg_SP
+ ("generalized use of anonymous access types " &
+ "is an Ada 2005 extension");
+ Error_Msg_SP
+ ("\unit must be compiled with -gnat05 switch");
+ end if;
+
+ Set_Object_Definition
+ (Decl_Node, P_Access_Definition (Not_Null_Present));
+ else
+ Set_Object_Definition
+ (Decl_Node, P_Subtype_Indication (Not_Null_Present));
+ end if;
end if;
-- Array case
@@ -1471,13 +1505,15 @@ package body Ch3 is
Decl_Node := New_Node (N_Object_Declaration, Ident_Sloc);
Set_Object_Definition (Decl_Node, P_Array_Type_Definition);
- -- Ada 2005 (AI-254)
+ -- Ada 2005 (AI-254, AI-406)
elsif Token = Tok_Not then
-- OBJECT_DECLARATION ::=
-- DEFINING_IDENTIFIER_LIST : [aliased] [constant]
-- [NULL_EXCLUSION] SUBTYPE_INDICATION [:= EXPRESSION];
+ -- | DEFINING_IDENTIFIER_LIST : [aliased] [constant]
+ -- ACCESS_DEFINITION [:= EXPRESSION];
-- OBJECT_RENAMING_DECLARATION ::=
-- ...
@@ -1496,16 +1532,18 @@ package body Ch3 is
Acc_Node := P_Access_Definition (Not_Null_Present);
if Token /= Tok_Renames then
- Error_Msg_SC ("RENAMES expected");
- raise Error_Resync;
- end if;
+ Decl_Node := New_Node (N_Object_Declaration, Ident_Sloc);
+ Set_Object_Definition (Decl_Node, Acc_Node);
+ goto init;
- Scan; -- past renames
- No_List;
- Decl_Node :=
- New_Node (N_Object_Renaming_Declaration, Ident_Sloc);
- Set_Access_Definition (Decl_Node, Acc_Node);
- Set_Name (Decl_Node, P_Name);
+ else
+ Scan; -- past renames
+ No_List;
+ Decl_Node :=
+ New_Node (N_Object_Renaming_Declaration, Ident_Sloc);
+ Set_Access_Definition (Decl_Node, Acc_Node);
+ Set_Name (Decl_Node, P_Name);
+ end if;
else
Type_Node := P_Subtype_Mark;
@@ -1551,17 +1589,21 @@ package body Ch3 is
Acc_Node := P_Access_Definition (Null_Exclusion_Present => False);
+ -- Object declaration with access definition, or renaming.
+
if Token /= Tok_Renames then
- Error_Msg_SC ("RENAMES expected");
- raise Error_Resync;
- end if;
+ Decl_Node := New_Node (N_Object_Declaration, Ident_Sloc);
+ Set_Object_Definition (Decl_Node, Acc_Node);
+ goto init; -- ??? is this really needed goes here anyway
- Scan; -- past renames
- No_List;
- Decl_Node :=
- New_Node (N_Object_Renaming_Declaration, Ident_Sloc);
- Set_Access_Definition (Decl_Node, Acc_Node);
- Set_Name (Decl_Node, P_Name);
+ else
+ Scan; -- past renames
+ No_List;
+ Decl_Node :=
+ New_Node (N_Object_Renaming_Declaration, Ident_Sloc);
+ Set_Access_Definition (Decl_Node, Acc_Node);
+ Set_Name (Decl_Node, P_Name);
+ end if;
-- Subtype indication case
@@ -1600,6 +1642,7 @@ package body Ch3 is
-- Scan out initialization, allowed only for object declaration
+ <<init>> -- is this really needed ???
Init_Loc := Token_Ptr;
Init_Expr := Init_Expr_Opt;
@@ -1765,7 +1808,8 @@ package body Ch3 is
Make_Private_Extension_Declaration (No_Location,
Defining_Identifier => Empty,
Subtype_Indication => Subtype_Indication (Typedef_Node),
- Abstract_Present => Abstract_Present (Typedef_Node));
+ Abstract_Present => Abstract_Present (Typedef_Node),
+ Interface_List => Interface_List (Typedef_Node));
Delete_Node (Typedef_Node);
return Typedecl_Node;
@@ -3823,6 +3867,20 @@ package body Ch3 is
Check_Bad_Layout;
P_Identifier_Declarations (Decls, Done, In_Spec);
+ -- Ada2005: A subprogram declaration can start with "not" or
+ -- "overriding". In older versions, "overriding" is handled
+ -- like an identifier, with the appropriate warning.
+
+ when Tok_Not =>
+ Check_Bad_Layout;
+ Append (P_Subprogram (Pf_Decl_Gins_Pbod_Rnam_Stub), Decls);
+ Done := False;
+
+ when Tok_Overriding =>
+ Check_Bad_Layout;
+ Append (P_Subprogram (Pf_Decl_Gins_Pbod_Rnam_Stub), Decls);
+ Done := False;
+
when Tok_Package =>
Check_Bad_Layout;
Append (P_Package (Pf_Decl_Gins_Pbod_Rnam_Stub), Decls);
diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads
index 1697b359640..1908af5ca63 100644
--- a/gcc/ada/rtsfind.ads
+++ b/gcc/ada/rtsfind.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2005, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2005 Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -484,10 +484,14 @@ package Rtsfind is
RE_Stream_Access, -- Ada.Streams.Stream_IO
+ RE_Addr_Ptr, -- Ada.Tags
RE_CW_Membership, -- Ada.Tags
+ RE_IW_Membership, -- Ada.Tags
+ RE_Descendant_Tag, -- Ada.Tags
RE_DT_Entry_Size, -- Ada.Tags
RE_DT_Prologue_Size, -- Ada.Tags
RE_External_Tag, -- Ada.Tags
+ RE_Get_Access_Level, -- Ada.Tags
RE_Get_External_Tag, -- Ada.Tags
RE_Get_Prim_Op_Address, -- Ada.Tags
RE_Get_RC_Offset, -- Ada.Tags
@@ -495,9 +499,13 @@ package Rtsfind is
RE_Inherit_DT, -- Ada.Tags
RE_Inherit_TSD, -- Ada.Tags
RE_Internal_Tag, -- Ada.Tags
+ RE_Is_Descendant_At_Same_Level, -- Ada.Tags
+ RE_Register_Interface_Tag, -- Ada.Tags
RE_Register_Tag, -- Ada.Tags
+ RE_Set_Access_Level, -- Ada.Tags
RE_Set_Expanded_Name, -- Ada.Tags
RE_Set_External_Tag, -- Ada.Tags
+ RE_Set_Offset_To_Top, -- Ada.Tags
RE_Set_Prim_Op_Address, -- Ada.Tags
RE_Set_RC_Offset, -- Ada.Tags
RE_Set_Remotely_Callable, -- Ada.Tags
@@ -505,6 +513,7 @@ package Rtsfind is
RE_Tag_Error, -- Ada.Tags
RE_TSD_Entry_Size, -- Ada.Tags
RE_TSD_Prologue_Size, -- Ada.Tags
+ RE_Interface_Tag, -- Ada.Tags
RE_Tag, -- Ada.Tags
RE_Address_Array, -- Ada.Tags
@@ -1582,10 +1591,14 @@ package Rtsfind is
RE_Stream_Access => Ada_Streams_Stream_IO,
+ RE_Addr_Ptr => Ada_Tags,
RE_CW_Membership => Ada_Tags,
+ RE_IW_Membership => Ada_Tags,
+ RE_Descendant_Tag => Ada_Tags,
RE_DT_Entry_Size => Ada_Tags,
RE_DT_Prologue_Size => Ada_Tags,
RE_External_Tag => Ada_Tags,
+ RE_Get_Access_Level => Ada_Tags,
RE_Get_External_Tag => Ada_Tags,
RE_Get_Prim_Op_Address => Ada_Tags,
RE_Get_RC_Offset => Ada_Tags,
@@ -1593,9 +1606,13 @@ package Rtsfind is
RE_Inherit_DT => Ada_Tags,
RE_Inherit_TSD => Ada_Tags,
RE_Internal_Tag => Ada_Tags,
+ RE_Is_Descendant_At_Same_Level => Ada_Tags,
+ RE_Register_Interface_Tag => Ada_Tags,
RE_Register_Tag => Ada_Tags,
+ RE_Set_Access_Level => Ada_Tags,
RE_Set_Expanded_Name => Ada_Tags,
RE_Set_External_Tag => Ada_Tags,
+ RE_Set_Offset_To_Top => Ada_Tags,
RE_Set_Prim_Op_Address => Ada_Tags,
RE_Set_RC_Offset => Ada_Tags,
RE_Set_Remotely_Callable => Ada_Tags,
@@ -1603,6 +1620,7 @@ package Rtsfind is
RE_Tag_Error => Ada_Tags,
RE_TSD_Entry_Size => Ada_Tags,
RE_TSD_Prologue_Size => Ada_Tags,
+ RE_Interface_Tag => Ada_Tags,
RE_Tag => Ada_Tags,
RE_Address_Array => Ada_Tags,
diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb
index 661ac7651bc..fd4392aa931 100644
--- a/gcc/ada/sem_ch12.adb
+++ b/gcc/ada/sem_ch12.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2005, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2005 Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -690,12 +690,13 @@ package body Sem_Ch12 is
-- parent at the end of the instantiation (see Remove_Parent).
type Instance_Env is record
- Ada_Version : Ada_Version_Type;
- Instantiated_Parent : Assoc;
- Exchanged_Views : Elist_Id;
- Hidden_Entities : Elist_Id;
- Current_Sem_Unit : Unit_Number_Type;
- Parent_Unit_Visible : Boolean := False;
+ Ada_Version : Ada_Version_Type;
+ Ada_Version_Explicit : Ada_Version_Type;
+ Instantiated_Parent : Assoc;
+ Exchanged_Views : Elist_Id;
+ Hidden_Entities : Elist_Id;
+ Current_Sem_Unit : Unit_Number_Type;
+ Parent_Unit_Visible : Boolean := False;
end record;
package Instance_Envs is new Table.Table (
@@ -1696,6 +1697,8 @@ package body Sem_Ch12 is
end if;
Formal := New_Copy (Pack_Id);
+ Create_Instantiation_Source (N, Gen_Unit, False, S_Adjustment);
+
New_N :=
Copy_Generic_Node
(Original_Node (Gen_Decl), Empty, Instantiating => True);
@@ -2620,17 +2623,30 @@ package body Sem_Ch12 is
-- generic is not a child unit of another generic, to avoid scope
-- problems and the reinstallation of parent instances.
- if Front_End_Inlining
- and then Expander_Active
+ if Expander_Active
and then (not Is_Child_Unit (Gen_Unit)
or else not Is_Generic_Unit (Scope (Gen_Unit)))
- and then (Is_In_Main_Unit (N)
- or else In_Main_Context (Current_Scope))
- and then Nkind (Parent (N)) /= N_Compilation_Unit
and then Might_Inline_Subp
and then not Is_Actual_Pack
then
- Inline_Now := True;
+ if Front_End_Inlining
+ and then (Is_In_Main_Unit (N)
+ or else In_Main_Context (Current_Scope))
+ and then Nkind (Parent (N)) /= N_Compilation_Unit
+ then
+ Inline_Now := True;
+
+ -- In configurable_run_time mode we force the inlining of
+ -- predefined subprogram marked Inline_Always, to minimize
+ -- the use of the run-time library.
+
+ elsif Is_Predefined_File_Name
+ (Unit_File_Name (Get_Source_Unit (Gen_Decl)))
+ and then Configurable_Run_Time_Mode
+ and then Nkind (Parent (N)) /= N_Compilation_Unit
+ then
+ Inline_Now := True;
+ end if;
end if;
Needs_Body :=
@@ -2641,7 +2657,6 @@ package body Sem_Ch12 is
or else Might_Inline_Subp)
and then not Is_Actual_Pack
and then not Inline_Now
-
and then (Operating_Mode = Generate_Code
or else (Operating_Mode = Check_Semantics
and then ASIS_Mode));
@@ -2657,12 +2672,11 @@ package body Sem_Ch12 is
end if;
-- If the current context is generic, and the package being
- -- instantiated is declared within a formal package, there
- -- is no body to instantiate until the enclosing generic is
- -- instantiated, and there is an actual for the formal
- -- package. If the formal package has parameters, we build a
- -- regular package instance for it, that preceeds the original
- -- formal package declaration.
+ -- instantiated is declared within a formal package, there is no
+ -- body to instantiate until the enclosing generic is instantiated
+ -- and there is an actual for the formal package. If the formal
+ -- package has parameters, we build regular package instance for
+ -- it, that preceeds the original formal package declaration.
if In_Open_Scopes (Scope (Scope (Gen_Unit))) then
declare
@@ -2683,9 +2697,9 @@ package body Sem_Ch12 is
end if;
end;
- -- If we are generating the calling stubs from the instantiation
- -- of a generic RCI package, we will not use the body of the
- -- generic package.
+ -- If we are generating the calling stubs from the instantiation of
+ -- a generic RCI package, we will not use the body of the generic
+ -- package.
if Distribution_Stub_Mode = Generate_Caller_Stub_Body
and then Is_Compilation_Unit (Defining_Entity (N))
@@ -2829,7 +2843,8 @@ package body Sem_Ch12 is
end if;
end if;
- -- There is a problem with inlining here.
+ -- There is a problem with inlining here
+ -- More comments needed??? what problem
Set_Unit (Parent (N), Act_Decl);
Set_Parent_Spec (Act_Decl, Parent_Spec (N));
@@ -3500,6 +3515,30 @@ package body Sem_Ch12 is
Check_Elab_Instantiation (N);
end if;
+ if Is_Dispatching_Operation (Act_Decl_Id)
+ and then Ada_Version >= Ada_05
+ then
+ declare
+ Formal : Entity_Id;
+
+ begin
+ Formal := First_Formal (Act_Decl_Id);
+ while Present (Formal) loop
+ if Ekind (Etype (Formal)) = E_Anonymous_Access_Type
+ and then Is_Controlling_Formal (Formal)
+ and then not Can_Never_Be_Null (Formal)
+ then
+ Error_Msg_NE ("access parameter& is controlling,",
+ N, Formal);
+ Error_Msg_NE ("\corresponding parameter of & must be"
+ & " explicitly null-excluding", N, Gen_Id);
+ end if;
+
+ Next_Formal (Formal);
+ end loop;
+ end;
+ end if;
+
Check_Hidden_Child_Unit (N, Gen_Unit, Act_Decl_Id);
-- Subject to change, pending on if other pragmas are inherited ???
@@ -3507,7 +3546,6 @@ package body Sem_Ch12 is
Validate_Categorization_Dependency (N, Act_Decl_Id);
if not Is_Intrinsic_Subprogram (Act_Decl_Id) then
-
if not Generic_Separately_Compiled (Gen_Unit) then
Inherit_Context (Gen_Decl, N);
end if;
@@ -3521,7 +3559,7 @@ package body Sem_Ch12 is
or else Is_Inlined (Act_Decl_Id))
and then (Operating_Mode = Generate_Code
or else (Operating_Mode = Check_Semantics
- and then ASIS_Mode))
+ and then ASIS_Mode))
and then (Expander_Active or else ASIS_Mode)
and then not ABE_Is_Certain (N)
and then not Is_Eliminated (Act_Decl_Id)
@@ -3764,6 +3802,7 @@ package body Sem_Ch12 is
(E1, E2 : Entity_Id) return Boolean
is
Ent : Entity_Id;
+
begin
Ent := E2;
while Present (Ent) loop
@@ -5814,12 +5853,13 @@ package body Sem_Ch12 is
Saved : Instance_Env;
begin
- Saved.Ada_Version := Ada_Version;
- Saved.Instantiated_Parent := Current_Instantiated_Parent;
- Saved.Exchanged_Views := Exchanged_Views;
- Saved.Hidden_Entities := Hidden_Entities;
- Saved.Current_Sem_Unit := Current_Sem_Unit;
- Saved.Parent_Unit_Visible := Parent_Unit_Visible;
+ Saved.Ada_Version := Ada_Version;
+ Saved.Ada_Version_Explicit := Ada_Version_Explicit;
+ Saved.Instantiated_Parent := Current_Instantiated_Parent;
+ Saved.Exchanged_Views := Exchanged_Views;
+ Saved.Hidden_Entities := Hidden_Entities;
+ Saved.Current_Sem_Unit := Current_Sem_Unit;
+ Saved.Parent_Unit_Visible := Parent_Unit_Visible;
Instance_Envs.Increment_Last;
Instance_Envs.Table (Instance_Envs.Last) := Saved;
@@ -6976,6 +7016,22 @@ package body Sem_Ch12 is
Nam := Make_Identifier (Loc, Chars (Formal_Sub));
end if;
+ elsif Nkind (Specification (Formal)) = N_Procedure_Specification
+ and then Null_Present (Specification (Formal))
+ then
+ -- Generate null body for procedure, for use in the instance
+
+ Decl_Node :=
+ Make_Subprogram_Body (Loc,
+ Specification => New_Spec,
+ Declarations => New_List,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (Make_Null_Statement (Loc))));
+
+ Set_Is_Intrinsic_Subprogram (Defining_Unit_Name (New_Spec));
+ return Decl_Node;
+
else
Error_Msg_Sloc := Sloc (Scope (Analyzed_S));
Error_Msg_NE
@@ -8172,7 +8228,18 @@ package body Sem_Ch12 is
Ancestor := Get_Instance_Of (Etype (Base_Type (A_Gen_T)));
end if;
- if not Is_Ancestor (Base_Type (Ancestor), Act_T) then
+ -- Ada 2005 (AI-251)
+
+ if Ada_Version >= Ada_05
+ and then Is_Interface (Ancestor)
+ then
+ if not Interface_Present_In_Ancestor (Act_T, Ancestor) then
+ Error_Msg_NE
+ ("(Ada 2005) expected type implementing & in instantiation",
+ Actual, Ancestor);
+ end if;
+
+ elsif not Is_Ancestor (Base_Type (Ancestor), Act_T) then
Error_Msg_NE
("expect type derived from & in instantiation",
Actual, First_Subtype (Ancestor));
@@ -9061,6 +9128,7 @@ package body Sem_Ch12 is
begin
Ada_Version := Saved.Ada_Version;
+ Ada_Version_Explicit := Saved.Ada_Version_Explicit;
if No (Current_Instantiated_Parent.Act_Id) then
@@ -10060,16 +10128,18 @@ package body Sem_Ch12 is
(Gen_Unit : Entity_Id;
Act_Unit : Entity_Id)
is
-
begin
-- Regardless of the current mode, predefined units are analyzed in
-- the most current Ada mode, and earlier version Ada checks do not
-- apply to predefined units.
+ -- Why is this not using the routine Opt.Set_Opt_Config_Switches ???
+
if Is_Internal_File_Name
(Fname => Unit_File_Name (Get_Source_Unit (Gen_Unit)),
Renamings_Included => True) then
Ada_Version := Ada_Version_Type'Last;
+ Ada_Version_Explicit := Ada_Version_Explicit_Config;
end if;
Current_Instantiated_Parent := (Gen_Unit, Act_Unit, Assoc_Null);
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index 609871aa1c8..7ca349c337d 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2005, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2005 Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -76,6 +76,12 @@ 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_Derived_Type
(N : Node_Id;
Parent_Type : Entity_Id;
@@ -164,6 +170,23 @@ package body Sem_Ch3 is
-- False is for an implicit derived full type for a type derived from a
-- private type (see Build_Derived_Type).
+ procedure Collect_Interfaces
+ (N : Node_Id;
+ Derived_Type : Entity_Id);
+ -- Ada 2005 (AI-251): Subsidiary procedure to Build_Derived_Record_Type.
+ -- Collect the list of interfaces that are not already implemented by the
+ -- ancestors. This is the list of interfaces for which we must provide
+ -- additional tag components.
+
+ procedure Complete_Subprograms_Derivation
+ (Partial_View : Entity_Id;
+ Derived_Type : Entity_Id);
+ -- Ada 2005 (AI-251): Used to complete type derivation of private tagged
+ -- types implementing interfaces. In this case some interface primitives
+ -- may have been overriden with the partial-view and, instead of
+ -- re-calculating them, they are included in the list of primitive
+ -- operations of the full-view.
+
function Inherit_Components
(N : Node_Id;
Parent_Base : Entity_Id;
@@ -485,6 +508,12 @@ package body Sem_Ch3 is
-- the appropriate semantic fields. If the full view of the parent is
-- a record type, build constrained components of subtype.
+ procedure Derive_Interface_Subprograms
+ (Derived_Type : Entity_Id);
+ -- Ada 2005 (AI-251): Subsidiary procedure to Build_Derived_Record_Type.
+ -- Traverse the list of implemented interfaces and derive all their
+ -- subprograms.
+
procedure Derived_Standard_Character
(N : Node_Id;
Parent_Type : Entity_Id;
@@ -503,10 +532,6 @@ package body Sem_Ch3 is
-- defined in the N_Full_Type_Declaration node N, that is T is the
-- derived type.
- function Find_Type_Of_Subtype_Indic (S : Node_Id) return Entity_Id;
- -- Given a subtype indication S (which is really an N_Subtype_Indication
- -- node or a plain N_Identifier), find the type of the subtype mark.
-
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
@@ -677,6 +702,21 @@ package body Sem_Ch3 is
Error_Msg_N ("task entries cannot have access parameters", N);
end if;
+ -- Ada 2005: for an object declaration, the corresponding anonymous
+ -- type is declared in the current scope. For access formals, access
+ -- components, and access discriminants, the scope is that of the
+ -- enclosing declaration, as set above.
+
+ if Nkind (Related_Nod) = N_Object_Declaration then
+ Set_Scope (Anon_Type, Current_Scope);
+ end if;
+
+ if All_Present (N)
+ and then Ada_Version >= Ada_05
+ then
+ Error_Msg_N ("ALL is 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
@@ -731,13 +771,13 @@ package body Sem_Ch3 is
Set_Is_Access_Constant (Anon_Type, Constant_Present (N));
- -- The context is either a subprogram 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,
- -- it is not a primitive operation of the type (which is declared
- -- elsewhere in some other scope).
+ -- 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_With_Type (Desig_Type)
@@ -763,8 +803,42 @@ package body Sem_Ch3 is
Desig_Type : constant Entity_Id :=
Create_Itype (E_Subprogram_Type, Parent (T_Def));
+ D_Ityp : Node_Id := Associated_Node_For_Itype (Desig_Type);
begin
+ -- Associate the Itype node with the inner full-type declaration
+ -- or subprogram spec. This is required to handle nested anonymous
+ -- declarations. For example:
+
+ -- procedure P
+ -- (X : access procedure
+ -- (Y : access procedure
+ -- (Z : access T)))
+
+ while Nkind (D_Ityp) /= N_Full_Type_Declaration
+ and then Nkind (D_Ityp) /= N_Procedure_Specification
+ and then Nkind (D_Ityp) /= N_Function_Specification
+ and then Nkind (D_Ityp) /= N_Object_Renaming_Declaration
+ and then Nkind (D_Ityp) /= N_Formal_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) = N_Procedure_Specification
+ or else Nkind (D_Ityp) = N_Function_Specification
+ then
+ Set_Scope (Desig_Type, Scope (Defining_Unit_Name (D_Ityp)));
+
+ elsif Nkind (D_Ityp) = N_Full_Type_Declaration
+ or else Nkind (D_Ityp) = N_Object_Renaming_Declaration
+ or else Nkind (D_Ityp) = 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
Analyze (Subtype_Mark (T_Def));
Set_Etype (Desig_Type, Entity (Subtype_Mark (T_Def)));
@@ -940,6 +1014,143 @@ package body Sem_Ch3 is
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);
+ Elmt : Elmt_Id;
+ Ext : Node_Id;
+ L : List_Id;
+ Last_Tag : Node_Id;
+ Comp : Node_Id;
+
+ procedure Add_Tag (Iface : Entity_Id);
+ -- Comment required ???
+
+ -------------
+ -- Add_Tag --
+ -------------
+
+ procedure Add_Tag (Iface : Entity_Id) is
+ Def : Node_Id;
+ Tag : Entity_Id;
+ Decl : Node_Id;
+
+ begin
+ pragma Assert (Is_Tagged_Type (Iface)
+ and then Is_Interface (Iface));
+
+ Def :=
+ Make_Component_Definition (Loc,
+ Aliased_Present => True,
+ Subtype_Indication =>
+ New_Occurrence_Of (RTE (RE_Interface_Tag), Loc));
+
+ Tag := Make_Defining_Identifier (Loc, New_Internal_Name ('V'));
+
+ Decl :=
+ Make_Component_Declaration (Loc,
+ Defining_Identifier => Tag,
+ Component_Definition => Def);
+
+ Analyze_Component_Declaration (Decl);
+
+ Set_Analyzed (Decl);
+ Set_Ekind (Tag, E_Component);
+ Set_Is_Limited_Record (Tag);
+ Set_Is_Tag (Tag);
+ Init_Component_Location (Tag);
+
+ pragma Assert (Is_Frozen (Iface));
+
+ Set_DT_Entry_Count (Tag,
+ DT_Entry_Count (First_Entity (Iface)));
+
+ if not Present (Last_Tag) then
+ Prepend (Decl, L);
+ else
+ Insert_After (Last_Tag, Decl);
+ end if;
+
+ Last_Tag := Decl;
+ end Add_Tag;
+
+ -- Start of procesing for Add_Interface_Tag_Components
+
+ begin
+ if Ekind (Typ) /= E_Record_Type
+ or else not Present (Abstract_Interfaces (Typ))
+ or else Is_Empty_Elmt_List (Abstract_Interfaces (Typ))
+ then
+ return;
+ end if;
+
+ if Present (Abstract_Interfaces (Typ)) then
+
+ -- 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 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.
+
+ pragma Assert (Present
+ (First_Elmt (Abstract_Interfaces (Typ))));
+
+ Elmt := First_Elmt (Abstract_Interfaces (Typ));
+ while Present (Elmt) loop
+ Add_Tag (Node (Elmt));
+ Next_Elmt (Elmt);
+ end loop;
+ end if;
+ end Add_Interface_Tag_Components;
+
-----------------------------------
-- Analyze_Component_Declaration --
-----------------------------------
@@ -1023,12 +1234,7 @@ package body Sem_Ch3 is
T := Access_Definition
(Related_Nod => N,
N => Access_Definition (Component_Definition (N)));
-
- -- 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 (T, Current_Scope); -- Ada 2005 (AI-230)
+ Set_Is_Local_Anonymous_Access (T);
-- Ada 2005 (AI-254)
@@ -1044,10 +1250,10 @@ package body Sem_Ch3 is
-- If the subtype is a constrained subtype of the enclosing record,
-- (which must have a partial view) the back-end does not handle
- -- properly 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.
+ -- properly 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)))
@@ -1127,9 +1333,8 @@ package body Sem_Ch3 is
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.
+ -- 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);
@@ -1742,7 +1947,13 @@ package body Sem_Ch3 is
-- Protected objects with interrupt handlers must be at library level
- if Has_Interrupt_Handler (T) then
+ -- Ada 2005: this test is not needed (and the corresponding clause
+ -- in the RM is removed) because accessibility checks are sufficient
+ -- to make handlers not at the library level illegal.
+
+ if Has_Interrupt_Handler (T)
+ and then Ada_Version < Ada_05
+ then
Error_Msg_N
("interrupt object can only be declared at library level", Id);
end if;
@@ -2265,6 +2476,26 @@ package body Sem_Ch3 is
Parent_Base : Entity_Id;
begin
+ -- Ada 2005 (AI-251): Decorate all the names in the list of ancestor
+ -- interfaces
+
+ if Is_Non_Empty_List (Interface_List (N)) then
+ declare
+ I : Node_Id := First (Interface_List (N));
+ T : Entity_Id;
+ begin
+ while Present (I) loop
+ T := Find_Type_Of_Subtype_Indic (I);
+
+ if not Is_Interface (T) then
+ Error_Msg_NE ("(Ada 2005) & must be an interface", I, T);
+ end if;
+
+ Next (I);
+ end loop;
+ end;
+ end if;
+
Generate_Definition (T);
Enter_Name (T);
@@ -3065,6 +3296,7 @@ package body Sem_Ch3 is
Element_Type := Access_Definition
(Related_Nod => Related_Id,
N => Access_Definition (Component_Def));
+ Set_Is_Local_Anonymous_Access (Element_Type);
-- Ada 2005 (AI-230): In case of components that are anonymous
-- access types the level of accessibility depends on the enclosing
@@ -3218,7 +3450,7 @@ package body Sem_Ch3 is
elsif Is_Abstract (Element_Type) then
Error_Msg_N
- ("The type of a component cannot be abstract",
+ ("the type of a component cannot be abstract",
Subtype_Indication (Component_Def));
end if;
@@ -4931,15 +5163,15 @@ package body Sem_Ch3 is
Last_Discrim : Entity_Id;
Constrs : Elist_Id;
- Discs : Elist_Id := New_Elmt_List;
+ 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.
- Assoc_List : Elist_Id;
- New_Discrs : Elist_Id;
- New_Base : Entity_Id;
- New_Decl : Node_Id;
- New_Indic : Node_Id;
+ Assoc_List : Elist_Id;
+ New_Discrs : Elist_Id;
+ New_Base : Entity_Id;
+ New_Decl : Node_Id;
+ New_Indic : Node_Id;
Is_Tagged : constant Boolean := Is_Tagged_Type (Parent_Type);
Discriminant_Specs : constant Boolean :=
@@ -4947,12 +5179,14 @@ package body Sem_Ch3 is
Private_Extension : constant Boolean :=
(Nkind (N) = N_Private_Extension_Declaration);
- Constraint_Present : Boolean;
- Inherit_Discrims : Boolean := False;
-
- Save_Etype : Entity_Id;
- Save_Discr_Constr : Elist_Id;
- Save_Next_Entity : Entity_Id;
+ Constraint_Present : Boolean;
+ Has_Interfaces : Boolean := False;
+ Inherit_Discrims : Boolean := False;
+ Last_Inherited_Prim_Op : Elmt_Id;
+ Tagged_Partial_View : Entity_Id;
+ Save_Etype : Entity_Id;
+ Save_Discr_Constr : Elist_Id;
+ Save_Next_Entity : Entity_Id;
begin
if Ekind (Parent_Type) = E_Record_Type_With_Private
@@ -5193,7 +5427,54 @@ package body Sem_Ch3 is
Freeze_Before (N, Parent_Type);
end if;
- if Type_Access_Level (Derived_Type) /= Type_Access_Level (Parent_Type)
+ -- 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.
+
+ if Ada_Version >= Ada_05 then
+ if Present (Enclosing_Generic_Body (Derived_Type)) then
+ declare
+ Ancestor_Type : Entity_Id := Parent_Type;
+
+ begin
+ -- Check to see if any ancestor of the derived type is a
+ -- formal type.
+
+ while not Is_Generic_Type (Ancestor_Type)
+ and then Etype (Ancestor_Type) /= Ancestor_Type
+ loop
+ Ancestor_Type := Etype (Ancestor_Type);
+ end loop;
+
+ -- 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 guaranteed 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
+ ("parent type of& must not be descendant of formal type"
+ & " of an enclosing generic body",
+ Indic, Derived_Type);
+ end if;
+ end;
+ end if;
+
+ 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
@@ -5223,6 +5504,29 @@ package body Sem_Ch3 is
end if;
end if;
+ -- Ada 2005 (AI-251)
+
+ if Ada_Version = Ada_05
+ 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
+ if Is_Non_Empty_List (Interface_List (Type_Def)) then
+ Iface := First (Interface_List (Type_Def));
+
+ while Present (Iface) loop
+ Freeze_Before (N, Etype (Iface));
+ Next (Iface);
+ end loop;
+ end if;
+ 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
@@ -5424,6 +5728,17 @@ package body Sem_Ch3 is
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
+ Set_Is_Interface (Derived_Type, Interface_Present (Type_Def));
+ Set_Abstract_Interfaces (Derived_Type, No_Elist);
+ end if;
+
-- Fields inherited from the Parent_Type
Set_Discard_Names
@@ -5507,6 +5822,143 @@ package body Sem_Ch3 is
(Derived_Type, Expand_To_Stored_Constraint (Parent_Base, Discs));
end if;
+ -- Ada 2005 (AI-251): Look for the partial view of tagged types
+ -- declared in the private part. This will be used 1) to check that
+ -- the set of interfaces in both views is equal, and 2) to complete
+ -- the derivation of subprograms covering interfaces.
+
+ Tagged_Partial_View := Empty;
+
+ if Has_Private_Declaration (Derived_Type) then
+ Tagged_Partial_View := Next_Entity (Derived_Type);
+ loop
+ exit when Has_Private_Declaration (Tagged_Partial_View)
+ and then Full_View (Tagged_Partial_View) = Derived_Type;
+
+ Next_Entity (Tagged_Partial_View);
+ end loop;
+ end if;
+
+ -- Ada 2005 (AI-251): Collect the whole list of implemented
+ -- interfaces.
+
+ if Ada_Version >= Ada_05 then
+ Set_Abstract_Interfaces (Derived_Type, New_Elmt_List);
+
+ if Nkind (N) = N_Private_Extension_Declaration then
+ Collect_Interfaces (N, Derived_Type);
+ else
+ Collect_Interfaces (Type_Definition (N), Derived_Type);
+ end if;
+
+ -- Check that the full view and the partial view agree
+ -- in the set of implemented interfaces
+
+ if Has_Private_Declaration (Derived_Type)
+ and then Present (Abstract_Interfaces (Derived_Type))
+ and then not Is_Empty_Elmt_List
+ (Abstract_Interfaces (Derived_Type))
+ then
+ declare
+ N_Partial : constant Node_Id := Parent (Tagged_Partial_View);
+ N_Full : constant Node_Id := Parent (Derived_Type);
+
+ Iface_Partial : Entity_Id;
+ Iface_Full : Entity_Id;
+ Num_Ifaces_Partial : Natural := 0;
+ Num_Ifaces_Full : Natural := 0;
+ Same_Interfaces : Boolean := True;
+
+ begin
+ -- Count the interfaces implemented by the partial view
+
+ if not Is_Empty_List (Interface_List (N_Partial)) then
+ Iface_Partial := First (Interface_List (N_Partial));
+
+ while Present (Iface_Partial) loop
+ Num_Ifaces_Partial := Num_Ifaces_Partial + 1;
+ Next (Iface_Partial);
+ end loop;
+ end if;
+
+ -- Take into account the case in which the partial
+ -- view is a directly derived from an interface
+
+ if Is_Interface (Etype
+ (Defining_Identifier (N_Partial)))
+ then
+ Num_Ifaces_Partial := Num_Ifaces_Partial + 1;
+ end if;
+
+ -- Count the interfaces implemented by the full view
+
+ if not Is_Empty_List (Interface_List
+ (Type_Definition (N_Full)))
+ then
+ Iface_Full := First (Interface_List
+ (Type_Definition (N_Full)));
+
+ while Present (Iface_Full) loop
+ Num_Ifaces_Full := Num_Ifaces_Full + 1;
+ Next (Iface_Full);
+ end loop;
+ end if;
+
+ -- Take into account the case in which the full
+ -- view is a directly derived from an interface
+
+ if Is_Interface (Etype
+ (Defining_Identifier (N_Full)))
+ then
+ Num_Ifaces_Full := Num_Ifaces_Full + 1;
+ end if;
+
+ if Num_Ifaces_Full > 0
+ and then Num_Ifaces_Full = Num_Ifaces_Partial
+ then
+
+ -- Check that the full-view and the private-view have
+ -- the same list of interfaces
+
+ Iface_Full := First (Interface_List
+ (Type_Definition (N_Full)));
+
+ while Present (Iface_Full) loop
+ Iface_Partial := First (Interface_List (N_Partial));
+
+ while Present (Iface_Partial)
+ and then Etype (Iface_Partial) /= Etype (Iface_Full)
+ loop
+ Next (Iface_Partial);
+ end loop;
+
+ -- If not found we check if the partial view is a
+ -- direct derivation of the interface.
+
+ if not Present (Iface_Partial)
+ and then
+ Etype (Tagged_Partial_View) /= Etype (Iface_Full)
+ then
+ Same_Interfaces := False;
+ exit;
+ end if;
+
+ Next (Iface_Full);
+ end loop;
+ end if;
+
+ if Num_Ifaces_Partial /= Num_Ifaces_Full
+ or else not Same_Interfaces
+ then
+ Error_Msg_N
+ ("(Ada 2005) full declaration and private declaration"
+ & " must have the same list of interfaces",
+ Derived_Type);
+ end if;
+ end;
+ end if;
+ end if;
+
else
Set_Is_Packed (Derived_Type, Is_Packed (Parent_Base));
Set_Has_Non_Standard_Rep
@@ -5596,6 +6048,13 @@ package body Sem_Ch3 is
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 then
+ Add_Interface_Tag_Components (N, Derived_Type);
+ end if;
+
-- Analyze the record extension
Record_Type_Definition
@@ -5613,8 +6072,140 @@ package body Sem_Ch3 is
-- derived freeze if necessary.
Set_Has_Delayed_Freeze (Derived_Type);
+
if Derive_Subps then
Derive_Subprograms (Parent_Type, Derived_Type);
+
+ -- Ada 2005 (AI-251): Check if this tagged type implements abstract
+ -- interfaces
+
+ Has_Interfaces := False;
+
+ if Is_Tagged_Type (Derived_Type) then
+ declare
+ E : Entity_Id;
+
+ begin
+ E := Derived_Type;
+ loop
+ if Is_Interface (E)
+ or else (Present (Abstract_Interfaces (E))
+ and then
+ not Is_Empty_Elmt_List (Abstract_Interfaces (E)))
+ then
+ Has_Interfaces := True;
+ exit;
+ end if;
+
+ exit when Etype (E) = E
+
+ -- Protect the frontend against wrong source
+
+ or else Etype (E) = Derived_Type;
+
+ E := Etype (E);
+ end loop;
+ end;
+ end if;
+
+ -- Ada 2005 (AI-251): Keep separate the management of tagged types
+ -- implementing interfaces
+
+ if Is_Tagged_Type (Derived_Type)
+ and then Has_Interfaces
+ then
+ -- Complete the decoration of private tagged types
+
+ if Present (Tagged_Partial_View) then
+ Complete_Subprograms_Derivation
+ (Partial_View => Tagged_Partial_View,
+ Derived_Type => Derived_Type);
+ end if;
+
+ -- Ada 2005 (AI-251): Derive the interface subprograms of all the
+ -- implemented interfaces and check if some of the subprograms
+ -- inherited from the ancestor cover some interface subprogram.
+
+ if not Present (Tagged_Partial_View) then
+ declare
+ Subp_Elmt : Elmt_Id := First_Elmt
+ (Primitive_Operations
+ (Derived_Type));
+ Iface_Subp_Elmt : Elmt_Id;
+ Subp : Entity_Id;
+ Iface_Subp : Entity_Id;
+ Is_Interface_Subp : Boolean;
+
+ begin
+ -- Ada 2005 (AI-251): Remember the entity corresponding to
+ -- the last inherited primitive operation. This is required
+ -- to check if some of the inherited subprograms covers some
+ -- of the new interfaces.
+
+ Last_Inherited_Prim_Op := No_Elmt;
+
+ while Present (Subp_Elmt) loop
+ Last_Inherited_Prim_Op := Subp_Elmt;
+ Next_Elmt (Subp_Elmt);
+ end loop;
+
+ -- Ada 2005 (AI-251): Derive subprograms in abstract
+ -- interfaces
+
+ Derive_Interface_Subprograms (Derived_Type);
+
+ -- Ada 2005 (AI-251): Check if some of the inherited
+ -- subprograms cover some of the new interfaces.
+
+ if Present (Last_Inherited_Prim_Op) then
+ Iface_Subp_Elmt := Next_Elmt (Last_Inherited_Prim_Op);
+ while Present (Iface_Subp_Elmt) loop
+ Subp_Elmt := First_Elmt (Primitive_Operations
+ (Derived_Type));
+ while Subp_Elmt /= Last_Inherited_Prim_Op loop
+ Subp := Node (Subp_Elmt);
+ Iface_Subp := Node (Iface_Subp_Elmt);
+
+ Is_Interface_Subp :=
+ Present (Alias (Subp))
+ and then Present (DTC_Entity (Alias (Subp)))
+ and then Is_Interface (Scope
+ (DTC_Entity
+ (Alias (Subp))));
+
+ if Chars (Subp) = Chars (Iface_Subp)
+ and then not Is_Interface_Subp
+ and then not Is_Abstract (Subp)
+ and then Type_Conformant (Iface_Subp, Subp)
+ then
+ Check_Dispatching_Operation
+ (Subp => Subp,
+ Old_Subp => Iface_Subp);
+
+ -- Traverse the list of aliased subprograms
+
+ declare
+ E : Entity_Id := Alias (Subp);
+ begin
+ while Present (Alias (E)) loop
+ E := Alias (E);
+ end loop;
+ Set_Alias (Subp, E);
+ end;
+
+ Set_Has_Delayed_Freeze (Subp);
+ exit;
+ end if;
+
+ Next_Elmt (Subp_Elmt);
+ end loop;
+
+ Next_Elmt (Iface_Subp_Elmt);
+ end loop;
+ end if;
+ end;
+ end if;
+ end if;
end if;
-- If we have a private extension which defines a constrained derived
@@ -6424,6 +7015,16 @@ package body Sem_Ch3 is
Error_Msg_NE
("type must be declared abstract or & overridden",
T, Subp);
+
+ -- Ada 2005 (AI-345): Protected or task type implementing
+ -- abstract interfaces
+
+ elsif Is_Concurrent_Record_Type (T)
+ and then Present (Abstract_Interfaces (T))
+ then
+ Error_Msg_NE
+ ("interface subprogram & must be overridden",
+ T, Subp);
end if;
else
Error_Msg_NE
@@ -6475,6 +7076,11 @@ package body Sem_Ch3 is
-- ??? 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);
@@ -6483,6 +7089,7 @@ package body Sem_Ch3 is
and then Has_Discriminants (Etype (C))
and then not Is_Constrained (Etype (C))
and then not In_Instance
+ and then Ada_Version < Ada_05
then
Error_Msg_N
("aliased component must be constrained ('R'M 3.6(11))",
@@ -6880,6 +7487,67 @@ package body Sem_Ch3 is
Resolve (Bound, Standard_Float);
end Check_Real_Bound;
+ ------------------------
+ -- Collect_Interfaces --
+ ------------------------
+
+ procedure Collect_Interfaces (N : Node_Id; Derived_Type : Entity_Id) is
+ I : Node_Id;
+
+ procedure Add_Interface (Iface : Entity_Id);
+
+ procedure Add_Interface (Iface : Entity_Id) is
+ Elmt : Elmt_Id := First_Elmt (Abstract_Interfaces (Derived_Type));
+
+ begin
+ while Present (Elmt) and then Node (Elmt) /= Iface loop
+ Next_Elmt (Elmt);
+ end loop;
+
+ if not Present (Elmt) then
+ Append_Elmt (Node => Iface,
+ To => Abstract_Interfaces (Derived_Type));
+ end if;
+ end Add_Interface;
+
+ begin
+ pragma Assert (False
+ or else Nkind (N) = N_Derived_Type_Definition
+ or else Nkind (N) = N_Record_Definition
+ or else Nkind (N) = N_Private_Extension_Declaration);
+
+ -- Traverse the graph of ancestor interfaces
+
+ if Is_Non_Empty_List (Interface_List (N)) then
+ I := First (Interface_List (N));
+
+ while Present (I) loop
+
+ -- Protect against wrong usages. Example:
+ -- type I is interface;
+ -- type O is tagged null record;
+ -- type Wrong is new I and O with null record;
+
+ if Is_Interface (Etype (I)) then
+
+ -- Do not add the interface when the derived type already
+ -- implements this interface
+
+ if not Interface_Present_In_Ancestor (Derived_Type,
+ Etype (I))
+ then
+ Collect_Interfaces
+ (Type_Definition (Parent (Etype (I))),
+ Derived_Type);
+ Add_Interface (Etype (I));
+ end if;
+ end if;
+
+ Next (I);
+ end loop;
+ end if;
+ end Collect_Interfaces;
+
------------------------------
-- Complete_Private_Subtype --
------------------------------
@@ -7091,6 +7759,77 @@ package body Sem_Ch3 is
end if;
end Complete_Private_Subtype;
+ -------------------------------------
+ -- Complete_Subprograms_Derivation --
+ -------------------------------------
+
+ procedure Complete_Subprograms_Derivation
+ (Partial_View : Entity_Id;
+ Derived_Type : Entity_Id)
+ is
+ Result : constant Elist_Id := New_Elmt_List;
+ Elmt_P : Elmt_Id := No_Elmt;
+ Elmt_D : Elmt_Id;
+ Found : Boolean;
+ Prim_Op : Entity_Id;
+ E : Entity_Id;
+
+ begin
+ if Is_Tagged_Type (Partial_View) then
+ Elmt_P := First_Elmt (Primitive_Operations (Partial_View));
+ end if;
+
+ -- Inherit primitives declared with the partial-view
+
+ while Present (Elmt_P) loop
+ Prim_Op := Node (Elmt_P);
+ Found := False;
+ Elmt_D := First_Elmt (Primitive_Operations (Derived_Type));
+ while Present (Elmt_D) loop
+ if Node (Elmt_D) = Prim_Op then
+ Found := True;
+ exit;
+ end if;
+
+ Next_Elmt (Elmt_D);
+ end loop;
+
+ if not Found then
+ Append_Elmt (Prim_Op, Result);
+
+ -- Search for entries associated with abstract interfaces that
+ -- have been covered by this primitive
+
+ Elmt_D := First_Elmt (Primitive_Operations (Derived_Type));
+ while Present (Elmt_D) loop
+ E := Node (Elmt_D);
+
+ if Chars (E) = Chars (Prim_Op)
+ and then Is_Abstract (E)
+ and then Present (Alias (E))
+ and then Present (DTC_Entity (Alias (E)))
+ and then Is_Interface (Scope (DTC_Entity (Alias (E))))
+ then
+ Remove_Elmt (Primitive_Operations (Derived_Type), Elmt_D);
+ end if;
+
+ Next_Elmt (Elmt_D);
+ end loop;
+ end if;
+
+ Next_Elmt (Elmt_P);
+ end loop;
+
+ -- Append the entities of the full-view to the list of primitives
+ -- of derived_type
+
+ Elmt_D := First_Elmt (Result);
+ while Present (Elmt_D) loop
+ Append_Elmt (Node (Elmt_D), Primitive_Operations (Derived_Type));
+ Next_Elmt (Elmt_D);
+ end loop;
+ end Complete_Subprograms_Derivation;
+
----------------------------
-- Constant_Redeclaration --
----------------------------
@@ -7190,9 +7929,18 @@ package body Sem_Ch3 is
then
Enter_Name (Id);
- -- Verify that types of both declarations match
+ -- 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) then
+ 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 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);
@@ -7257,6 +8005,24 @@ package body Sem_Ch3 is
Desig_Subtype : Entity_Id := Create_Itype (E_Void, Related_Nod);
Constraint_OK : Boolean := True;
+ function Has_Defaulted_Discriminants (Typ : Entity_Id) return Boolean;
+ -- Simple predicate to test for defaulted discriminants
+ -- Shouldn't this be in sem_util???
+
+ ---------------------------------
+ -- Has_Defaulted_Discriminants --
+ ---------------------------------
+
+ function Has_Defaulted_Discriminants (Typ : Entity_Id) return Boolean is
+ begin
+ return Has_Discriminants (Typ)
+ and then Present (First_Discriminant (Typ))
+ and then Present
+ (Discriminant_Default_Value (First_Discriminant (Typ)));
+ end Has_Defaulted_Discriminants;
+
+ -- Start of processing for Constrain_Access
+
begin
if Is_Array_Type (Desig_Type) then
Constrain_Array (Desig_Subtype, S, Related_Nod, Def_Id, 'P');
@@ -7296,6 +8062,9 @@ package body Sem_Ch3 is
-- 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.
declare
Pack : constant Node_Id :=
@@ -7324,8 +8093,9 @@ package body Sem_Ch3 is
then
if No (Discriminant_Specifications (Decl)) then
Error_Msg_N
- ("cannot constrain general access type " &
- "if designated type has unconstrained view", S);
+ ("cannot constrain general access type if " &
+ "designated type has constrained partial view",
+ S);
end if;
exit;
@@ -7376,6 +8146,31 @@ package body Sem_Ch3 is
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_05 then
+ if Ekind (Base_Type (T)) = E_General_Access_Type
+ and then Has_Defaulted_Discriminants (Desig_Type)
+ then
+ Error_Msg_N
+ ("access subype of general access type not allowed", S);
+ Error_Msg_N ("\ when 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
+ Error_Msg_N ("access subtype not allowed in generic body", S);
+ Error_Msg_N
+ ("\ wben designated type is a discriminated formal", S);
+ end if;
+ end if;
end Constrain_Access;
---------------------
@@ -7461,6 +8256,8 @@ package body Sem_Ch3 is
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, True);
@@ -9047,6 +9844,58 @@ package body Sem_Ch3 is
Set_Is_Constrained (T);
end Decimal_Fixed_Point_Type_Declaration;
+ ---------------------------------
+ -- Derive_Interface_Subprogram --
+ ---------------------------------
+
+ procedure Derive_Interface_Subprograms (Derived_Type : Entity_Id) is
+
+ procedure Do_Derivation (T : Entity_Id);
+ -- This inner subprograms is used to climb to the ancestors.
+ -- It is needed to add the derivations to the Derived_Type.
+
+ procedure Do_Derivation (T : Entity_Id) is
+ Etyp : constant Entity_Id := Etype (T);
+ AI : Elmt_Id;
+
+ begin
+ if Etyp /= T
+ and then Is_Interface (Etyp)
+ then
+ Do_Derivation (Etyp);
+ end if;
+
+ if Present (Abstract_Interfaces (T))
+ and then not Is_Empty_Elmt_List (Abstract_Interfaces (T))
+ then
+ AI := First_Elmt (Abstract_Interfaces (T));
+
+ while Present (AI) loop
+ Derive_Subprograms
+ (Parent_Type => Node (AI),
+ Derived_Type => Derived_Type,
+ Is_Interface_Derivation => True);
+
+ Next_Elmt (AI);
+ end loop;
+ end if;
+ end Do_Derivation;
+
+ begin
+ Do_Derivation (Derived_Type);
+
+ -- At this point the list of primitive operations of Derived_Type
+ -- contains the entities corresponding to all the subprograms of all the
+ -- implemented interfaces. If N interfaces have subprograms with the
+ -- same profile we have N entities in this list because each one must be
+ -- allocated in its corresponding virtual table.
+
+ -- Its alias attribute references its original interface subprogram.
+ -- When overriden, the alias attribute is later saved in the
+ -- Abstract_Interface_Alias attribute.
+
+ end Derive_Interface_Subprograms;
+
-----------------------
-- Derive_Subprogram --
-----------------------
@@ -9430,9 +10279,10 @@ package body Sem_Ch3 is
------------------------
procedure Derive_Subprograms
- (Parent_Type : Entity_Id;
- Derived_Type : Entity_Id;
- Generic_Actual : Entity_Id := Empty)
+ (Parent_Type : Entity_Id;
+ Derived_Type : Entity_Id;
+ Generic_Actual : Entity_Id := Empty;
+ Is_Interface_Derivation : Boolean := False)
is
Op_List : constant Elist_Id :=
Collect_Primitive_Operations (Parent_Type);
@@ -9468,7 +10318,13 @@ package body Sem_Ch3 is
Subp := Node (Elmt);
if Ekind (Subp) /= E_Enumeration_Literal then
- if No (Generic_Actual) then
+ if Is_Interface_Derivation then
+ if not Is_Predefined_Dispatching_Operation (Subp) then
+ Derive_Subprogram
+ (New_Subp, Subp, Derived_Type, Parent_Base);
+ end if;
+
+ elsif No (Generic_Actual) then
Derive_Subprogram
(New_Subp, Subp, Derived_Type, Parent_Base);
@@ -9567,6 +10423,7 @@ package body Sem_Ch3 is
Is_Completion : Boolean)
is
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_Type : Entity_Id;
@@ -9608,6 +10465,92 @@ package body Sem_Ch3 is
begin
Parent_Type := Find_Type_Of_Subtype_Indic (Indic);
+ -- 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
+ Error_Msg_NE ("(Ada 2005) & must be an interface",
+ Indic, Parent_Type);
+
+ else
+ Iface_Def := Type_Definition (Parent (Parent_Type));
+
+ -- 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_N ("(Ada 2005) limited interface cannot" &
+ " inherit from protected interface", Indic);
+
+ elsif Synchronized_Present (Iface_Def) then
+ Error_Msg_N ("(Ada 2005) limited interface cannot" &
+ " inherit from synchronized interface", Indic);
+
+ elsif Task_Present (Iface_Def) then
+ Error_Msg_N ("(Ada 2005) limited interface cannot" &
+ " inherit from task interface", Indic);
+
+ 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_N ("(Ada 2005) non-limited interface cannot" &
+ " inherit from protected interface", Indic);
+
+ elsif Synchronized_Present (Iface_Def) then
+ Error_Msg_N ("(Ada 2005) non-limited interface cannot" &
+ " inherit from synchronized interface", Indic);
+
+ elsif Task_Present (Iface_Def) then
+ Error_Msg_N ("(Ada 2005) non-limited interface cannot" &
+ " inherit from task interface", Indic);
+
+ else
+ null;
+ end if;
+ end if;
+ end if;
+ 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
+ I : Node_Id := First (Interface_List (Def));
+ T : Entity_Id;
+ begin
+ while Present (I) loop
+ T := Find_Type_Of_Subtype_Indic (I);
+
+ if not Is_Interface (T) then
+ Error_Msg_NE ("(Ada 2005) & must be an interface", I, T);
+ end if;
+
+ Next (I);
+ end loop;
+ end;
+ end if;
+
if Parent_Type = Any_Type
or else Etype (Parent_Type) = Any_Type
or else (Is_Class_Wide_Type (Parent_Type)
@@ -10009,6 +10952,14 @@ package body Sem_Ch3 is
("completion of nonlimited type cannot be limited", N);
end if;
+ -- Ada 2005 (AI-251): Private extension declaration of a
+ -- task type. This case arises with tasks implementing interfaces
+
+ elsif Nkind (N) = N_Task_Type_Declaration
+ or else Nkind (N) = N_Protected_Type_Declaration
+ then
+ null;
+
elsif Nkind (N) /= N_Full_Type_Declaration
or else Nkind (Type_Definition (N)) /= N_Derived_Type_Definition
then
@@ -10078,6 +11029,8 @@ package body Sem_Ch3 is
if Is_Type (Prev)
and then (Is_Tagged_Type (Prev)
or else Present (Class_Wide_Type (Prev)))
+ and then (Nkind (N) /= N_Task_Type_Declaration
+ and then Nkind (N) /= N_Protected_Type_Declaration)
then
-- The full declaration is either a tagged record or an
-- extension otherwise this is an error
@@ -10183,11 +11136,19 @@ package body Sem_Ch3 is
and then No (Expression (P))
then
null;
-
else
Insert_Actions (Obj_Def, Freeze_Entity (T, Sloc (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);
+
+ -- comment here, what cases ???
+
else
T := Process_Subtype (Obj_Def, Related_Nod);
end if;
@@ -10850,7 +11811,17 @@ package body Sem_Ch3 is
Component := First_Entity (Parent_Base);
while Present (Component) loop
- if Ekind (Component) /= E_Component
+
+ -- Ada 2005 (AI-251): Do not inherit tags corresponding with the
+ -- interfaces of the parent
+
+ if Ekind (Component) = E_Component
+ and then Is_Tag (Component)
+ and then Etype (Component) = RTE (RE_Interface_Tag)
+ then
+ null;
+
+ elsif Ekind (Component) /= E_Component
or else Chars (Component) = Name_uParent
then
null;
@@ -11812,6 +12783,18 @@ package body Sem_Ch3 is
if Nkind (Discriminant_Type (Discr)) = N_Access_Definition then
Discr_Type := Access_Definition (N, Discriminant_Type (Discr));
+ -- Ada 2005 (AI-230): Access discriminants are now allowed for
+ -- nonlimited types, and are treated like other components of
+ -- anonymous access types in terms of accessibility.
+
+ if not Is_Concurrent_Type (Current_Scope)
+ and then not Is_Concurrent_Record_Type (Current_Scope)
+ and then not Is_Limited_Record (Current_Scope)
+ and then Ekind (Current_Scope) /= E_Limited_Private_Type
+ then
+ Set_Is_Local_Anonymous_Access (Discr_Type);
+ end if;
+
-- Ada 2005 (AI-254)
if Present (Access_To_Subprogram_Definition
@@ -11981,6 +12964,34 @@ package body Sem_Ch3 is
Full_Parent : Entity_Id;
Full_Indic : Node_Id;
+ function Find_Interface_In_Descendant
+ (Typ : Entity_Id) return Entity_Id;
+ -- Find an implemented interface in the derivation chain of Typ
+
+ ----------------------------------
+ -- Find_Interface_In_Descendant --
+ ----------------------------------
+
+ function Find_Interface_In_Descendant
+ (Typ : Entity_Id) return Entity_Id
+ is
+ T : Entity_Id;
+
+ begin
+ T := Typ;
+ while T /= Etype (T) loop
+ if Is_Interface (Etype (T)) then
+ return Etype (T);
+ end if;
+
+ T := Etype (T);
+ end loop;
+
+ return Empty;
+ end Find_Interface_In_Descendant;
+
+ -- Start of processing for Process_Full_View
+
begin
-- First some sanity checks that must be done after semantic
-- decoration of the full view and thus cannot be placed with other
@@ -12017,6 +13028,54 @@ package body Sem_Ch3 is
Error_Msg_N ("generic type cannot have a completion", Full_T);
end if;
+ -- Ada 2005 (AI-396): A full view shall be a descendant of an
+ -- interface type if and only if the corresponding partial view
+ -- (if any) is also a descendant of the interface type, or if
+ -- the partial view is untagged.
+
+ if Ada_Version >= Ada_05
+ and then Is_Tagged_Type (Full_T)
+ then
+ declare
+ Iface : Entity_Id;
+ Iface_Def : Node_Id;
+
+ begin
+ Iface := Find_Interface_In_Descendant (Full_T);
+
+ if Present (Iface) then
+ Iface_Def := Type_Definition (Parent (Iface));
+ end if;
+
+ -- The full view derives from an interface descendant, but the
+ -- partial view does not share the same tagged type.
+
+ if Present (Iface)
+ and then Is_Tagged_Type (Priv_T)
+ and then Etype (Full_T) /= Etype (Priv_T)
+ then
+ Error_Msg_N ("(Ada 2005) tagged partial view cannot be " &
+ "completed by a type that implements an " &
+ "interface", Priv_T);
+ end if;
+
+ -- The full view derives from a limited, protected,
+ -- synchronized or task interface descendant, but the
+ -- partial view is not labeled as limited.
+
+ if Present (Iface)
+ and then (Limited_Present (Iface_Def)
+ or Protected_Present (Iface_Def)
+ or Synchronized_Present (Iface_Def)
+ or Task_Present (Iface_Def))
+ and then not Limited_Present (Parent (Priv_T))
+ then
+ Error_Msg_N ("(Ada 2005) non-limited private type cannot be " &
+ "completed by a limited type", Priv_T);
+ 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)
@@ -12044,9 +13103,24 @@ package body Sem_Ch3 is
return;
elsif 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);
+
+ -- Ada 2005 (AI-251): No error needed if the immediate
+ -- ancestor of the partial view is an interface
+ --
+ -- Example:
+ --
+ -- type PT1 is new I1 with private;
+ -- private
+ -- type PT1 is new T and I1 with null record;
+
+ if Is_Interface (Base_Type (Priv_Parent)) then
+ null;
+
+ else
+ Error_Msg_N
+ ("parent of full type must descend from parent"
+ & " of private extension", Full_Indic);
+ end if;
-- Check the rules of 7.3(10): if the private extension inherits
-- known discriminants, then the full type must also inherit those
@@ -12124,7 +13198,7 @@ package body Sem_Ch3 is
then
Error_Msg_N
("full view must define a constrained type if partial view"
- & " has no discriminants", Full_T);
+ & " has no discriminants", Full_T);
end if;
-- ??????? Do we implement the following properly ?????
@@ -12144,6 +13218,22 @@ package body Sem_Ch3 is
end if;
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_Discriminants (Full_T)
+ and then
+ Present
+ (Discriminant_Default_Value (First_Discriminant (Full_T)))
+ then
+ Set_Has_Constrained_Partial_View (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
@@ -12748,7 +13838,7 @@ package body Sem_Ch3 is
Rewrite (S, New_Copy_Tree (Subtype_Mark (S)));
- -- Set Ekind of orphan itype, to prevent cascaded errors.
+ -- Set Ekind of orphan itype, to prevent cascaded errors
if Present (Def_Id) then
Set_Ekind (Def_Id, Ekind (Any_Type));
@@ -12848,46 +13938,390 @@ package body Sem_Ch3 is
N : Node_Id;
Prev : Entity_Id)
is
- Def : constant Node_Id := Type_Definition (N);
+ Loc : constant Source_Ptr := Sloc (N);
+ Def : constant Node_Id := Type_Definition (N);
+ Inc_T : Entity_Id := Empty;
Is_Tagged : Boolean;
Tag_Comp : Entity_Id;
- begin
- -- 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.
+ procedure Check_Anonymous_Access_Types (Comp_List : Node_Id);
+ -- Ada 2005 AI-382: an access component in a record declaration 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 that accessibility checks are properly performed
+ -- on it. The declaration of the access type is placed ahead of that
+ -- of the record, to prevent circular order-of-elaboration issues in
+ -- gigi. We create an incomplete type for the record declaration, which
+ -- is the designated type of the anonymous access.
+
+ procedure Make_Incomplete_Type_Declaration;
+ -- If the record type contains components that include an access to the
+ -- current record, 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.
- Is_Tagged :=
- Tagged_Present (Def)
- or else (Serious_Errors_Detected > 0 and then Is_Tagged_Type (T));
+ ----------------------------------
+ -- Check_Anonymous_Access_Types --
+ ----------------------------------
- -- 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).
+ procedure Check_Anonymous_Access_Types (Comp_List : Node_Id) is
+ Anon_Access : Entity_Id;
+ Acc_Def : Node_Id;
+ Comp : Node_Id;
+ Decl : Node_Id;
+ Type_Def : Node_Id;
- -- Enter record scope
+ 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, or a 'Class attribute
+ -- reference, or recursively a reference appearing in a parameter
+ -- type in an access_to_subprogram definition.
- New_Scope (T);
+ ----------------
+ -- Mentions_T --
+ ----------------
+
+ function Mentions_T (Acc_Def : Node_Id) return Boolean is
+ Subt : Node_Id;
+
+ begin
+ if No (Access_To_Subprogram_Definition (Acc_Def)) then
+ Subt := Subtype_Mark (Acc_Def);
+
+ if Nkind (Subt) = N_Identifier then
+ return Chars (Subt) = Chars (T);
+ elsif Nkind (Subt) = N_Attribute_Reference
+ and then Attribute_Name (Subt) = Name_Class
+ then
+ return (Chars (Prefix (Subt))) = Chars (T);
+ else
+ return False;
+ end if;
+
+ else
+ -- Component is an access_to_subprogram: examine its formals
+
+ declare
+ Param_Spec : Node_Id;
+
+ begin
+ Param_Spec :=
+ First
+ (Parameter_Specifications
+ (Access_To_Subprogram_Definition (Acc_Def)));
+ 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;
+ end if;
+
+ Next (Param_Spec);
+ end loop;
+
+ return False;
+ end;
+ end if;
+ end Mentions_T;
+
+ -- Start of processing for Check_Anonymous_Access_Types
+
+ 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
+ and then
+ Present (Access_Definition (Component_Definition (Comp)))
+ and then
+ Mentions_T (Access_Definition (Component_Definition (Comp)))
+ then
+ Acc_Def :=
+ Access_To_Subprogram_Definition
+ (Access_Definition (Component_Definition (Comp)));
+
+ Make_Incomplete_Type_Declaration;
+ Anon_Access :=
+ Make_Defining_Identifier (Loc,
+ Chars => New_Internal_Name ('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),
+ Subtype_Mark => Subtype_Mark (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_Definition
+ (Component_Definition (Comp)))));
+ end if;
+
+ Decl := Make_Full_Type_Declaration (Loc,
+ Defining_Identifier => Anon_Access,
+ Type_Definition => Type_Def);
+
+ Insert_Before (N, Decl);
+ Analyze (Decl);
+
+ Set_Access_Definition (Component_Definition (Comp), Empty);
+ Set_Subtype_Indication (Component_Definition (Comp),
+ New_Occurrence_Of (Anon_Access, Loc));
+ Set_Ekind (Anon_Access, E_Anonymous_Access_Type);
+ Set_Is_Local_Anonymous_Access (Anon_Access);
+ 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_Types (Component_List (V));
+ Next_Non_Pragma (V);
+ end loop;
+ end;
+ end if;
+ end Check_Anonymous_Access_Types;
+
+ --------------------------------------
+ -- Make_Incomplete_Type_Declaration --
+ --------------------------------------
+
+ procedure Make_Incomplete_Type_Declaration is
+ Decl : Node_Id;
+ H : Entity_Id;
+
+ begin
+ -- If there is a previous partial view, no need to create a new one.
+
+ if Prev /= T then
+ return;
+
+ elsif No (Inc_T) then
+ Inc_T := Make_Defining_Identifier (Loc, Chars (T));
+ 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.
+
+ H := Current_Entity (T);
+
+ if H = T then
+ Set_Name_Entity_Id (Chars (T), Empty);
+ else
+ while Present (H)
+ and then Homonym (H) /= T
+ loop
+ H := Homonym (T);
+ end loop;
+
+ Set_Homonym (H, Homonym (T));
+ end if;
+
+ Insert_Before (N, Decl);
+ Analyze (Decl);
+ Set_Full_View (Inc_T, T);
+
+ if Tagged_Present (Def) then
+ Make_Class_Wide_Type (Inc_T);
+ Set_Class_Wide_Type (T, Class_Wide_Type (Inc_T));
+ end if;
+ end if;
+ end Make_Incomplete_Type_Declaration;
+
+ -- Start of processing for Record_Type_Declaration
+ begin
-- These flags must be initialized before calling Process_Discriminants
-- because this routine makes use of them.
- Set_Is_Tagged_Type (T, Is_Tagged);
- Set_Is_Limited_Record (T, Limited_Present (Def));
+ Set_Ekind (T, E_Record_Type);
+ Set_Etype (T, T);
+ Init_Size_Align (T);
+ Set_Abstract_Interfaces (T, No_Elist);
+ Set_Stored_Constraint (T, No_Elist);
+
+ -- Normal case
- -- Type is abstract if full declaration carries keyword, or if
- -- previous partial view did.
+ if Ada_Version < Ada_05
+ 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.
- Set_Is_Abstract (T, Is_Abstract (T) or else Abstract_Present (Def));
+ Is_Tagged :=
+ Tagged_Present (Def)
+ or else (Serious_Errors_Detected > 0 and then Is_Tagged_Type (T));
- Set_Ekind (T, E_Record_Type);
- Set_Etype (T, T);
- Init_Size_Align (T);
+ Set_Is_Tagged_Type (T, Is_Tagged);
+ Set_Is_Limited_Record (T, Limited_Present (Def));
- Set_Stored_Constraint (T, No_Elist);
+ -- Type is abstract if full declaration carries keyword, or if
+ -- previous partial view did.
+
+ Set_Is_Abstract (T, Is_Abstract (T)
+ or else Abstract_Present (Def));
+
+ else
+ Is_Tagged := True;
+ Set_Is_Tagged_Type (T);
+
+ Set_Is_Limited_Record (T, Limited_Present (Def)
+ or else Task_Present (Def)
+ or else Protected_Present (Def));
+
+ -- Type is abstract if full declaration carries keyword, or if
+ -- previous partial view did.
+
+ Set_Is_Abstract (T);
+ Set_Is_Interface (T);
+ 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_Types (Component_List (Def));
+
+ -- Ada 2005 (AI-251): Complete the initialization of attributes
+ -- associated with abstract interfaces and decorate the names in the
+ -- list of ancestor interfaces (if any).
+
+ if Ada_Version >= Ada_05
+ and then Present (Interface_List (Def))
+ then
+ declare
+ Iface : Node_Id;
+ Iface_Def : Node_Id;
+ Iface_Typ : Entity_Id;
+ begin
+ Iface := First (Interface_List (Def));
+
+ while Present (Iface) loop
+ Iface_Typ := Find_Type_Of_Subtype_Indic (Iface);
+ Iface_Def := Type_Definition (Parent (Iface_Typ));
+
+ if not Is_Interface (Iface_Typ) then
+ Error_Msg_NE ("(Ada 2005) & must be an 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);
+
+ -- Ada 2005 (AI-345): Protected interfaces can only
+ -- inherit from limited, synchronized or protected
+ -- interfaces.
+
+ if Protected_Present (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", Iface);
+
+ else
+ Error_Msg_N ("(Ada 2005) protected interface cannot"
+ & " inherit from non-limited interface", Iface);
+ end if;
+
+ -- Ada 2005 (AI-345): Synchronized interfaces can only
+ -- inherit from limited and synchronized.
+
+ elsif Synchronized_Present (Def) then
+ if Limited_Present (Iface_Def)
+ or else Synchronized_Present (Iface_Def)
+ then
+ null;
+
+ elsif Protected_Present (Iface_Def) then
+ Error_Msg_N ("(Ada 2005) synchronized interface " &
+ "cannot inherit from protected interface", Iface);
+
+ elsif Task_Present (Iface_Def) then
+ Error_Msg_N ("(Ada 2005) synchronized interface " &
+ "cannot inherit from task interface", Iface);
+
+ else
+ Error_Msg_N ("(Ada 2005) synchronized interface " &
+ "cannot inherit from non-limited interface",
+ Iface);
+ end if;
+
+ -- Ada 2005 (AI-345): Task interfaces can only inherit
+ -- from limited, synchronized or task interfaces.
+
+ elsif Task_Present (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", Iface);
+
+ else
+ Error_Msg_N ("(Ada 2005) task interface cannot" &
+ " inherit from non-limited interface", Iface);
+ end if;
+ end if;
+ end if;
+
+ Next (Iface);
+ end loop;
+
+ Set_Abstract_Interfaces (T, New_Elmt_List);
+ Collect_Interfaces (Type_Definition (N), T);
+ 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
+
+ New_Scope (T);
-- If an incomplete or private type declaration was already given for
-- the type, then this scope already exists, and the discriminants have
@@ -12912,11 +14346,17 @@ package body Sem_Ch3 is
Enter_Name (Tag_Comp);
Set_Is_Tag (Tag_Comp);
+ Set_Is_Aliased (Tag_Comp);
Set_Ekind (Tag_Comp, E_Component);
Set_Etype (Tag_Comp, RTE (RE_Tag));
Set_DT_Entry_Count (Tag_Comp, No_Uint);
Set_Original_Record_Component (Tag_Comp, Tag_Comp);
Init_Component_Location (Tag_Comp);
+
+ -- Ada 2005 (AI-251): Addition of the Tag corresponding to all the
+ -- implemented interfaces
+
+ Add_Interface_Tag_Components (N, T);
end if;
Make_Class_Wide_Type (T);
@@ -12940,6 +14380,17 @@ package body Sem_Ch3 is
-- Exit from record scope
End_Scope;
+
+ if Expander_Active
+ and then Is_Tagged
+ and then not Is_Empty_List (Interface_List (Def))
+ then
+ -- Ada 2005 (AI-251): Derive the interface subprograms of all the
+ -- implemented interfaces and check if some of the subprograms
+ -- inherited from the ancestor cover some interface subprogram.
+
+ Derive_Interface_Subprograms (T);
+ end if;
end Record_Type_Declaration;
----------------------------
diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb
index 88035b8a1f4..1cf52cbfa58 100644
--- a/gcc/ada/sem_ch4.adb
+++ b/gcc/ada/sem_ch4.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2005, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2005 Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -390,7 +390,8 @@ package body Sem_Ch4 is
else
declare
- Def_Id : Entity_Id;
+ Def_Id : Entity_Id;
+ Base_Typ : Entity_Id;
begin
-- If the allocator includes a N_Subtype_Indication then a
@@ -410,10 +411,11 @@ package body Sem_Ch4 is
-- access-to-composite type, but the constraint is ignored.
Find_Type (Subtype_Mark (E));
+ Base_Typ := Entity (Subtype_Mark (E));
- if Is_Elementary_Type (Entity (Subtype_Mark (E))) then
+ if Is_Elementary_Type (Base_Typ) then
if not (Ada_Version = Ada_83
- and then Is_Access_Type (Entity (Subtype_Mark (E))))
+ and then Is_Access_Type (Base_Typ))
then
Error_Msg_N ("constraint not allowed here", E);
@@ -431,6 +433,17 @@ package body Sem_Ch4 is
Rewrite (E, New_Copy_Tree (Subtype_Mark (E)));
Analyze_Allocator (N);
return;
+
+ -- Ada 2005, AI-363: if the designated type has a constrained
+ -- partial view, it cannot receive a discriminant constraint,
+ -- and the allocated object is unconstrained.
+
+ elsif Ada_Version >= Ada_05
+ and then Has_Constrained_Partial_View (Base_Typ)
+ then
+ Error_Msg_N
+ ("constraint no allowed when type " &
+ "has a constrained partial view", Constraint (E));
end if;
if Expander_Active then
@@ -670,9 +683,18 @@ package body Sem_Ch4 is
if Ekind (Etype (Nam)) = E_Subprogram_Type then
Nam_Ent := Etype (Nam);
+ -- If the prefix is an access_to_subprogram, this may be an indirect
+ -- call. This is the case if the name in the call is not an entity
+ -- name, or if it is a function name in the context of a procedure
+ -- call. In this latter case, we have a call to a parameterless
+ -- function that returns a pointer_to_procedure which is the entity
+ -- being called.
+
elsif Is_Access_Type (Etype (Nam))
and then Ekind (Designated_Type (Etype (Nam))) = E_Subprogram_Type
- and then not Name_Denotes_Function
+ and then
+ (not Name_Denotes_Function
+ or else Nkind (N) = N_Procedure_Call_Statement)
then
Nam_Ent := Designated_Type (Etype (Nam));
Insert_Explicit_Dereference (Nam);
@@ -1969,6 +1991,9 @@ package body Sem_Ch4 is
Is_Indexed :=
Try_Indexed_Call (N, Nam, Designated_Type (Subp_Type));
+ -- The prefix can also be a parameterless function that returns an
+ -- access to subprogram. in which case this is an indirect call.
+
elsif Is_Access_Type (Subp_Type)
and then Ekind (Designated_Type (Subp_Type)) = E_Subprogram_Type
then
@@ -2099,6 +2124,23 @@ package body Sem_Ch4 is
end if;
if Report and not Is_Indexed then
+
+ -- Ada 2005 (AI-251): Complete the error notification
+ -- to help new Ada 2005 users
+
+ if Is_Class_Wide_Type (Etype (Formal))
+ and then Is_Interface (Etype (Etype (Formal)))
+ and then not Interface_Present_In_Ancestor
+ (Typ => Etype (Actual),
+ Iface => Etype (Etype (Formal)))
+ then
+ Error_Msg_Name_1 := Chars (Actual);
+ Error_Msg_Name_2 := Chars (Etype (Etype (Formal)));
+ Error_Msg_NE
+ ("(Ada 2005) % does not implement interface %",
+ Actual, Etype (Etype (Formal)));
+ end if;
+
Wrong_Type (Actual, Etype (Formal));
if Nkind (Actual) = N_Op_Eq
@@ -4892,6 +4934,30 @@ package body Sem_Ch4 is
end if;
+ -- Before analysis, the function call appears as an
+ -- indexed component.
+
+ elsif Nkind (Parent_Node) = N_Indexed_Component then
+ Node_To_Replace := Parent_Node;
+
+ declare
+ Actual : Node_Id;
+ New_Act : Node_Id;
+ begin
+ Actual := First (Expressions (Parent_Node));
+ while Present (Actual) loop
+ New_Act := New_Copy_Tree (Actual);
+ Analyze (New_Act);
+ Append (New_Act, Actuals);
+ Next (Actual);
+ end loop;
+ end;
+
+ Call_Node :=
+ Make_Function_Call (Loc,
+ Name => New_Copy_Tree (Subprog),
+ Parameter_Associations => Actuals);
+
-- Parameterless call
else
@@ -4901,7 +4967,6 @@ package body Sem_Ch4 is
Make_Function_Call (Loc,
Name => New_Copy_Tree (Subprog),
Parameter_Associations => Actuals);
-
end if;
end Transform_Object_Operation;
diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb
index 024a6cb1c24..b3bb22275c4 100644
--- a/gcc/ada/sem_ch6.adb
+++ b/gcc/ada/sem_ch6.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2005, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2005 Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -122,13 +122,14 @@ package body Sem_Ch6 is
-- against a formal access-to-subprogram type so Get_Instance_Of must
-- be called.
- procedure Check_Overriding_Operation
- (N : Node_Id;
- Subp : Entity_Id);
- -- Check that a subprogram with a pragma Overriding or Optional_Overriding
- -- is legal. This check is performed here rather than in Sem_Prag because
- -- the pragma must follow immediately the declaration, and can be treated
- -- as part of the declaration itself, as described in AI-218.
+ procedure Check_Overriding_Indicator
+ (Subp : Entity_Id;
+ Does_Override : Boolean);
+ -- Verify the consistency of an overriding_indicator given for subprogram
+ -- declaration, body, renaming, or instantiation. The flag Does_Override
+ -- is set if the scope into which we are introducing the subprogram
+ -- contains a type-conformant subprogram that becomes hidden by the new
+ -- subprogram.
procedure Check_Subprogram_Order (N : Node_Id);
-- N is the N_Subprogram_Body node for a subprogram. This routine applies
@@ -514,6 +515,14 @@ package body Sem_Ch6 is
Analyze (P);
+ -- If this is a call of the form Obj.Op, the call may have been
+ -- analyzed and possibly rewritten into a block, in which case
+ -- we are done.
+
+ if Analyzed (N) then
+ return;
+ end if;
+
-- If error analyzing prefix, then set Any_Type as result and return
if Etype (P) = Any_Type then
@@ -678,7 +687,7 @@ package body Sem_Ch6 is
-- Anything else is an error
else
- Error_Msg_N ("Invalid procedure or entry call", N);
+ Error_Msg_N ("invalid procedure or entry call", N);
end if;
end Analyze_Procedure_Call;
@@ -836,6 +845,16 @@ package body Sem_Ch6 is
-- If front-end inlining is enabled, look ahead to recognize a pragma
-- that may appear after the body.
+ procedure Verify_Overriding_Indicator;
+ -- If there was a previous spec, the entity has been entered in the
+ -- current scope previously. If the body itself carries an overriding
+ -- indicator, check that it is consistent with the known status of the
+ -- entity.
+
+ ----------------------------
+ -- Check_Following_Pragma --
+ ----------------------------
+
procedure Check_Following_Pragma is
Prag : Node_Id;
@@ -860,6 +879,27 @@ package body Sem_Ch6 is
end if;
end Check_Following_Pragma;
+ ---------------------------------
+ -- Verify_Overriding_Indicator --
+ ---------------------------------
+
+ procedure Verify_Overriding_Indicator is
+ begin
+ if Must_Override (Body_Spec)
+ and then not Is_Overriding_Operation (Spec_Id)
+ then
+ Error_Msg_NE
+ ("subprogram& is not overriding", Body_Spec, Spec_Id);
+
+ elsif Must_Not_Override (Body_Spec)
+ and then Is_Overriding_Operation (Spec_Id)
+ then
+ Error_Msg_NE
+ ("subprogram& overrides inherited operation",
+ Body_Spec, Spec_Id);
+ end if;
+ end Verify_Overriding_Indicator;
+
-- Start of processing for Analyze_Subprogram_Body
begin
@@ -1065,6 +1105,7 @@ package body Sem_Ch6 is
elsif Present (Spec_Id) then
Spec_Decl := Unit_Declaration_Node (Spec_Id);
+ Verify_Overriding_Indicator;
end if;
-- Place subprogram on scope stack, and make formals visible. If there
@@ -1072,6 +1113,11 @@ package body Sem_Ch6 is
if Present (Spec_Id) then
Generate_Reference (Spec_Id, Body_Id, 'b', Set_Ref => False);
+
+ if Is_Child_Unit (Spec_Id) then
+ Generate_Reference (Spec_Id, Scope (Spec_Id), 'k', False);
+ end if;
+
if Style_Check then
Style.Check_Identifier (Body_Id, Spec_Id);
end if;
@@ -1136,6 +1182,27 @@ package body Sem_Ch6 is
if Nkind (N) /= N_Subprogram_Body_Stub then
Set_Corresponding_Spec (N, Spec_Id);
+
+ -- Ada 2005 (AI-345): Restore the correct Etype: here we undo the
+ -- work done by Analyze_Subprogram_Specification to allow the
+ -- overriding of task, protected and interface primitives.
+
+ if Comes_From_Source (Spec_Id)
+ and then Present (First_Entity (Spec_Id))
+ and then Ekind (Etype (First_Entity (Spec_Id))) = E_Record_Type
+ and then Is_Tagged_Type (Etype (First_Entity (Spec_Id)))
+ and then Present (Abstract_Interfaces
+ (Etype (First_Entity (Spec_Id))))
+ and then Present (Corresponding_Concurrent_Type
+ (Etype (First_Entity (Spec_Id))))
+ then
+ Set_Etype (First_Entity (Spec_Id),
+ Corresponding_Concurrent_Type
+ (Etype (First_Entity (Spec_Id))));
+ end if;
+
+ -- Comment needed here, since this is not Ada 2005 stuff! ???
+
Install_Formals (Spec_Id);
Last_Formal := Last_Entity (Spec_Id);
New_Scope (Spec_Id);
@@ -1500,15 +1567,27 @@ package body Sem_Ch6 is
if Nkind (Parent (N)) = N_Compilation_Unit then
Set_Body_Required (Parent (N), True);
+
+ if Ada_Version >= Ada_05
+ and then Nkind (Specification (N)) = N_Procedure_Specification
+ and then Null_Present (Specification (N))
+ then
+ Error_Msg_N
+ ("null procedure cannot be declared at library level", N);
+ end if;
end if;
Generate_Reference_To_Formals (Designator);
Check_Eliminated (Designator);
- if Comes_From_Source (N)
- and then Is_List_Member (N)
+ -- Ada 2005: if procedure is declared with "is null" qualifier,
+ -- it requires no body.
+
+ if Nkind (Specification (N)) = N_Procedure_Specification
+ and then Null_Present (Specification (N))
then
- Check_Overriding_Operation (N, Designator);
+ Set_Has_Completion (Designator);
+ Set_Is_Inlined (Designator);
end if;
end Analyze_Subprogram_Declaration;
@@ -1524,6 +1603,39 @@ package body Sem_Ch6 is
Designator : constant Entity_Id := Defining_Entity (N);
Formals : constant List_Id := Parameter_Specifications (N);
+ function Has_Interface_Formals (T : List_Id) return Boolean;
+ -- Ada 2005 (AI-251): Returns true if some non class-wide interface
+ -- formal is found.
+
+ ---------------------------
+ -- Has_Interface_Formals --
+ ---------------------------
+
+ function Has_Interface_Formals (T : List_Id) return Boolean is
+ Param_Spec : Node_Id;
+ Formal : Entity_Id;
+
+ begin
+ Param_Spec := First (T);
+
+ while Present (Param_Spec) loop
+ Formal := Defining_Identifier (Param_Spec);
+
+ if Is_Class_Wide_Type (Etype (Formal)) then
+ null;
+
+ elsif Is_Interface (Etype (Formal)) then
+ return True;
+ end if;
+
+ Next (Param_Spec);
+ end loop;
+
+ return False;
+ end Has_Interface_Formals;
+
+ -- Start of processing for Analyze_Subprogram_Specification
+
begin
Generate_Definition (Designator);
@@ -1544,6 +1656,30 @@ package body Sem_Ch6 is
if Present (Formals) then
New_Scope (Designator);
Process_Formals (Formals, N);
+
+ -- Ada 2005 (AI-345): Allow overriding primitives of protected
+ -- interfaces by means of normal subprograms. For this purpose
+ -- temporarily use the corresponding record type as the etype
+ -- of the first formal.
+
+ if Ada_Version >= Ada_05
+ and then Comes_From_Source (Designator)
+ and then Present (First_Entity (Designator))
+ and then (Ekind (Etype (First_Entity (Designator)))
+ = E_Protected_Type
+ or else
+ Ekind (Etype (First_Entity (Designator)))
+ = E_Task_Type)
+ and then Present (Corresponding_Record_Type
+ (Etype (First_Entity (Designator))))
+ and then Present (Abstract_Interfaces
+ (Corresponding_Record_Type
+ (Etype (First_Entity (Designator)))))
+ then
+ Set_Etype (First_Entity (Designator),
+ Corresponding_Record_Type (Etype (First_Entity (Designator))));
+ end if;
+
End_Scope;
elsif Nkind (N) = N_Function_Specification then
@@ -1571,6 +1707,20 @@ package body Sem_Ch6 is
end if;
end if;
+ if Ada_Version >= Ada_05
+ and then Comes_From_Source (N)
+ and then Nkind (Parent (N)) /= N_Abstract_Subprogram_Declaration
+ and then (Nkind (N) /= N_Procedure_Specification
+ or else
+ not Null_Present (N))
+ and then Has_Interface_Formals (Formals)
+ then
+ Error_Msg_Name_1 := Chars (Defining_Unit_Name
+ (Specification (Parent (N))));
+ Error_Msg_N
+ ("(Ada 2005) interface subprogram % must be abstract or null", N);
+ end if;
+
return Designator;
end Analyze_Subprogram_Specification;
@@ -1638,7 +1788,8 @@ package body Sem_Ch6 is
then
Conv := Current_Entity (Id);
- elsif Nkind (Id) = N_Selected_Component
+ elsif (Nkind (Id) = N_Selected_Component
+ or else Nkind (Id) = N_Expanded_Name)
and then Chars (Selector_Name (Id)) = Name_Unchecked_Conversion
then
Conv := Current_Entity (Selector_Name (Id));
@@ -1647,9 +1798,9 @@ package body Sem_Ch6 is
return False;
end if;
- return
- Present (Conv)
- and then Scope (Conv) = Standard_Standard
+ return Present (Conv)
+ and then Is_Predefined_File_Name
+ (Unit_File_Name (Get_Source_Unit (Conv)))
and then Is_Intrinsic_Subprogram (Conv);
end Is_Unchecked_Conversion;
@@ -2572,100 +2723,49 @@ package body Sem_Ch6 is
end Check_Mode_Conformant;
--------------------------------
- -- Check_Overriding_Operation --
+ -- Check_Overriding_Indicator --
--------------------------------
- procedure Check_Overriding_Operation
- (N : Node_Id;
- Subp : Entity_Id)
+ procedure Check_Overriding_Indicator
+ (Subp : Entity_Id;
+ Does_Override : Boolean)
is
- Arg1 : Node_Id;
- Decl : Node_Id;
- Has_Pragma : Boolean := False;
+ Decl : Node_Id;
+ Spec : Node_Id;
begin
- -- See whether there is an overriding pragma immediately following
- -- the declaration. Intervening pragmas, such as Inline, are allowed.
-
- Decl := Next (N);
- while Present (Decl)
- and then Nkind (Decl) = N_Pragma
- loop
- if Chars (Decl) = Name_Overriding
- or else Chars (Decl) = Name_Optional_Overriding
- then
- -- For now disable the use of these pragmas, until the ARG
- -- finalizes the design of this feature.
-
- Error_Msg_N ("?unrecognized pragma", Decl);
-
- if not Is_Overriding_Operation (Subp) then
-
- -- Before emitting an error message, check whether this
- -- may override an operation that is not yet visible, as
- -- in the case of a derivation of a private operation in
- -- a child unit. Such an operation is introduced with a
- -- different name, but its alias is the parent operation.
-
- declare
- E : Entity_Id;
-
- begin
- E := First_Entity (Current_Scope);
-
- while Present (E) loop
- if Ekind (E) = Ekind (Subp)
- and then not Comes_From_Source (E)
- and then Present (Alias (E))
- and then Chars (Alias (E)) = Chars (Subp)
- and then In_Open_Scopes (Scope (Alias (E)))
- then
- exit;
- else
- Next_Entity (E);
- end if;
- end loop;
-
- if No (E) then
- Error_Msg_NE
- ("& must override an inherited operation",
- Decl, Subp);
- end if;
- end;
- end if;
+ if Ekind (Subp) = E_Enumeration_Literal then
- -- Verify syntax of pragma
+ -- No overriding indicator for literals
- Arg1 := First (Pragma_Argument_Associations (Decl));
-
- if Present (Arg1) then
- if not Is_Entity_Name (Expression (Arg1)) then
- Error_Msg_N ("pragma applies to local subprogram", Decl);
+ return;
- elsif Chars (Expression (Arg1)) /= Chars (Subp) then
- Error_Msg_N
- ("pragma must apply to preceding subprogram", Decl);
+ else
+ Decl := Unit_Declaration_Node (Subp);
+ end if;
- elsif Present (Next (Arg1)) then
- Error_Msg_N ("illegal pragma format", Decl);
- end if;
- end if;
+ if Nkind (Decl) = N_Subprogram_Declaration
+ or else Nkind (Decl) = N_Subprogram_Body
+ or else Nkind (Decl) = N_Subprogram_Renaming_Declaration
+ or else Nkind (Decl) = N_Subprogram_Body_Stub
+ then
+ Spec := Specification (Decl);
+ else
+ return;
+ end if;
- Set_Analyzed (Decl);
- Has_Pragma := True;
- exit;
+ if not Does_Override then
+ if Must_Override (Spec) then
+ Error_Msg_NE ("subprogram& is not overriding", Spec, Subp);
end if;
- Next (Decl);
- end loop;
-
- if not Has_Pragma
- and then Explicit_Overriding
- and then Is_Overriding_Operation (Subp)
- then
- Error_Msg_NE ("Missing overriding pragma for&", Subp, Subp);
+ else
+ if Must_Not_Override (Spec) then
+ Error_Msg_NE
+ ("subprogram& overrides inherited operation", Spec, Subp);
+ end if;
end if;
- end Check_Overriding_Operation;
+ end Check_Overriding_Indicator;
-------------------
-- Check_Returns --
@@ -3142,6 +3242,8 @@ package body Sem_Ch6 is
end if;
end Base_Types_Match;
+ -- Start of processing for Conforming_Types
+
begin
-- The context is an instance association for a formal
-- access-to-subprogram type; the formal parameter types require
@@ -3182,7 +3284,8 @@ package body Sem_Ch6 is
or else Subtypes_Statically_Match (Type_1, Full_View (Type_2));
end if;
- -- Ada 2005 (AI-254): Detect anonymous access to subprogram types
+ -- Ada 2005 (AI-254): Anonymous access to subprogram types must be
+ -- treated recursively because they carry a signature.
Are_Anonymous_Access_To_Subprogram_Types :=
@@ -3264,10 +3367,23 @@ package body Sem_Ch6 is
Etype (Base_Type (Desig_2)), Ctype);
elsif Are_Anonymous_Access_To_Subprogram_Types then
- return Ctype = Type_Conformant
- or else
+ if Ada_Version < Ada_05 then
+ return Ctype = Type_Conformant
+ or else
Subtypes_Statically_Match (Desig_1, Desig_2);
+ -- We must check the conformance of the signatures themselves
+
+ else
+ declare
+ Conformant : Boolean;
+ begin
+ Check_Conformance
+ (Desig_1, Desig_2, Ctype, False, Conformant);
+ return Conformant;
+ end;
+ end if;
+
else
return Base_Type (Desig_1) = Base_Type (Desig_2)
and then (Ctype = Type_Conformant
@@ -4438,12 +4554,18 @@ package body Sem_Ch6 is
(S : Entity_Id;
Derived_Type : Entity_Id := Empty)
is
+ Does_Override : Boolean := False;
+ -- Set if the current scope has an operation that is type-conformant
+ -- with S, and becomes hidden by S.
+
E : Entity_Id;
-- Entity that S overrides
Prev_Vis : Entity_Id := Empty;
-- Needs comment ???
+ Is_Alias_Interface : Boolean := False;
+
function Is_Private_Declaration (E : Entity_Id) return Boolean;
-- Check that E is declared in the private part of the current package,
-- or in the package body, where it may hide a previous declaration.
@@ -4522,8 +4644,17 @@ package body Sem_Ch6 is
and then Is_Abstract (S)
and then (not Is_Overriding or else not Is_Abstract (E))
then
- Error_Msg_N ("abstract subprograms must be visible "
- & "('R'M 3.9.3(10))!", S);
+ if not Is_Interface (T) then
+ Error_Msg_N ("abstract subprograms must be visible "
+ & "('R'M 3.9.3(10))!", S);
+
+ -- Ada 2005 (AI-251)
+
+ else
+ Error_Msg_N ("primitive subprograms of interface types "
+ & "declared in a visible part, must be declared in "
+ & "the visible part ('R'M 3.9.4)!", S);
+ end if;
elsif Ekind (S) = E_Function
and then Is_Tagged_Type (T)
@@ -4650,6 +4781,15 @@ package body Sem_Ch6 is
Check_Dispatching_Operation (S, Empty);
Maybe_Primitive_Operation;
+ -- Ada 2005 (AI-397): Subprograms in the context of protected
+ -- types have their overriding indicators checked in Sem_Ch9.
+
+ if Ekind (S) not in Subprogram_Kind
+ or else Ekind (Scope (S)) /= E_Protected_Type
+ then
+ Check_Overriding_Indicator (S, False);
+ end if;
+
-- If there is a homonym that is not overloadable, then we have an
-- error, except for the special cases checked explicitly below.
@@ -4673,6 +4813,7 @@ package body Sem_Ch6 is
Enter_Overloaded_Entity (S);
Set_Homonym (S, Homonym (E));
Check_Dispatching_Operation (S, Empty);
+ Check_Overriding_Indicator (S, False);
-- If the subprogram is implicit it is hidden by the previous
-- declaration. However if it is dispatching, it must appear in the
@@ -4706,6 +4847,12 @@ package body Sem_Ch6 is
-- E exists and is overloadable
else
+ Is_Alias_Interface :=
+ Present (Alias (S))
+ and then Is_Dispatching_Operation (Alias (S))
+ and then Present (DTC_Entity (Alias (S)))
+ and then Is_Interface (Scope (DTC_Entity (Alias (S))));
+
-- Loop through E and its homonyms to determine if any of them is
-- the candidate for overriding by S.
@@ -4718,8 +4865,13 @@ package body Sem_Ch6 is
-- Check if we have type conformance
- elsif Type_Conformant (E, S) then
+ -- Ada 2005 (AI-251): In case of overriding an interface
+ -- subprogram it is not an error that the old and new entities
+ -- have the same profile, and hence we skip this code.
+ elsif not Is_Alias_Interface
+ and then Type_Conformant (E, S)
+ then
-- If the old and new entities have the same profile and one
-- is not the body of the other, then this is an error, unless
-- one of them is implicitly declared.
@@ -4762,6 +4914,11 @@ package body Sem_Ch6 is
-- the existing declaration, which is overriding.
Set_Is_Overriding_Operation (E);
+
+ if Comes_From_Source (E) then
+ Check_Overriding_Indicator (E, True);
+ end if;
+
return;
-- Within an instance, the renaming declarations for
@@ -4805,6 +4962,8 @@ package body Sem_Ch6 is
-- replaced in the list of primitive operations of its type
-- (see Override_Dispatching_Operation).
+ Does_Override := True;
+
declare
Prev : Entity_Id;
@@ -4912,6 +5071,7 @@ package body Sem_Ch6 is
Enter_Overloaded_Entity (S);
Set_Is_Overriding_Operation (S);
+ Check_Overriding_Indicator (S, True);
if Is_Dispatching_Operation (E) then
@@ -4921,7 +5081,41 @@ package body Sem_Ch6 is
Set_Convention (S, Convention (E));
- Check_Dispatching_Operation (S, E);
+ -- AI-251: If the subprogram implements an interface,
+ -- check if this subprogram covers other interface
+ -- subprograms available in the same scope.
+
+ if Present (Alias (E))
+ and then Ekind (Alias (E)) /= E_Operator
+ and then Present (DTC_Entity (Alias (E)))
+ and then Is_Interface (Scope (DTC_Entity
+ (Alias (E))))
+ then
+ Check_Dispatching_Operation (S, E);
+
+ declare
+ E1 : Entity_Id;
+
+ begin
+ E1 := Homonym (E);
+ while Present (E1) loop
+ if Present (Alias (E1))
+ and then Ekind (Alias (E1)) /= E_Operator
+ and then Present (DTC_Entity (Alias (E1)))
+ and then Is_Interface
+ (Scope (DTC_Entity (Alias (E1))))
+ and then Type_Conformant (E1, S)
+ then
+ Check_Dispatching_Operation (S, E1);
+ end if;
+
+ E1 := Homonym (E1);
+ end loop;
+ end;
+ else
+ Check_Dispatching_Operation (S, E);
+ end if;
+
else
Check_Dispatching_Operation (S, Empty);
end if;
@@ -4978,6 +5172,7 @@ package body Sem_Ch6 is
Enter_Overloaded_Entity (S);
Maybe_Primitive_Operation;
+ Check_Overriding_Indicator (S, Does_Override);
-- If S is a derived operation for an untagged type then by
-- definition it's not a dispatching operation (even if the parent
diff --git a/gcc/ada/sem_ch9.adb b/gcc/ada/sem_ch9.adb
index 06060ab9ff0..71b42f7e1f6 100644
--- a/gcc/ada/sem_ch9.adb
+++ b/gcc/ada/sem_ch9.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2004, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2005 Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -30,6 +30,7 @@ with Einfo; use Einfo;
with Errout; use Errout;
with Exp_Ch9;
with Elists; use Elists;
+with Freeze; use Freeze;
with Itypes; use Itypes;
with Lib.Xref; use Lib.Xref;
with Nlists; use Nlists;
@@ -67,6 +68,11 @@ package body Sem_Ch9 is
-- count the entries (checking the static requirement), and compare with
-- the given maximum.
+ procedure Check_Overriding_Indicator (Def : Node_Id);
+ -- Ada 2005 (AI-397): Check the overriding indicator of entries and
+ -- subprograms of protected or task types. Def is the definition of
+ -- the protected or task type.
+
function Find_Concurrent_Spec (Body_Id : Entity_Id) return Entity_Id;
-- Find entity in corresponding task or protected declaration. Use full
-- view if first declaration was for an incomplete type.
@@ -1024,6 +1030,7 @@ package body Sem_Ch9 is
Check_Max_Entries (N, Max_Protected_Entries);
Process_End_Label (N, 'e', Current_Scope);
+ Check_Overriding_Indicator (N);
end Analyze_Protected_Definition;
----------------------------
@@ -1031,9 +1038,12 @@ package body Sem_Ch9 is
----------------------------
procedure Analyze_Protected_Type (N : Node_Id) is
- E : Entity_Id;
- T : Entity_Id;
- Def_Id : constant Entity_Id := Defining_Identifier (N);
+ E : Entity_Id;
+ T : Entity_Id;
+ Def_Id : constant Entity_Id := Defining_Identifier (N);
+ Iface : Node_Id;
+ Iface_Def : Node_Id;
+ Iface_Typ : Entity_Id;
begin
if No_Run_Time_Mode then
@@ -1052,13 +1062,56 @@ package body Sem_Ch9 is
end if;
Set_Ekind (T, E_Protected_Type);
+ Set_Is_First_Subtype (T, True);
Init_Size_Align (T);
Set_Etype (T, T);
- Set_Is_First_Subtype (T, True);
Set_Has_Delayed_Freeze (T, True);
Set_Stored_Constraint (T, No_Elist);
New_Scope (T);
+ -- Ada 2005 (AI-345)
+
+ if Present (Interface_List (N)) then
+ Iface := First (Interface_List (N));
+
+ while Present (Iface) loop
+ Iface_Typ := Find_Type_Of_Subtype_Indic (Iface);
+ Iface_Def := Type_Definition (Parent (Iface_Typ));
+
+ if not Is_Interface (Iface_Typ) then
+ Error_Msg_NE ("(Ada 2005) & must be an interface",
+ Iface, Iface_Typ);
+
+ else
+ -- Ada 2005 (AI-251): "The declaration of a specific
+ -- descendant of an interface type freezes the interface
+ -- type" RM 13.14
+
+ Freeze_Before (N, Etype (Iface));
+
+ -- Ada 2005 (AI-345): Protected types can only implement
+ -- limited, synchronized or protected interfaces.
+
+ 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 type cannot implement a "
+ & "task interface", Iface);
+
+ else
+ Error_Msg_N ("(Ada 2005) protected type cannot implement a "
+ & "non-limited interface", Iface);
+ end if;
+ end if;
+
+ Next (Iface);
+ end loop;
+ end if;
+
if Present (Discriminant_Specifications (N)) then
if Has_Discriminants (T) then
@@ -1071,6 +1124,8 @@ package body Sem_Ch9 is
end if;
end if;
+ Set_Is_Constrained (T, not Has_Discriminants (T));
+
Analyze (Protected_Definition (N));
-- Protected types with entries are controlled (because of the
@@ -1119,9 +1174,9 @@ package body Sem_Ch9 is
---------------------
procedure Analyze_Requeue (N : Node_Id) is
+ Count : Natural := 0;
Entry_Name : Node_Id := Name (N);
Entry_Id : Entity_Id;
- Found : Boolean;
I : Interp_Index;
It : Interp;
Enclosing : Entity_Id;
@@ -1200,29 +1255,37 @@ package body Sem_Ch9 is
if Is_Overloaded (Entry_Name) then
Get_First_Interp (Entry_Name, I, It);
- Found := False;
Entry_Id := Empty;
while Present (It.Nam) loop
if No (First_Formal (It.Nam))
or else Subtype_Conformant (Enclosing, It.Nam)
then
- if not Found then
- Found := True;
+
+ -- Ada 2005 (AI-345): Since protected and task types have
+ -- primitive entry wrappers, we only consider source entries.
+
+ if Comes_From_Source (It.Nam) then
+ Count := Count + 1;
Entry_Id := It.Nam;
else
- Error_Msg_N ("ambiguous entry name in requeue", N);
- return;
+ Remove_Interp (I);
end if;
end if;
Get_Next_Interp (I, It);
end loop;
- if not Found then
- Error_Msg_N ("no entry matches context", N);
+ if Count = 0 then
+ Error_Msg_N ("no entry matches context", N);
+ return;
+
+ elsif Count > 1 then
+ Error_Msg_N ("ambiguous entry name in requeue", N);
return;
+
else
+ Set_Is_Overloaded (Entry_Name, False);
Set_Entity (Entry_Name, Entry_Id);
end if;
@@ -1361,7 +1424,7 @@ package body Sem_Ch9 is
elsif Nkind (Alt) = N_Terminate_Alternative then
if Terminate_Present then
- Error_Msg_N ("Only one terminate alternative allowed", N);
+ Error_Msg_N ("only one terminate alternative allowed", N);
else
Terminate_Present := True;
Check_Restriction (No_Terminate_Alternatives, N);
@@ -1462,11 +1525,16 @@ package body Sem_Ch9 is
T_Decl :=
Make_Protected_Type_Declaration (Loc,
Defining_Identifier => T,
- Protected_Definition => Relocate_Node (Protected_Definition (N)));
+ Protected_Definition => Relocate_Node (Protected_Definition (N)),
+ Interface_List => Interface_List (N));
+
+ -- Ada 2005 (AI-399): Mark the object as aliased. Required to use
+ -- the attribute 'access
O_Decl :=
Make_Object_Declaration (Loc,
Defining_Identifier => O_Name,
+ Aliased_Present => Ada_Version >= Ada_05,
Object_Definition => Make_Identifier (Loc, Chars (T)));
Rewrite (N, T_Decl);
@@ -1489,7 +1557,6 @@ package body Sem_Ch9 is
-- expanded twice, with disastrous result.
Analyze_Protected_Type (N);
-
end Analyze_Single_Protected;
-------------------------
@@ -1518,11 +1585,16 @@ package body Sem_Ch9 is
T_Decl :=
Make_Task_Type_Declaration (Loc,
Defining_Identifier => T,
- Task_Definition => Relocate_Node (Task_Definition (N)));
+ Task_Definition => Relocate_Node (Task_Definition (N)),
+ Interface_List => Interface_List (N));
+
+ -- Ada 2005 (AI-399): Mark the object as aliased. Required to use
+ -- the attribute 'access
O_Decl :=
Make_Object_Declaration (Loc,
Defining_Identifier => O_Name,
+ Aliased_Present => Ada_Version >= Ada_05,
Object_Definition => Make_Identifier (Loc, Chars (T)));
Rewrite (N, T_Decl);
@@ -1690,6 +1762,7 @@ package body Sem_Ch9 is
Check_Max_Entries (N, Max_Task_Entries);
Process_End_Label (N, 'e', Current_Scope);
+ Check_Overriding_Indicator (N);
end Analyze_Task_Definition;
-----------------------
@@ -1697,8 +1770,11 @@ package body Sem_Ch9 is
-----------------------
procedure Analyze_Task_Type (N : Node_Id) is
- T : Entity_Id;
- Def_Id : constant Entity_Id := Defining_Identifier (N);
+ T : Entity_Id;
+ Def_Id : constant Entity_Id := Defining_Identifier (N);
+ Iface : Node_Id;
+ Iface_Def : Node_Id;
+ Iface_Typ : Entity_Id;
begin
Check_Restriction (No_Tasking, N);
@@ -1720,6 +1796,47 @@ package body Sem_Ch9 is
Set_Stored_Constraint (T, No_Elist);
New_Scope (T);
+ -- Ada 2005 (AI-345)
+
+ if Present (Interface_List (N)) then
+ Iface := First (Interface_List (N));
+ while Present (Iface) loop
+ Iface_Typ := Find_Type_Of_Subtype_Indic (Iface);
+ Iface_Def := Type_Definition (Parent (Iface_Typ));
+
+ if not Is_Interface (Iface_Typ) then
+ Error_Msg_NE ("(Ada 2005) & must be an interface",
+ Iface, Iface_Typ);
+
+ else
+ -- Ada 2005 (AI-251): The declaration of a specific descendant
+ -- of an interface type freezes the interface type (RM 13.14).
+
+ Freeze_Before (N, Etype (Iface));
+
+ -- Ada 2005 (AI-345): Task types can only implement limited,
+ -- synchronized or task interfaces.
+
+ 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 type cannot implement a " &
+ "protected interface", Iface);
+
+ else
+ Error_Msg_N ("(Ada 2005) task type cannot implement a " &
+ "non-limited interface", Iface);
+ end if;
+ end if;
+
+ Next (Iface);
+ end loop;
+ end if;
+
if Present (Discriminant_Specifications (N)) then
if Ada_Version = Ada_83 and then Comes_From_Source (N) then
Error_Msg_N ("(Ada 83) task discriminant not allowed!", N);
@@ -1736,6 +1853,8 @@ package body Sem_Ch9 is
end if;
end if;
+ Set_Is_Constrained (T, not Has_Discriminants (T));
+
if Present (Task_Definition (N)) then
Analyze_Task_Definition (Task_Definition (N));
end if;
@@ -1901,6 +2020,263 @@ package body Sem_Ch9 is
end if;
end Check_Max_Entries;
+ --------------------------------
+ -- Check_Overriding_Indicator --
+ --------------------------------
+
+ procedure Check_Overriding_Indicator (Def : Node_Id) is
+ Aliased_Hom : Entity_Id;
+ Decl : Node_Id;
+ Def_Id : Entity_Id;
+ Hom : Entity_Id;
+ Ifaces : constant List_Id := Interface_List (Parent (Def));
+ Overrides : Boolean;
+ Spec : Node_Id;
+ Vis_Decls : constant List_Id := Visible_Declarations (Def);
+
+ function Matches_Prefixed_View_Profile
+ (Ifaces : List_Id;
+ Entry_Params : List_Id;
+ Proc_Params : List_Id) return Boolean;
+ -- Ada 2005 (AI-397): Determine if an entry parameter profile matches
+ -- the prefixed view profile of an abstract procedure. Also determine
+ -- whether the abstract procedure belongs to an implemented interface.
+
+ -----------------------------------
+ -- Matches_Prefixed_View_Profile --
+ -----------------------------------
+
+ function Matches_Prefixed_View_Profile
+ (Ifaces : List_Id;
+ Entry_Params : List_Id;
+ Proc_Params : List_Id) return Boolean
+ is
+ Entry_Param : Node_Id;
+ Proc_Param : Node_Id;
+ Proc_Param_Typ : Entity_Id;
+
+ function Includes_Interface
+ (Iface : Entity_Id;
+ Ifaces : List_Id) return Boolean;
+ -- Determine if an interface is contained in a list of interfaces
+
+ ------------------------
+ -- Includes_Interface --
+ ------------------------
+
+ function Includes_Interface
+ (Iface : Entity_Id;
+ Ifaces : List_Id) return Boolean
+ is
+ Ent : Entity_Id;
+
+ begin
+ Ent := First (Ifaces);
+
+ while Present (Ent) loop
+ if Etype (Ent) = Iface then
+ return True;
+ end if;
+
+ Next (Ent);
+ end loop;
+
+ return False;
+ end Includes_Interface;
+
+ -- Start of processing for Matches_Prefixed_View_Profile
+
+ begin
+ Proc_Param := First (Proc_Params);
+ Proc_Param_Typ := Etype (Parameter_Type (Proc_Param));
+
+ -- The first parameter of the abstract procedure must be of an
+ -- interface type. The task or protected type must also implement
+ -- that interface.
+
+ if not Is_Interface (Proc_Param_Typ)
+ or else not Includes_Interface (Proc_Param_Typ, Ifaces)
+ then
+ return False;
+ end if;
+
+ Entry_Param := First (Entry_Params);
+ Proc_Param := Next (Proc_Param);
+ while Present (Entry_Param)
+ and then Present (Proc_Param)
+ loop
+ -- The two parameters must be mode conformant and have the exact
+ -- same types.
+
+ if In_Present (Entry_Param) /= In_Present (Proc_Param)
+ or else Out_Present (Entry_Param) /= Out_Present (Proc_Param)
+ or else Etype (Parameter_Type (Entry_Param)) /=
+ Etype (Parameter_Type (Proc_Param))
+ then
+ return False;
+ end if;
+
+ Next (Entry_Param);
+ Next (Proc_Param);
+ end loop;
+
+ -- One of the lists is longer than the other
+
+ if Present (Entry_Param) or else Present (Proc_Param) then
+ return False;
+ end if;
+
+ return True;
+ end Matches_Prefixed_View_Profile;
+
+ -- Start of processing for Check_Overriding_Indicator
+
+ begin
+ if Present (Ifaces) then
+ Decl := First (Vis_Decls);
+ while Present (Decl) loop
+
+ -- Consider entries with either "overriding" or "not overriding"
+ -- indicator present.
+
+ if Nkind (Decl) = N_Entry_Declaration
+ and then (Must_Override (Decl)
+ or else
+ Must_Not_Override (Decl))
+ then
+ Def_Id := Defining_Identifier (Decl);
+
+ Overrides := False;
+
+ Hom := Homonym (Def_Id);
+ while Present (Hom) loop
+
+ -- The current entry may override a procedure from an
+ -- implemented interface.
+
+ if Ekind (Hom) = E_Procedure
+ and then (Is_Abstract (Hom)
+ or else
+ Null_Present (Parent (Hom)))
+ then
+ Aliased_Hom := Hom;
+
+ while Present (Alias (Aliased_Hom)) loop
+ Aliased_Hom := Alias (Aliased_Hom);
+ end loop;
+
+ if Matches_Prefixed_View_Profile (Ifaces,
+ Parameter_Specifications (Decl),
+ Parameter_Specifications (Parent (Aliased_Hom)))
+ then
+ Overrides := True;
+ exit;
+ end if;
+ end if;
+
+ Hom := Homonym (Hom);
+ end loop;
+
+ if Overrides then
+ if Must_Not_Override (Decl) then
+ Error_Msg_NE ("entry& is overriding", Def_Id, Def_Id);
+ end if;
+ else
+ if Must_Override (Decl) then
+ Error_Msg_NE ("entry& is not overriding", Def_Id, Def_Id);
+ end if;
+ end if;
+
+ -- Consider subprograms with either "overriding" or "not
+ -- overriding" indicator present.
+
+ elsif Nkind (Decl) = N_Subprogram_Declaration
+ and then (Must_Override (Specification (Decl))
+ or else
+ Must_Not_Override (Specification (Decl)))
+ then
+ Spec := Specification (Decl);
+ Def_Id := Defining_Unit_Name (Spec);
+
+ Overrides := False;
+
+ Hom := Homonym (Def_Id);
+ while Present (Hom) loop
+
+ -- Function
+
+ if Ekind (Def_Id) = E_Function
+ and then Ekind (Hom) = E_Function
+ and then Is_Abstract (Hom)
+ and then Matches_Prefixed_View_Profile (Ifaces,
+ Parameter_Specifications (Spec),
+ Parameter_Specifications (Parent (Hom)))
+ and then Etype (Subtype_Mark (Spec)) =
+ Etype (Subtype_Mark (Parent (Hom)))
+ then
+ Overrides := True;
+ exit;
+
+ -- Procedure
+
+ elsif Ekind (Def_Id) = E_Procedure
+ and then Ekind (Hom) = E_Procedure
+ and then (Is_Abstract (Hom)
+ or else
+ Null_Present (Parent (Hom)))
+ and then Matches_Prefixed_View_Profile (Ifaces,
+ Parameter_Specifications (Spec),
+ Parameter_Specifications (Parent (Hom)))
+ then
+ Overrides := True;
+ exit;
+ end if;
+
+ Hom := Homonym (Hom);
+ end loop;
+
+ if Overrides then
+ if Must_Not_Override (Spec) then
+ Error_Msg_NE
+ ("subprogram& is overriding", Def_Id, Def_Id);
+ end if;
+ else
+ if Must_Override (Spec) then
+ Error_Msg_NE
+ ("subprogram& is not overriding", Def_Id, Def_Id);
+ end if;
+ end if;
+ end if;
+
+ Next (Decl);
+ end loop;
+
+ -- The protected or task type is not implementing an interface,
+ -- we need to check for the presence of "overriding" entries or
+ -- subprograms and flag them as erroneous.
+
+ else
+ Decl := First (Vis_Decls);
+
+ while Present (Decl) loop
+ if Nkind (Decl) = N_Entry_Declaration
+ and then Must_Override (Decl)
+ then
+ Def_Id := Defining_Identifier (Decl);
+ Error_Msg_NE ("entry& is not overriding", Def_Id, Def_Id);
+
+ elsif Nkind (Decl) = N_Subprogram_Declaration
+ and then Must_Override (Specification (Decl))
+ then
+ Def_Id := Defining_Identifier (Specification (Decl));
+ Error_Msg_NE ("subprogram& is not overriding", Def_Id, Def_Id);
+ end if;
+
+ Next (Decl);
+ end loop;
+ end if;
+ end Check_Overriding_Indicator;
+
--------------------------
-- Find_Concurrent_Spec --
--------------------------
diff --git a/gcc/ada/sem_disp.adb b/gcc/ada/sem_disp.adb
index 9f8521bb427..c5fe8324cbe 100644
--- a/gcc/ada/sem_disp.adb
+++ b/gcc/ada/sem_disp.adb
@@ -31,6 +31,7 @@ with Einfo; use Einfo;
with Exp_Disp; use Exp_Disp;
with Exp_Ch7; use Exp_Ch7;
with Exp_Tss; use Exp_Tss;
+with Exp_Util; use Exp_Util;
with Errout; use Errout;
with Hostparm; use Hostparm;
with Nlists; use Nlists;
@@ -219,12 +220,25 @@ package body Sem_Disp is
elsif Ekind (T) = E_Anonymous_Access_Type
and then Is_Tagged_Type (Designated_Type (T))
- and then Ekind (Designated_Type (T)) /= E_Incomplete_Type
then
- if Is_First_Subtype (Designated_Type (T)) then
- Tagged_Type := Designated_Type (T);
- else
- Tagged_Type := Base_Type (Designated_Type (T));
+ if Ekind (Designated_Type (T)) /= E_Incomplete_Type then
+ if Is_First_Subtype (Designated_Type (T)) then
+ Tagged_Type := Designated_Type (T);
+ else
+ Tagged_Type := Base_Type (Designated_Type (T));
+ end if;
+
+ -- Ada 2005 (AI-50217)
+
+ elsif From_With_Type (Designated_Type (T))
+ and then Present (Non_Limited_View (Designated_Type (T)))
+ then
+ if Is_First_Subtype (Non_Limited_View (Designated_Type (T))) then
+ Tagged_Type := Non_Limited_View (Designated_Type (T));
+ else
+ Tagged_Type := Base_Type (Non_Limited_View
+ (Designated_Type (T)));
+ end if;
end if;
end if;
@@ -522,6 +536,18 @@ package body Sem_Disp is
Set_Is_Dispatching_Operation (Subp, False);
Tagged_Type := Find_Dispatching_Type (Subp);
+ -- Ada 2005 (AI-345)
+
+ if Ada_Version = Ada_05
+ and then Present (Tagged_Type)
+ and then Is_Concurrent_Type (Tagged_Type)
+ and then not Is_Empty_Elmt_List
+ (Abstract_Interfaces
+ (Corresponding_Record_Type (Tagged_Type)))
+ then
+ Tagged_Type := Corresponding_Record_Type (Tagged_Type);
+ end if;
+
-- If Subp is derived from a dispatching operation then it should
-- always be treated as dispatching. In this case various checks
-- below will be bypassed. Makes sure that late declarations for
@@ -574,8 +600,10 @@ package body Sem_Disp is
elsif Present (Old_Subp)
and then Is_Dispatching_Operation (Old_Subp)
then
- if Nkind (Unit_Declaration_Node (Subp)) = N_Subprogram_Body
- and then Comes_From_Source (Subp)
+ if Comes_From_Source (Subp)
+ and then
+ (Nkind (Unit_Declaration_Node (Subp)) = N_Subprogram_Body
+ or else Nkind (Unit_Declaration_Node (Subp)) in N_Body_Stub)
then
declare
Subp_Body : constant Node_Id := Unit_Declaration_Node (Subp);
@@ -947,7 +975,6 @@ package body Sem_Disp is
Set_Alias (Old_Subp, Alias (Subp));
-- The derived subprogram should inherit the abstractness
-
-- of the parent subprogram (except in the case of a function
-- returning the type). This sets the abstractness properly
-- for cases where a private extension may have inherited
@@ -1140,6 +1167,34 @@ package body Sem_Disp is
New_Op : Entity_Id)
is
Op_Elmt : Elmt_Id := First_Elmt (Primitive_Operations (Tagged_Type));
+ Elmt : Elmt_Id;
+ Found : Boolean;
+
+ function Is_Interface_Subprogram (Op : Entity_Id) return Boolean;
+ -- Comment requjired ???
+
+ -----------------------------
+ -- Is_Interface_Subprogram --
+ -----------------------------
+
+ function Is_Interface_Subprogram (Op : Entity_Id) return Boolean is
+ Aux : Entity_Id;
+
+ begin
+ Aux := Op;
+ while Present (Alias (Aux))
+ and then Present (DTC_Entity (Alias (Aux)))
+ loop
+ if Is_Interface (Scope (DTC_Entity (Alias (Aux)))) then
+ return True;
+ end if;
+ Aux := Alias (Aux);
+ end loop;
+
+ return False;
+ end Is_Interface_Subprogram;
+
+ -- Start of processing for Override_Dispatching_Operation
begin
-- Patch the primitive operation list
@@ -1157,7 +1212,49 @@ package body Sem_Disp is
return;
end if;
- Replace_Elmt (Op_Elmt, New_Op);
+ -- Ada 2005 (AI-251): Do not replace subprograms corresponding to
+ -- abstract interfaces. They will be used later to generate the
+ -- corresponding thunks to initialize the Vtable (see subprogram
+ -- Freeze_Subprogram)
+
+ if Is_Interface_Subprogram (Prev_Op) then
+ Set_DT_Position (Prev_Op, DT_Position (Alias (Prev_Op)));
+ Set_Is_Abstract (Prev_Op, Is_Abstract (New_Op));
+ Set_Is_Overriding_Operation (Prev_Op);
+ Set_Abstract_Interface_Alias (Prev_Op, Alias (Prev_Op));
+ Set_Alias (Prev_Op, New_Op);
+ Set_Is_Internal (Prev_Op);
+
+ -- Override predefined primitive operations
+
+ if Is_Predefined_Dispatching_Operation (Prev_Op) then
+ Replace_Elmt (Op_Elmt, New_Op);
+ return;
+ end if;
+
+ -- Check if this primitive operation was previously added for another
+ -- interface.
+
+ Elmt := First_Elmt (Primitive_Operations (Tagged_Type));
+ Found := False;
+ while Present (Elmt) loop
+ if Node (Elmt) = New_Op then
+ Found := True;
+ exit;
+ end if;
+
+ Next_Elmt (Elmt);
+ end loop;
+
+ if not Found then
+ Append_Elmt (New_Op, Primitive_Operations (Tagged_Type));
+ -- Replace_Elmt (Op_Elmt, New_Op); -- why is this commented out???
+ end if;
+ return;
+
+ else
+ Replace_Elmt (Op_Elmt, New_Op);
+ end if;
if (not Is_Package (Current_Scope))
or else not In_Private_Part (Current_Scope)
diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb
index cc55d26d2d5..fdba2bdec03 100644
--- a/gcc/ada/sem_res.adb
+++ b/gcc/ada/sem_res.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2005, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2005 Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -31,6 +31,7 @@ with Debug_A; use Debug_A;
with Einfo; use Einfo;
with Errout; use Errout;
with Expander; use Expander;
+with Exp_Disp; use Exp_Disp;
with Exp_Ch7; use Exp_Ch7;
with Exp_Tss; use Exp_Tss;
with Exp_Util; use Exp_Util;
@@ -357,7 +358,9 @@ package body Sem_Res is
procedure Check_Direct_Boolean_Op (N : Node_Id) is
begin
- if Root_Type (Etype (Left_Opnd (N))) = Standard_Boolean then
+ if Nkind (N) in N_Op
+ and then Root_Type (Etype (Left_Opnd (N))) = Standard_Boolean
+ then
Check_Restriction (No_Direct_Boolean_Operators, N);
end if;
end Check_Direct_Boolean_Op;
@@ -538,6 +541,12 @@ package body Sem_Res is
if Paren_Count (N) > 0 then
Error_Msg_N
("discriminant in constraint must appear alone", N);
+
+ elsif Nkind (N) = N_Expanded_Name
+ and then Comes_From_Source (N)
+ then
+ Error_Msg_N
+ ("discriminant must appear alone as a direct name", N);
end if;
return;
@@ -2120,7 +2129,7 @@ package body Sem_Res is
if Typ = Any_Real
and then Expr_Type = Any_Fixed
then
- Error_Msg_N ("Illegal context for mixed mode operation", N);
+ Error_Msg_N ("illegal context for mixed mode operation", N);
Set_Etype (N, Universal_Real);
Ctx_Type := Universal_Real;
end if;
@@ -2590,9 +2599,23 @@ package body Sem_Res is
if Has_Aliased_Components (Etype (Expression (A)))
/= Has_Aliased_Components (Etype (F))
then
- Error_Msg_N
- ("both component types in a view conversion must be"
- & " aliased, or neither", A);
+ if Ada_Version < Ada_05 then
+ Error_Msg_N
+ ("both component types in a view conversion must be"
+ & " aliased, or neither", A);
+
+ -- Ada 2005: rule is relaxed (see AI-363)
+
+ elsif Has_Aliased_Components (Etype (F))
+ and then
+ not Has_Aliased_Components (Etype (Expression (A)))
+ then
+ Error_Msg_N
+ ("view conversion operand must have aliased " &
+ "components", N);
+ Error_Msg_N
+ ("\since target type has aliased components", N);
+ end if;
elsif not Same_Ancestor (Etype (F), Etype (Expression (A)))
and then
@@ -2600,8 +2623,8 @@ package body Sem_Res is
or else Is_By_Reference_Type (Etype (Expression (A))))
then
Error_Msg_N
- ("view conversion between unrelated by_reference "
- & "array types not allowed (\A\I-00246)?", A);
+ ("view conversion between unrelated by reference " &
+ "array types not allowed (\'A'I-00246)", A);
end if;
end if;
@@ -2620,19 +2643,16 @@ package body Sem_Res is
or else Is_Limited_Type (Etype (Expression (A))))
then
Error_Msg_N
- ("Conversion between unrelated limited array types "
- & "not allowed (\A\I-00246)?", A);
-
- -- Disable explanation (which produces additional errors)
- -- until AI is approved and warning becomes an error.
+ ("conversion between unrelated limited array types " &
+ "not allowed (\A\I-00246)", A);
- -- if Is_Limited_Type (Etype (F)) then
- -- Explain_Limited_Type (Etype (F), A);
- -- end if;
+ if Is_Limited_Type (Etype (F)) then
+ Explain_Limited_Type (Etype (F), A);
+ end if;
- -- if Is_Limited_Type (Etype (Expression (A))) then
- -- Explain_Limited_Type (Etype (Expression (A)), A);
- -- end if;
+ if Is_Limited_Type (Etype (Expression (A))) then
+ Explain_Limited_Type (Etype (Expression (A)), A);
+ end if;
end if;
Resolve (A, Etype (F));
@@ -2668,9 +2688,9 @@ package body Sem_Res is
Check_Unset_Reference (A);
end if;
- -- In Ada 83 we cannot pass an OUT parameter as an IN
- -- or IN OUT actual to a nested call, since this is a
- -- case of reading an out parameter, which is not allowed.
+ -- In Ada 83 we cannot pass an OUT parameter as an IN or IN OUT
+ -- actual to a nested call, since this is case of reading an
+ -- out parameter, which is not allowed.
if Ada_Version = Ada_83
and then Is_Entity_Name (A)
@@ -3035,6 +3055,46 @@ package body Sem_Res is
end if;
end if;
+ -- Ada 2005 (AI-344): A class-wide allocator requires an accessibility
+ -- check that the level of the type of the created object is not deeper
+ -- than the level of the allocator's access type, since extensions can
+ -- now occur at deeper levels than their ancestor types. This is a
+ -- static accessibility level check; a run-time check is also needed in
+ -- the case of an initialized allocator with a class-wide argument (see
+ -- Expand_Allocator_Expression).
+
+ if Ada_Version >= Ada_05
+ and then Is_Class_Wide_Type (Designated_Type (Typ))
+ then
+ declare
+ Exp_Typ : Entity_Id;
+
+ begin
+ if Nkind (E) = N_Qualified_Expression then
+ Exp_Typ := Etype (E);
+ elsif Nkind (E) = N_Subtype_Indication then
+ Exp_Typ := Entity (Subtype_Mark (Original_Node (E)));
+ else
+ Exp_Typ := Entity (E);
+ end if;
+
+ if Type_Access_Level (Exp_Typ) > Type_Access_Level (Typ) then
+ if In_Instance_Body then
+ Error_Msg_N ("?type in allocator has deeper level than" &
+ " designated class-wide type", E);
+ Error_Msg_N ("?Program_Error will be raised at run time", E);
+ Rewrite (N,
+ Make_Raise_Program_Error (Sloc (N),
+ Reason => PE_Accessibility_Check_Failed));
+ Set_Etype (N, Typ);
+ else
+ Error_Msg_N ("type in allocator has deeper level than" &
+ " designated class-wide type", E);
+ end if;
+ end if;
+ end;
+ end if;
+
-- Check for allocation from an empty storage pool
if No_Pool_Assigned (Typ) then
@@ -3126,8 +3186,8 @@ package body Sem_Res is
if Universal_Interpretation (N) = Universal_Integer then
-- A universal integer literal is resolved as standard integer
- -- except in the case of a fixed-point result, where we leave
- -- it as universal (to be handled by Exp_Fixd later on)
+ -- except in the case of a fixed-point result, where we leave it
+ -- as universal (to be handled by Exp_Fixd later on)
if Is_Fixed_Point_Type (T) then
Resolve (N, Universal_Integer);
@@ -3209,11 +3269,11 @@ package body Sem_Res is
Get_Next_Interp (Index, It);
end loop;
- -- Reanalyze the literal with the fixed type of the context.
- -- If context is Universal_Fixed, we are within a conversion,
- -- leave the literal as a universal real because there is no
- -- usable fixed type, and the target of the conversion plays
- -- no role in the resolution.
+ -- Reanalyze the literal with the fixed type of the context. If
+ -- context is Universal_Fixed, we are within a conversion, leave
+ -- the literal as a universal real because there is no usable
+ -- fixed type, and the target of the conversion plays no role in
+ -- the resolution.
declare
Op2 : Node_Id;
@@ -3466,11 +3526,11 @@ package body Sem_Res is
W : Node_Id;
begin
- -- The context imposes a unique interpretation with type Typ on
- -- a procedure or function call. Find the entity of the subprogram
- -- that yields the expected type, and propagate the corresponding
- -- formal constraints on the actuals. The caller has established
- -- that an interpretation exists, and emitted an error if not unique.
+ -- The context imposes a unique interpretation with type Typ on a
+ -- procedure or function call. Find the entity of the subprogram that
+ -- yields the expected type, and propagate the corresponding formal
+ -- constraints on the actuals. The caller has established that an
+ -- interpretation exists, and emitted an error if not unique.
-- First deal with the case of a call to an access-to-subprogram,
-- dereference made explicit in Analyze_Call.
@@ -3480,9 +3540,9 @@ package body Sem_Res is
Nam := Etype (Subp);
else
- -- Find the interpretation whose type (a subprogram type)
- -- has a return type that is compatible with the context.
- -- Analysis of the node has established that one exists.
+ -- Find the interpretation whose type (a subprogram type) has a
+ -- return type that is compatible with the context. Analysis of
+ -- the node has established that one exists.
Get_First_Interp (Subp, I, It);
Nam := Empty;
@@ -3507,18 +3567,18 @@ package body Sem_Res is
Resolve (Subp, Nam);
end if;
- -- For an indirect call, we always invalidate checks, since we
- -- do not know whether the subprogram is local or global. Yes
- -- we could do better here, e.g. by knowing that there are no
- -- local subprograms, but it does not seem worth the effort.
- -- Similarly, we kill al knowledge of current constant values.
+ -- For an indirect call, we always invalidate checks, since we do not
+ -- know whether the subprogram is local or global. Yes we could do
+ -- better here, e.g. by knowing that there are no local subprograms,
+ -- but it does not seem worth the effort. Similarly, we kill al
+ -- knowledge of current constant values.
Kill_Current_Values;
- -- If this is a procedure call which is really an entry call, do
- -- the conversion of the procedure call to an entry call. Protected
- -- operations use the same circuitry because the name in the call
- -- can be an arbitrary expression with special resolution rules.
+ -- If this is a procedure call which is really an entry call, do the
+ -- conversion of the procedure call to an entry call. Protected
+ -- operations use the same circuitry because the name in the call can be
+ -- an arbitrary expression with special resolution rules.
elsif Nkind (Subp) = N_Selected_Component
or else Nkind (Subp) = N_Indexed_Component
@@ -3589,12 +3649,12 @@ package body Sem_Res is
Error_Msg_N ("cannot call thread body directly", N);
end if;
- -- If the subprogram is not global, then kill all checks. This is
- -- a bit conservative, since in many cases we could do better, but
- -- it is not worth the effort. Similarly, we kill constant values.
- -- However we do not need to do this for internal entities (unless
- -- they are inherited user-defined subprograms), since they are not
- -- in the business of molesting global values.
+ -- If the subprogram is not global, then kill all checks. This is a bit
+ -- conservative, since in many cases we could do better, but it is not
+ -- worth the effort. Similarly, we kill constant values. However we do
+ -- not need to do this for internal entities (unless they are inherited
+ -- user-defined subprograms), since they are not in the business of
+ -- molesting global values.
if not Is_Library_Level_Entity (Nam)
and then (Comes_From_Source (Nam)
@@ -3604,43 +3664,47 @@ package body Sem_Res is
Kill_Current_Values;
end if;
- -- Check for call to obsolescent subprogram
+ -- Deal with call to obsolescent subprogram. Note that we always allow
+ -- such calls in the compiler itself and the run-time, since we assume
+ -- that we know what we are doing in such cases. For example, the calls
+ -- in Ada.Characters.Handling to its own obsolescent subprograms are
+ -- just fine.
- if Warn_On_Obsolescent_Feature
- and then Is_Subprogram (Nam)
- and then Is_Obsolescent (Nam)
- then
- Error_Msg_NE ("call to obsolescent subprogram&?", N, Nam);
+ if Is_Obsolescent (Nam) and then not GNAT_Mode then
+ Check_Restriction (No_Obsolescent_Features, N);
- -- Output additional warning if present
+ if Warn_On_Obsolescent_Feature then
+ Error_Msg_NE ("call to obsolescent subprogram&?", N, Nam);
- W := Obsolescent_Warning (Nam);
+ -- Output additional warning if present
- if Present (W) then
- Name_Buffer (1) := '|';
- Name_Buffer (2) := '?';
- Name_Len := 2;
+ W := Obsolescent_Warning (Nam);
- -- Add characters to message, protecting all of them
+ if Present (W) then
+ Name_Buffer (1) := '|';
+ Name_Buffer (2) := '?';
+ Name_Len := 2;
- for J in 1 .. String_Length (Strval (W)) loop
- Add_Char_To_Name_Buffer (''');
- Add_Char_To_Name_Buffer
- (Get_Character (Get_String_Char (Strval (W), J)));
- end loop;
+ -- Add characters to message, and output message
+
+ for J in 1 .. String_Length (Strval (W)) loop
+ Add_Char_To_Name_Buffer (''');
+ Add_Char_To_Name_Buffer
+ (Get_Character (Get_String_Char (Strval (W), J)));
+ end loop;
- Error_Msg_N (Name_Buffer (1 .. Name_Len), N);
+ Error_Msg_N (Name_Buffer (1 .. Name_Len), N);
+ end if;
end if;
end if;
- -- Check that a procedure call does not occur in the context
- -- of the entry call statement of a conditional or timed
- -- entry call. Note that the case of a call to a subprogram
- -- renaming of an entry will also be rejected. The test
- -- for N not being an N_Entry_Call_Statement is defensive,
- -- covering the possibility that the processing of entry
- -- calls might reach this point due to later modifications
- -- of the code above.
+ -- Check that a procedure call does not occur in the context of the
+ -- entry call statement of a conditional or timed entry call. Note that
+ -- the case of a call to a subprogram renaming of an entry will also be
+ -- rejected. The test for N not being an N_Entry_Call_Statement is
+ -- defensive, covering the possibility that the processing of entry
+ -- calls might reach this point due to later modifications of the code
+ -- above.
if Nkind (Parent (N)) = N_Entry_Call_Alternative
and then Nkind (N) /= N_Entry_Call_Statement
@@ -3662,34 +3726,33 @@ package body Sem_Res is
Error_Msg_N ("\cannot call operation that may modify it", N);
end if;
- -- Freeze the subprogram name if not in default expression. Note
- -- that we freeze procedure calls as well as function calls.
- -- Procedure calls are not frozen according to the rules (RM
- -- 13.14(14)) because it is impossible to have a procedure call to
- -- a non-frozen procedure in pure Ada, but in the code that we
- -- generate in the expander, this rule needs extending because we
- -- can generate procedure calls that need freezing.
+ -- Freeze the subprogram name if not in default expression. Note that we
+ -- freeze procedure calls as well as function calls. Procedure calls are
+ -- not frozen according to the rules (RM 13.14(14)) because it is
+ -- impossible to have a procedure call to a non-frozen procedure in pure
+ -- Ada, but in the code that we generate in the expander, this rule
+ -- needs extending because we can generate procedure calls that need
+ -- freezing.
if Is_Entity_Name (Subp) and then not In_Default_Expression then
Freeze_Expression (Subp);
end if;
- -- For a predefined operator, the type of the result is the type
- -- imposed by context, except for a predefined operation on universal
- -- fixed. Otherwise The type of the call is the type returned by the
- -- subprogram being called.
+ -- For a predefined operator, the type of the result is the type imposed
+ -- by context, except for a predefined operation on universal fixed.
+ -- Otherwise The type of the call is the type returned by the subprogram
+ -- being called.
if Is_Predefined_Op (Nam) then
if Etype (N) /= Universal_Fixed then
Set_Etype (N, Typ);
end if;
- -- If the subprogram returns an array type, and the context
- -- requires the component type of that array type, the node is
- -- really an indexing of the parameterless call. Resolve as such.
- -- A pathological case occurs when the type of the component is
- -- an access to the array type. In this case the call is truly
- -- ambiguous.
+ -- If the subprogram returns an array type, and the context requires the
+ -- component type of that array type, the node is really an indexing of
+ -- the parameterless call. Resolve as such. A pathological case occurs
+ -- when the type of the component is an access to the array type. In
+ -- this case the call is truly ambiguous.
elsif Needs_No_Actuals (Nam)
and then
@@ -3760,10 +3823,10 @@ package body Sem_Res is
Set_Is_Overloaded (Subp, False);
Set_Is_Overloaded (N, False);
- -- If we are calling the current subprogram from immediately within
- -- its body, then that is the case where we can sometimes detect
- -- cases of infinite recursion statically. Do not try this in case
- -- restriction No_Recursion is in effect anyway.
+ -- If we are calling the current subprogram from immediately within its
+ -- body, then that is the case where we can sometimes detect cases of
+ -- infinite recursion statically. Do not try this in case restriction
+ -- No_Recursion is in effect anyway.
Scop := Current_Scope;
@@ -4018,8 +4081,6 @@ package body Sem_Res is
T : Entity_Id;
begin
- Check_Direct_Boolean_Op (N);
-
-- If this is an intrinsic operation which is not predefined, use
-- the types of its declared arguments to resolve the possibly
-- overloaded operands. Otherwise the operands are unambiguous and
@@ -4059,6 +4120,7 @@ package body Sem_Res is
Check_Unset_Reference (R);
Generate_Operator_Reference (N, T);
Eval_Relational_Op (N);
+ Check_Direct_Boolean_Op (N);
end if;
end if;
end Resolve_Comparison_Op;
@@ -4213,7 +4275,7 @@ package body Sem_Res is
null;
else
Error_Msg_N
- ("Invalid use of subtype mark in expression or call", N);
+ ("invalid use of subtype mark in expression or call", N);
end if;
-- Check discriminant use if entity is discriminant in current scope,
@@ -4636,7 +4698,7 @@ package body Sem_Res is
elsif Ekind (Scope (Nam)) = E_Task_Type
and then not In_Open_Scopes (Scope (Nam))
then
- Error_Msg_N ("Task has no entry with this name", Entry_Name);
+ Error_Msg_N ("task has no entry with this name", Entry_Name);
end if;
end if;
@@ -4752,8 +4814,6 @@ package body Sem_Res is
-- Start of processing for Resolve_Equality_Op
begin
- Check_Direct_Boolean_Op (N);
-
Set_Etype (N, Base_Type (Typ));
Generate_Reference (T, N, ' ');
@@ -4822,6 +4882,8 @@ package body Sem_Res is
then
Error_Msg_NE ("cannot call abstract subprogram &!", N, Entity (N));
end if;
+
+ Check_Direct_Boolean_Op (N);
end if;
end Resolve_Equality_Op;
@@ -4837,20 +4899,35 @@ package body Sem_Res is
It : Interp;
begin
- -- Now that we know the type, check that this is not a
- -- dereference of an uncompleted type. Note that this
- -- is not entirely correct, because dereferences of
- -- private types are legal in default expressions.
- -- This consideration also applies to similar checks
- -- for allocators, qualified expressions, and type
- -- conversions. ???
-
- Check_Fully_Declared (Typ, N);
+ -- Now that we know the type, check that this is not dereference of an
+ -- uncompleted type. Note that this is not entirely correct, because
+ -- dereferences of private types are legal in default expressions. This
+ -- exception is taken care of in Check_Fully_Declared.
+
+ -- This consideration also applies to similar checks for allocators,
+ -- qualified expressions, and type conversions.
+
+ -- An additional exception concerns other per-object expressions that
+ -- are not directly related to component declarations, in particular
+ -- representation pragmas for tasks. These will be per-object
+ -- expressions if they depend on discriminants or some global entity.
+ -- If the task has access discriminants, the designated type may be
+ -- incomplete at the point the expression is resolved. This resolution
+ -- takes place within the body of the initialization procedure, where
+ -- the discriminant is replaced by its discriminal.
+
+ if Is_Entity_Name (Prefix (N))
+ and then Ekind (Entity (Prefix (N))) = E_In_Parameter
+ then
+ null;
+ else
+ Check_Fully_Declared (Typ, N);
+ end if;
if Is_Overloaded (P) then
- -- Use the context type to select the prefix that has the
- -- correct designated type.
+ -- Use the context type to select the prefix that has the correct
+ -- designated type.
Get_First_Interp (P, I, It);
while Present (It.Typ) loop
@@ -4863,13 +4940,12 @@ package body Sem_Res is
if Present (It.Typ) then
Resolve (P, It.Typ);
else
- -- If no interpretation covers the designated type of the
- -- prefix, this is the pathological case where not all
- -- implementations of the prefix allow the interpretation
- -- of the node as a call. Now that the expected type is known,
- -- Remove other interpretations from prefix, rewrite it as
- -- a call, and resolve again, so that the proper call node
- -- is generated.
+ -- If no interpretation covers the designated type of the prefix,
+ -- this is the pathological case where not all implementations of
+ -- the prefix allow the interpretation of the node as a call. Now
+ -- that the expected type is known, Remove other interpretations
+ -- from prefix, rewrite it as a call, and resolve again, so that
+ -- the proper call node is generated.
Get_First_Interp (P, I, It);
while Present (It.Typ) loop
@@ -4903,14 +4979,13 @@ package body Sem_Res is
Apply_Access_Check (N);
end if;
- -- If the designated type is a packed unconstrained array type,
- -- and the explicit dereference is not in the context of an
- -- attribute reference, then we must compute and set the actual
- -- subtype, since it is needed by Gigi. The reason we exclude
- -- the attribute case is that this is handled fine by Gigi, and
- -- in fact we use such attributes to build the actual subtype.
- -- We also exclude generated code (which builds actual subtypes
- -- directly if they are needed).
+ -- If the designated type is a packed unconstrained array type, and the
+ -- explicit dereference is not in the context of an attribute reference,
+ -- then we must compute and set the actual subtype, since it is needed
+ -- by Gigi. The reason we exclude the attribute case is that this is
+ -- handled fine by Gigi, and in fact we use such attributes to build the
+ -- actual subtype. We also exclude generated code (which builds actual
+ -- subtypes directly if they are needed).
if Is_Array_Type (Etype (N))
and then Is_Packed (Etype (N))
@@ -4921,9 +4996,9 @@ package body Sem_Res is
Set_Etype (N, Get_Actual_Subtype (N));
end if;
- -- Note: there is no Eval processing required for an explicit
- -- deference, because the type is known to be an allocators, and
- -- allocator expressions can never be static.
+ -- Note: there is no Eval processing required for an explicit deference,
+ -- because the type is known to be an allocators, and allocator
+ -- expressions can never be static.
end Resolve_Explicit_Dereference;
@@ -4940,8 +5015,8 @@ package body Sem_Res is
begin
if Is_Overloaded (Name) then
- -- Use the context type to select the prefix that yields the
- -- correct component type.
+ -- Use the context type to select the prefix that yields the correct
+ -- component type.
declare
I : Interp_Index;
@@ -4953,6 +5028,9 @@ package body Sem_Res is
begin
Get_First_Interp (P, I, It);
+ -- the task has access discriminants, the designated type may be
+ -- incomplete at the point the expression is resolved. This resolution
+ -- takes place within the body of the initialization proc
while Present (It.Typ) loop
if (Is_Array_Type (It.Typ)
@@ -5009,10 +5087,10 @@ package body Sem_Res is
Index := First_Index (Array_Type);
Expr := First (Expressions (N));
- -- The prefix may have resolved to a string literal, in which case
- -- its etype has a special representation. This is only possible
- -- currently if the prefix is a static concatenation, written in
- -- functional notation.
+ -- The prefix may have resolved to a string literal, in which case its
+ -- etype has a special representation. This is only possible currently
+ -- if the prefix is a static concatenation, written in functional
+ -- notation.
if Ekind (Array_Type) = E_String_Literal_Subtype then
Resolve (Expr, Standard_Positive);
@@ -5067,9 +5145,9 @@ package body Sem_Res is
Set_Entity (N, Op);
Set_Is_Overloaded (N, False);
- -- If the operand type is private, rewrite with suitable
- -- conversions on the operands and the result, to expose
- -- the proper underlying numeric type.
+ -- If the operand type is private, rewrite with suitable conversions on
+ -- the operands and the result, to expose the proper underlying numeric
+ -- type.
if Is_Private_Type (Typ) then
Arg1 := Unchecked_Convert_To (Btyp, Left_Opnd (N));
@@ -5167,11 +5245,9 @@ package body Sem_Res is
B_Typ : Entity_Id;
begin
- Check_Direct_Boolean_Op (N);
-
- -- Predefined operations on scalar types yield the base type. On
- -- the other hand, logical operations on arrays yield the type of
- -- the arguments (and the context).
+ -- Predefined operations on scalar types yield the base type. On the
+ -- other hand, logical operations on arrays yield the type of the
+ -- arguments (and the context).
if Is_Array_Type (Typ) then
B_Typ := Typ;
@@ -5211,6 +5287,7 @@ package body Sem_Res is
Set_Etype (N, B_Typ);
Generate_Operator_Reference (N, B_Typ);
Eval_Logical_Op (N);
+ Check_Direct_Boolean_Op (N);
end Resolve_Logical_Op;
---------------------------
@@ -5269,8 +5346,8 @@ package body Sem_Res is
procedure Resolve_Null (N : Node_Id; Typ : Entity_Id) is
begin
- -- Handle restriction against anonymous null access values
- -- This restriction can be turned off using -gnatdh.
+ -- Handle restriction against anonymous null access values This
+ -- restriction can be turned off using -gnatdh.
-- Ada 2005 (AI-231): Remove restriction
@@ -5417,9 +5494,9 @@ package body Sem_Res is
Explain_Limited_Type (Btyp, N);
end if;
- -- If the operands are themselves concatenations, resolve them as
- -- such directly. This removes several layers of recursion and allows
- -- GNAT to handle larger multiple concatenations.
+ -- If the operands are themselves concatenations, resolve them as such
+ -- directly. This removes several layers of recursion and allows GNAT to
+ -- handle larger multiple concatenations.
if Nkind (Op1) = N_Op_Concat
and then not Is_Array_Type (Component_Type (Typ))
@@ -5468,8 +5545,8 @@ package body Sem_Res is
begin
-- Catch attempts to do fixed-point exponentation with universal
- -- operands, which is a case where the illegality is not caught
- -- during normal operator analysis.
+ -- operands, which is a case where the illegality is not caught during
+ -- normal operator analysis.
if Is_Fixed_Point_Type (Typ) and then Comes_From_Source (N) then
Error_Msg_N ("exponentiation not available for fixed point", N);
@@ -5560,9 +5637,9 @@ package body Sem_Res is
-- Start of processing for Resolve_Op_Not
begin
- -- Predefined operations on scalar types yield the base type. On
- -- the other hand, logical operations on arrays yield the type of
- -- the arguments (and the context).
+ -- Predefined operations on scalar types yield the base type. On the
+ -- other hand, logical operations on arrays yield the type of the
+ -- arguments (and the context).
if Is_Array_Type (Typ) then
B_Typ := Typ;
@@ -5669,12 +5746,12 @@ package body Sem_Res is
Check_Unset_Reference (H);
-- We have to check the bounds for being within the base range as
- -- required for a non-static context. Normally this is automatic
- -- and done as part of evaluating expressions, but the N_Range
- -- node is an exception, since in GNAT we consider this node to
- -- be a subexpression, even though in Ada it is not. The circuit
- -- in Sem_Eval could check for this, but that would put the test
- -- on the main evaluation path for expressions.
+ -- required for a non-static context. Normally this is automatic and
+ -- done as part of evaluating expressions, but the N_Range node is an
+ -- exception, since in GNAT we consider this node to be a subexpression,
+ -- even though in Ada it is not. The circuit in Sem_Eval could check for
+ -- this, but that would put the test on the main evaluation path for
+ -- expressions.
Check_Non_Static_Context (L);
Check_Non_Static_Context (H);
@@ -5756,8 +5833,6 @@ package body Sem_Res is
Realval => Small_Value (Typ) * Cint));
Set_Is_Static_Expression (N, Stat);
-
-
end if;
-- In all cases, set the corresponding integer field
@@ -6389,8 +6464,8 @@ package body Sem_Res is
-----------------------------
procedure Resolve_Type_Conversion (N : Node_Id; Typ : Entity_Id) is
- Target_Type : constant Entity_Id := Etype (N);
- Conv_OK : constant Boolean := Conversion_OK (N);
+ Conv_OK : constant Boolean := Conversion_OK (N);
+ Target_Type : Entity_Id := Etype (N);
Operand : Node_Id;
Opnd_Type : Entity_Id;
Rop : Node_Id;
@@ -6525,6 +6600,43 @@ package body Sem_Res is
("?useless conversion, & has this type", N, Entity (Orig_N));
end if;
end if;
+
+ -- Ada 2005 (AI-251): Handle conversions to abstract interface types
+
+ if Ada_Version >= Ada_05 then
+ if Is_Access_Type (Target_Type) then
+ Target_Type := Directly_Designated_Type (Target_Type);
+ end if;
+
+ if Is_Class_Wide_Type (Target_Type) then
+ Target_Type := Etype (Target_Type);
+ end if;
+
+ if Is_Interface (Target_Type) then
+ if Is_Class_Wide_Type (Opnd_Type) then
+ Opnd_Type := Etype (Opnd_Type);
+ end if;
+
+ if not Interface_Present_In_Ancestor
+ (Typ => Opnd_Type,
+ Iface => Target_Type)
+ then
+ if Nkind (Operand) = N_Attribute_Reference then
+ Error_Msg_Name_1 := Chars (Prefix (Operand));
+ else
+ Error_Msg_Name_1 := Chars (Operand);
+ end if;
+
+ Error_Msg_Name_2 := Chars (Target_Type);
+ Error_Msg_NE
+ ("(Ada 2005) % does not implement interface %",
+ Operand, Target_Type);
+
+ else
+ Expand_Interface_Conversion (N);
+ end if;
+ end if;
+ end if;
end Resolve_Type_Conversion;
----------------------
@@ -6998,6 +7110,13 @@ package body Sem_Res is
return
Conversion_Check (False,
"downward conversion of tagged objects not allowed");
+
+ -- Ada 2005 (AI-251): The conversion of a tagged type to an
+ -- abstract interface type is always valid
+
+ elsif Is_Interface (Target_Type) then
+ return True;
+
else
Error_Msg_NE
("invalid tagged conversion, not compatible with}",
@@ -7162,6 +7281,94 @@ package body Sem_Res is
return True;
+ -- Ada 2005 (AI-251)
+
+ elsif (Ekind (Target_Type) = E_General_Access_Type
+ or else Ekind (Target_Type) = E_Anonymous_Access_Type)
+ and then Is_Interface (Directly_Designated_Type (Target_Type))
+ then
+ -- Check the static accessibility rule of 4.6(17). Note that the
+ -- check is not enforced when within an instance body, since the RM
+ -- requires such cases to be caught at run time.
+
+ if Ekind (Target_Type) /= E_Anonymous_Access_Type then
+ if Type_Access_Level (Opnd_Type) >
+ Type_Access_Level (Target_Type)
+ then
+ -- In an instance, this is a run-time check, but one we know
+ -- will fail, so generate an appropriate warning. The raise
+ -- will be generated by Expand_N_Type_Conversion.
+
+ if In_Instance_Body then
+ Error_Msg_N
+ ("?cannot convert local pointer to non-local access type",
+ Operand);
+ Error_Msg_N
+ ("?Program_Error will be raised at run time", Operand);
+
+ else
+ Error_Msg_N
+ ("cannot convert local pointer to non-local access type",
+ Operand);
+ return False;
+ end if;
+
+ -- Special accessibility checks are needed in the case of access
+ -- discriminants declared for a limited type.
+
+ elsif Ekind (Opnd_Type) = E_Anonymous_Access_Type
+ and then not Is_Local_Anonymous_Access (Opnd_Type)
+ then
+ -- When the operand is a selected access discriminant the check
+ -- needs to be made against the level of the object denoted by
+ -- the prefix of the selected name. (Object_Access_Level
+ -- handles checking the prefix of the operand for this case.)
+
+ if Nkind (Operand) = N_Selected_Component
+ and then Object_Access_Level (Operand)
+ > Type_Access_Level (Target_Type)
+ then
+ -- In an instance, this is a run-time check, but one we
+ -- know will fail, so generate an appropriate warning.
+ -- The raise will be generated by Expand_N_Type_Conversion.
+
+ if In_Instance_Body then
+ Error_Msg_N
+ ("?cannot convert access discriminant to non-local" &
+ " access type", Operand);
+ Error_Msg_N
+ ("?Program_Error will be raised at run time", Operand);
+
+ else
+ Error_Msg_N
+ ("cannot convert access discriminant to non-local" &
+ " access type", Operand);
+ return False;
+ end if;
+ end if;
+
+ -- The case of a reference to an access discriminant from
+ -- within a limited type declaration (which will appear as
+ -- a discriminal) is always illegal because the level of the
+ -- discriminant is considered to be deeper than any (namable)
+ -- access type.
+
+ if Is_Entity_Name (Operand)
+ and then not Is_Local_Anonymous_Access (Opnd_Type)
+ and then (Ekind (Entity (Operand)) = E_In_Parameter
+ or else Ekind (Entity (Operand)) = E_Constant)
+ and then Present (Discriminal_Link (Entity (Operand)))
+ then
+ Error_Msg_N
+ ("discriminant has deeper accessibility level than target",
+ Operand);
+ return False;
+ end if;
+ end if;
+ end if;
+
+ return True;
+
elsif (Ekind (Target_Type) = E_General_Access_Type
or else Ekind (Target_Type) = E_Anonymous_Access_Type)
and then
@@ -7181,11 +7388,13 @@ package body Sem_Res is
return False;
end if;
- -- Check the static accessibility rule of 4.6(17). Note that
- -- the check is not enforced when within an instance body, since
- -- the RM requires such cases to be caught at run time.
+ -- Check the static accessibility rule of 4.6(17). Note that the
+ -- check is not enforced when within an instance body, since the RM
+ -- requires such cases to be caught at run time.
- if Ekind (Target_Type) /= E_Anonymous_Access_Type then
+ if Ekind (Target_Type) /= E_Anonymous_Access_Type
+ or else Is_Local_Anonymous_Access (Target_Type)
+ then
if Type_Access_Level (Opnd_Type)
> Type_Access_Level (Target_Type)
then
@@ -7207,13 +7416,17 @@ package body Sem_Res is
return False;
end if;
- elsif Ekind (Opnd_Type) = E_Anonymous_Access_Type then
+ -- Special accessibility checks are needed in the case of access
+ -- discriminants declared for a limited type.
+
+ elsif Ekind (Opnd_Type) = E_Anonymous_Access_Type
+ and then not Is_Local_Anonymous_Access (Opnd_Type)
+ then
- -- When the operand is a selected access discriminant
- -- the check needs to be made against the level of the
- -- object denoted by the prefix of the selected name.
- -- (Object_Access_Level handles checking the prefix
- -- of the operand for this case.)
+ -- When the operand is a selected access discriminant the check
+ -- needs to be made against the level of the object denoted by
+ -- the prefix of the selected name. (Object_Access_Level
+ -- handles checking the prefix of the operand for this case.)
if Nkind (Operand) = N_Selected_Component
and then Object_Access_Level (Operand)
@@ -7238,11 +7451,11 @@ package body Sem_Res is
end if;
end if;
- -- The case of a reference to an access discriminant
- -- from within a type declaration (which will appear
- -- as a discriminal) is always illegal because the
- -- level of the discriminant is considered to be
- -- deeper than any (namable) access type.
+ -- The case of a reference to an access discriminant from
+ -- within a limited type declaration (which will appear as
+ -- a discriminal) is always illegal because the level of the
+ -- discriminant is considered to be deeper than any (namable)
+ -- access type.
if Is_Entity_Name (Operand)
and then (Ekind (Entity (Operand)) = E_In_Parameter
diff --git a/gcc/ada/sem_type.adb b/gcc/ada/sem_type.adb
index 3411194aa18..93a692e5e9c 100644
--- a/gcc/ada/sem_type.adb
+++ b/gcc/ada/sem_type.adb
@@ -28,6 +28,7 @@ with Atree; use Atree;
with Alloc;
with Debug; use Debug;
with Einfo; use Einfo;
+with Elists; use Elists;
with Errout; use Errout;
with Lib; use Lib;
with Opt; use Opt;
@@ -529,7 +530,7 @@ package body Sem_Type is
end if;
end loop;
- -- On exit, we know that current homograph is not hidden.
+ -- On exit, we know that current homograph is not hidden
Add_One_Interp (N, H, Etype (H));
@@ -686,6 +687,58 @@ package body Sem_Type is
then
return True;
+ -- Ada 2005 (AI-345): A class-wide abstract interface type T1 covers a
+ -- task_type or protected_type implementing T1
+
+ elsif Ada_Version >= Ada_05
+ and then Is_Class_Wide_Type (T1)
+ and then Is_Interface (Etype (T1))
+ and then Is_Concurrent_Type (T2)
+ and then Interface_Present_In_Ancestor (
+ Typ => Corresponding_Record_Type (Base_Type (T2)),
+ Iface => Etype (T1))
+ then
+ return True;
+
+ -- Ada 2005 (AI-251): A class-wide abstract interface type T1 covers an
+ -- object T2 implementing T1
+
+ elsif Ada_Version >= Ada_05
+ and then Is_Class_Wide_Type (T1)
+ and then Is_Interface (Etype (T1))
+ and then Is_Tagged_Type (T2)
+ then
+ if Interface_Present_In_Ancestor (Typ => T2,
+ Iface => Etype (T1))
+ then
+ return True;
+
+ elsif Present (Abstract_Interfaces (T2)) then
+
+ -- Ada 2005 (AI-251): A class-wide abstract interface type T1
+ -- covers an object T2 that implements a direct derivation of T1.
+
+ declare
+ E : Elmt_Id := First_Elmt (Abstract_Interfaces (T2));
+ begin
+ while Present (E) loop
+ if Is_Ancestor (Etype (T1), Node (E)) then
+ return True;
+ end if;
+
+ Next_Elmt (E);
+ end loop;
+ end;
+
+ -- We should also check the case in which T1 is an ancestor of
+ -- some implemented interface???
+
+ return False;
+
+ else
+ return False;
+ end if;
+
-- In a dispatching call the actual may be class-wide
elsif Is_Class_Wide_Type (T2)
@@ -1629,6 +1682,13 @@ package body Sem_Type is
then
return
Covers (Typ, Etype (N))
+
+ -- Ada 2005 (AI-345)
+
+ or else
+ (Is_Concurrent_Type (Etype (N))
+ and then Covers (Typ, Corresponding_Record_Type (Etype (N))))
+
or else
(not Is_Tagged_Type (Typ)
and then Ekind (Typ) /= E_Anonymous_Access_Type
@@ -1641,6 +1701,14 @@ package body Sem_Type is
and then
(Scope (It.Nam) /= Standard_Standard
or else not Is_Invisible_Operator (N, Base_Type (Typ))))
+
+ -- Ada 2005 (AI-345)
+
+ or else
+ (Is_Concurrent_Type (It.Typ)
+ and then Covers (Typ, Corresponding_Record_Type
+ (Etype (It.Typ))))
+
or else (not Is_Tagged_Type (Typ)
and then Ekind (Typ) /= E_Anonymous_Access_Type
and then Covers (It.Typ, Typ))
@@ -1694,6 +1762,72 @@ package body Sem_Type is
Headers := (others => No_Entry);
end Init_Interp_Tables;
+ -----------------------------------
+ -- Interface_Present_In_Ancestor --
+ -----------------------------------
+
+ function Interface_Present_In_Ancestor
+ (Typ : Entity_Id;
+ Iface : Entity_Id) return Boolean
+ is
+ AI : Entity_Id;
+ E : Entity_Id;
+ Elmt : Elmt_Id;
+
+ begin
+ if Is_Access_Type (Typ) then
+ E := Etype (Directly_Designated_Type (Typ));
+ else
+ E := Typ;
+ end if;
+
+ if Is_Concurrent_Type (E) then
+ E := Corresponding_Record_Type (E);
+ end if;
+
+ if Is_Class_Wide_Type (E) then
+ E := Etype (E);
+ end if;
+
+ if E = Iface then
+ return True;
+ end if;
+
+ loop
+ if Present (Abstract_Interfaces (E))
+ and then Abstract_Interfaces (E) /= Empty_List_Or_Node -- ????
+ and then not Is_Empty_Elmt_List (Abstract_Interfaces (E))
+ then
+ Elmt := First_Elmt (Abstract_Interfaces (E));
+
+ while Present (Elmt) loop
+ AI := Node (Elmt);
+
+ if AI = Iface or else Is_Ancestor (Iface, AI) then
+ return True;
+ end if;
+
+ Next_Elmt (Elmt);
+ end loop;
+ end if;
+
+ exit when Etype (E) = E;
+
+ -- Check if the current type is a direct derivation of the
+ -- interface
+
+ if Etype (E) = Iface then
+ return True;
+ end if;
+
+ -- Climb to the immediate ancestor
+
+ E := Etype (E);
+ end loop;
+
+ return False;
+ end Interface_Present_In_Ancestor;
+
---------------------
-- Intersect_Types --
---------------------
@@ -1766,6 +1900,16 @@ package body Sem_Type is
elsif Nkind (Parent (L)) = N_Range then
Error_Msg_N ("incompatible types given in constraint", Parent (L));
+ -- Ada 2005 (AI-251): Complete the error notification
+
+ elsif Is_Class_Wide_Type (Etype (R))
+ and then Is_Interface (Etype (Class_Wide_Type (Etype (R))))
+ then
+ Error_Msg_Name_1 := Chars (L);
+ Error_Msg_Name_2 := Chars (Etype (Class_Wide_Type (Etype (R))));
+ Error_Msg_NE ("(Ada 2005) % does not implement interface %",
+ L, Etype (Class_Wide_Type (Etype (R))));
+
else
Error_Msg_N ("incompatible types", Parent (L));
end if;
@@ -1930,7 +2074,7 @@ package body Sem_Type is
Headers (Hash (N)) := Interp_Map.Last;
else
- -- Place node at end of chain, or locate its previous entry.
+ -- Place node at end of chain, or locate its previous entry
loop
if Interp_Map.Table (Map_Ptr).Node = N then
@@ -1949,7 +2093,7 @@ package body Sem_Type is
end if;
end loop;
- -- Chain the new node.
+ -- Chain the new node
Interp_Map.Increment_Last;
Interp_Map.Table (Map_Ptr).Next := Interp_Map.Last;
@@ -2259,8 +2403,29 @@ package body Sem_Type is
elsif T2 = Any_Modular and then Is_Modular_Integer_Type (T1) then
return T1;
+ -- ----------------------------------------------------------
-- Special cases for equality operators (all other predefined
-- operators can never apply to tagged types)
+ -- ----------------------------------------------------------
+
+ -- Ada 2005 (AI-251): T1 and T2 are class-wide types, and T2 is an
+ -- interface
+
+ elsif Is_Class_Wide_Type (T1)
+ and then Is_Class_Wide_Type (T2)
+ and then Is_Interface (Etype (T2))
+ then
+ return T1;
+
+ -- Ada 2005 (AI-251): T1 is a concrete type that implements the
+ -- class-wide interface T2
+
+ elsif Is_Class_Wide_Type (T2)
+ and then Is_Interface (Etype (T2))
+ and then Interface_Present_In_Ancestor (Typ => T1,
+ Iface => Etype (T2))
+ then
+ return T1;
elsif Is_Class_Wide_Type (T1)
and then Is_Ancestor (Root_Type (T1), T2)
@@ -2302,7 +2467,7 @@ package body Sem_Type is
then
return T1;
- -- If none of the above cases applies, types are not compatible.
+ -- If none of the above cases applies, types are not compatible
else
return Any_Type;
@@ -2314,11 +2479,11 @@ package body Sem_Type is
-----------------------
-- In addition to booleans and arrays of booleans, we must include
- -- aggregates as valid boolean arguments, because in the first pass
- -- of resolution their components are not examined. If it turns out not
- -- to be an aggregate of booleans, this will be diagnosed in Resolve.
- -- Any_Composite must be checked for prior to the array type checks
- -- because Any_Composite does not have any associated indexes.
+ -- aggregates as valid boolean arguments, because in the first pass of
+ -- resolution their components are not examined. If it turns out not to be
+ -- an aggregate of booleans, this will be diagnosed in Resolve.
+ -- Any_Composite must be checked for prior to the array type checks because
+ -- Any_Composite does not have any associated indexes.
function Valid_Boolean_Arg (T : Entity_Id) return Boolean is
begin
diff --git a/gcc/ada/sem_type.ads b/gcc/ada/sem_type.ads
index d4d3c472c86..8cf54fdc1f2 100644
--- a/gcc/ada/sem_type.ads
+++ b/gcc/ada/sem_type.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2004 Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2005 Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -203,6 +203,13 @@ package Sem_Type is
-- matches the signature of the operator, and is declared in an
-- open scope, or in the scope of the result type.
+ function Interface_Present_In_Ancestor
+ (Typ : Entity_Id;
+ Iface : Entity_Id) return Boolean;
+ -- Ada 2005 (AI-251): Typ must be a tagged record type/subtype and Iface
+ -- must be an abstract interface type. This function is used to check if
+ -- some ancestor of Typ implements Iface.
+
function Intersect_Types (L, R : Node_Id) return Entity_Id;
-- Find the common interpretation to two analyzed nodes. If one of the
-- interpretations is universal, choose the non-universal one. If either