This patch corrects the mechanism which handles limited with clauses to semi- declare abstract states (the states are fully declared when Abstract_States is analyzed). The end result is that multiple limited with clauses now reference one unique entity which denotes the state.
------------ -- Source -- ------------ -- aip.ads package AIP with SPARK_Mode is pragma Pure; end AIP; -- aip-ip.ads limited with AIP.UDP; limited with AIP.TCP; package AIP.IP with SPARK_Mode, Abstract_State => (FIB, State), Initializes => (FIB, State) is procedure IP_Input (Netif : Integer; Buf : Integer) with Global => (Input => (FIB, UDP.State), In_Out => (TCP.State, State)); pragma Export (C, IP_Input, "AIP_ip_input"); end AIP.IP; -- aip-ip.adb with AIP.UDP; with AIP.TCP; package body AIP.IP with SPARK_Mode, Refined_State => (State => IP_Serial, FIB => Default_Router) is Default_Router : Integer := 0; IP_Serial : Integer := 0; procedure IP_Input (Netif : Integer; Buf : Integer) with Refined_Global => (Input => (Default_Router, UDP.State), In_Out => (IP_Serial, TCP.State)) is begin null; end IP_Input; end AIP.IP; -- aip-tcp.ads limited with AIP.IP; package AIP.TCP with SPARK_Mode, Abstract_State => State is procedure TCP_Input (Buf : Integer; Netif : Integer) with Global => (Input => IP.FIB, In_Out => (IP.State, State)); end AIP.TCP; -- aip-udp.ads with AIP.IP; package AIP.UDP with SPARK_Mode, Abstract_State => State is procedure UDP_Input (Buf : Integer; Netif : Integer) with Global => (Input => State); end AIP.UDP; ----------------- -- Compilation -- ----------------- $ gcc -c aip-ip.adb Tested on x86_64-pc-linux-gnu, committed on trunk 2014-07-31 Hristian Kirtchev <kirtc...@adacore.com> * sem_ch10.adb (Process_State): Remove local variable Name. Add local variable Decl. Partially declare an abstract state by generating an entity and storing it in the state declaration. * sem_prag.adb (Create_Abstract_State): Fully declare a semi-declared abstract state.
Index: sem_ch10.adb =================================================================== --- sem_ch10.adb (revision 213264) +++ sem_ch10.adb (working copy) @@ -5695,10 +5695,10 @@ procedure Process_State (State : Node_Id) is Loc : constant Source_Ptr := Sloc (State); + Decl : Node_Id; + Dummy : Entity_Id; Elmt : Node_Id; Id : Entity_Id; - Name : Name_Id; - Dummy : Entity_Id; begin -- Multiple abstract states appear as an aggregate @@ -5721,12 +5721,12 @@ -- extension aggregate. elsif Nkind (State) = N_Extension_Aggregate then - Name := Chars (Ancestor_Part (State)); + Decl := Ancestor_Part (State); -- Simple state declaration elsif Nkind (State) = N_Identifier then - Name := Chars (State); + Decl := State; -- Possibly an illegal state declaration @@ -5734,15 +5734,27 @@ return; end if; - -- Construct a dummy state for the purposes of establishing a - -- non-limited => limited view relation. Note that the dummy - -- state is not added to list Abstract_States to avoid multiple - -- definitions. + -- Abstract states are elaborated when the related pragma is + -- elaborated. Since the withed package is not analyzed yet, + -- the entities of the abstract states are not available. To + -- overcome this complication, create the entities now and + -- store them in their respective declarations. The entities + -- are later used by routine Create_Abstract_State to declare + -- and enter the states into visibility. - Id := Make_Defining_Identifier (Loc, New_External_Name (Name)); - Set_Parent (Id, State); - Decorate_State (Id, Scop); + if No (Entity (Decl)) then + Id := Make_Defining_Identifier (Loc, Chars (Decl)); + Set_Entity (Decl, Id); + Set_Parent (Id, State); + Decorate_State (Id, Scop); + + -- Otherwise the package was previously withed + + else + Id := Entity (Decl); + end if; + Build_Shadow_Entity (Id, Scop, Dummy); end Process_State; Index: sem_prag.adb =================================================================== --- sem_prag.adb (revision 213271) +++ sem_prag.adb (working copy) @@ -10519,11 +10519,24 @@ Is_Null : Boolean) is begin - -- The generated state abstraction reuses the same chars - -- from the original state declaration. Decorate the entity. + -- The abstract state may be semi-declared when the related + -- package was withed through a limited with clause. In that + -- case reuse the entity to fully declare the state. - State_Id := Make_Defining_Identifier (Loc, Nam); + if Present (Decl) and then Present (Entity (Decl)) then + State_Id := Entity (Decl); + -- Otherwise the elaboration of pragma Abstract_State + -- declares the state. + + else + State_Id := Make_Defining_Identifier (Loc, Nam); + + if Present (Decl) then + Set_Entity (Decl, State_Id); + end if; + end if; + -- Null states never come from source Set_Comes_From_Source (State_Id, not Is_Null);