diff mbox

[Ada] Implementation of simple storage pools for dynamic allocation

Message ID 20120208092727.GA450@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Feb. 8, 2012, 9:27 a.m. UTC
The pragma Simple_Storage_Pool is provided for designating a library-level
limited private or limited record type as a simple storage pool type.
This provides an alternative to Ada's standard Storage_Pools, where
the pool type is not required to be tagged or have associated finalization
actions, eliminating the need for run-time support. A simple storage pool type
is defined with an Allocate operation, and optionally can have Deallocate
and Storage_Size operations (as well as other user-defined operations).
An access type can be associated with a pool object by setting the
attribute (or aspect) Simple_Storage_Pool. Allocators for the type will
invoke the pool's Allocate procedure, and unchecked deallocation invokes
the Deallocate operation (if defined).

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

2012-02-08  Gary Dismukes  <dismukes@adacore.com>

	* aspects.ads (type Aspect_Id): Add Aspect_Simple_Storage_Pool.
	(Impl_Defined_Aspects): Add entry for Aspect_Simple_Storage_Pool.
	(Aspect_Argument): Add Name entry for Aspect_Simple_Storage_Pool.
	(Aspect_Names): Add entry for Aspect_Simple_Storage_Pool.
	* aspects.adb (Canonical_Aspect): Add entry for
	Aspect_Simple_Storage_Pool.
	* exp_attr.adb (Expand_N_Attribute_Reference): Handle case of
	Attribute_Simple_Storage_Pool in the same way as Storage_Pool
	(add conversion, analyze/resolve). For the Storage_Size attribute,
	for the simple pool case, locate and use the simple pool type's
	Storage_Size function (if any), otherwise evaluate to zero.
	* exp_ch4.adb (Expand_N_Allocator): In the case of an allocator
	for an access type with an associated simple storage pool,
	locate and use the pool type's Allocate.
	* exp_intr.adb (Expand_Unc_Deallocation): In the case where the
	access type has a simple storage pool, locate the pool type's
	Deallocate procedure (if present) and use it as the procedure
	to call on the Free operation.
	* freeze.adb (Freeze_Entity): In the case of a full type for
	a private type defined with pragma Simple_Storage_Pool, check
	that the full type is also appropriate for the pragma. For
	a simple storage pool type, validate that the operations
	Allocate, Deallocate (if present), and Storage_Size
	(if present) are defined with appropriate expected profiles.
	(Validate_Simple_Pool_Op_Formal): New procedure
	(Validate_Simple_Pool_Operation): New procedure Add with and
	use of Rtsfind.
	* par-prag.adb: Add Pragma_Simple_Storage_Pool to case statement
	(no action required).
	* sem_attr.adb (Analyze_Attribute): For the case of the
	Storage_Pool attribute, give a warning if the prefix type has an
	associated simple storage pool, and rewrite the attribute as a
	raise of Program_Error. In the case of the Simple_Storage_Pool
	attribute, check that the prefix type has an associated simple
	storage pool, and set the attribute type to the pool's type.
	* sem_ch13.adb (Analyze_Aspect_Specifications): Add
	Aspect_Simple_Storage_Pool case choice.
	(Analyze_Attribute_Definition_Clause): Add
	Aspect_Simple_Storage_Pool to case for Ignore_Rep_Clauses
	(no action). Add handling for Simple_Storage_Pool attribute
	definition, requiring the name to denote a simple storage pool
	object.
	(Check_Aspect_At_Freeze_Point): For a simple storage pool
	aspect, set the type to that of the name specified for the aspect.
	* sem_prag.adb (Analyze_Pragma): Add handling for pragma
	Simple_Storage_Pool, requiring that it applies to a library-level
	type declared in a package declaration that is a limited private
	or limited record type.
	* sem_res.adb (Resolve_Allocator): Flag an attempt to call a
	build-in-place function in an allocator for an access type with
	a simple storage pool as unsupported.
	* snames.ads-tmpl: Add Name_Simple_Storage_Pool.
	(type Attribute_Id): Add Attribute_Simple_Storage_Pool.
	(type Pragma_Id): Add Pragma_Simple_Storage_Pool.
	* snames.adb-tmpl (Get_Pragma_Id): Handle case of
	Name_Simple_Storage_Pool.
	(Is_Pragma_Name): Return True for Name_Simple_Storage_Pool.
diff mbox

Patch

Index: exp_attr.adb
===================================================================
--- exp_attr.adb	(revision 183996)
+++ exp_attr.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2011, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2012, 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- --
@@ -4217,6 +4217,17 @@ 
       when Attribute_Scaling =>
          Expand_Fpt_Attribute_RI (N);
 
+      -------------------------
+      -- Simple_Storage_Pool --
+      -------------------------
+
+      when Attribute_Simple_Storage_Pool =>
+         Rewrite (N,
+           Make_Type_Conversion (Loc,
+             Subtype_Mark => New_Reference_To (Etype (N), Loc),
+             Expression   => New_Reference_To (Entity (N), Loc)));
+         Analyze_And_Resolve (N, Typ);
+
       ----------
       -- Size --
       ----------
@@ -4475,8 +4486,11 @@ 
       -- Storage_Size --
       ------------------
 
-      when Attribute_Storage_Size => Storage_Size : begin
+      when Attribute_Storage_Size => Storage_Size : declare
+         Alloc_Op  : Entity_Id := Empty;
 
+      begin
+
          --  Access type case, always go to the root type
 
          --  The case of access types results in a value of zero for the case
@@ -4497,20 +4511,65 @@ 
                          (Storage_Size_Variable (Root_Type (Ptyp)), Loc)))));
 
             elsif Present (Associated_Storage_Pool (Root_Type (Ptyp))) then
-               Rewrite (N,
-                 OK_Convert_To (Typ,
-                   Make_Function_Call (Loc,
-                     Name =>
-                       New_Reference_To
-                         (Find_Prim_Op
-                           (Etype (Associated_Storage_Pool (Root_Type (Ptyp))),
-                            Attribute_Name (N)),
-                          Loc),
 
-                     Parameter_Associations => New_List (
-                       New_Reference_To
-                         (Associated_Storage_Pool (Root_Type (Ptyp)), Loc)))));
+               --  If the access type is associated with a simple storage pool
+               --  object, then attempt to locate the optional Storage_Size
+               --  function of the simple storage pool type. If not found,
+               --  then the result will default to zero.
 
+               if Present (Get_Rep_Pragma (Root_Type (Ptyp),
+                                           Name_Simple_Storage_Pool))
+               then
+                  declare
+                     Pool_Type : constant Entity_Id :=
+                                   Base_Type (Etype (Entity (N)));
+
+                  begin
+                     Alloc_Op := Get_Name_Entity_Id (Name_Storage_Size);
+                     while Present (Alloc_Op) loop
+                        if Scope (Alloc_Op) = Scope (Pool_Type)
+                          and then Present (First_Formal (Alloc_Op))
+                          and then Etype (First_Formal (Alloc_Op)) = Pool_Type
+                        then
+                           exit;
+                        end if;
+
+                        Alloc_Op := Homonym (Alloc_Op);
+                     end loop;
+                  end;
+
+               --  In the normal Storage_Pool case, retrieve the primitive
+               --  function associated with the pool type.
+
+               else
+                  Alloc_Op :=
+                    Find_Prim_Op
+                      (Etype (Associated_Storage_Pool (Root_Type (Ptyp))),
+                       Attribute_Name (N));
+               end if;
+
+               --  If Storage_Size wasn't found (can only occur in the simple
+               --  storage pool case), then simply use zero for the result.
+
+               if not Present (Alloc_Op) then
+                  Rewrite (N, Make_Integer_Literal (Loc, 0));
+
+               --  Otherwise, rewrite the allocator as a call to pool type's
+               --  Storage_Size function.
+
+               else
+                  Rewrite (N,
+                    OK_Convert_To (Typ,
+                      Make_Function_Call (Loc,
+                        Name =>
+                          New_Reference_To (Alloc_Op, Loc),
+
+                        Parameter_Associations => New_List (
+                          New_Reference_To
+                            (Associated_Storage_Pool
+                               (Root_Type (Ptyp)), Loc)))));
+               end if;
+
             else
                Rewrite (N, Make_Integer_Literal (Loc, 0));
             end if;
Index: sem_prag.adb
===================================================================
--- sem_prag.adb	(revision 183996)
+++ sem_prag.adb	(working copy)
@@ -13150,6 +13150,65 @@ 
             Check_Valid_Configuration_Pragma;
             Short_Descriptors := True;
 
+         -------------------------
+         -- Simple_Storage_Pool --
+         -------------------------
+
+         --  pragma Simple_Storage_Pool (type_LOCAL_NAME);
+
+         when Pragma_Simple_Storage_Pool => Simple_Storage_Pool : declare
+               Type_Id : Node_Id;
+               Typ     : Entity_Id;
+
+         begin
+            GNAT_Pragma;
+            Check_Arg_Count (1);
+            Check_Arg_Is_Library_Level_Local_Name (Arg1);
+
+            Type_Id := Get_Pragma_Arg (Arg1);
+            Find_Type (Type_Id);
+            Typ := Entity (Type_Id);
+
+            if Typ = Any_Type then
+               return;
+            end if;
+
+            --  We require the pragma to apply to a type declared in a package
+            --  declaration, but not (immediately) within a package body.
+
+            if Ekind (Current_Scope) /= E_Package
+              or else In_Package_Body (Current_Scope)
+            then
+               Error_Pragma
+                 ("pragma% can only apply to type declared immediately " &
+                  "within a package declaration");
+            end if;
+
+            --  A simple storage pool type must be an immutably limited record
+            --  or private type. If the pragma is given for a private type,
+            --  the full type is similarly restricted (which is checked later
+            --  in Freeze_Entity).
+
+            if Is_Record_Type (Typ)
+              and then not Is_Immutably_Limited_Type (Typ)
+            then
+               Error_Pragma
+                 ("pragma% can only apply to explicitly limited record type");
+
+            elsif Is_Private_Type (Typ) and then not Is_Limited_Type (Typ) then
+               Error_Pragma
+                 ("pragma% can only apply to a private type that is limited");
+
+            elsif not Is_Record_Type (Typ)
+              and then not Is_Private_Type (Typ)
+            then
+               Error_Pragma
+                 ("pragma% can only apply to limited record or private type");
+            end if;
+
+            Record_Rep_Item (Typ, N);
+         end Simple_Storage_Pool;
+
          ----------------------
          -- Source_File_Name --
          ----------------------
@@ -15117,6 +15176,7 @@ 
       Pragma_Shared                         => -1,
       Pragma_Shared_Passive                 => -1,
       Pragma_Short_Descriptors              =>  0,
+      Pragma_Simple_Storage_Pool            =>  0,
       Pragma_Source_File_Name               => -1,
       Pragma_Source_File_Name_Project       => -1,
       Pragma_Source_Reference               => -1,
Index: freeze.adb
===================================================================
--- freeze.adb	(revision 183996)
+++ freeze.adb	(working copy)
@@ -42,6 +42,7 @@ 
 with Opt;      use Opt;
 with Restrict; use Restrict;
 with Rident;   use Rident;
+with Rtsfind; use Rtsfind;
 with Sem;      use Sem;
 with Sem_Aux;  use Sem_Aux;
 with Sem_Cat;  use Sem_Cat;
@@ -4103,6 +4104,281 @@ 
                   end loop;
                end;
             end if;
+
+            --  If the type is a simple storage pool type, then this is where
+            --  we attempt to locate and validate its Allocate, Deallocate, and
+            --  Storage_Size operations (the first is required, and the latter
+            --  two are optional). We also verify that the full type for a
+            --  private type is allowed to be a simple storage pool type.
+
+            if Present (Get_Rep_Pragma (E, Name_Simple_Storage_Pool))
+              and then (Is_Base_Type (E) or else Has_Private_Declaration (E))
+            then
+
+               --  If the type is marked Has_Private_Declaration, then this is
+               --  a full type for a private type that was specified with the
+               --  pragma Simple_Storage_Pool, and here we ensure that the
+               --  pragma is allowed for the full type (for example, it can't
+               --  be an array type, or a nonlimited record type).
+
+               if Has_Private_Declaration (E) then
+                  if (not Is_Record_Type (E)
+                       or else not Is_Immutably_Limited_Type (E))
+                    and then not Is_Private_Type (E)
+                  then
+                     Error_Msg_Name_1 := Name_Simple_Storage_Pool;
+
+                     Error_Msg_N
+                       ("pragma% can only apply to full type that is an " &
+                        "explicitly limited type", E);
+                  end if;
+               end if;
+
+               Validate_Simple_Pool_Ops : declare
+                  Pool_Type    : Entity_Id renames E;
+                  Address_Type : constant Entity_Id := RTE (RE_Address);
+                  Stg_Cnt_Type : constant Entity_Id := RTE (RE_Storage_Count);
+
+                  procedure Validate_Simple_Pool_Op_Formal
+                    (Pool_Op        : Entity_Id;
+                     Pool_Op_Formal : in out Entity_Id;
+                     Expected_Mode  : Formal_Kind;
+                     Expected_Type  : Entity_Id;
+                     Formal_Name    : String;
+                     OK_Formal      : in out Boolean);
+                  --  Validate one formal Pool_Op_Formal of the candidate pool
+                  --  operation Pool_Op. The formal must be of Expected_Type
+                  --  and have mode Expected_Mode. OK_Formal will be set to
+                  --  False if the formal doesn't match. If OK_Formal is False
+                  --  on entry, then the formal will effectively be ignored
+                  --  (because validation of the pool op has already failed).
+                  --  Upon return, Pool_Op_Formal will be updated to the next
+                  --  formal, if any.
+
+                  procedure Validate_Simple_Pool_Operation (Op_Name : Name_Id);
+                  --  Search for and validate a simple pool operation with the
+                  --  name Op_Name. If the name is Allocate, then there must be
+                  --  exactly one such primitive operation for the simple pool
+                  --  type. If the name is Deallocate or Storage_Size, then
+                  --  there can be at most one such primitive operation. The
+                  --  profile of the located primitive must conform to what
+                  --  is expected for each operation.
+
+                  ------------------------------------
+                  -- Validate_Simple_Pool_Op_Formal --
+                  ------------------------------------
+
+                  procedure Validate_Simple_Pool_Op_Formal
+                    (Pool_Op        : Entity_Id;
+                     Pool_Op_Formal : in out Entity_Id;
+                     Expected_Mode  : Formal_Kind;
+                     Expected_Type  : Entity_Id;
+                     Formal_Name    : String;
+                     OK_Formal      : in out Boolean)
+                  is
+                  begin
+                     --  If OK_Formal is False on entry, then simply ignore
+                     --  the formal, because an earlier formal has already
+                     --  been flagged.
+
+                     if not OK_Formal then
+                        return;
+
+                     --  If no formal is passed in, then issue an error for a
+                     --  missing formal.
+
+                     elsif not Present (Pool_Op_Formal) then
+                        Error_Msg_NE
+                          ("simple storage pool op missing formal " &
+                           Formal_Name & " of type&", Pool_Op, Expected_Type);
+                        OK_Formal := False;
+
+                        return;
+                     end if;
+
+                     if Etype (Pool_Op_Formal) /= Expected_Type then
+                        --  If the pool type was expected for this formal, then
+                        --  this will not be considered a candidate operation
+                        --  for the simple pool, so we unset OK_Formal so that
+                        --  the op and any later formals will be ignored.
+
+                        if Expected_Type = Pool_Type then
+                           OK_Formal := False;
+
+                           return;
+
+                        else
+                           Error_Msg_NE
+                             ("wrong type for formal " & Formal_Name &
+                              " of simple storage pool op; expected type&",
+                              Pool_Op_Formal, Expected_Type);
+                        end if;
+                     end if;
+
+                     --  Issue error if formal's mode is not the expected one
+
+                     if Ekind (Pool_Op_Formal) /= Expected_Mode then
+                        Error_Msg_N
+                          ("wrong mode for formal of simple storage pool op",
+                           Pool_Op_Formal);
+                     end if;
+
+                     --  Advance to the next formal
+
+                     Next_Formal (Pool_Op_Formal);
+                  end Validate_Simple_Pool_Op_Formal;
+
+                  ------------------------------------
+                  -- Validate_Simple_Pool_Operation --
+                  ------------------------------------
+
+                  procedure Validate_Simple_Pool_Operation
+                    (Op_Name : Name_Id)
+                  is
+                     Op       : Entity_Id;
+                     Found_Op : Entity_Id := Empty;
+                     Formal   : Entity_Id;
+                     Is_OK    : Boolean;
+
+                  begin
+                     pragma Assert
+                       (Op_Name = Name_Allocate
+                          or else Op_Name = Name_Deallocate
+                          or else Op_Name = Name_Storage_Size);
+
+                     Error_Msg_Name_1 := Op_Name;
+
+                     --  For each homonym declared immediately in the scope
+                     --  of the simple storage pool type, determine whether
+                     --  the homonym is an operation of the pool type, and,
+                     --  if so, check that its profile is as expected for
+                     --  a simple pool operation of that name.
+
+                     Op := Get_Name_Entity_Id (Op_Name);
+                     while Present (Op) loop
+                        if Ekind_In (Op, E_Function, E_Procedure)
+                          and then Scope (Op) = Current_Scope
+                        then
+                           Formal := First_Entity (Op);
+
+                           Is_OK := True;
+
+                           --  The first parameter must be of the pool type
+                           --  in order for the operation to qualify.
+
+                           if Op_Name = Name_Storage_Size then
+                              Validate_Simple_Pool_Op_Formal
+                                (Op, Formal, E_In_Parameter, Pool_Type,
+                                 "Pool", Is_OK);
+
+                           else
+                              Validate_Simple_Pool_Op_Formal
+                                (Op, Formal, E_In_Out_Parameter, Pool_Type,
+                                 "Pool", Is_OK);
+                           end if;
+
+                           --  If another operation with this name has already
+                           --  been located for the type, then flag an error,
+                           --  since we only allow the type to have a single
+                           --  such primitive.
+
+                           if Present (Found_Op) and then Is_OK then
+                              Error_Msg_NE
+                                ("only one % operation allowed for " &
+                                 "simple storage pool type&", Op, Pool_Type);
+                           end if;
+
+                           --  In the case of Allocate and Deallocate, a formal
+                           --  of type System.Address is required.
+
+                           if Op_Name = Name_Allocate then
+                              Validate_Simple_Pool_Op_Formal
+                                (Op, Formal, E_Out_Parameter,
+                                 Address_Type, "Storage_Address", Is_OK);
+
+                           elsif Op_Name = Name_Deallocate then
+                              Validate_Simple_Pool_Op_Formal
+                                (Op, Formal, E_In_Parameter,
+                                 Address_Type, "Storage_Address", Is_OK);
+                           end if;
+
+                           --  In the case of Allocate and Deallocate, formals
+                           --  of type Storage_Count are required as the third
+                           --  and fourth parameters.
+
+                           if Op_Name /= Name_Storage_Size then
+                              Validate_Simple_Pool_Op_Formal
+                                (Op, Formal, E_In_Parameter,
+                                 Stg_Cnt_Type, "Size_In_Storage_Units", Is_OK);
+
+                              Validate_Simple_Pool_Op_Formal
+                                (Op, Formal, E_In_Parameter,
+                                 Stg_Cnt_Type, "Alignment", Is_OK);
+                           end if;
+
+                           --  If no mismatched formals have been found (Is_OK)
+                           --  and no excess formals are present, then this
+                           --  operation has been validated, so record it.
+
+                           if not Present (Formal) and then Is_OK then
+                              Found_Op := Op;
+                           end if;
+                        end if;
+
+                        Op := Homonym (Op);
+                     end loop;
+
+                     --  There must be a valid Allocate operation for the type,
+                     --  so issue an error if none was found.
+
+                     if Op_Name = Name_Allocate
+                       and then not Present (Found_Op)
+                     then
+                        Error_Msg_N ("missing % operation for simple " &
+                                     "storage pool type", Pool_Type);
+
+                     elsif Present (Found_Op) then
+                        --  Simple pool operations can't be abstract
+
+                        if Is_Abstract_Subprogram (Found_Op) then
+                           Error_Msg_N
+                             ("simple storage pool operation must not be " &
+                              "abstract", Found_Op);
+                        end if;
+
+                        --  The Storage_Size operation must be a function with
+                        --  Storage_Count as its result type.
+
+                        if Op_Name = Name_Storage_Size then
+                           if Ekind (Found_Op) = E_Procedure then
+                              Error_Msg_N
+                                ("% operation must be a function", Found_Op);
+
+                           elsif Etype (Found_Op) /= Stg_Cnt_Type then
+                              Error_Msg_NE
+                                ("wrong result type for%, expected type&",
+                                 Found_Op, Stg_Cnt_Type);
+                           end if;
+
+                        --  Allocate and Deallocate must be procedures
+
+                        elsif Ekind (Found_Op) = E_Function then
+                           Error_Msg_N
+                             ("% operation must be a procedure", Found_Op);
+                        end if;
+                     end if;
+                  end Validate_Simple_Pool_Operation;
+
+               --  Start of processing for Validate_Simple_Pool_Ops
+
+               begin
+                  Validate_Simple_Pool_Operation (Name_Allocate);
+
+                  Validate_Simple_Pool_Operation (Name_Deallocate);
+
+                  Validate_Simple_Pool_Operation (Name_Storage_Size);
+               end Validate_Simple_Pool_Ops;
+            end if;
          end if;
 
          --  Now that all types from which E may depend are frozen, see if the
Index: sem_res.adb
===================================================================
--- sem_res.adb	(revision 183996)
+++ sem_res.adb	(working copy)
@@ -4228,6 +4228,31 @@ 
             Wrong_Type (Expression (E), Etype (E));
          end if;
 
+         --  Calls to build-in-place functions are not currently supported in
+         --  allocators for access types associated with a simple storage pool.
+         --  Supporting such allocators may require passing additional implicit
+         --  parameters to build-in-place functions (or a significant revision
+         --  of the current b-i-p implementation to unify the handling for
+         --  multiple kinds of storage pools). ???
+
+         if Is_Immutably_Limited_Type (Desig_T)
+           and then Nkind (Expression (E)) = N_Function_Call
+         then
+            declare
+               Pool : constant Entity_Id
+                        := Associated_Storage_Pool (Root_Type (Typ));
+            begin
+               if Present (Pool)
+                 and then Present (Get_Rep_Pragma
+                                     (Etype (Pool), Name_Simple_Storage_Pool))
+               then
+                  Error_Msg_N
+                    ("limited function calls not yet supported in simple " &
+                     "storage pool allocators", Expression (E));
+               end if;
+            end;
+         end if;
+
          --  A special accessibility check is needed for allocators that
          --  constrain access discriminants. The level of the type of the
          --  expression used to constrain an access discriminant cannot be
Index: sem_attr.adb
===================================================================
--- sem_attr.adb	(revision 183996)
+++ sem_attr.adb	(working copy)
@@ -4528,7 +4528,8 @@ 
       -- Storage_Pool --
       ------------------
 
-      when Attribute_Storage_Pool => Storage_Pool :
+      when Attribute_Storage_Pool        |
+           Attribute_Simple_Storage_Pool => Storage_Pool :
       begin
          Check_E0;
 
@@ -4546,8 +4547,39 @@ 
                Set_Entity (N, RTE (RE_Global_Pool_Object));
             end if;
 
-            Set_Etype (N, Class_Wide_Type (RTE (RE_Root_Storage_Pool)));
+            if Attr_Id = Attribute_Storage_Pool then
+               if Present (Get_Rep_Pragma (Etype (Entity (N)),
+                                           Name_Simple_Storage_Pool))
+               then
+                  Error_Msg_Name_1 := Aname;
+                  Error_Msg_N ("cannot use % attribute for type with simple " &
+                               "storage pool?", N);
+                  Error_Msg_N
+                     ("\Program_Error will be raised at run time?", N);
 
+                  Rewrite
+                    (N, Make_Raise_Program_Error
+                          (Sloc (N), Reason => PE_Explicit_Raise));
+               end if;
+
+               Set_Etype (N, Class_Wide_Type (RTE (RE_Root_Storage_Pool)));
+
+            --  In the Simple_Storage_Pool case, verify that the pool entity is
+            --  actually of a simple storage pool type, and set the attribute's
+            --  type to the pool object's type.
+
+            else
+               if not Present (Get_Rep_Pragma (Etype (Entity (N)),
+                                               Name_Simple_Storage_Pool))
+               then
+                  Error_Attr_P
+                    ("cannot use % attribute for type without simple " &
+                     "storage pool");
+               end if;
+
+               Set_Etype (N, Etype (Entity (N)));
+            end if;
+
             --  Validate_Remote_Access_To_Class_Wide_Type for attribute
             --  Storage_Pool since this attribute is not defined for such
             --  types (RM E.2.3(22)).
@@ -7931,6 +7963,7 @@ 
            Attribute_Priority                   |
            Attribute_Read                       |
            Attribute_Result                     |
+           Attribute_Simple_Storage_Pool        |
            Attribute_Storage_Pool               |
            Attribute_Storage_Size               |
            Attribute_Storage_Unit               |
Index: exp_ch4.adb
===================================================================
--- exp_ch4.adb	(revision 183996)
+++ exp_ch4.adb	(working copy)
@@ -3565,6 +3565,31 @@ 
                   Set_Procedure_To_Call (N, RTE (RE_SS_Allocate));
                end if;
 
+            --  In the case of an allocator for a simple storage pool, locate
+            --  and save a reference to the pool type's Allocate routine.
+
+            elsif Present (Get_Rep_Pragma
+                             (Etype (Pool), Name_Simple_Storage_Pool))
+            then
+               declare
+                  Alloc_Op  : Entity_Id := Get_Name_Entity_Id (Name_Allocate);
+                  Pool_Type : constant Entity_Id := Base_Type (Etype (Pool));
+
+               begin
+                  while Present (Alloc_Op) loop
+                     if Scope (Alloc_Op) = Scope (Pool_Type)
+                       and then Present (First_Formal (Alloc_Op))
+                       and then Etype (First_Formal (Alloc_Op)) = Pool_Type
+                     then
+                        Set_Procedure_To_Call (N, Alloc_Op);
+
+                        exit;
+                     end if;
+
+                     Alloc_Op := Homonym (Alloc_Op);
+                  end loop;
+               end;
+
             elsif Is_Class_Wide_Type (Etype (Pool)) then
                Set_Procedure_To_Call (N, RTE (RE_Allocate_Any));
 
Index: aspects.adb
===================================================================
--- aspects.adb	(revision 183996)
+++ aspects.adb	(working copy)
@@ -298,6 +298,7 @@ 
     Aspect_Remote_Access_Type           => Aspect_Remote_Access_Type,
     Aspect_Read                         => Aspect_Read,
     Aspect_Shared                       => Aspect_Atomic,
+    Aspect_Simple_Storage_Pool          => Aspect_Simple_Storage_Pool,
     Aspect_Size                         => Aspect_Size,
     Aspect_Small                        => Aspect_Small,
     Aspect_Static_Predicate             => Aspect_Predicate,
Index: aspects.ads
===================================================================
--- aspects.ads	(revision 183996)
+++ aspects.ads	(working copy)
@@ -74,6 +74,7 @@ 
       Aspect_Predicate,                     -- GNAT
       Aspect_Priority,
       Aspect_Read,
+      Aspect_Simple_Storage_Pool,           -- GNAT
       Aspect_Size,
       Aspect_Small,
       Aspect_Static_Predicate,
@@ -186,6 +187,7 @@ 
                              Aspect_Pure_Function        => True,
                              Aspect_Remote_Access_Type   => True,
                              Aspect_Shared               => True,
+                             Aspect_Simple_Storage_Pool  => True,
                              Aspect_Suppress_Debug_Info  => True,
                              Aspect_Test_Case            => True,
                              Aspect_Universal_Data       => True,
@@ -277,6 +279,7 @@ 
                         Aspect_Predicate               => Expression,
                         Aspect_Priority                => Expression,
                         Aspect_Read                    => Name,
+                        Aspect_Simple_Storage_Pool     => Name,
                         Aspect_Size                    => Expression,
                         Aspect_Small                   => Expression,
                         Aspect_Static_Predicate        => Expression,
@@ -364,6 +367,7 @@ 
      Aspect_Remote_Types                 => Name_Remote_Types,
      Aspect_Shared                       => Name_Shared,
      Aspect_Shared_Passive               => Name_Shared_Passive,
+     Aspect_Simple_Storage_Pool          => Name_Simple_Storage_Pool,
      Aspect_Size                         => Name_Size,
      Aspect_Small                        => Name_Small,
      Aspect_Static_Predicate             => Name_Static_Predicate,
Index: par-prag.adb
===================================================================
--- par-prag.adb	(revision 183996)
+++ par-prag.adb	(working copy)
@@ -1230,6 +1230,7 @@ 
            Pragma_Shared_Passive                 |
            Pragma_Short_Circuit_And_Or           |
            Pragma_Short_Descriptors              |
+           Pragma_Simple_Storage_Pool            |
            Pragma_Storage_Size                   |
            Pragma_Storage_Unit                   |
            Pragma_Static_Elaboration_Desired     |
Index: snames.adb-tmpl
===================================================================
--- snames.adb-tmpl	(revision 183996)
+++ snames.adb-tmpl	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2011, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2012, 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- --
@@ -217,6 +217,8 @@ 
          return Pragma_Priority;
       elsif N = Name_Relative_Deadline then
          return Pragma_Relative_Deadline;
+      elsif N = Name_Simple_Storage_Pool then
+         return Pragma_Simple_Storage_Pool;
       elsif N = Name_Storage_Size then
          return Pragma_Storage_Size;
       elsif N = Name_Storage_Unit then
@@ -414,6 +416,7 @@ 
         or else N = Name_Interface
         or else N = Name_Relative_Deadline
         or else N = Name_Priority
+        or else N = Name_Simple_Storage_Pool
         or else N = Name_Storage_Size
         or else N = Name_Storage_Unit;
    end Is_Pragma_Name;
Index: exp_intr.adb
===================================================================
--- exp_intr.adb	(revision 183996)
+++ exp_intr.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2011, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2012, 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- --
@@ -1084,6 +1084,34 @@ 
          if Is_RTE (Pool, RE_SS_Pool) then
             null;
 
+         --  If the pool object is of a simple storage pool type, then attempt
+         --  to locate the type's Deallocate procedure, if any, and set the
+         --  free operation's procedure to call. If the type doesn't have a
+         --  Deallocate (which is allowed), then the actual will simply be set
+         --  to null.
+
+         elsif Present (Get_Rep_Pragma
+                          (Etype (Pool), Name_Simple_Storage_Pool))
+         then
+            declare
+               Dealloc_Op  : Entity_Id := Get_Name_Entity_Id (Name_Deallocate);
+               Pool_Type : constant Entity_Id := Base_Type (Etype (Pool));
+
+            begin
+               while Present (Dealloc_Op) loop
+                  if Scope (Dealloc_Op) = Scope (Pool_Type)
+                    and then Present (First_Formal (Dealloc_Op))
+                    and then Etype (First_Formal (Dealloc_Op)) = Pool_Type
+                  then
+                     Set_Procedure_To_Call (Free_Node, Dealloc_Op);
+
+                     exit;
+                  end if;
+
+                  Dealloc_Op := Homonym (Dealloc_Op);
+               end loop;
+            end;
+
          --  Case of a class-wide pool type: make a dispatching call to
          --  Deallocate through the class-wide Deallocate_Any.
 
Index: sem_ch13.adb
===================================================================
--- sem_ch13.adb	(revision 183996)
+++ sem_ch13.adb	(working copy)
@@ -1064,23 +1064,24 @@ 
 
                --  Aspects corresponding to attribute definition clauses
 
-               when Aspect_Address        |
-                    Aspect_Alignment      |
-                    Aspect_Bit_Order      |
-                    Aspect_Component_Size |
-                    Aspect_External_Tag   |
-                    Aspect_Input          |
-                    Aspect_Machine_Radix  |
-                    Aspect_Object_Size    |
-                    Aspect_Output         |
-                    Aspect_Read           |
-                    Aspect_Size           |
-                    Aspect_Small          |
-                    Aspect_Storage_Pool   |
-                    Aspect_Storage_Size   |
-                    Aspect_Stream_Size    |
-                    Aspect_Value_Size     |
-                    Aspect_Write          =>
+               when Aspect_Address             |
+                    Aspect_Alignment           |
+                    Aspect_Bit_Order           |
+                    Aspect_Component_Size      |
+                    Aspect_External_Tag        |
+                    Aspect_Input               |
+                    Aspect_Machine_Radix       |
+                    Aspect_Object_Size         |
+                    Aspect_Output              |
+                    Aspect_Read                |
+                    Aspect_Size                |
+                    Aspect_Small               |
+                    Aspect_Simple_Storage_Pool |
+                    Aspect_Storage_Pool        |
+                    Aspect_Storage_Size        |
+                    Aspect_Stream_Size         |
+                    Aspect_Value_Size          |
+                    Aspect_Write               =>
 
                   --  Construct the attribute definition clause
 
@@ -2210,13 +2211,14 @@ 
             --  legality, e.g. failing to provide a stream attribute for a
             --  type may make a program illegal.
 
-            when Attribute_External_Tag |
-                 Attribute_Input        |
-                 Attribute_Output       |
-                 Attribute_Read         |
-                 Attribute_Storage_Pool |
-                 Attribute_Storage_Size |
-                 Attribute_Write        =>
+            when Attribute_External_Tag        |
+                 Attribute_Input               |
+                 Attribute_Output              |
+                 Attribute_Read                |
+                 Attribute_Simple_Storage_Pool |
+                 Attribute_Storage_Pool        |
+                 Attribute_Storage_Size        |
+                 Attribute_Write               =>
                null;
 
             --  Other cases are errors ("attribute& cannot be set with
@@ -3163,7 +3165,7 @@ 
 
          --  Storage_Pool attribute definition clause
 
-         when Attribute_Storage_Pool => Storage_Pool : declare
+         when Attribute_Storage_Pool | Attribute_Simple_Storage_Pool => declare
             Pool : Entity_Id;
             T    : Entity_Id;
 
@@ -3194,9 +3196,25 @@ 
                return;
             end if;
 
-            Analyze_And_Resolve
-              (Expr, Class_Wide_Type (RTE (RE_Root_Storage_Pool)));
+            if Id = Attribute_Storage_Pool then
+               Analyze_And_Resolve
+                 (Expr, Class_Wide_Type (RTE (RE_Root_Storage_Pool)));
 
+            --  In the Simple_Storage_Pool case, we allow a variable of any
+            --  Simple_Storage_Pool type, so we Resolve without imposing an
+            --  expected type.
+
+            else
+               Analyze_And_Resolve (Expr);
+
+               if not Present (Get_Rep_Pragma
+                                 (Etype (Expr), Name_Simple_Storage_Pool))
+               then
+                  Error_Msg_N
+                    ("expression must be of a simple storage pool type", Expr);
+               end if;
+            end if;
+
             if not Denotes_Variable (Expr) then
                Error_Msg_N ("storage pool must be a variable", Expr);
                return;
@@ -3280,7 +3298,7 @@ 
                Error_Msg_N ("incorrect reference to a Storage Pool", Expr);
                return;
             end if;
-         end Storage_Pool;
+         end;
 
          ------------------
          -- Storage_Size --
@@ -6147,6 +6165,13 @@ 
          when Aspect_Small =>
             T := Universal_Real;
 
+         --  For a simple storage pool, we have to retrieve the type of the
+         --  pool object associated with the aspect's corresponding attribute
+         --  definition clause.
+
+         when Aspect_Simple_Storage_Pool =>
+            T := Etype (Expression (Aspect_Rep_Item (ASN)));
+
          when Aspect_Storage_Pool =>
             T := Class_Wide_Type (RTE (RE_Root_Storage_Pool));
 
Index: snames.ads-tmpl
===================================================================
--- snames.ads-tmpl	(revision 183996)
+++ snames.ads-tmpl	(working copy)
@@ -909,6 +909,7 @@ 
    Name_Elab_Body                      : constant Name_Id := N + $; -- GNAT
    Name_Elab_Spec                      : constant Name_Id := N + $; -- GNAT
    Name_Elab_Subp_Body                 : constant Name_Id := N + $; -- GNAT
+   Name_Simple_Storage_Pool            : constant Name_Id := N + $; -- GNAT
    Name_Storage_Pool                   : constant Name_Id := N + $;
 
    --  These attributes are the ones that return types
@@ -1459,6 +1460,7 @@ 
       Attribute_Elab_Body,
       Attribute_Elab_Spec,
       Attribute_Elab_Subp_Body,
+      Attribute_Simple_Storage_Pool,
       Attribute_Storage_Pool,
 
       --  Type attributes
@@ -1730,6 +1732,7 @@ 
       Pragma_Fast_Math,
       Pragma_Interface,
       Pragma_Priority,
+      Pragma_Simple_Storage_Pool,
       Pragma_Storage_Size,
       Pragma_Storage_Unit,