6.5.16.1 is the “rule that only apply to “lvalue = lvalue;” assignments and is not relevant here”
It does not apply to “lvalue = 1;” or to “lvalue = 2;”, which are the two relevant assignments in the example in the article.
For context, I think I made it clear in the article that the program being discussed is UB, and therefore that the compiler is not to blame. But since I wrote this article, I have had people telling me “The complaint isn't about alignment at all, it's that the optimizer assumes that two pointers to the same basic type cannot overlap in memory”.
My reply to this specific sentence is:
No. You are wrong. There are no words in the standard that say that “basic types cannot overlap in memory”. There is not even a notion of “basic type”. There are clauses about pointer alignment, that are explicitly cited in the article, and there are clauses about strict aliasing, that are shown in the article not to be the reason for GCC optimizing the program by using -fno-strict-aliasing. There are no rules about “basic types not overlapping” in the C standard. You only think there are. Or please cite them. (6.5.16.1 is a rule about assignment, it only applies for the code pattern lvalue1 = lvalue2;)
I'm sorry, can you explain how that's not relevant here? You're being incongruously combative, but I still think you're mostly agreeing with me.
The section on "simple" assignments doesn't say that the rvalue must be an lvalue expression syntactically . I think it applies very well to "*p = 1;", which is the statement in the linked code. What am I missing?
> There are no words in the standard that say that “basic types cannot overlap in memory”.
I don't believe I said there were. I said the standard expressly allowed the optimization in the linked article. And as far as I can see, absent a clearer explanation for why that section doesn't apply, it does.
1 is not an object, but even if it was one, it would not be an object that overlaps with “* p”.
You are interpreting the C standard as if it were a philosophy text. It contains a rule that says that in very precise circumstances (for an assignment from one to the other) objects must not partially overlap, and you are claiming that it means that “two pointers to the same basic type cannot overlap in memory”. The clause does not say that, sorry. The clause applies to the objects that are on one side and the other of an assignment.
> I said the standard expressly allowed the optimization in the linked article.
I hope that the article makes it clear that the standard expressly allows the optimization. Specific, explicit rules, cited in the article, about pointer alignment, allow the optimization.
For this reason, I, “violently” as you say, disagree with the sentence “The complaint isn't about alignment at all, it's that the optimizer assumes that two pointers to the same basic type cannot overlap in memory”. This sentence gets it all wrong. It is about alignment; it is not about “pointers to basic types”, whatever that is, not being allowed to overlap in memory; they are allowed to overlap for large enough “basic types” because it is about alignment, not overlap:
You could argue that GCC 9.3 only missed the optimization in the example in this Compiler Explorer link for some other reason and that absence of optimization doesn't mean that p and q cannot overlap. This would be correct, this aspect is one of the difficulties in studying the rules that these compilers implement. However, what I am saying is that if you reported this missed optimization to GCC developers, they would tell you that GCC can't optimize the function f because p and q can overlap. There is no clause in the C standard that prevent them to (apart from strict aliasing rules, but I used the option to tell the compiler I didn't want it to take advantage of these ones).
(Please do not bother them with this, or if you do, at least leave me out of it; I have nothing better to do than to write this because it's the week-end but they have better things to do.)
> No. You are wrong. There are no words in the standard that say that “basic types cannot overlap in memory”.
§ J.2, Undefined Behavior
An object is assigned to an inexactly overlapping object or to an exactly overlapping object with incompatible type (6.5.16.1).
> There is not even a notion of “basic type”.
"Object."
You repeatedly (in this thread, and on your blog) express that you don't really understand "strict" (ISO standard) aliasing rules, and that seems to be the case.
This line of J.2 only refers to the already cited 6.5.16.1.
You keep quoting this clause as if it applied to any of the assignments in the program being discussed.
It doesn't.
That clause says that in an assignment of the form “lvalue1 = lvalue2;”, there must only be exact overlap or no overlap between lvalue1 and lvalue2. This does not apply to assignments of the form “lvalue = 1;” or “lvalue = 2;” which are the interesting assignments in the program being discussed.
Objects are not “basic types” for the original sentence that claimed that “basic types cannot overlap in memory”. Objects overlap in memory all the time.
> You repeatedly (in this thread, and on your blog) express that you don't really understand "strict" (ISO standard) aliasing rules, and that seems to be the case.
If you say so. I'm not the one who thinks that “* p” and “1” overlap.
> You keep quoting this clause as if it applied to any of the assignments in the program being discussed.
> It doesn't.
You keep asserting that 6.5.16.1 is not relevant, as if it makes it so; but it doesn't. It's your opinion; the assertions are not persuasive.
void f(void) {
char *t = malloc(1 + sizeof(int));
if (!t) abort();
int *fp = (int*)t;
int *fq = (int*)(t+1);
h(fp, fq);
int h(int *p, int *q){
*p = 1;
*q = 1;
return *p;
}
Please explain to me why you continue to believe that is not an object being assigned to an inexactly overlapping object or to an exactly overlapping object with incompatible type?
“If the value being stored in an object is read from another object that overlaps in any way the storage of the first object, then the overlap shall be exact and the two objects shall have qualified or unqualified versions of a compatible type; otherwise, the behavior is undefined.”
Under “6.5.16.1 Simple assignment”, so this describes a rule about assignment.
Which assignment in the program are you claiming stores in an object a value read from another object that overlaps in any way the storage of the first object?
It does not apply to “lvalue = 1;” or to “lvalue = 2;”, which are the two relevant assignments in the example in the article.
For context, I think I made it clear in the article that the program being discussed is UB, and therefore that the compiler is not to blame. But since I wrote this article, I have had people telling me “The complaint isn't about alignment at all, it's that the optimizer assumes that two pointers to the same basic type cannot overlap in memory”.
My reply to this specific sentence is:
No. You are wrong. There are no words in the standard that say that “basic types cannot overlap in memory”. There is not even a notion of “basic type”. There are clauses about pointer alignment, that are explicitly cited in the article, and there are clauses about strict aliasing, that are shown in the article not to be the reason for GCC optimizing the program by using -fno-strict-aliasing. There are no rules about “basic types not overlapping” in the C standard. You only think there are. Or please cite them. (6.5.16.1 is a rule about assignment, it only applies for the code pattern lvalue1 = lvalue2;)