Open Quuxplusone opened 4 years ago
Hi, is this a bug or not?
[This still reproduces in trunk, though I suspect the mechanism by which we get
to the bad result is probably different these days.]
This is formally a bug in C, but not in C++: in C++, infinite loops with no
side-effects are undefined behavior unconditionally, whereas in C they're valid
if the loop condition is a constant expression.
In any case, I don't think that's relevant to what's happening to this code,
and the transform that LLVM is performing does appear to be incorrect.
What's happening is:
1) The "return 0" in main is replaced by "unreachable" because foo() is deduced
to be noreturn.
2) CSE removes the call to foo (presumably because foo() is annotated as
readnone and its result is unused):
*** IR Dump Before Early CSE w/ MemorySSA ***
; Function Attrs: nofree noreturn nounwind uwtable
define dso_local i32 @main() local_unnamed_addr #1 {
entry:
%call = call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i64 0, i64 0), i32 100)
call void @foo()
unreachable
}
*** IR Dump After Early CSE w/ MemorySSA ***
; Function Attrs: nofree noreturn nounwind uwtable
define dso_local i32 @main() local_unnamed_addr #1 {
entry:
%call = call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i64 0, i64 0), i32 100)
unreachable
}
I believe step (1) is correct, but step (2) is a bug -- it results in a
miscompilation of nonterminating programs, and would only be correct if foo()
were annotated 'willreturn'.
If there's an annotation that Clang needs to emit to prevent this
transformation being applied in C to 'foo', that's certainly something we can
do, but on the face of it this appears to be an optimizer bug.
Hi, the test.c
include
void foo( ) { while(1){} //do {}while(1); //crash //for(;;); //crash while(-1){} // non-executed loop, but still crash } int main () { int size = 100; printf("size = %d\n", size); foo(); return 0; }
is a simple function call code. When I compiler is using
clang-6.0 -O1 test.c
(or O2, O3, and Os) and then./a.out
, the output issize=100 size=100 Segmentation fault(code dumped).
The strange thing is that
printf
function executed twice and whatever loop I use in the function foo(), even a non-executed loop, it gets faults.