Какой смысл в этих предупреждениях о засоренных переменных?

У меня есть такая функция:

#include <setjmp.h>
jmp_buf buf;
void func2(int g);
extern int some_global;
void func(int x)
{
    if (setjmp(buf))
        return;
    if (some_global)
        x += 5;
    func2(x);
}

GCC (gcc (Debian 4.4.5-8) 4.4.5) выдает предупреждение:

test.c: In function ‘func’:
test.c:5: warning: argument ‘x’ might be clobbered by ‘longjmp’ or ‘vfork’ [-Wclobbered]

Почему???? Я имею в виду, очевидно, меня не волнует, засоряется x или нет, потому что он не может быть использован после возврата setjmp. Даже компилятор должен знать о чем-то настолько очевидном, учитывая, что он имеет некоторые особые знания setjmp.

Мой главный интерес - поиск ошибок в кодовой базе, которую я унаследовал, поэтому «используйте вместо этого этот стиль кодирования» - это не совет, который я ищу. Однако здесь есть ряд причудливых поворотов. Например, если x - это локальная переменная, а не параметр, то GCC не жалуется. Кроме того, GCC не будет жаловаться без строки if (some_global). Хороший. Что-то мешает анализу потока GCC, или, возможно, GCC знает что-то, чего я не знаю.

So,

  • Есть ли простой способ подавить это предупреждение для этой функции, точно так же, как вы можете преобразовать неиспользуемые параметры в (void)?

  • Или я просто подавлю предупреждение во всем проекте?

  • Или я что-то упускаю?

Обновление. Позвольте мне поделиться с вами немного другой версией, которая не генерирует предупреждения:

#include <setjmp.h>
jmp_buf buf;
void func2(int g);
extern int some_global;
void func(int y)
{
    int x = y;
    if (setjmp(buf))
        return;
    if (some_global)
        x += 5;
    func2(x);
}

person Dietrich Epp    schedule 11.10.2011    source источник
comment
Я считаю, что компилятор недостаточно умен. Мне приходилось обходить подобные вещи с MSVC ++ ни разу при компиляции со всеми включенными предупреждениями и обработанными как ошибки. Хорошо, что компилятор иногда может что-то сказать, так как это может сэкономить время другим, менее знающим и удачливым людям, чем мы.   -  person Alexey Frunze    schedule 11.10.2011
comment
мой gcc (4.5.2) жалуется, только если используется -Wextra (ввод -Wclobbered). вы используете любой флаг?   -  person Hasturkun    schedule 11.10.2011
comment
@Hasturkun: Кажется, вы сами ответили на свой вопрос.   -  person Dietrich Epp    schedule 12.10.2011
comment
Я не получаю предупреждения с gcc 4.6.1. Возможно, проблема связана с конкретной версией.   -  person sashang    schedule 12.10.2011
comment
@DietrichEpp: я спрашиваю, потому что -Wuninitialized задокументирован как генерирующий подобное предупреждение, хотя в противном случае я не могу заставить gcc сгенерировать это сообщение   -  person Hasturkun    schedule 12.10.2011
comment
Если x помещается в регистр, а не в стек, то x может быть заблокирован, если выполняется переход.   -  person jww    schedule 06.06.2016
comment
@jww: Но x никогда не используется, если совершается прыжок, поэтому не имеет значения, заторможен ли он (так что предупреждение является ненужным и нежелательным).   -  person Dietrich Epp    schedule 06.06.2016


Ответы (2)


Немного поскребив сеть и перечитав документы GCC, я наткнулся на следующее:

Атрибуты функции:

returns_twice

Атрибут returns_twice сообщает компилятору, что функция может возвращать более одного раза. Компилятор перед вызовом такой функции гарантирует, что все регистры не работают, и выдаст предупреждение о переменных, которые могут быть сбиты после второго возврата из функции. Примеры таких функций: setjmp и vfork. longjmp-подобный аналог такой функции, если он есть, может потребоваться пометить атрибутом noreturn.

Таким образом, похоже, что GCC не имеет каких-либо специальных знаний о setjmp, он просто намекает на то, что он есть. Все, что он знает, - это то, что setjmp возвращается дважды, а не то, что он всегда возвращает 0 в первый раз и ненулевое значение впоследствии. Гоша, это было бы хорошо.

person Dietrich Epp    schedule 12.10.2011

От 1_:

Значения автоматических переменных не указываются после вызова longjmp (), если они соответствуют всем следующим критериям:

   ·  they are local to the function that made the corresponding setjmp(3)
      call;

   ·  their  values  are  changed  between  the  calls  to  setjmp(3)  and
      longjmp(); and

   ·  they are not declared as volatile.

Как оказалось, ваша переменная x в первом примере соответствует критериям:

  • Он является локальным для функции, так как параметры функции являются точно так же, как локальные автоматические переменные.
  • Его значение может быть изменено сразу после setjmp, если some_global истинно.
  • Не изменчив.

Таким образом, его значение может быть неопределенным (затертым).

Насчет того, почему вторая версия не выдает предупреждение ... понятия не имею.

person rodrigo    schedule 11.10.2011
comment
Похоже, вы не читали мой вопрос. Я прямо сказал, что меня не волнует, затирается ли x, поскольку он не используется после возврата setjmp. Я хочу знать, есть ли способ локально подавить предупреждение. - person Dietrich Epp; 12.10.2011