3 ms·
The standard explicitly disallows compiling of UB for constexpr. Otherwise, what you write is provably correct - UB is not statically decidable in all cases (
by DannyBee 4y ago
The standard explicitly disallows compiling of UB for constexpr.
Otherwise, what you write is provably correct - UB is not statically decidable in all cases (and depending on the type of UB, not even in a lot of cases).
- jenadine 4y agoUnless you used std::is_constant_evaluated() and the code running at runtime was not the one tested at compile time
- ithkuil 4y agoDoesn't it depend on the actual values? If your compile time evaluations don't trigger signed integer overflow (or any other UB) does it follow that at runtime you couldn't pass a parameter that would trigger signed overflow? I mean it's still useful because at least you know your test code is not artificially passing because of some UB makes it look like passing
- tialaramex 4y ago> it's still useful because at least you know your test code is not artificially passing because of some UB makes it look like passing Right, that's the extent of what this does. When I saw it on r/cpp I thought OK, somebody realised now they can make their C++ tests work as a reasonable person would expect, or perhaps realised that without this C++ tests are almost worthless because they can invoke Undefined Behaviour silently. But increasingly I suspect the OP mistook this for a breakthrough in correctness which it isn't, otherwise why post it to HN? On the other hand, the prohibition on UB for constexpr doesn't reach up to where IFNDR lives, so I'd guess most non-trivial C++ software is technically nonsense with no defined meaning as a result of IFNDR regardless of how many or few unit tests were written or whether they use constexpr to prohibit Undefined Behaviour. A cheerful thought. [Ill-Formed, No Diagnostic Required: A recurring statement in the C++ ISO document which basically says if you did this then too bad, that's not a well-formed C++ program, however your compiler may not notice that this isn't a C++ program, so, your program might compile, and even execute, but what if anything happens when you run it isn't specified in this ISO standard, good luck.]
- DannyBee 4y agoNo, it doesn't depend on the values. Yes, it does follow. The compiler is not allowed to compile constexpr code that could produce UB at runtime. period. :) That is, conditional constepxr code that depends on values and could produce UB is not valid constexpr code, and a compiler is not supposed to compile it. This is very explicit in the standard. Think of it as a statically decidable set of code. Now, it wouldn't shock me if compilers don't achieve this right now, but the standard is clear that constexpr code may not contain operations that could produce undefined behavior at runtime.
- simiones 4y agoThat is a complete misunderstanding. A constexpr function can very well take an input, and it can invoke UB based on the runtime value of that input. What the standard prohibits is compile-time evaluation of an expression which invokes UB. So, if you actually call your function at compile-time with a constexpr value that ends up invoking UB in the function (say, an integer overflow), THEN the standard mandates that the compiler throw an error rather than compiling some random value in. For example: constexpr void foo(int x) { std::cout << 1024 * 1024 * 1024 * x; } int main() { static_assert(foo(100)); // will fail because computing 1024 * 1024 * 100 is signed integer overflow, which is UB foo(100); // invokes UB at runtime; in practice, will perhaps print some overflowed value } Edit: I should also add that you can very well invoke UB in a constexpr expression if it is standard library UB and not core language UB (e.g. if you try to pop() from an empty std::vector).
- robotresearcher 4y agoYou're both right, but you're talking about different things. If you use the same values at run time as you use in the tests, the tests predict the behavior as desired. If you use different values at run time as you use in the tests, the tests do not predict the behavior as desired.
- tsimionescu 4y ago> You're both right, but you're talking about different things. The GP post is explicitly claiming that the values don't matter, and that per the standard a constexpr function should be guaranteed by the compiler to be incapable of producing UB (or else compilation should fail and it should not be allowed to be declared constexpr). This is simply false. Here is the GP statement: >> That is, conditional constepxr code that depends on values and could produce UB is not valid constexpr code, and a compiler is not supposed to compile it. [emphasis mine] > If you use the same values at run time as you use in the tests, the tests predict the behavior as desired. Even this is not fully guaranteed by the standard, as core constant expressions must only be guaranteed not to invoke core language UB. They may still be considered core constant expressions and evaluated at compile time even if they exhibit standard library UB (e.g. if they are not respecting some preconditions of an std::vector method).