[Ada] Recompile when a dependency has been replaced with another file name

Arnaud Charlet charlet@adacore.com
Thu Oct 7 09:26:00 GMT 2010


When a source in a project being extended has been replaced by a source
with a different file name in the extending project, other sources that
depend on the replaced source file need to be recompiled. This patch
ensures that they are.
No simple test.

Tested on x86_64-pc-linux-gnu, committed on trunk

2010-10-07  Vincent Celier  <celier@adacore.com>

	* make.adb (Check): Call Check_Source_Info_In_ALI with Project_Tree
	* makeutl.adb (Check_Source_Info_In_ALI): If there is at least one
	replaced source, check that none of the replaced sources are in the
	dependencies.
	* makeutl.ads (Check_Source_Info_In_ALI): New parameter Tree
	* prj-nmsc.adb (Remove_Source): New parameter Tree. If the source is
	replaced with a source with a different file name, put it in the hash
	table Replaced_Sources.
	(Add_Source): Call Remove_Source with Data.Tree. If there is at least
	one replaced source, check if it has the same file name as the current
	source; if it has, remove it from the hash table Replaced_Sources.
	* prj.adb (Reset): Reset hash table Tree.Replaced_Sources
	* prj.ads (Replaced_Source_HTable): New hash table
	(Project_Tree_Data): New components Replaced_Sources and
	Replaced_Source_Number.

-------------- next part --------------
Index: make.adb
===================================================================
--- make.adb	(revision 165080)
+++ make.adb	(working copy)
@@ -1843,7 +1843,7 @@ package body Make is
 
             elsif not Read_Only and then Main_Project /= No_Project then
 
-               if not Check_Source_Info_In_ALI (ALI) then
+               if not Check_Source_Info_In_ALI (ALI, Project_Tree) then
                   ALI := No_ALI_Id;
                   return;
                end if;
Index: prj.adb
===================================================================
--- prj.adb	(revision 165080)
+++ prj.adb	(working copy)
@@ -898,6 +898,9 @@ package body Prj is
       Array_Table.Init              (Tree.Arrays);
       Package_Table.Init            (Tree.Packages);
       Source_Paths_Htable.Reset     (Tree.Source_Paths_HT);
+      Replaced_Source_HTable.Reset  (Tree.Replaced_Sources);
+
+      Tree.Replaced_Source_Number := 0;
 
       Free_List (Tree.Projects, Free_Project => True);
       Free_Units (Tree.Units_HT);
Index: prj.ads
===================================================================
--- prj.ads	(revision 165080)
+++ prj.ads	(working copy)
@@ -1333,6 +1333,14 @@ package Prj is
    -- Project_Tree_Data --
    -----------------------
 
+   package Replaced_Source_HTable is new Simple_HTable
+     (Header_Num => Header_Num,
+      Element    => File_Name_Type,
+      No_Element => No_File,
+      Key        => File_Name_Type,
+      Hash       => Hash,
+      Equal      => "=");
+
    type Private_Project_Tree_Data is private;
    --  Data for a project tree that is used only by the Project Manager
 
@@ -1347,6 +1355,13 @@ package Prj is
          Packages          : Package_Table.Instance;
          Projects          : Project_List;
 
+         Replaced_Sources  : Replaced_Source_HTable.Instance;
+         --  The list of sources that have been replaced by sources with
+         --  different file names.
+
+         Replaced_Source_Number : Natural := 0;
+         --  The number of entries in Replaced_Sources
+
          Units_HT : Units_Htable.Instance;
          --  Unit name to Unit_Index (and from there so Source_Id)
 
Index: makeutl.adb
===================================================================
--- makeutl.adb	(revision 165080)
+++ makeutl.adb	(working copy)
@@ -203,7 +203,10 @@ package body Makeutl is
    -- Check_Source_Info_In_ALI --
    ------------------------------
 
-   function Check_Source_Info_In_ALI (The_ALI : ALI_Id) return Boolean is
+   function Check_Source_Info_In_ALI
+     (The_ALI : ALI_Id;
+      Tree    : Project_Tree_Ref) return Boolean
+   is
       Unit_Name : Name_Id;
 
    begin
@@ -242,7 +245,7 @@ package body Makeutl is
          end loop;
       end loop;
 
-      --  Loop to check subunits
+      --  Loop to check subunits and replaced sources
 
       for D in ALIs.Table (The_ALI).First_Sdep ..
                ALIs.Table (The_ALI).Last_Sdep
@@ -253,8 +256,32 @@ package body Makeutl is
          begin
             Unit_Name := SD.Subunit_Name;
 
-            if Unit_Name /= No_Name then
+            if Unit_Name = No_Name then
+               --  Check if this source file has been replaced by a source with
+               --  a different file name.
+
+               if Tree /= null and then Tree.Replaced_Source_Number > 0 then
+                  declare
+                     Replacement : constant File_Name_Type :=
+                       Replaced_Source_HTable.Get
+                         (Tree.Replaced_Sources, SD.Sfile);
+
+                  begin
+                     if Replacement /= No_File then
+                        if Verbose_Mode then
+                           Write_Line
+                             ("source file" &
+                              Get_Name_String (SD.Sfile) &
+                              " has been replaced by " &
+                              Get_Name_String (Replacement));
+                        end if;
 
+                        return False;
+                     end if;
+                  end;
+               end if;
+
+            else
                --  For separates, the file is no longer associated with the
                --  unit ("proc-sep.adb" is not associated with unit "proc.sep")
                --  so we need to check whether the source file still exists in
Index: makeutl.ads
===================================================================
--- makeutl.ads	(revision 165080)
+++ makeutl.ads	(working copy)
@@ -105,7 +105,9 @@ package Makeutl is
    --  True if the unit is in one of the project file, but the file name is not
    --  one of its source. Returns False otherwise.
 
-   function Check_Source_Info_In_ALI (The_ALI : ALI.ALI_Id) return Boolean;
+   function Check_Source_Info_In_ALI
+     (The_ALI : ALI.ALI_Id;
+      Tree    : Project_Tree_Ref) return Boolean;
    --  Check whether all file references in ALI are still valid (i.e. the
    --  source files are still associated with the same units). Return True
    --  if everything is still valid.
Index: prj-nmsc.adb
===================================================================
--- prj-nmsc.adb	(revision 165080)
+++ prj-nmsc.adb	(working copy)
@@ -482,7 +482,8 @@ package body Prj.Nmsc is
    --  if file cannot be found.
 
    procedure Remove_Source
-     (Id          : Source_Id;
+     (Tree        : Project_Tree_Ref;
+      Id          : Source_Id;
       Replaced_By : Source_Id);
    --  Remove a file from the list of sources of a project. This might be
    --  because the file is replaced by another one in an extending project,
@@ -872,7 +873,16 @@ package body Prj.Nmsc is
       Lang_Id.First_Source := Id;
 
       if Source_To_Replace /= No_Source then
-         Remove_Source (Source_To_Replace, Id);
+         Remove_Source (Data.Tree, Source_To_Replace, Id);
+      end if;
+
+      if Data.Tree.Replaced_Source_Number > 0 and then
+         Replaced_Source_HTable.Get (Data.Tree.Replaced_Sources, Id.File) /=
+           No_File
+      then
+         Replaced_Source_HTable.Remove (Data.Tree.Replaced_Sources, Id.File);
+         Data.Tree.Replaced_Source_Number :=
+           Data.Tree.Replaced_Source_Number - 1;
       end if;
 
       Files_Htable.Set (Data.File_To_Source, File_Name, Id);
@@ -6193,7 +6203,7 @@ package body Prj.Nmsc is
                           (Project.Source_Names,
                            Source.File,
                            No_Name_Location);
-                        Remove_Source (Source, No_Source);
+                        Remove_Source (Data.Tree, Source, No_Source);
 
                         Error_Msg_Name_1 := Name_Id (Source.File);
                         Error_Msg
@@ -6277,7 +6287,7 @@ package body Prj.Nmsc is
                end if;
 
                if Source.Path = No_Path_Information then
-                  Remove_Source (Source, No_Source);
+                  Remove_Source (Data.Tree, Source, No_Source);
                end if;
             end if;
 
@@ -7589,7 +7599,8 @@ package body Prj.Nmsc is
    -------------------
 
    procedure Remove_Source
-     (Id          : Source_Id;
+     (Tree        : Project_Tree_Ref;
+      Id          : Source_Id;
       Replaced_By : Source_Id)
    is
       Source : Source_Id;
@@ -7609,6 +7620,21 @@ package body Prj.Nmsc is
       if Replaced_By /= No_Source then
          Id.Replaced_By := Replaced_By;
          Replaced_By.Declared_In_Interfaces := Id.Declared_In_Interfaces;
+
+         if Id.File /= Replaced_By.File then
+            declare
+               Replacement : constant File_Name_Type :=
+                 Replaced_Source_HTable.Get (Tree.Replaced_Sources, Id.File);
+            begin
+               Replaced_Source_HTable.Set
+                 (Tree.Replaced_Sources, Id.File, Replaced_By.File);
+
+               if Replacement = No_File then
+                  Tree.Replaced_Source_Number :=
+                    Tree.Replaced_Source_Number + 1;
+               end if;
+            end;
+         end if;
       end if;
 
       Id.In_Interfaces := False;


More information about the Gcc-patches mailing list