| Issue |
107453
|
| Summary |
[libc++][enhancement] Enable assertions unconditionally during constant evaluation
|
| Labels |
libc++
|
| Assignees |
|
| Reporter |
MitalAshok
|
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.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs