On Wed, Apr 08, 2020 at 09:02:59PM -0700, Linus Torvalds wrote: > Try linearizing this with 'sparse', and see it fail miserably: > > int t(void) > { > goto inside; > return 0 ? > ({ inside: return 3; 1; }) > : > 2; > } > > I came up with that disgusting example after talking to Nick > Desaulniers about how sparse does some front-end optimizations early, > and it made me go "Hmm... What about.." Funny, I worked on something very similar last week: void f(int x, int y) { 1 ? x : ({ a: y; }); goto a; } > There are two reasonable approaches for the above: > > - return 3 (due to the "goto inside") > > - tell the user to pound sand for doing crazy things and jumping into > a statement expression from outside. > > clang does #1. gcc does #2. > > sparse does something bad, and just generates garbage silently. Yes, the problem is caused at expand_conditional() where one of the sides is throwed away if the condition is known. So the label doesn't exist anymore and at linearization Sparse ends with a jump to an unexisting BB. I tried to simply discard the early optimization in expand but then when testing the kernel I got a whole bunch of warnings (bad type or dereference of noderef type, I don't remember). So it seems that in general (when nobody jump into the expression statement) the conditional needs to be simplified before evaluation. I tried also to warn on gotos jumping into an expression statement. The idea was to give a new 'label_scope' for each such statement. Things are a bit complicated because the labels are implicitly declared by the gotos. I'll need to look a bit more at this. -- Luc