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

    <tr>
        <th>Summary</th>
        <td>
            [Clang] Unexpected results from `__reference_{constructs,converts}_from_temporary`
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            question,
            clang:frontend
      </td>
    </tr>

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

    <tr>
      <th>Reporter</th>
      <td>
          frederick-vs-ja
      </td>
    </tr>
</table>

<pre>
    It seems that the following `static_assert`'s should pass, but Clang currently rejects them ([link](https://www.godbolt.org/z/7Wec34cnT)).

```C++
static_assert(!__reference_constructs_from_temporary(void(&&)(), void()), "Normal function is treated as lvalue.");
static_assert(!__reference_converts_from_temporary(void(&)(), void()), "Normal function is treated as lvalue.");
static_assert(!__reference_constructs_from_temporary(void(&)(), void()), "Normal function is treated as lvalue.");
static_assert(!__reference_converts_from_temporary(void(&&)(), void()), "Normal function is treated as lvalue.");
static_assert(__reference_constructs_from_temporary(int&&, const int), "const int is adjusted to int");
static_assert(__reference_converts_from_temporary(int&&, const int), "const int is adjusted to int");
```

- Per [[expr.type]/2](https://eel.is/c++draft/expr.type#2), "`const int` prvalue" needs to be adjusted to "`int` prvalue", so there shouldn't be cv-qualification dropping and the binding to temporary object should be valid.
- For the (normal) function case, as `decltype(std::declval<Fun>())` is `Fun&` when `Fun` is a normal function type, the reference binding should be valid. But despite the binding being valid or not, there can never be a temporary and thus the traits should report `false`.

This probably doesn't block the library implementation of [P2255R2](https://wg21.lin/p2255r2) because workaround can be easily implemented.

----
Moreover, the results of these traits is a bit unclear to me for the following cases ([link](https://www.godbolt.org/z/jqrM3hvWP)):

```C++
struct Abstract {
  virtual void fun() = 0;
};

static_assert(__reference_constructs_from_temporary(Abstract&&, Abstract), "The code is so abstract.");
static_assert(__reference_converts_from_temporary(Abstract&&, Abstract), "The code is so abstract.");

static_assert(__reference_constructs_from_temporary(int(&&)[], int[]), "Array-of-unknown-bound prvalue?");
static_assert(__reference_converts_from_temporary(int(&&)[], int[]), "Array-of-unknown-bound prvalue?");
```

It seems that the abstractness of the class should be ignored in the spirit of [P0929R2](https://wg21.link/p0929r2) (so Clang is giving correct results for the `Abstract` case), but this doesn't seem clear in the current standard wording.

The case for `int[]` is really weird as there's no prvalue of type `T[]`.

CC @cjdb @cor3ntin @timsong-cpp
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzMV02P4jgT_jXmUgIFJwQ4cOiGF-k9zGq06tUcW45dgLuNnSk7Ydhfv7KTQNMzs9uz2_shReD483HVU09VhPd6bxFXbHbPZpuRaMLB0WpHqJC0fB63fvwkRpVT59X_A3jEo4dwEAHCAWHnjHEnbffAyswHEbR8FN4jBVZmjM89-INrjIJaeM_4GqomwNoIuwfZEKEN5gyETyhD3BWPwPiCze6Nts9stmF8cQih9iy_Y3zL-PZ0Ok32TlXOhImjPePbXxnfzj-hzAtpHxhfMr6csGzDsrv-t8y6Z834fXxS7y1UvmB8-vhIuENCK_FROusDNTL4xx2542PAY-1I0JnxReu0SivK9CxTexnvdhlZ9h2M858cHYWBXWNl0M6C9hAIRUAFwoNphWlwwjiPK_I3g2uR_gjav4LrTUb7r1rsn4H2VotpGwZUa0gTIXUNWC5dEYVQT42PMILrZv0IhO-Y5h0BXGLwZWCO4SMSJNW5xy81TcK5xhTzW_6t0Ec0E-0Z38oukBWJXYj9l7U851d4rMyuoMsMakruYZyDRVQ-Iq3wBni36qv5cUPvojoR9nJmGZ-HuFy248-NMHqnpUiUUOTqOuqhsCopZKWtiu_BwcW64KqoeIM2VgitMFpNBsNsHaW1jC9sohzjyyvrpPAYMQkfRVehNN3tFz6oaK38Lva1wrB8vW0sy_935XGZRW-xMosDvIzvpwPaoacbFmBfEb07YJ1AXbhzudrra8B9E0Chr3XAGxtUGH_TJHAE1oV-U0KQwoLFFil55YWtOkM2KT1AIKHDJakQ1o5CBL8TxiMrsxvpfzhoDzW5SlTmDMqh7_1mnHxO2xldpTP0sTZ4RBs6J7pd5OVHzmezn7_JxdOeTydGW8a3dZxFkXhQoRSNRzg5ehbkGqvSrSoEFF6bF8egugE6Ho_HXeuDI3Qt0tXYvjHBR0ThgP5igOSlSgdorDQoKNLrGNMxvUrLkSz-TyXVp8_0IT-0nz721Mnv3pJWo5rBXeUDCRmAzfsBgFZTaIRJuhqJ1XESWL6B7CoU8821_Zfkc4BwlbBrzyARDwcE6RRGa3oHop_wgwr-Hfl8RwDvkEheZLhU5kUAcaB_GQDdEYnz2O3GjX227mTHVWLxoIX59v0yy9-E6Jup5uu6dTC1RT8EF0gjvH8hZnpvHaECbdOwrzXpMGhDtuTL39eG5ygOcVonDlGfXV_6ag973abwdEQxEwxxPgQwK7MLXcqsl_zlUECHKGxXPYt3g04Geqx9bQ0-CKsEqShJUYFfySOmjdOhfeLrrN-lAUJhzBlOqCnVN0mnU01v3eCAZLtznQA_XFbfHLNeAysy-aSq9O8ot0Hb2A766J3dj2Vdj9QqV8t8KUa4ms7zLC_4YpaPDqtsKotK5VOu5tWsyJYLLKvFfLbY5XJailKM9IpnvJhm-TTjxTzPJ7PpQqmC43QuM7EsOCsyPAptJsa0x6hvI-19g6vptMiLYmREhcanrx_OPzfoYwbosn4scqK_WH63I2cDWhUHZpsRreJm46rZe1ZkRvvgr9sHHUz6nErOZrMN_GLxS40ylhkXR5M7RqO9jBg2v78GMuPrIYLYfPM6iMps1JBZ3TJvr8OhqSbSHRnfRjj937gmF-sNxrfp6rGI6m_frvhvAQAA__9VVnfe">