https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110728
--- Comment #11 from Michael Matz <matz at gcc dot gnu.org> --- (In reply to Michael Matz from comment #9) > Just for completeness: I agree with Andrew that the initial code example in > comment #0 doesn't show any problem. The edge from asmgoto to l0 doesn't > cross > the scope of the variable, hence no cleanups should be run. The cleanup > call that is there is from the edge that leaves the function scope before > return, and it's placed correctly. I was reminded that this is incorrect. Though it isn't documented that way (AFAICS) the cleanup attribute itself create a scope, as we're using the try/finally middle-end mechanisms to implement this attribute. We can't change that behaviour anymore of course, so that's how it has to be: jumping in front of the decl of 'x' _is_ supposed to run the cleanup. The initial example essentially boils down to: void test4(void) { l0:; try { /* implicit scope per instantiation of __cleanup__ variable */ int x __attribute__((cleanup(test4cleanup))); asm goto("# %l0"::::l0); /* <-- leaves scope created by x */ } finally { test4cleanup(); } }