Open llvmbot opened 10 years ago
Hmm, looks like that fails too though. We're doing something wrong here.
This is undefined behaviour. From C99 (n1256) 7.13:
An invocation of the setjmp macro shall appear only in one of the following contexts:
— the entire controlling expression of a selection or iteration statement;
— one operand of a relational or equality operator with the other operand an integer constant expression, with the resulting expression being the entire controlling expression of a selection or iteration statement;
— the operand of a unary ! operator with the resulting expression being the entire controlling expression of a selection or iteration statement; or
If the invocation appears in any other context, the behavior is undefined.
If you want to ignore __builtin_setjmp()'s result, you should write:
(void)__builtin_setjmp(...);
Note that the C standard says specifically this:
s = setjmp(env); /* WRONG! */
It's of little relevance here. If you consider it is, please view this bug report as complaining about the following kind of code, which is explicitly allowed by the C standard:
__builtin_setjmp(..); /* ignore the return value */
do_this_in_all_cases();
Or:
if (__builtin_setjmp(..) == 1)
; /* nothing */
do_this_in_all_cases();
A workaround that should always work: replace a bare __builtin_setjmp(buf) line with:
while (__builtin_setjmp(buf)) { }
Here, LLVM cannot optimize the two paths back into one, unlike e.g. the same statement with "if" instead of "while".
It means that after a __builtin_longjmp() we will repeat the __builtin_setjmp() once, which is at worst a minor performance problem, and which can be considered a good thing to do if you're (rarely but) possibly doing several longjmp() to go back to this point, like in some search algorithm.
Extended Description
__builtin_setjmp() only works when we immediately switch on its result and branch into two different code paths. If instead we write this kind of code:
then, at least on x86-64, it produces this kind of assembler for the first line:
where ".LBB4_-1" is a bogus label not defined anywhere in the .s file. It fails to assemble, of course.