What is really missing from the C "aliasing" rules is a recognition that an access to a pointer/lvalue which is visibly freshly derived from another is, depending upon the form of derivation, either a definite or potential access to the former [in the former case, anything that couldn't be accessed by the original couldn't be accessed by the derived pointer/lvalue; in the latter case, the derived pointer/lvalue might access things the original could not].
I think the authors of C89 most likely thought that principle was sufficiently obvious that there was no need to expressly state it. Were it not for the Standard's rule forbidding it, an implementation might plausibly have ignored the possibility of an `int` being accessed via an `unsigned`, but I don't think the authors of the Standard imagined that a non-obtuse compiler writer wouldn't allow for the possibility that something like:
The present rules, as written, have absurd corner cases. Given something like:
union U { float f[2]; unsigned ui[2]; } uu;
the Standard would, so far as I can tell, treat as identical the functions test1, test2, and test3 below:
float test1(int i, int j)
{
uu.f[i] = 1.0f;
uu.ui[j] += 1;
return uu.f[i];
}
float test2(int i, int j)
{
*(uu.f+i) = 1.0f;
*(uu.ui+j) += 1;
return *(uu.f+i);
}
float evil(unsigned *ui, float *f)
{ *f = 1.0f; *ui += 1; return *f; }
int test2(int i, int j)
{
evil(uu.f+i, uu.ui+j);
}
If a dereferenced pointer to union member type isn't allowed to access the union, the first example would be UB regardless of i and j, but that would imply that non-character arrays within unions are meaningless. If such pointers are allowed to access union objects, then test2 (and the evil function within it) would have defined behavior even when i and j are both zero.
BTW, I think any quality compiler should recognize the possiblity of type punning in the first two, though the Standard doesn't actually require either. Neither clang or gcc, however, recognizes the possibility of type punning in the second even though the behavior of the [] operators in the first are defined* as equivalent to the second.
1. I want this too.
2. Here is my proposal: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2366.pdf
3. Yes, variadic functions should be improved.