!standard 13.3(23/2) 08-01-17 AI05-0083-1/01 !standard 13.3(40) !class binding interpretation 08-01-17 !status work item 08-01-17 !status received 07-12-23 !priority Low !difficulty Hard !qualifier Clarification !subject Representation values of formal parameters !summary ** TBD ** !question Does 13.3(22/2) and 13.3(40/1) mean "view of an object" rather than just "object"? Generally, Section 13 text says "view" when it means it, and it usually does not mean it. For instance, 13.1(11/2) says that all views of a type have the same representation aspects. The distinction between "view of an object" and just "object" matters when the prefix of a representation attribute is a formal parameter. Consider: type Lim is limited record C : Character; end record; for Lim'Alignment use 2; Lim_Obj : Lim; for Lim_Obj'Alignment use 4; procedure Do_Something (Param : in out Lim) is begin Put (Integer'Image(Param'Alignment)); end Do_Something; Do_Something (Lim_Obj); -- What is output by this call? Lim'Alignment is 2. Lim_Obj'Alignment is 4. Both of these values are required by 13.1(17) ("then that aspect of the entity is as specified"). But what is the value of Param'Alignment? Param is passed by reference, so it is defined by 6.4.1(10) to denote a view conversion of the actual parameter (Lim_Obj in this case). If 13.3(22/2) means "object" (in the sense that every view has the same alignment), then the value of Param'Alignment must be 4 (because it was specified for the object), and this call must output "4". If 13.3(22/2) means "view of an object", then the value of Param'Alignment doesn't seem to be specified at all. It could be any value that is a factor of the object's alignment, and it could even be larger than the object's alignment if, for instance, the target aligns all objects to alignment 8. These are very different answers, and the actual answer has impacts on code generation. Similar questions apply to Size and other attributes that can be specified for objects. !recommendation (See Summary.) !wording ** TBD ** !discussion For alignment, both possible meanings seem bad. The meaning of "object" is bad because it requires the implementation to pass the alignment along with the formal parameter. (That wouldn't be necessary for a by-copy parameter, which is a new object, but that just makes things more confusing.) Moreover, it limits the reasoning that can be done about the alignment of the passed object. The second is bad because returning 0 or 1 for the alignment of all parameters would be a correct implementation. This means that a programmer couldn't assume anything about the alignment, even though the alignment is specified for the subtype of the parameter - there would be no way to control the alignment of a formal parameter. Moreover, the real alignment of the object is hidden. It would seem best if the alignment of a formal parameter was that of the subtype of the parameter. In that case, the parameter's alignment can be specified with a suitable subtype. But there doesn't seem to be any way to come up with that answer from the wording of the standard. Note that the answers for other attributes don't necessarily need to be the same. For instance, for Size of an unconstrained formal object, the Size of the actual is likely to be more useful than the Size of the formal type (which is likely to be a very large number). OTOH, it would be best if the result could be calculated from the array descriptor, rather than being required to be passed in. --!corrigendum 13.9(7) !ACATS Test ** TBD ** !appendix From: Robert A. Duff Sent: Sunday, December 23, 2007 6:58 PM Here's a possible bug in the RM regarding alignment, found by Robert Dewar. Suppose we have type X is tagged null record; procedure Munge (Arg : X); type Y is new X; for Y'Alignment use X'Alignment / 2; So perhaps X'Alignment = 4 and Y'Alignment = 2. Munge will assume its parameter is aligned to 4 bytes, but Munge on a Y object might pass a misaligned object. We don't see anything making this illegal, but it seems infeasible to implement properly. **************************************************************** From: Pascal Leroy Sent: Monday, December 24, 2007 2:47 AM > type X is tagged null record; > procedure Munge (Arg : X); > type Y is new X; > for Y'Alignment use X'Alignment / 2; How about 13.1(24/2): "An implementation need not support a nonconfirming representation item if it could cause an aliased object or an object of a by-reference type to be allocated at a nonaddressable location or, when the alignment attribute of the subtype of such an object is nonzero, at an address that is not an integral multiple of that alignment." It seems to me that the alignment_clause would cause some objects of type X (namely, those that are obtained by view-converting objects of type Y) to be allocated at an address that is not a multiple of the alignment of their subtype. Therefore, I believe that an implementation is allowed to reject the alignment_clause. It certainly was the intent of AI 291 to avoid this kind of pathology. **************************************************************** From: Robert Dewar Sent: Monday, December 24, 2007 4:47 AM To me, leaving this implementation defined is wrong, since there is no reasonable implementation model if you accept this alignment clause. The same is true for Size clauses if your implementation allows Size clauses to change the internal representation. e.g. type x is tagged record a,b,c,d,e,f,g,h : Boolean; end record; for X'Size use 72; procedure Munge (Arg : X); type xnew is new for xnew'Size use 40; I think it wrong for a compiler to be allowed to accept the above, where the size clause causes implicit packing. The whole business of Size and Alignment being subtype specific is dubious in this context. **************************************************************** From: Tucker Taft Sent: Monday, December 24, 2007 12:04 PM What about 13.3(32.1/2)? Doesn't this address this issue exactly: An implementation need not support an Alignment specified for a derived tagged type which is not a multiple of the Alignment of the parent type. An implementation need not support a nonconfirming Alignment specified for a derived untagged by-reference type. **************************************************************** From: Robert Dewar Sent: Monday, December 24, 2007 1:10 PM As per my note, I don't think IA is good enough here Making something legal for which we have no reasonnable implentation model, then saying that you can but do not have to reject it is bad language design policy in my view. **************************************************************** From: Robert A. Duff Sent: Monday, December 24, 2007 1:42 PM I agree, but this style is used throughout chapter 13. At this point, I'd say "not broken enough to fix". **************************************************************** From: Robert Dewar Sent: Monday, December 24, 2007 7:25 AM Is that really true, I don't see other examples like this, can you quote an example of what you mean by throughout. To me all the other limitations you are allowed are about things that might be implementable on some architectures but not on others. Alignment is a bit of an orphan anyway, for instance we remembered to say: > 53 A Size clause on a composite subtype should not affect the internal > layout of components. But we forgot to say the same for alignment, and of course it is just as important. By the way, I just noticed the following note: > 37 (4) The Alignment of a composite object is always equal to the least > common multiple of the Alignments of its components, or a multiple > thereof. rubbish of course: [For the record, this note was deleted by the Amendment; it's not present in the current Ada standard - ED.] type x is record a,b,c : integer; end record; for x'alignment use 1; though come to think of it, what on earth does the alignment of a component mean? I took it to mean the alignment of the type of the component? Could it mean something else. **************************************************************** From: Tucker Taft Sent: Monday, December 24, 2007 6:36 PM This is implementation device under the special heading of "recommended level of support" so most implementors treat is as gospel, since they all support the systems-programming annex. In general, we allow implementations to accept almost any representation item if they really want to, but most follow the "recommended level of support" very closely, and certainly users who go beyond that are clearly venturing into implementation-dependent territory. **************************************************************** From: Randy Brukardt Sent: Wednesday, December 26, 2007 8:42 PM > To me, leaving this implementation defined is wrong, since there is > no reasonable implementation model if you accept this alignment > clause. I strongly disagree with this statement: it makes perfect sense to accept this alignment clause in some implementation models on some targets. For instance, Janus/Ada on the x86 does not use any instructions whose correctness depend on the alignment of an object. For this, procedure Munge will work with an object of any (non-zero) alignment. In such a case, there might be a performance difference, but generally it is a mistake for the compiler to second-guess what the customer wants. At most it would make sense to issue a warning on the alignment clause: "This alignment may lead to reduced performance in inherited subprograms." Of course, such an alignment clause isn't portable, and I have no problem imagining architectures where implementing it would be difficult or impossible. Such architectures have a number of reasons that they can use to reject the alignment clause (such as the rules noted by others). It might be useful for Janus/Ada to note that with another warning: "This alignment clause may not be supported on other Ada compilers." -- but again that is no reason to disallow it. There doesn't seem to be any good reason to disallow representation clauses that may work on some implementations (these clauses are already target-dependent, so portability is not a major issue beyond ensuring a basic level of support). The most important thing is to ensure that implementations aren't *required* to do the impossible, and that is already done. As such, not only don't I think that a rule change is needed, but I think that any such change would be actively harmful. **************************************************************** From: Robert Dewar Sent: Wednesday, December 26, 2007 9:01 PM > For instance, Janus/Ada on the x86 does not use any instructions whose > correctness depend on the alignment of an object. For this, procedure Munge > will work with an object of any (non-zero) alignment. In such a case, there > might be a performance difference, but generally it is a mistake for the > compiler to second-guess what the customer wants. At most it would make > sense to issue a warning on the alignment clause: "This alignment may lead > to reduced performance in inherited subprograms." It will work, but the resulting program is erroneous, because you have an object which does not match the alignment of the type. That's a clear error to me. > Of course, such an alignment clause isn't portable, and I have no problem > imagining architectures where implementing it would be difficult or > impossible. Such architectures have a number of reasons that they can use to > reject the alignment clause (such as the rules noted by others). It might be > useful for Janus/Ada to note that with another warning: "This alignment > clause may not be supported on other Ada compilers." -- but again that is no > reason to disallow it. > > There doesn't seem to be any good reason to disallow representation clauses > that may work on some implementations (these clauses are already > target-dependent, so portability is not a major issue beyond ensuring a > basic level of support). The most important thing is to ensure that > implementations aren't *required* to do the impossible, and that is already > done. "may work" is fine, but "happen to work even if the program is erroneous" is quite another matter > As such, not only don't I think that a rule change is needed, but I think > that any such change would be actively harmful. I do not think it is harmful to stop programmers writing programs that are erroneous. Anyway, no big deal, if people want to write erroneous Janus programs that's OK with me, but I think in fact that all compilers should prevent this if they do not have an implementation model that guarantees that objects have the alignment specified by their types. Basically Janus is simply not following the alignment specified for the parent type in this situation, it may get away with this non-conformance, but for example, an ACATS test that verified that the alignment was correct in this case is not only a valid test, but perhaps even a desirable one if there are implementations trying to get away with not obeying alignment clauses in this situation. **************************************************************** From: Robert Dewar Sent: Wednesday, December 26, 2007 9:11 PM To say a little more about Randy and the Janus approach here, since there is a general principle involved. It is fine to have compilers that accept rep clauses that other compilers reject PROVIDING that they respect these rep clauses. In the situation type R is ... some by-reference type ... for R'Alignment use 4; that should mean, if accepted that all objects of this type are aligned on a boundary of 4. If your implementation cannot guarantee this, it must reject this clause. Now if we accept type R1 is new R; for R1'Alignment use 2; And the implementation mechanism is to call routines defined for R passing objects of type R with an alignment of 2 and not 4, then to me that's plain wrong, since it is violating the rep clause on R. It's fine to accept both clauses ONLY if you can obey both, and I still see no implementation model that can achieve this, Randy's report of a non-conforming model that happens to work most of the time is not a counter-example. For example, if I am in the routine involved, I am quite entitled to assume that Arg'Address is a multiple of 4, and base some assumptions on this. If that's not true, then the compiler is wrong. I said in my previous code that the code is erroneous, that's not really right, the code is fine, what is wrong is for any compiler to accept it! **************************************************************** From: Randy Brukardt Sent: Wednesday, December 26, 2007 10:40 PM > It will work, but the resulting program is erroneous, because you have > an object which does not match the alignment of the type. That's a clear > error to me. To be pendantic, I don't think you mean "erroneous", because what the program does is well-defined. It surely isn't going to "format the hard disk", as erroneous programs can do. We don't have a formal word for this sort of issue and you need to avoid using a formally defined term else your meaning be mis-interpreted. End pendantic. More below. > "may work" is fine, but "happen to work even if the program is > erroneous" is quite another matter The program is not "erroneous". Whether it is even wrong is not clear to me: does the alignment of a formal parameter reflect that of the actual, or is it just a nominal alignment? In the former case, you'd have to pass the alignment value with all objects -- which seems to be a silly thing to do. Or you've have to ban all non-confirming alignment clauses on derived types that *could* be passed by reference. To do that latter in the language would require banning all non-confirming alignment clauses on derived composite types. And you'd have to do the same for size clauses. That seems pretty draconian to me. > > As such, not only don't I think that a rule change is needed, but I think > > that any such change would be actively harmful. > > I do not think it is harmful to stop programmers writing programs > that are erroneous. "Wrong", perhaps, but not erroneous. > Anyway, no big deal, if people want to write erroneous Janus programs > that's OK with me, but I think in fact that all compilers should prevent > this if they do not have an implementation model that guarantees that > objects have the alignment specified by their types. Basically Janus > is simply not following the alignment specified for the parent type > in this situation, it may get away with this non-conformance, but > for example, an ACATS test that verified that the alignment was > correct in this case is not only a valid test, but perhaps even a > desirable one if there are implementations trying to get away with > not obeying alignment clauses in this situation. My view has always been that the only place that size and alignment really matter is on the declaration of [original] objects (and components). It's surely important for atomic and volatile objects; it's less important for "regular" objects, and it is not important at all for non-original views of "original" objects. For a formal parameter, you can't write non-pathological Ada code that depends on the alignment (assuming an implementation model where there aren't any alignment-specific instructions used): the only such code that you can write is to test the 'Address value, and that is not a useful thing to do. So I don't see any reason for a routine to *assume* the alignment value of its formal parameter. Indeed, anything else would be too expensive inside of a code-shared generic -- Janus/Ada only ensures that the size and alignment match for "original" objects, and not for views of such objects. (We used to go even further in generics, but we had to change it in order to support aliased objects inside of generics to be accessed by types outside of the generic.) Perhaps I'm just seriously confused (not unlikely in the case of 'Size and 'Alignment - most of what I read about them appear to be nonsense). In any case, we discussed whether to try to craft rules to make the impossible-to-implement cases illegal when we were discussing the issues with limited by-reference types, and I'm pretty sure we decided that crafting such rules would be very hard since either they'd have to be very incomplete or they would go too far (as the one I suggested above). If they are left incomplete, then we'd need both the existing permissions and the extra rules making some cases illegal, which seems like saying the same thing twice (and in different ways) -- which has proven to be a maintenance hazard in the past. So the decision was made to let implementers "do the right thing". It is apparent that it is not clear (to at least this implementer) what the "right thing" is, so perhaps there would be some benefit to revisiting that, but I don't think that there is likely to be any interest in making more things illegal. **************************************************************** From: Robert Dewar Sent: Wednesday, December 26, 2007 10:56 PM > My view has always been that the only place that size and alignment really > matter is on the declaration of [original] objects (and components). It's > surely important for atomic and volatile objects; it's less important for > "regular" objects, and it is not important at all for non-original views of > "original" objects. Well that might be your view, but that is not what the RM says, it says > 26.3/2 For an object X of subtype S, if S'Alignment is not zero, then > X'Alignment is a nonzero integral multiple of S'Alignment unless > specified otherwise by a representation item. it makes no distinction between regular and original objects whatever the heck that means, it just says that all objects have this alignment, The subprogram parameter is an object, it clearly is covered by this rule. I don't know how you conclude otherwise. > For a formal parameter, you can't write non-pathological Ada code that > depends on the alignment (assuming an implementation model where there > aren't any alignment-specific instructions used): the only such code that > you can write is to test the 'Address value, and that is not a useful thing > to do. I see, so now we are down to saying that it's OK to be non-conforming because Randy declares that the non-conformance is a pathology :-) Here is non-pathological use of 'Address, you take addresses of things that you know are aligned to 4 bytes, convert them to Integer'Address values, then use the low two bits for storing bits of some kind. Odd code, and probably too clever, but certainly valid, and by no stretch of the imagination invalid. These addresses might for example be used in some kind of caching scheme to recognize parameters that were previously passed. **************************************************************** From: Randy Brukardt Sent: Wednesday, December 26, 2007 11:42 PM > Well that might be your view, but that is not what the RM says, it says > > > 26.3/2 For an object X of subtype S, if S'Alignment is not zero, then > > X'Alignment is a nonzero integral multiple of S'Alignment unless > > specified otherwise by a representation item. > > it makes no distinction between regular and original objects whatever > the heck that means, it just says that all objects have this alignment, > The subprogram parameter is an object, it clearly is covered by this > rule. I don't know how you conclude otherwise. This wording says "object" rather than "view of an object". A pass-by-reference formal parameter is a "view of an object" - it's not really an object itself. (The wording of the Standard seems confused on this point, but it hardly can be otherwise.) That means that the value of Arg'Alignment has to be that of the actual. Consider an inversion of your original example: type X is tagged null record; procedure Munge (Arg : X); type Y is new X; for Y'Alignment use X'Alignment * 2 This seems useful, but (in the absence of expensive passing of the alignment), Arg will have the wrong alignment inside of Munge. The "error" will be harmless (any value passed will have at least the proper alignment), but it still is wrong. Following your suggestion for a language legality rule, you'd need a rule similar to 13.1(10): "For a composite derived type, no subtype-related representation items are allowed if the parent type has any user-defined primitive subprograms." But that seems like too much a limitation to me. Now, you can argue that the original wording means "view of an object". But if you do that, then you could have different values for different views of an object (such as a partial and full view) -- and that violates 13.1(11/2). And surely the formal parameter passed by-reference is a view of the actual object (6.4.1(10) says that the formal denotes a view conversion of the actual) - and thus the formal and actual have to have the same alignment by 13.1(11/2). So this line of argument leads nowhere. It does seem that something is wrong somewhere with the wording for Size and Alignment, but it surely isn't clear to me what it is. > > For a formal parameter, you can't write non-pathological Ada code that > > depends on the alignment (assuming an implementation model where there > > aren't any alignment-specific instructions used): the only such code that > > you can write is to test the 'Address value, and that is not a useful thing > > to do. > > I see, so now we are down to saying that it's OK to be non-conforming > because Randy declares that the non-conformance is a pathology :-) I don't think arguing from pathology is very strong (there is reasonable disagreement on what is a pathology and what is just clever code), but I don't think it is worth deciding rules that can't matter in actual practice. We'd got more interesting things to do. > Here is non-pathological use of 'Address, you take addresses of things > that you know are aligned to 4 bytes, convert them to Integer'Address > values, then use the low two bits for storing bits of some kind. Odd > code, and probably too clever, but certainly valid, and by no stretch > of the imagination invalid. > > These addresses might for example be used in some kind of caching > scheme to recognize parameters that were previously passed. Well, I don't find this example too convincing -- it's too tricky by half. My rule of thumb for deciding on whether something is a pathology is whether I could convince a customer that it wasn't legitimate should the need arise. But I realize your mileage may vary, and I'll be happy to agree to disagree on this point. It isn't critical anyway -- the real question is whether you think Size and Alignment should be specifiable at all on derived composite types. **************************************************************** From: Robert Dewar Sent: Wednesday, December 26, 2007 9:01 PM > That means that the value of Arg'Alignment has to be that of the actual. > Consider an inversion of your original example: > > type X is tagged null record; > procedure Munge (Arg : X); > type Y is new X; > for Y'Alignment use X'Alignment * 2 > > This seems useful, but (in the absence of expensive passing of the > alignment), Arg will have the wrong alignment inside of Munge. The "error" > will be harmless (any value passed will have at least the proper alignment), > but it still is wrong. No, it's not wrong, any object of type Y has an alignment of X'Alignment. That's how alignments work! > Well, I don't find this example too convincing -- it's too tricky by half. > My rule of thumb for deciding on whether something is a pathology is whether > I could convince a customer that it wasn't legitimate should the need arise. tricky /= pathological. I have seen this technique of using the unset bits of aligned pointers for flags used many times, e.g. in the heap manager for the old Alsys x86 compiler. > But I realize your mileage may vary, and I'll be happy to agree to disagree > on this point. It isn't critical anyway -- the real question is whether you > think Size and Alignment should be specifiable at all on derived composite > types. Well the business of changing internal layout is separate of course. As to whether you should allow size and alignment to be specified for derived composite types, yes, of course you want that. In particular, it is routine for the alignment of a derived type to be larger than that of the base type, as in: type X is tagged record Y : Integer; end record; for X'Alignment use 4; -- confirming rep clause type X1 is X with record Z : Long_Float; end record; for X1'Alignment use 8; -- confirming rep clause Just as the size can get bigger with no ill effects, the alignment can get bigger with no ill effects, since you can't convert an X to an X1, and when you convert an X1 to an X, the view has the right size and alignment. It's never a problem if the alignment is too big. An alignment of 4 means the lower bits are xxxxxx00, it does not mean they are xxxxx100! The issue is can you specify a smaller size or alignment for a derived type, well the answer for size is obviously not I would say, though we would get a similar situation with type X is tagged record Y : Integer; end record; for X'Size use 1600; -- lots of space to spare type X1 is X with record Z : Long_Float; end record; for X1'Size use 1200; -- not so much space to spare And I think the situation is the same with an alignment. Here is something that I think should be perfectly fine in any subprogram: type Arg is .. some by ref type .. for Arg'Alignment use 4; procedure X (A : Arg) is -- Arg has alignment of 4 R : Integer; for R'Address use A'Address; Now according to your formulation, the integer could end up with a wrong alignment, which seems clearly wrong to me. R is a regular (or whatever adjective you came up with) object here, and it is explicitly erroneous to specify an address for an object that is not sufficiently aligned. Are you really saying you think this last example is potentially erroneous becuase a view can be underaligned? That sounds very wrong to me. I really don't think alignments have been thought through carefully enough. You have a rather casual view, because you are on a machine where most (not all) hardware types work OK (though with huge time penalties) if they are unaligned, but most architectures are not like that. **************************************************************** From: Randy Brukardt Sent: Thursday, December 27, 2007 5:35 PM > > This seems useful, but (in the absence of expensive passing of the > > alignment), Arg will have the wrong alignment inside of Munge. The "error" > > will be harmless (any value passed will have at least the proper alignment), > > but it still is wrong. > > No, it's not wrong, any object of type Y has an alignment of > X'Alignment. That's how alignments work! I fear you've missed my point. I'm explaining how the wording in the Standard defines alignments. That isn't making any value judgment on whether that is good or bad, and surely isn't describing how I think alignments should work. Don't shoot the messenger! For the record, I think I agree with you that something is wrong here. But that doesn't change what the standard says. ... > > ... It isn't critical anyway -- the real question is whether you > > think Size and Alignment should be specifiable at all on > > derived composite types. > > Well the business of changing internal layout is separate of course. As > to whether you should allow size and alignment to be specified for > derived composite types, yes, of course you want that. Good. Then I think we agree on the basic point that we shouldn't disallow anything that is possibly useful. ... > The issue is can you specify a smaller size or alignment for > a derived type, well the answer for size is obviously not I > would say, though we would get a similar situation with > > type X is tagged record > Y : Integer; > end record; > for X'Size use 1600; -- lots of space to spare > > type X1 is X with record > Z : Long_Float; > end record; > for X1'Size use 1200; -- not so much space to spare > > And I think the situation is the same with an alignment. I think that the ARG intended for implementers to "do the right thing" here. But as our discussion has pointed out, it isn't necessarily obvious what the right thing is. At the very least, the AARM should be more explicit. > Here is something that I think should be perfectly fine in > any subprogram: > > type Arg is .. some by ref type .. > for Arg'Alignment use 4; > > procedure X (A : Arg) is -- Arg has alignment of 4 > R : Integer; > for R'Address use A'Address; > > Now according to your formulation, the integer could end up > with a wrong alignment, which seems clearly wrong to me. R > is a regular (or whatever adjective you came up with) object > here, and it is explicitly erroneous to specify an address for > an object that is not sufficiently aligned. > > Are you really saying you think this last example is > potentially erroneous because a view can be underaligned? > That sounds very wrong to me. Well, in our compiler, Integer (and all predefined types) have an alignment of 1, so there is no problem. Only alignments that are explicitly specified have a non-zero value. (There is a second layer of "guideline" alignments that are enforced only when convenient, which is used to try to align things like integer objects. That mess came about because we took Ada 95's 13.3(26) seriously, and do not allow any representation items to specify (explicitly or implicitly) a smaller alignment. That rule has been deleted and generally was decided to be wrong, so I could try to simplify our implementation, but that would be extra work for something that isn't broken.) In any case, all uses of 'Address are potentially erroneous (by 13.3(13)) and not portable. This particular example surely isn't portable, as A'Address might very well point at a tag or descriptor. So the only way to figure out whether an 'Address clause will work is to read your documentation or talk to your vendor. And not to expect it to work somewhere else. > I really don't think alignments have been thought through > carefully enough. You have a rather casual view, because > you are on a machine where most (not all) hardware types > work OK (though with huge time penalties) if they are > unaligned, but most architectures are not like that. I plead guilty to working on machines where alignment issues aren't critical. I'm dubious about the "huge time penalties" (on most code I've worked on, alignment hasn't made a noticeable difference, and testing has shown that code on which it matters is rare), but surely I've tried to make it possible to align things in those cases where it matters. But every target that I've worked on, it would *work* even though it wasn't optimal. That even included the U2200, which reminds me of a funny story tangentially related to this discussion. On the U2200, we targeted a Unisys-provided backend that took care of code generation and included support for unaligned objects (because it had originally been written for a bad C front-end that couldn't align anything). Quite a while after I finished the implementation of alignments in our front-end, the guy on our team responsible for machine-level debugging off-handedly remarked that it was hard to debug the code because everything was unaligned. This was a big surprise to me, since I'd spent more than a month ensuring that every place memory was allocated called the appropriate alignment code. After some code inspection, I found an off-by-one error in my alignment code: the effect was that every address ended with "11" rather than "00"! Oops! Fixing that eliminated that particular gripe, and presumably made the programs run faster. Moral: even when I've tried to do the right thing for alignment, I've gotten it wrong. But this isn't about me. It's about the wording of the Standard. And, in particular, whether different views of an object can have different representation values. And, if so, what are they? My interpretation has been that 'Size and 'Alignment work the same way, and that is backed up by the wording of their definitions. Moreover, I've always assumed that if 'Size or 'Alignment is specified for an object, that you *must* get that value if you query it. That means that neither 'Size nor 'Alignment can be known at compile-time for formal parameters passed by reference, because the attribute has to return the value (possibly specified) for the original object. (They're never static in such a case, so there is no legality depending on this; they can only be queried.) That makes sense for 'Size, since it can be valuable to know the actual size, and anything else is going to be returning gibberish: type Arr is array (Positive range <>) of Character; procedure Check (Arg : Arr; Sz : Natural); Obj4 : Arr(1..4); for Obj4 use 32; Obj8 : Arr(1..8); for Obj8 use 64; procedure Check (Arg : Arr; Sz : Natural) is begin if Arg'Size /= Sz then Put_Line ("** Not size of actual"); end if; end Check; Check(Obj4, Obj4'Size); Check(Obj8, Obj8'Size); On the other hand, doing this for 'Alignment violates Dewar's rule, because it essentially says that the alignment of a reference parameter is unknown. But the primary purpose of alignment is to allow the compiler to generate code only for aligned references, and clearly the alignment has to be known at compile-time for that to work. So I think I agree that there is something wrong here. But I think Robert has convinced me that I'm not the person to try to fix it. Hopefully someone else will take a crack at it. ****************************************************************