https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110728
--- Comment #8 from John McCall <rjmccall at gmail dot com> --- > Let me clarify. If GCC were change behavior of `asm goto` to > invoke the destructor/cleanup function before the backwards edge > of `asm goto`, I would submit a patch to clang to implement that > behavior as well. Ah, thank you, I understand what you're saying now. Yes, we would take that. I think this test case might be a little more illuminating and separates out the issue of the back-edge and the uninitialized variable: https://godbolt.org/z/doG7414va ``` #include <malloc.h> #define GOTO 1 #define COMPUTED_GOTO 2 #define ASM_GOTO 3 #define CASE ASM_GOTO static void free_from(int **ptr) { free(*ptr); } int test() { #if CASE == COMPUTED_GOTO void *lbl = &&label; #endif if (1) { __attribute__((cleanup(free_from))) int *p = calloc(sizeof(int), 1); #if CASE == GOTO goto label; #elif CASE == COMPUTED_GOTO goto *lbl; #elif CASE == ASM_GOTO asm goto("<<< asm goto %l0 >>>"::::label); #endif } label: return 0; } ``` GCC produces this output for CASE == ASM_GOTO (stripping the .LFB labels): ``` test: push rbp mov rbp, rsp sub rsp, 16 mov esi, 1 mov edi, 4 call calloc mov QWORD PTR [rbp-8], rax <<< asm goto .L3 >>> lea rax, [rbp-8] mov rdi, rax call free_from .L3: mov eax, 0 leave ret `` It does something similar for CASE == COMPUTED_GOTO. In both cases, the branch avoids the cleanup with no diagnostic. But it does the right thing with CASE == GOTO.