[multiple changes]
authorArnaud Charlet <charlet@gcc.gnu.org>
Wed, 23 Jun 2010 06:59:47 +0000 (08:59 +0200)
committerArnaud Charlet <charlet@gcc.gnu.org>
Wed, 23 Jun 2010 06:59:47 +0000 (08:59 +0200)
2010-06-23  Ed Schonberg  <schonberg@adacore.com>

* sem_util.adb (Mark_Coextensions): If the expression in the allocator
for a coextension in an object declaration is a concatenation, treat
coextension as dynamic.

2010-06-23  Javier Miranda  <miranda@adacore.com>

* sem_ch3.adb (Add_Internal_Interface_Entities): Ensure that the
internal entities are added to the scope of the tagged type.
(Derive_Subprograms): Do not stop derivation when we find the first
internal entity that has attribute Interface_Alias. After the change
done to Override_Dispatching_Operations it is no longer true that
these primirives are always located at the end of the list of
primitives.
* einfo.ads (Primitive_Operations): Add documentation.
* exp_disp.adb (Write_DT): Improve output adding to the name of the
primitive a prefix indicating its corresponding tagged type.
* sem_disp.adb (Override_Dispatching_Operations): If the overridden
entity covers the primitive of an interface that is not an ancestor of
this tagged type then the new primitive is added at the end of the list
of primitives.  Required to fulfill the C++ ABI.

From-SVN: r161253

gcc/ada/ChangeLog
gcc/ada/einfo.ads
gcc/ada/exp_disp.adb
gcc/ada/sem_ch3.adb
gcc/ada/sem_disp.adb
gcc/ada/sem_util.adb

index ba3b9e996505a11a22d22444ec25b946e0100b31..5ea2f6fe3ec116c1bc1b74fc840107695fc45056 100644 (file)
@@ -1,3 +1,26 @@
+2010-06-23  Ed Schonberg  <schonberg@adacore.com>
+
+       * sem_util.adb (Mark_Coextensions): If the expression in the allocator
+       for a coextension in an object declaration is a concatenation, treat
+       coextension as dynamic.
+
+2010-06-23  Javier Miranda  <miranda@adacore.com>
+
+       * sem_ch3.adb (Add_Internal_Interface_Entities): Ensure that the
+       internal entities are added to the scope of the tagged type.
+       (Derive_Subprograms): Do not stop derivation when we find the first
+       internal entity that has attribute Interface_Alias. After the change
+       done to Override_Dispatching_Operations it is no longer true that
+       these primirives are always located at the end of the list of
+       primitives.
+       * einfo.ads (Primitive_Operations): Add documentation.
+       * exp_disp.adb (Write_DT): Improve output adding to the name of the
+       primitive a prefix indicating its corresponding tagged type.
+       * sem_disp.adb (Override_Dispatching_Operations): If the overridden
+       entity covers the primitive of an interface that is not an ancestor of
+       this tagged type then the new primitive is added at the end of the list
+       of primitives.  Required to fulfill the C++ ABI.
+
 2010-06-23  Javier Miranda  <miranda@adacore.com>
 
        * atree.ads (Set_Reporting_Proc): New subprogram.
index dbc5d7fe17d51a78a6d1e60297dac7a6e31e38dd..a3bff056113be84b4c12205321de3d8c6b2b5130 100644 (file)
@@ -3152,7 +3152,9 @@ package Einfo is
 --       types. Points to an element list of entities for primitive operations
 --       for the tagged type. Not present (and not set) in untagged types (it
 --       is an error to reference the primitive operations field of a type
---       that is not tagged).
+--       that is not tagged). In order to fulfill the C++ ABI, entities of
+--       primitives that come from source must be stored in this list following
+--       their order of occurrence in the sources.
 
 --    Prival (Node17)
 --       Present in private components of protected types. Refers to the entity
index 5a1f24964223e1f6aac65f22ac76bee2baed0618..fbc6ddbb38d75158a6a94920d2928efc9eaa418e 100644 (file)
@@ -7127,7 +7127,7 @@ package body Exp_Disp is
             Next_Elmt (Prim_Elmt);
          end loop;
 
-         --  Third stage: Fix the position of all the new primitives
+         --  Third stage: Fix the position of all the new primitives.
          --  Entries associated with primitives covering interfaces
          --  are handled in a latter round.
 
@@ -7515,6 +7515,17 @@ package body Exp_Disp is
             Write_Str ("(predefined) ");
          end if;
 
+         --  Prefix the name of the primitive with its corresponding tagged
+         --  type to facilitate seeing inherited primitives.
+
+         if Present (Alias (Prim)) then
+            Write_Name
+              (Chars (Find_Dispatching_Type (Ultimate_Alias (Prim))));
+         else
+            Write_Name (Chars (Typ));
+         end if;
+
+         Write_Str (".");
          Write_Name (Chars (Prim));
 
          --  Indicate if this primitive has an aliased primitive
index 37856403451cd87daa7e9aa66cedf983792fe199..d5b39f99f9d00a77367e2f57d0c03460aa77e183 100644 (file)
@@ -1517,13 +1517,14 @@ package body Sem_Ch3 is
    -------------------------------------
 
    procedure Add_Internal_Interface_Entities (Tagged_Type : Entity_Id) is
-      Elmt        : Elmt_Id;
-      Iface       : Entity_Id;
-      Iface_Elmt  : Elmt_Id;
-      Iface_Prim  : Entity_Id;
-      Ifaces_List : Elist_Id;
-      New_Subp    : Entity_Id := Empty;
-      Prim        : Entity_Id;
+      Elmt          : Elmt_Id;
+      Iface         : Entity_Id;
+      Iface_Elmt    : Elmt_Id;
+      Iface_Prim    : Entity_Id;
+      Ifaces_List   : Elist_Id;
+      New_Subp      : Entity_Id := Empty;
+      Prim          : Entity_Id;
+      Restore_Scope : Boolean := False;
 
    begin
       pragma Assert (Ada_Version >= Ada_05
@@ -1532,6 +1533,13 @@ package body Sem_Ch3 is
         and then Has_Interfaces (Tagged_Type)
         and then not Is_Interface (Tagged_Type));
 
+      --  Ensure that the internal entities are added to the scope of the type
+
+      if Scope (Tagged_Type) /= Current_Scope then
+         Push_Scope (Scope (Tagged_Type));
+         Restore_Scope := True;
+      end if;
+
       Collect_Interfaces (Tagged_Type, Ifaces_List);
 
       Iface_Elmt := First_Elmt (Ifaces_List);
@@ -1556,32 +1564,47 @@ package body Sem_Ch3 is
                    (Tagged_Type => Tagged_Type,
                     Iface_Prim  => Iface_Prim);
 
+               --  Handle cases where the type has no primitive covering this
+               --  interface primitive.
+
                if No (Prim) then
 
-                  --  In some rare cases, a name conflict may have kept the
-                  --  operation completely hidden. Look for it in the list
-                  --  of primitive operations of the type.
+                  --  if the tagged type is defined at library level then we
+                  --  invoke Check_Abstract_Overriding to report the error
+                  --  and thus avoid generating the dispatch tables.
 
-                  declare
-                     El : Elmt_Id;
+                  if Is_Library_Level_Tagged_Type (Tagged_Type) then
+                     Check_Abstract_Overriding (Tagged_Type);
+                     pragma Assert (Serious_Errors_Detected > 0);
+                     return;
 
-                  begin
-                     El := First_Elmt (Primitive_Operations (Tagged_Type));
-                     while Present (El) loop
-                        Prim := Node (El);
-                        exit when Is_Subprogram (Prim)
-                          and then Alias (Prim) = Iface_Prim;
-                        Next_Elmt (El);
-                     end loop;
+                  --  For tagged types defined in nested scopes it is still
+                  --  possible to cover this interface primitive by means of
+                  --  late overriding (see Override_Dispatching_Operation).
 
-                     --  If the operation was not explicitly overridden, it
-                     --  should have been inherited as an abstract operation
-                     --  so Prim can not be Empty at this stage.
+                  --  Search in the list of primitives of the type for the
+                  --  entity that will be overridden in such case to reference
+                  --  it in the internal entity that we build here. If the
+                  --  primitive is not overridden then the error will be
+                  --  reported later as part of the analysis of entities
+                  --  defined in the enclosing scope.
 
-                     if No (El) then
-                        raise Program_Error;
-                     end if;
-                  end;
+                  else
+                     declare
+                        El : Elmt_Id;
+
+                     begin
+                        El := First_Elmt (Primitive_Operations (Tagged_Type));
+                        while Present (El)
+                          and then Alias (Node (El)) /= Iface_Prim
+                        loop
+                           Next_Elmt (El);
+                        end loop;
+
+                        pragma Assert (Present (El));
+                        Prim := Node (El);
+                     end;
+                  end if;
                end if;
 
                Derive_Subprogram
@@ -1627,6 +1650,10 @@ package body Sem_Ch3 is
 
          Next_Elmt (Iface_Elmt);
       end loop;
+
+      if Restore_Scope then
+         Pop_Scope;
+      end if;
    end Add_Internal_Interface_Entities;
 
    -----------------------------------
@@ -12827,13 +12854,13 @@ package body Sem_Ch3 is
             Subp       := Node (Elmt);
             Alias_Subp := Ultimate_Alias (Subp);
 
-            --  At this early stage Derived_Type has no entities with attribute
-            --  Interface_Alias. In addition, such primitives are always
-            --  located at the end of the list of primitives of Parent_Type.
-            --  Therefore, if found we can safely stop processing pending
-            --  entities.
+            --  Do not derive internal entities of the parent that link
+            --  interface primitives and its covering primitive. These
+            --  entities will be added to this type when frozen.
 
-            exit when Present (Interface_Alias (Subp));
+            if Present (Interface_Alias (Subp)) then
+               goto Continue;
+            end if;
 
             --  If the generic actual is present find the corresponding
             --  operation in the generic actual. If the parent type is a
@@ -13008,6 +13035,7 @@ package body Sem_Ch3 is
                Act_Subp := Node (Act_Elmt);
             end if;
 
+            <<Continue>>
             Next_Elmt (Elmt);
          end loop;
 
index 77fcb4f6b9acab6077111f5a9ce2446587c9cf69..a21337bb600c8ba225dee4b54e44738a927d0e94 100644 (file)
@@ -784,7 +784,7 @@ package body Sem_Disp is
         and then not Comes_From_Source (Subp)
         and then not Has_Dispatching_Parent
       then
-         --  Complete decoration if internally built subprograms that override
+         --  Complete decoration of internally built subprograms that override
          --  a dispatching primitive. These entities correspond with the
          --  following cases:
 
@@ -1709,7 +1709,28 @@ package body Sem_Disp is
          return;
       end if;
 
-      Replace_Elmt (Elmt, New_Op);
+      --  The location of entities that come from source in the list of
+      --  primitives of the tagged type must follow their order of occurrence
+      --  in the sources to fulfill the C++ ABI. If the overriden entity is a
+      --  primitive of an interface that is not an ancestor of this tagged
+      --  type (that is, it is an entity added to the list of primitives by
+      --  Derive_Interface_Progenitors), then we must append the new entity
+      --  at the end of the list of primitives.
+
+      if Present (Alias (Prev_Op))
+        and then Is_Interface (Find_Dispatching_Type (Alias (Prev_Op)))
+        and then not Is_Ancestor (Find_Dispatching_Type (Alias (Prev_Op)),
+                                  Tagged_Type)
+      then
+         Remove_Elmt (Primitive_Operations (Tagged_Type), Elmt);
+         Append_Elmt (New_Op, Primitive_Operations (Tagged_Type));
+
+      --  The new primitive replaces the overriden entity. Required to ensure
+      --  that overriding primitive is assigned the same dispatch table slot.
+
+      else
+         Replace_Elmt (Elmt, New_Op);
+      end if;
 
       if Ada_Version >= Ada_05
         and then Has_Interfaces (Tagged_Type)
index cbc099ee059ec08c124edb403a2283d242138bb1..b141ca41fe63d7684b21863d7c5c5be23191aeb5 100644 (file)
@@ -7948,6 +7948,16 @@ package body Sem_Util is
             if Is_Dynamic then
                Set_Is_Dynamic_Coextension (N);
 
+            --  If the allocator expression is potentially dynamic, it may
+            --  be expanded out of order and require dynamic allocation
+            --  anyway, so we treat the coextension itself as dynamic.
+            --  Potential optimization ???
+
+            elsif Nkind (Expression (N)) = N_Qualified_Expression
+              and then Nkind (Expression (Expression (N))) = N_Op_Concat
+            then
+               Set_Is_Dynamic_Coextension (N);
+
             else
                Set_Is_Static_Coextension (N);
             end if;