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

    <tr>
        <th>Summary</th>
        <td>
            link error when compiling coroutine code.
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            clang,
            c++20,
            coroutines
      </td>
    </tr>

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

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

<pre>
    See https://godbolt.org/z/rc37E78EM for a minimal testcase.

The following code is compiled with gcc, but clang emits a link error (`in function Foo::CoroutineBody(): <source>:60: undefined reference to CoroutinePromise<void>::CoroutinePromise<Foo&>(Foo&)`) when linking to a binary. We seem to miss a symbol.


```cpp
#include <coroutine>

template <typename Final>
class Gen;

template <typename Final>
class CoroutinePromise final {
 public:
  template <typename... Args>
  explicit CoroutinePromise(Args&&... args) {}

 Gen<Final> get_return_object() { return Gen<Final>(my_handle()); }

 std::coroutine_handle<CoroutinePromise> my_handle() {
    return std::coroutine_handle<CoroutinePromise>::from_promise(*this);
  }
 void unhandled_exception() {}
  void return_void() {}

  template <typename U>
  auto await_transform(Gen<U> gen) {
    struct Awaitable {
      bool await_ready() { return false; }
 std::coroutine_handle<> await_suspend(
          const std::coroutine_handle<> handle_in) {
        return handle_in;
 }
      decltype(auto) await_resume() {}
    };
    return Awaitable();
  }

  std::suspend_always initial_suspend() { return {}; }
  std::suspend_always final_suspend() noexcept { return {}; }
};


template <typename Final>
class Gen final {
 public:
  using final_result_type = Final;
  using promise_type =CoroutinePromise<Final>;
  explicit Gen(const std::coroutine_handle<promise_type> handle)
      : handle_(handle) {}

  std::coroutine_handle<promise_type> handle_;  
};

class Foo  {
 public:
  Gen<void> TestBody2() {
    auto s = 
 [&]() -> Gen<void> { co_await this->CoroutineBody(); co_return; };
 return s();
  }
 private:
  Gen<void> CoroutineBody();
};

Gen<void> Foo ::CoroutineBody() {
  if constexpr (0) // remove it will make clang compile.
    co_await []() -> Gen<void> { co_return; }();
}

int main() {
  return 0;
}
```


</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJycVkuP4jgQ_jXmUhoUHALhwIFHs6eVVtoZ7TFynAp4x7Ej22ma_fUrx0kIr27NoBZNnKqvqr56uJi14qgQ1yTZkmQ_YY07abM-6Z8o1CTXxWX9NyKcnKstiTeEHgg9HHWRa-mm2hwJPfxH6MHwePm2TN_-hFIbYFAJJSomwaF1nFmckmhPok34_n5CKLWU-izUEbguEIQFrqtaSCzgLNwJjpwTuoO8ccAlU0fASjgLDKRQPwGN0QYITckiEgrKRnEntIKD1t7JeLPTRjdOKNzq4uLl6IrEGyDxzurGcCTxG4k3i8gfNqrAUigswGCJBhVHcBoGiL-MroRFEu_etSiC5tjE9b03Txdegqbdb7oii4jQFZxPqFrnfcxOA4NcKGYuU_gHwSJW_rAS1sdoL1Wu5Q1n3fciCn-8rrsTGgvFZVOgD473PnkfRnoOq1oy18q4S42KVQgHoZgcBLlk1sIfqEi8_S3Vez6g9EJAlh0c1E0uBffkhWd4Bj2dTmFjjnYAB8CPWgou3GNGaNqKepoXXpG1T6vW5nI_jiIEtuv9hiO6zKBrjMp0_i9yF2rEa0I4v9MgNK0u2YmpQmJXT76ktnBvyLoi1MeQi14r3j2WzBvcoY74Auhd-UXMIFsaXWX1wBShG3cSNnjdWxicB1_a0KgAW2T4wbH2LTXyapANwh19bU88Cn2WY_gxyi5rfDOcmXCZM0zZUpuK0DSw_yPkSj0QY51puION12O5xNu3ALnWskM1yPoRME5vyaQna5TAT2n2jgQ829gaVRvzyKD_cK2s-xIlPGTiMahRxq9CQ7JG_PtPgVx6QglNPYUerI_XNhU-zVtIePxYYAOP_ah8rJD-YAiv4yFj8swuFoQSTjA5pueW8M6VG8ZforWz4w5L6VCVX4COQ_zdGfj17Gqsn-PBTc-4dJkHBRLve9DtrWzXioPYs_uj9-aqOww_3xA0_brExmau5eaTOioef-11JUZoOog87eBfN5b5fMCrbASSD1rDZ_yG_u8uXPiO1vmbnD4bku0EsS3zfaskW38pJPtO_JvHuEX0NcR11rYM-MHoZZ5uDa1cKLe-zob09PP5ddtAbcQ7c_gytOc2X5F3q-tJfLnvjEkSZRhO-FG3a1O7kYRdDgxW-h1BODgLKaFiP7FbubqNbHqlemAsbItf0ntL22Nwo8iEclAxoR6d70iOnmj269AYaFKs42IVr9gE17NllMxnySxOJqc1Ukxn-Xwex4uELVmSp7N5xHjMkpznrEgmYk0jOo9ms8VsTpM4mS5XZV6mBceoXKbRqiDzCCsm5FTK98pvvxNhbYPrZUpX0USyHKVtF2lKWwYJpYTu_BOhW0K3NLqe9Amz_ijZT8zag37Lm6Ml80gK6-zVjBNO4nq0-rbbZMhP2KE7tHabnk4aI9d3K7twpyafcl0RevC43b9vtdFh_zm0sVhCD204_wcAAP__2R6azQ">