https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63748
Manuel López-Ibáñez <manu at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |manu at gcc dot gnu.org Depends on| |24639 Summary|[4.9/5 Regression] may be |[4.9/5 Regression] wrong |used uninitialized warning |may be used uninitialized |on variable definition with |warning (abnormal edges) |initializer | --- Comment #5 from Manuel López-Ibáñez <manu at gcc dot gnu.org> --- (In reply to Ulrich Weigand from comment #4) > Huh? No matter what, "buf" is in fact never used uninitialized in this > function, and that should be trivial to see; the only use of "buf" occurs in > line 17 immediately after the definition of "buf" in line 16, whether any > longjmp is ever called or not. > > Also, if any of the gotos in this function is removed, the warning > disappears. The problem seems to be related to some call-graph > optimizations (note that the if (noside) check is partially redundant). The problem arises because we create PHI nodes with default definitions of buf for the basic block created by the gotos. For example: ;; basic block 6, loop depth 0, count 0, freq 0, maybe hot ;; prev block 5, next block 7, flags: (NEW, REACHABLE) ;; pred: 3 (ABNORMAL) ;; 8 (ABNORMAL) ;; starting at line -1 # argvec_2(ab) = PHI <[test.c:9:9] argvec_13(ab)(3), argvec_3(ab)(8)> # buf_5(ab) = PHI <buf_18(D)(ab)(3), buf_6(ab)(8)> # .MEM_9(ab) = PHI <.MEM_16(ab)(3), .MEM_25(ab)(8)> # .MEM_20(ab) = VDEF <.MEM_9(ab)> # USE = anything # CLB = anything ABNORMAL_DISPATCHER (0); ;; succ: 5 (ABNORMAL) and no subsequent optimization is able to realize that those PHI nodes are never used or to remove the edges as unreachable. I think this is some issue with how the call-graph is built. A simplified version of 015t.ssa: test (intD.6 opD.1753, intD.6 nosideD.1754) { ;; basic block 2, loop depth 0, count 0, freq 0, maybe hot ;; pred: ENTRY (FALLTHRU) ;; starting at line 9 [test.c:11:6] if (op_14(D) != 0) goto <bb 3>; else goto <bb 10>; ;; basic block 3, loop depth 0, count 0, freq 0, maybe hot ;; pred: 2 (TRUE_VALUE) ;; starting at line 13 [test.c:13:16] # .MEM_16(ab) = VDEF <.MEM_15(D)> _17 = alloc_jmp_bufD.1750 (); ;; succ: 4 (FALLTHRU) ;; 6 (ABNORMAL) ;; basic block 4, loop depth 0, count 0, freq 0, maybe hot ;; pred: 3 (FALLTHRU) ;; starting at line 13, discriminator 1 [test.c:13:16] buf_19 = _17; ;; succ: 5 (FALLTHRU) ;; basic block 5, loop depth 0, count 0, freq 0, maybe hot ;; pred: 4 (FALLTHRU) ;; 6 (ABNORMAL) ;; starting at line 14 # buf_4(ab) = PHI <[test.c:13:16] buf_19(4), buf_5(ab)(6)> setjmpD.1749 (buf_4(ab)); [test.c:16:10] if (noside_22(D) != 0) goto <bb 11> (nosideret); else goto <bb 7> (do_call_it); ;; succ: 11 (TRUE_VALUE) ;; 7 (FALSE_VALUE) ;; basic block 6, loop depth 0, count 0, freq 0, maybe hot ;; pred: 3 (ABNORMAL) ;; 8 (ABNORMAL) ;; starting at line -1 # buf_5(ab) = PHI <buf_18(D)(ab)(3), buf_6(ab)(8)> ABNORMAL_DISPATCHER (0); ;; succ: 5 (ABNORMAL) ;; basic block 7, loop depth 0, count 0, freq 0, maybe hot ;; pred: 5 (FALSE_VALUE) ;; 10 (FALLTHRU) ;; starting at line 21 # buf_6(ab) = PHI <buf_4(ab)(5), buf_18(D)(ab)(10)> do_call_itL.2: [test.c:21:10] if (noside_22(D) != 0) goto <bb 11> (nosideret); else goto <bb 8>; ;; succ: 11 (TRUE_VALUE) ;; 8 (FALSE_VALUE) ;; basic block 8, loop depth 0, count 0, freq 0, maybe hot ;; pred: 7 (FALSE_VALUE) ;; starting at line 24 _26 = fooD.1752 (argvec_3(ab)); ;; succ: 9 (FALLTHRU) ;; 6 (ABNORMAL) ;; basic block 9, loop depth 0, count 0, freq 0, maybe hot ;; pred: 8 (FALLTHRU) ;; starting at line 24, discriminator 1 [test.c:24:14] _27 = _26; [test.c:24:14] goto <bb 12>; ;; succ: 12 (FALLTHRU) ;; basic block 10, loop depth 0, count 0, freq 0, maybe hot ;; pred: 2 (FALSE_VALUE) ;; starting at line 27 argvec_24 = allocaD.858 (1); [test.c:28:3] goto <bb 7> (do_call_it); ;; succ: 7 (FALLTHRU) ;; basic block 11, loop depth 0, count 0, freq 0, maybe hot ;; pred: 5 (TRUE_VALUE) ;; 7 (TRUE_VALUE) ;; starting at line 31 nosideretL.5: [test.c:31:10] _28 = 1; ;; succ: 12 (FALLTHRU) ;; basic block 12, loop depth 0, count 0, freq 0, maybe hot ;; pred: 9 (FALLTHRU) ;; 11 (FALLTHRU) ;; starting at line -1 # _7 = PHI <[test.c:24:14] _27(9), [test.c:31:10] _28(11)> return _7; ;; succ: EXIT } which is more or less: test (intD.6 opD.1753, intD.6 nosideD.1754) { bb1: if (op_14(D) != 0) { try { _17 = alloc_jmp_bufD.1750 (); [test.c:13:16] buf_19 = _17; goto bb5; } catch { goto bb6; } } else { argvec_24 = allocaD.858 (1); [test.c:28:3] goto do_call_it; } bb5: # buf_4(ab) = PHI <[test.c:13:16] buf_19(bb1), buf_5(ab)(6)> setjmpD.1749 (buf_4(ab)); [test.c:16:10] if (noside_22(D) != 0) goto nosideret; else goto do_call_it; bb6: # buf_5(ab) = PHI <buf_18(D)(ab)(bb1), buf_6(ab)(bb8)> ABNORMAL_DISPATCHER (0); goto bb5: do_call_it: # buf_6(ab) = PHI <buf_4(ab)(5), buf_18(D)(ab)(10)> [test.c:21:10] if (noside_22(D) != 0) goto nosideret; else goto bb8; bb8: try { [test.c:24:14] _7 = fooD.1752 (argvec_3(ab)); [test.c:24:14] goto bb12; } catch { goto bb6; } nosideret: [test.c:31:10] _7 = 1; bb12: return _7; } Thus, it is clear that buf can be used uninitialized if the abnormal edge is taken (represented by the first try-catch). Now, I don't have any idea why there is an abnormal edge there. I guess this is what Andrew was explaining about alloc_jmp_buf. If it is indeed needed, then there may be a missing optimization later (someone else would need to compare the -fdump-tree-all-all files when removing one of the gotos). Perhaps, as a work-around, the uninit pass could ignore default definitions that come from abnormal edges, but I'm not sure if this will cause some false negatives.