!standard 9.10(1) 09-03-10 AI05-0009-1/09 !standard 13.1(15/1) !standard 13.2(9) !standard 13.3(13) !standard C.6(2) !standard C.6(4) !standard C.6(6) !standard C.6(9) !standard C.6(13) !standard C.6(14) !class binding interpretation 06-03-21 !status Amendment 201Z 09-03-09 !status ARG Approved 6-0-2 09-02-21 !status work item 08-10-10 !status ARG Approved 8-0-0 08-06-21 !status work item 06-03-21 !status received 06-02-20 !priority Medium !difficulty Hard !qualifier Error !subject Confirming representation items and independence !summary The incorporation of confirming representation items has semantic implications for independent addressability. Two new pragmas (Independent and Independent_Components) are introduced to allow a user to specify that the components of an object of a type should be independently addressable. Additionally, objects or types that have a convention specified by an interfacing pragma have been added to the kinds of representation items that impact independent addressability. Atomic objects are always independently addressable from any other nonoverlapping object (no matter what representation items apply). A derived type can inherit a non-confirming representation item, which is still considered non-confirming. Execution is erroneous if an address clause specifies a valid address that is not appropriate for either the entity or its use. !question 9.10(1) says that two nonoverlapping objects are independently addressable unless one or more representation items are specified for them. AI95-0291-2 says that confirming representation items don't change the representation of items, so it seems weird that they can affect independent addressibility. Is this intended? (No.) !recommendation (See summary.) !wording Replace 9.10(1) by: If two different objects, including nonoverlapping parts of the same object, are independently addressable, they can be manipulated concurrently by two different tasks without synchronization. Any two nonoverlapping objects are independently addressable if either object is specified as independently addressable (see C.6). Otherwise, two nonoverlapping objects are independently addressable except when they are both parts of a composite object for which a non-confirming representation item is used to specify packing, record layout, Component_Size, or convention, in which case it is unspecified whether the parts are independently addressable. Update the AARM notes in 13.1 (8.v, 8.w; 8.hh) to add the new pragmas independent and independent components. Change 13.1(15/1) as follows: A derived type inherits each type-related aspect of representation of its parent type that was directly specified before the declaration of the derived type, or (in the case where the parent is derived) that was inherited by the parent type from the grandparent type. A derived subtype inherits each subtype-specific aspect of representation of its parent subtype that was directly specified before the declaration of the derived type, or (in the case where the parent is derived) that was inherited by the parent subtype from the grandparent subtype, but only if the parent subtype statically matches the first subtype of the parent type. An inherited aspect of representation is overridden by a subsequent representation item that specifies {a different value for} the same aspect of the type or subtype. AARM Ramification: If an inherited non-confirming aspect is confirmed by a later representation item for a derived type, the confirming representation item does not override the inherited one. Thus the derived type has both a specified confirming and an inherited non-confirming representation item -- this means that rules that apply only to non-confirming representation items still apply to this type. Change 13.2(9) as follows: * For a packed array type, if the [component subtype's] Size {of the component subtype} is less than or equal to the word size, [and Component_Size is not specified for the type,] Component_Size should be less than or equal to the Size of the component subtype, rounded up to the nearest factor of the word size. Change 13.3(13) as follows: If an Address is specified, it is the programmer's responsibility to ensure that the address is valid {and appropriate for the entity and its use}; otherwise, program execution is erroneous. AARM Discussion: "Appropriate for the entity and its use" covers cases such as misaligned addresses, read-only code addresses for variable data objects (and non-executable data addresses for code units), and addresses which would force objects that are supposed to be independently addressable to not be. Such addresses may be "valid" as they designate locations that are accessible to the program, but the program execution is still erroneous (meaning that implementations do not have to worry about these cases). Modify C.6(2) as follows: The form for pragmas Atomic, Volatile, {Independent, }Atomic_Components, [and ]Volatile_Components{, and Independent_Components} is as follows: Add after C.6(4): [Syntax] pragma Independent (*component*_local_name); Add after C.6(6): pragma Independent_Components(local_name); Change C.6(9) as follows: [Name Resolution Rules] The local_name in an Atomic or Volatile pragma shall resolve to denote either an object_declaration, a non-inherited component_declaration, or a full_type_declaration. {The *component*_local_name in an Independent pragma shall resolve to denote a non-inherited component_declaration.} The *array*_local_name in an Atomic_Components or Volatile_Components pragma shall resolve to denote the declaration of an array type or an array object of an anonymous type. {The local_name in an Independent_Components pragma shall resolve to denote the declaration of an array or record type or an array object of an anonymous type.} Add after C.6(13): [Legality Rules] It is illegal to apply either an Independent or Independent_Components pragma to a component, object, or type if the implementation cannot provide the independent addressability required by the pragma (see 9.10). It is illegal to specify a representation aspect for a component, object, or type to which pragma Independent or Independent_Components applies, in a way that prevents the implementation from providing the independent addressability required by the pragma. Add after C.6(14): [Static Semantics] Pragmas Independent and Independent_Components *specify as independently addressable* the named object or component(s), or in the case of a type, all objects of that type. All atomic objects are specified as independently addressable. AARM Ramification: If the compiler cannot guarantee that an object (including a component) to which pragma Independent or pragma Independent_Components applies is independently addressable from any other nonoverlapping object, then the pragma must be rejected. Similarly, an atomic object (including atomic components) is always independently addressable from any other nonoverlapping object. Any representation item which would prevent this from being true should be rejected, notwithstanding what this Standard says elsewhere. End AARM Ramification. !discussion The problem to be addressed is demonstrated by the following (on a byte-addressable target): A : array (1..4) of character; for A'Component_Size use 8; The components of A are no longer independent by the original wording, which would have allowed different encodings of the following statements: A (1) := ; A (4) := ; Independent Sequence: Store to A (1) Store to A (4) Dependent Sequence: Load 32-bit register with A Set MSB to Set LSB to Store 32-bit register to A The dependent sequence is disallowed when pragma Independent_Components applies to A on the byte addressable machine; on a word addressable machine the pragma would be rejected because each component of A is not independently addressable. If the Component_Size clause is confirming (as it is likely to be on a byte-addressable target), then the new wording also requires that the components are independent and therefore the second code sequence is not allowed in that case. More generally, we include "non-confirming" in 9.10(1) so that giving a confirming representation item does not change the semantics of a program. The original wording violated the language design principle explained in 13.1(1.a.2/2). We also added Convention to 9.10(1) to allow non-independent addressability for conventions other than Ada. Atomic objects always have independent addressability compared to any other object (including components). This is necessary so that the intent that tasks can access such objects safely without (separate) synchronization is accomplished. The new pragmas are added in C.6, defining Independent to be applicable to individual record components, and Independent_Components which applies to array and record types. Pragma Independent and Independent_Components are similar to Volatile and Atomic in that only a single entity name is accepted with the pragma. The minutes from the Albuquerque ARG meeting note that pragma Independent_Components should be considered for all composite types; however, there is no way to remove independence for the discriminants of tasks or components of protected types, so the pragma is not needed for those types. Moreover, as a representation pragma, it is not allowed on partial views (by 13.1(9)), so we only need to allow array and record types. We added the term specify as independently addressable C.6(14.1) to simplify the wording needed in 9.10(1), and to ensure that the pragmas have a definition in C.6 (defining them completely in 9.10(1) would make C.6 mysterious). A separate problem was identified during the preparation of this AI. A confirming representation item specifies the value that the compiler would have chosen anyway. However, a derived type can inherit a non-confirming representation value; if this value is then specified, we want it to remain non-confirming. We also noted that 13.2(9) seems to allow different behavior if a confirming representation item is given, which breaks the model that confirming representation items never change anything. It was also noted that an address specified in an address clause could be used to break independent addressibility in places where it was required. 13.3(13) could cover this by using an expansive reading of "valid" (where an address isn't valid if it causes some violation of semantics even if it is legitimate address for the target), but hardly anyone [Editor's note: except Tucker! ;-)] reads this paragraph that way. After all, Ada has a fairly specific meaning for a "valid" value of a type (see 13.9.1), and it mainly refers to the actual bit pattern of the value. Thus we add clarifying wording and an AARM note. !corrigendum 9.10(1) @drepl If two different objects, including nonoverlapping parts of the same object, are @i, they can be manipulated concurrently by two different tasks without synchronization. Normally, any two nonoverlapping objects are independently addressable. However, if packing, record layout, or Component_Size is specified for a given composite object, then it is implementation defined whether or not two nonoverlapping parts of that composite object are independently addressable. @dby If two different objects, including nonoverlapping parts of the same object, are @i, they can be manipulated concurrently by two different tasks without synchronization. Any two nonoverlapping objects are independently addressable if either object is specified as independently addressable (see C.6). Otherwise, two nonoverlapping objects are independently addressable except when they are both parts of a composite object for which a non-confirming representation item is used to specify packing, record layout, Component_Size, or convention, in which case it is unspecified whether the parts are independently addressable. !corrigendum 13.1(15/1) @drepl A derived type inherits each type-related aspect of representation of its parent type that was directly specified before the declaration of the derived type, or (in the case where the parent is derived) that was inherited by the parent type from the grandparent type. A derived subtype inherits each subtype-specific aspect of representation of its parent subtype that was directly specified before the declaration of the derived type, or (in the case where the parent is derived) that was inherited by the parent subtype from the grandparent subtype, but only if the parent subtype statically matches the first subtype of the parent type. An inherited aspect of representation is overridden by a subsequent representation item that specifies the same aspect of the type or subtype. @drepl A derived type inherits each type-related aspect of representation of its parent type that was directly specified before the declaration of the derived type, or (in the case where the parent is derived) that was inherited by the parent type from the grandparent type. A derived subtype inherits each subtype-specific aspect of representation of its parent subtype that was directly specified before the declaration of the derived type, or (in the case where the parent is derived) that was inherited by the parent subtype from the grandparent subtype, but only if the parent subtype statically matches the first subtype of the parent type. An inherited aspect of representation is overridden by a subsequent representation item that specifies a different value for the same aspect of the type or subtype. !corrigendum 13.2(9) @drepl @xbullet @dby @xbullet !corrigendum 13.3(13) @drepl If an Address is specified, it is the programmer's responsibility to ensure that the address is valid; otherwise, program execution is erroneous. @dby If an Address is specified, it is the programmer's responsibility to ensure that the address is valid and appropriate for the entity and its use; otherwise, program execution is erroneous. !corrigendum C.6(2) @drepl The form for pragmas Atomic, Volatile, Atomic_Components, and Volatile_Components is as follows: @dby The form for pragmas Atomic, Volatile, Independent, Atomic_Components, Volatile_Components, and Independent_Components is as follows: !corrigendum C.6(4) @dinsa @xindent<@b Volatile(@fa);> @dinst @xindent<@b Independent(@i@fa);> !corrigendum C.6(6) @dinsa @xindent<@b Volatile_Components(@i@fa);> @dinst @xindent<@b Independent_Components(@fa);> !corrigendum C.6(9) @drepl The @fa in an Atomic or Volatile pragma shall resolve to denote either an @fa, a non-inherited @fa, or a @fa. The @i@fa in an Atomic_Components or Volatile_Components pragma shall resolve to denote the declaration of an array type or an array object of an anonymous type. @dby The @fa in an Atomic or Volatile pragma shall resolve to denote either an @fa, a non-inherited @fa, or a @fa. The @i@fa in an Independent pragma shall resolve to denote a non-inherited @fa. The @i@fa in an Atomic_Components or Volatile_Components pragma shall resolve to denote the declaration of an array type or an array object of an anonymous type. The @fa in an Independent_Components pragma shall resolve to denote the declaration of an array or record type or an array object of an anonymous type. !corrigendum C.6(13) @dinsa If a pragma Volatile, Volatile_Components, Atomic, or Atomic_Components applies to a stand-alone constant object, then a pragma Import shall also apply to it. @dinss It is illegal to apply either an Independent or Independent_Components pragma to a component, object, or type if the implementation cannot provide the independent addressability required by the pragma (see 9.10). It is illegal to specify a representation aspect for a component, object, or type to which pragma Independent or Independent_Components applies, in a way that prevents the implementation from providing the independent addressability required by the pragma. !corrigendum C.6(14) @dinsa These pragmas are representation pragmas (see 13.1). @dinst Pragmas Independent and Independent_Components @i the named object or component(s), or in the case of a type, all objects of that type. All atomic objects are specified as independently addressable. !ACATS Tests ACATS tests can be generated that would verify the rejection of the pragmas for all but bit-addressable architectures (TBD). The verification of code generation is target dependent and probably can't be effectively tested. !appendix [Note: This thread originally branched off of the discussion in AI-447. Mail preceding this one can be found there. - Editor] From: Pascal Leroy Sent: Friday, February 17, 2006 6:34 AM > Indeed. I actually think that there should be a rule that the > compiled accept all confirming representation clauses, which > is not necessarily the case. There is actually an IA to that effect in Ada 2005, see 13.1(21.1). Of course, with dope and dynamic stuff and so on this cannot be a requirement. But this IA is intended to nudge implementers in the right direction. **************************************************************** From: Robert Dewar Sent: Friday, February 17, 2006 7:04 AM Good, I had missed that. I agree IA is fine here (as I have commented in the past, IA is often stronger than a requirement, since it is to be interpreted informally -- to me all documentation requirements would be stronger if they were IA :-)) **************************************************************** From: Robert A. Duff Sent: Friday, February 17, 2006 7:10 AM > > Indeed. I actually think that there should be a rule that the > > compiled accept all confirming representation clauses, which > > is not necessarily the case. > > There is actually an IA to that effect in Ada 2005, see 13.1(21.1). Of > course, with dope and dynamic stuff and so on this cannot be a > requirement. But this IA is intended to nudge implementers in the right > direction. 21.1/2 {AI95-00291-02} A confirming representation item should be supported. This is not "mere" Implementation Advice. It is "Recommended Level of Support", so the "should" becomes "shall" in the SP Annex. I wonder if that was the intent. The AARM says: Wording Changes from Ada 95 ... 28.n/2 {AI95-00291-02} Added wording to define confirming representation items, and to suggest that they should always be supported. This is not just a wording change, and does not merely "suggest". I don't understand the "with dope and dynamic stuff" part of your comment above (which echoes the sentiment in the AARM): 21.a.1/2 To be honest: A confirming representation item might not be possible for some entities. For instance, consider an unconstrained array. The size of such a type is implementation-defined, and might not actually be a representable value, or might not be static. The way I read para 21.1 is: if you write a confirming representation clause (confirming some aspect of rep), then the compiler has to accept it. It does not claim that there is a way to confirm every aspect of everything (e.g. sizes of non-static stuff). You cannot, for example, specify that you want a twos complement little endian representation for an integer, even if that would be confirming. So I don't see any dishonesty that the "To be honest" needs to address. **************************************************************** From: Randy Brukardt Sent: Friday, February 17, 2006 2:07 PM > This is not just a wording change, and does not merely "suggest". This is a BI, so it wasn't documented as an extension. I've just finished going over the entire set of BIs and changing that (with a marker so it's possible to tell the difference between BI and Amendment extensions, incompatibilities, and the like), but I managed to miss this one. (It's likely that I missed others as well, feel free to point them out.) We felt that this was always the intent of Ada, it just wasn't written down. (I'm not aware of any compiler that would violate this rule - Janus/Ada doesn't implement all rep. items to the Recommended Level of Support, but it allows confirming ones on all of them.) ... > The way I read para 21.1 is: if you write a confirming representation clause > (confirming some aspect of rep), then the compiler has to accept > it. It does not claim that there is a way to confirm every aspect of > everything (e.g. sizes of non-static stuff). You cannot, for example, > specify that you > want a twos complement little endian representation for an integer, even if > that would be confirming. So I don't see any dishonesty that the "To be > honest" needs to address. That's one way to read it, but I thought there was enough possibility for confusion that it was worth reiterating it. It's easy to read it as meaning that there must be a way to write a confirming item (I read it that way every time, I agree your reading makes more sense, but I *still* read it the other way.) I suppose the AARM note could be classified as a Ramification or some such, but it still seems iffy to me. **************************************************************** From: Robert Dewar Sent: Friday, February 17, 2006 1:44 PM > The way I read para 21.1 is: if you write a confirming representation clause > (confirming some aspect of rep), then the compiler has to accept it. It does > not claim that there is a way to confirm every aspect of everything > (e.g. sizes of non-static stuff). You cannot, for example, specify that you > want a twos complement little endian representation for an integer, even if > that would be confirming. So I don't see any dishonesty that the "To be > honest" needs to address. Hmm, suppose my compiler is very clever, and figures out it can overlap two components of a record because they are never used at the same time, how do I confirm that. Suppose that my compiler has 'Size be some value, but does not follow the IA/requirements that come with this in the RM, then a confirming rep clause says too much. Suppose that my compiler by default allows two fields in the same byte to be accessed independently different tasks, because it figures this is safe, if I write an implicit rep clause, then I treat on the independence land mine. [this is fun!] Suppose a compiler figures out that it can store an object of type Integer in 8 bits, because no larger value is stored, can I really specify a size of 8 bits for the object? Suppose a compiler uses different representations for local and global objects, what's the 'Size of the type in that case? Whatever the answer, a confirming rep clause will mess things up. How can I confirm the layout of a record with dynamic fields, well perhaps pragma Pack might do it, can pragma Pack ever be considered to be a confirming rep clause (I think not). If I store biased types in some cases, do you really want me to be able to force it in all cases. Suppose I align a type in different ways in different cases. In this case 'Alignment will return the lowest value, but specifying this lowest value will force this value in all cases, is that confirming? This should have been IA, not a requirement, in my view. **************************************************************** From: Randy Brukardt Sent: Friday, February 17, 2006 2:22 PM > This should have been IA, not a requirement, in my view. The requirement is as Bob described it: "*IF* you can write a confirming rep. item, then it shall be supported.". It's not a requirement to always be able to write a confirming rep. item. In most of your examples, you can't write a confirming rep. item (because there are multiple sizes, the size isn't known, the item has properties not described by a rep. item, etc.) So there is no problem, the requirement means nothing. In the rest, you are giving different semantics to items that don't have a rep. item to those that do. It was the sense of the ARG that having such constructs was in very bad taste. It was *precisely* the intent of the ARG to (implicitly) ban such things in an implementation that claims to follow the Recommended Level of Support. (I say that because we spent a lot of effort changing any rule in the Standard that even seemed to imply that could be the case.) So, I don't see that there is any problem with a requirement here. Implementers have a lot of leaway in defining the default representation, so it shouldn't be a problem to skirt the rule if necessary. P.S. See, Bob, why we need the To Be Honest?? :-) **************************************************************** From: Robert Dewar Sent: Friday, February 17, 2006 2:29 PM > In most of your examples, you can't write a confirming rep. item (because > there are multiple sizes, the size isn't known, the item has properties not > described by a rep. item, etc.) So there is no problem, the requirement > means nothing. Actually in almost all the cases I gave, you *can* write a confirming rep item. It just does not confirm exactly. > In the rest, you are giving different semantics to items that don't have a > rep. item to those that do THe RM does this! If you don't have a rep clause, then you are guaranteed independence. But if you give a confirming rep clause you are no longer guaranteed independence. Has this changed in 2005? If so, what language changed this. **************************************************************** From: Pascal Leroy Sent: Monday, February 20, 2006 2:17 AM This didn't change, and it was an oversight as far as I can tell. It seems to me that we should have added "nonconfirming" to the last sentence of 9.10(1). This can always be done later by an AI: it won't affect the code generated by compilers. **************************************************************** From: Robert Dewar Sent: Monday, February 20, 2006 5:49 AM It definitely can affect the generated code. It immediately occurred to me, it would surprise me if there were not other similar consequences. This is a very delicate area. One problem for example: There is nothing now to stop a compiler from doing things quite differently for rep'ed and non-rep'ed stuff. Just because you think you have specified all the visible standard attributes does not mean you have specified enough. Also now you are giving real semantics to the notion of a confirming rep clause, and I don't see how that is possible. After all the compiler can change its defaults at any time. It seems really awkward in a formal requirements sense to talk about what the compiler *would have* done. Also how do you know you are confirming all the attributes. And how is this testable? This seems a quagmire to me, better to put this in implementation advice, where we do not have to worry about formal definition. In fact the whole business of confirming rep clauses would have been better as IA. **************************************************************** From: Robert Dewar Sent: Monday, February 20, 2006 7:15 AM One really worrisome thing here. If you are going to start ascribing real semantics to confirming rep clauses, then the compiler has to be able to recognize confirming rep clauses. That's really hard. It would mean major new circuitry for us to figure this out, something like laying out the type with and without rep clauses to see if it came out the same - UGH! **************************************************************** From: Pascal Leroy Sent: Monday, February 20, 2006 9:17 AM True, we'd have to do the same. On the other hand, doesn't it bother you that if I write: type T is new String; for T'Component_Size use 8; my program becomes mysteriously nonportable because of 9.10(1)? This doesn't seem to be helpful to users... **************************************************************** From: Robert Dewar Sent: Monday, February 20, 2006 10:35 AM Well it is not mysteriously nonportable, it is just that you can't count on independence for strings, something I have always known, and which is critical on some word addressed architectures like the old alpha. Standard.String is packed, so definitely any program expecting dependence is seriously non-portable! So your example is not a good one, T lacks independence before you even give a component size. If I do type T is array (Positive) of Character; then on the old Alpha, you have to allocate 32-bits/character. If you say for T'Component_Size use 8; then everything is fine, you get 8-bit characters but you lose independence. **************************************************************** From: Randy Brukardt Sent: Monday, February 20, 2006 8:22 PM > This didn't change, and it was an oversight as far as I can tell. It > seems to me that we should have added "nonconfirming" to the last sentence > of 9.10(1). This can always be done later by an AI: it won't affect the > code generated by compilers. I agree. We spent a lot of time going thought Section 13 and eliminating any wording that implied any dependence on the existence of confirming rep. clauses. We didn't look anywhere else, probably because we bought the fiction that they don't affect semantics. :-) Anything that implies otherwise is a mistake, and it should be fixed ASAP. Sounds like a candidate for AI05-00001. **************************************************************** From: Randy Brukardt Sent: Monday, February 20, 2006 8:36 PM > One really worrisome thing here. If you are going to start ascribing > real semantics to confirming rep clauses, then the compiler has to be > able to recognize confirming rep clauses. That's really hard. It would > mean major new circuitry for us to figure this out, something like > laying out the type with and without rep clauses to see if it came > out the same - UGH! It seems to me that you have this bass-ackwards. A confirming rep. clause has no semantics; it's what the compiler would have done anyway. (Independence is one of the things that the compiler has to "do anyway"). A non-confirming rep. clause *might* have semantics. But it's not necessary to apply semantics just because there is a rep. clause (you don't have go out of your way to make things not independent, for example). T'Size = 16 might not be confirming, but it still is independent, for instance. A few days ago, you talked about "almost confirming" rep. clauses. Such a thing is not possible; either it is confirming, or it is not. If T'Size = 16, then for T'Size use 16; is confirming. Period. And whether or not the rep. clause is given is semantically neutral. If you need to know if a rep. clause is confirming, there is something wrong with your default representations. In a new compiler, you fix the defaults, you don't stand on your head. Now, I realize that compatibility reasons might mean that you need to stand on your head, but the cause of that is bad taste in existing choices. We wanted to strongly discourage those choices, and the harder you have to work to make them, the more successful we were. ;-) **************************************************************** From: Robert Dewar Sent: Monday, February 20, 2006 9:18 PM >> One really worrisome thing here. If you are going to start ascribing >> real semantics to confirming rep clauses, then the compiler has to be >> able to recognize confirming rep clauses. That's really hard. It would >> mean major new circuitry for us to figure this out, something like >> laying out the type with and without rep clauses to see if it came >> out the same - UGH! > > It seems to me that you have this bass-ackwards. Yes, well I see how it may seem that way if you have not really carefully thought out the issues, in which case the "requirement" of allowing confirming rep clauses may seem like a no-brainer. > A confirming rep. clause has no semantics; it's what the compiler would have > done anyway. (Independence is one of the things that the compiler has to "do > anyway"). Sorry Randy, that's plain wrong, a compiler does not have to provide independence if a rep clause is present. That's the way the language is. That means that the compiler does not have to generate code ensuring independence if a rep clause is present. On some machines, it takes extra code to guarantee independence in the default case. The idea that independence has to provided if a rep clause is confirming is really difficult since you need a way to test this predicate, and certainly in our compiler there is easy way to do this. I suspect that some people may have an over-naive view of code generation for modern processors here ... > A non-confirming rep. clause *might* have semantics. But it's not > necessary to apply semantics just because there is a rep. clause (you don't > have go out of your way to make things not independent, for example). T'Size > = 16 might not be confirming, but it still is independent, for instance. Might we perhaps remind ourselves of what 9.10 actually says: However, if packing, record layout, or Component_Size is specified for a given composite object, then it is implementation defined whether or not two nonoverlapping parts of that composite object are independently addressable. It is not *all* rep clauses that have this effect, and in particular, specifying 'Size for a type does NOT give you permission to compromise independent addressability for record components or stand alone objects. If you have a record type, then it is mandatory to ensure independent addressability unless a pragma Pack is given, or a record layout is given. Similarly for an array, it is mandatory to ensure independent addressability unless a pragma Pack is given, or a component clause is given. Note incidentally that this means that a compiler MUST reject type R is array (0 .. 31) of Boolean; for R'Size use 32; XR : R; for XR'Size use 32; unless it has a way of independently addressing bits (in other words, the IA of 13.3(53): 53 A Size clause on a composite subtype should not affect the internal layout of components. often becomes a requirement in practice because of the rules on independent addressability. The rules on independent addressability have powerful effects, it is important to bear them in mind whenever you are discussing rep clauses. > A few days ago, you talked about "almost confirming" rep. clauses. Such a > thing is not possible; either it is confirming, or it is not. If T'Size = > 16, then for T'Size use 16; is confirming. Period. And whether or not the > rep. clause is given is semantically neutral. Actually again, this is NOT the semantics of the language as it stands today (Ada 95). Specifying 'Size officially affects only packing and unchecked conversion, so if by default have 'Size of 16 for a type for which no 'Size is specified, then all you are saying is that you will pack it this way if you can, and that UC will work for 16 bits. But look at the Ada 95 RM ... we have the following IA, that applies *ONLY* if a Size clause is *explicitly* given: 50 If the Size of a subtype is specified, and allows for efficient independent addressability (see 9.10) on the target architecture, then the Size of the following objects of the subtype should equal the Size of the subtype: 51 Aliased objects (including components). 52 Unaliased components, unless the Size of the component is determined by a component_clause or Component_Size clause. So suddenly a "confirming" rep clause for the type brings these two IA paras into play where they were not in play before. If you find that odd, all i can say is that is the way the language is. I did not write this section, I am just a reader reading what is there. > If you need to know if a rep. clause is confirming, there is something wrong > with your default representations. No, that's just wrong, if a rep clause is given you do NOT have to generate less efficient code to ensure independence! In fact in Ada 95, given an "obvious" confirming rep clause is a way of telling the compiler: don't bother with independence. You can change this (in an incompatible way) in Ada 2005 of course, but a) you had better realize you are doing so (looks like the critical issue of independence was not even discussed). b) if you make incomaptibilities you had better justify them c) you had better make sure that things are easily implementable These requirements interact, and it looks like more thought is needed for all three. I would just remove the stuff about confirming rep clauses. It has either no effect, or it has effects that are possibly detrimental. In other words, you put this there because you think it will have some useful effect for some existing or future compilers. Just *why* do you think a compiler might *not* allow a "confirming" rep clause? I don't see the answer to this question. Looks to me like this new requirement was put in as something obvious (a la Randy mail that I am replying to here), and was not carefully enough thought out. If you want an example of efficiency of code generation, consider X : String (1 .. 4); X (1) := Ascii.Nul; X (3) := Ascii.Nul; it is just fine to generate a word load, followed by an AND, followed by a word store in this case, since independence is not required. But if I do type S is array (Positive range <>) of Character; X : S (1 .. 4) then if I choose (as many compilers would) to still store the characters in 8-bit bytes, the above combination would not be valid, since for this type data independence is required. But if I add the "confirming" rep clause for S'Component_Size use 8; Now I can generate the load/and/store sequence since data independence is no longer required. Again, I didn't write this, I am just a reader, and that's what the Ada 95 RM says. **************************************************************** From: Robert Dewar Sent: Monday, February 20, 2006 9:25 PM > I agree. We spent a lot of time going thought Section 13 and eliminating any > wording that implied any dependence on the existence of confirming rep. > clauses. We didn't look anywhere else, probably because we bought the > fiction that they don't affect semantics. :-) Anything that implies > otherwise is a mistake, and it should be fixed ASAP. Sounds like a candidate > for AI05-00001. I look forward to the reading the suggested fix, I don't see one that does not introduce incompatibilities. **************************************************************** From: Randy Brukardt Sent: Monday, February 20, 2006 10:18 PM > > A confirming rep. clause has no semantics; it's what the compiler would have > > done anyway. (Independence is one of the things that the compiler has to "do > > anyway"). > > Sorry Randy, that's plain wrong, a compiler does not have to provide > independence if a rep clause is present. That's the way the language is. Yes, but that's the bug. We don't require it for any other representation property, and it is a clear oversight that that it was missed here. > That means that the compiler does not have to generate code ensuring > independence if a rep clause is present. On some machines, it takes > extra code to guarantee independence in the default case. That seems like a very bad design for a machine, at least for Ada. :-) If you have to use extra code by default, pretty much everything will get weighted down with that code. On all of the machines I'm aware of, it's just a space vs. time trade-off, and there is a solution (not necessarily optimal) that doesn't require extra code. > The idea that independence has to provided if a rep clause is confirming > is really difficult since you need a way to test this predicate, and > certainly in our compiler there is easy way to do this. I presume you meant "*no* easy way". I understand, but again this seems like a singularly bad machine to run Ada on. It would only be usable in an environment with strict, unbreakable coding rules; while such exist, they aren't the norm for programming of any sort. ... > Might we perhaps remind ourselves of what 9.10 actually says: > > However, if packing, record layout, or Component_Size is specified for > a given composite object, then it is implementation defined whether or > not two nonoverlapping parts of that composite object are > independently addressable. > > It is not *all* rep clauses that have this effect, and in particular, > specifying 'Size for a type does NOT give you permission to compromise > independent addressability for record components or stand alone objects. Right, but remember that this rule is wrong; at a least it should say "non-confirming" like all other rules for rep. clauses. ... > > A few days ago, you talked about "almost confirming" rep. clauses. Such a > > thing is not possible; either it is confirming, or it is not. If T'Size = > > 16, then for T'Size use 16; is confirming. Period. And whether or not the > > rep. clause is given is semantically neutral. > > Actually again, this is NOT the semantics of the language as it > stands today (Ada 95). We're not talking about Ada 95; we're talking about Ada 2005. Ada 95 had lots of problems with these rules, they've been fixed. Moreover, the AIs in question are BIs; they apply to Ada 95 as well as Ada 2005. ... > But look at the Ada 95 RM ... we have the following IA, that > applies *ONLY* if a Size clause is *explicitly* given: > > 50 If the Size of a subtype is specified, and allows for efficient > independent addressability (see 9.10) on the target architecture, > then the Size of the following objects of the subtype should equal > the Size of the subtype: Again, this was changed by AI-51: "is specified, and" was dropped. This applies to all sizes. > > If you need to know if a rep. clause is confirming, there is something wrong > > with your default representations. > > No, that's just wrong, if a rep clause is given you do NOT have > to generate less efficient code to ensure independence! In fact > in Ada 95, given an "obvious" confirming rep clause is a way of > telling the compiler: don't bother with independence. That's a horribly kludgy usage, and precisely the sort of thing that we wanted to get rid of. If that means that the default objects all have to take 64-bits, so be it. (Although I seriously doubt that would be the case on any commonly used processors.) ... > In other words, you put this there because you think it will > have some useful effect for some existing or future compilers. > Just *why* do you think a compiler might *not* allow a > "confirming" rep clause? Mainly because it appears useless to them. User need to know that it is safe to confirm the representation of the type, and that it isn't going to have some bizarre side-effects (such as the loss of independence). Moreover, implementers tend not to do work that's useless. It's important for them to know that confirming rep. clauses aren't useless. > I don't see the answer to this question. Looks to me like this > new requirement was put in as something obvious (a la Randy > mail that I am replying to here), and was not carefully > enough thought out. > > If you want an example of efficiency of code generation, consider > > X : String (1 .. 4); > > X (1) := Ascii.Nul; > X (3) := Ascii.Nul; > > it is just fine to generate a word load, followed by an AND, > followed by a word store in this case, since independence > is not required. But if I do > > type S is array (Positive range <>) of Character; > X : S (1 .. 4) > > then if I choose (as many compilers would) to still store > the characters in 8-bit bytes, the above combination would > not be valid, since for this type data independence is > required. If you don't have byte operations, the default component size for this array cannot be 8. It has to be 16 or 32 or whatever. Or you have to provide independence all of the time (and I agree that's too expensive). But are there any such machines in use today? The old Alphas are, well, old, and everything else I can think of has 8 bit operations. > But if I add the "confirming" rep clause > > for S'Component_Size use 8; > > Now I can generate the load/and/store sequence since > data independence is no longer required. And then there is no problem, because this isn't confirming on this machine. > Again, I didn't write this, I am just a reader, and > that's what the Ada 95 RM says. And it's clearly wrong. A rep. clause like the above should never, ever change the semantics. In any case, I agree that we need to give careful consideration to changing this rule, because it might cause a real hardship. (Although I'd like to see concrete examples of code that causes trouble on particular processors.) One solution would be to have an independent way to specify "independence", so kludges like expecting a confirming clause to have a semantic meaning aren't necessary. Sure sounds like an AI05. **************************************************************** From: Robert Dewar Sent: Monday, February 20, 2006 10:52 PM > Right, but remember that this rule is wrong; at a least it should say > "non-confirming" like all other rules for rep. clauses. Yes, but that is incompatible and has severe implementation consequences because it is hard to check the predicate confirming. Why? Well if we have a record type, the only way we know what the default representation is is to lay it out with no rep clauses. So you are in practice suggesting that we lay it out twice whenever there is a rep clause, once to see the default layout, once to see the layout with the rep clause, to see if they are the same. The rules for layout of records in the default case are extremely complex and ABI dependent. Not all the machines in the world are simple minded as the x86 when it comes to alignment (though for efficiency, you want to align things on the x86 far more than is usually done). > That's a horribly kludgy usage, and precisely the sort of thing that we > wanted to get rid of. If that means that the default objects all have to > take 64-bits, so be it. (Although I seriously doubt that would be the case > on any commonly used processors.) I think you just don't know enough processors well enough :-). Just as we take shared generics into serious consideration even though almost all Ada 95 compilers do not try to do universal sharing, we certainly must take architectures other than the x86 into effect, and casually causing major incompatibilties with these architectures and announcing "so be it" is casual beyond belief to me. >> If you want an example of efficiency of code generation, consider >> >> X : String (1 .. 4); >> >> X (1) := Ascii.Nul; >> X (3) := Ascii.Nul; >> >> it is just fine to generate a word load, followed by an AND, >> followed by a word store in this case, since independence >> is not required. But if I do >> >> type S is array (Positive range <>) of Character; >> X : S (1 .. 4) >> >> then if I choose (as many compilers would) to still store >> the characters in 8-bit bytes, the above combination would >> not be valid, since for this type data independence is >> required. > > If you don't have byte operations, the default component size for this array > cannot be 8. It has to be 16 or 32 or whatever. Or you have to provide > independence all of the time (and I agree that's too expensive). Please read more carefully, we are of COURSE talking about a machine with byte operations here. hat's the WHOLE POINT of this example. Indeed just think of it as an example for the x86. Code where you do not have to worry about independence mov eax,w and eax,0xff00ff00 mov w,eax Code where you have to worry about independence sub al,al mov w+0,al mov w+2,al Now which sequence is faster depends of course on the state of the multiple pipelines and the store buffer (things that a modern optiming compiler worries about). For type String, you can choose either sequence For type S with no Pack, you can only use the second sequence For type S with a pack, you can choose either sequence It is *EXACTLY* intentional that pragma Pack give this kind of freedom! That's why the independence rule is there (for more about independence and its consequences, see Norm Schulman's PhD thesis [NYU, me as the advisor]) > But are there any such machines in use today? The old Alphas are, well, old, > and everything else I can think of has 8 bit operations. You don't know general architectures very well, there are a number of DSP chips and other special purpose chips with odd word lengths! That's why we put a pragma Pack on String, knowing that it destroyed independence. As for the "old" alphas, there are plenty around, and any serious compiler that is intended for general use on the alpha must accomodate this architecture. >> But if I add the "confirming" rep clause >> >> for S'Component_Size use 8; >> >> Now I can generate the load/and/store sequence since >> data independence is no longer required. > > And then there is no problem, because this isn't confirming on this machine. We are talking about a byte addressed machine. I think you fired off your response too quickly here, please reread this example carefully. It applies for instance to the x86. >> Again, I didn't write this, I am just a reader, and >> that's what the Ada 95 RM says. > > And it's clearly wrong. A rep. clause like the above should never, ever > change the semantics. Make up things as you go along if you like, but of COURSE rep clauses can change the semantics in Ada 95. Do you really think the pragma Pack on String is there for any other reason than to change the semantics? > In any case, I agree that we need to give careful consideration to changing > this rule, because it might cause a real hardship. (Although I'd like to see > concrete examples of code that causes trouble on particular processors.) One > solution would be to have an independent way to specify "independence", so > kludges like expecting a confirming clause to have a semantic meaning aren't > necessary. Sure sounds like an AI05. As I said, we put the pragma Pack in in Standard precisely because of the independence issue. This pragma could have a comment: pragma Pack (String); -- ensure a component size of 8 if possible, even at the expense of -- losing independence. A separate way of controlling independence was certainly considered, but rightly rejected as over-complex. I really think this entire issue has been addressed without sufficient thought, and it seems a mess to me. The original formulation of Ada 95 Size/Alignment stuff is a bit of a mess anyway, this seems to make it worse. **************************************************************** From: Randy Brukardt Sent: Monday, February 20, 2006 11:37 PM ... > > And it's clearly wrong. A rep. clause like the above should never, ever > > change the semantics. > > Make up things as you go along if you like, but of COURSE rep clauses > can change the semantics in Ada 95. Do you really think the pragma Pack > on String is there for any other reason than to change the semantics? A pragma Pack can never be confirming, because the "pack" aspect is not one that anything has by default. > > In any case, I agree that we need to give careful consideration to changing > > this rule, because it might cause a real hardship. (Although I'd like to see > > concrete examples of code that causes trouble on particular processors.) One > > solution would be to have an independent way to specify "independence", so > > kludges like expecting a confirming clause to have a semantic meaning aren't > > necessary. Sure sounds like an AI05. > > As I said, we put the pragma Pack in in Standard precisely because of > the independence issue. This pragma could have a comment: > > pragma Pack (String); > -- ensure a component size of 8 if possible, even at the expense of > -- losing independence. > > A separate way of controlling independence was certainly considered, but > rightly rejected as over-complex. Well, pragma Pack is never confirming, so it would in fact be good enough for this purpose. My example was Component_Size, which is a different kettle of fish. And yes, in the absence of pragma Pack/"pragma lose independence", I think that independence ought to be maintained. > I really think this entire issue has been addressed without sufficient > thought, and it seems a mess to me. The original formulation of Ada 95 > Size/Alignment stuff is a bit of a mess anyway, this seems to make it > worse. Sorry, but any more thought on those AIs wasn't going to lead anywhere. I think most of us feel our heads were about to explode when AI-51 was finally finished! Perhaps we would have had different conclusions had you been involved in the meeting discussions, but you weren't, and we didn't. **************************************************************** From: Pascal Leroy Sent: Tuesday, February 21, 2006 2:29 AM > > Right, but remember that this rule is wrong; at a least it should say > > "non-confirming" like all other rules for rep. clauses. > > Yes, but that is incompatible... I must be a bonehead, but I don't see the incompatibility here. Adding "nonconfirming" to 9.10(1) would guarantee independence in *more* cases. I am sure that there are many programs out there that depend on independence, and *removing* independence in some situations would not be acceptable. However I cannot imagine that a program would depend on non-independence (unless it were erroneous). Now of course it could mean generating a less efficient instruction sequence in the new circumstances where you have to guarantee independence. But we don't worry about this: the code generated by a compiler can change at the drop of a hat (in particular, at every new release) and we are not in the business of counting the number of cycles that it takes to perform some operations. Incidentally, I don't understand why 9.10(1) doesn't mention pragma Convention. Consider an array of 4 characters. On an old Alpha, as you explained, it would have to be laid out with components occupying 32 bits. But if you put a pragma Convention (C) on the array, I would expect the components to use 8 bits. (I see that the C standard doesn't specify the size of char, but I am pretty sure that most of the C code out there assumes that it's 8 bits.) **************************************************************** From: Robert Dewar Sent: Tuesday, February 21, 2006 8:02 AM > My example was Component_Size, which is a different kettle of fish. And yes, > in the absence of pragma Pack/"pragma lose independence", I think that > independence ought to be maintained. Gosh, you are now proposing a different semantics between type X is array (0 .. 31) of Boolean; pragma Pack (X); and type X is array (0 .. 31) of Boolean; for X'Component_Size use 1; and furthermore you are suggesting that the latter should maintain independence. That would be *hugely* incompatible, since it would require, on all common architectures, that the latter very common construction should be rejected. You cannot be serious, you must have said something you did not mean. If you are just musing about a language that is not Ada, then what you say may make sense, though I would do it exactly the other way round. I would not make independence the default, since accessing components of a single composite object is the unusual case, which can use commenting in any case, so I would have a pragma Independent_Access (type); with the meaning that the layout of type must accomodate access to different components by independent tasks. > Sorry, but any more thought on those AIs wasn't going to lead anywhere. I > think most of us feel our heads were about to explode when AI-51 was finally > finished! If you feel your head is about to explode, you probably have got things wrong, and you need more work. You should feel comfortable with something when it is finished, not disturbed by it. Anyway, this problem with independence is a significant bug, and I see no reasonable proposal to fix it that is not either very hard to implement on some compilers, or incompatible, so I don't see a way out. I suggest someone finds something, you can't just add a new feature to Ada 2005 that is wrong in this kind of way without at least some idea that it can be fixed. Otherwise better to leave it out, and put it back when you figure out how. After all, this particular rule, about confirming rep clauses, is not addressing some real problem, so why generate real problems with a new requirement that is not in any sense urgent, and which has not been completely thought through. In practice of course, this is not that serious. There is plenty of stuff in the RM that makes no sense that implementors and users and the ACATS tests ignore, and this stuff does not cause any significant problems, since it is ignored. I am sure this new rule will also be essentially ignored by existing compilers. Still it seems unnecessary to add useless things to the standard. **************************************************************** From: Robert Dewar Sent: Tuesday, February 21, 2006 8:17 AM > Now of course it could mean generating a less efficient instruction > sequence in the new circumstances where you have to guarantee > independence. But we don't worry about this: the code generated by a > compiler can change at the drop of a hat (in particular, at every new > release) and we are not in the business of counting the number of cycles > that it takes to perform some operations. No, but we are in the business of not requiring changes to the code generator without a lot of thought, and some idea that this is a benefit. And as I have pointed out before, giving specific semantics to the notion of a confirming rep clause is a potential implementation earthquake, since at least in the case of GNAT, there is simply no easy way to tell if a rep clause is or is not confirming. > Incidentally, I don't understand why 9.10(1) doesn't mention pragma > Convention. Consider an array of 4 characters. On an old Alpha, as you > explained, it would have to be laid out with components occupying 32 bits. > But if you put a pragma Convention (C) on the array, I would expect the > components to use 8 bits. (I see that the C standard doesn't specify the > size of char, but I am pretty sure that most of the C code out there > assumes that it's 8 bits.) I agree, that's a bug, probably the understanding is that pragma convention is equivalent to a component size or record rep clause. But it should be stated. Presumably pragma Convention (Ada) would be exempted, or is this another way to tell the compiler you do not care out independence :-) **************************************************************** From: Randy Brukardt Sent: Tuesday, February 21, 2006 2:36 PM Robert Dewar write: > Randy Brukardt wrote: > > > My example was Component_Size, which is a different kettle of fish. And yes, > > in the absence of pragma Pack/"pragma lose independence", I think that > > independence ought to be maintained. > > Gosh, you are now proposing a different semantics between > > type X is array (0 .. 31) of Boolean; > pragma Pack (X); > > and > > type X is array (0 .. 31) of Boolean; > for X'Component_Size use 1; > > and furthermore you are suggesting that the latter should maintain > independence. No, no, no. The X'Component_Size is not going to be confirming on any common architecture, so it clearly isn't going to require independence. (If it is confirming, then the default implementation *can* guarentee independence, and then it should here, too, and again there is no problem.) Now, if you had stuck with your original example: type X is array (0 .. 31) of Character; pragma Pack (X); and type X is array (0 .. 31) of Character; for X'Component_Size use 8; Then you are exactly right; the latter should maintain independence, while the former doesn't have to. That just follows from the "no semantics for confirming rep. clauses" rules - and it's an easy rule to remember. > > Sorry, but any more thought on those AIs wasn't going to lead anywhere. I > > think most of us feel our heads were about to explode when AI-51 was finally > > finished! > > If you feel your head is about to explode, you probably have got > things wrong, and you need more work. You should feel comfortable > with something when it is finished, not disturbed by it. The problem is that it is hugely difficult to come to agreement on these issues; the solution is just fine. But getting everybody on board to even a relatively trivial issue is very painful work. We even considered no solution at all (essentially the anarchy solution), but that isn't considered acceptable politically. If I was starting a new language (as you put it), I'd blow away the entire definitions of Size, etc. and start over with something that actually makes sense (on the line of the GNAT 'Object_Size). But we're not doing that. Given the options, somebodies ox is going to get gored (or at least injured). In any case, you seem to be ignoring the critical point, which is a usability issue. Do you agree or disagree with the statement "users should be able to add confirming rep. clauses without changing the semantics of their program"? Now, it seems to me that the discussion has pointed out one important point: determining if a record rep. clause is confirming is very difficult, so if there is a real need to do that, we need to look at exempting it from any such requirement. But making that determination for most rep. clauses is reasonably easy, so there needs to be no exception for them. **************************************************************** From: Robert Dewar Sent: Tuesday, February 21, 2006 2:37 PM > Now, if you had stuck with your original example: > > type X is array (0 .. 31) of Character; > pragma Pack (X); > > and > > type X is array (0 .. 31) of Character; > for X'Component_Size use 8; To me it is plain horrible to introduce a fundamental difference between the pragma Pack and the component size clause here (given that the Pack must result in a component size of 8). > In any case, you seem to be ignoring the critical point, which is a > usability issue. Do you agree or disagree with the statement "users should > be able to add confirming rep. clauses without changing the semantics of > their program"? I think that is fine as implementation advice. I think it is a horrible error as a requirement, but still I think most compilers will just ignore it, and no one will notice the difference. > > Now, it seems to me that the discussion has pointed out one important point: > determining if a record rep. clause is confirming is very difficult, so if > there is a real need to do that, we need to look at exempting it from any > such requirement. But making that determination for most rep. clauses is > reasonably easy, so there needs to be no exception for them. It is not so easy to tell if a component clause if confirming or not, since laying out arrays is highly target dependent, so the determination happens deep in the target dependent area. Again, we would have to introduce the idea of laying out the type twice, just to see if the component clause was confirming. **************************************************************** From: Pascal Leroy Sent: Wednesday, February 22, 2006 3:32 AM > > type X is array (0 .. 31) of Character; > > pragma Pack (X); > > > > and > > > > type X is array (0 .. 31) of Character; > > for X'Component_Size use 8; > > To me it is plain horrible to introduce a fundamental > difference between the pragma Pack and the component size > clause here (given that the Pack must result in a component > size of 8). This might represent Dewar's interpretation, but it is not borne out by 13.2, which talks about "storage minimization". Consider the case of an array that has dope. It would be very sensible for pragma Pack to affect the layout of dope *and* components, causing the dope to be compressed somehow. On the other hand the Component_Size clause would only affect the components, not the dope. The above array probably doesn't have dope, but for an unconstrained array (eg, String) there might be a significant different between Pack and Component_Size. > > Now, it seems to me that the discussion has pointed out one important > > point: determining if a record rep. clause is confirming is very > > difficult, so if there is a real need to do that, we need to look at > > exempting it from any such requirement. But making that determination > > for most rep. clauses is reasonably easy, so there needs to be no > > exception for them. > > It is not so easy to tell if a component clause if confirming > or not, since laying out arrays is highly target dependent, > so the determination happens deep in the target dependent > area. It is not so easy for alignment either: in our implementation the choice of size and alignment are intertwined, and the size is clearly affected by a record representation clause. So if we believe that confirming representation clauses have to be neutral (I do) then we have to bite the bullet, we cannot exempt some of them. > Again, we would have to introduce the idea of laying > out the type twice, just to see if the component clause was > confirming. As I said earlier we would have to do the same, but somehow it doesn't seem too bad . In our implementation it wouldn't take more than a couple of days. Time well spent if you ask me compared to, say, Unicode support. (As usual with implementations, YMMV.) **************************************************************** From: Robert Dewar Sent: Wednesday, February 22, 2006 5:58 AM > This might represent Dewar's interpretation, but it is not borne out by > 13.2, which talks about "storage minimization". Consider the case of an > array that has dope. It would be very sensible for pragma Pack to affect > the layout of dope *and* components, causing the dope to be compressed > somehow. On the other hand the Component_Size clause would only affect > the components, not the dope. Well I don't know about "very sensible", since (a) I can't imagine any such scheme that makes sense, and (b) of course as you note below this array does not have any "dope". Let us just say it is conceivable. But since "dope" is semantically invisible, I don't think the above makes any sense at all, a compiler is free to compress or uncompress the dope regardless of the presence or absence of either rep clause. But the distinction that Randy was suggesting was that there was a substantial *semantic* difference between the two cases. Let's look at a very exact case type X is array (0 .. 31) of Character; pragma Pack (X); In randy's suggested interpretation, this does not guarantee independence. type X is array (0 .. 31) of Character; for X'Component_Size use 8; Now, assuming that Standard.String'Component_Size is 8, Randy says this should guarantee independence (and that's something that a real semantic test can be written for). That's what I object to. A formal semantic difference between these two rep clauses, which have always been equivalent in Ada 95. > It is not so easy for alignment either: in our implementation the choice > of size and alignment are intertwined, and the size is clearly affected by > a record representation clause. So if we believe that confirming > representation clauses have to be neutral (I do) then we have to bite the > bullet, we cannot exempt some of them. Well as long as there is no significant semantic effect, I don't see the difficulty >> Again, we would have to introduce the idea of laying >> out the type twice, just to see if the component clause was >> confirming. > > As I said earlier we would have to do the same, but somehow it doesn't > seem too bad . In our implementation it wouldn't take more than a couple > of days. Time well spent if you ask me compared to, say, Unicode support. > (As usual with implementations, YMMV.) This would be a real mess in GNAT, we just wouldn't do it. It would represent weeks of work, may be more, to completely change the way types are layed out. That's because the layout occurs very late in the back end, and we would have to alter the entire interface between the back end and front end. Note that Ada is obviously designed to allow this late layout of composite objects (that's why things like record_type'Size are not static when they perfectly well could be from a semantic point of view when the record has all static layout). Actually regarding the Unicode support, we have customers taking full advantage of this Ada 2005 feature right now (we have fully implemented this for a while). To me, to go through this (much more difficult) implementation effort just to deal with this independence glitch would be a major nonsense, which would benefit absolutely no users at all. So adding "non-confirming" to the independence paragraph is not a minor fix, it is a major change at the last moment, which I find entirely unacceptable. **************************************************************** From: Tucker Taft Sent: Wednesday, February 22, 2006 5:41 PM This topic feels a bit overblown to me. We are mostly talking about the issue of independence, and I would expect that for a given representation, either the load/stores are independent or they aren't. I would be surprised that if you had two types with identical representations, that an implementation would provide independence for one but not for the other simply because there was no rep. clause on one but there was on the other. There are a finite number of Ada implementations, and it is unlikely to increase any time soon. Do any implementations actually go out of there way to provide independence for a given representation *only* when there are no rep. clauses? Seems like most of us have plenty of better things to do. **************************************************************** From: Robert Dewar Sent: Wednesday, February 22, 2006 9:10 PM You might equally ask whether implementations go out of their way to reject confirming rep clauses, and the answer is no, they do not. Either we are talking about crafting the language in a way that makes sense for all reasonable implementations, in which case we have to worry about the independence issue (I gave a perfectly reasonable example of a case in which a compiler might generate different code depending on whether independence is require, you can easily find other examples. Or we are taking a pragmatic view wrt existing compilers, in which case the whole business of mentioning confirming rep clauses is junk. If there are any existing compilers that reject confirming rep clauses, the RM is not likely to make them change their implementation anyway! **************************************************************** From: Robert Dewar Sent: Wednesday, February 22, 2006 9:13 PM > Do any implementations actually go out > of there way to provide independence for a given > representation *only* when there are no rep. clauses? > Seems like most of us have plenty of better things to do. That's exactly the wrong way round. You have to go out of your way to guarantee independence. The back end is in the business of combining instructions to reduce the instruction count, and the point of independence is to prevent such combining. I have no idea whether the GCC back end can do combinations that are troublesome in practice. It is almost impossible to make absolute statements about what the optimizer will do, since it works with the machine description in a goal driven way, and figuring out all possible outcomes is infeasible. **************************************************************** From: Randy Brukardt Sent: Wednesday, February 22, 2006 9:31 PM Out of curiosity, how do you guarantee independence when it is required by the language for such a backend? On the face of it, it would seem incompatible with Ada. **************************************************************** From: Tucker Taft Sent: Thursday, February 23, 2006 9:03 AM >> Do any implementations actually go out >> of there way to provide independence for a given >> representation *only* when there are no rep. clauses? >> Seems like most of us have plenty of better things to do. > > That's exactly the wrong way round. You have to go > out of your way to guarantee independence. Isn't that what my question is asking? Do any implementations make an effort to guarantee independence? Or do they just rely on choosing default representations that they presume will provide it? > ... The back > end is in the business of combining instructions to > reduce the instruction count, and the point of > independence is to prevent such combining. Combining is not really a problem for independence. For independence the key is that you don't store more bits than you need to. Loading more is OK. (This is not about atomicness, which is a separate discussion.) But the real question is does GNAT make an effort to prevent storing more bits than necessary, or do they just presume that if the machine has instructions for storing 16-bit values directly, that that is what the backend will do? I suspect that most implementations where the back end and front end are supported by separate organizations, that there is an implicit understanding that overlong stores won't be used unless there is no choice. > I have no idea whether the GCC back end can do > combinations that are troublesome in practice. > It is almost impossible to make absolute > statements about what the optimizer will do, > since it works with the machine description > in a goal driven way, and figuring out all > possible outcomes is infeasible. I don't think it is combinations. It is overlong stores. And a troublesome overlong store is one that also requires a load and a mask. In any case, the real question is whether GNAT is doing something special to guarantee independence for the default representation? **************************************************************** From: Randy Brukardt Sent: Thursday, February 23, 2006 4:37 PM As usual, Tucker has more clearly stated my question. It seems that usually independence is something that you would expect out of a back-end, not something you would need to ask for. Of course, a front-end creator could be wrong about that assumption, but it seems likely that they wouldn't find that out until there was a bug report... **************************************************************** From: Robert Dewar Sent: Thursday, February 23, 2006 6:08 PM > Isn't that what my question is asking? Do any > implementations make an effort to guarantee independence? > Or do they just rely on choosing default > representations that they presume will provide it? Well I would not trust this presumption. I don't know what goes on in the back end here, but would not be completely surprised to find out that we *did* have some independence bugs in some strange cases, which would need fixing (but would not be hard to fix). > Combining is not really a problem for independence. > For independence the key is that you don't store > more bits than you need to. Loading more is OK. > (This is not about atomicness, which is a separate > discussion.) Right, and the combiner is clever enough to know that it can store more bits if it loads them first. After all it has to do this kind of thing all the time. Actually it is quite interesting to worry about whether there are independence bugs in the back end, there might be! > I suspect that most implementations where the > back end and front end are supported by separate > organizations, that there is an implicit understanding > that overlong stores won't be used unless there is > no choice. I don't think there is any such implicit understanding in gcc, not that I know of anyway. > I don't think it is combinations. It is overlong > stores. And a troublesome overlong store is one > that also requires a load and a mask. But lots of sequences require load-more-than-you-need mask, store-more-than-you-need. This is after all the routine code for dealing with packed bit arrays. > > In any case, the real question is whether GNAT is doing > something special to guarantee independence > for the default representation? I don't know, and the actual question might be whether GNAT needs to do something special with the GCC 4 optimizer (which we have not fully integrated yet, but which already caused us trouble -- e.g. it was helpfully eliminating 'Valid tests because it assumed that things were valid :-)) So I think the likely scenario is that as the optimizer improves, we find we *do* need to do more to guarantee independence even if we don't now. That's easy enough to do (providing we don't have to evaluate the is-confirming predicate, which I discussed the other day, and our back end folks agreed that this would be really difficult to do). **************************************************************** From: Robert Dewar Sent: Thursday, February 23, 2006 7:10 PM I think this thread does show that the proper solution for independence would indeed be a pragma (though as I said before, I think you want the default to be no independence, and a pragma that guarantees independence -- of course pragma Atomic_Comonents is often enough to achieve what you want). **************************************************************** From: Pascal Leroy Sent: Friday, February 24, 2006 1:39 AM I agree. The fact that specifying the representation affects independence, and does so in a non-portable way, is poor language design. Incidentally, this discussion has convinced me that confirming representation clauses are not the essence of the problem: if I specify a component size of 64 bits for an array of characters, chances are that this won't be confirming and chances are that it won't affect independence (YMMV). Why don't we provide a way for the user to clearly express her intent? Representation items specify the representation, period. If an algorithm depends on independence (or doesn't depend on independence -- what the default should be is a different discussion) it should state it explicitly, irrespective of representation items. This would make the code much more readable, because you would not have to interpret the *absence* of a representation item as implying independence. And it would also improve safety and portability, because a combination of representation items and independence requirements that could not be satisfied would be rejected, instead of silently becoming erroneous. **************************************************************** From: Robert Dewar Sent: Friday, February 24, 2006 5:22 AM > Why don't we provide a way for the user to clearly express her intent? > Representation items specify the representation, period. If an algorithm > depends on independence (or doesn't depend on independence -- what the > default should be is a different discussion) it should state it > explicitly, irrespective of representation items. I strongly agree with this, although it is formally an incompatible change. So here is a form in which it is compatible: pragma Independent_Components (type_local_NAME); This pragma specifies that independence must be guaranteed for the given type, even if a representation clause is present. The compiler must reject the pragma if it is not possible to guarantee independence for the type given the representation clauses present. If no representation clauses are present, then the default representation that is chosen must be such that the compiler can guarantee independence by default. For such types, the use of pragma Independent_Components has no effect (but may still be useful as clear documentation that separate tasks may access separate components in an asynchronous manner. > > This would make the code much more readable, because you would not have to > interpret the *absence* of a representation item as implying independence. > And it would also improve safety and portability, because a combination of > representation items and independence requirements that could not be > satisfied would be rejected, instead of silently becoming erroneous. Right, a better formulation would be to require the pragma even if there are no rep clauses present, but that's a significantly incompatible change. Of course compilers could simply refrain from taking advantage of this incompatibility if they were concerned about compatibility issues, but still, from a formal point of view, it would be a an incompatible change, and therefore contentious. The change, even in the compatible form I give here, solves the issue of conforming rep clauses, because the rule would simply be that a set of conforming rep clauses must include the independence pragma (of course you could leave it out if you were not interested in separate task access). **************************************************************** From: Bibb Latting Sent: Monday, November 6, 2006 5:21 PM While working on this AI, I had the following questions regarding both the text of the AI and what should or shouldn't be included: 9.10 (1) How about removing implementation defined from this paragraph. Something along the lines of: "However, representation items such as packing and record layout may prevent a subcomponent of an object from being independently addressable." 9.10 (16 and 17) Should the implementation advice attempt to include update of any implementation data such as array doping or other hidden data? Should some documentation recommendation be added that identifies those elementary values, if any, that are not suitable for use with multiple tasks? Dependently Addressable Objects Should an implementation permission be given to allow generation of an instruction sequence which might break inter-task synchronization when an object is not independently addressable? High Integrity Are there any appropriate restrictions applicable for "pragma Independent_Components". Specifically, should D.7, Tasking Restrictions; D.13.1, The "Ravenscar" profile, and H.4 High Integrity Restrictions contain a restriction to prevent the use of "Independent_Components"? Privacy Using independent addressing as the default synchronization method causes a dreadful headache when considering privacy. Might the introduction of a "Pragma Independent" as some sort of recursive application of pragma Independent_Components partially mitigate this problem? Initialized Discriminates The behavior of assignment to initialized discriminates is problematic here; should initialized discriminates be explicitly excluded from those objects which are independently addressable? Should an initialized discriminate be cause to reject a pragma Independent_Components? Independent Addressability Should pragma Independent_Components cause rejection of elementary components which are independently addressable, but can not be updated using an indivisible operation? Should a pragma be provided to assure thread-safe elementary object representation and instruction selection (as opposed to the flexibility associated with independent addressability)? Memory Segment Allocation What relevance, if any, does segment allocation have with regards to inter-task data sharing (a segment can be "local" or "shared" on some architectures), particularly on multi-processor systems? Is there a default that needs to be addressed? Notes 13.1 (21.1) was selected for implementation advice for confirming representations to avoid implementation advice for each item (e.g. 13.1 (21.1) recommends a confirming representation for pragma pack, which is considered to be non-confirming). 9.10 was discarded as an appropriate location because of the unnecessary forward reference to a confirming representation. **************************************************************** From: Randy Brukardt Sent: Tuesday, November 7, 2006 6:59 PM > While working on this AI, I had the following questions regarding > both the text of the AI and what should or shouldn't be included: > > 9.10 (1) > > How about removing implementation defined from this paragraph. > Something along the lines of: > > "However, representation items such as packing and record layout may > prevent a subcomponent of an object from being independently > addressable." Why? "implementation-defined" means it is supposed to be documented somehow. That means users have a way to find out what happens. Granted, using the new pragma it probably better than depending on implementation-defined behavior. But I think we want to make as little change here as possible (we don't want to break existing programs). > 9.10 (16 and 17) > > Should the implementation advice attempt to include update of any > implementation data such as array doping or other hidden data? I don't know how you could do that. Objects are independent unless the language says that they don't have to be, so any hidden stuff also has to be independent. And we almost never talk about implementation artifacts: the implementation is supposed to handle those correctly. If the objects aren't independent, then any dope wouldn't need to be, either. > Should some documentation recommendation be added that identifies > those elementary values, if any, that are not suitable for use with > multiple tasks? Robert Dewar will say that documentation requirements are junk. Besides, your question doesn't make sense. Independent addressability merely says that two tasks can access *different* objects (inc. components) without interference. That surely must be possible for all types in the absence of representation items. (Just put one Boolean per byte, for instance.) We expect compilers to get this right. > Dependently Addressable Objects > > Should an implementation permission be given to allow generation of > an instruction sequence which might break inter-task synchronization > when an object is not independently addressable? We always have to talk in terms of two objects when we're talking about independently addressable. It seems like you might be confusing independent addressibility with Atomic. The language seems clear that if two objects are not independently addressible, then the tasks might need some explicit synchronization to access them. I don't see that anything about this has anything to do with "instruction sequences" (that's Atomic). If I'm wrong, perhaps an example of the problem would help. > High Integrity > > Are there any appropriate restrictions applicable for "pragma > Independent_Components". Specifically, should D.7, Tasking > Restrictions; D.13.1, The "Ravenscar" profile, and H.4 High Integrity > Restrictions contain a restriction to prevent the use of > "Independent_Components"? Huh again? Why would you *not* want Independent_Components, as it prevents dependencies not shown in the source code. It might be nice to have a restriction to flag things that are *not* independently addressable -- but that surely was an issue in Ada 95, and it wasn't considered important enough to bother with. > Privacy > > Using independent addressing as the default synchronization method > causes a dreadful headache when considering privacy. Might the > introduction of a "Pragma Independent" as some sort of recursive > application of pragma Independent_Components partially mitigate this > problem? Huh again? Independent addressibility is *not* a synchronization method!! That's Atomic (see C.6). It merely says that things will work as expected, when two tasks access *different* objects. When an objects/components are not independently addressable, then there can be interference between them even if they are semantically separate. For instance, if we have: type Rec is record B1, B2 : Boolean; end record; pragma Independent_Components (Rec); Obj : Rec; then if task T1 accesses Obj.B1, and task T2 accesses Obj.B2, no synchronization is needed. OTOH, if we replaced Independent_Components by Pack, then there is no guarantee that T1 and T2 can access the two components of Obj without trouble. (This is more interesting with arrays, but I'm giving the example as a record because it is easier to write and understand.) > Initialized Discriminates > > The behavior of assignment to initialized discriminates is > problematic here; should initialized discriminates be explicitly > excluded from those objects which are independently addressable? > > Should an initialized discriminate be cause to reject a pragma > Independent_Components? I don't see any reason that initialized discriminants have any bearing on this at all. Please explain with an example. > Independent Addressability > > Should pragma Independent_Components cause rejection of elementary > components which are independently addressable, but can not be > updated using an indivisible operation? Indivisible operations are those for Atomic. You're thinking of Atomic_Components again. The only reason I can think of for rejecting Independent_Components is if another rep. clause requires a mask-and-store implementation: type Arr is (1..8) of Boolean; for Arr'Component_Size use 1; pragma Independent_Components (Arr); -- Reject this. But if the components are large and require multiple instructions, that's not a problem so long as the memory cells in question are separate from any other objects cells. > Should a pragma be provided to assure thread-safe elementary object > representation and instruction selection (as opposed to the > flexibility associated with independent addressability)? That sounds like pragma Atomic and Atomic_Components. Or did you have something else in mind? > Memory Segment Allocation > > What relevance, if any, does segment allocation have with regards to > inter-task data sharing (a segment can be "local" or "shared" on > some architectures), particularly on multi-processor systems? Is > there a default that needs to be addressed? That level of detail is usually left up to the implementer. Atomic is an exception, but we're not talking about that here. > Notes > > 13.1 (21.1) was selected for implementation advice for confirming > representations to avoid implementation advice for each item > (e.g. 13.1 (21.1) recommends a confirming representation for pragma > pack, which is considered to be non-confirming). 9.10 was discarded > as an appropriate location because of the unnecessary forward > reference to a confirming representation. I'm not sure what this means. There shouldn't need to be any new advice about confirming representations. The bug in 9.10 was that confirming rep. clauses had a semantic effect, we don't want that ever to be true. For all representation items, a confirming clause should be supported (if such a thing can be written -- which isn't necessarily possible, because we don't have a pragma Unpack to specify the absence of pragma Pack, for one example). There is no exception to this rule! We're surely not going to distribute some goofy rules about independent addressibility all over the standard. **************************************************************** From: Robert Dewar Sent: Sunday, May 20, 2007 10:01 PM > Modify to identify only non-confirming representations as those > that can cause dependent addressability. Modify to include > convention as an item that can cause an object to be dependent > (exclude convention Ada) for a representation. Change dependent > addressability from implementation defined to unspecified. I don't think this is tenable. What on earth is the semantic definition of a confirming representation clause. After all there is nothing in the standard that prevents a compiler from basing the representation of an item on the phases of the moon, or the MD-5 checksum of the program (the latter ensuring that the would-be default representation is changed by adding "confirming rep clauses". Also it may simply not be possible from a formal point of view to specify a confirming rep clause, e.g. suppose that an array is by default stored in some sparse hash table form, and only has a meaningful component size if one is specified, or if the component size is queried. etc etc. At most this could be implementation advice I do not see why convention should possibly affect independence > > AARM 13.1 (8.v, 8.w; 8.gg, 8.hh) > > Add independent and independent components, respectively. > > C.6 > > Add pragmas Independent and Independent_Components. Independent > applies to components of record types; Independent_Components > applies to components of arrays or anonymous array objects. The pragmas make good sense indeed. And with the pragmas the whole business of trying to specify what is meant by a confirming rep clause disappears. **************************************************************** From: Randy Brukardt Sent: Monday, May 21, 2006 12:25 AM ... > What on earth is the semantic > definition of a confirming representation clause. It's in 13.1(18.2/2): A representation item that specifies an aspect of representation that would have been chosen in the absence of the representation item is said to be confirming. The recommended level of support 13.1(21.1/2) is that confirming items (if they can be written, see below) always be supported. Next question. ;-) > After all > there is nothing in the standard that prevents a compiler > from basing the representation of an item on the phases > of the moon, or the MD-5 checksum of the program (the latter > ensuring that the would-be default representation is changed > by adding "confirming rep clauses". Also it may simply not > be possible from a formal point of view to specify a confirming > rep clause, e.g. suppose that an array is by default stored > in some sparse hash table form, and only has a meaningful > component size if one is specified, or if the component size > is queried. etc etc. Recommended level of support is always implementation advice. In any case, we had this discussion right here on the ARG list back in February of 2006. Then, you said: > Indeed. I actually think that there should be a rule that the > compiled accept all confirming representation clauses, which > is not necessarily the case. To which it was pointed out that there indeed is such a rule in Ada 2005. Note that further discussion (and an AARM note) points out that it might not be possible to write a confirming rep. clause; the rule is intended to be read such that if you *can* write such a clause, then it must be accepted. It's also intended that a confirming representation item never have a semantic effect. We changed all of the chapter 13 rules to make that true; we missed this one on chapter 9. Since the "representation choosen by implementation by default" has to be independent anyway, this change can't have any semantic effect on a correct compiler. It just means that if you confirm a component size (for one example), you don't lose independence as a side-effect. Remember that independent components is the default; you don't need advice that the default remains true! The pragmas are needed so that you can force independence even when giving non-confirming representation items like Pack. (And if independence can't be maintained, then the program is illegal.) ... > I do not see why convention should possibly affect independence Pascal brought that up. He suggested that "I don't understand why 9.10(1) doesn't mention pragma Convention. Consider an array of 4 characters. On an old Alpha, as you explained, it would have to be laid out with components occupying 32 bits. But if you put a pragma Convention (C) on the array, I would expect the components to use 8 bits. (I see that the C standard doesn't specify the size of char, but I am pretty sure that most of the C code out there assumes that it's 8 bits.)". Bibb is just trying to write the AI as the ARG agreed at the last meeting. Hope this helps. **************************************************************** From: Robert Dewar Sent: Tuesday, May 22, 2007 2:15 PM > Recommended level of support is always implementation advice. Not if Annex C is in effect > > In any case, we had this discussion right here on the ARG list back in > February of 2006. Then, you said: > >> Indeed. I actually think that there should be a rule that the >> compiled accept all confirming representation clauses, which >> is not necessarily the case. This is reasonable if there are no special semantics associated with this. > To which it was pointed out that there indeed is such a rule in Ada 2005. > > Note that further discussion (and an AARM note) points out that it might not > be possible to write a confirming rep. clause; the rule is intended to be > read such that if you *can* write such a clause, then it must be accepted. And that's fine > It's also intended that a confirming representation item never have a > semantic effect. We changed all of the chapter 13 rules to make that true; > we missed this one on chapter 9. Since the "representation choosen by > implementation by default" has to be independent anyway, this change can't > have any semantic effect on a correct compiler. It just means that if you > confirm a component size (for one example), you don't lose independence as a > side-effect. I find it awkward and confusing to have this rule. I think it better to rely on the new pragmas. After all we are changing the language right now. In Ada 2005, writing a confirming rep clause clearly does kill independence (even if this was not intended), so it has to be fixed, and the clean way of fixing it is with the pragmas in any case. It is a good thing to emphasize independence as a property rather than relying on the default behavior. It's a pity that we don't have a way of turning off independence by default. Probably implementations should add a configuration pragma that has this effect, relying on the new pragmas to add it back where needed (this would avoid having to unpack things just in case independence was required). Remember that in Ada 83, we just did not think this out properly at all (this was the huge change at the last minute in the printers proof that dealt with independence at all). The pragmas are a MUCH cleaner solution > Pascal brought that up. He suggested that "I don't understand why 9.10(1) > doesn't mention pragma Convention. Consider an array of 4 characters. On > an old Alpha, as you explained, it would have to be laid out with components > occupying 32 bits. But if you put a pragma Convention (C) on the array, I > would expect the components to use 8 bits. (I see that the C standard > doesn't specify the size of char, but I am pretty sure that most of the C > code out there > assumes that it's 8 bits.)". OK, that makes sense > > Bibb is just trying to write the AI as the ARG agreed at the last meeting. Well it's no big deal in fact, none of this independence stuff is anything any implementor gives a thought to (it just falls out :-)) **************************************************************** From: Randy Brukardt Sent: Tuesday, May 22, 2007 3:02 PM > Well it's no big deal in fact, none of this independence stuff is > anything any implementor gives a thought to (it just falls out :-)) I agree. And it is not really testable (a test which tries to generate a independence failure might very well work for many other reasons even if the independence is wrong). So, after choosing default representations appropriately, pretty much this is something worth worrying about only if there is a bug report from a customer (for instance, if a code generator gets too aggressive combining instructions). **************************************************************** From: Randy Brukardt Sent: Thursday, February 28, 2008 12:28 AM I've completed an update of AI05-0009-1 [this is version /04 of the AI - ED] based on the ARG discussion from the Paris meeting (the last time this AI was discussed). I'm still a bit uncertain if I have the wording right and all of the cases covered. You can find my concerns by reading the "Editor's notes" in the AI. Comments and suggestions are welcome. **************************************************************** From: Tucker Taft Sent: Monday, March 10, 2008 10:49 PM I agree that the wording is problematic. Suppose we change 9.10 to say roughly the following: If two different objects, including nonoverlapping parts of the same object, are independently addressable, they can be manipulated concurrently by two different tasks without synchronization. Any two nonoverlapping objects are independently addressable if either object is atomic, if a pragma Independent applies to either object (see C.6), or if either is a component of a composite object to which pragma Independent_Components applies (see C.6). Otherwise, two nonoverlapping objects are independently addressable except when they are both parts of a composite object for which a non-confirming representation item is used to specify packing, record layout, Component_Size, or convention, in which case it is unspecified whether the parts are independently addressable. Essentially, by putting the rule about atomic and pragma Independent* up front, and putting the rest in an "otherwise" clause, we give the right precedence. We could simplify the above by defining what it means for a "declaration of independence" to apply to an object... ;-) ;-), then we get: ... if either object is atomic, or if a declaration of independence applies to either object (see C.6). Otherwise, ... Wouldn't that be fun? Right up there with initialized alligators and pure streams. **************************************************************** From: Robert A. Duff Sent: Tuesday, March 11, 2008 11:12 AM > Wouldn't that be fun? :-) :-) **************************************************************** Editor's note, Tuesday, July 8, 2008 Although not previously noted, the lead-in paragraph (C.6(2)) to the syntax of the pragmas needs to be updated as well. **************************************************************** Editor's note, Wednesday, October 22, 2008 During editorial review of this AI, Pascal Leroy objected to the organization of the wording by this AI. Here is an edited summary of the discussion on that topic between Pascal Leroy, Ed Schonberg, and Randy Brukardt. Pascal: I find the overall structure of this AI quite strange: the syntax and legality of the new pragmas are defined in C.6, but the actual semantics are hidden in 9.10(1). Even worse, for atomicity, a bit of the semantics (the independence) is also hidden in 9.10(1). It would have been nicer to define the full semantics in C.6 (for instance by saying that the pragmas make the object "potentially independently addressable", or some other technical term) and use that term in 9.10. Ed: Note that 9.10 already has references to Annex C, in particular 9.10 (15), so maybe the pragmas should be mentioned first at the end of 9.10? Pascal: I actually think that it would be fine to have a forward reference similar to 9.10(15): "A pragma Independent may also be used to ensure that certain objects are independently addressible". But I have a problem with the fact that, as the AI stands today, the new text in C.6 doesn't say a word about the semantics of the pragma. To the reader of this annex, this is going to be entirely mysterious. Randy: The 9.10 text has a number of forward references to C.6. But the idea of putting the entire definition in C.6 would make a much more massive forward reference where no significant one exists today. Moreover, we originally had a proposal for a term like "independent addressable object", and it was removed during a meeting to simplify the presentation. To put it back is completely wrong. I think that all that is really needed is a user note to point to 9.10 for the semantics for pragma Independent. Pascal: It reads very weird in C.6: the Dynamic Semantics and Implementation Requirements section don't mention pragmas Independent... at all. That's plain wrong. The solution adopted for pragma Atomic (where the pragma is fully defined in C.6 with a forward reference in 9.10) seems much preferable. I don't care that this would add a forward reference, it just doesn't make sense to have a pragma defined in two places. Ed: I tend to agree, the pragmas should be treated in the same way. Randy: We now have a major problem, as I am the author of record on this AI, and I totally disagree with both of you on this one. This could very well kill the AI in my opinion, or worse make it completely impenetrable and full of bugs. (1) Pascal's original suggest of defining a term like "independent object" was tried in an earlier version of the AI, and it doesn't work. The problem is that independence is always between *two* objects; there is no such thing as a single object being independent. The only way that we could find that made sense was to eliminate the term. (2) The definition of independence in 9.10 is very intertwined with the meaning of the pragmas. I tried factoring them out or inverting the definition, and it simply does not work. Tucker suggested the current formulation, but it still took 5 or 6 tries to get it right. (3) Moving the definition of independence to Annex C makes no sense; this is a core definition that has no bearing on the pragmas. (4) I think the pragmas should be defined in 9.10 (they ought to be a core feature supported by all implementations), but I lost that battle previously. Someone thought that they were similar to the existing pragmas in C.6, but it turns out that they are not at all similar. However, I don't want to be reopening previous decisions in the absence of a clear error -- which we do not have here. As such, the only thing I could see doing here would be to add a redundant paragraph in C.6 under Static Semantics [Pragmas Independent and Independent_Components guarantee independent addressability for the named object or component, or in the case of a type, for objects of that type (see 9.10).] ****************************************************************