https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65892
--- Comment #59 from James Kuyper Jr. <jameskuyper at alumni dot caltech.edu> --- (In reply to Davin McCall from comment #56) > (In reply to James Kuyper Jr. from comment #55) > > The problem is, you're using a statement that the access must occur via a > > union, with the implication that the code in question does not access the > > member through the union. > > If "via a union" allows that at some point that the address of a union > member was taken and that pointer is then dereferenced, and type punning via > a union is allowed (as is implied by another footnote in the same section), > then: Footnote 95 is the only one I can find which allows type punning via a union - is that the one you're referring to? Footnote 95 makes absolutely no use of the word "via". It says, quite explicitly, "the member used to read the contents of a union", and therefore can't apply when not directly using an actual member to read it. What I said about allowing indirect access was specific to the special guarantee from 6.5.2.3p6, and was not in any way intended to imply that indirect type punning using a union is allowed when that guarantee doesn't apply. > 1) all type-based alias analysis is effectively impossible Alias analysis is only affected by the special guarantee if a) the types involved are both struct types b) both struct types are members of the same union c) the struct types share a common initial sequence d) the code in question inspects the value of one of the members of the common initial sequence. e) a completed declaration of the union type that they are members of is visible at the point in the code where the inspection occurrs. It seems to me that the overwhelming majority of cases will fail to meet at least one of those requirements, so type-based alias analysis is still possible, it's just made more complicated by the need to check for those things. > The real problem is that "it is permitted to inspect" doesn't say how one > should perform an "inspection" nor what the result should be. You want it to > mean "access (read) the structure member in the normal way and have its > value match that of the corresponding structure member from the common > initial sequence of the active member". But the "special guarantee" grants a > permission, which is most easily read as not doing anything other than > specifying that a certain action (reading a struct member) doesn't have > undefined behaviour in certain circumstances. Well, that's sufficiently vague that I can agree with it. It's the fact that, in other circumstance, the behavior is undefined, that allows optimizations that would fail if the pointers alias each other. Such optimizations are therefore not allowed in the circumstances where 6.5.3.2p6 applies. > It's not even actually explicated that the value read should match that of > the corresponding common-initial-sequence member of the struct object that > is the active member of the union object in question; in thinking that it > should be, we're already making the assumption that this clause is intended > to permit a certain case of type-punning. But, as I noted above, if > type-punning is generally allowed, Which is NOT what I claimed. > ... and if accessing via the union > "immediately" has the same semantics as taking the address of the union > member and accessing via the resulting pointer Which I only claimed to be true when the special guarantee applies. > ... - then the clause isn't > necessary anyway, Since I didn't make the general claims you're asserting that I made, the clause is necessary. > ... except to mandate that the common-initial-sequence layout > is identical between distinct structs which are punned in this way, and in > that case what is the point of requiring that the union declaration be > visible? It's a pre-condition for the indirect access to be valid, which would otherwise not be allowed. > ... (Unless you want to argue that the point is to mandate the common > initial sequence layout is necessarily identical only if the union > declaration is visible; No, I think the primary point is to disallow optimizations based upon the normal assumption that the two struct types can't alias each other. However, the standard does not otherwise constrain the layout of any member of a struct type other than the first, so in any context where 6.5.2.3p6 doesn't interfere, the common initial sequence is allowed to have different layouts in the different struct types. I can't imagine any good reason for an implementation to do so - I'd expect that for any given value of n, for any given implementation of C, the location within a struct of the nth member is determined uniquely by the types of the preceding members - but the standard doesn't require that to be the case. > So for your interpretation I believe you need that either: > > 1) type punning via a union is not normally permissible, despite the > footnote claiming it is, and It is permitted to use a union member to perform type-punning. Since the results (including whether or not a trap representation is involved) depend upon the implementation-defined representations of the two types that are being punned, such code is never fully portable, but not all code needs to be portable. > 2) a lot of production code is broken. No. > or > > 1) type punning via a union is permissible Yes > and the "special guarantee" > clause serves only to enforce common layout of structs, No, because it covers indirect type punning through the use of unions, and not just direct type punning. > ... and the union > declaration amendment is not sensible, No, because it's needed to restrict the circumstances where aliasing is permitted; without that restriction, type-based aliasing checks would be just as badly broken as you incorrectly claim they would be. > 2) TBAA is impossible and most current compilers are broken. > > or > > 1) type punning via a union is permissible, but the semantics of accessing a > member of the union "immediately" do differ to those of taking the address > of the member and later dereferencing it, despite the fact that the text > does not explicate this, and The test that allows union type punning does apply only to reading using a member. The text that allows accessing the common initial sequence uses a more general term, "inspect", so the relevant text does in fact make that distinction. > 2) the "special guarantee" clause changes the semantics of "indirect" union > member access to match those of "direct" member access, in specified cases, > despite that the present wording only dances around this topic without ever > touching it. It says it is permitted, which would seem to me to obviously cancel the anti-aliasing rules that would otherwise prohibit it. I don't see the "dancing around" that you see. > > The standard explicitly says, referring to the same example mentioned in DR > > 257, that the second code fragment is not valid, but only "because the union > > type is not visible within function f", implying that it would be valid if > > the declaration of the union type were moved so that it would be visible > > inside f(). If it were so moved, it would be essentially equivalent to the > > code which was the original defect report. While examples are non-normative, > > that example implies that the visibility clause was intended to actually > > serve a purpose (and it seems obvious to me that it actually does so). > > I'm not arguing that N685 Keep in mind that I'm only talking about what the current standard says; N685 is relevant to my comments only because, and therefore, only insofar as, the current standard implements what N685 proposed.