OSDN Git Service

2004-04-19 Arnaud Charlet <charlet@act-europe.fr>
[pf3gnuchains/gcc-fork.git] / gcc / ada / sem_elim.adb
index 3f99d82..3117549 100644 (file)
@@ -29,12 +29,12 @@ with Einfo;   use Einfo;
 with Errout;  use Errout;
 with Namet;   use Namet;
 with Nlists;  use Nlists;
+with Sinput;  use Sinput;
 with Sinfo;   use Sinfo;
 with Snames;  use Snames;
 with Stand;   use Stand;
 with Stringt; use Stringt;
 with Table;
-with Uintp;   use Uintp;
 
 with GNAT.HTable; use GNAT.HTable;
 package body Sem_Elim is
@@ -83,8 +83,9 @@ package body Sem_Elim is
       Result_Type : Name_Id;
       --  Result type name if Result_Types parameter present, No_Name if not
 
-      Homonym_Number : Uint;
-      --  Homonyn number if Homonym_Number parameter present, No_Uint if not.
+      Source_Location : Name_Id;
+      --  String describing the source location of subprogram defining name if
+      --  Source_Location parameter present, No_Name if not
 
       Hash_Link : Access_Elim_Data;
       --  Link for hash table use
@@ -229,8 +230,6 @@ package body Sem_Elim is
       Elmt : Access_Elim_Data;
       Scop : Entity_Id;
       Form : Entity_Id;
-      Ctr  : Nat;
-      Ent  : Entity_Id;
 
       function Original_Chars (S : Entity_Id) return Name_Id;
       --  If the candidate subprogram is a protected operation of a single
@@ -360,22 +359,200 @@ package body Sem_Elim is
             elsif Ekind (E) = E_Function
               or else Ekind (E) = E_Procedure
             then
-               --  If Homonym_Number present, then see if it matches
+               --  If Source_Location present, then see if it matches
+
+               if Elmt.Source_Location /= No_Name then
+                  Get_Name_String (Elmt.Source_Location);
+
+                  declare
+                     Sloc_Trace : constant String :=
+                       Name_Buffer (1 .. Name_Len);
+
+                     Idx : Natural := Sloc_Trace'First;
+                     --  Index in Sloc_Trace, if equals to 0, then we have
+                     --  completely traversed Sloc_Trace
+
+                     Last : constant Natural := Sloc_Trace'Last;
+
+                     P      : Source_Ptr;
+                     Sindex : Source_File_Index;
+
+                     function File_Mame_Match return Boolean;
+                     --  This function is supposed to be called when Idx points
+                     --  to the beginning of the new file name, and Name_Buffer
+                     --  is set to contain the name of the proper source file
+                     --  from the chain corresponding to the Sloc of E. First
+                     --  it checks that these two files have the same name. If
+                     --  this check is successful, moves Idx to point to the
+                     --  beginning of the column number.
+
+                     function Line_Num_Match return Boolean;
+                     --  This function is supposed to be called when Idx points
+                     --  to the beginning of the column number, and P is
+                     --  set to point to the proper Sloc the chain
+                     --  corresponding to the Sloc of E. First it checks that
+                     --  the line number Idx points on and the line number
+                     --  corresponding to P are the same. If this check is
+                     --  successful, moves Idx to point to the beginning of
+                     --  the next file name in Sloc_Trace. If there is no file
+                     --  name any more, Idx is set to 0.
+
+                     function Different_Trace_Lengths return Boolean;
+                     --  From Idx and P, defines if there are in both traces
+                     --  more element(s) in the instantiation chains. Returns
+                     --  False if one trace contains more element(s), but
+                     --  another does not. If both traces contains more
+                     --  elements (that is, the function returns False), moves
+                     --  P ahead in the chain corresponding to E, recomputes
+                     --  Sindex and sets the name of the corresponding file in
+                     --  Name_Buffer
+
+                     function Skip_Spaces return Natural;
+                     --  If Sloc_Trace (Idx) is not space character, returns
+                     --  Idx. Otherwise returns the index of the nearest
+                     --  non-space character in Sloc_Trace to the right of
+                     --  Idx. Returns 0 if there is no such character.
+
+                     function Different_Trace_Lengths return Boolean is
+                     begin
+                        P := Instantiation (Sindex);
+
+                        if (P = No_Location and then Idx /= 0)
+                          or else
+                           (P /= No_Location and then Idx = 0)
+                        then
+                           return True;
+                        else
 
-               if Elmt.Homonym_Number /= No_Uint then
-                  Ctr := 1;
+                           if P /= No_Location then
+                              Sindex := Get_Source_File_Index (P);
+                              Get_Name_String (File_Name (Sindex));
+                           end if;
 
-                  Ent := E;
-                  while Present (Homonym (Ent))
-                    and then Scope (Ent) = Scope (Homonym (Ent))
-                  loop
-                     Ctr := Ctr + 1;
-                     Ent := Homonym (Ent);
-                  end loop;
+                           return False;
+                        end if;
+                     end Different_Trace_Lengths;
 
-                  if Ctr /= Elmt.Homonym_Number then
-                     goto Continue;
-                  end if;
+                     function File_Mame_Match return Boolean is
+                        Tmp_Idx : Positive;
+                        End_Idx : Positive;
+                     begin
+
+                        if Idx = 0 then
+                           return False;
+                        end if;
+
+                        for J in Idx .. Last loop
+                           if Sloc_Trace (J) = ':' then
+                              Tmp_Idx := J - 1;
+                              exit;
+                           end if;
+                        end loop;
+
+                        for J in reverse Idx .. Tmp_Idx loop
+                           if Sloc_Trace (J) /= ' ' then
+                              End_Idx := J;
+                              exit;
+                           end if;
+                        end loop;
+
+                        if Sloc_Trace (Idx .. End_Idx) =
+                           Name_Buffer (1 .. Name_Len)
+                        then
+                           Idx := Tmp_Idx + 2;
+
+                           Idx := Skip_Spaces;
+
+                           return True;
+                        else
+                           return False;
+                        end if;
+
+                     end File_Mame_Match;
+
+                     function Line_Num_Match return Boolean is
+                        N : Int := 0;
+                     begin
+
+                        if Idx = 0 then
+                           return False;
+                        end if;
+
+                        while Idx <= Last
+                           and then
+                              Sloc_Trace (Idx) in '0' .. '9'
+                        loop
+                           N := N * 10 +
+                            (Character'Pos (Sloc_Trace (Idx)) -
+                             Character'Pos ('0'));
+
+                           Idx := Idx + 1;
+                        end loop;
+
+                        if Get_Physical_Line_Number (P) =
+                           Physical_Line_Number (N)
+                        then
+
+                           while Sloc_Trace (Idx) /= '['
+                               and then
+                                 Idx <= Last
+                           loop
+                              Idx := Idx + 1;
+                           end loop;
+
+                           if Sloc_Trace (Idx) = '['
+                             and then
+                               Idx < Last
+                           then
+                              Idx := Idx + 1;
+                              Idx := Skip_Spaces;
+                           else
+                              Idx := 0;
+                           end if;
+
+                           return True;
+                        else
+                           return False;
+                        end if;
+
+                     end Line_Num_Match;
+
+                     function Skip_Spaces return Natural is
+                        Res : Natural := Idx;
+                     begin
+
+                        while Sloc_Trace (Res) = ' ' loop
+                           Res := Res + 1;
+
+                           if Res > Last then
+                              Res := 0;
+                              exit;
+                           end if;
+                        end loop;
+
+                        return Res;
+                     end Skip_Spaces;
+
+                  begin
+                     P      := Sloc (E);
+                     Sindex := Get_Source_File_Index (P);
+                     Get_Name_String (File_Name (Sindex));
+
+                     Idx := Skip_Spaces;
+
+                     while Idx > 0 loop
+
+                        if not File_Mame_Match then
+                           goto Continue;
+                        elsif not Line_Num_Match then
+                           goto Continue;
+                        end if;
+
+                        if Different_Trace_Lengths then
+                           goto Continue;
+                        end if;
+                     end loop;
+                  end;
                end if;
 
                --  If we have a Result_Type, then we must have a function
@@ -394,7 +571,14 @@ package body Sem_Elim is
                if Elmt.Parameter_Types /= null then
                   Form := First_Formal (E);
 
-                  if No (Form) and then Elmt.Parameter_Types = null then
+                  if No (Form)
+                   and then
+                    Elmt.Parameter_Types'Length = 1
+                   and then
+                    Elmt.Parameter_Types (1) = No_Name
+                  then
+                     --  Parameterless procedure matches
+
                      null;
 
                   elsif Elmt.Parameter_Types = null then
@@ -471,7 +655,7 @@ package body Sem_Elim is
       Arg_Entity          : Node_Id;
       Arg_Parameter_Types : Node_Id;
       Arg_Result_Type     : Node_Id;
-      Arg_Homonym_Number  : Node_Id)
+      Arg_Source_Location : Node_Id)
    is
       Data : constant Access_Elim_Data := new Elim_Data;
       --  Build result data here
@@ -593,7 +777,13 @@ package body Sem_Elim is
            and then Paren_Count (Arg_Parameter_Types) = 1
          then
             String_To_Name_Buffer (Strval (Arg_Parameter_Types));
-            Data.Parameter_Types := new Names'(1 => Name_Find);
+
+            if Name_Len = 0 then
+               --  Parameterless procedure
+               Data.Parameter_Types := new Names'(1 => No_Name);
+            else
+               Data.Parameter_Types := new Names'(1 => Name_Find);
+            end if;
 
          --  Otherwise must be an aggregate
 
@@ -647,25 +837,24 @@ package body Sem_Elim is
          Data.Result_Type := No_Name;
       end if;
 
-      --  Process Homonym_Number argument
+      --  Process Source_Location argument
 
-      if Present (Arg_Homonym_Number) then
+      if Present (Arg_Source_Location) then
 
-         if Nkind (Arg_Homonym_Number) /= N_Integer_Literal then
+         if Nkind (Arg_Source_Location) /= N_String_Literal then
             Error_Msg_N
-              ("Homonym_Number argument for pragma% must be integer literal",
-               Arg_Homonym_Number);
+              ("Source_Location argument for pragma% must be string literal",
+               Arg_Source_Location);
             return;
          end if;
 
-         Data.Homonym_Number := Intval (Arg_Homonym_Number);
+         String_To_Name_Buffer (Strval (Arg_Source_Location));
+         Data.Source_Location := Name_Find;
 
       else
-         Data.Homonym_Number := No_Uint;
+         Data.Source_Location := No_Name;
       end if;
 
-      --  Now link this new entry into the hash table
-
       Elmt := Elim_Hash_Table.Get (Hash_Subprograms.Get_Key (Data));
 
       --  If we already have an entry with this same key, then link