Чому констатаційна функція дозволяє визначати не визначену поведінку?


16

В 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.

(BTW чому помилка говорить "виклик до 'f (3)'", тоді як це дзвінок до f (13)? ..)

Потім я видаляю constexprз x, але зробити . Згідно з документами :fconsteval

consteval - визначає, що функція є безпосередньою функцією, тобто кожен виклик функції повинен виробляти константу часу компіляції

Я очікую, що така програма знову призведе до помилки компіляції. Але натомість програма компілює та працює з UB .

Чому так?

UPD: Коментатори припустили, що це помилка компілятора. Про це я повідомив: https://bugs.llvm.org/show_bug.cgi?id=43714


2
in call to 'f(3)'- це дивно! Вих. Якщо поставити f(123)кланг попереджає про in call to 'f(119)'.
KamilCuk

Я думаю, це просто помилка. У стандарті зрозуміло, що "негайне виклик має бути постійним виразом". Однак можливо також, що відбувається щось складніше (тобто, можливо, цю вимогу буде знято, і Кланг реалізує нову поведінку).
Брайан

3
Помилка компілятора. Тут нічого не бачити, рухайтеся.
ТК

1
@JesperJuhl Готово.
Михайло

4
Цілиці @StoryTeller є доповненням двох, але переповнення все ще не визначене.
Баррі

Відповіді:


2

Це помилка компілятора. Або, якщо бути точнішим, це "недооцінена" функція (див . Коментар у багзіллі ):

Так, здається, що констеваль ще не реалізований відповідно до: https://clang.llvm.org/cxx_status.html

(ключове слово, мабуть, додано, але не фактична підтримка впровадження)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.