Почему функция conteval допускает неопределенное поведение?

В C++ есть очень аккуратное свойство константных выражений: их оценка не может иметь неопределенное поведение (7.7.4.7):

Выражение e является основным константным выражением, если при вычислении e, следуя правилам абстрактной машины ([intro.execution]), не будет выполнено одно из следующих действий:

  • ...

  • операция, которая будет иметь неопределенное поведение, как указано в [intro] - [cpp] этого документа [Примечание: включая, например, целочисленное переполнение со знаком ([expr.prop]), определенную арифметику указателя ([expr.add]), деление на ноль или определенные операции смены - примечание конца];

Попытка сохранить значение 13! в constexpr int действительно приводит к приятной ошибке компиляции:

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;
}

Выход:

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.

(Кстати, почему ошибка говорит "вызов f (3)" ", в то время как это вызов f (13)?..)

Затем я удаляю constexpr из x, но делаю f a consteval. Согласно документам:

consteval - указывает, что функция является непосредственной функцией, то есть каждый вызов этой функции должен создавать константу времени компиляции

Я ожидаю, что такая программа снова вызовет ошибку компиляции. Но вместо этого программа компилируется и запускается с UB.

Почему это так?

UPD: Комментаторы предположили, что это ошибка компилятора. Я сообщил об этом: https://bugs.llvm.org/show_bug.cgi?id=43714

Ответы

Ответ 1

Это ошибка компилятора. Или, если быть более точным, это "недопустимая" функция (см. комментарий в bugzilla):

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

(ключевое слово, вероятно, было добавлено, но не фактическая поддержка реализации)