Нет предупреждения при возврате NULL с gcc

С помощью gcc 5.2.0, я заметил, что этот код не генерирует предупреждение:

#include <stddef.h>

int function(void)
{
    return NULL;
}

void procedure(void)
{
    return NULL;
}

Я использовал флаги -Wall -Wextra -std=c99 -pedantic и я использую archlinux Я не уверен, почему этот код работает на gcc, особенно с тех пор, как clang 3.7.0 генерирует предупреждение.

Я также пытался с более старыми версиями gcc как 4.9 или 4.7, и они оба генерируют предупреждения.

Предупреждения:

warning: return makes integer from pointer without a cast

а также

warning: ‘return’ with a value, in function returning void

Я должен упомянуть, что я попытался скомпилировать gcc 5.2 на Debian, и результат тот же. Таким образом, archlinux, похоже, не является проблемой.

Каково обоснование? Я не могу найти что-либо связанное с этим где-либо еще.

Спасибо!

3 ответа

Решение

Я заполнил отчет об ошибке здесь: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67730

Это было подтверждено и исправлено для 5.3, кажется!

Спасибо за вашу помощь.

Похоже, что это регрессия в gcc 5.2.0 - и, насколько я могу судить, странная.

С gcc 4.4.5 и 4.8.4 программа (после добавления необходимого #include <stddef.h>) выдает предупреждения обоим return NULL; операторы, даже без каких-либо дополнительных параметров командной строки.

С gcc 5.2.0 предупреждение не выводится даже при gcc -c -Wall -Wextra -std=c99 -pedantic, Для второго, который возвращает значение из void функция, диагностика обязательна.

Теперь вот странная часть.

$ gcc --version | head -n 1
gcc (GCC) 5.2.0
$ cat c.c
#include <stddef.h>

int function(void) {
#ifdef USE_NULL
   return NULL;
#else
    return ((void*)0);
#endif
}

void procedure(void) {
#ifdef USE_NULL
   return NULL;
#else
    return ((void*)0);
#endif
}
$ gcc -c c.c
c.c: In function ‘function’:
c.c:7:12: warning: return makes integer from pointer without a cast [-Wint-conversion]
     return ((void*)0);
            ^
c.c: In function ‘procedure’:
c.c:15:12: warning: ‘return’ with a value, in function returning void
     return ((void*)0);
            ^
$ gcc -c -DUSE_NULL c.c
$ 

когда USE_NULL определяется, предупреждения не выдаются. Компилирование с gcc -E -DUSE_NULL (который выводит вывод препроцессора в стандартный вывод) подтверждает, что NULL определяется как ((void*)0), Но когда я заменяю NULL с ((void*)0)предупреждения выдаются (как и должно быть).

Я не знаю, что происходит. Однажды макрос NULL был расширен, он должен быть неотличим от ((void*)0)и все же поведение компилятора меняется в зависимости от того, какой из них используется.

Действительность первой функции зависит от того, как NULL определено. Там нет проблем с первой функцией, если NULL определяется как 0, Но если это будет определено как (void *) 0 (что обычно имеет место в коде C) первая функция становится недействительной. GCC часто очень склонен к неявным преобразованиям указателя в целое число.

Вторая функция совершенно недействительна. В спецификации языка четко указано, что "оператор возврата с выражением не должен появляться в функции, тип возвращаемого значения void". Если он компилируется, это должен быть еще один пример того, как GCC чрезмерно допускает что-то.

Вам нужно запустить GCC в -pedantic режим, если вы хотите, чтобы его диагностический вывод был связан со стандартным языком C. В режиме по умолчанию это не заслуживающий доверия компилятор C (по крайней мере, в терминах его диагностического вывода), и тот факт, что он "не выдает предупреждение", абсолютно ничего не значит.

Однако в моих экспериментах я не мог заставить GCC жаловаться на вторую функцию даже при -std= а также -pedantic переключатели. Похоже, ошибка в компиляторе.

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