OSDN Git Service

More improvements to sparc VIS vec_init code generation.
[pf3gnuchains/gcc-fork.git] / gcc / ada / exp_tss.adb
index 5068b24..8b19f91 100644 (file)
@@ -6,18 +6,17 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2003 Free Software Foundation, Inc.          --
+--          Copyright (C) 1992-2010, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
--- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
 -- for  more details.  You should have  received  a copy of the GNU General --
--- Public License  distributed with GNAT;  see file COPYING.  If not, write --
--- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
--- MA 02111-1307, USA.                                                      --
+-- Public License  distributed with GNAT; see file COPYING3.  If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license.          --
 --                                                                          --
 -- GNAT was originally developed  by the GNAT team at  New York University. --
 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
@@ -28,8 +27,11 @@ with Atree;    use Atree;
 with Einfo;    use Einfo;
 with Elists;   use Elists;
 with Exp_Util; use Exp_Util;
+with Nlists;   use Nlists;
 with Lib;      use Lib;
-with Namet;    use Namet;
+with Restrict; use Restrict;
+with Rident;   use Rident;
+with Sem_Aux;  use Sem_Aux;
 with Sem_Util; use Sem_Util;
 with Sinfo;    use Sinfo;
 
@@ -39,12 +41,15 @@ package body Exp_Tss is
    -- Base_Init_Proc --
    --------------------
 
-   function Base_Init_Proc (Typ : Entity_Id) return Entity_Id is
+   function Base_Init_Proc
+     (Typ : Entity_Id;
+      Ref : Entity_Id := Empty) return Entity_Id
+   is
       Full_Type : E;
       Proc      : Entity_Id;
 
    begin
-      pragma Assert (Ekind (Typ) in Type_Kind);
+      pragma Assert (Is_Type (Typ));
 
       if Is_Private_Type (Typ) then
          Full_Type := Underlying_Type (Base_Type (Typ));
@@ -54,19 +59,26 @@ package body Exp_Tss is
 
       if No (Full_Type) then
          return Empty;
+
       elsif Is_Concurrent_Type (Full_Type)
         and then Present (Corresponding_Record_Type (Base_Type (Full_Type)))
       then
-         return Init_Proc (Corresponding_Record_Type (Base_Type (Full_Type)));
+         --  The initialization routine to be called is that of the base type
+         --  of the corresponding record type, which may itself be a subtype
+         --  and possibly an itype.
+
+         return Init_Proc
+           (Base_Type (Corresponding_Record_Type (Base_Type (Full_Type))),
+            Ref);
 
       else
-         Proc := Init_Proc (Base_Type (Full_Type));
+         Proc := Init_Proc (Base_Type (Full_Type), Ref);
 
          if No (Proc)
            and then Is_Composite_Type (Full_Type)
            and then Is_Derived_Type (Full_Type)
          then
-            return Init_Proc (Root_Type (Full_Type));
+            return Init_Proc (Root_Type (Full_Type), Ref);
          else
             return Proc;
          end if;
@@ -97,6 +109,70 @@ package body Exp_Tss is
       Prepend_Elmt (TSS, TSS_Elist (FN));
    end Copy_TSS;
 
+   -------------------
+   -- CPP_Init_Proc --
+   -------------------
+
+   function CPP_Init_Proc (Typ  : Entity_Id) return Entity_Id is
+      FN   : constant Node_Id := Freeze_Node (Typ);
+      Elmt : Elmt_Id;
+
+   begin
+      if not Is_CPP_Class (Root_Type (Typ))
+        or else No (FN)
+        or else No (TSS_Elist (FN))
+      then
+         return Empty;
+
+      else
+         Elmt := First_Elmt (TSS_Elist (FN));
+         while Present (Elmt) loop
+            if Is_CPP_Init_Proc (Node (Elmt)) then
+               return Node (Elmt);
+            end if;
+
+            Next_Elmt (Elmt);
+         end loop;
+      end if;
+
+      return Empty;
+   end CPP_Init_Proc;
+
+   ------------------------
+   -- Find_Inherited_TSS --
+   ------------------------
+
+   function Find_Inherited_TSS
+     (Typ : Entity_Id;
+      Nam : TSS_Name_Type) return Entity_Id
+   is
+      Btyp : Entity_Id := Typ;
+      Proc : Entity_Id;
+
+   begin
+      loop
+         Btyp := Base_Type (Btyp);
+         Proc :=  TSS (Btyp, Nam);
+
+         exit when Present (Proc)
+           or else not Is_Derived_Type (Btyp);
+
+         --  If Typ is a derived type, it may inherit attributes from some
+         --  ancestor.
+
+         Btyp := Etype (Btyp);
+      end loop;
+
+      if No (Proc) then
+
+         --  If nothing else, use the TSS of the root type
+
+         Proc := TSS (Base_Type (Underlying_Type (Typ)), Nam);
+      end if;
+
+      return Proc;
+   end Find_Inherited_TSS;
+
    -----------------------
    -- Get_TSS_Name_Type --
    -----------------------
@@ -112,8 +188,8 @@ package body Exp_Tss is
       if C1 in 'A' .. 'Z' and then C2 in 'A' .. 'Z' then
          Nm := (C1, C2);
 
-         for J in OK_TSS_Names'Range loop
-            if Nm = OK_TSS_Names (J) then
+         for J in TSS_Names'Range loop
+            if Nm = TSS_Names (J) then
                return Nm;
             end if;
          end loop;
@@ -126,20 +202,30 @@ package body Exp_Tss is
    -- Has_Non_Null_Base_Init_Proc --
    ---------------------------------
 
+   --  Note: if a base Init_Proc is present, and No_Default_Initialization is
+   --  present, then we must avoid testing for a null init proc, since there
+   --  is no init proc present in this case.
+
    function Has_Non_Null_Base_Init_Proc (Typ : Entity_Id) return Boolean is
       BIP : constant Entity_Id := Base_Init_Proc (Typ);
-
    begin
-      return Present (BIP) and then not Is_Null_Init_Proc (BIP);
+      return Present (BIP)
+        and then (Restriction_Active (No_Default_Initialization)
+                    or else not Is_Null_Init_Proc (BIP));
    end Has_Non_Null_Base_Init_Proc;
 
    ---------------
    -- Init_Proc --
    ---------------
 
-   function Init_Proc (Typ : Entity_Id) return Entity_Id is
+   function Init_Proc
+     (Typ  : Entity_Id;
+      Ref  : Entity_Id := Empty) return Entity_Id
+   is
       FN   : constant Node_Id := Freeze_Node (Typ);
       Elmt : Elmt_Id;
+      E1   : Entity_Id;
+      E2   : Entity_Id;
 
    begin
       if No (FN) then
@@ -148,11 +234,68 @@ package body Exp_Tss is
       elsif No (TSS_Elist (FN)) then
          return Empty;
 
-      else
+      elsif No (Ref) then
          Elmt := First_Elmt (TSS_Elist (FN));
          while Present (Elmt) loop
             if Is_Init_Proc (Node (Elmt)) then
-               return Node (Elmt);
+               if not Is_CPP_Class (Typ) then
+                  return Node (Elmt);
+
+               --  For CPP classes, we are looking for the default constructor,
+               --  and so we must skip any non-default constructor.
+
+               elsif
+                 No (Next
+                      (First
+                        (Parameter_Specifications (Parent (Node (Elmt))))))
+               then
+                  return Node (Elmt);
+               end if;
+            end if;
+
+            Next_Elmt (Elmt);
+         end loop;
+
+      --  Non-default constructors are currently supported only in the context
+      --  of interfacing with C++.
+
+      else pragma Assert (Is_CPP_Class (Typ));
+
+         --  Use the referenced function to locate the init_proc matching
+         --  the C++ constructor.
+
+         Elmt := First_Elmt (TSS_Elist (FN));
+         while Present (Elmt) loop
+            if Is_Init_Proc (Node (Elmt)) then
+               E1 := Next_Formal (First_Formal (Node (Elmt)));
+               E2 := First_Formal (Ref);
+               while Present (E1) and then Present (E2) loop
+                  if Chars (E1) /= Chars (E2)
+                    or else Ekind (E1) /= Ekind (E2)
+                  then
+                     exit;
+
+                  elsif Ekind (Etype (E1)) /= E_Anonymous_Access_Type
+                    and then Ekind (Etype (E2)) /= E_Anonymous_Access_Type
+                    and then Etype (E1) /= Etype (E2)
+                  then
+                     exit;
+
+                  elsif Ekind (Etype (E1)) = E_Anonymous_Access_Type
+                    and then Ekind (Etype (E2)) = E_Anonymous_Access_Type
+                    and then Directly_Designated_Type (Etype (E1))
+                               /= Directly_Designated_Type (Etype (E2))
+                  then
+                     exit;
+                  end if;
+
+                  E1 := Next_Formal (E1);
+                  E2 := Next_Formal (E2);
+               end loop;
+
+               if No (E1) and then No (E2) then
+                  return Node (Elmt);
+               end if;
             end if;
 
             Next_Elmt (Elmt);
@@ -162,6 +305,18 @@ package body Exp_Tss is
       return Empty;
    end Init_Proc;
 
+   ----------------------
+   -- Is_CPP_Init_Proc --
+   ----------------------
+
+   function Is_CPP_Init_Proc (E : Entity_Id) return Boolean is
+      C1 : Character;
+      C2 : Character;
+   begin
+      Get_Last_Two_Chars (Chars (E), C1, C2);
+      return C1 = TSS_CPP_Init_Proc (1) and then C2 = TSS_CPP_Init_Proc (2);
+   end Is_CPP_Init_Proc;
+
    ------------------
    -- Is_Init_Proc --
    ------------------
@@ -200,18 +355,14 @@ package body Exp_Tss is
 
    function Make_Init_Proc_Name (Typ : Entity_Id) return Name_Id is
    begin
-      Get_Name_String (Chars (Typ));
-      Name_Len := Name_Len + 2;
-      Name_Buffer (Name_Len - 1) := TSS_Init_Proc (1);
-      Name_Buffer (Name_Len)     := TSS_Init_Proc (2);
-      return Name_Find;
+      return Make_TSS_Name (Typ, TSS_Init_Proc);
    end Make_Init_Proc_Name;
 
-   -------------------------
-   -- Make_TSS_Name_Local --
-   -------------------------
+   -------------------
+   -- Make_TSS_Name --
+   -------------------
 
-   function Make_TSS_Name_Local
+   function Make_TSS_Name
      (Typ : Entity_Id;
       Nam : TSS_Name_Type) return Name_Id
    is
@@ -219,25 +370,25 @@ package body Exp_Tss is
       Get_Name_String (Chars (Typ));
       Add_Char_To_Name_Buffer (Nam (1));
       Add_Char_To_Name_Buffer (Nam (2));
-      Add_Char_To_Name_Buffer ('_');
-      Add_Nat_To_Name_Buffer (Increment_Serial_Number);
       return Name_Find;
-   end Make_TSS_Name_Local;
+   end Make_TSS_Name;
 
-   -------------------
-   -- Make_TSS_Name --
-   -------------------
+   -------------------------
+   -- Make_TSS_Name_Local --
+   -------------------------
 
-   function Make_TSS_Name
+   function Make_TSS_Name_Local
      (Typ : Entity_Id;
       Nam : TSS_Name_Type) return Name_Id
    is
    begin
       Get_Name_String (Chars (Typ));
+      Add_Char_To_Name_Buffer ('_');
+      Add_Nat_To_Name_Buffer (Increment_Serial_Number);
       Add_Char_To_Name_Buffer (Nam (1));
       Add_Char_To_Name_Buffer (Nam (2));
       return Name_Find;
-   end Make_TSS_Name;
+   end Make_TSS_Name_Local;
 
    --------------
    -- Same_TSS --
@@ -277,20 +428,31 @@ package body Exp_Tss is
    -------------
 
    procedure Set_TSS (Typ : Entity_Id; TSS : Entity_Id) is
-      Subprog_Body : constant Node_Id := Unit_Declaration_Node (TSS);
-
    begin
-      --  Case of insertion location is in unit defining the type
+      --  Make sure body of subprogram is frozen
+
+      --  Skip this for Init_Proc with No_Default_Initialization, since the
+      --  Init proc is a dummy void entity in this case to be ignored.
+
+      if (Is_Init_Proc (TSS) or else Is_CPP_Init_Proc (TSS))
+        and then Restriction_Active (No_Default_Initialization)
+      then
+         null;
+
+      --  Skip this if not in the same code unit (since it means we are using
+      --  an already existing TSS in another unit)
 
-      if In_Same_Code_Unit (Typ, TSS) then
-         Append_Freeze_Action (Typ, Subprog_Body);
+      elsif not In_Same_Code_Unit (Typ, TSS) then
+         null;
 
-      --  Otherwise, we are using an already existing TSS in another unit
+      --  Otherwise make sure body is frozen
 
       else
-         null;
+         Append_Freeze_Action (Typ, Unit_Declaration_Node (TSS));
       end if;
 
+      --  Set TSS entry
+
       Copy_TSS (TSS, Typ);
    end Set_TSS;