Почему gcc предупреждает о decltype (main()), но не clang?

Возьмите следующий код:

int main()
{
    decltype(main()) x = 0;
    return x;
}

gcc жалуется:

main.cpp: In function 'int main()':
main.cpp:8:19: warning: ISO C++ forbids taking address of function '::main' [-Wpedantic]
     decltype(main()) x = 0;
                   ^
main.cpp:8:19: warning: ISO C++ forbids taking address of function '::main' [-Wpedantic]

но не clang. Так что насчет decltype(main()) вызывает эту ошибку? Как decltype берет адрес основного?

Ответы

Ответ 1

Диагностика GCC может быть неправильно сформулирована в этом случае, потому что decltype не нужно знать адрес main; он должен знать только его тип. Однако предупреждение основано на следующем стандарте (§3.6.1/3):

Функция main не должна использоваться в программе.

Я предполагаю, что GCC интерпретирует это как означающее, что вы даже не можете использовать его в неоцениваемом выражении.

Clang (версия 3.4 в любом случае), похоже, вообще не реализует это правило, даже если я включу все флаги, о которых я могу думать, и даже если main вызывает себя рекурсивно. Вот почему это не дает вам предупреждения.

Ответ 2

Этот вопрос на самом деле появился недавно в undefined группе обсуждения по исследованию поведения по умолчанию в потоке Что означает "функция main не должна использоваться внутри программы" означает?. Это не сразу, но здесь начинается там, где указан следующий оператор:

Я не думаю, что decltype (main()) является odr-use, или SizeOf (decltype (основной)).

очень сокращенный набор ответов выглядит следующим образом:

Правда, я просто не понимаю, какая это будет. Вы могли бы означать sizeof (decltype (& main)) в последнем случае.

Я думаю, что наиболее распространенное использование ODR без использования ODR будет определять его после передовая декларация, и теперь Стивен Кламаж пояснил, что должны быть плохо сформированы. Более широкое определение "использования" как результат поиска имени без ссылки на ODR выглядит корректно.

и

У С++ 98 упоминание "use" имело перекрестную ссылку на 3.2 [basic.def.odr]. С++ 11 больше не имеет перекрестной ссылки и не был изменен, чтобы сказать "odr-use", поэтому я ожидаю, что это означает любое использование.

и, как представляется, интерпретация раздела 3.6.1 Основная функция, которая гласит:

Функция main не должна использоваться внутри программы. [...]

означает любое использование даже в необоснованных контекстах и ​​поэтому gcc здесь является правильным, чтобы создать ошибку, хотя само сообщение не имеет смысла.

Обновить

Интересно и поучительно отметить, что оригинальное предложение : N3154, чтобы исправить Отчет о дефектах 1109 изменил бы 3.6.1 на:

Функция main не должна использоваться в качестве параметра (3.2) в программе....

который допустил бы пример decltype, но был изменен, если принят, и мы видим, что новый предложение: N3214 изменилось на то, что у нас есть сегодня:

Функция main не должна использоваться в программе

который будет строго указывать на мнение в списке рассылки UB, что любое использование main плохо сформировано, действительно верно.