Почему функция conteval допускает неопределенное поведение? - PullRequest
16 голосов
/ 18 октября 2019

В 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. Согласно docs :

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

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

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

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

1 Ответ

2 голосов
/ 19 октября 2019

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

Yup - кажется, что conteval еще не реализован, согласно:https://clang.llvm.org/cxx_status.html

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

...