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 <d...@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.
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