Почему переменные с квалификацией const принимаются в качестве инициализаторов в gcc?

При компиляции этого кода в последней версии gcc (или clang) с -std=c17 -pedantic-errors -Wall -Wextra

static const int y = 1;
static int x = y;

тогда я не получаю диагностического сообщения компилятора, хотя я вполне уверен, что это недействительный C, а нарушение ограничения. Мы можем доказать, что это не соответствует требованиям, посмотрев на C17 6.7.9 / 4:

Ограничения
...
Все выражения в инициализаторе для объекта, который имеет статическую продолжительность или продолжительность хранения потока, должны быть константными выражениями или строковыми литералами.

Затем определение константных выражений, в данном случае целочисленное постоянное выражение (6.6):

Целочисленное константное выражение должно иметь целочисленный тип и содержать только операнды, которые являются целочисленными константами, константами перечисления, символьными константами, выражениями sizeof, результатами которых являются целочисленные константы, выражения _Alignof и плавающие константы, которые являются непосредственными операндами. слепков.

И, наконец, определение целочисленных констант (6.4.4.1/2):

Целочисленная константа начинается с цифры, но не имеет периода или экспоненты. Он может иметь префикс, определяющий его основу, и суффикс, определяющий его тип.

Таким образом, переменная const int не является ни целочисленной константой, ни выражением целочисленной константы. Следовательно, это недопустимый инициализатор. Это обсуждалось ранее (например, здесь), и я думаю, что уже установлено, что это не соответствует требованиям. Однако мой вопрос:

Почему gcc решил не соответствовать требованиям даже в строгом режиме?

clang, по-видимому, всегда был несовместимым, но gcc изменился с совместимого в версии 7.3 на несовместимый в версии 8.0 и выше. gcc 7.3 и ранее выдает ошибку: элемент инициализатора не является постоянным даже в режиме по умолчанию без -pedantic-errors.

Похоже, что в отношении этого сообщения было принято какое-то активное, осознанное решение. Почему он был полностью удален в gcc и почему его не оставили как было при компиляции в строгом режиме -std=c17 -pedantic-errors?


person Lundin    schedule 05.07.2021    source источник
comment
Если кто-нибудь сможет найти объяснение, почему clang решил не соответствовать требованиям, это тоже было бы интересно. Я сохраняю этот вопрос специально для gcc, чтобы не задавать сразу два вопроса.   -  person Lundin    schedule 05.07.2021
comment
Отвечает ли это на ваш вопрос? Почему элемент инициализатора не является константой ... . больше не работает?   -  person Alex Lop.    schedule 05.07.2021
comment
@jdm опубликовал комментарий в вопросе, заданном KamilCuk, который ссылается на эту ошибку gcc: gcc.gnu.org/bugzilla/show_bug.cgi?id=69960, который, я думаю, отвечает на ваш вопрос, документируя обсуждение.   -  person Paul Hankin    schedule 05.07.2021
comment
@AlexLop. Нет, это не отвечает на вопрос, почему gcc решил не соответствовать требованиям даже в строгом режиме? Как упоминалось в вопросе, мы уже установили, что это не соответствует требованиям, я не об этом спрашиваю.   -  person Lundin    schedule 05.07.2021
comment
@PaulHankin Не совсем, это просто различные более или менее запутанные случайные комментарии. Компиляторам не разрешено молча игнорировать нарушения ограничений.   -  person Lundin    schedule 05.07.2021
comment
В частности, -std=c17 -pedantic-errors должен быть строгим режимом. Я не компилирую -std=gnu17 и не хочу, чтобы присутствовали какие-либо расширения компилятора.   -  person Lundin    schedule 05.07.2021
comment
Расширенное обсуждение взад-вперед было заархивирован в чате. Оставляйте комментарии по их прямому назначению: предлагать улучшения и / или запрашивать разъяснения по вопросу.   -  person Cody Gray    schedule 06.07.2021


Ответы (1)


Почему gcc решил не соответствовать требованиям даже в строгом режиме?

Поскольку поставленный вопрос направлен на мотивацию разработчиков, единственная информация, которую мы должны продолжить, поскольку третьи стороны, исходит из общедоступных артефактов разработки, таких как ошибка GCC, сообщения фиксации репозитория и фактический код. Как было указано в комментариях, этот вопрос обсуждается в ветке комментариев Bugzilla, связанной с изменить.

Обсуждение Bugzilla, похоже, показывает, что разработчики учли требования стандарта в этой области, хотя и несколько поверхностно. См., В частности, комментарии 9 и 10. Они поднимают параграф 6.6 / 10 спецификации языка:

Реализация может принимать другие формы константных выражений.

Они не подвергают это какому-либо особому анализу, и я читаю комментарии скорее как поиск оправдания для изменения, чем как вдумчивое исследование соображений соответствия GCC.

Таким образом, они внесли изменение, потому что они хотели реализовать запрос функции, и они нашли достаточное (для них) обоснование на языке стандарта, чтобы считать измененное поведение совместимым с языковыми ограничениями, поэтому не требуя диагностики.


Существует также подразумеваемый вопрос о том, действительно ли недавнее молчаливое принятие GCC представленных форм декларации нарушает обязательство соответствующих процессоров диагностировать нарушения ограничений.

Хотя можно интерпретировать 6.6 / 10 как разрешение реализациям принимать любые выражения, которые они выбирают как соответствующие требованиям для любого вида константного выражения, это кажется чревато. Удовлетворяет ли данный фрагмент кода ограничениям языка, не должно зависеть от реализации. Любая из этих интерпретаций, если она будет принята, решит эту проблему:

  • 6.6 / 10 следует интерпретировать как конкретный случай общего правила, согласно которому соответствующая реализация может принимать несоответствующий код, не подразумевая, что это дает право процессору рассматривать код как соответствующий.

  • 6.6 / 10 следует интерпретировать как разрешение процессорам интерпретировать больше выражений как константных выражений, чем те, которые описаны в предыдущих параграфах, но это не имеет отношения к определениям конкретных видов константных выражений, определенных в этих параграфах (целочисленные константные выражения и арифметические константы выражения).

Они не исключают друг друга. Я подписываюсь на последнее, как я уже писал ранее, и, как правило, предпочитаю и первое.

person John Bollinger    schedule 05.07.2021
comment
Итак, у нас есть несколько конкурирующих объяснений этой фразы, все в той или иной степени правдоподобны. Какова бы ни была реальная цель стандарта, его формулировка неаккуратна и должна быть исправлена. - person n. 1.8e9-where's-my-share m.; 05.07.2021
comment
Удовлетворяет ли данный фрагмент кода ограничениям языка, не должно зависеть от реализации. Позволю себе не согласиться. int main(void) { int x[sizeof(long)-5]; } не может быть проанализировано на соответствие независимым от реализации способом. - person n. 1.8e9-where's-my-share m.; 05.07.2021
comment
Предположим, что стандарт разрешает реализации принимать улучшенные константные выражения (которые не являются целочисленными или арифметическими константными выражениями). Что означает такое разрешение без перечисления контекстов, в которых эти выражения разрешены, а другие - нет? Если реализации также разрешено определять для них допустимые контексты, это фактически то же самое, что и разрешение менее ограниченных целочисленных / арифметических константных выражений, за исключением того, что новые должны называться по-другому. - person n. 1.8e9-where's-my-share m.; 05.07.2021
comment
@ n.1.8e9-where's-my-sharem., имеет смысл принять гипотетические улучшенные константные выражения, потому что существует множество контекстов, которые требуют константного выражения без указания целочисленного константного выражения или арифметического константного выражения. Нет необходимости указывать конкретные контексты, в которых могут использоваться только улучшенные константные выражения. - person John Bollinger; 05.07.2021