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
функция.