On Tue, May 28, 2019 at 08:30:59AM -0700, H.J. Lu wrote: > > We shouldn't generate ENDBR in that case, nothing can goto to bar (otherwise > > it would remain a normal label, not a deleted label). > > > > But return value of func () may be used with indirect jump.
No, it may be used say to print that address, but computed goto can't be used to jump from one function to a different function, see https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html "You may not use this mechanism to jump to code in a different function. If you do that, totally unpredictable things happen." NOTE_INSN_DELETED_LABEL is not guaranteed to be followed by any sensible code, the only reason it is kept is that there is or might be something referencing the label and so you want to emit the label somewhere in the function, but don't care much where in the function. Let's look at weirdo testcases where we warn about by default with -Wreturn-local-addr, but still the indirect jump is within the same function: void * foo (void *x) { if (!x) { return &&bar; bar: return 0; } goto *x; } void * qux (void *x, int y) { if (y == 1) { return &&bar; bar: return (void *) 5; } else if (y == 2) { return &&baz; baz: return (void *) 6; } goto *x; } if called with foo (foo (0)) or qux (qux (0, 1)) or qux (qux (0, 2)). In foo we emit NOTE_INSN_DELETED_LABEL, but just return that and optimize away the actual goto *x, because we can prove what it will do. In qux we can't and so there is no NOTE_INSN_DELETED_LABEL. Jakub