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

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

--- ai05s/ai05-0218-1.txt	2010/10/19 01:20:08	1.2
+++ ai05s/ai05-0218-1.txt	2011/03/05 06:37:20	1.3
@@ -1,4 +1,4 @@
-!standard  7.5(8.2/3)                             10-10-18    AI05-0218-1/01
+!standard  7.5(8.2/3)                             11-03-03    AI05-0218-1/02
 !class binding interpretation 10-06-13
 !status work item 10-06-13
 !status received 10-04-15
@@ -41,38 +41,123 @@
      -- I.Ptr := I.X.Field'Access; -- clearly illegal
    end Volatility_Test;
 
-Should this be fixed?
+Should this be fixed? (Yes.)
 
 !recommendation
 
 (See Summary.)
 
-Delete the 2nd occurrence of the phrase "or allow pass by copy"
-in C.6(12).
+!wording
 
-In other words, replace
+   In C.6(12) replace
+     If an atomic type is used as an actual for a generic formal derived
+     type, then the ancestor of the formal type shall be atomic or allow
+     pass by copy.
+   with
+     If an atomic type is used as an actual for a generic formal derived
+     type, then the ancestor of the formal type shall be atomic.
+
+   Append after C.6(12):
+     If a volatile type is used as an actual for a generic formal array
+     type, then the element type of the formal type shall be volatile.
 
-   If an atomic type is used as an actual for a generic formal derived
-   type, then the ancestor of the formal type shall be atomic or allow
-   pass by copy.
-
-with
-
-   If an atomic type is used as an actual for a generic formal derived
-   type, then the ancestor of the formal type shall be atomic.
-
 !discussion
 
-The !question and !summary sections talk about volatility, but the wording
-change mentions only atomicity. This makes sense because of the next
-sentence in C.6(12):
+We don't want to allow an access value to designate a volatile object of a
+non-volatile type, but this can happen if we allow (as the language does today)
+the following scenario:
+
+    1) A generic formal type which has an aliased or tagged subcomponent
+       where the subcomponent does not appear (as seen from the
+       generic body) to be volatile.
+
+    2) An instance with a corresponding actual type which is volatile
+       (which implies that the corresponding actual subcomponent is
+       volatile).
+
+See the example in the !question section for details.
+
+There is no corresponding problem for atomicity because atomicity of a type does
+not imply atomicity of its components.
+
+There is no problem with formal types other than formal derived and formal array
+because these are the only formal types that can have tagged or aliased
+subcomponents (in particular, a discriminant of a formal private type cannot be
+tagged or aliased),
+
+We are not trying to prevent, for example, a non-volatile formal private type
+with a corresponding actual type which is volatile.
+
+Since we are really only interested here in volatility, we want to be careful
+not to disallow useful cases involving atomicity.
+
+For example, we want to allow an atomic array type with a non-atomic component
+as an actual corresponding to a formal array type.
+
+This probably means that we cannot stick with the "no specific rules for
+volatility; just reuse the rules for atomicity as per the final sentence of
+C.6(12/3)" approach.
+
+The proposed rule would be too stringent if we had a way of specifying (e.g. via
+an aspect clause on a formal type) that a formal type is volatile or has
+volatile components. If this were possible, then we might need something more
+permissive like
+
+     If a volatile type is used as an actual for a generic formal array
+     type, then the formal array type shall have volatile components.
+
+     AARM note:
+     A formal array type has volatile components if the
+     array type is volatile, the element type of the array type is
+     volatile, or the volatile_components aspect of the array type
+     is specified to be True.
+
+This change is incompatible with previous versions of Ada, in that some
+actual types will no longer be legal for certain formal types. There doesn't
+seem to be an alternative short of requiring compilers to treat all designated
+objects of general access types as if they are volatile (which would have a
+significant negative impact on optimizations). [This affects *all* general
+access types because conversions are allowed between access types with the
+same designated type.]
+
+!corrigendum C.6(12)
+
+@drepl
+If an atomic object is passed as a parameter, then the type of the formal
+parameter shall either be atomic or allow pass by copy (that
+is, not be a nonatomic by-reference type). If an atomic object is used
+as an actual for a generic formal object of mode @b<in out>, then the
+type of the generic formal object shall be atomic. If the @fa<prefix> of
+an @fa<attribute_reference> for an Access attribute denotes an atomic
+object (including a component), then the designated type of
+the resulting access type shall be atomic. If an atomic type is used as
+an actual for a generic formal derived type, then the ancestor of the
+formal type shall be atomic or allow pass by copy. Corresponding rules
+apply to volatile objects and types.
+@dby
+If an atomic object is passed as a parameter, then the type of the formal
+parameter shall either be atomic or allow pass by copy (that
+is, not be a nonatomic by-reference type). If an atomic object is used
+as an actual for a generic formal object of mode @b<in out>, then the
+type of the generic formal object shall be atomic. If the @fa<prefix> of
+an @fa<attribute_reference> for an Access attribute denotes an atomic
+object (including a component), then the designated type of
+the resulting access type shall be atomic. If an atomic type is used as
+an actual for a generic formal derived type, then the ancestor of the
+formal type shall be atomic. Corresponding rules
+apply to volatile objects and types.
 
-   Corresponding rules apply to volatile objects and types.
+If a volatile type is used as an actual for a generic formal array
+type, then the element type of the formal type shall be volatile.
 
-
 !ACATS Test
+
+Add a B-Test to check that the appropriate actual types are rejected (or
+modify an existing test).
+
+!ASIS
 
-Add a B-Test to check that this type is classified as "immutably limited".
+No ASIS impact.
 
 !appendix
 
@@ -315,5 +400,159 @@
 > occurrence, which is talking about formal derived types.
 
 Right.
+
+****************************************************************
+
+From: Steve Baird
+Sent: Thursday, March 3, 2011  4:01 PM
+
+More homework from the Tampa meeting.
+Once again, thanks to Randy and Tuck for review and suggestions.
+
+[Editor's note: The wording and discussion sections of version /02
+of the AI followed.]
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, March 3, 2011  4:01 PM
+
+...
+> We are not trying to prevent, for example, a non-volatile formal
+> private type with a corresponding actual type which is volatile.
+
+For the record, I had a couple of unresolved concerns related to the above
+statement, but I now don't think there is anything that needs to be done.
+
+First, I was concerned that there was a way to create this problem with all
+generic formal types using explicitly aliased parameters. That would look
+something like:
+
+    generic
+        type T is range <>;
+        type Acc_T is access T;
+    package Gen is
+        procedure Proc (P : aliased in T);
+    end Gen;
+
+    package body Gen is
+        procedure Proc (P : aliased in T) is
+           P_A : Acc_T := P'Unchecked_Access;
+        begin
+           ...
+        end Proc;
+    end Gen;
+
+If the actual for T was volatile and the designated type of the actual type for
+Acc_T was not, a call of Proc with a library-level object would not be erroneous
+and there would be a problem.
+
+But I now think the static matching rules combined with the fact that volatile
+(and atomic) are type-related aspects prevent problems. The only problems can
+occur when the volatility is "inherited" from a larger object, and that requires
+components.
+
+[Humm, aside: can a problem occur with an access discriminant? Those can get the
+implicit volatility, and have implicit conversions to other types. Naaah,
+probably not; they can't be aliased.]
+
+The second issue is the more general one of the impact on generic sharing
+implementations. I had originally thought that these rules were intended to
+ensure that the compiler always statically knows when it is accessing an atomic
+or volatile object (that's important since these properties mainly affect
+instruction selection and optimization, not things that can be changed at
+runtime). But that is clearly not true when generic sharing is being used.
+
+For instance, in the example above, a sharing implementation will not know
+whether or not T is a volatile (or atomic) type. The effect is that pretty much
+every object of a formal type (or a type derived from a formal type) has to
+assume the worst, use thunks to do all reads and writes (because of the
+possibility of atomic operations, for which reading or writing too many bits
+is also not allowed), and block the majority of optimizations.
+
+I've been pondering just how much of an additional hit (beyond the existing
+costs of sharing) that this really is. For composite types (formal private
+types, formal array types, and most formal derived types) it probably is
+negligible as the fact that the size of objects isn't known until runtime forces
+virtually all operations to memory (can't put anything in a register which might
+not be big enough). For elementary types, the additional cost could be as much
+as 10-20%, but mostly from the loss of common subexpression optimizations on
+reads and dead write optimizations. (And of course that is very code dependent.)
+The use of thunks is already required to deal with the representation of aliased
+objects/components properly, so there is no additional cost from that.
+
+The biggest danger is probably from future optimizations that forget that
+generic bodies can't be optimized much. But that's clearly my problem and not a
+language problem.
+
+Since a language change to have better guarantees would be fairly incompatible
+for volatile and atomic types, I think there would have to be more of an
+implementation problem to push for a change here. So I won't do that.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Saturday, March 5, 2011  12:33 AM
+
+> More homework from the Tampa meeting.
+
+There was a part of the notes (actually two parts) from the meeting that you
+didn't address:
+
+"Also note that tagged components would have the same problem."
+
+I'm not sure what this means, as tagged components are not automatically aliased.
+So I suspect this is just junk. However:
+
+"Steve previously noticed a problem with view conversions of arrays (that is, in
+an in out parameter) that prevents volatile components."
+
+I'm not sure what this means, either (I suspect this is misrecorded), but there
+clearly is a problem here.
+
+The parameter passing rule currently reads:
+
+"If an atomic object is passed as a parameter, then the formal parameter shall
+either have an atomic type or allow pass by copy."
+
+Atomic_Components can be applied to an anonymous array object. The array object
+as a whole is not an atomic object by C.6(7/2) (the individual components are).
+So the above mentioned rule does not apply to such an anonymous array object.
+There does not appear to be any rule preventing converting that anonymous array
+object to some other array type (including one that does not have atomic components).
+Thus we can cause the original problem with such an array object:
+
+   procedure AA_Test is
+     type A1 is array (1 .. 10) of aliased Integer;
+     O1 : array (1 .. 10) of aliased Integer;
+     pragma Atomic_Components (O1);
+
+     generic
+        type Arr is array (1 .. 10) of aliased Integer;
+     package G is
+        type Ref is access all Integer;
+        Ptr : Ref;
+        procedure P (A : Arr);
+     end G;
+     package body G is
+     begin
+        procedure P (A : aliased Arr) is
+        begin
+            Ptr := A(1)'Unchecked_Access;
+        end P;
+     end G;
+     package I is new G (A1);
+   begin
+     I.P (A1(O1));
+     I.Ptr.all := I.Ptr.all + 1; -- problematic references to a volatile
+   end Volatility_Test;
+
+[Note that I used "aliased" in the parameter to ensure by-reference passing;
+most compilers would pass this type by reference anyway so that isn't strictly
+necessary. This code is not erroneous so long as the passed object lives as long
+as the instance.]
+
+Probably this conversion ought to be illegal, but I'm not sure of the exact rule
+needed.
 
 ****************************************************************

Questions? Ask the ACAA Technical Agent