aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ada/a-tags.adb248
-rw-r--r--gcc/ada/a-tags.ads120
-rw-r--r--gcc/ada/exp_ch3.adb636
-rw-r--r--gcc/ada/rtsfind.ads6
4 files changed, 817 insertions, 193 deletions
diff --git a/gcc/ada/a-tags.adb b/gcc/ada/a-tags.adb
index a8d6cd0..cfce834 100644
--- a/gcc/ada/a-tags.adb
+++ b/gcc/ada/a-tags.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2005, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2006, 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- --
@@ -34,6 +34,8 @@
with Ada.Exceptions;
with System.HTable;
with System.Storage_Elements; use System.Storage_Elements;
+with System.WCh_Con; use System.WCh_Con;
+with System.WCh_StW; use System.WCh_StW;
pragma Elaborate_All (System.HTable);
@@ -42,6 +44,10 @@ package body Ada.Tags is
-- Structure of the GNAT Primary Dispatch Table
-- +----------------------+
+-- | table of |
+-- : predefined primitive :
+-- | ops pointers |
+-- +----------------------+
-- | Signature |
-- +----------------------+
-- | Tagged_Kind |
@@ -66,8 +72,6 @@ package body Ada.Tags is
-- +-------------------+
-- | num prim ops |
-- +-------------------+
--- | num interfaces |
--- +-------------------+
-- | Ifaces_Table_Ptr --> Interface Data
-- +-------------------+ +------------+
-- Select Specific Data <---- SSD_Ptr | | table |
@@ -84,6 +88,10 @@ package body Ada.Tags is
-- Structure of the GNAT Secondary Dispatch Table
-- +-----------------------+
+-- | table of |
+-- : predefined primitive :
+-- | ops pointers |
+-- +-----------------------+
-- | Signature |
-- +-----------------------+
-- | Tagged_Kind |
@@ -126,9 +134,9 @@ package body Ada.Tags is
-- Field_Type_Ptr in A-Tags.ads.
-- Define the specifications of Get_<Field_Name> and Set_<Field_Name>
- -- in A-Tags.ads.
+ -- in a-tags.ads.
- -- Update the GNAT Dispatch Table structure in A-Tags.adb
+ -- Update the GNAT Dispatch Table structure in a-tags.adb
-- Provide bodies to the Get_<Field_Name> and Set_<Field_Name> routines.
-- The profile of a Get_<Field_Name> routine should resemble:
@@ -184,9 +192,16 @@ package body Ada.Tags is
-- Declarations for the table of interfaces
type Interface_Data_Element is record
- Iface_Tag : Tag;
- Offset : System.Storage_Elements.Storage_Offset;
+ Iface_Tag : Tag;
+ Static_Offset_To_Top : Boolean;
+ Offset_To_Top_Value : System.Storage_Elements.Storage_Offset;
+ Offset_To_Top_Func : System.Address;
end record;
+ -- If some ancestor of the tagged type has discriminants the field
+ -- Static_Offset_To_Top is False and the field Offset_To_Top_Func
+ -- is used to store the address of the function generated by the
+ -- expander which provides this value; otherwise Static_Offset_To_Top
+ -- is True and such value is stored in the Offset_To_Top_Value field.
type Interfaces_Array is
array (Natural range <>) of Interface_Data_Element;
@@ -322,9 +337,6 @@ package body Ada.Tags is
-- only to declare the corresponding access type.
end record;
- -- Run-time check types and subprograms: These subprograms are used only
- -- when the run-time is compiled with assertions enabled.
-
type Signature_Type is
(Must_Be_Primary_DT,
Must_Be_Secondary_DT,
@@ -356,6 +368,17 @@ package body Ada.Tags is
function To_Acc_Size is new Unchecked_Conversion (System.Address, Acc_Size);
-- The profile of the implicitly defined _size primitive
+ type Offset_To_Top_Function_Ptr is
+ access function (This : System.Address)
+ return System.Storage_Elements.Storage_Offset;
+ -- Type definition used to call the function that is generated by the
+ -- expander in case of tagged types with discriminants that have secondary
+ -- dispatch tables. This function provides the Offset_To_Top value in this
+ -- specific case.
+
+ function To_Offset_To_Top_Function_Ptr is
+ new Unchecked_Conversion (System.Address, Offset_To_Top_Function_Ptr);
+
type Storage_Offset_Ptr is access System.Storage_Elements.Storage_Offset;
function To_Storage_Offset_Ptr is
@@ -365,11 +388,6 @@ package body Ada.Tags is
-- Local Subprograms --
-----------------------
- function Check_Index
- (T : Tag;
- Index : Natural) return Boolean;
- -- Check that Index references a valid entry of the dispatch table of T
-
function Check_Signature (T : Tag; Kind : Signature_Type) return Boolean;
-- Check that the signature of T is valid and corresponds with the subset
-- specified by the signature Kind.
@@ -489,20 +507,6 @@ package body Ada.Tags is
end HTable_Subprograms;
- -----------------
- -- Check_Index --
- -----------------
-
- function Check_Index
- (T : Tag;
- Index : Natural) return Boolean
- is
- Max_Entries : constant Natural := Get_Num_Prim_Ops (T);
-
- begin
- return Index /= 0 and then Index <= Max_Entries;
- end Check_Index;
-
---------------------
-- Check_Signature --
---------------------
@@ -624,7 +628,7 @@ package body Ada.Tags is
pragma Assert
(Check_Signature (T, Must_Be_Interface));
- Obj_Base := This - Offset_To_Top (Curr_DT);
+ Obj_Base := This - Offset_To_Top (This);
Obj_DT := To_Tag_Ptr (Obj_Base).all;
pragma Assert
@@ -636,8 +640,25 @@ package body Ada.Tags is
if Iface_Table /= null then
for Id in 1 .. Iface_Table.Nb_Ifaces loop
if Iface_Table.Table (Id).Iface_Tag = T then
- Obj_Base := Obj_Base + Iface_Table.Table (Id).Offset;
- Obj_DT := To_Tag_Ptr (Obj_Base).all;
+
+ -- Case of Static value of Offset_To_Top
+
+ if Iface_Table.Table (Id).Static_Offset_To_Top then
+ Obj_Base :=
+ Obj_Base + Iface_Table.Table (Id).Offset_To_Top_Value;
+
+ -- Otherwise we call the function generated by the expander
+ -- to provide us with this value
+
+ else
+ Obj_Base :=
+ Obj_Base +
+ To_Offset_To_Top_Function_Ptr
+ (Iface_Table.Table (Id).Offset_To_Top_Func).all
+ (Obj_Base);
+ end if;
+
+ Obj_DT := To_Tag_Ptr (Obj_Base).all;
pragma Assert
(Check_Signature (Obj_DT, Must_Be_Secondary_DT));
@@ -680,7 +701,7 @@ package body Ada.Tags is
pragma Assert
(Check_Signature (T, Must_Be_Primary_Or_Interface));
- Obj_Base := This - Offset_To_Top (Curr_DT);
+ Obj_Base := This - Offset_To_Top (This);
Obj_DT := To_Tag_Ptr (Obj_Base).all;
pragma Assert
@@ -782,12 +803,10 @@ package body Ada.Tags is
---------------------
function Get_Entry_Index (T : Tag; Position : Positive) return Positive is
- Index : constant Integer := Position - Default_Prim_Op_Count;
begin
pragma Assert (Check_Signature (T, Must_Be_Primary_DT));
- pragma Assert (Check_Index (T, Position));
- pragma Assert (Index > 0);
- return SSD (T).SSD_Table (Index).Index;
+ pragma Assert (Position <= Get_Num_Prim_Ops (T));
+ return SSD (T).SSD_Table (Position).Index;
end Get_Entry_Index;
----------------------
@@ -815,6 +834,21 @@ package body Ada.Tags is
end if;
end Get_Num_Prim_Ops;
+ --------------------------------
+ -- Get_Predef_Prim_Op_Address --
+ --------------------------------
+
+ function Get_Predefined_Prim_Op_Address
+ (T : Tag;
+ Position : Positive) return System.Address
+ is
+ Prim_Ops_DT : constant Tag := To_Tag (To_Address (T) - DT_Prologue_Size);
+ begin
+ pragma Assert (Check_Signature (T, Must_Be_Primary_Or_Secondary_DT));
+ pragma Assert (Position <= Default_Prim_Op_Count);
+ return Prim_Ops_DT.Prims_Ptr (Position);
+ end Get_Predefined_Prim_Op_Address;
+
-------------------------
-- Get_Prim_Op_Address --
-------------------------
@@ -825,7 +859,7 @@ package body Ada.Tags is
is
begin
pragma Assert (Check_Signature (T, Must_Be_Primary_Or_Secondary_DT));
- pragma Assert (Check_Index (T, Position));
+ pragma Assert (Position <= Get_Num_Prim_Ops (T));
return T.Prims_Ptr (Position);
end Get_Prim_Op_Address;
@@ -837,12 +871,10 @@ package body Ada.Tags is
(T : Tag;
Position : Positive) return Prim_Op_Kind
is
- Index : constant Integer := Position - Default_Prim_Op_Count;
begin
pragma Assert (Check_Signature (T, Must_Be_Primary_DT));
- pragma Assert (Check_Index (T, Position));
- pragma Assert (Index > 0);
- return SSD (T).SSD_Table (Index).Kind;
+ pragma Assert (Position <= Get_Num_Prim_Ops (T));
+ return SSD (T).SSD_Table (Position).Kind;
end Get_Prim_Op_Kind;
----------------------
@@ -853,12 +885,10 @@ package body Ada.Tags is
(T : Tag;
Position : Positive) return Positive
is
- Index : constant Integer := Position - Default_Prim_Op_Count;
begin
pragma Assert (Check_Signature (T, Must_Be_Secondary_DT));
- pragma Assert (Check_Index (T, Position));
- pragma Assert (Index > 0);
- return OSD (T).OSD_Table (Index);
+ pragma Assert (Position <= Get_Num_Prim_Ops (T));
+ return OSD (T).OSD_Table (Position);
end Get_Offset_Index;
-------------------
@@ -898,6 +928,9 @@ package body Ada.Tags is
----------------
procedure Inherit_DT (Old_T : Tag; New_T : Tag; Entry_Count : Natural) is
+ Old_T_Prim_Ops : Tag;
+ New_T_Prim_Ops : Tag;
+ Size : Positive;
begin
pragma Assert (Check_Signature (Old_T, Must_Be_Primary_Or_Secondary_DT));
pragma Assert (Check_Signature (New_T, Must_Be_Primary_Or_Secondary_DT));
@@ -906,6 +939,11 @@ package body Ada.Tags is
if Old_T /= null then
New_T.Prims_Ptr (1 .. Entry_Count) :=
Old_T.Prims_Ptr (1 .. Entry_Count);
+ Old_T_Prim_Ops := To_Tag (To_Address (Old_T) - DT_Prologue_Size);
+ New_T_Prim_Ops := To_Tag (To_Address (New_T) - DT_Prologue_Size);
+ Size := Default_Prim_Op_Count;
+ New_T_Prim_Ops.Prims_Ptr (1 .. Size) :=
+ Old_T_Prim_Ops.Prims_Ptr (1 .. Size);
end if;
end Inherit_DT;
@@ -1034,12 +1072,18 @@ package body Ada.Tags is
-------------------
function Offset_To_Top
- (T : Tag) return System.Storage_Elements.Storage_Offset
+ (This : System.Address) return System.Storage_Elements.Storage_Offset
is
- Offset_To_Top : constant Storage_Offset_Ptr :=
- To_Storage_Offset_Ptr
- (To_Address (T) - K_Offset_To_Top);
+ Curr_DT : constant Tag := To_Tag_Ptr (This).all;
+ Offset_To_Top : Storage_Offset_Ptr;
begin
+ Offset_To_Top := To_Storage_Offset_Ptr
+ (To_Address (Curr_DT) - K_Offset_To_Top);
+
+ if Offset_To_Top.all = SSE.Storage_Offset'Last then
+ Offset_To_Top := To_Storage_Offset_Ptr (This + Tag_Size);
+ end if;
+
return Offset_To_Top.all;
end Offset_To_Top;
@@ -1066,14 +1110,18 @@ package body Ada.Tags is
Parent_Tag : Tag;
-- The tag of the parent type through the dispatch table
+ Prim_Ops_DT : Tag;
+ -- The table of primitive operations of the parent
+
F : Acc_Size;
-- Access to the _size primitive of the parent. We assume that it is
-- always in the first slot of the dispatch table.
begin
pragma Assert (Check_Signature (T, Must_Be_Primary_DT));
- Parent_Tag := TSD (T).Tags_Table (1);
- F := To_Acc_Size (Parent_Tag.Prims_Ptr (1));
+ Parent_Tag := TSD (T).Tags_Table (1);
+ Prim_Ops_DT := To_Tag (To_Address (Parent_Tag) - DT_Prologue_Size);
+ F := To_Acc_Size (Prim_Ops_DT.Prims_Ptr (1));
-- Here we compute the size of the _parent field of the object
@@ -1156,12 +1204,10 @@ package body Ada.Tags is
Position : Positive;
Value : Positive)
is
- Index : constant Integer := Position - Default_Prim_Op_Count;
begin
pragma Assert (Check_Signature (T, Must_Be_Primary_DT));
- pragma Assert (Check_Index (T, Position));
- pragma Assert (Index > 0);
- SSD (T).SSD_Table (Index).Index := Value;
+ pragma Assert (Position <= Get_Num_Prim_Ops (T));
+ SSD (T).SSD_Table (Position).Index := Value;
end Set_Entry_Index;
-----------------------
@@ -1219,12 +1265,10 @@ package body Ada.Tags is
Position : Positive;
Value : Positive)
is
- Index : constant Integer := Position - Default_Prim_Op_Count;
begin
pragma Assert (Check_Signature (T, Must_Be_Secondary_DT));
- pragma Assert (Check_Index (T, Position));
- pragma Assert (Index > 0);
- OSD (T).OSD_Table (Index) := Value;
+ pragma Assert (Position <= Get_Num_Prim_Ops (T));
+ OSD (T).OSD_Table (Position) := Value;
end Set_Offset_Index;
-----------------------
@@ -1234,7 +1278,9 @@ package body Ada.Tags is
procedure Set_Offset_To_Top
(This : System.Address;
Interface_T : Tag;
- Offset_Value : System.Storage_Elements.Storage_Offset)
+ Is_Static : Boolean;
+ Offset_Value : System.Storage_Elements.Storage_Offset;
+ Offset_Func : System.Address)
is
Prim_DT : Tag;
Sec_Base : System.Address;
@@ -1257,7 +1303,7 @@ package body Ada.Tags is
-- "This" points to the primary DT and we must save Offset_Value in the
-- Offset_To_Top field of the corresponding secondary dispatch table.
- Prim_DT := To_Tag_Ptr (This).all;
+ Prim_DT := To_Tag_Ptr (This).all;
pragma Assert
(Check_Signature (Prim_DT, Must_Be_Primary_DT));
@@ -1268,9 +1314,13 @@ package body Ada.Tags is
To_Storage_Offset_Ptr (To_Address (Sec_DT) - K_Offset_To_Top);
pragma Assert
- (Check_Signature (Sec_DT, Must_Be_Primary_Or_Secondary_DT));
+ (Check_Signature (Sec_DT, Must_Be_Secondary_DT));
- Offset_To_Top.all := Offset_Value;
+ if Is_Static then
+ Offset_To_Top.all := Offset_Value;
+ else
+ Offset_To_Top.all := SSE.Storage_Offset'Last;
+ end if;
-- Save Offset_Value in the table of interfaces of the primary DT. This
-- data will be used by the subprogram "Displace" to give support to
@@ -1284,7 +1334,14 @@ package body Ada.Tags is
if Iface_Table /= null then
for Id in 1 .. Iface_Table.Nb_Ifaces loop
if Iface_Table.Table (Id).Iface_Tag = Interface_T then
- Iface_Table.Table (Id).Offset := Offset_Value;
+ Iface_Table.Table (Id).Static_Offset_To_Top := Is_Static;
+
+ if Is_Static then
+ Iface_Table.Table (Id).Offset_To_Top_Value := Offset_Value;
+ else
+ Iface_Table.Table (Id).Offset_To_Top_Func := Offset_Func;
+ end if;
+
return;
end if;
end loop;
@@ -1307,6 +1364,22 @@ package body Ada.Tags is
OSD_Ptr.all := Value;
end Set_OSD;
+ ------------------------------------
+ -- Set_Predefined_Prim_Op_Address --
+ ------------------------------------
+
+ procedure Set_Predefined_Prim_Op_Address
+ (T : Tag;
+ Position : Positive;
+ Value : System.Address)
+ is
+ Prim_Ops_DT : constant Tag := To_Tag (To_Address (T) - DT_Prologue_Size);
+ begin
+ pragma Assert (Check_Signature (T, Must_Be_Primary_Or_Secondary_DT));
+ pragma Assert (Position >= 1 and then Position <= Default_Prim_Op_Count);
+ Prim_Ops_DT.Prims_Ptr (Position) := Value;
+ end Set_Predefined_Prim_Op_Address;
+
-------------------------
-- Set_Prim_Op_Address --
-------------------------
@@ -1318,7 +1391,7 @@ package body Ada.Tags is
is
begin
pragma Assert (Check_Signature (T, Must_Be_Primary_Or_Secondary_DT));
- pragma Assert (Check_Index (T, Position));
+ pragma Assert (Position <= Get_Num_Prim_Ops (T));
T.Prims_Ptr (Position) := Value;
end Set_Prim_Op_Address;
@@ -1331,12 +1404,10 @@ package body Ada.Tags is
Position : Positive;
Value : Prim_Op_Kind)
is
- Index : constant Integer := Position - Default_Prim_Op_Count;
begin
pragma Assert (Check_Signature (T, Must_Be_Primary_DT));
- pragma Assert (Check_Index (T, Position));
- pragma Assert (Index > 0);
- SSD (T).SSD_Table (Index).Kind := Value;
+ pragma Assert (Position <= Get_Num_Prim_Ops (T));
+ SSD (T).SSD_Table (Position).Kind := Value;
end Set_Prim_Op_Kind;
-------------------
@@ -1359,6 +1430,19 @@ package body Ada.Tags is
TSD (T).Remotely_Callable := Value;
end Set_Remotely_Callable;
+ -------------------
+ -- Set_Signature --
+ -------------------
+
+ procedure Set_Signature (T : Tag; Value : Signature_Kind) is
+ Signature : constant System.Address := To_Address (T) - K_Signature;
+ Sig_Ptr : constant Signature_Values_Ptr :=
+ To_Signature_Values_Ptr (Signature);
+ begin
+ Sig_Ptr.all (1) := Valid_Signature;
+ Sig_Ptr.all (2) := Value;
+ end Set_Signature;
+
-------------
-- Set_SSD --
-------------
@@ -1426,4 +1510,28 @@ package body Ada.Tags is
return To_Type_Specific_Data_Ptr (TSD_Ptr.all);
end TSD;
+ ------------------------
+ -- Wide_Expanded_Name --
+ ------------------------
+
+ WC_Encoding : Character;
+ pragma Import (C, WC_Encoding, "__gl_wc_encoding");
+ -- Encoding method for source, as exported by binder
+
+ function Wide_Expanded_Name (T : Tag) return Wide_String is
+ begin
+ return String_To_Wide_String
+ (Expanded_Name (T), Get_WC_Encoding_Method (WC_Encoding));
+ end Wide_Expanded_Name;
+
+ -----------------------------
+ -- Wide_Wide_Expanded_Name --
+ -----------------------------
+
+ function Wide_Wide_Expanded_Name (T : Tag) return Wide_Wide_String is
+ begin
+ return String_To_Wide_Wide_String
+ (Expanded_Name (T), Get_WC_Encoding_Method (WC_Encoding));
+ end Wide_Wide_Expanded_Name;
+
end Ada.Tags;
diff --git a/gcc/ada/a-tags.ads b/gcc/ada/a-tags.ads
index 25fed4f..bb69544 100644
--- a/gcc/ada/a-tags.ads
+++ b/gcc/ada/a-tags.ads
@@ -68,6 +68,12 @@ package Ada.Tags is
Tag_Error : exception;
+ function Wide_Expanded_Name (T : Tag) return Wide_String;
+ pragma Ada_05 (Wide_Expanded_Name);
+
+ function Wide_Wide_Expanded_Name (T : Tag) return Wide_Wide_String;
+ pragma Ada_05 (Wide_Wide_Expanded_Name);
+
private
-- The following subprogram specifications are placed here instead of
-- the package body to see them from the frontend through rtsfind.
@@ -151,11 +157,25 @@ private
Default_Prim_Op_Count : constant Positive := 15;
-- Number of predefined primitive operations added by the Expander for a
- -- tagged type. It is utilized for indexing in the two auxiliary tables
- -- used for dispatching asynchronous, conditional and timed selects. In
- -- order to be space efficient, indexing is performed by subtracting this
- -- constant value from the provided position in the auxiliary tables (must
- -- match Exp_Disp.Default_Prim_Op_Count).
+ -- tagged type (must match Exp_Disp.Default_Prim_Op_Count).
+
+ type Signature_Kind is
+ (Unknown,
+ Valid_Signature,
+ Primary_DT,
+ Secondary_DT,
+ Abstract_Interface);
+ for Signature_Kind'Size use 8;
+ -- Kind of signature found in the header of the dispatch table. These
+ -- signatures are generated by the frontend and are used by the Check_XXX
+ -- routines to ensure that the kind of dispatch table managed by each of
+ -- the routines in this package is correct. This additional check is only
+ -- performed with this run-time package is compiled with assertions enabled
+
+ -- The signature is a sequence of two bytes. The first byte must have the
+ -- value Valid_Signature, and the second byte must have a value in the
+ -- range Primary_DT .. Abstract_Interface. The Unknown value is used by
+ -- the Check_XXX routines to indicate that the signature is wrong.
package SSE renames System.Storage_Elements;
@@ -200,6 +220,13 @@ private
-- operation in the DT, retrieve the corresponding operation's position in
-- the primary dispatch table from the Offset Specific Data table of T.
+ function Get_Predefined_Prim_Op_Address
+ (T : Tag;
+ Position : Positive) return System.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).
+
function Get_Prim_Op_Address
(T : Tag;
Position : Positive) return System.Address;
@@ -239,9 +266,11 @@ private
-- Initialize the TSD of a type knowing the tag of the direct ancestor
function Offset_To_Top
- (T : Tag) return System.Storage_Elements.Storage_Offset;
+ (This : System.Address) return System.Storage_Elements.Storage_Offset;
-- Returns the current value of the offset_to_top component available in
- -- the prologue of the dispatch table.
+ -- the prologue of the dispatch table. If the parent of the tagged type
+ -- has discriminants this value is stored in a record component just
+ -- immediately after the tag component.
function OSD (T : Tag) return Object_Specific_Data_Ptr;
-- Ada 2005 (AI-251): Given a pointer T to a secondary dispatch table,
@@ -305,7 +334,9 @@ private
procedure Set_Offset_To_Top
(This : System.Address;
Interface_T : Tag;
- Offset_Value : System.Storage_Elements.Storage_Offset);
+ Is_Static : Boolean;
+ Offset_Value : System.Storage_Elements.Storage_Offset;
+ Offset_Func : System.Address);
-- 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" is
-- not required (and the compiler passes always the Null_Address value) and
@@ -319,6 +350,14 @@ private
-- Given a pointer T to a secondary dispatch table, store the pointer to
-- the record containing the Object Specific Data generated by GNAT.
+ procedure Set_Predefined_Prim_Op_Address
+ (T : Tag;
+ Position : Positive;
+ Value : System.Address);
+ -- Given a pointer to a dispatch Table (T) and a position in the dispatch
+ -- table associated with a predefined primitive operation, put the address
+ -- of the virtual function in it (used for overriding).
+
procedure Set_Prim_Op_Address
(T : Tag;
Position : Positive;
@@ -342,6 +381,9 @@ private
-- Set to true if the type has been declared in a context described
-- in E.4 (18).
+ procedure Set_Signature (T : Tag; Value : Signature_Kind);
+ -- Given a pointer T to a dispatch table, store the signature id
+
procedure Set_SSD (T : Tag; Value : System.Address);
-- Given a pointer T to a dispatch Table, stores the pointer to the record
-- containing the Select Specific Data generated by GNAT.
@@ -363,11 +405,15 @@ private
-- record containing the Type Specific Data generated by GNAT.
DT_Prologue_Size : constant SSE.Storage_Count :=
- SSE.Storage_Count (4 * (Standard'Address_Size / System.Storage_Unit));
- -- Size of the first part of the dispatch table
+ SSE.Storage_Count
+ ((Default_Prim_Op_Count + 4) *
+ (Standard'Address_Size / System.Storage_Unit));
+ -- Size of the hidden part of the dispatch table. It contains the table of
+ -- predefined primitive operations plus the C++ ABI header.
DT_Signature_Size : constant SSE.Storage_Count :=
- SSE.Storage_Count (1 * (Standard'Address_Size / System.Storage_Unit));
+ SSE.Storage_Count
+ (1 * (Standard'Address_Size / System.Storage_Unit));
-- Size of the Signature field of the dispatch table
DT_Tagged_Kind_Size : constant SSE.Storage_Count :=
@@ -375,23 +421,35 @@ private
-- Size of the Tagged_Type_Kind field of the dispatch table
DT_Offset_To_Top_Size : constant SSE.Storage_Count :=
- SSE.Storage_Count (1 * (Standard'Address_Size / System.Storage_Unit));
+ SSE.Storage_Count
+ (1 * (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 (1 * (Standard'Address_Size / System.Storage_Unit));
+ SSE.Storage_Count
+ (1 * (Standard'Address_Size /
+ System.Storage_Unit));
-- 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));
+ SSE.Storage_Count
+ (1 * (Standard'Address_Size / System.Storage_Unit));
-- Size of each primitive operation entry in the Dispatch Table
+ Tag_Size : constant SSE.Storage_Count :=
+ SSE.Storage_Count (1 * (Standard'Address_Size / System.Storage_Unit));
+ -- Size of each tag
+
TSD_Prologue_Size : constant SSE.Storage_Count :=
- SSE.Storage_Count (10 * (Standard'Address_Size / System.Storage_Unit));
+ SSE.Storage_Count
+ (10 * (Standard'Address_Size /
+ System.Storage_Unit));
-- Size of the first part of the type specific data
TSD_Entry_Size : constant SSE.Storage_Count :=
- SSE.Storage_Count (1 * (Standard'Address_Size / System.Storage_Unit));
+ SSE.Storage_Count
+ (1 * (Standard'Address_Size / System.Storage_Unit));
-- Size of each ancestor tag entry in the TSD
type Address_Array is array (Natural range <>) of System.Address;
@@ -400,24 +458,6 @@ private
-- of this type are declared with a dummy size of 1, the actual size
-- depending on the number of primitive operations.
- type Signature_Kind is
- (Unknown,
- Valid_Signature,
- Primary_DT,
- Secondary_DT,
- Abstract_Interface);
- for Signature_Kind'Size use 8;
- -- Kind of signature found in the header of the dispatch table. These
- -- signatures are generated by the frontend and are used by the Check_XXX
- -- routines to ensure that the kind of dispatch table managed by each of
- -- the routines in this package is correct. This additional check is only
- -- performed with this run-time package is compiled with assertions enabled
-
- -- The signature is a sequence of two bytes. The first byte must have the
- -- value Valid_Signature, and the second byte must have a value in the
- -- range Primary_DT .. Abstract_Interface. The Unknown value is used by
- -- the Check_XXX routines to indicate that the signature is wrong.
-
-- Unchecked Conversions
type Addr_Ptr is access System.Address;
@@ -427,6 +467,8 @@ private
array (1 .. DT_Signature_Size) of Signature_Kind;
-- Type used to see the signature as a sequence of Signature_Kind values
+ type Signature_Values_Ptr is access all Signature_Values;
+
function To_Addr_Ptr is
new Unchecked_Conversion (System.Address, Addr_Ptr);
@@ -455,6 +497,13 @@ private
new Unchecked_Conversion (System.Storage_Elements.Storage_Offset,
Signature_Values);
+ function To_Signature_Values_Ptr is
+ new Unchecked_Conversion (System.Address,
+ Signature_Values_Ptr);
+
+ function To_Tag is
+ new Unchecked_Conversion (System.Address, Tag);
+
function To_Tag_Ptr is
new Unchecked_Conversion (System.Address, Tag_Ptr);
@@ -470,6 +519,7 @@ private
pragma Inline_Always (Get_Access_Level);
pragma Inline_Always (Get_Entry_Index);
pragma Inline_Always (Get_Offset_Index);
+ pragma Inline_Always (Get_Predefined_Prim_Op_Address);
pragma Inline_Always (Get_Prim_Op_Address);
pragma Inline_Always (Get_Prim_Op_Kind);
pragma Inline_Always (Get_RC_Offset);
@@ -488,10 +538,12 @@ private
pragma Inline_Always (Set_Num_Prim_Ops);
pragma Inline_Always (Set_Offset_Index);
pragma Inline_Always (Set_Offset_To_Top);
+ pragma Inline_Always (Set_Predefined_Prim_Op_Address);
pragma Inline_Always (Set_Prim_Op_Address);
pragma Inline_Always (Set_Prim_Op_Kind);
pragma Inline_Always (Set_RC_Offset);
pragma Inline_Always (Set_Remotely_Callable);
+ pragma Inline_Always (Set_Signature);
pragma Inline_Always (Set_OSD);
pragma Inline_Always (Set_SSD);
pragma Inline_Always (Set_TSD);
diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb
index 6a975e6..62cfb4e 100644
--- a/gcc/ada/exp_ch3.adb
+++ b/gcc/ada/exp_ch3.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2005, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2006, 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- --
@@ -51,6 +51,7 @@ with Sem; use Sem;
with Sem_Attr; use Sem_Attr;
with Sem_Ch3; use Sem_Ch3;
with Sem_Ch8; use Sem_Ch8;
+with Sem_Disp; use Sem_Disp;
with Sem_Eval; use Sem_Eval;
with Sem_Mech; use Sem_Mech;
with Sem_Res; use Sem_Res;
@@ -237,6 +238,17 @@ package body Exp_Ch3 is
-- discriminant_checking functions of the parent can be reused by
-- a derived type.
+ procedure Make_Controlling_Function_Wrappers
+ (Tag_Typ : Entity_Id;
+ Decl_List : out List_Id;
+ Body_List : out List_Id);
+ -- Ada 2005 (AI-391): Makes specs and bodies for the wrapper functions
+ -- associated with inherited functions with controlling results which
+ -- are not overridden. The body of each wrapper function consists solely
+ -- of a return statement whose expression is an extension aggregate
+ -- invoking the inherited subprogram's parent subprogram and extended
+ -- with a null association list.
+
function Predef_Spec_Or_Body
(Loc : Source_Ptr;
Tag_Typ : Entity_Id;
@@ -1097,6 +1109,7 @@ package body Exp_Ch3 is
-- honest. Actually it isn't quite type honest, because there can be
-- conflicts of views in the private type case. That is why we set
-- Conversion_OK in the conversion node.
+
if (Is_Record_Type (Typ)
or else Is_Array_Type (Typ)
or else Is_Private_Type (Typ))
@@ -1241,6 +1254,7 @@ package body Exp_Ch3 is
if With_Default_Init
and then Nkind (Id_Ref) = N_Selected_Component
+ and then Nkind (Arg) = N_Identifier
then
Append_To (Args,
Make_Selected_Component (Loc,
@@ -1403,6 +1417,11 @@ package body Exp_Ch3 is
-- of the initialization procedure (by calling all the preceding
-- auxiliary routines), and install it as the _init TSS.
+ procedure Build_Offset_To_Top_Functions;
+ -- Ada 2005 (AI-251): Build the tree corresponding to the procedure spec
+ -- and body of the Offset_To_Top function that is generated when the
+ -- parent of a type with discriminants has secondary dispatch tables.
+
procedure Build_Record_Checks (S : Node_Id; Check_List : List_Id);
-- Add range checks to components of disciminated records. S is a
-- subtype indication of a record component. Check_List is a list
@@ -1577,7 +1596,7 @@ package body Exp_Ch3 is
while Present (D) loop
-- Don't generate the assignment for discriminants in derived
-- tagged types if the discriminant is a renaming of some
- -- ancestor discriminant. This initialization will be done
+ -- ancestor discriminant. This initialization will be done
-- when initializing the _parent field of the derived record.
if Is_Tagged and then
@@ -1726,6 +1745,127 @@ package body Exp_Ch3 is
return Res;
end Build_Init_Call_Thru;
+ -----------------------------------
+ -- Build_Offset_To_Top_Functions --
+ -----------------------------------
+
+ procedure Build_Offset_To_Top_Functions is
+ ADT : Elmt_Id;
+ Body_Node : Node_Id;
+ Func_Id : Entity_Id;
+ Spec_Node : Node_Id;
+ E : Entity_Id;
+
+ procedure Build_Offset_To_Top_Internal (Typ : Entity_Id);
+ -- Internal subprogram used to recursively traverse all the ancestors
+
+ ----------------------------------
+ -- Build_Offset_To_Top_Internal --
+ ----------------------------------
+
+ procedure Build_Offset_To_Top_Internal (Typ : Entity_Id) is
+ begin
+ -- Climb to the ancestor (if any) handling private types
+
+ if Present (Full_View (Etype (Typ))) then
+ if Full_View (Etype (Typ)) /= Typ then
+ Build_Offset_To_Top_Internal (Full_View (Etype (Typ)));
+ end if;
+
+ elsif Etype (Typ) /= Typ then
+ Build_Offset_To_Top_Internal (Etype (Typ));
+ end if;
+
+ if Present (Abstract_Interfaces (Typ))
+ and then not Is_Empty_Elmt_List (Abstract_Interfaces (Typ))
+ then
+ E := First_Entity (Typ);
+ while Present (E) loop
+ if Is_Tag (E)
+ and then Chars (E) /= Name_uTag
+ then
+ if Typ = Rec_Type then
+ Body_Node := New_Node (N_Subprogram_Body, Loc);
+
+ Func_Id := Make_Defining_Identifier (Loc,
+ New_Internal_Name ('F'));
+
+ Set_DT_Offset_To_Top_Func (E, Func_Id);
+
+ Spec_Node := New_Node (N_Function_Specification, Loc);
+ Set_Defining_Unit_Name (Spec_Node, Func_Id);
+ Set_Parameter_Specifications (Spec_Node, New_List (
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Loc, Name_uO),
+ In_Present => True,
+ Parameter_Type => New_Reference_To (Typ, Loc))));
+ Set_Result_Definition (Spec_Node,
+ New_Reference_To (RTE (RE_Storage_Offset), Loc));
+
+ Set_Specification (Body_Node, Spec_Node);
+ Set_Declarations (Body_Node, New_List);
+ Set_Handled_Statement_Sequence (Body_Node,
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (
+ Make_Return_Statement (Loc,
+ Expression =>
+ Make_Attribute_Reference (Loc,
+ Prefix =>
+ Make_Selected_Component (Loc,
+ Prefix => Make_Identifier (Loc,
+ Name_uO),
+ Selector_Name => New_Reference_To
+ (E, Loc)),
+ Attribute_Name => Name_Position)))));
+
+ Set_Ekind (Func_Id, E_Function);
+ Set_Mechanism (Func_Id, Default_Mechanism);
+ Set_Is_Internal (Func_Id, True);
+
+ if not Debug_Generated_Code then
+ Set_Debug_Info_Off (Func_Id);
+ end if;
+
+ Analyze (Body_Node);
+
+ Append_Freeze_Action (Rec_Type, Body_Node);
+ end if;
+
+ Next_Elmt (ADT);
+ end if;
+
+ Next_Entity (E);
+ end loop;
+ end if;
+ end Build_Offset_To_Top_Internal;
+
+ -- Start of processing for Build_Offset_To_Top_Functions
+
+ begin
+ if Etype (Rec_Type) = Rec_Type
+ or else not Has_Discriminants (Etype (Rec_Type))
+ or else No (Abstract_Interfaces (Rec_Type))
+ or else Is_Empty_Elmt_List (Abstract_Interfaces (Rec_Type))
+ then
+ return;
+ end if;
+
+ -- Skip the first _Tag, which is the main tag of the
+ -- tagged type. Following tags correspond with abstract
+ -- interfaces.
+
+ ADT := Next_Elmt (First_Elmt (Access_Disp_Table (Rec_Type)));
+
+ -- Handle private types
+
+ if Present (Full_View (Rec_Type)) then
+ Build_Offset_To_Top_Internal (Full_View (Rec_Type));
+ else
+ Build_Offset_To_Top_Internal (Rec_Type);
+ end if;
+ end Build_Offset_To_Top_Functions;
+
--------------------------
-- Build_Init_Procedure --
--------------------------
@@ -1758,9 +1898,10 @@ package body Exp_Ch3 is
----------------------------------
procedure Init_Secondary_Tags_Internal (Typ : Entity_Id) is
- E : Entity_Id;
- Aux_N : Node_Id;
- Iface : Entity_Id;
+ Aux_N : Node_Id;
+ E : Entity_Id;
+ Iface : Entity_Id;
+ Prev_E : Entity_Id;
begin
-- Climb to the ancestor (if any) handling private types
@@ -1800,33 +1941,132 @@ package body Exp_Ch3 is
Expression =>
New_Reference_To (Aux_N, Loc)));
- -- Generate:
- -- Set_Offset_To_Top (Init, Iface'Tag, n);
+ -- Issue error if Set_Offset_To_Top is not available
+ -- in a configurable run-time environment.
- Append_To (Body_Stmts,
- Make_Procedure_Call_Statement (Loc,
- Name => New_Reference_To
- (RTE (RE_Set_Offset_To_Top), Loc),
- Parameter_Associations => New_List (
- Make_Attribute_Reference (Loc,
- Prefix => Make_Identifier (Loc, Name_uInit),
- Attribute_Name => Name_Address),
-
- Unchecked_Convert_To (RTE (RE_Tag),
- New_Reference_To
- (Node (First_Elmt
- (Access_Disp_Table (Iface))),
- 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
- (E, Loc)),
- Attribute_Name => Name_Position)))));
+ if not RTE_Available (RE_Set_Offset_To_Top) then
+ Error_Msg_CRT ("abstract interface types", Typ);
+ return;
+ end if;
+
+ -- We generate a different call to Set_Offset_To_Top
+ -- when the parent of the type has discriminants
+
+ if Typ /= Etype (Typ)
+ and then Has_Discriminants (Etype (Typ))
+ then
+ pragma Assert (Present (DT_Offset_To_Top_Func (E)));
+
+ -- Generate:
+ -- Set_Offset_To_Top
+ -- (This => Init,
+ -- Interface_T => Iface'Tag,
+ -- Is_Constant => False,
+ -- Offset_Value => n,
+ -- Offset_Func => Fn'Address)
+
+ Append_To (Body_Stmts,
+ Make_Procedure_Call_Statement (Loc,
+ Name => New_Reference_To
+ (RTE (RE_Set_Offset_To_Top), Loc),
+ Parameter_Associations => New_List (
+ Make_Attribute_Reference (Loc,
+ Prefix => Make_Identifier (Loc,
+ Name_uInit),
+ Attribute_Name => Name_Address),
+
+ Unchecked_Convert_To (RTE (RE_Tag),
+ New_Reference_To
+ (Node (First_Elmt
+ (Access_Disp_Table (Iface))),
+ Loc)),
+
+ New_Occurrence_Of (Standard_False, 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
+ (E, Loc)),
+ Attribute_Name => Name_Position)),
+
+ Unchecked_Convert_To (RTE (RE_Address),
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To
+ (DT_Offset_To_Top_Func (E),
+ Loc),
+ Attribute_Name =>
+ Name_Address)))));
+
+ -- In this case the next component stores the value
+ -- of the offset to the top
+
+ Prev_E := E;
+ Next_Entity (E);
+ pragma Assert (Present (E));
+
+ Append_To (Body_Stmts,
+ Make_Assignment_Statement (Loc,
+ Name =>
+ Make_Selected_Component (Loc,
+ Prefix => Make_Identifier (Loc,
+ Name_uInit),
+ Selector_Name =>
+ New_Reference_To (E, Loc)),
+ Expression =>
+ Make_Attribute_Reference (Loc,
+ Prefix =>
+ Make_Selected_Component (Loc,
+ Prefix => Make_Identifier (Loc,
+ Name_uInit),
+ Selector_Name => New_Reference_To
+ (Prev_E, Loc)),
+ Attribute_Name => Name_Position)));
+
+ -- Normal case: No discriminants in the parent type
+
+ else
+ -- Generate:
+ -- Set_Offset_To_Top
+ -- (This => Init,
+ -- Interface_T => Iface'Tag,
+ -- Is_Constant => True,
+ -- Offset_Value => n,
+ -- Offset_Func => null);
+
+ Append_To (Body_Stmts,
+ Make_Procedure_Call_Statement (Loc,
+ Name => New_Reference_To
+ (RTE (RE_Set_Offset_To_Top), Loc),
+ Parameter_Associations => New_List (
+ Make_Attribute_Reference (Loc,
+ Prefix => Make_Identifier (Loc, Name_uInit),
+ Attribute_Name => Name_Address),
+
+ Unchecked_Convert_To (RTE (RE_Tag),
+ New_Reference_To
+ (Node (First_Elmt
+ (Access_Disp_Table (Iface))),
+ Loc)),
+
+ New_Occurrence_Of (Standard_True, 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
+ (E, Loc)),
+ Attribute_Name => Name_Position)),
+
+ New_Reference_To
+ (RTE (RE_Null_Address), Loc))));
+ end if;
Next_Elmt (ADT);
end if;
@@ -1897,8 +2137,9 @@ package body Exp_Ch3 is
if Parent_Subtype_Renaming_Discrims then
-- N is a Derived_Type_Definition that renames the parameters
- -- of the ancestor type. We init it by expanding our discrims
- -- and call the ancestor _init_proc with a type-converted object
+ -- of the ancestor type. We initialize it by expanding our
+ -- discriminants and call the ancestor _init_proc with a
+ -- type-converted object
Append_List_To (Body_Stmts,
Build_Init_Call_Thru (Parameters));
@@ -1945,7 +2186,9 @@ package body Exp_Ch3 is
-- _Init._Tag := Typ'Tag;
-- Suppress the tag assignment when Java_VM because JVM tags are
- -- represented implicitly in objects.
+ -- represented implicitly in objects. It is also suppressed in
+ -- case of CPP_Class types because in this case the tag is
+ -- initialized in the C++ side.
if Is_Tagged_Type (Rec_Type)
and then not Is_CPP_Class (Rec_Type)
@@ -2375,7 +2618,10 @@ package body Exp_Ch3 is
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_Interface_Tag); -- Ada 2005 (AI-251)
+
+ -- Ada 2005 (AI-251): Check also the tag of abstract interfaces
+
+ and then not Is_RTE (T, RE_Interface_Tag);
end Component_Needs_Simple_Initialization;
---------------------
@@ -2552,7 +2798,8 @@ package body Exp_Ch3 is
-- since the call is generated, there had better be a routine
-- at the other end of the call, even if it does nothing!)
- -- Note: the reason we exclude the CPP_Class case is ???
+ -- Note: the reason we exclude the CPP_Class case is because in this
+ -- case the initialization is performed in the C++ side.
if Is_CPP_Class (Rec_Id) then
return False;
@@ -2647,6 +2894,7 @@ package body Exp_Ch3 is
elsif Requires_Init_Proc (Rec_Type)
or else Is_Unchecked_Union (Rec_Type)
then
+ Build_Offset_To_Top_Functions;
Build_Init_Procedure;
Set_Is_Public (Proc_Id, Is_Public (Pe));
@@ -3342,7 +3590,7 @@ package body Exp_Ch3 is
if Is_Access_Type (Def_Id) then
-- Anonymous access types are created for the components of the
- -- record parameter for an entry declaration. No master is created
+ -- record parameter for an entry declaration. No master is created
-- for such a type.
if Has_Task (Designated_Type (Def_Id))
@@ -3352,17 +3600,22 @@ package body Exp_Ch3 is
Build_Master_Renaming (Parent (Def_Id), Def_Id);
-- Create a class-wide master because a Master_Id must be generated
- -- for access-to-limited-class-wide types, whose root may be extended
- -- with task components.
+ -- for access-to-limited-class-wide types whose root may be extended
+ -- with task components, and for access-to-limited-interfaces because
+ -- they can be used to reference tasks implementing such interface.
elsif Is_Class_Wide_Type (Designated_Type (Def_Id))
- and then Is_Limited_Type (Designated_Type (Def_Id))
+ and then (Is_Limited_Type (Designated_Type (Def_Id))
+ or else
+ (Is_Interface (Designated_Type (Def_Id))
+ and then
+ Is_Limited_Interface (Designated_Type (Def_Id))))
and then Tasking_Allowed
- -- Don't create a class-wide master for types whose convention is
+ -- Do not create a class-wide master for types whose convention is
-- Java since these types cannot embed Ada tasks anyway. Note that
-- the following test cannot catch the following case:
- --
+
-- package java.lang.Object is
-- type Typ is tagged limited private;
-- type Ref is access all Typ'Class;
@@ -3370,7 +3623,7 @@ package body Exp_Ch3 is
-- type Typ is tagged limited ...;
-- pragma Convention (Typ, Java)
-- end;
- --
+
-- Because the convention appears after we have done the
-- processing for type Ref.
@@ -3487,7 +3740,7 @@ package body Exp_Ch3 is
if No (Expr) then
- -- Expand Initialize call for controlled objects. One may wonder why
+ -- Expand Initialize call for controlled objects. One may wonder why
-- the Initialize Call is not done in the regular Init procedure
-- attached to the record type. That's because the init procedure is
-- recursively called on each component, including _Parent, thus the
@@ -3591,21 +3844,27 @@ package body Exp_Ch3 is
-- 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
+ 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
+ declare
+ Prag : Node_Id;
+ begin
Prag :=
Make_Linker_Section_Pragma
(Def_Id, Sloc (N), ".persistent.bss");
Insert_After (N, Prag);
Analyze (Prag);
- end if;
- end;
+ end;
+ end if;
+
+ -- If access type, then we know it is null if not initialized
+
+ if Is_Access_Type (Typ) then
+ Set_Is_Known_Null (Def_Id);
+ end if;
-- Explicit initialization present
@@ -3618,23 +3877,23 @@ package body Exp_Ch3 is
Expr_Q := Expr;
end if;
- -- When we have the appropriate type of aggregate in the
- -- expression (it has been determined during analysis of the
- -- aggregate by setting the delay flag), let's perform in
- -- place assignment and thus avoid creating a temporary.
+ -- When we have the appropriate type of aggregate in the expression
+ -- (it has been determined during analysis of the aggregate by
+ -- setting the delay flag), let's perform in place assignment and
+ -- thus avoid creating a temporary.
if Is_Delayed_Aggregate (Expr_Q) then
Convert_Aggr_In_Object_Decl (N);
else
- -- In most cases, we must check that the initial value meets
- -- any constraint imposed by the declared type. However, there
- -- is one very important exception to this rule. If the entity
- -- has an unconstrained nominal subtype, then it acquired its
- -- constraints from the expression in the first place, and not
- -- only does this mean that the constraint check is not needed,
- -- but an attempt to perform the constraint check can
- -- cause order of elaboration problems.
+ -- In most cases, we must check that the initial value meets any
+ -- constraint imposed by the declared type. However, there is one
+ -- very important exception to this rule. If the entity has an
+ -- unconstrained nominal subtype, then it acquired its constraints
+ -- from the expression in the first place, and not only does this
+ -- mean that the constraint check is not needed, but an attempt to
+ -- perform the constraint check can cause order order of
+ -- elaboration problems.
if not Is_Constr_Subt_For_U_Nominal (Typ) then
@@ -3653,6 +3912,7 @@ package body Exp_Ch3 is
-- If the type is controlled we attach the object to the final
-- list and adjust the target after the copy. This
+ -- ??? incomplete sentence
if Controlled_Type (Typ) then
declare
@@ -3662,10 +3922,10 @@ package body Exp_Ch3 is
begin
-- Attach the result to a dummy final list which will never
-- be finalized if Delay_Finalize_Attachis set. It is
- -- important to attach to a dummy final list rather than
- -- not attaching at all in order to reset the pointers
- -- coming from the initial value. Equivalent code exists
- -- in the sec-stack case in Exp_Ch4.Expand_N_Allocator.
+ -- important to attach to a dummy final list rather than not
+ -- attaching at all in order to reset the pointers coming
+ -- from the initial value. Equivalent code exists in the
+ -- sec-stack case in Exp_Ch4.Expand_N_Allocator.
if Delay_Finalize_Attach (N) then
F :=
@@ -3694,11 +3954,11 @@ package body Exp_Ch3 is
-- For tagged types, when an init value is given, the tag has to
-- be re-initialized separately in order to avoid the propagation
-- of a wrong tag coming from a view conversion unless the type
- -- is class wide (in this case the tag comes from the init
- -- value). Suppress the tag assignment when Java_VM because JVM
- -- tags are represented implicitly in objects. Ditto for types
- -- that are CPP_CLASS, and for initializations that are
- -- aggregates, because they have to have the right tag.
+ -- is class wide (in this case the tag comes from the init value).
+ -- Suppress the tag assignment when Java_VM because JVM tags are
+ -- represented implicitly in objects. Ditto for types that are
+ -- CPP_CLASS, and for initializations that are aggregates, because
+ -- they have to have the right tag.
if Is_Tagged_Type (Typ)
and then not Is_Class_Wide_Type (Typ)
@@ -3706,8 +3966,8 @@ package body Exp_Ch3 is
and then not Java_VM
and then Nkind (Expr) /= N_Aggregate
then
- -- The re-assignment of the tag has to be done even if
- -- the object is a constant
+ -- The re-assignment of the tag has to be done even if the
+ -- object is a constant.
New_Ref :=
Make_Selected_Component (Loc,
@@ -3731,9 +3991,7 @@ package body Exp_Ch3 is
-- For discrete types, set the Is_Known_Valid flag if the
-- initializing value is known to be valid.
- elsif Is_Discrete_Type (Typ)
- and then Expr_Known_Valid (Expr)
- then
+ elsif Is_Discrete_Type (Typ) and then Expr_Known_Valid (Expr) then
Set_Is_Known_Valid (Def_Id);
elsif Is_Access_Type (Typ) then
@@ -3743,7 +4001,7 @@ package body Exp_Ch3 is
-- Can_Never_Be_Null if this is a constant.
if Known_Non_Null (Expr) then
- Set_Is_Known_Non_Null (Def_Id);
+ Set_Is_Known_Non_Null (Def_Id, True);
if Constant_Present (N) then
Set_Can_Never_Be_Null (Def_Id);
@@ -3761,19 +4019,19 @@ package body Exp_Ch3 is
end if;
end if;
- -- Cases where the back end cannot handle the initialization
- -- directly. In such cases, we expand an assignment that will
- -- be appropriately handled by Expand_N_Assignment_Statement.
+ -- Cases where the back end cannot handle the initialization directly
+ -- In such cases, we expand an assignment that will be appropriately
+ -- handled by Expand_N_Assignment_Statement.
- -- The exclusion of the unconstrained case is wrong, but for
- -- now it is too much trouble ???
+ -- The exclusion of the unconstrained case is wrong, but for now it
+ -- is too much trouble ???
if (Is_Possibly_Unaligned_Slice (Expr)
or else (Is_Possibly_Unaligned_Object (Expr)
and then not Represented_As_Scalar (Etype (Expr))))
- -- The exclusion of the unconstrained case is wrong, but for
- -- now it is too much trouble ???
+ -- The exclusion of the unconstrained case is wrong, but for now
+ -- it is too much trouble ???
and then not (Is_Array_Type (Etype (Expr))
and then not Is_Constrained (Etype (Expr)))
@@ -4427,6 +4685,9 @@ package body Exp_Ch3 is
Renamed_Eq : Node_Id := Empty;
-- Could use some comments ???
+ Wrapper_Decl_List : List_Id := No_List;
+ Wrapper_Body_List : List_Id := No_List;
+
begin
-- Build discriminant checking functions if not a derived type (for
-- derived types that are not tagged types, we always use the
@@ -4508,6 +4769,17 @@ package body Exp_Ch3 is
if Is_Tagged_Type (Def_Id) then
if Is_CPP_Class (Def_Id) then
+
+ -- Because of the new C++ ABI compatibility we now allow the
+ -- programer to use the Ada tag (and in this case we must do
+ -- the normal expansion of the tag)
+
+ if Etype (First_Component (Def_Id)) = RTE (RE_Tag)
+ and then Underlying_Type (Etype (Def_Id)) = Def_Id
+ then
+ Expand_Tagged_Root (Def_Id);
+ end if;
+
Set_All_DT_Position (Def_Id);
Set_Default_Constructor (Def_Id);
@@ -4562,6 +4834,21 @@ package body Exp_Ch3 is
(Def_Id, Predef_List, Renamed_Eq);
Insert_List_Before_And_Analyze (N, Predef_List);
+ -- Ada 2005 (AI-391): For a nonabstract null extension, create
+ -- wrapper functions for each nonoverridden inherited function
+ -- with a controlling result of the type. The wrapper for such
+ -- a function returns an extension aggregate that invokes the
+ -- the parent function.
+
+ if Ada_Version >= Ada_05
+ and then not Is_Abstract (Def_Id)
+ and then Is_Null_Extension (Def_Id)
+ then
+ Make_Controlling_Function_Wrappers
+ (Def_Id, Wrapper_Decl_List, Wrapper_Body_List);
+ Insert_List_Before_And_Analyze (N, Wrapper_Decl_List);
+ end if;
+
Set_Is_Frozen (Def_Id, True);
Set_All_DT_Position (Def_Id);
@@ -4752,11 +5039,19 @@ package body Exp_Ch3 is
Predef_List := Predefined_Primitive_Bodies (Def_Id, Renamed_Eq);
Append_Freeze_Actions (Def_Id, Predef_List);
+ -- Ada 2005 (AI-391): If any wrappers were created for nonoverridden
+ -- inherited functions, then add their bodies to the freeze actions.
+
+ if Present (Wrapper_Body_List) then
+ Append_Freeze_Actions (Def_Id, Wrapper_Body_List);
+ end if;
+
-- Populate the two auxiliary tables used for dispatching
-- asynchronous, conditional and timed selects for synchronized
-- types that implement a limited interface.
if Ada_Version >= Ada_05
+ and then not Restriction_Active (No_Dispatching_Calls)
and then Is_Concurrent_Record_Type (Def_Id)
and then Implements_Interface (
Typ => Def_Id,
@@ -5022,7 +5317,7 @@ package body Exp_Ch3 is
-- code requires both those types to be frozen
if Is_Frozen (Desig_Type)
- and then (not Present (Freeze_Node (Desig_Type))
+ and then (No (Freeze_Node (Desig_Type))
or else Analyzed (Freeze_Node (Desig_Type)))
then
Freeze_Action_Typ := Def_Id;
@@ -5608,6 +5903,167 @@ package body Exp_Ch3 is
return Empty_List;
end Init_Formals;
+ -------------------------------------
+ -- Make_Predefined_Primitive_Specs --
+ -------------------------------------
+
+ procedure Make_Controlling_Function_Wrappers
+ (Tag_Typ : Entity_Id;
+ Decl_List : out List_Id;
+ Body_List : out List_Id)
+ is
+ Loc : constant Source_Ptr := Sloc (Tag_Typ);
+ Prim_Elmt : Elmt_Id;
+ Subp : Entity_Id;
+ Actual_List : List_Id;
+ Formal_List : List_Id;
+ Formal : Entity_Id;
+ Par_Formal : Entity_Id;
+ Formal_Node : Node_Id;
+ Func_Spec : Node_Id;
+ Func_Decl : Node_Id;
+ Func_Body : Node_Id;
+ Return_Stmt : Node_Id;
+
+ begin
+ Decl_List := New_List;
+ Body_List := New_List;
+
+ Prim_Elmt := First_Elmt (Primitive_Operations (Tag_Typ));
+
+ while Present (Prim_Elmt) loop
+ Subp := Node (Prim_Elmt);
+
+ -- If a primitive function with a controlling result of the type has
+ -- not been overridden by the user, then we must create a wrapper
+ -- function here that effectively overrides it and invokes the
+ -- abstract inherited function's nonabstract parent. This can only
+ -- occur for a null extension. Note that functions with anonymous
+ -- controlling access results don't qualify and must be overridden.
+ -- We also exclude Input attributes, since each type will have its
+ -- own version of Input constructed by the expander. The test for
+ -- Comes_From_Source is needed to distinguish inherited operations
+ -- from renamings (which also have Alias set).
+
+ if Is_Abstract (Subp)
+ and then Present (Alias (Subp))
+ and then not Comes_From_Source (Subp)
+ and then Ekind (Subp) = E_Function
+ and then Has_Controlling_Result (Subp)
+ and then not Is_Access_Type (Etype (Subp))
+ and then not Is_TSS (Subp, TSS_Stream_Input)
+ then
+ Formal_List := No_List;
+ Formal := First_Formal (Subp);
+
+ if Present (Formal) then
+ Formal_List := New_List;
+
+ while Present (Formal) loop
+ Append
+ (Make_Parameter_Specification
+ (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Sloc (Formal),
+ Chars => Chars (Formal)),
+ In_Present => In_Present (Parent (Formal)),
+ Out_Present => Out_Present (Parent (Formal)),
+ Parameter_Type =>
+ New_Reference_To (Etype (Formal), Loc),
+ Expression =>
+ New_Copy_Tree (Expression (Parent (Formal)))),
+ Formal_List);
+
+ Next_Formal (Formal);
+ end loop;
+ end if;
+
+ Func_Spec :=
+ Make_Function_Specification (Loc,
+ Defining_Unit_Name =>
+ Make_Defining_Identifier (Loc, Chars (Subp)),
+ Parameter_Specifications =>
+ Formal_List,
+ Result_Definition =>
+ New_Reference_To (Etype (Subp), Loc));
+
+ Func_Decl := Make_Subprogram_Declaration (Loc, Func_Spec);
+ Append_To (Decl_List, Func_Decl);
+
+ -- Build a wrapper body that calls the parent function. The body
+ -- contains a single return statement that returns an extension
+ -- aggregate whose ancestor part is a call to the parent function,
+ -- passing the formals as actuals (with any controlling arguments
+ -- converted to the types of the corresponding formals of the
+ -- parent function, which might be anonymous access types), and
+ -- having a null extension.
+
+ Formal := First_Formal (Subp);
+ Par_Formal := First_Formal (Alias (Subp));
+ Formal_Node := First (Formal_List);
+
+ if Present (Formal) then
+ Actual_List := New_List;
+ else
+ Actual_List := No_List;
+ end if;
+
+ while Present (Formal) loop
+ if Is_Controlling_Formal (Formal) then
+ Append_To (Actual_List,
+ Make_Type_Conversion (Loc,
+ Subtype_Mark =>
+ New_Occurrence_Of (Etype (Par_Formal), Loc),
+ Expression =>
+ New_Reference_To
+ (Defining_Identifier (Formal_Node), Loc)));
+ else
+ Append_To
+ (Actual_List,
+ New_Reference_To
+ (Defining_Identifier (Formal_Node), Loc));
+ end if;
+
+ Next_Formal (Formal);
+ Next_Formal (Par_Formal);
+ Next (Formal_Node);
+ end loop;
+
+ Return_Stmt :=
+ Make_Return_Statement (Loc,
+ Expression =>
+ Make_Extension_Aggregate (Loc,
+ Ancestor_Part =>
+ Make_Function_Call (Loc,
+ Name => New_Reference_To (Alias (Subp), Loc),
+ Parameter_Associations => Actual_List),
+ Null_Record_Present => True));
+
+ Func_Body :=
+ Make_Subprogram_Body (Loc,
+ Specification => New_Copy_Tree (Func_Spec),
+ Declarations => Empty_List,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (Return_Stmt)));
+
+ Set_Defining_Unit_Name
+ (Specification (Func_Body),
+ Make_Defining_Identifier (Loc, Chars (Subp)));
+
+ Append_To (Body_List, Func_Body);
+
+ -- Replace the inherited function with the wrapper function
+ -- in the primitive operations list.
+
+ Override_Dispatching_Operation
+ (Tag_Typ, Subp, New_Op => Defining_Unit_Name (Func_Spec));
+ end if;
+
+ Next_Elmt (Prim_Elmt);
+ end loop;
+ end Make_Controlling_Function_Wrappers;
+
------------------
-- Make_Eq_Case --
------------------
@@ -6371,6 +6827,8 @@ package body Exp_Ch3 is
if Ada_Version >= Ada_05
and then
+ not Restriction_Active (No_Dispatching_Calls)
+ and then
((Is_Interface (Tag_Typ) and then Is_Limited_Record (Tag_Typ))
or else
(Is_Concurrent_Record_Type (Tag_Typ)
diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads
index 3b4522c..acc7ac92 100644
--- a/gcc/ada/rtsfind.ads
+++ b/gcc/ada/rtsfind.ads
@@ -502,6 +502,7 @@ package Rtsfind is
RE_Get_Entry_Index, -- Ada.Tags
RE_Get_External_Tag, -- Ada.Tags
RE_Get_Offset_Index, -- Ada.Tags
+ RE_Get_Predefined_Prim_Op_Address, -- Ada.Tags
RE_Get_Prim_Op_Address, -- Ada.Tags
RE_Get_Prim_Op_Kind, -- Ada.Tags
RE_Get_RC_Offset, -- Ada.Tags
@@ -539,11 +540,13 @@ package Rtsfind is
RE_Set_Offset_Index, -- Ada.Tags
RE_Set_Offset_To_Top, -- Ada.Tags
RE_Set_OSD, -- Ada.Tags
+ RE_Set_Predefined_Prim_Op_Address, -- Ada.Tags
RE_Set_Prim_Op_Address, -- Ada.Tags
RE_Set_Prim_Op_Kind, -- Ada.Tags
RE_Set_RC_Offset, -- Ada.Tags
RE_Set_Remotely_Callable, -- Ada.Tags
RE_Set_SSD, -- Ada.Tags
+ RE_Set_Signature, -- Ada.Tags
RE_Set_Tagged_Kind, -- Ada.Tags
RE_Set_TSD, -- Ada.Tags
RE_Tag, -- Ada.Tags
@@ -1656,6 +1659,7 @@ package Rtsfind is
RE_Get_Entry_Index => Ada_Tags,
RE_Get_External_Tag => Ada_Tags,
RE_Get_Offset_Index => Ada_Tags,
+ RE_Get_Predefined_Prim_Op_Address => Ada_Tags,
RE_Get_Prim_Op_Address => Ada_Tags,
RE_Get_Prim_Op_Kind => Ada_Tags,
RE_Get_RC_Offset => Ada_Tags,
@@ -1693,11 +1697,13 @@ package Rtsfind is
RE_Set_Offset_Index => Ada_Tags,
RE_Set_Offset_To_Top => Ada_Tags,
RE_Set_OSD => Ada_Tags,
+ RE_Set_Predefined_Prim_Op_Address => Ada_Tags,
RE_Set_Prim_Op_Address => Ada_Tags,
RE_Set_Prim_Op_Kind => Ada_Tags,
RE_Set_RC_Offset => Ada_Tags,
RE_Set_Remotely_Callable => Ada_Tags,
RE_Set_SSD => Ada_Tags,
+ RE_Set_Signature => Ada_Tags,
RE_Set_Tagged_Kind => Ada_Tags,
RE_Set_TSD => Ada_Tags,
RE_Tag => Ada_Tags,