https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112870

--- Comment #2 from Grant Wittman <grantrwittmann at gmail dot com> ---
(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:
        push    rbp
        mov     rbp, rsp
        nop
        pop     rbp
        ret
one:
        .long   1
main:
        push    rbp
        mov     rbp, rsp
        mov     eax, DWORD PTR one[rip]
        test    eax, eax
        jne     .L9
        nop
        jmp     .L4
.L10:
        nop
.L4:
        mov     eax, OFFSET FLAT:function
        jmp     rax
.L9:
        nop
        mov     eax, DWORD PTR one[rip]
        test    eax, 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:
        push    rbp
        mov     rbp, rsp
        nop
        pop     rbp
        ret
one:
        .long   1
main:
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-8], OFFSET FLAT:.L4
        mov     eax, DWORD PTR one[rip]
        test    eax, eax
        jne     .L9
.L4:
        nop
        jmp     .L4 ; <-- GOTO STATEMENT INFINITE LOOP AGAIN
.L9:
        nop
        mov     eax, DWORD PTR one[rip]
        test    eax, eax
        jne     .L6
        jmp     .L4
.L6:
        mov     eax, 0
        pop     rbp
        ret

Reply via email to