21

I have a function like this:

#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) gives a warning:

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

Why???? I mean, obviously I don't care if x is clobbered or not, because it can't possibly be used after setjmp returns. Even the compiler should be aware of something so blindingly obvious, given that it has some kind of special knowledge of setjmp.

My main interest is finding bugs in a code base that I inherited, so, "use this coding style instead" is not advice I am looking for. However, there are a number of bizarre twists here. For example, if x is a local variable instead of a parameter, then GCC does not complain. Also, GCC will not complain without the if (some_global) line. Nice. Something is messing up GCC's flow analysis, or maybe GCC knows something I don't.

So,

  • Is there an easy way to suppress this warning for this function, just the same way you can cast unused parameters to (void)?

  • Or do I just suppress the warning project-wide?

  • Or am I missing something?

Update: Let me share with you a slightly different version that does not generate a warning:

#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);
}
Marc Mutz - mmutz
  • 24,485
  • 12
  • 80
  • 90
Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
  • I think the compiler is not smart enough. I've had to work around some similar stuff with MSVC++ not once when compiling with all warnings enabled and treated as errors. It's good the compiler can say something sometimes as it may save some time to other less knowledgeable and fortunate folks than us. – Alexey Frunze Oct 11 '11 at 07:55
  • my gcc (4.5.2) only complains if `-Wextra` is used (bringing in `-Wclobbered`). are you using either flag? – Hasturkun Oct 11 '11 at 12:04
  • @Hasturkun: It seems you have answered your question yourself. – Dietrich Epp Oct 12 '11 at 01:04
  • I don't get a warning with gcc 4.6.1. Might be a versions specifc issue. – sashang Oct 12 '11 at 02:43
  • @DietrichEpp: I'm asking because `-Wuninitialized` is documented as generating a similar warning, although I can't get gcc to generate that message otherwise – Hasturkun Oct 12 '11 at 18:42
  • If `x` is placed in a register rather than the stack, then `x` may be clobbered if the jump is taken. – jww Jun 05 '16 at 21:35
  • @jww: But `x` is never used if the jump is taken, so it is irrelevant whether it is clobbered (so the warning is unnecessary and unwanted). – Dietrich Epp Jun 05 '16 at 21:39

2 Answers2

16

After scraping the net a bit, and re-reading the GCC docs, I came across this:

Function Attributes:

returns_twice

The returns_twice attribute tells the compiler that a function may return more than one time. The compiler will ensure that all registers are dead before calling such a function and will emit a warning about the variables that may be clobbered after the second return from the function. Examples of such functions are setjmp and vfork. The longjmp-like counterpart of such function, if any, might need to be marked with the noreturn attribute.

So it appears that GCC does not have any "special knowledge" of setjmp, it just insinuates that it does. All it knows is that setjmp returns twice, not that it always returns 0 the first time and nonzero afterwards. Gosh, that would have been nice.

Community
  • 1
  • 1
Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
7

From man longjmp:

The values of automatic variables are unspecified after a call to longjmp() if they meet all the following criteria:

   ·  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.

As it happens, your x variable in the first example meets the criteria:

  • It is local to the function, as function parameters are just like local automatic variables.
  • Its value may be changed just after setjmp if some_global is true.
  • It is not volatile.

So its value may be unspecified (clobbered).

About why the second version does not emit the warning... no idea.

stm
  • 662
  • 1
  • 6
  • 23
rodrigo
  • 94,151
  • 12
  • 143
  • 190
  • 2
    It seems that you did not read my question. I explicitly said that I do not care whether x is clobbered, since it is not used after `setjmp` returns. I wish to know if there is a way to suppress the warning locally. – Dietrich Epp Oct 12 '11 at 01:02