CVS difference for ai05s/ai05-0050-1.txt

Differences between 1.1 and version 1.2
Log of other versions for file ai05s/ai05-0050-1.txt

--- ai05s/ai05-0050-1.txt	2007/05/05 01:39:15	1.1
+++ ai05s/ai05-0050-1.txt	2007/10/31 02:24:49	1.2
@@ -1,4 +1,4 @@
-!standard 6.5(24/2)                              07-05-04    AI05-0050-1/01
+!standard 6.5(24/2)                              07-10-30    AI05-0050-1/02
 !class binding interpretation 07-05-04
 !status work item 07-05-04
 !status received 07-04-20
@@ -9,18 +9,6 @@
 
 !summary
 
-*TBD*
-
-!question
-
-Should the implementation permissions of 6.5(24/2) be revised? The current permission
-both requires inefficient implementations in some cases and also allows an exception to
-be raised in cases where no exception would be raised without the permission.
-
-!recommendation
-
-(Recommended in e-mail discussion:)
-
 If an object is being initialized by a function call and the implementation
 can tell before the call that the object subtype and the function result
 subtype are incompatible, then the implementation should be permitted
@@ -37,10 +25,186 @@
 All of these permissions apply to recursive calls (that is, calls to a function in
 a return statement).
 
+!question
+
+Should the implementation permissions of 6.5(24/2) be revised? The current permission
+both requires inefficient implementations in some cases and also allows an exception to
+be raised in cases where no exception would be raised without the permission.
+
+!recommendation
+
+(See summary.)
+
 !wording
+
+Replace 6.5(24/2)
 
-*TBD*
+  If the result subtype of a function is unconstrained, and a call on the
+  function is used to provide the initial value of an object with a
+  constrained nominal subtype, Constraint_Error may be raised at the point
+  of the call (after abandoning the execution of the function body) if,
+  while elaborating the return_subtype_indication or evaluating the expression
+  of a return statement that applies to the function body, it is determined 
+  that the value of the result will violate the constraint of the subtype 
+  of this object. 
+  
+with  
+  
+  If a call on a function is used to provide the initial value of an object
+  of a composite type, then certain actions which would be performed
+  after the evaluation of the function call according to the canonical
+  semantics may be performed earlier.
+  
+  Consider the following three points at which the constraints of the
+  function result may become known:
+      - before calling the function
+        (in the case where the function result subtype is constrained)
+      
+      - during the elaboration of the return object declaration of an
+         extended_return_statement of the function
+      
+      - during the evaluation of the expression of a simple_return_statement
+        of the function
+   .
+   
+  If, at any of these points, it is determined that the function result
+  value will violate either the constraint of the subtype of the object
+  or some other intermediate constraint that would be checked during the
+  initialization of the object, then Constraint_Error may be raised at that
+  point.
+  
+  If the function call is used to provide the initial value of an
+  initialized allocator, then any calls to System.Storage_Pools.Allocate
+  (or System.Storage_Pools.Deallocate) which are associated with the
+  allocation of the object may be performed at any of these points, or at the
+  point of a non-value-returning exit from an extended return statement of the
+  function.
+  
+  These permissions do not apply in the case of an extended_return_statement
+  where the function result object is discriminated and is not known to be
+  constrained. 
+  
+  AARM Notes
+  
+  These permissions apply transitively in the case of a function call
+  which returns the value of another function call. In the following example,
+  
+    declare   
+      type T is
+	limited record
+	    ... ;
+	end record;
+       -- requires in-place initialization
 
+      type Unconstrained is array (Positive range <>) of T;
+    
+      function Some_Function return T is ... ;
+
+      function F1 return Unconstrained is
+      begin
+        return (1 .. 10 => Some_Function);
+      end F1;
+
+      function F2 return Unconstrained is
+      begin
+        return F1;
+      end F2;
+
+      X : Unconstrained (1..3) := F2;
+    begin
+      null;
+    end;
+      
+  , Constraint_Error may be raised in F1 before any calls to Some_Function
+  are executed.
+  
+  The "intermediate constraint" wording refers to cases like
+  
+    declare
+      type T is
+	limited record
+	    ... ;
+	end record;
+       -- requires in-place initialization
+
+      type Unconstrained is array (Positive range <>) of T;
+      
+      subtype Constrained is T (1 .. 3);
+      
+      function Some_Function return T is ... ;
+
+      function F1 return Unconstrained is
+        begin return (1.. 10 => Some_Function); end;
+      
+      function F2 return Constrained is begin return F1; end if;
+      
+      function F3 return Unconstrained is
+      begin
+        return Constrained'(F1);
+      end F3;
+      
+      
+    begin
+      begin
+        declare
+          X : Unconstrained := F2;
+        begin null; end;
+      exception when Constraint_Error => null;
+      end;
+      
+      begin
+        declare
+          X : Unconstrained := F3;
+        begin null; end;
+      exception when Constraint_Error => null;
+      end;
+      
+      begin
+        declare
+          X : Unconstrained := Constrained'(F1);
+        begin null; end;
+      exception when Constraint_Error => null;
+      end;      
+    end;
+    
+  In all three of these cases, Constraint_Error may be raised in F1 before
+  the execution of any calls to Some_Function.
+  
+  The "These permissions do not apply" clause handles the
+  case of an extended return object with mutable discriminants.
+  Because of this clause, the permissions of this section do not apply in
+  the following example
+  
+    declare
+      type T (Is_Big : Boolean := True) is
+       record
+         case Is_Big is
+           when False => null;
+           when True  => Big_Component : String (1..1024) := (others => 'X');
+         end case;
+       end record;
+       
+      function F return T is
+      begin
+        return X : T do
+         X.Big_Component := (others => 'Y');
+         X := (Is_Big => False);
+        end return;
+      end F;
+      
+      Small_Object : T (Is_Big => False) := F;
+    begin
+      null;
+    end;
+      
+   and so Constraint_Error may not be raised (which is good).
+   
+   Note that this revocation of permissions only applies in cases where
+   in-place initialization is optional. This means that any difficulties
+   associated with implementing in-place initialization without these
+   permissions can be sidestepped.
+   
+
 !discussion
 
 The implementation permissions of 6.5(24/2) do not go far enough.
@@ -230,7 +394,81 @@
    #3 could be viewed as requiring only a clarification of the current
       wording.
 
+----
+
+It has been argued that these permissions are already implied by
+11.6 and therefore do not need to be repeated. This is simply not the case.
+For example, the permissions given in this section allow a constraint check
+to be moved into an independent subprogram. 11.6 alone would not allow this.
+
+This is necessary to support allocation of function result objects by
+compiler-generated callback routines, where the caller of a function
+passes in a reference to a storage allocation routine which
+is invoked when the constraints of the function result are known.
+If a constraint check performed by the callback routine fails, this
+appears to the user as though Constraint_Error were raised at the point
+where the callback routine was called (i.e., within the function).
+If the function in question is an independent subprogram, this means
+that the constraint check has been moved into an independent subprogram.
+
+Even if the permissions of this section were redundant, they should still
+be stated explicitly here for the sake of the clarity of the language
+definition. Reliance on these permissions is effectively required in the cases
+where in-place initialization is required. Section 11.6 is about permissions
+which enable optional optimizations - an implementer should have
+the option of completely ignoring 11.6. Permissions which are
+needed in order to correctly implement the language should be stated
+outside of 11.6 .
+
+----
+
+The original wording of 6.5(24/2) applied in the case of a scalar result
+type. This seems wrong. Do we really want this paragraph to apply in the
+case of a function whose result subtype is Standard.Float? No.
+That is why the revised wording includes the phrase "of a composite type".
+This permission refers to dynamic semantics, so there are no issues with
+privacy.
+
+----
 
+The mention of System.Storage_Pools.Deallocate is needed to allow
+implementations to avoid storage leaks. Consider the following example:
+
+  declare
+    type T is
+      limited record
+	... ;
+    end record;
+    -- requires in-place initialization
+
+    type Unconstrained is array (Positive range <>) of T;
+
+    function F1 return Unconstrained is
+       Result_Length : Natural := 10;
+    begin
+      for Really_Return in Boolean loop
+        Result_Length := Result_Length * 2;
+        return Result : Unconstrained (1 .. Result_Length) do
+          ...;
+          if not Really_Return then goto L;
+        end return;
+        <<L>> null;
+      end loop; 
+     end F1;
+     
+     type Unconstrained_Ref is access Unconstrained;
+     for Unconstrained_Ref'Storage_Pool use ... ;
+     
+     Ptr : Unconstrained_Ref := new Unconstrained'(F1);
+   begin
+      ...;
+   end;
+   
+The execution of this example may involve two calls to
+System.Storage_Pools.Allocate. We do not want to require that implementations
+clean up after the first call by calling Deallocate,
+but we do want to give implementations that option.
+
 !ACATS test
 
 
@@ -673,3 +911,26 @@
 
 ****************************************************************
 
+From: Randy Brukardt
+Sent: Tuesday, October 30, 2007  7:10 PM
+
+[Commenting on version /02 of the AI.]
+
+I don't see much problem with allowing this permission for scalar types
+(although I doubt it would be used much).
+
+The issue with Deallocate is just the tip of the iceberg; any object that
+needs finalization has similar issues if it gets constructed far enough to
+"exist", as there is no permission to do the finalization early. That's
+touched on in another AI (AI05-0066-1), although I suspect that we'll end up
+with a solution that doesn't fix it. I think any object that is "inaccessible"
+should be able to be finalized at the leaving of any master (so long as it
+doesn't contain any tasks that haven't terminated -- waiting for tasks at
+random points would be a no-no). The reason for restricting to the leaving
+of any master prevents Finalize from being called in the middle of an operation
+(it shouldn't be necessary to protect it against multitasking issues in an
+otherwise single-tasking environment). A similar permission for Deallocate
+is also needed. I don't see any reason to clutter this one spot with something
+that needs to cover the entire language.
+
+****************************************************************

Questions? Ask the ACAA Technical Agent