Why does a consteval function allow undefined behavior?

684 Views Asked by At

There is a very neat property of constant expressions in C++: their evaluation cannot have undefined behavior (7.7.4.7):

An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine ([intro.execution]), would evaluate one of the following:

  • ...

  • an operation that would have undefined behavior as specified in [intro] through [cpp] of this document [ Note: including, for example, signed integer overflow ([expr.prop]), certain pointer arithmetic ([expr.add]), division by zero, or certain shift operations — end note ] ;

Trying to store the value of 13! in a constexpr int indeed yields a nice compile error:

constexpr int f(int n) 
{
    int r = n--;
    for (; n > 1; --n) r *= n;
    return r;
}

int main() 
{
    constexpr int x = f(13);
    return x;
}

Output:

9:19: error: constexpr variable 'x' must be initialized by a constant expression
    constexpr int x = f(13);
                  ^   ~~~~~
4:26: note: value 3113510400 is outside the range of representable values of type 'int'
    for (; n > 1; --n) r *= n;
                         ^
9:23: note: in call to 'f(3)'
    constexpr int x = f(13);
                      ^
1 error generated.

(BTW why does the error say "call to 'f(3)'", while it is a call to f(13)?..)

Then, I remove constexpr from x, but make f a consteval. According to the docs:

consteval - specifies that a function is an immediate function, that is, every call to the function must produce a compile-time constant

I do expect that such a program would again cause a compile error. But instead, the program compiles and runs with UB.

Why is that?

UPD: Commenters suggested that this is a compiler bug. I reported it: https://bugs.llvm.org/show_bug.cgi?id=43714

1

There are 1 best solutions below

0
On BEST ANSWER

This is a compiler bug. Or, to be more precise, this is an "underimplemented" feature (see the comment in bugzilla):

Yup - seems consteval isn't implemented yet, according to: https://clang.llvm.org/cxx_status.html

(the keyword's probably been added but not the actual implementation support)