!standard 7.5(8.2/3) 10-10-18 AI05-0218-1/01 !class binding interpretation 10-06-13 !status work item 10-06-13 !status received 10-04-15 !priority Low !difficulty Hard !qualifier Omission !subject Generics and volatility !summary A nonvolatile generic formal derived type precludes a volatile actual type. !question The language tries to prevent an access value from denoting a volatile object of a nonvolatile type. The following example seems to violate this rule. procedure Volatility_Test is type T1 is record Field : aliased Integer; end record; type T2 is new T1; pragma Volatile (T2); generic type Formal_Derived is new T1; package G is X : Formal_Derived; type Ref is access all Integer; Ptr : Ref; end G; package body G is begin Ptr := X.Field'Access; end G; package I is new G (T2); begin I.Ptr.all := I.Ptr.all + 1; -- problematic references to a volatile null; -- I.Ptr := I.X.Field'Access; -- clearly illegal end Volatility_Test; Should this be fixed? !recommendation (See Summary.) Delete the 2nd occurrence of the phrase "or allow pass by copy" in C.6(12). In other words, 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. !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): Corresponding rules apply to volatile objects and types. !ACATS Test Add a B-Test to check that this type is classified as "immutably limited". !appendix From: Steve Baird Sent: Thursday, April 15, 2010 7:35 PM > It seems like the case ought to be detected, or at least we ought to > consider if the problem is severe enough to fix (as the fix will be > incompatible). Ok, I'll inflict this one on the group. The language tries to prevent an access value from denoting a volatile object of a nonvolatile type. The following example seems to violate this rule. Does this warrant fixing? procedure Volatility_Test is type T1 is record Field : aliased Integer; end record; type T2 is new T1; pragma Volatile (T2); generic type Formal_Derived is new T1; package G is X : Formal_Derived; type Ref is access all Integer; Ptr : Ref; end G; package body G is begin Ptr := X.Field'Access; end G; package I is new G (T2); begin I.Ptr.all := I.Ptr.all + 1; -- problematic references to a volatile null; -- I.Ptr := I.X.Field'Access; -- clearly illegal end Volatility_Test; Note that C.6(12) currently includes the following: ... 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. One solution would be to delete the "or allow pass by copy" wording, although that change would affect the atomic case as well. **************************************************************** From: Randy Brukardt Sent: Thursday, April 15, 2010 8:03 PM It should be noted that this rule potentially inflicts a large burden on implementations that do generic sharing, as it essentially requires anything whose actual type can be volatile (or atomic) to be passed by copy if that is allowed at all. For types that allow passing by copy but that the compiler would normally pass by reference (such as larger composite types), this can be very expensive. (Alternatively, the compiler could revert to non-sharing semantics when any actual might be volatile or atomic, but of course that would limit the sharing possibilities fairly significantly.) There also seems to be an issue if the compiler choose in the example above to pass the type by reference in any primitive subprograms. Humm...(answering own question)...actually T1 int eh example above can't have primitive subprograms (else the pragma is illegal). So scratch this issue. Anyway, the sharing issue alone would not be worth changing the language for, but it seems to provide an additional data point that the existing rule is dubious. **************************************************************** From: Robert Dewar Sent: Thursday, April 15, 2010 8:08 PM I am not normally very sympathetic to Randy's concerns about generic sharing, but in this particular case, I think he has a really good point. This definitely needs fixing in my view. **************************************************************** From: Steve Baird Sent: Monday, July 19, 2010 6:02 PM One of my homework items from Valencia is to propose wording for this AI. To recap, we want prevent an access value from denoting a volatile object of a nonvolatile type as in the following example: procedure Volatility_Test is type T1 is record Fld : aliased Integer; end record; type T2 is new T1; pragma Volatile (T2); generic type Formal_Derived is new T1; package G is X : Formal_Derived; type Ref is access all Integer; Ptr : Ref; end G; package body G is begin Ptr := X.Fld'Access; end G; package I is new G (T2); begin I.Ptr.all := I.Ptr.all + 1; -- problematic references to a volatile end Volatility_Test; So ... !wording Append to the end of C.6(12): Furthermore, if a volatile type is used as an actual for a generic formal derived type, then the ancestor of the formal type shall be volatile. Alternatives include: 1) In the proposed wording, replace "shall be volatile" with "shall be volatile or elementary". It might appear that there is no harm in allowing a generic which has a "new Standard.Integer" formal derived type to be instantiated with a volatile actual. The problem discussed here has to do with the volatility of subcomponents (see final sentence of C.6(8)) and an elementary type has no subcomponents. Adding two words to allow this case might seem reasonable. However, there is another problem which has not been discussed which this relaxation might open up. 4.6(24.9/2) states (in the context of a type conversion between two array types unrelated by derivation): The operand type of a view conversion shall not have a tagged, private, or volatile subcomponent. Consider a view conversion between two array types declared in a generic body; the two types have our "new Standard.Integer" formal derived type as subcomponent of their common element type. If we allow a volatile actual type, we can get a violation of the above rule and it looks like this could lead to problems. 2) Add no new wording and instead delete the existing phrase "or allow pass by copy" from C.6(12). This would disallow more than we need to as it would affect the rules for Atomic types as well as Volatile types. This seems like a significant and unnecessary incompatibility. 3) Add the new sentence as a new paragraph and drop the leading "Furthermore, ". It does seem a odd to have the sentence "Corresponding rules apply to volatile objects and types." appearing other than at the end of its paragraph. **************************************************************** From: Randy Brukardt Sent: Monday, July 19, 2010 6:24 PM I didn't think about this in detail, but... > 2) Add no new wording and instead delete the existing phrase > "or allow pass by copy" from C.6(12). This would disallow > more than we need to as it would affect the rules for Atomic > types as well as Volatile types. This seems like a > significant and unnecessary incompatibility. ...this doesn't make sense to me since Atomic always implies Volatile (C.6(8)) So anything that applies to volatile types also applies to atomic types, and thus any incompatibility (no matter how it is stated) clearly applies to atomic as well. There might be good reasons for not doing this, but the given reason isn't it. (It should be obvious that the problematic case is even more problematic for atomic objects, in the event that they are allowed by the implementation.) **************************************************************** From: Steve Baird Sent: Monday, July 19, 2010 6:37 PM > There might be good reasons for not doing this, but the given reason > isn't it. Good point; I had the implication backwards. I think there are no good reasons for not doing this and the proposed wording change should simply be that 5-word deletion. **************************************************************** From: Steve Baird Sent: Monday, July 19, 2010 6:49 PM > ...this doesn't make sense to me since Atomic always implies Volatile > (C.6(8)) So anything that applies to volatile types also applies to > atomic types, and thus any incompatibility (no matter how it is > stated) clearly applies to atomic as well. I agree with you, but it isn't as obvious as you make it sound. Consider the case of an atomic formal where the actual is volatile, not atomic, and allows pass by copy. If this case is possible, then we have a scenario where the proposed 5-word deletion would be unnecessarily restrictive. But how did we get this actual which meets all the formal-to-actual matching rules but isn't atomic? We don't have a "pragma Non_Atomic" which can be applied to a derived type with an atomic parent. So I think you are right. **************************************************************** From: Tucker Taft Sent: Monday, July 19, 2010 8:29 PM You should be careful with misinterpretation of your solution (2), because the phrase "or allow pass by copy" appears *twice* in C.6(12). I presume you mean the second occurrence, which is talking about formal derived types. And I agree the most straightforward solution is to eliminate this second "allow pass by copy". **************************************************************** From: Steve Baird Sent: Tuesday, July 20, 2010 2:56 PM > You should be careful with misinterpretation of your solution (2), > because the phrase "or allow pass by copy" appears *twice* in C.6(12). Good point. I presume you mean the second > occurrence, which is talking about formal derived types. Right. ****************************************************************