Логическое ИЛИ: второй операнд не вычисляется (6.5.14.4), но компилятор выдает предупреждение: нарушение стандарта?

ISO / IEC 9899: рабочий проект 202x (E) - 5 февраля 2020 г. C17..C2x N2479:

6.5.14 Оператор логического ИЛИ:

  1. Если первый операнд не равен 0, второй операнд не оценивается.

Контекст: существует один компилятор C, который выдает предупреждение condition is always true / false для выражений, содержащих логические операторы. Например, если в выражении a || b переменная b равна unequal to 0, компилятор генерирует condition is always true (с указанием позиции b в исходном коде).

Вопрос: Можно ли факт формирования такого предупреждения интерпретировать как нарушение 6.5.14.4? Пожалуйста, предоставьте объяснение / аргументацию / ссылки.

Примечание: gcc / clang / cl (настроенный с наивысшим уровнем предупреждений) не генерирует никаких предупреждений для приведенного выше примера.

UPD. MRE:

int main(void)
{
    int c1 = 1, c2 = 1, r = 0;
    if ( c1 || c2 ) { r = 1; }
    return r;
}
$ cc x.c
x.c:4:10: warning: condition is always true
x.c:4:16: warning: condition is always true

person pmor    schedule 23.11.2020    source источник
comment
Покажите минимальный воспроизводимый пример, демонстрирующий предупреждение. Но в целом его генерирует статический анализатор, а не среда выполнения. Так что нет, это не может быть истолковано как стандартное нарушение.   -  person Eugene Sh.    schedule 24.11.2020
comment
Компиляторам разрешено рассказывать вам о вещах, которые, хотя и законны, могут не соответствовать вашим намерениям. Распространенным случаем является присваивание в операторе if (if (x = 3)), которое, хотя и совершенно законно, часто не соответствует замыслу программиста.   -  person 1201ProgramAlarm    schedule 24.11.2020
comment
Предупреждение компилятора не является наблюдаемым эффектом оценки.   -  person Language Lawyer    schedule 24.11.2020
comment
5.1.1.3 примечание 9: Цель состоит в том, что реализация должна идентифицировать природу и, где это возможно, локализовать каждое нарушение. Конечно, реализация может производить любое количество диагностик, пока действующая программа все еще правильно переведена. Он также может успешно перевести недопустимую программу. Курсив добавлен.   -  person user3386109    schedule 24.11.2020
comment
Какой компилятор на какой платформе выдает эти предупреждения? Компилятор не ошибается - оба условия условия всегда верны. Неважно, оценивает он их или нет. Это может уменьшить код до int main(void) { return 1; } - вероятно, так и будет, если будет вообще какая-то оптимизация.   -  person Jonathan Leffler    schedule 24.11.2020
comment
Вы не должны цитировать абзацы с разделителем периода так же, как пункты, потому что это не позволяет различить некоторые пункты и абзацы, такие как пункт 6.5.1 и пункт 1 пункта 6.5.   -  person Eric Postpischil    schedule 24.11.2020
comment
@LanguageLawyer (и другие): может ли компилятор выдавать диагностику или нет, не является проблемой как таковой. Проблема в том, что для того, чтобы решить, выдавать ли такое предупреждение, компилятор должен попытаться оценить второй операнд и, если предупреждение должно быть выдано, добиться успеха (и определил, что это было 1), но все же 6.5.14 4 запрещает оценку второго операнда (если первый не равен нулю).   -  person Eric Postpischil    schedule 24.11.2020
comment
@EricPostpischil Проблема в том, что для того, чтобы решить, выдавать ли такое предупреждение, компилятор должен попытаться оценить второй операнд. Если компилятор выдает ошибку для int main(void) { return 0 || x; }, означает ли это, что он оценивает второй операнд?   -  person Language Lawyer    schedule 24.11.2020
comment
Просто любопытно: есть ли предупреждение, если вы измените c1 = 1 на c1 = 0? Кстати, какой компилятор C вы используете?   -  person Jabberwocky    schedule 24.11.2020


Ответы (1)


Хотя можно утверждать, что единственный способ, которым компилятор мог узнать значение второго операнда ||, заключался в его оценке, а это нарушает запрет на оценку в C 2018 6.5.14 4 («… Если первый операнд || сравнивает неравно с 0, второй операнд не оценивается ») если первый операнд сравнивается с неравным 0, подразумевается, что« оценка »относится к оценкам, сделанным во время выполнения программы, а не к преобразованию. Концептуальные модели C, описанные в C 2018 5.1, отделяют перевод и выполнение. 6.5.14 4 - запрет на оценку во время выполнения программы, а не во время перевода.

person Eric Postpischil    schedule 24.11.2020