If a library level package declaration or generic package declaration
contains a non-null abstract state, and does not otherwise require a
body, then in accorance with SPARK (LRM 7.1.5(4)), the package must
contain a pragma Elaborate_Body. This implements this requirement,
as shown in the following compiled with -gnatj60 -gnatd.V.
1. package Needs_Pragma_Elaborate_Body
2. with Abstract_State => State
|
>>> package "Needs_Pragma_Elaborate_Body" specifies
a non-null abstract state, but package does not
otherwise require a body, pragma Elaborate_Body
is required in this case
3. is
4. -- package declarations with non-null
5. -- Abstract State shall have bodies.
6.
7. -- There should be a pragma Elaborate_Body
8. end Needs_Pragma_Elaborate_Body;
Tested on x86_64-pc-linux-gnu, committed on trunk
2013-10-15 Robert Dewar <[email protected]>
* sem_ch7.adb (Unit_Requires_Body): Add flag
Ignore_Abstract_State (Analyze_Package_Specification): Enforce
rule requiring Elaborate_Body if a non-null abstract state is
specified for a library-level package.
* sem_ch7.ads (Unit_Requires_Body): Add flag Ignore_Abstract_State.
Index: sem_ch7.adb
===================================================================
--- sem_ch7.adb (revision 203568)
+++ sem_ch7.adb (working copy)
@@ -1483,7 +1483,38 @@
Clear_Constants (Id, First_Private_Entity (Id));
end if;
+ -- Issue an error in SPARK mode if a package specification contains
+ -- more than one tagged type or type extension.
+
Check_One_Tagged_Type_Or_Extension_At_Most;
+
+ -- Issue an error if a package that is a library unit does not require a
+ -- body, and we have a non-null abstract state (SPARK LRM 7.1.5(4)).
+
+ if not Unit_Requires_Body (Id, Ignore_Abstract_State => True)
+ and then Present (Abstract_States (Id))
+
+ -- We use Scope_Depth of 1 to identify library units, which seems a
+ -- bit ugly, but there doesn't seem to be an easier way.
+
+ and then Scope_Depth (Id) = 1
+
+ -- A null abstract state always appears as the sole element of the
+ -- state list.
+
+ and then not Is_Null_State (Node (First_Elmt (Abstract_States (Id))))
+ then
+ declare
+ P : constant Node_Id := Get_Pragma (Id, Pragma_Abstract_State);
+ begin
+ Error_Msg_NE
+ ("package & specifies a non-null abstract state", P, Id);
+ Error_Msg_N
+ ("\but package does not otherwise require a body", P);
+ Error_Msg_N
+ ("\pragma Elaborate_Body is required in this case", P);
+ end;
+ end if;
end Analyze_Package_Specification;
--------------------------------------
@@ -2588,7 +2619,10 @@
-- Unit_Requires_Body --
------------------------
- function Unit_Requires_Body (P : Entity_Id) return Boolean is
+ function Unit_Requires_Body
+ (P : Entity_Id;
+ Ignore_Abstract_State : Boolean := False) return Boolean
+ is
E : Entity_Id;
begin
@@ -2627,12 +2661,17 @@
end;
-- A [generic] package that introduces at least one non-null abstract
- -- state requires completion. A null abstract state always appears as
- -- the sole element of the state list.
+ -- state requires completion. However, there is a separate rule that
+ -- requires that such a package have a reason other than this for a
+ -- body being required (if necessary a pragma Elaborate_Body must be
+ -- provided). If Ignore_Abstract_State is True, we don't do this check
+ -- (so we can use Unit_Requires_Body to check for some other reason).
elsif Ekind_In (P, E_Generic_Package, E_Package)
+ and then not Ignore_Abstract_State
and then Present (Abstract_States (P))
- and then not Is_Null_State (Node (First_Elmt (Abstract_States (P))))
+ and then
+ not Is_Null_State (Node (First_Elmt (Abstract_States (P))))
then
return True;
end if;
Index: sem_ch7.ads
===================================================================
--- sem_ch7.ads (revision 203568)
+++ sem_ch7.ads (working copy)
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2008, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -52,9 +52,15 @@
-- but is deferred until the compilation of the private part of the
-- child for public child packages.
- function Unit_Requires_Body (P : Entity_Id) return Boolean;
- -- Check if a unit requires a body. A specification requires a body
- -- if it contains declarations that require completion in a body.
+ function Unit_Requires_Body
+ (P : Entity_Id;
+ Ignore_Abstract_State : Boolean := False) return Boolean;
+ -- Check if a unit requires a body. A specification requires a body if it
+ -- contains declarations that require completion in a body. If the flag
+ -- Ignore_Abstract_State is set True, then the test for a non-null abstract
+ -- state (which normally requires a body) is not carried out. This allows
+ -- the use of this routine to tell if there is some other reason that a
+ -- body is required (as is required for analyzing Abstract_State).
procedure May_Need_Implicit_Body (E : Entity_Id);
-- If a package declaration contains tasks or RACWs and does not require