https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80959
--- Comment #4 from Martin Liška <marxin at gcc dot gnu.org> --- So there's explanation what happens: 1) w/o -fsanitize=address: decide_copy_try_finally returns true and so that we copy BB that contains finally statement: foo () { int n; int D.1806; bar (&n); i.0_1 = i; switch (i.0_1) <default: <D.1804>, case 1: <D.1801>> <D.1801>: i.1_2 = i; switch (i.1_2) <default: <D.1802>> <D.1802>: D.1806 = 0; goto <D.1809>; goto <D.1803>; <D.1804>: D.1806 = 0; goto <D.1809>; <D.1803>: n = {CLOBBER}; goto <D.1808>; <D.1809>: n = {CLOBBER}; goto <D.1807>; <D.1808>: return; <D.1807>: return D.1806; } then CFG pass removes the dead BBs. All works fine. 2) w/ -fsanitize=address the decide_copy_try_finally returns false and thus we create switch to dispatch from the finally statement: foo () { int finally_tmp.2; int n; int D.2128; ASAN_MARK (UNPOISON, &n, 4); bar (&n); i.0_1 = i; switch (i.0_1) <default: <D.2126>, case 1: <D.2123>> <D.2123>: i.1_2 = i; switch (i.1_2) <default: <D.2124>> <D.2124>: D.2128 = 0; finally_tmp.2 = 0; goto <D.2131>; goto <D.2125>; <D.2126>: D.2128 = 0; finally_tmp.2 = 0; goto <D.2131>; <D.2125>: finally_tmp.2 = 1; <D.2131>: ASAN_MARK (POISON, &n, 4); switch (finally_tmp.2) <default: <D.2134>, case 1: <D.2132>> <D.2132>: goto <D.2133>; <D.2134>: goto <D.2129>; <D.2133>: return; <D.2129>: return D.2128; } Then CFG removes: Removing basic block 7 ;; basic block 7, loop depth 0 ;; pred: 5 finally_tmp.2 = 1; ;; succ: 8 now finally_tmp.2 can have only one value, but the switch statement, as well as the problematic return BB are not removed.