https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112870
--- Comment #2 from Grant Wittman ---
(In reply to Andrew Pinski from comment #1)
> This is all undefined behavior.
>
>
> Please read
> https://gcc.gnu.org/onlinedocs/gcc-13.2.0/gcc/Labels-as-Values.html .
>
> Specifically:
> You may not use this mechanism to jump to code in a different function.
I think I might get what you mean by 'undefined behavior', but this result is
predictable. I know that specific code snippet does not work, but it was the
shortest example I could make that would recreate the error.
Additionally, that doesn't explain why the last instruction is compiled
completely differently when the line `void* label_var = &&label;`, is removed.
I understand that the `label` is also removed from compilation but I can still
just use this code and it compiles correctly:
void function() {
return;
}
int main() {
goto *&function;
}
Again this code does not run without a segfault, but it compiles correctly.
If I force the compiler to add the labels into the assembly, it will still
compile correctly:
void function() {
return;
}
int one = 1;
int main() {
if(one) goto end;
label:
goto *&function;
end:
if(!one) goto label;
return 0;
}
which compiles to
function:
pushrbp
mov rbp, rsp
nop
pop rbp
ret
one:
.long 1
main:
pushrbp
mov rbp, rsp
mov eax, DWORD PTR one[rip]
testeax, eax
jne .L9
nop
jmp .L4
.L10:
nop
.L4:
mov eax, OFFSET FLAT:function
jmp rax
.L9:
nop
mov eax, DWORD PTR one[rip]
testeax, eax
je .L10
mov eax, 0
pop rbp
ret
But by adding that declaration of `label_var` back, it breaks again
void function() {
return;
}
int one = 1;
int main() {
void* label_var = &&label; // <-- ADDED STATEMENT
if(one) goto end;
label:
goto *&function;
end:
if(!one) goto label;
return 0;
}
which compiles to
function:
pushrbp
mov rbp, rsp
nop
pop rbp
ret
one:
.long 1
main:
pushrbp
mov rbp, rsp
mov QWORD PTR [rbp-8], OFFSET FLAT:.L4
mov eax, DWORD PTR one[rip]
testeax, eax
jne .L9
.L4:
nop
jmp .L4 ; <-- GOTO STATEMENT INFINITE LOOP AGAIN
.L9:
nop
mov eax, DWORD PTR one[rip]
testeax, eax
jne .L6
jmp .L4
.L6:
mov eax, 0
pop rbp
ret