A child unit given by a subprogram body without a declaration is given a
declaration when it is compiled, to simplify code generation and tools. If
the child unit appears in several with-clauses for the same unit (for example
through with_clauses in various subunits) all with_clauses must refer to the
same file, to prevent binding errors caused by the presence of the generated
subprogram declaration in the ali file.
The following must compile quietly:

   gnatmake -q m

with Q;
procedure M is
begin
   null;
end;
---
package Q is
  procedure S1;
  procedure S2;
end;
---
package body Q is
  procedure S1 is separate;
  procedure S2 is separate;
end;
---
procedure Q.C is
begin
  null;
end;
---
with Q.C;
separate (Q)
procedure S1 is
begin
   null;
end;
---
with Q.C;
separate (Q)
procedure S2 is
begin
   null;
end;

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

2011-09-02  Ed Schonberg  <schonb...@adacore.com>

        * sem_ch10.adb (Analyze_With_Clause): If the library unit
        is the generated subprogram declaration for a child unit body
        that acts as spec, use the original body in the with_clause,
        to prevent binding errors.

Index: sem_ch10.adb
===================================================================
--- sem_ch10.adb        (revision 178381)
+++ sem_ch10.adb        (working copy)
@@ -2536,6 +2536,21 @@
          --  Child unit in a with clause
 
          Change_Selected_Component_To_Expanded_Name (Name (N));
+
+         --  If this is a child unit without a spec, and it has benn analyzed
+         --  already, a declaration has been created for it. The with_clause
+         --  must reflect the actual body, and not the generated declaration,
+         --  to prevent spurious binding errors involving an out-of-date spec.
+         --  Note that this can only happen if the unit includes more than one
+         --  with_clause for the child unit (e.g. in separate subunits).
+
+         if Unit_Kind = N_Subprogram_Declaration
+           and then Analyzed (Library_Unit (N))
+           and then not Comes_From_Source (Library_Unit (N))
+         then
+            Set_Library_Unit (N,
+               Cunit (Get_Source_Unit (Corresponding_Body (U))));
+         end if;
       end if;
 
       --  Restore style checks and restrictions

Reply via email to