clang говорит, что вызов функции void consteval не является постоянным выражением

Clang (trunk) выдает ошибку для следующего кода:

consteval void f() {}

int main() 
{ 
    f();  // error: call to consteval function 'f' is not a constant expression
          // note: subobject of type 'void' is not initialized
}

в то время как gcc(trunk) компилирует это без ошибок.

Я считаю, что это, вероятно, ошибка clang, поскольку и gcc, и clang принимают этот код:

consteval int g() { return 42; }

int main() 
{ 
    g();  // ok
}

Вот код, с которым можно поиграть.

Так это ошибка clang, или код плохо сформирован, или есть ub, или что-то еще?


Изменить: я чувствую, что может быть уместно указать, что clang позволяет звонить fот других функций, если они также состоят. Это дает ошибку только тогда, когдаf вызывается из неконстевальных функций:

consteval int h() 
{ 
    f();       // ok
    return 42; 
}

демо.

1 ответ

Это была ошибка Clang, которая появилась между версиями 10 и 11 и исправлена ​​в прошлом месяце. Реализация consteval в Clang в основном, но не полностью, и эта ошибка возникла после того, как один из патчей добавил более полный consteval служба поддержки.

Подробности: точка входа верхнего уровня в оценщик констант Clang проверяет, является ли результат допустимым результатом константного выражения - он проверяет, не содержит ли результат указателей на продолжительность автоматического хранения, временную или аналогичную. Но эта проверка никогда не обновлялась, чтобы учесть void быть буквальным типом и отклонять значения типа voidза то, что он "неинициализирован". Этого никогда не замечалось до добавления consteval поддержки, потому что все постоянные оценки верхнего уровня неvoid типы.

Я обнаружил, что окончательный вариант С ++20:

9.2.5 Спецификаторы constexpr и consteval [dcl.constexpr] (2) Спецификатор constexpr или consteval, используемый в объявлении функции, объявляет, что эта функция является функцией constexpr. Функция или конструктор, объявленный с помощью спецификатора consteval, называется анимированной функцией. Деструктор, функция распределения или функция освобождения не должны объявляться с помощью спецификатора consteval.

(3) Определение функции constexpr должно удовлетворять следующим требованиям:

3.1 его возвращаемый тип (если есть) должен быть буквальным;

а также

6.8 Типы [basic.types]

(10) Тип является буквальным, если он:

(10.1) резюме недействительно

...

Как это void допустимый тип возвращаемого значения для consteval функция.

Другие вопросы по тегам