-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Miscompilation with noalias and pointer equality #59679
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This general class of problem is known (see e.g. #34577), but this is a particularly nice example of the issue. Did you encounter a real-world miscompile, or is this a constructed test case? |
I stumbled upon this example while discussing the formal definition of #include <stdint.h>
int x[1];
int test(int *restrict p, int i)
{
int *q = p;
p[i] = 1;
if ((uintptr_t)p == (uintptr_t)x)
{
int *r = q;
*r = 2;
}
return p[i];
} Executing So I tried simplifying the example to one that doesn't invoke UB under any definition, resulting in the version of Finally, I discussed the example with @carbotaniuman and others, who found that this issue can also be reproduced with the Rust compiler, making this issue attributable to LLVM rather than the Clang frontend. |
This reproducer specifically, is very much a constructed example. (Oh I missed the message above thanks to my email client, sorry for any noise). I would like to add that my Rust example is similar to some of my real Rust code, but to my knowledge I have not gotten any miscompilations yet.
…On Fri, Dec 23, 2022, 12:07 PM LegionMammal978 ***@***.***> wrote:
Did you encounter a real-world miscompile, or is this a constructed test
case?
I stumbled upon this example while discussing the formal definition of
restrict with u/flatfinger on Reddit. They noted
<https://reddit.com/comments/zq2zg5/_/j19nj3t> that both GCC and Clang
unconditionally return 1 from a similar function:
#include <stdint.h>int x[1];int test(int *restrict p, int i)
{
int *q = p;
p[i] = 1;
if ((uintptr_t)p == (uintptr_t)x)
{
int *r = q;
*r = 2;
}
return p[i];
}
Executing test(x, 0) likely invokes UB under the current formal
definition (since r is arguably not based on p), but I noticed that the
proposed modifications to the restrict definition in N3025
<https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3025.htm> and N3058
<https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3058.htm> would
require test(x, 0) to return 2.
So I tried simplifying the example to one that doesn't have UB under any
definition, resulting in the version of test() posted here. GCC and Clang
still assume that *ptr = 2 does not affect the return value.
Finally, I discussed the example with @carbotaniuman
<https://github.com/carbotaniuman> and others, who found that this issue
can also be reproduced with the Rust compiler, making this problem
attributable to LLVM rather than the Clang frontend.
—
Reply to this email directly, view it on GitHub
<#59679 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AJ4ICP4G46GO3NJ4OWDZ7CTWOXS7VANCNFSM6AAAAAATH5E54Y>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
I think you should not expect a defined behavior for the code. You should not use |
The |
@LegionMammal978 Thanks for your clarification. I found some more explanations on this topic: https://www.open-std.org/jtc1/SC22/wg14/www/docs/n2260.pdf |
Reproducer
Tested with clang 15.0.0 and trunk
The issue appears to be that Clang's constant propagation replaces
*ptr = 2
withx = 2
, which breaks the noalias based on analysis and allows thereturn *ptr
to be simplified toreturn 1
.The text was updated successfully, but these errors were encountered: