In the case that a local jmp_buf is actually represented by registers rather than stack memory, is it possible for setjmp or longjmp to cause the contents of the local jmp_buf to be indeterminate when setjmp returns from a longjmp?
The suggested duplicate Is it allowed to do longjmp() multiple times for one setjmp() call? asks in the context of a global variable. It was suggested since the answer explains that the variable is not modified in a way that would prevent it from being subsequently called, that sufficiently answers the question for a local variable too.
However, treatment of a local variable differs from a global variable. In particular, if the local jmp_buf variable is actually held in registers and not memory, restoration after longjmp may not render a reusable jmp_buf variable.
As an academic exercise, I was attempting to use setjmp as a substitute for goto. To keep the loop replacement local to the function, the jmp_buf used is also a local variable.
void foo (int n) {
jmp_buf jb;
volatile int i;
i = setjmp(jb);
if (i < n) {
do_stuff(i);
longjmp(jb, ++i);
}
}
I understand that non-volatile local variables that have been modified between the setjmp call and the longjmp call are unspecified after longjmp. However, I was curious about the local jmp_buf variable itself, particularly in the case where the jmp_buf variable is represented by registers rather than memory on the stack.
It is unclear if longjmp itself can be considered something that may modify the local jmp_buf variable, and whether this means its contents are unspecified when setjmp returns after the call to longjmp.
I thought I could easily dispatch the issue by declaring jb to be volatile, but this triggered a warning (which I treat as an error):
... error: passing argument 1 of ‘_setjmp’ discards ‘volatile’ qualifier from pointer target type [-Werror=discarded-qualifiers]
setjmp(jb);
^~
Also, the specification of setjmp does not speak to whether it is saving the register values as they would be after setting the jmp_buf or before setting the jmp_buf.
If I need to be concerned about it, I can create a volatile copy of the jmp_buf and copy its contents around. But, I'd like to avoid that if it isn't required.