OSDN Git Service

Regenerate gcc/configure.
[pf3gnuchains/gcc-fork.git] / gcc / ada / prj-nmsc.adb
index 75e4c6e..ca6a732 100644 (file)
@@ -192,6 +192,7 @@ package body Prj.Nmsc is
      (Id                  : out Source_Id;
       Data                : in out Tree_Processing_Data;
       Project             : Project_Id;
+      Source_Dir_Rank     : Natural;
       Lang_Id             : Language_Ptr;
       Kind                : Source_Kind;
       File_Name           : File_Name_Type;
@@ -295,6 +296,7 @@ package body Prj.Nmsc is
    procedure Check_File
      (Project           : in out Project_Processing_Data;
       Data              : in out Tree_Processing_Data;
+      Source_Dir_Rank   : Natural;
       Path              : Path_Name_Type;
       File_Name         : File_Name_Type;
       Display_File_Name : File_Name_Type;
@@ -539,6 +541,7 @@ package body Prj.Nmsc is
      (Id                  : out Source_Id;
       Data                : in out Tree_Processing_Data;
       Project             : Project_Id;
+      Source_Dir_Rank     : Natural;
       Lang_Id             : Language_Ptr;
       Kind                : Source_Kind;
       File_Name           : File_Name_Type;
@@ -598,7 +601,7 @@ package body Prj.Nmsc is
                if Data.Flags.Allow_Duplicate_Basenames then
                   Add_Src := True;
 
-               elsif Project.Known_Order_Of_Source_Dirs then
+               elsif Source_Dir_Rank /= Source.Source_Dir_Rank then
                   Add_Src := False;
 
                else
@@ -610,7 +613,7 @@ package body Prj.Nmsc is
                end if;
 
             else
-               if Project.Known_Order_Of_Source_Dirs then
+               if Source_Dir_Rank /= Source.Source_Dir_Rank then
                   Add_Src := False;
 
                --  We might be seeing the same file through a different path
@@ -652,7 +655,7 @@ package body Prj.Nmsc is
                   Location, Project);
 
                Error_Msg_Name_1 := Project.Name;
-               Error_Msg_Name_2 := Name_Id (Path.Name);
+               Error_Msg_Name_2 := Name_Id (Path.Display_Name);
                Error_Msg
                  (Data.Flags, "\  project %%, %%", Location, Project);
 
@@ -722,6 +725,7 @@ package body Prj.Nmsc is
       end if;
 
       Id.Project             := Project;
+      Id.Source_Dir_Rank     := Source_Dir_Rank;
       Id.Language            := Lang_Id;
       Id.Kind                := Kind;
       Id.Alternate_Languages := Alternate_Languages;
@@ -773,6 +777,10 @@ package body Prj.Nmsc is
          Source_Paths_Htable.Set (Data.Tree.Source_Paths_HT, Path.Name, Id);
       end if;
 
+      if Index /= 0 then
+         Project.Has_Multi_Unit_Sources := True;
+      end if;
+
       --  Add the source to the language list
 
       Id.Next_In_Lang := Lang_Id.First_Source;
@@ -1427,6 +1435,34 @@ package body Prj.Nmsc is
                                 From_List => Element.Value.Values,
                                 In_Tree   => Data.Tree);
 
+                        when Name_Multi_Unit_Switches =>
+                           Put (Into_List =>
+                                  Lang_Index.Config.Multi_Unit_Switches,
+                                From_List => Element.Value.Values,
+                                In_Tree   => Data.Tree);
+
+                        when Name_Multi_Unit_Object_Separator =>
+                           Get_Name_String (Element.Value.Value);
+
+                           if Name_Len /= 1 then
+                              Error_Msg
+                                (Data.Flags,
+                                 "multi-unit object separator must have " &
+                                 "a single character",
+                                 Element.Value.Location, Project);
+
+                           elsif Name_Buffer (1) = ' ' then
+                              Error_Msg
+                                (Data.Flags,
+                                 "multi-unit object separator cannot be " &
+                                 "a space",
+                                 Element.Value.Location, Project);
+
+                           else
+                              Lang_Index.Config.Multi_Unit_Object_Separator :=
+                                Name_Buffer (1);
+                           end if;
+
                         when Name_Path_Syntax =>
                            begin
                               Lang_Index.Config.Path_Syntax :=
@@ -1548,10 +1584,18 @@ package body Prj.Nmsc is
                            Lang_Index.Config.Config_Body :=
                              Element.Value.Value;
 
+                        when Name_Config_Body_File_Name_Index =>
+
+                           --  Attribute Config_Body_File_Name_Index
+                           --     ( < Language > )
+
+                           Lang_Index.Config.Config_Body_Index :=
+                             Element.Value.Value;
+
                         when Name_Config_Body_File_Name_Pattern =>
 
                            --  Attribute Config_Body_File_Name_Pattern
-                           --  (<language>)
+                           --    (<language>)
 
                            Lang_Index.Config.Config_Body_Pattern :=
                              Element.Value.Value;
@@ -1563,10 +1607,18 @@ package body Prj.Nmsc is
                            Lang_Index.Config.Config_Spec :=
                              Element.Value.Value;
 
+                        when Name_Config_Spec_File_Name_Index =>
+
+                           --  Attribute Config_Spec_File_Name_Index
+                           --    ( < Language > )
+
+                           Lang_Index.Config.Config_Spec_Index :=
+                             Element.Value.Value;
+
                         when Name_Config_Spec_File_Name_Pattern =>
 
                            --  Attribute Config_Spec_File_Name_Pattern
-                           --  (<language>)
+                           --    (<language>)
 
                            Lang_Index.Config.Config_Spec_Pattern :=
                              Element.Value.Value;
@@ -2041,6 +2093,22 @@ package body Prj.Nmsc is
                           In_Tree   => Data.Tree);
                   end if;
 
+               elsif Attribute.Name = Name_Run_Path_Origin then
+                  Get_Name_String (Attribute.Value.Value);
+
+                  if Name_Len = 0 then
+                     Error_Msg
+                       (Data.Flags,
+                        "run path origin cannot be empty",
+                        Attribute.Value.Location, Project);
+                  end if;
+
+                  Project.Config.Run_Path_Origin := Attribute.Value.Value;
+
+               elsif Attribute.Name = Name_Library_Install_Name_Option then
+                  Project.Config.Library_Install_Name_Option :=
+                    Attribute.Value.Value;
+
                elsif Attribute.Name = Name_Separate_Run_Path_Options then
                   declare
                      pragma Unsuppress (All_Checks);
@@ -2468,6 +2536,12 @@ package body Prj.Nmsc is
                         Project.Decl.Attributes,
                         Data.Tree);
 
+      Library_Interface : constant Prj.Variable_Value :=
+                            Prj.Util.Value_Of
+                              (Snames.Name_Library_Interface,
+                               Project.Decl.Attributes,
+                               Data.Tree);
+
       List      : String_List_Id;
       Element   : String_Element;
       Name      : File_Name_Type;
@@ -2552,22 +2626,90 @@ package body Prj.Nmsc is
 
          Project.Interfaces_Defined := True;
 
-      elsif Project.Extends /= No_Project then
-         Project.Interfaces_Defined := Project.Extends.Interfaces_Defined;
+      elsif Project.Library and then not Library_Interface.Default then
+
+         --  Set In_Interfaces to False for all sources. It will be set to True
+         --  later for the sources in the Library_Interface list.
 
-         if Project.Interfaces_Defined then
-            Iter := For_Each_Source (Data.Tree, Project);
+         Project_2 := Project;
+         while Project_2 /= No_Project loop
+            Iter := For_Each_Source (Data.Tree, Project_2);
             loop
                Source := Prj.Element (Iter);
                exit when Source = No_Source;
-
-               if not Source.Declared_In_Interfaces then
-                  Source.In_Interfaces := False;
-               end if;
-
+               Source.In_Interfaces := False;
                Next (Iter);
             end loop;
-         end if;
+
+            Project_2 := Project_2.Extends;
+         end loop;
+
+         List := Library_Interface.Values;
+         while List /= Nil_String loop
+            Element := Data.Tree.String_Elements.Table (List);
+            Get_Name_String (Element.Value);
+            To_Lower (Name_Buffer (1 .. Name_Len));
+            Name := Name_Find;
+
+            Project_2 := Project;
+            Big_Loop_2 :
+            while Project_2 /= No_Project loop
+               Iter := For_Each_Source (Data.Tree, Project_2);
+
+               loop
+                  Source := Prj.Element (Iter);
+                  exit when Source = No_Source;
+
+                  if Source.Unit /= No_Unit_Index and then
+                     Source.Unit.Name = Name_Id (Name)
+                  then
+                     if not Source.Locally_Removed then
+                        Source.In_Interfaces := True;
+                        Source.Declared_In_Interfaces := True;
+
+                        Other := Other_Part (Source);
+
+                        if Other /= No_Source then
+                           Other.In_Interfaces := True;
+                           Other.Declared_In_Interfaces := True;
+                        end if;
+
+                        if Current_Verbosity = High then
+                           Write_Str ("   interface: ");
+                           Write_Line (Get_Name_String (Source.Path.Name));
+                        end if;
+                     end if;
+
+                     exit Big_Loop_2;
+                  end if;
+
+                  Next (Iter);
+               end loop;
+
+               Project_2 := Project_2.Extends;
+            end loop Big_Loop_2;
+
+            List := Element.Next;
+         end loop;
+
+         Project.Interfaces_Defined := True;
+
+      elsif Project.Extends /= No_Project
+        and then Project.Extends.Interfaces_Defined
+      then
+         Project.Interfaces_Defined := True;
+
+         Iter := For_Each_Source (Data.Tree, Project);
+         loop
+            Source := Prj.Element (Iter);
+            exit when Source = No_Source;
+
+            if not Source.Declared_In_Interfaces then
+               Source.In_Interfaces := False;
+            end if;
+
+            Next (Iter);
+         end loop;
       end if;
    end Check_Interfaces;
 
@@ -2807,6 +2949,7 @@ package body Prj.Nmsc is
                     (Id               => Source,
                      Data             => Data,
                      Project          => Project,
+                     Source_Dir_Rank  => 0,
                      Lang_Id          => Lang_Id,
                      Kind             => Kind,
                      File_Name        => File_Name,
@@ -2916,16 +3059,17 @@ package body Prj.Nmsc is
 
             if Unit /= No_Name then
                Add_Source
-                 (Id           => Source,
-                  Data         => Data,
-                  Project      => Project,
-                  Lang_Id      => Lang_Id,
-                  Kind         => Kind,
-                  File_Name    => File_Name,
-                  Display_File => File_Name_Type (Element.Value.Value),
-                  Unit         => Unit,
-                  Index        => Index,
-                  Location     => Element.Value.Location,
+                 (Id               => Source,
+                  Data             => Data,
+                  Project          => Project,
+                  Source_Dir_Rank  => 0,
+                  Lang_Id          => Lang_Id,
+                  Kind             => Kind,
+                  File_Name        => File_Name,
+                  Display_File     => File_Name_Type (Element.Value.Value),
+                  Unit             => Unit,
+                  Index            => Index,
+                  Location         => Element.Value.Location,
                   Naming_Exception => True);
             end if;
 
@@ -4675,7 +4819,8 @@ package body Prj.Nmsc is
                         (Name_Source_Files,
                          Project.Decl.Attributes, Data.Tree);
 
-      Last_Source_Dir : String_List_Id  := Nil_String;
+      Last_Source_Dir   : String_List_Id    := Nil_String;
+      Last_Src_Dir_Rank : Number_List_Index := No_Number_List;
 
       Languages : constant Variable_Value :=
                       Prj.Util.Value_Of
@@ -4684,6 +4829,7 @@ package body Prj.Nmsc is
       procedure Find_Source_Dirs
         (From     : File_Name_Type;
          Location : Source_Ptr;
+         Rank     : Natural;
          Removed  : Boolean := False);
       --  Find one or several source directories, and add (or remove, if
       --  Removed is True) them to list of source directories of the project.
@@ -4695,27 +4841,125 @@ package body Prj.Nmsc is
       procedure Find_Source_Dirs
         (From     : File_Name_Type;
          Location : Source_Ptr;
+         Rank     : Natural;
          Removed  : Boolean := False)
       is
          Directory : constant String := Get_Name_String (From);
-         Element   : String_Element;
+
+         procedure Add_To_Or_Remove_From_List
+           (Path_Id         : Name_Id;
+            Display_Path_Id : Name_Id);
+         --  When Removed = False, the directory Path_Id to the list of
+         --  source_dirs if not already in the list. When Removed = True,
+         --  removed directory Path_Id if in the list.
 
          procedure Recursive_Find_Dirs (Path : Name_Id);
          --  Find all the subdirectories (recursively) of Path and add them
          --  to the list of source directories of the project.
 
+         --------------------------------
+         -- Add_To_Or_Remove_From_List --
+         --------------------------------
+
+         procedure Add_To_Or_Remove_From_List
+           (Path_Id         : Name_Id;
+            Display_Path_Id : Name_Id)
+         is
+            List       : String_List_Id;
+            Prev       : String_List_Id;
+            Rank_List  : Number_List_Index;
+            Prev_Rank  : Number_List_Index;
+            Element    : String_Element;
+
+         begin
+            Prev      := Nil_String;
+            Prev_Rank := No_Number_List;
+            List      := Project.Source_Dirs;
+            Rank_List := Project.Source_Dir_Ranks;
+            while List /= Nil_String loop
+               Element := Data.Tree.String_Elements.Table (List);
+               exit when Element.Value = Path_Id;
+               Prev := List;
+               List := Element.Next;
+               Prev_Rank := Rank_List;
+               Rank_List := Data.Tree.Number_Lists.Table (Prev_Rank).Next;
+            end loop;
+
+            --  The directory is in the list if List is not Nil_String
+
+            if not Removed and then List = Nil_String then
+               if Current_Verbosity = High then
+                  Write_Str  ("   Adding Source Dir=");
+                  Write_Line (Get_Name_String (Path_Id));
+               end if;
+
+               String_Element_Table.Increment_Last (Data.Tree.String_Elements);
+               Element :=
+                 (Value         => Path_Id,
+                  Index         => 0,
+                  Display_Value => Display_Path_Id,
+                  Location      => No_Location,
+                  Flag          => False,
+                  Next          => Nil_String);
+
+               Number_List_Table.Increment_Last (Data.Tree.Number_Lists);
+
+               if Last_Source_Dir = Nil_String then
+
+                  --  This is the first source directory
+
+                  Project.Source_Dirs :=
+                    String_Element_Table.Last (Data.Tree.String_Elements);
+                  Project.Source_Dir_Ranks :=
+                    Number_List_Table.Last (Data.Tree.Number_Lists);
+
+               else
+                  --  We already have source directories, link the previous
+                  --  last to the new one.
+
+                  Data.Tree.String_Elements.Table (Last_Source_Dir).Next :=
+                    String_Element_Table.Last (Data.Tree.String_Elements);
+                  Data.Tree.Number_Lists.Table (Last_Src_Dir_Rank).Next :=
+                    Number_List_Table.Last (Data.Tree.Number_Lists);
+               end if;
+
+               --  And register this source directory as the new last
+
+               Last_Source_Dir :=
+                 String_Element_Table.Last (Data.Tree.String_Elements);
+               Data.Tree.String_Elements.Table (Last_Source_Dir) := Element;
+               Last_Src_Dir_Rank :=
+                 Number_List_Table.Last (Data.Tree.Number_Lists);
+               Data.Tree.Number_Lists.Table (Last_Src_Dir_Rank) :=
+                 (Number => Rank, Next => No_Number_List);
+
+            elsif Removed and then List /= Nil_String then
+
+               --  Remove source dir, if present
+
+               if Prev = Nil_String then
+                  Project.Source_Dirs :=
+                    Data.Tree.String_Elements.Table (List).Next;
+                  Project.Source_Dir_Ranks :=
+                    Data.Tree.Number_Lists.Table (Rank_List).Next;
+
+               else
+                  Data.Tree.String_Elements.Table (Prev).Next :=
+                    Data.Tree.String_Elements.Table (List).Next;
+                  Data.Tree.Number_Lists.Table (Prev_Rank).Next :=
+                    Data.Tree.Number_Lists.Table (Rank_List).Next;
+               end if;
+            end if;
+         end Add_To_Or_Remove_From_List;
+
          -------------------------
          -- Recursive_Find_Dirs --
          -------------------------
 
          procedure Recursive_Find_Dirs (Path : Name_Id) is
-            Dir     : Dir_Type;
-            Name    : String (1 .. 250);
-            Last    : Natural;
-            List    : String_List_Id;
-            Prev    : String_List_Id;
-            Element : String_Element;
-            Found   : Boolean := False;
+            Dir  : Dir_Type;
+            Name : String (1 .. 250);
+            Last : Natural;
 
             Non_Canonical_Path : Name_Id := No_Name;
             Canonical_Path     : Name_Id := No_Name;
@@ -4752,74 +4996,13 @@ package body Prj.Nmsc is
                end if;
             end if;
 
-            --  Check if directory is already in list
-
-            List := Project.Source_Dirs;
-            Prev := Nil_String;
-            while List /= Nil_String loop
-               Element := Data.Tree.String_Elements.Table (List);
-
-               if Element.Value /= No_Name then
-                  Found := Element.Value = Canonical_Path;
-                  exit when Found;
-               end if;
-
-               Prev := List;
-               List := Element.Next;
-            end loop;
-
-            --  If directory is not already in list, put it there
-
-            if (not Removed) and (not Found) then
-               if Current_Verbosity = High then
-                  Write_Str  ("   ");
-                  Write_Line (The_Path (The_Path'First .. The_Path_Last));
-               end if;
-
-               String_Element_Table.Increment_Last (Data.Tree.String_Elements);
-               Element :=
-                 (Value         => Canonical_Path,
-                  Display_Value => Non_Canonical_Path,
-                  Location      => No_Location,
-                  Flag          => False,
-                  Next          => Nil_String,
-                  Index         => 0);
-
-               --  Case of first source directory
-
-               if Last_Source_Dir = Nil_String then
-                  Project.Source_Dirs :=
-                    String_Element_Table.Last (Data.Tree.String_Elements);
-
-                  --  Here we already have source directories
-
-               else
-                  --  Link the previous last to the new one
-
-                  Data.Tree.String_Elements.Table
-                    (Last_Source_Dir).Next :=
-                      String_Element_Table.Last (Data.Tree.String_Elements);
-               end if;
-
-               --  And register this source directory as the new last
-
-               Last_Source_Dir :=
-                 String_Element_Table.Last (Data.Tree.String_Elements);
-               Data.Tree.String_Elements.Table (Last_Source_Dir) := Element;
-
-            elsif Removed and Found then
-               if Prev = Nil_String then
-                  Project.Source_Dirs :=
-                    Data.Tree.String_Elements.Table (List).Next;
-               else
-                  Data.Tree.String_Elements.Table (Prev).Next :=
-                    Data.Tree.String_Elements.Table (List).Next;
-               end if;
-            end if;
+            Add_To_Or_Remove_From_List
+              (Path_Id         => Canonical_Path,
+               Display_Path_Id => Non_Canonical_Path);
 
-            --  Now look for subdirectories. We do that even when this
-            --  directory is already in the list, because some of its
-            --  subdirectories may not be in the list yet.
+            --  Now look for subdirectories. Do that even when this directory
+            --  is already in the list, because some of its subdirectories may
+            --  not be in the list yet.
 
             Open (Dir, The_Path (The_Path'First .. The_Path_Last));
 
@@ -4839,12 +5022,14 @@ package body Prj.Nmsc is
 
                   declare
                      Path_Name : constant String :=
-                       Normalize_Pathname
-                         (Name      => Name (1 .. Last),
-                          Directory =>
-                            The_Path (The_Path'First .. The_Path_Last),
-                          Resolve_Links  => Opt.Follow_Links_For_Dirs,
-                          Case_Sensitive => True);
+                                   Normalize_Pathname
+                                     (Name           => Name (1 .. Last),
+                                      Directory      =>
+                                        The_Path
+                                          (The_Path'First .. The_Path_Last),
+                                      Resolve_Links  =>
+                                        Opt.Follow_Links_For_Dirs,
+                                      Case_Sensitive => True);
 
                   begin
                      if Is_Directory (Path_Name) then
@@ -4872,6 +5057,8 @@ package body Prj.Nmsc is
          if Current_Verbosity = High and then not Removed then
             Write_Str ("Find_Source_Dirs (""");
             Write_Str (Directory);
+            Write_Str (",");
+            Write_Str (Rank'Img);
             Write_Line (""")");
          end if;
 
@@ -4884,10 +5071,6 @@ package body Prj.Nmsc is
                        or else
                      Directory (Directory'Last - 2) = Directory_Separator)
          then
-            if not Removed then
-               Project.Known_Order_Of_Source_Dirs := False;
-            end if;
-
             Name_Len := Directory'Length - 3;
 
             if Name_Len = 0 then
@@ -4916,7 +5099,8 @@ package body Prj.Nmsc is
                                Directory =>
                                  Get_Name_String
                                    (Project.Directory.Display_Name),
-                               Resolve_Links  => False,
+                               Resolve_Links  =>
+                                 Opt.Follow_Links_For_Dirs,
                                Case_Sensitive => True);
 
             begin
@@ -4958,8 +5142,6 @@ package body Prj.Nmsc is
          else
             declare
                Path_Name  : Path_Information;
-               List       : String_List_Id;
-               Prev       : String_List_Id;
                Dir_Exists : Boolean;
 
             begin
@@ -4988,8 +5170,16 @@ package body Prj.Nmsc is
 
                else
                   declare
-                     Path              : constant String :=
-                                           Get_Name_String (Path_Name.Name);
+                     Path : constant String :=
+                              Normalize_Pathname
+                                (Name           =>
+                                   Get_Name_String (Path_Name.Name),
+                                 Directory      =>
+                                   Get_Name_String (Project.Directory.Name),
+                                 Resolve_Links  => Opt.Follow_Links_For_Dirs,
+                                 Case_Sensitive => True) &
+                              Directory_Separator;
+
                      Last_Path         : constant Natural :=
                                            Compute_Directory_Last (Path);
                      Path_Id           : Name_Id;
@@ -5005,79 +5195,16 @@ package body Prj.Nmsc is
                      Name_Len := 0;
                      Add_Str_To_Name_Buffer (Path (Path'First .. Last_Path));
                      Path_Id := Name_Find;
+
                      Name_Len := 0;
                      Add_Str_To_Name_Buffer
                        (Display_Path
                           (Display_Path'First .. Last_Display_Path));
                      Display_Path_Id := Name_Find;
 
-                     if not Removed then
-
-                        --  As it is an existing directory, we add it to the
-                        --  list of directories.
-
-                        String_Element_Table.Increment_Last
-                          (Data.Tree.String_Elements);
-                        Element :=
-                          (Value         => Path_Id,
-                           Index         => 0,
-                           Display_Value => Display_Path_Id,
-                           Location      => No_Location,
-                           Flag          => False,
-                           Next          => Nil_String);
-
-                        if Last_Source_Dir = Nil_String then
-
-                           --  This is the first source directory
-
-                           Project.Source_Dirs := String_Element_Table.Last
-                             (Data.Tree.String_Elements);
-
-                        else
-                           --  We already have source directories, link the
-                           --  previous last to the new one.
-
-                           Data.Tree.String_Elements.Table
-                             (Last_Source_Dir).Next :=
-                             String_Element_Table.Last
-                               (Data.Tree.String_Elements);
-                        end if;
-
-                        --  And register this source directory as the new last
-
-                        Last_Source_Dir := String_Element_Table.Last
-                          (Data.Tree.String_Elements);
-                        Data.Tree.String_Elements.Table
-                          (Last_Source_Dir) := Element;
-
-                     else
-                        --  Remove source dir, if present
-
-                        Prev := Nil_String;
-
-                        --  Look for source dir in current list
-
-                        List := Project.Source_Dirs;
-                        while List /= Nil_String loop
-                           Element := Data.Tree.String_Elements.Table (List);
-                           exit when Element.Value = Path_Id;
-                           Prev := List;
-                           List := Element.Next;
-                        end loop;
-
-                        if List /= Nil_String then
-                           --  Source dir was found, remove it from the list
-
-                           if Prev = Nil_String then
-                              Project.Source_Dirs :=
-                                Data.Tree.String_Elements.Table (List).Next;
-
-                           else
-                              Data.Tree.String_Elements.Table (Prev).Next :=
-                                Data.Tree.String_Elements.Table (List).Next;
-                           end if;
-                        end if;
-                     end if;
+                     Add_To_Or_Remove_From_List
+                       (Path_Id         => Path_Id,
+                        Display_Path_Id => Display_Path_Id);
                   end;
                end if;
             end;
@@ -5148,10 +5275,21 @@ package body Prj.Nmsc is
 
                Err_Vars.Error_Msg_File_1 :=
                  File_Name_Type (Object_Dir.Value);
-               Error_Msg
-                 (Data.Flags,
-                  "object directory { not found",
-                  Project.Location, Project);
+
+               case Data.Flags.Require_Obj_Dirs is
+                  when Error =>
+                     Error_Msg
+                       (Data.Flags,
+                        "object directory { not found",
+                        Project.Location, Project);
+                  when Warning =>
+                     Error_Msg
+                       (Data.Flags,
+                        "?object directory { not found",
+                        Project.Location, Project);
+                  when Silent =>
+                     null;
+               end case;
             end if;
          end if;
 
@@ -5265,6 +5403,13 @@ package body Prj.Nmsc is
          Project.Source_Dirs :=
            String_Element_Table.Last (Data.Tree.String_Elements);
 
+         Number_List_Table.Append
+           (Data.Tree.Number_Lists,
+            (Number => 1, Next => No_Number_List));
+
+         Project.Source_Dir_Ranks :=
+           Number_List_Table.Last (Data.Tree.Number_Lists);
+
          if Current_Verbosity = High then
             Write_Attr
               ("Default source directory",
@@ -5285,15 +5430,17 @@ package body Prj.Nmsc is
          declare
             Source_Dir : String_List_Id;
             Element    : String_Element;
-
+            Rank       : Natural;
          begin
             --  Process the source directories for each element of the list
 
             Source_Dir := Source_Dirs.Values;
+            Rank := 0;
             while Source_Dir /= Nil_String loop
                Element := Data.Tree.String_Elements.Table (Source_Dir);
+               Rank := Rank + 1;
                Find_Source_Dirs
-                 (File_Name_Type (Element.Value), Element.Location);
+                 (File_Name_Type (Element.Value), Element.Location, Rank);
                Source_Dir := Element.Next;
             end loop;
          end;
@@ -5315,6 +5462,7 @@ package body Prj.Nmsc is
                Find_Source_Dirs
                  (File_Name_Type (Element.Value),
                   Element.Location,
+                  0,
                   Removed => True);
                Source_Dir := Element.Next;
             end loop;
@@ -6571,6 +6719,7 @@ package body Prj.Nmsc is
    procedure Check_File
      (Project           : in out Project_Processing_Data;
       Data              : in out Tree_Processing_Data;
+      Source_Dir_Rank   : Natural;
       Path              : Path_Name_Type;
       File_Name         : File_Name_Type;
       Display_File_Name : File_Name_Type;
@@ -6595,6 +6744,14 @@ package body Prj.Nmsc is
       Kind                  : Source_Kind := Spec;
 
    begin
+      if Current_Verbosity = High then
+         Write_Line ("Checking file:");
+         Write_Str ("   Path = ");
+         Write_Line (Get_Name_String (Path));
+         Write_Str ("   Rank =");
+         Write_Line (Source_Dir_Rank'Img);
+      end if;
+
       if Name_Loc = No_Name_Location then
          Check_Name := For_All_Sources;
 
@@ -6604,7 +6761,7 @@ package body Prj.Nmsc is
             --  Check if it is OK to have the same file name in several
             --  source directories.
 
-            if not Project.Project.Known_Order_Of_Source_Dirs then
+            if Source_Dir_Rank = Name_Loc.Source.Source_Dir_Rank then
                Error_Msg_File_1 := File_Name;
                Error_Msg
                  (Data.Flags,
@@ -6678,6 +6835,7 @@ package body Prj.Nmsc is
             Add_Source
               (Id                  => Source,
                Project             => Project.Project,
+               Source_Dir_Rank     => Source_Dir_Rank,
                Lang_Id             => Language,
                Kind                => Kind,
                Data                => Data,
@@ -6687,6 +6845,15 @@ package body Prj.Nmsc is
                Unit                => Unit,
                Locally_Removed     => Locally_Removed,
                Path                => (Canonical_Path, Path));
+
+            --  If it is a source specified in a list, update the entry in
+            --  the Source_Names table.
+
+            if Name_Loc.Found and then Name_Loc.Source = No_Source then
+               Name_Loc.Source := Source;
+               Source_Names_Htable.Set
+                 (Project.Source_Names, File_Name, Name_Loc);
+            end if;
          end if;
       end if;
    end Check_File;
@@ -6702,6 +6869,8 @@ package body Prj.Nmsc is
    is
       Source_Dir        : String_List_Id;
       Element           : String_Element;
+      Src_Dir_Rank      : Number_List_Index;
+      Num_Nod           : Number_Node;
       Dir               : Dir_Type;
       Name              : String (1 .. 1_000);
       Last              : Natural;
@@ -6716,12 +6885,21 @@ package body Prj.Nmsc is
       --  Loop through subdirectories
 
       Source_Dir := Project.Project.Source_Dirs;
+      Src_Dir_Rank := Project.Project.Source_Dir_Ranks;
       while Source_Dir /= Nil_String loop
          begin
+            Num_Nod := Data.Tree.Number_Lists.Table (Src_Dir_Rank);
             Element := Data.Tree.String_Elements.Table (Source_Dir);
+
             if Element.Value /= No_Name then
                Get_Name_String (Element.Display_Value);
 
+               if Current_Verbosity = High then
+                  Write_Str ("Directory: ");
+                  Write_Str (Name_Buffer (1 .. Name_Len));
+                  Write_Line (Num_Nod.Number'Img);
+               end if;
+
                declare
                   Source_Directory : constant String :=
                                        Name_Buffer (1 .. Name_Len) &
@@ -6745,12 +6923,15 @@ package body Prj.Nmsc is
 
                      exit when Last = 0;
 
-                     --  ??? Duplicate system call here, we just did a a
-                     --  similar one. Maybe Ada.Directories would be more
-                     --  appropriate here.
+                     --  In fast project loading mode (without -eL), the user
+                     --  guarantees that no directory has a name which is a
+                     --  valid source name, so we can avoid doing a system call
+                     --  here. This provides a very significant speed up on
+                     --  slow file systems (remote files for instance).
 
-                     if Is_Regular_File
-                          (Source_Directory & Name (1 .. Last))
+                     if not Opt.Follow_Links_For_Files
+                       or else Is_Regular_File
+                                 (Source_Directory & Name (1 .. Last))
                      then
                         if Current_Verbosity = High then
                            Write_Str  ("   Checking ");
@@ -6808,7 +6989,7 @@ package body Prj.Nmsc is
                                  --  still need to add it to the list: if we
                                  --  don't, the file will not appear in the
                                  --  mapping file and will cause the compiler
-                                 --  to fail
+                                 --  to fail.
 
                                  To_Remove := True;
                               end if;
@@ -6816,6 +6997,7 @@ package body Prj.Nmsc is
 
                            Check_File
                              (Project           => Project,
+                              Source_Dir_Rank   => Num_Nod.Number,
                               Data              => Data,
                               Path              => Path,
                               File_Name         => File_Name,
@@ -6836,6 +7018,7 @@ package body Prj.Nmsc is
          end;
 
          Source_Dir := Element.Next;
+         Src_Dir_Rank := Num_Nod.Next;
       end loop;
 
       if Current_Verbosity = High then
@@ -7165,7 +7348,13 @@ package body Prj.Nmsc is
    begin
       if Current_Verbosity = High then
          Write_Str ("Removing source ");
-         Write_Line (Get_Name_String (Id.File) & " at" & Id.Index'Img);
+         Write_Str (Get_Name_String (Id.File));
+
+         if Id.Index /= 0 then
+            Write_Str (" at" & Id.Index'Img);
+         end if;
+
+         Write_Eol;
       end if;
 
       if Replaced_By /= No_Source then