[all-commits] [llvm/llvm-project] dbca16: [Coroutines] Use destroy slot for CoroElide resume...

Yuxuan Chen via All-commits all-commits at lists.llvm.org
Fri Jul 17 14:54:10 PDT 2026


  Branch: refs/heads/users/yuxuanchen1997/fix-coro-halo-suspend-never-bad-free
  Home:   https://github.com/llvm/llvm-project
  Commit: dbca16b70c1becb507741e8d7fb9f252b2754d19
      https://github.com/llvm/llvm-project/commit/dbca16b70c1becb507741e8d7fb9f252b2754d19
  Author: Yuxuan Chen <i at yuxuan.ch>
  Date:   2026-07-07 (Tue, 07 Jul 2026)

  Changed paths:
    A clang/test/CodeGenCoroutines/gh188230-coro-await-elidable-suspend-never-final.cpp
    M llvm/include/llvm/Transforms/Coroutines/CoroShape.h
    M llvm/lib/Transforms/Coroutines/CoroSplit.cpp
    M llvm/lib/Transforms/Coroutines/Coroutines.cpp
    M llvm/test/Transforms/Coroutines/coro-split-00.ll
    M llvm/test/Transforms/Coroutines/coro-split-addrspace.ll
    A llvm/test/Transforms/Coroutines/coro-split-resume-fallthrough-destroy-slot.ll

  Log Message:
  -----------
  [Coroutines] Use destroy slot for CoroElide resume fallthrough

Fixes https://github.com/llvm/llvm-project/issues/188230

When a switch coroutine is allocation-elided, resuming it can run through to a coro.end path and destroy the coroutine frame from inside the resume clone. That is fine for a heap-allocated frame, but it is wrong for the clang::coro_await_elidable CoroElide path: the caller may have supplied stack storage through the noalloc ramp. In that case, the frame's destroy slot is initialized to the cleanup clone, while the resume clone still emitted the normal coro.free/deallocation sequence and attempted to free storage owned by the caller.

This is not limited to coroutines where CoroSplit fails to see a final suspend. Clang still emits a final-suspend coro.suspend for a C++ final_suspend returning suspend_never, but that suspend can flow through to coro.end and self-destroy when resumed. For switch resume clones with a generated CoroElide noalloc variant, the fallthrough coro.end path now loads the destroy/cleanup function pointer from the coroutine frame and tail-calls it. The frame slot is the runtime discriminator: elided frames dispatch to cleanup and heap frames dispatch to destroy.

Add an IR regression for the split lowering and a C++ CodeGen regression for the original suspend_never final_suspend shape. The C++ test forces CoroAnnotationElide with -coro-elide-branch-ratio=0 because the current branch-frequency heuristic may otherwise skip the elision and hide the bug.

Assisted-By: Codex GPT 5.5



To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications


More information about the All-commits mailing list