diff mbox

[Ada] Implicit Elaborate_All(P) in P

Message ID 20170106102905.GA97731@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Jan. 6, 2017, 10:29 a.m. UTC
This patch fixes a bug where the compiler would add an implicit pragma
Elaborate_All(P) to the body of P itself, causing gnatbind to find a
spurious elaboration cycle.

The following test must build quietly.

gnatmake -q -f main.adb

with Ada.Finalization;
package Ctrl is
    type T (Object : access Boolean := null) is
new Ada.Finalization.Limited_Controlled
with null record;
    procedure Initialize (X : in out T);
end Ctrl;
package body Ctrl is
    procedure Initialize (X : in out T) is
    begin
       null;
    end Initialize;
end;
generic
package G is
    pragma Elaborate_Body;
end;
with Ctrl;
package body G is
    X : Ctrl.T;
end;
package Parent is
    procedure Require_Body;
end Parent;
with G;
with Parent;
package body Parent is
    package Instantiation is new G;
    procedure Require_Body is null;
end Parent;
with Parent;
procedure Main is
begin
    null;
end;

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

2017-01-06  Bob Duff  <duff@adacore.com>

	* sem_elab.adb (Activate_Elaborate_All_Desirable): Don't add
	Elaborate_All(P) to P itself. That could happen in obscure cases,
	and always introduced a cycle (P body must be elaborated before
	P body).
	* lib-writ.ads: Comment clarification.
	* ali-util.ads: Minor comment fix.
	* ali.adb: Minor reformatting.
diff mbox

Patch

Index: lib-writ.ads
===================================================================
--- lib-writ.ads	(revision 244124)
+++ lib-writ.ads	(working copy)
@@ -649,8 +649,10 @@ 
    --        AD  Elaborate_All_Desirable set for this unit, which means that
    --            there is no Elaborate_All, but the analysis suggests that
    --            Program_Error may be raised if the Elaborate_All conditions
-   --            cannot be satisfied. The binder will attempt to treat AD as
-   --            EA if it can.
+   --            cannot be satisfied. In dynamic elaboration mode, the binder
+   --            will attempt to treat AD as EA if it can. In static
+   --            elaboration mode, the binder will treat AD as EA, even if it
+   --            introduces cycles.
 
    --      The parameter source-name and lib-name are omitted for the case of a
    --      generic unit compiled with earlier versions of GNAT which did not
Index: ali-util.ads
===================================================================
--- ali-util.ads	(revision 244124)
+++ ali-util.ads	(working copy)
@@ -24,7 +24,7 @@ 
 ------------------------------------------------------------------------------
 
 --  This child unit provides utility data structures and procedures used
---  for manipulation of ALI data by the gnatbind and gnatmake.
+--  for manipulation of ALI data by gnatbind and gnatmake.
 
 package ALI.Util is
 
Index: sem_elab.adb
===================================================================
--- sem_elab.adb	(revision 244124)
+++ sem_elab.adb	(working copy)
@@ -446,6 +446,15 @@ 
          return;
       end if;
 
+      --  If an instance of a generic package contains a controlled object (so
+      --  we're calling Initialize at elaboration time), and the instance is in
+      --  a package body P that says "with P;", then we need to return without
+      --  adding "pragma Elaborate_All (P);" to P.
+
+      if U = Main_Unit_Entity then
+         return;
+      end if;
+
       Itm := First (CI);
       while Present (Itm) loop
          if Nkind (Itm) = N_With_Clause then
@@ -495,10 +504,8 @@ 
       end if;
 
       --  Here if we do not find with clause on spec or body. We just ignore
-      --  this case, it means that the elaboration involves some other unit
+      --  this case; it means that the elaboration involves some other unit
       --  than the unit being compiled, and will be caught elsewhere.
-
-      null;
    end Activate_Elaborate_All_Desirable;
 
    ------------------
@@ -528,7 +535,7 @@ 
        --  Generate a call to Error_Msg_NE with parameters Msg_D or Msg_S (for
        --  dynamic or static elaboration model), N and Ent. Msg_D is a real
        --  warning (output if Msg_D is non-null and Elab_Warnings is set),
-       --  Msg_S is an info message (output if Elab_Info_Messages is set.
+       --  Msg_S is an info message (output if Elab_Info_Messages is set).
 
       function Find_W_Scope return Entity_Id;
       --  Find top-level scope for called entity (not following renamings
Index: ali.adb
===================================================================
--- ali.adb	(revision 244124)
+++ ali.adb	(working copy)
@@ -2056,8 +2056,7 @@ 
                         --  Store AD indication unless ignore required
 
                         if not Ignore_ED then
-                           Withs.Table (Withs.Last).Elab_All_Desirable :=
-                             True;
+                           Withs.Table (Withs.Last).Elab_All_Desirable := True;
                         end if;
 
                      elsif Nextc = 'E' then