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

    <tr>
        <th>Summary</th>
        <td>
            [libc++][enhancement] Enable assertions unconditionally during constant evaluation
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            libc++
      </td>
    </tr>

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

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

<pre>
    Undefined behaviour when calling a library function is unspecified ([[expr.const]p(6.1)](https://eel.is/c++draft/expr.const#6.1). However, it is strange that whether it is detected depends on if libc++ is built with assertions or not.

Consider <https://godbolt.org/z/Kx6ez5no5>:

```c++
#include <vector>

constexpr int f() {
  std::vector<int> v;
 v.reserve(1);
  int& i = v.front();  // Library UB
 v.push_back(4);
  return i;
}

static_assert(f() == 4);
```

This doesn't compile with assertions:

```
<source>:11:15: error: static assertion expression is not an integral constant expression
   11 | static_assert(f() == 4);
      | ^~~~~~~~
/opt/compiler-explorer/clang-assertions-trunk-20240904/bin/../include/c++/v1/vector:652:5: note: subexpression not valid in a constant expression
  652 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/clang-assertions-trunk-20240904/bin/../include/c++/v1/__assert:66:71: note: expanded from macro '_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS'
   66 | # define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message) _LIBCPP_ASSERT(expression, message)
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/clang-assertions-trunk-20240904/bin/../include/c++/v1/__assert:23:10: note: expanded from macro '_LIBCPP_ASSERT'
   23 |        : _LIBCPP_ASSERTION_HANDLER(__FILE__ ":" _LIBCPP_TOSTRING(__LINE__) ": assertion " _LIBCPP_TOSTRING(            \
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 24 |              expression) " failed: " message "\n"))
      | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/clang-assertions-trunk-20240904/bin/../include/c++/v1/__assertion_handler:33:50: note: expanded from macro '_LIBCPP_ASSERTION_HANDLER'
   33 | # define _LIBCPP_ASSERTION_HANDLER(message) __builtin_verbose_trap("libc++", message)
      | ^~~~~~~~~~~~~~~~~~~~~~
<source>:6:12: note: in call to 'v.front()'
 6 |   int& i = v.front();  // Library UB
      | ^~~~~~~~~
<source>:11:15: note: in call to 'f()'
   11 | static_assert(f() == 4);
      |               ^~~
```

But does compile if assertions are disabled.

I believe libstdc++ does something like this, so this fails even without assertions enabled.

`if consteval` is not available in MSVC so this would have to be done with `__libcpp_is_constant_evaluated`/`__builtin_is_constant_evaluated`. This also removes the need for `[[maybe_unused]]` for variables used just for assertions.

The downside is the compile time would to increase on non-debug builds, where `LIBCPP_ASSERT(x)` goes from `(void) 0` to `is_constant_evaluated() && !(x) ? assert_handler(...) : (void) 0`. I haven't measured the actual impact, but I don't expect it to be much.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzEV1-T2rjy_TTipWtcRsYGHnhg-PNb6jeZ3crM7qtLthqsjZEoSfbM7MP97LdaNmBmk2ySeytXlSKDabW6T59uHwnn1EEjLlh6z9L1SDS-MnbxQXlRL11lPo0KI98Wv2uJe6VRQoGVaJVpLLxUqKEUda30AQTUqrDCvsG-0aVXRoNy0Gh3wlLtFUpgfBbOuMfXk41Ko51n6frE-CyLxozPWbpmfFZ5f3IsWTK-ZXyLWEfKMb4tGb9n_F5asff0_OqCJ932CH4xL9iiZXwFytPpzluhDwi-Ep6i9RXa_ieJHkuPEiSeUEsHFO-ecuhPIqOiUbWHF-UrEM6hpawcGAva-IjFaxYvu8-V0U5JtMCS1W0CByMLU_vI2APj278Y3_7_a4Z_pdqkLNmQ2cANy-LuXx9D_5QnSpd1I5Hct1h6Y2nvYGNAgjABpT3sCWk-BzbtPQA4L-msZHnevlLas2QDLUvORm1k0aFtkfFZqMflF_LKeAYKWLKGNtpbQw9mnRFAlyo89AT4_erx1LgqL0T5ifHZ5NanRd9YDeryiE3Xw5ycF16VeQc847NLVsmaorjxdgFu6OC5ojobdJrxqYfSHE-qxvfl_FIJ-q_JypnGltgVazymj5QlS0BrCccldHFePQLVAZ3rO0AbD0ITgniwooZQKqH9wOyMCIzHwKYr-J7MISzaxdLNv7p1ps3WnKhX-sTtHb6eamOpQbZlLfTh7orCnbeN_nTHYz6J5_GE8W2hNOPbKGJ827Pv2oWMb9sxffRkWmYpZ8ky4KKNxwBLUwyAIBRaUSsJSoP4GghZykM6-cPufvXbb_ny6Wnz8Tn_Y_mwW-ebh82HzeNzvlytNk9PAZYxHk_-rScjXwHjfEDPMJ5QUncLDcEU-qg5_ycc_3vrp1UkP7MmWWYZS5bT8bAm-HoSWqKEvTVHOIrSGmB8-k1QTy84ZVmHE0-geyd8Y60GteYrOKJz4oBUo9vtX7H8oVL9L7DnCc2J-LuxH8LMk5Bjv8jFre3u18f8l-Xj-mHzkfFZnm93D5s8J_6Hlw-_mD__-vT8cff4f8HqYfe4yfMwTYLhYG59YQ8MFktXP6NdvqGewCdDeLo15E1IEPZC1UivvvCtZ1JIPV3pfgT8nVffEcdP5JUyOq-EljXSyE2IYun3U-yGNle2JcnXm_qWbcPmzYNKUjpv0RbGYe6tOIXpy69qKkD9I6382dcwTbYxH6auOiEKPmR8q1AuWWY9Y35QzXwu1n9SCZ-Pb_8-sv_w1X-7Qnhf0UX3jQ-y6KKI1H4ob4VFkMqJokZ5I3J3UGCtsEVSyc7Ls1AOvpw5oq_oIlCrT6S4SbWvwJnwZ-hDB9iiDvrLNH54JOq_n8ayWO07oYCtqFkWX9RUK1RNGwjVD09_XE95MU0toRItEtAFgjS6F3wsi_Oc-Hg65crlZwGSk-9GeJQEEt8GszOhv2QXQZCWonYGLB5Niw58haCRes9YOqy76RzFW4F5oxuHkq436ZryIJNWWEU5OKDf4M_G-fD8ikp0q2UpmZdwyyAc6Lhz-bw6Yp-6N6B0aVE4hKC69J3EojmEm4wMFXmp0CJF-P6l-0rcymI4UDnDBAmQzFqjJFGQaBT4m8WfB6ZnKs-ouRgf9z6BJds-rcv44rOIZt4cusl8c0YEu1DCTrUfUbjGogwZi9I3ogZ1PInSUzJF42FHVQ62-HrC0tMFr6v-sSmraCQXiZwnczHCxXjK0zSbzCezUbWYJVKmY1HEcZHtp6kssIxjnvJkls1n0zgeqUU_qNPxPEkns2g2zcY4LrNiP99jyQWbxHgUqo7quj3SDW-knGtwMY6nkzQZ1aLA2oV79ftRmK5HdkG77orm4NgkrpXz7urHK1-HG_lgG9HnHnUldIlH1HR3hk1onGErNbo0Wir6Iur6DWRjqSmvgrsrlzJ61Nh68e6yqnzVFFFpjoxvKZj-v7uTNX8iQb4NGdKFvE-yXfB_BwAA__9nBBOc">