Indeed. And even with my lack of clang expertise, it's clear that this would be highly nontrivial to change in clang and probably some other compilers. It's clearly not a change that we should make lightly. On the other hand, that also makes it more urgent to address the issue, since compilers currently still seem to stop short of applying the rule in situations where it would interfere with real code.

I would personally still favor a more usable and intuitive model in the long term over implementer inconvenience in the short term. Implementations are easier to change than client code. The compiler problems are hard, but coming up with alternative parallel algorithms, or teaching tens of millions of programmers a needlessly complex rule, is almost certainly harder.

This seems to be a case where we currently have an unintuitive rule (at least to most people) that introduces UB that seriously gets in the way of applications (and in my opinion teaching), without a fully convincing argument to justify the rule. Especially given the general complaints about UB in C and C++, I think we should avoid such cases. I'm perfectly willing to accept UB in other cases, like signed integer overflow, where it gives useful implementation freedom and demonstrably helps optimizers. Here I think we basically have an unproven conjecture that it might eventually do the former (via potentially making use-after-free easier to detect) and some really obscure, and to me unconvincing, examples of the latter.

My conjecture (real information welcome!) is that current compilers tend to conflate compiler optimization facts like "*a aliases *b" or "a and b point to the same thing" with the result of the expression "a == b". The current standard sanctions this, but fundamentally they're not the same. When the compiler asks aliasing questions, it generally wants to know whether an update through one pointer could affect the value pointed to by the other. It doesn't care what answer it gets if either side cannot be safely dereferenced. We now have lots of examples where user code does care about that case.



On Fri, May 3, 2019 at 1:50 AM Niall Douglas <s_sourceforge@nedprod.com> wrote:
>>> T *a = new T;
>>> delete a;
>>> T *b = new T;
>>>
>>> // Everybody agrees the compiler can assume this is always true
>>> assert(a != b);
>> I'm not at all sure this is right. The compiler can definitely assume that
>> *a and *b do not alias; falsifying that would involve dereferences which
>> would result in undefined behavior. And disallowing that assumption would
>> slow down code. But that's not really exposed to the user, and not the same
>> thing as claiming a!=b is true.
>
> y

As I already explained with code snippets in previous emails, clang
already hard assumes the above comparison is always true. I'll relink my
godbolt example: https://godbolt.org/z/c219s9

This is because, as Richard Smith already explained, clang already does
provenance tracking, and its rules lead to the above result.

Given that production compilers are already shipping and making these
kinds of provenance-based optimisations, if those rules mathematically
lead to incorrect codegen, then I'd say it's urgent to get clang fixed.

Niall