diff mbox

[Ada] New aspect Disable_Controlled

Message ID 20150526081534.GA4988@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet May 26, 2015, 8:15 a.m. UTC
This implements a new aspect Disable_Controlled which can only be
used for controlled record types. It causes suppression of related
calls to Initialize, Adjust, Finalize (for conditional compilation
purposes).

The following test:

     1. with Ada.Finalization; use Ada.Finalization;
     2. with Text_IO; use Text_IO;
     3. procedure DisableC is
     4.    procedure Test1 is
     5.       type R is new Controlled with
     6.          record
     7.             X : Integer;
     8.          end record
     9.       with Disable_Controlled => False;
    10.       procedure Initialize (A : in out R);
    11.       procedure Adjust (A : in out R);
    12.       procedure Finalize (A : in out R);
    13.       procedure Initialize (A : in out R) is
    14.       begin
    15.          A.X := 0;
    16.          Put_Line ("  Initialize called");
    17.       end;
    18.       procedure Adjust (A : in out R) is
    19.       begin
    20.          A.X := A.X + 1;
    21.          Put_Line ("  Adjust called");
    22.       end;
    23.       procedure Finalize (A : in out R) is
    24.       begin
    25.          A.X := A.X - 1;
    26.          Put_Line ("  Finalize called");
    27.       end;
    28.       R1, R2 : R;
    29.    begin
    30.       R1 := R2;
    31.    end Test1;
    32.    procedure Test2 is
    33.       type R is new Controlled with
    34.          record
    35.             X : Integer;
    36.          end record
    37.       with Disable_Controlled => True;
    38.       procedure Initialize (A : in out R);
    39.       procedure Adjust (A : in out R);
    40.       procedure Finalize (A : in out R);
    41.       procedure Initialize (A : in out R) is
    42.       begin
    43.          A.X := 0;
    44.          Put_Line ("  Initialize called");
    45.       end;
    46.       procedure Adjust (A : in out R) is
    47.       begin
    48.          A.X := A.X + 1;
    49.          Put_Line ("  Adjust called");
    50.       end;
    51.       procedure Finalize (A : in out R) is
    52.       begin
    53.          A.X := A.X - 1;
    54.          Put_Line ("  Finalize called");
    55.       end;
    56.       R1, R2 : R;
    57.    begin
    58.       R1 := R2;
    59.    end;
    60. begin
    61.    Put_Line ("Enabled:");
    62.    Test1;
    63.    Put_Line ("Disabled:");
    64.    Test2;
    65. end;

generates the output:

Enabled:
  Initialize called
  Initialize called
  Finalize called
  Adjust called
  Finalize called
  Finalize called
Disabled:

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

2015-05-26  Robert Dewar  <dewar@adacore.com>

	* aspects.ads, aspects.adb: Add aspect Disable_Controlled.
	* einfo.ads, einfo.adb (Disable_Controlled): New flag.
	(Is_Controlled_Active): New function.
	* exp_ch3.adb (Expand_Freeze_Record_Type): Use
	Is_Controlled_Active.
	* exp_util.adb (Needs_Finalization): Finalization not needed
	if Disable_Controlled set.
	* freeze.adb (Freeze_Array_Type): Do not set
	Has_Controlled_Component if the component has Disable_Controlled.
	(Freeze_Record_Type): ditto.
	* sem_ch13.adb (Decorate): Minor reformatting.
	(Analyze_Aspect_Specifications): Implement Disable_Controlled.
	* sem_ch3.adb (Analyze_Object_Declaration): Handle
	Disable_Controlled.
	(Array_Type_Declaration): ditto.
	(Build_Derived_Private_Type): ditto.
	(Build_Derived_Type): ditto.
	(Record_Type_Definition): ditto.
	* snames.ads-tmpl: Add Name_Disable_Controlled.
diff mbox

Patch

Index: sem_ch3.adb
===================================================================
--- sem_ch3.adb	(revision 223661)
+++ sem_ch3.adb	(working copy)
@@ -4386,7 +4386,7 @@ 
         and then not Is_Constrained (Underlying_Type (T))
         and then not Is_Aliased (Id)
         and then not Is_Class_Wide_Type (T)
-        and then not Is_Controlled (T)
+        and then not Is_Controlled_Active (T)
         and then not Has_Controlled_Component (Base_Type (T))
         and then Expander_Active
       then
@@ -5614,7 +5614,7 @@ 
          Set_Packed_Array_Impl_Type (Implicit_Base, Empty);
          Set_Has_Controlled_Component (Implicit_Base,
            Has_Controlled_Component (Element_Type)
-             or else Is_Controlled  (Element_Type));
+             or else Is_Controlled_Active  (Element_Type));
          Set_Finalize_Storage_Only (Implicit_Base,
            Finalize_Storage_Only (Element_Type));
 
@@ -5640,7 +5640,7 @@ 
          Set_Has_Controlled_Component (T, Has_Controlled_Component
                                                         (Element_Type)
                                             or else
-                                          Is_Controlled (Element_Type));
+                                          Is_Controlled_Active (Element_Type));
          Set_Finalize_Storage_Only    (T, Finalize_Storage_Only
                                                         (Element_Type));
          Set_Default_SSO              (T);
@@ -7351,16 +7351,18 @@ 
             Error_Msg_N ("cannot add discriminants to untagged type", N);
          end if;
 
-         Set_Stored_Constraint (Derived_Type, No_Elist);
-         Set_Is_Constrained    (Derived_Type, Is_Constrained (Parent_Type));
-         Set_Is_Controlled     (Derived_Type, Is_Controlled  (Parent_Type));
+         Set_Stored_Constraint  (Derived_Type, No_Elist);
+         Set_Is_Constrained     (Derived_Type, Is_Constrained (Parent_Type));
+         Set_Is_Controlled      (Derived_Type, Is_Controlled  (Parent_Type));
+         Set_Disable_Controlled (Derived_Type, Disable_Controlled
+                                                              (Parent_Type));
          Set_Has_Controlled_Component
-                               (Derived_Type, Has_Controlled_Component
-                                                             (Parent_Type));
+                                (Derived_Type, Has_Controlled_Component
+                                                              (Parent_Type));
 
          --  Direct controlled types do not inherit Finalize_Storage_Only flag
 
-         if not Is_Controlled  (Parent_Type) then
+         if not Is_Controlled_Active (Parent_Type) then
             Set_Finalize_Storage_Only
               (Base_Type (Derived_Type), Finalize_Storage_Only (Parent_Type));
          end if;
@@ -8974,16 +8976,18 @@ 
    begin
       --  Set common attributes
 
-      Set_Scope          (Derived_Type, Current_Scope);
+      Set_Scope              (Derived_Type, Current_Scope);
 
-      Set_Etype          (Derived_Type,                Parent_Base);
-      Set_Ekind          (Derived_Type, Ekind         (Parent_Base));
-      Set_Has_Task       (Derived_Type, Has_Task      (Parent_Base));
-      Set_Has_Protected  (Derived_Type, Has_Protected (Parent_Base));
+      Set_Etype              (Derived_Type,                Parent_Base);
+      Set_Ekind              (Derived_Type, Ekind         (Parent_Base));
+      Set_Has_Task           (Derived_Type, Has_Task      (Parent_Base));
+      Set_Has_Protected      (Derived_Type, Has_Protected (Parent_Base));
 
-      Set_Size_Info      (Derived_Type,                 Parent_Type);
-      Set_RM_Size        (Derived_Type, RM_Size        (Parent_Type));
-      Set_Is_Controlled  (Derived_Type, Is_Controlled  (Parent_Type));
+      Set_Size_Info          (Derived_Type,                     Parent_Type);
+      Set_RM_Size            (Derived_Type, RM_Size            (Parent_Type));
+      Set_Is_Controlled      (Derived_Type, Is_Controlled      (Parent_Type));
+      Set_Disable_Controlled (Derived_Type, Disable_Controlled (Parent_Type));
+
       Set_Is_Tagged_Type (Derived_Type, Is_Tagged_Type (Parent_Type));
       Set_Is_Volatile    (Derived_Type, Is_Volatile    (Parent_Type));
 
@@ -21174,7 +21178,7 @@ 
          end;
       end if;
 
-      Final_Storage_Only := not Is_Controlled (T);
+      Final_Storage_Only := not Is_Controlled_Active (T);
 
       --  Ada 2005: Check whether an explicit Limited is present in a derived
       --  type declaration.
@@ -21240,7 +21244,8 @@ 
          elsif not Is_Class_Wide_Equivalent_Type (T)
            and then (Has_Controlled_Component (Etype (Component))
                       or else (Chars (Component) /= Name_uParent
-                                and then Is_Controlled (Etype (Component))))
+                                and then Is_Controlled_Active
+                                           (Etype (Component))))
          then
             Set_Has_Controlled_Component (T, True);
             Final_Storage_Only :=
Index: exp_util.adb
===================================================================
--- exp_util.adb	(revision 223661)
+++ exp_util.adb	(working copy)
@@ -6848,12 +6848,16 @@ 
       then
          return False;
 
+      --  Never needs finalization if Disable_Controlled set
+
+      elsif Disable_Controlled (T) then
+         return False;
+
       else
          --  Class-wide types are treated as controlled because derivations
          --  from the root type can introduce controlled components.
 
-         return
-           Is_Class_Wide_Type (T)
+         return Is_Class_Wide_Type (T)
              or else Is_Controlled (T)
              or else Has_Controlled_Component (T)
              or else Has_Some_Controlled_Component (T)
Index: einfo.adb
===================================================================
--- einfo.adb	(revision 223661)
+++ einfo.adb	(working copy)
@@ -558,6 +558,7 @@ 
 
    --    Has_Implicit_Dereference        Flag251
    --    Is_Processed_Transient          Flag252
+   --    Disable_Controlled              Flag253
    --    Is_Implementation_Defined       Flag254
    --    Is_Predicate_Function           Flag255
    --    Is_Predicate_Function_M         Flag256
@@ -595,7 +596,6 @@ 
    --    Is_Volatile_Full_Access         Flag285
    --    Needs_Typedef                   Flag286
 
-   --    (unused)                        Flag253
    --    (unused)                        Flag287
    --    (unused)                        Flag288
    --    (unused)                        Flag289
@@ -1026,6 +1026,11 @@ 
       return Node20 (Id);
    end Directly_Designated_Type;
 
+   function Disable_Controlled (Id : E) return B is
+   begin
+      return Flag253 (Base_Type (Id));
+   end Disable_Controlled;
+
    function Discard_Names (Id : E) return B is
    begin
       return Flag88 (Id);
@@ -3941,6 +3946,12 @@ 
       Set_Node20 (Id, V);
    end Set_Directly_Designated_Type;
 
+   procedure Set_Disable_Controlled (Id : E; V : B := True) is
+   begin
+      pragma Assert (Is_Type (Id) and then Is_Base_Type (Id));
+      Set_Flag253 (Id, V);
+   end Set_Disable_Controlled;
+
    procedure Set_Discard_Names (Id : E; V : B := True) is
    begin
       Set_Flag88 (Id, V);
@@ -7394,6 +7405,15 @@ 
         K = E_Constant or else K = E_In_Parameter or else K = E_Loop_Parameter;
    end Is_Constant_Object;
 
+   --------------------------
+   -- Is_Controlled_Active --
+   --------------------------
+
+   function Is_Controlled_Active (Id : E) return B is
+   begin
+      return Is_Controlled (Id) and then not Disable_Controlled (Id);
+   end Is_Controlled_Active;
+
    --------------------
    -- Is_Discriminal --
    --------------------
Index: einfo.ads
===================================================================
--- einfo.ads	(revision 223665)
+++ einfo.ads	(working copy)
@@ -911,6 +911,10 @@ 
 --       Designated_Type obtains this full type in the case of access to an
 --       incomplete type.
 
+--    Disable_Controlled (Flag253)
+--      Present in all entities. Set for controlled type (Is_Controlled flag
+--      set) if the aspect Disable_Controlled is active for the type.
+
 --    Discard_Names (Flag88)
 --       Defined in types and exception entities. Set if pragma Discard_Names
 --       applies to the entity. It is also set for declarative regions and
@@ -2337,6 +2341,10 @@ 
 --       i.e. is either a descendant of Ada.Finalization.Controlled or of
 --       Ada.Finalization.Limited_Controlled.
 
+--    Is_Controlled_Active (synth) [base type only]
+--       Defined in all type entities. Set if Is_Controlled is set for the
+--       type, and Disable_Controlled is not set.
+
 --    Is_Controlling_Formal (Flag97)
 --       Defined in all Formal_Kind entities. Marks the controlling parameters
 --       of dispatching operations.
@@ -5413,6 +5421,7 @@ 
    --    Linker_Section_Pragma               (Node33)
 
    --    Depends_On_Private                  (Flag14)
+   --    Disable_Controlled                  (Flag253)
    --    Discard_Names                       (Flag88)
    --    Finalize_Storage_Only               (Flag158)  (base type only)
    --    From_Limited_With                   (Flag159)
@@ -5491,6 +5500,7 @@ 
    --    Invariant_Procedure                 (synth)
    --    Is_Access_Protected_Subprogram_Type (synth)
    --    Is_Atomic_Or_VFA                    (synth)
+   --    Is_Controlled_Active                (synth)
    --    Predicate_Function                  (synth)
    --    Predicate_Function_M                (synth)
    --    Root_Type                           (synth)
@@ -6724,6 +6734,7 @@ 
    function Digits_Value                        (Id : E) return U;
    function Direct_Primitive_Operations         (Id : E) return L;
    function Directly_Designated_Type            (Id : E) return E;
+   function Disable_Controlled                  (Id : E) return B;
    function Discard_Names                       (Id : E) return B;
    function Discriminal                         (Id : E) return E;
    function Discriminal_Link                    (Id : E) return E;
@@ -7206,6 +7217,7 @@ 
    function Is_Base_Type                        (Id : E) return B;
    function Is_Boolean_Type                     (Id : E) return B;
    function Is_Constant_Object                  (Id : E) return B;
+   function Is_Controlled_Active                (Id : E) return B;
    function Is_Discriminal                      (Id : E) return B;
    function Is_Dynamic_Scope                    (Id : E) return B;
    function Is_External_State                   (Id : E) return B;
@@ -7380,6 +7392,7 @@ 
    procedure Set_Digits_Value                    (Id : E; V : U);
    procedure Set_Direct_Primitive_Operations     (Id : E; V : L);
    procedure Set_Directly_Designated_Type        (Id : E; V : E);
+   procedure Set_Disable_Controlled              (Id : E; V : B := True);
    procedure Set_Discard_Names                   (Id : E; V : B := True);
    procedure Set_Discriminal                     (Id : E; V : E);
    procedure Set_Discriminal_Link                (Id : E; V : E);
@@ -8155,6 +8168,7 @@ 
    pragma Inline (Digits_Value);
    pragma Inline (Direct_Primitive_Operations);
    pragma Inline (Directly_Designated_Type);
+   pragma Inline (Disable_Controlled);
    pragma Inline (Discard_Names);
    pragma Inline (Discriminal);
    pragma Inline (Discriminal_Link);
@@ -8658,6 +8672,7 @@ 
    pragma Inline (Set_Digits_Value);
    pragma Inline (Set_Direct_Primitive_Operations);
    pragma Inline (Set_Directly_Designated_Type);
+   pragma Inline (Set_Disable_Controlled);
    pragma Inline (Set_Discard_Names);
    pragma Inline (Set_Discriminal);
    pragma Inline (Set_Discriminal_Link);
@@ -9062,6 +9077,7 @@ 
 
    pragma Inline (Base_Type);
    pragma Inline (Is_Base_Type);
+   pragma Inline (Is_Controlled_Active);
    pragma Inline (Is_Package_Or_Generic_Package);
    pragma Inline (Is_Packed_Array);
    pragma Inline (Is_Subprogram_Or_Generic_Subprogram);
Index: freeze.adb
===================================================================
--- freeze.adb	(revision 223661)
+++ freeze.adb	(working copy)
@@ -2226,7 +2226,7 @@ 
 
             --  Propagate flags for component type
 
-            if Is_Controlled (Component_Type (Arr))
+            if Is_Controlled_Active (Component_Type (Arr))
               or else Has_Controlled_Component (Ctyp)
             then
                Set_Has_Controlled_Component (Arr);
@@ -4106,7 +4106,7 @@ 
                    (Has_Controlled_Component (Etype (Comp))
                      or else
                        (Chars (Comp) /= Name_uParent
-                         and then Is_Controlled (Etype (Comp)))
+                         and then Is_Controlled_Active (Etype (Comp)))
                      or else
                        (Is_Protected_Type (Etype (Comp))
                          and then
Index: aspects.adb
===================================================================
--- aspects.adb	(revision 223661)
+++ aspects.adb	(working copy)
@@ -517,6 +517,7 @@ 
     Aspect_Depends                      => Aspect_Depends,
     Aspect_Dimension                    => Aspect_Dimension,
     Aspect_Dimension_System             => Aspect_Dimension_System,
+    Aspect_Disable_Controlled           => Aspect_Disable_Controlled,
     Aspect_Discard_Names                => Aspect_Discard_Names,
     Aspect_Dispatching_Domain           => Aspect_Dispatching_Domain,
     Aspect_Dynamic_Predicate            => Aspect_Predicate,
Index: aspects.ads
===================================================================
--- aspects.ads	(revision 223661)
+++ aspects.ads	(working copy)
@@ -171,6 +171,7 @@ 
       Aspect_Asynchronous,
       Aspect_Atomic,
       Aspect_Atomic_Components,
+      Aspect_Disable_Controlled,            -- GNAT
       Aspect_Discard_Names,
       Aspect_Effective_Reads,               -- GNAT
       Aspect_Effective_Writes,              -- GNAT
@@ -414,6 +415,7 @@ 
       Aspect_Depends                      => Name_Depends,
       Aspect_Dimension                    => Name_Dimension,
       Aspect_Dimension_System             => Name_Dimension_System,
+      Aspect_Disable_Controlled           => Name_Disable_Controlled,
       Aspect_Discard_Names                => Name_Discard_Names,
       Aspect_Dispatching_Domain           => Name_Dispatching_Domain,
       Aspect_Dynamic_Predicate            => Name_Dynamic_Predicate,
@@ -704,6 +706,7 @@ 
       Aspect_Depends                      => Never_Delay,
       Aspect_Dimension                    => Never_Delay,
       Aspect_Dimension_System             => Never_Delay,
+      Aspect_Disable_Controlled           => Never_Delay,
       Aspect_Effective_Reads              => Never_Delay,
       Aspect_Effective_Writes             => Never_Delay,
       Aspect_Extensions_Visible           => Never_Delay,
Index: sem_ch13.adb
===================================================================
--- sem_ch13.adb	(revision 223661)
+++ sem_ch13.adb	(working copy)
@@ -1205,8 +1205,7 @@ 
 
    procedure Analyze_Aspect_Specifications (N : Node_Id; E : Entity_Id) is
       procedure Decorate (Asp : Node_Id; Prag : Node_Id);
-      --  Establish linkages between an aspect and its corresponding
-      --  pragma.
+      --  Establish linkages between an aspect and its corresponding pragma
 
       procedure Insert_After_SPARK_Mode
         (Prag    : Node_Id;
@@ -1235,7 +1234,7 @@ 
 
       procedure Decorate (Asp : Node_Id; Prag : Node_Id) is
       begin
-         Set_Aspect_Rep_Item           (Asp,  Prag);
+         Set_Aspect_Rep_Item           (Asp, Prag);
          Set_Corresponding_Aspect      (Prag, Asp);
          Set_From_Aspect_Specification (Prag);
          Set_Parent                    (Prag, Asp);
@@ -3055,7 +3054,7 @@ 
                --  Case 5: Special handling for aspects with an optional
                --  boolean argument.
 
-               --  In the general case, the corresponding pragma cannot be
+               --  In the delayed case, the corresponding pragma cannot be
                --  generated yet because the evaluation of the boolean needs
                --  to be delayed till the freeze point.
 
@@ -3145,6 +3144,25 @@ 
                      end if;
 
                      goto Continue;
+
+                  --  Disable_Controlled
+
+                  elsif A_Id = Aspect_Disable_Controlled then
+                     if Ekind (E) /= E_Record_Type
+                       or else not Is_Controlled (E)
+                     then
+                        Error_Msg_N
+                          ("aspect % requires controlled record type", Aspect);
+                        goto Continue;
+                     end if;
+
+                     if not Present (Expr)
+                       or else Is_True (Static_Boolean (Expr))
+                     then
+                        Set_Disable_Controlled (E);
+                     end if;
+
+                     goto Continue;
                   end if;
 
                   --  Library unit aspects require special handling in the case
Index: snames.ads-tmpl
===================================================================
--- snames.ads-tmpl	(revision 223661)
+++ snames.ads-tmpl	(working copy)
@@ -141,6 +141,7 @@ 
    Name_Default_Component_Value        : constant Name_Id := N + $;
    Name_Dimension                      : constant Name_Id := N + $;
    Name_Dimension_System               : constant Name_Id := N + $;
+   Name_Disable_Controlled             : constant Name_Id := N + $;
    Name_Dynamic_Predicate              : constant Name_Id := N + $;
    Name_Static_Predicate               : constant Name_Id := N + $;
    Name_Synchronization                : constant Name_Id := N + $;
Index: exp_ch3.adb
===================================================================
--- exp_ch3.adb	(revision 223661)
+++ exp_ch3.adb	(working copy)
@@ -6936,9 +6936,10 @@ 
          --  type. See Make_CW_Equivalent_Type.
 
          if not Is_Class_Wide_Equivalent_Type (Def_Id)
-           and then (Has_Controlled_Component (Comp_Typ)
-                      or else (Chars (Comp) /= Name_uParent
-                                and then Is_Controlled (Comp_Typ)))
+           and then
+             (Has_Controlled_Component (Comp_Typ)
+               or else (Chars (Comp) /= Name_uParent
+                         and then (Is_Controlled_Active (Comp_Typ))))
          then
             Set_Has_Controlled_Component (Def_Id);
          end if;