https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95137
--- Comment #10 from Iain Sandoe <iains at gcc dot gnu.org> --- It seems that the ubsan complaints look all rather similar. At least for the following case, ubsan seems to cause a change which introduces a bogus temporary use. class-00-co-ret.C u=is a very simple coroutine - this is the output of -fdump-tree-gimple for the main body of the actor function. without ubsan. _7 = &frame_ptr->__p; frame_ptr->__aw_s.is = coro1::promise_type::initial_suspend (_7); [return slot optimization] _8 = &frame_ptr->__aw_s.is; _9 = coro1::suspend_always_prt::await_ready (_8); retval.0 = ~_9; if (retval.0 != 0) goto <D.11135>; else goto <D.11136>; <D.11135>: frame_ptr->__resume_at = 2; _10 = &frame_ptr->__aw_s.is; coro1::suspend_always_prt::await_suspend (_10, frame_ptr->__self_h); D.11053 = .CO_YIELD (2, 0, &resume.2, &destroy.2, frame_ptr); retval.1 = D.11053; switch (retval.1) <default: <D.11056>, case 0: <D.11054>, case 1: <D.11055>> <D.11054>: .CO_SUSPN (&actor.suspend.ret); <D.11055>: goto resume.2; <D.11056>: goto destroy.2; destroy.2: _11 = &frame_ptr->__aw_s.is; coro1::suspend_always_prt::~suspend_always_prt (_11); goto coro.delete.promise; <D.11136>: resume.2: frame_ptr->__i_a_r_c = 1; _12 = &frame_ptr->__aw_s.is; coro1::suspend_always_prt::await_resume (_12); _13 = &frame_ptr->__aw_s.is; coro1::suspend_always_prt::~suspend_always_prt (_13); { puts ("coro1: about to return"); _14 = &frame_ptr->__p; coro1::promise_type::return_value (_14, 42); goto final.suspend; ==== with ubsan _7 = &frame_ptr->__p; frame_ptr->__aw_s.is = coro1::promise_type::initial_suspend (_7); [return slot optimization] D.11410 = &frame_ptr->__aw_s.is; .UBSAN_NULL (D.11410, 4B, 0); _8 = coro1::suspend_always_prt::await_ready (D.11410); retval.0 = ~_8; if (retval.0 != 0) goto <D.11411>; else goto <D.11412>; <D.11411>: frame_ptr->__resume_at = 2; D.11413 = &frame_ptr->__aw_s.is; .UBSAN_NULL (D.11413, 4B, 0); coro1::suspend_always_prt::await_suspend (D.11413, frame_ptr->__self_h); D.11322 = .CO_YIELD (2, 0, &resume.2, &destroy.2, frame_ptr); retval.1 = D.11322; switch (retval.1) <default: <D.11325>, case 0: <D.11323>, case 1: <D.11324>> <D.11323>: .CO_SUSPN (&actor.suspend.ret); <D.11324>: goto resume.2; <D.11325>: goto destroy.2; destroy.2: D.11415 = &frame_ptr->__aw_s.is; .UBSAN_NULL (D.11415, 4B, 0); coro1::suspend_always_prt::~suspend_always_prt (D.11415); goto coro.delete.promise; <D.11412>: resume.2: frame_ptr->__i_a_r_c = 1; D.11416 = &frame_ptr->__aw_s.is; .UBSAN_NULL (D.11416, 4B, 0); coro1::suspend_always_prt::await_resume (D.11416); .UBSAN_NULL (D.11415, 4B, 0); ^^^ this is not correct D.11415 is not valid here, (D.11416 would be). coro1::suspend_always_prt::~suspend_always_prt (D.11415); { puts ("coro1: about to return"); D.11417 = &frame_ptr->__p; .UBSAN_NULL (D.11417, 4B, 4); coro1::promise_type::return_value (D.11417, 42); goto final.suspend; }