<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/130326>130326</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Coroutine miscompile: parameter destroyed twice(?) at -O1
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            miscompilation,
            coroutines
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          zmodem
      </td>
    </tr>
</table>

<pre>
    I'm not actually sure that the parameter is destroyed twice, but that's how the bug first appeared.

Consider:

```
#include <coroutine>
#include <utility>
#include <stdio.h>

// Boilerplate based on https://theshoemaker.de/posts/yet-another-cpp-coroutine-tutorial
class Task { 
public:
    struct FinalAwaiter {
        bool await_ready() const noexcept { return false; }
        template <typename P> auto await_suspend(std::coroutine_handle<P> handle) noexcept {
            return handle.promise().continuation;
        }
        void await_resume() const noexcept { }
    };

    struct Promise {
        std::coroutine_handle<> continuation;
        Task get_return_object() {
            return Task { std::coroutine_handle<Promise>::from_promise(*this) };
        }
 void unhandled_exception() noexcept { }
        void return_void() noexcept { }
        std::suspend_always initial_suspend() noexcept { return {}; }
 FinalAwaiter final_suspend() noexcept { return {}; }
    };
    using promise_type = Promise;

    Task() = default;
    ~Task() { if (handle_) { handle_.destroy(); } }

    struct Awaiter {
 std::coroutine_handle<Promise> handle;
        bool await_ready() const noexcept { return !handle || handle.done(); }
        auto await_suspend(std::coroutine_handle<> calling) noexcept {
 handle.promise().continuation = calling;
            return handle;
 }
        void await_resume() const noexcept { }
    };

    auto operator co_await() noexcept { return Awaiter{handle_}; }
    void run() {
 handle_.promise().continuation = std::noop_coroutine();
 handle_.resume();
    }

private:
    explicit Task(std::coroutine_handle<Promise> handle) : handle_(handle) { }
 std::coroutine_handle<Promise> handle_;
};

// The interesting part starts here.
namespace {
struct Cleanup {
  Cleanup() : is_engaged(true) {}
 Cleanup(Cleanup&& other) { is_engaged = true; other.is_engaged = false; }
 ~Cleanup() { if (is_engaged) { printf("CLEANUP\n"); } }
  bool is_engaged;
};
}

Task hello(Cleanup c) {
  printf("HELLO\n");
 co_return;
}

Task foo(Cleanup c) { co_await hello(std::move(c)); }

int main() {
  Task t = foo(Cleanup());
  t.run();
}

$ clang++ /tmp/a.cc -std=c++20 -O0 && ./a.out
HELLO
CLEANUP

$ clang++ /tmp/a.cc -std=c++20 -O1 && ./a.out
HELLO
CLEANUP
CLEANUP
```

The expectation is that there is only one "engaged" Cleanup object, and so we should only see that printed once.

The anonymous namespace seems to be an important factor.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJy0V8tu4zoS_Rp6U7AgU3HsLLyQnRgzQGO6Fz1rg5LKFqcpUiCLSXsW_e0XlChZdh79uLhGgEgiearq1KkiKZyTJ424YcstWz7OhKfa2M3_G1NhMytMdd78m_FVA9oQiJK8UOoMzlsEqgUB1QitsKJBQgvSQYWOrDljBfQiS2R8B4WnbjLjKwe1eekWFf4ER2kdgWhbFBarhKU5S_Od0U5WaFmW9x_YfRr_0pzxTOpS-QqBZbvSWONJamTZ06tBT1JJOr815KiSJqnjUBjdM76HrZEKbasEIRTCYQVGQ03UuuBLN4dqdLXBRnxDm1TI-L41jhzj-zPSXGhDNdp52bbz0bc5eTJWCsXSvFTCOfgq3Ddgqy2wNG99oWTZxwoA4Mj6kmAvtVD5i5CBVbbaxtHwK4xRIMLQwaKozoyvGX-A0mhHoA1-L7GlDt4ieavhKJRDlm2BrR4nOIRNHyrLdnRuUYsG4QvLnkB4MtGC865FXTG-dlQFL7N8DOxQC10pZNmuWxXf-MOVExOD4Rdd6ucmrTWNdNhHkJRGk9RekDSaZdOV144_G1mNBDjf4PsMXBaGpw7zmucvvQc3nn4Uawj1fU-71J4weBYCPZjif1hSdPBdOkZBfEhyJCt76qccrWkOUwZzqqXr7Ty-yV9HnNc9YnXoeQoh9O69w9xIeQwpPP98xRhJVNBBqBdxdiC1JCnURFivgCIpga0ukAH5qiaO4eVPUKZaCC_eSX2CyOMhFAKw7BFGtieaCWkaUpk9QoVH4RVdoH5MJ6y2II_A-Lqn-zB8jK9J7JP99Ohf9PFaojdd4NckMlRj9rc6B-OLHgfYasdWu6FuK6PxyvGJkd9uHl1BCaWkPr3VPH7aKrpcDADZhw0nDv8D7aSL2rRoBRkLpTl0gB_oMmaVrbaDPm5V2tec19fNY5DPT_gYCdfGtIfLPjkkbQo1jfpC4CjF1spnQXjZovB7q2QpaaiH31NkVzyj8bE-hvKI8f8W5iGmYpKTuKN_rRGkJrToqCtzYQkcCUsOarQYjhxh33OtKIdNIJbdTqHQvh2bdnwf6z8H6Q6oT-KEQeFk_RBDDOGyYHy6Z_weuiPC2CJGjC5tHUq27eckN4O3-_iPG5fGjjN1rP_eWqnp2E3ku09P-X_--4Utd5px_qr5xDYxwbghd9BFt2nVqJS5hAjldJ-bWv3X06dPn69shimliRvlW9hH8xbyWFyj7VErjXkOMg4zr1oTS3OpCRohb4qp33ipZ3dqLRbDpR4oGSvxxlXG76BUIjSvLeNbCIfEpmV8L5KyhHnn3GPZD_IU5p9TiEJIuknGE0vznp40H5LzZ9CLX4OeGJkerdM8lAt-b7GkvpNINx7yLYY3o9UZjEZgnI8S42OtDKedHQhdgTPwguBq41XVr3QYbw2dMrrzdYnJxbbQRp8b4x1citIhNg7IQBHGQTatsSQ0wVGUZGwyqzZZ9ZA9iBluFqu7RbbKsuViVm9Sjsv18XhcpVVRLO-W67Uo-FIIUfBVJe7FTG54ypdplq4W67uHxSJZLBbZ6v5uUa7vM7HMOLtLsRFSJUo9N4mxp5l0zuNmkaUZv58pUaBy3cWJ80a60jStVP2hMIh8xzgf25cLn5aPM7sJYPPCnxy7S5V05C7wJEnhZjesgRE0dN_JNevVHWvNsn3QtaCggpm3anN9bzlJqn2RlKZhfB_sxX_z1po-Z_sutnCTieE9b_hfAQAA___7vUix">