[Bug middle-end/21161] [6/7/8 Regression] "clobbered by longjmp" warning ignores the data flow
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=21161 --- Comment #15 from Bruno Haible --- > I think the following test case does show what Bruno was trying to prove. Yes, the test case from comment 14 much better reflects what this bug report is about, than the one from comment 13.
[Bug middle-end/21161] [6/7/8 Regression] "clobbered by longjmp" warning ignores the data flow
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=21161 --- Comment #14 from Peter Bergner --- (In reply to Peter Bergner from comment #13) > In case you haven't creduce'd the test case yet, here's what I got: Of course that's a totally bogus test case given what Bruno was trying to prove, namely that obj is never updated between the setjmp call and the call to longjmp, therefor we shouldn't get a warning. I think the following test case does show what Bruno was trying to prove. bergner@pike:~/gcc/BUGS/PR21161$ cat bug.c #include typedef struct { long a; } * b; b global_obj; void c (b obj) { jmp_buf env; if (setjmp(env) != 0) obj = global_obj; if (obj->a) longjmp (env, 1); } bergner@pike:~/gcc/BUGS/PR21161$ /home/bergner/gcc/build/gcc-fsf-mainline-debug/gcc/xgcc -B/home/bergner/gcc/build/gcc-fsf-mainline-debug/gcc -W -O1 -S bug.c bug.c: In function ‘c’: bug.c:7:6: warning: argument ‘obj’ might be clobbered by ‘longjmp’ or ‘vfork’ [-Wclobbered] c (b obj) ~~^~~
[Bug middle-end/21161] [6/7/8 Regression] "clobbered by longjmp" warning ignores the data flow
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=21161 Peter Bergner changed: What|Removed |Added CC||bergner at gcc dot gnu.org --- Comment #13 from Peter Bergner --- In case you haven't creduce'd the test case yet, here's what I got: bergner@pike:~/gcc/BUGS/PR21161$ cat pr21161.i extern int _setjmp (void); typedef struct { long a; } * b; extern void d (void); void c (b obj) { _setjmp(); if (((b)0)->a) obj = 0; if (((b)obj)->a) d(); } bergner@pike:~/gcc/BUGS/PR21161$ /home/bergner/gcc/build/gcc-fsf-mainline-debug/gcc/xgcc -B/home/bergner/gcc/build/gcc-fsf-mainline-debug/gcc -W -O1 -S pr21161.i pr21161.i: In function ‘c’: pr21161.i:5:6: warning: argument ‘obj’ might be clobbered by ‘longjmp’ or ‘vfork’ [-Wclobbered] c (b obj) ~~^~~
[Bug middle-end/21161] [6/7/8 Regression] "clobbered by longjmp" warning ignores the data flow
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=21161 Jeffrey A. Law changed: What|Removed |Added Assignee|unassigned at gcc dot gnu.org |law at redhat dot com --- Comment #12 from Jeffrey A. Law --- I've got something that is working on most targets. I'm still refining a bit, but I'm pretty confident we'll be able to fix in this cycle. As expected scanning RTL from the setjmp point to figure out where the longjmp will go (so that we can use the live-in set at the longjmp target rather than the live set at the setjmp point) is a bit hairy. It's almost certainly the case that the scanning is not going to work on all targets. For example MIPS inserts an unspec sequence to fiddle the GOT after the call and I really don't want to ignore an insn we don't understand. But again, what I've currently got works on most targets and there's still some refinements to do to improve coverage.
[Bug middle-end/21161] [6/7/8 Regression] "clobbered by longjmp" warning ignores the data flow
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=21161 --- Comment #11 from Jeffrey A. Law --- Just to record some thoughts. The implementation of the "clobbered by longjmp" warning essentially looks at the objects that are live at the setjmp point. In theory we can do better when we're dealing with setjmp/sigsetjmp (but not getcontext for example). In theory we can look at the code after the setjmp for this kind of pattern: (insn 15 14 21 2 (set (reg:SI 91 [ ]) (reg:SI 0 ax)) "j.c":18 86 {*movsi_internal} (expr_list:REG_DEAD (reg:SI 0 ax) (nil))) (insn 21 15 22 2 (set (reg:CCZ 17 flags) (compare:CCZ (reg:SI 91 [ ]) (const_int 0 [0]))) "j.c":18 7 {*cmpsi_ccno_1} (nil)) (jump_insn 22 21 23 2 (set (pc) (if_then_else (eq (reg:CCZ 17 flags) (const_int 0 [0])) (label_ref 28) (pc))) "j.c":18 672 {*jcc} (expr_list:REG_DEAD (reg:CCZ 17 flags) (int_list:REG_BR_PROB 719407028 (nil))) -> 28) Since in the longjmp case, we know this will fallthru, we look at the what's live-in in the fallthru successor. If the test were inverted we'd (of course) look at the live in of the target of the branch. THat live-in set is what we want to use to compute setjmp_crosses rather than what's actually live at the setjmp (which is overly-conservative as it is the union of what's live on both paths after the setjmp, only one of which we care about). The implementation would be somewhat gross. It'd have to account for the differences between setjmp/sigsetjmp and things like savectx, vfork, and getcontext. It might be somewhat fragile since we'd be matching a series of insns which could look radically different on some targets. *But* a proof of concept does seem to work. I'm going to try to polish that up. I haven't check if that addresses any of Florian's concerns from 61118. There's a reasonable chance it will. Alternately this could be done on gimple, but I suspect factoring of the abnormal dispatcher as well as the inaccurate CFG will kill us.
[Bug middle-end/21161] [6/7/8 Regression] "clobbered by longjmp" warning ignores the data flow
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=21161 Jeffrey A. Law changed: What|Removed |Added Target Milestone|--- |8.0