OSDN Git Service

2010-01-26 Robert Dewar <dewar@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / binde.adb
index 7479e51..3a85ae8 100644 (file)
@@ -6,18 +6,17 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2007, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2009, 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,  51  Franklin  Street,  Fifth  Floor, --
--- Boston, MA 02110-1301, 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,12 +27,14 @@ with Binderr;  use Binderr;
 with Butil;    use Butil;
 with Debug;    use Debug;
 with Fname;    use Fname;
-with Lib;      use Lib;
 with Namet;    use Namet;
 with Opt;      use Opt;
+with Osint;
 with Output;   use Output;
 with Targparm; use Targparm;
 
+with System.Case_Util; use System.Case_Util;
+
 package body Binde is
 
    --  The following data structures are used to represent the graph that is
@@ -324,14 +325,14 @@ package body Binde is
 
       --  Prefer a waiting body to any other case
 
-      if Is_Waiting_Body (U1) and not Is_Waiting_Body (U2) then
+      if Is_Waiting_Body (U1) and then not Is_Waiting_Body (U2) then
          if Debug_Flag_B then
             Write_Line ("  True: u1 is waiting body, u2 is not");
          end if;
 
          return True;
 
-      elsif Is_Waiting_Body (U2) and not Is_Waiting_Body (U1) then
+      elsif Is_Waiting_Body (U2) and then not Is_Waiting_Body (U1) then
          if Debug_Flag_B then
             Write_Line ("  False: u2 is waiting body, u1 is not");
          end if;
@@ -340,14 +341,14 @@ package body Binde is
 
       --  Prefer a predefined unit to a non-predefined unit
 
-      elsif UT1.Predefined and not UT2.Predefined then
+      elsif UT1.Predefined and then not UT2.Predefined then
          if Debug_Flag_B then
             Write_Line ("  True: u1 is predefined, u2 is not");
          end if;
 
          return True;
 
-      elsif UT2.Predefined and not UT1.Predefined then
+      elsif UT2.Predefined and then not UT1.Predefined then
          if Debug_Flag_B then
             Write_Line ("  False: u2 is predefined, u1 is not");
          end if;
@@ -356,13 +357,13 @@ package body Binde is
 
       --  Prefer an internal unit to a non-internal unit
 
-      elsif UT1.Internal and not UT2.Internal then
+      elsif UT1.Internal and then not UT2.Internal then
          if Debug_Flag_B then
             Write_Line ("  True: u1 is internal, u2 is not");
          end if;
          return True;
 
-      elsif UT2.Internal and not UT1.Internal then
+      elsif UT2.Internal and then not UT1.Internal then
          if Debug_Flag_B then
             Write_Line ("  False: u2 is internal, u1 is not");
          end if;
@@ -371,14 +372,14 @@ package body Binde is
 
       --  Prefer a body to a spec
 
-      elsif Is_Body_Unit (U1) and not Is_Body_Unit (U2) then
+      elsif Is_Body_Unit (U1) and then not Is_Body_Unit (U2) then
          if Debug_Flag_B then
             Write_Line ("  True: u1 is body, u2 is not");
          end if;
 
          return True;
 
-      elsif Is_Body_Unit (U2) and not Is_Body_Unit (U1) then
+      elsif Is_Body_Unit (U2) and then not Is_Body_Unit (U1) then
          if Debug_Flag_B then
             Write_Line ("  False: u2 is body, u1 is not");
          end if;
@@ -864,18 +865,71 @@ package body Binde is
         Units.Table (Before).First_With .. Units.Table (Before).Last_With
       loop
          --  Skip if this with is an interface to a stand-alone library.
-         --  Skip also if no ALI file for this with, happens with certain
-         --  specialized generic files that do not get compiled.
+         --  Skip also if no ALI file for this WITH, happens for language
+         --  defined generics while bootstrapping the compiler (see body of
+         --  Lib.Writ.Write_With_Lines). Finally, skip if it is a limited
+         --  with clause, which does not impose an elaboration link.
 
          if not Withs.Table (W).SAL_Interface
            and then Withs.Table (W).Afile /= No_File
-           and then Generic_Separately_Compiled (Withs.Table (W).Sfile)
+           and then not Withs.Table (W).Limited_With
          then
-            Elab_All_Links
-              (Unit_Id_Of (Withs.Table (W).Uname),
-               After,
-               Reason,
-               Make_Elab_Entry (Withs.Table (W).Uname, Link));
+            declare
+               Info : constant Int :=
+                        Get_Name_Table_Info
+                          (Withs.Table (W).Uname);
+
+            begin
+               --  If the unit is unknown, for some unknown reason, fail
+               --  graciously explaining that the unit is unknown. Without
+               --  this check, gnatbind will crash in Unit_Id_Of.
+
+               if Info = 0 or else Unit_Id (Info) = No_Unit_Id then
+                  declare
+                     Withed       : String :=
+                                      Get_Name_String (Withs.Table (W).Uname);
+                     Last_Withed  : Natural := Withed'Last;
+                     Withing      : String :=
+                                      Get_Name_String
+                                        (Units.Table (Before).Uname);
+                     Last_Withing : Natural := Withing'Last;
+                     Spec_Body    : String  := " (Spec)";
+
+                  begin
+                     To_Mixed (Withed);
+                     To_Mixed (Withing);
+
+                     if Last_Withed > 2 and then
+                       Withed (Last_Withed - 1) = '%'
+                     then
+                        Last_Withed := Last_Withed - 2;
+                     end if;
+
+                     if Last_Withing > 2 and then
+                       Withing (Last_Withing - 1) = '%'
+                     then
+                        Last_Withing := Last_Withing - 2;
+                     end if;
+
+                     if Units.Table (Before).Utype = Is_Body or else
+                       Units.Table (Before).Utype = Is_Body_Only
+                     then
+                        Spec_Body := " (Body)";
+                     end if;
+
+                     Osint.Fail
+                       ("could not find unit "
+                        & Withed (Withed'First .. Last_Withed) & " needed by "
+                        & Withing (Withing'First .. Last_Withing) & Spec_Body);
+                  end;
+               end if;
+
+               Elab_All_Links
+                 (Unit_Id_Of (Withs.Table (W).Uname),
+                  After,
+                  Reason,
+                  Make_Elab_Entry (Withs.Table (W).Uname, Link));
+            end;
          end if;
       end loop;
 
@@ -1185,8 +1239,8 @@ package body Binde is
                         Make_Elab_Entry
                           (Withs.Table (W).Uname, No_Elab_All_Link));
 
-                     --  Elaborate_All_Desirable case, for this we establish
-                     --  the same links as above, but with a different reason.
+                  --  Elaborate_All_Desirable case, for this we establish the
+                  --  same links as above, but with a different reason.
 
                   elsif Withs.Table (W).Elab_All_Desirable then
 
@@ -1204,15 +1258,15 @@ package body Binde is
                         Make_Elab_Entry
                           (Withs.Table (W).Uname, No_Elab_All_Link));
 
-                     --  Pragma Elaborate case. We must build a link for the
-                     --  withed unit itself, and also the corresponding body
-                     --  if there is one.
+                  --  Pragma Elaborate case. We must build a link for the
+                  --  withed unit itself, and also the corresponding body if
+                  --  there is one.
 
-                     --  However, skip this processing if there is no ALI file
-                     --  for the WITH entry, because this means it is a
-                     --  generic (even when we fix the generics so that an ALI
-                     --  file is present, we probably still will have no ALI
-                     --  file for unchecked and other special cases).
+                  --  However, skip this processing if there is no ALI file for
+                  --  the WITH entry, because this means it is a generic (even
+                  --  when we fix the generics so that an ALI file is present,
+                  --  we probably still will have no ALI file for unchecked and
+                  --  other special cases).
 
                   elsif Withs.Table (W).Elaborate
                     and then Withs.Table (W).Afile /= No_File
@@ -1224,8 +1278,8 @@ package body Binde is
                           (Corresponding_Body (Withed_Unit), U, Elab);
                      end if;
 
-                     --  Elaborate_Desirable case, for this we establish
-                     --  the same links as above, but with a different reason.
+                  --  Elaborate_Desirable case, for this we establish
+                  --  the same links as above, but with a different reason.
 
                   elsif Withs.Table (W).Elab_Desirable then
                      Build_Link (Withed_Unit, U, Withed);
@@ -1236,8 +1290,14 @@ package body Binde is
                            U, Elab_Desirable);
                      end if;
 
-                     --  Case of normal WITH with no elaboration pragmas, just
-                     --  build the single link to the directly referenced unit
+                  --  A limited_with does not establish an elaboration
+                  --  dependence (that's the whole point!).
+
+                  elsif Withs.Table (W).Limited_With then
+                     null;
+
+                  --  Case of normal WITH with no elaboration pragmas, just
+                  --  build the single link to the directly referenced unit
 
                   else
                      Build_Link (Withed_Unit, U, Withed);
@@ -1319,18 +1379,18 @@ package body Binde is
 
       --  Prefer anything else to a waiting body (!)
 
-      elsif Is_Waiting_Body (U1) and not Is_Waiting_Body (U2) then
+      elsif Is_Waiting_Body (U1) and then not Is_Waiting_Body (U2) then
          return False;
 
-      elsif Is_Waiting_Body (U2) and not Is_Waiting_Body (U1) then
+      elsif Is_Waiting_Body (U2) and then not Is_Waiting_Body (U1) then
          return True;
 
       --  Prefer a spec to a body (!)
 
-      elsif Is_Body_Unit (U1) and not Is_Body_Unit (U2) then
+      elsif Is_Body_Unit (U1) and then not Is_Body_Unit (U2) then
          return False;
 
-      elsif Is_Body_Unit (U2) and not Is_Body_Unit (U1) then
+      elsif Is_Body_Unit (U2) and then not Is_Body_Unit (U1) then
          return True;
 
       --  If both are waiting bodies, then prefer the one whose spec is