Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do compilers know C++ constexpr computations do not trigger undefined behavior?

The C++ standard mandates compilers to check for undefined behavior in C++ constexpr computations.

In this talk, Chandler Carruth states that "you will run out of the ability to detect errors" when checking for UB, and that in the general case, detecting UB is related to the halting problem, so provably impossible to decide.

He is not talking about UB in constexpr, but constexpr computations are as general as a regular programs since C++14, so this still applies.

So what do compilers do when they cannot decide if a program is UB or not? Do they still accept the program and go on compiling with fingers crossed? Or are they more conservative and reject the program, even if it is potentially correct? (My personnal feeling is they do that)

For me, this is of practical importance since I have a constexpr evaluation with non-trivial pointer arithmetics compiling fine with Clang but failing with GCC, and I am pretty sure this not UB. You can say it is a GCC bug, but if UB is undecidable, all compilers are and will be buggy in this regard.

More fundamentally, why is UB-free requested by the standard? Is there a technical reason? Or more a philosophical one ("if the compiler can't check, the programmer can trigger UB, and bad things will result")?

I think this is inconsistent with the rest of C++ that never prevents you from shooting yourself in the foot. I would prefer GCC to accept my constexpr code and crash, or emit trash if UB; rather than not compiling when it does not know if it is UB.

====== EDIT ======

As pointed out by M.M and Nicol Bolas, the standard specifies limitations (even in C++14) so that we are never in a halting problem type of UB. However, I am still wondering if checking for UB is maybe too complex and if compiler heuristics fail, then they flag it (potentially incorrectly) as non-constexpr.

But I have the feeling from the comments that this is more a problem of non-mature implementations.

like image 347
Bérenger Avatar asked Mar 03 '23 06:03

Bérenger


1 Answers

The point you are missing is that constant expressions only allow for a restricted subset of the language.

If you go outside that, you no longer have a constant expression, and if you are in a context needing one the standard mandates diagnosing the error.

A constexpr-function only has to have at least one input where it is a constant expression, no diagnostic required. All the rest might not be.

In the general case, compilers just note paths leading to UB to prune presumably dead code, and explore the freedom they have in optimizing what remains. They are not required to find all, most, or even any of those opportunities though.

like image 139
Deduplicator Avatar answered May 10 '23 23:05

Deduplicator