After looking at the Livermore for a while, we found the issue that was causing LTO to produce a different result.
Consider the code below [1]. setup() doesn’t touch bar/baz, main() doesn’t reference foo. LTO finds, correctly, that it can remove the setup(), but the result is different.
The code is clearly wrong, but the compiler has no right to fix user’s stupidity, even at that level. The only think I can think that would mitigate the problem would be to have a warning or out-of-bounds access when it’s that obvious.
Clang folks,
Correct me it I’m wrong, but I humbly think this should be done in the front-end, so it’s easy to print out line information without requiring debug symbols to be present. How easy would be to do that in Clang’s AST?
I assume it’s only a matter of checking the stride against the bounds of the array, if all is knowns at compile time. That would also help against segmentation fault.
It wouldn’t, however, work with variable length arrays, but VLA tend to segfault more often than silently overwrite other global variables.
cheers,
–renato
[1]
#include <stdio.h>
struct {
int foo[20];
int bar[20];
int baz[20];
} S;
void setup() {
int i;
// OVERWRITES ALL THREE ARRAYS
for (i=0; i<60; i++)
S.foo[i] = i; // ONLY REFERENCES FOO
}
// DOESN’T USE FOO
int main() {
int i;
setup();
printf("Bar: ");
for (i=0; i<20; i++)
printf("%d “, S.bar[i]);
printf(”\nBaz: “);
for (i=0; i<20; i++)
printf(”%d “, S.baz[i]);
puts(”");
return 0;
}