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

    <tr>
        <th>Summary</th>
        <td>
            is_trivially_copyable returns wrong result with constrained ctor and assignment operators
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

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

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

<pre>
    Hello, we are rolling out our own optional implementation. While making sure our optional is trivially copyable and movable for types that are trivially copyable/movable themselves we found an inconsistency between Clang against both GCC and MSVC compilers.

A complete test case can be found here: https://godbolt.org/z/c38rYx8zq

The most reduced one I could find is this (https://godbolt.org/z/GeszesT6q):
```cpp
template <typename T>
struct Optional {
public:
    // Trivial copy/move constructors
    Optional(const Optional& other) noexcept requires(std::is_trivially_copy_constructible_v<T>) = default;
    Optional(Optional&& other) noexcept requires(std::is_trivially_move_constructible_v<T>) = default;

    // Non-Trivial copy/move constructors
    Optional(const Optional& other) requires(!std::is_trivially_copy_constructible_v<T>);
    Optional(Optional&& other) requires(!std::is_trivially_move_constructible_v<T>);

    // Trivial assignment operators
    Optional& operator=(const Optional& other) noexcept requires (std::is_trivially_copy_assignable_v<T>) = default;
    Optional& operator=(Optional&& other) noexcept requires (std::is_trivially_move_assignable_v<T>) = default;

    // Non-Trivial assignment operators
    Optional& operator=(const Optional& other) requires (!std::is_trivially_copy_assignable_v<T>);
    Optional& operator=(Optional&& other) requires (!std::is_trivially_move_assignable_v<T>);
};

// The following assertion works with GCC and MSVC, but not with Clang.
static_assert(std::is_trivially_copyable<Optional<int>>::value);
// This works on GCC, MSVC and Clang.
static_assert(!std::is_trivially_copyable<Optional<std::string>>::value);
```

We have reproduced this issue on Windows using Clang and the Microsoft STL, and as shown in Godbolt it also fail on Linux with Clang and stdlibc++. From our point of view it is a compiler bug in Clang.

I would be happy to help fix this, but I have no experience with Clang codebase.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy1Vltz6jYQ_jXmZecw2MbGPPiBQJNm5qR9OJmT6RMj2wtWj5AcSeaSX9-VHBOaCw2nLWOM0WX322_X-rZQ1SH_FYVQQTSHHQLTCFoJweUaVGvpq0HtJKjGciWZAL5pBG5QWuYGhvBQc4GwYT_cDtPSdr_luNyA1XzLmRAHKFVzYAUtZ7KCjdr655XSYA8N0sKaWQ_g7Y4guu7X2xo3BsWWNuzc7pZsMQlclkoabizK8gAF2h2ihLlgBIutGZfGQqFsDTfzufd_9-37nOxvGsKvzTAYLYLRrLvP_LhAS96Q9pXMIN0kmX12WKPGIJ5BbW1j6IHw0bVWVaGEHSq9pn9P9C3jTP-xz54eT83f10SYIrsaq7bECpREuCWfrahgxcm8Y62mWxBl_-ThBs0Tmvv0MYimblnnJx11V9k03YhFCohRQEE8d2xLtkG4D-JfumljdVta-L1PWzC56iaathC8PBoG-nRI4L5Lkk9Rlx7iiFLgLSltXjb0Vikav-BkIAVKCWrCDlLhvsTGsfLYco2GlhtbOdfxjJvlsSiWzuPy6IpTUSy3FJaPhgwF8QIqXLFW2CC-ehfGCYCfxODCvRDDGwZ_U_LLf83iCfAgCn-Gv0s5-4zH82x9zFDPDjOGr6U7dehkQc0-YiY9TlMCLiw3OF9vHQR2ebG9xvTp2vsYkKfzAkBnK-9_4PY0gvNV-H4Q_5LJT7k_w-ELb5PFKw77uqydEJBq7pzqkRXUDgrslP5BssRfyYzT1oLEVCrbTXpZGvZHLylpueyMnK1BL4Tx_Bh2POfSOsjucju2TLT4twB6uKQlHTYCScgcIK9_DuE5MGez9xbPcS296MTMeWy9Rp3y-4BQMzoCNTZadeLohZAb06ID_0DyqHYGWuOYf5Z36VYh3PFSK6NWFr7df3UhuglmwNSug-EUeaeewKnNEEbBinHhjH7lst2fZMZvpFgEL8oguqJrCNdabXxr0yjuXpUVbDnunCmCx46NBOV57VydktrdbykDTuALF2LTHMAqaiNEQ4q_90H2VXLbUSAV4J7qnVNDg6fgSlVhQR3JcIB5mKaTbBrFYTqo8riaxlM2sNwKzN_NFvFqWy2pGLQiS_SO0DHR2e5OZ-qTiHKnPM_kvT0bBq0W-auuhAy0xZA4oD9CbPufL5TEP7GkQrr2CaQQr5Msm4wGdT4uizSsplmSTJMoHJdhMs2mkzRmKQ2Oy_FAsAKFyYOE-I-ko9qZoOcgWQx4Ho2iKAxH2WgSJWEyLJNqytg4m4xjFo6zUTAe4YbSO3Q4XLs00LmHRPkxNCmoUzQvk12giN4d2WetrZXOZ3eLm2jgHece-F_riapD">