[Bug c/17913] [4.0/4.1 Regression] ICE jumping into statement expression

joseph at codesourcery dot com gcc-bugzilla@gcc.gnu.org
Thu Mar 24 20:35:00 GMT 2005


------- Additional Comments From joseph at codesourcery dot com  2005-03-24 20:34 -------
Subject: Re:  [4.0/4.1 Regression] ICE jumping into statement
 expression

On Thu, 24 Mar 2005, mmitchel at gcc dot gnu dot org wrote:

> Joseph, do you think it is tractable and reasonable to diagnose jumps into
> statement expressions for 4.0?  If you and RTH agree that this should be
> invalid, then that would be ideal.  If you agree that this should be invalid,
> but don't think it's possible to fix, would you please adjust the Keywords entry
> here, so that this is not marked as a wrong-code/ice-on-valid-code regression,
> but rather accepts-invalid?

I think it is tractable and reasonable to diagnose jumps into statement 
expressions (at least for C, not having looked at the implementation for 
C++) for 4.0.  I also don't see anything *wrong* with the C front end 
changes in the patch posted for this bug, given that the rest of the patch 
could still be of use if there are front ends which want to continue to 
allow jumps into conditional expressions which might otherwise get folded.  
(And in abstract there's nothing wrong with a front end trying to fold a 
COND_EXPR arising from if (0) { ... } else { ... }, which certainly can be 
jumped into; just that in practice trying to fold such a tree is unlikely 
to be useful.)

Having spent an hour working out how to diagnose jumps into statement 
expressions I've arrived at the following approach which I'd try; I expect 
something similar would work for C++ as well:

* Add three flags to labels: one for "this label was in a statement 
expression which has finished, so you can't jump to it any more", one for 
"this label has a goto jumping to it from the current level of statement 
expression nesting" and one for "this label has a goto jumping to it from 
outside the current level of statement expression nesting".

* Keep a list at each level of statement expression nesting (including 
inside a function but outside all statement expressions) of all labels 
defined at that level, and a list of all labels with gotos to them at that 
level.

* When a goto is encountered, it mustn't be to a label with the first 
flag.  Otherwise, if it doesn't have the second or third flag, give it the 
second flag and put it on the current list of gotos.

* When a label is defined, it mustn't have the third flag.  Otherwise, put 
it on the list of labels defined at that level.

* When starting a statement expression, start new lists as above.  Given 
all labels on the immediately previous list of gotos the third flag (so 
they can't be defined until that statement expression ends).

* When ending a statement expression, give all labels defined in that 
expression the first flag.  Remove the third flag from all gotos in the 
level to which we are returning, leaving the second flag on them.  Move 
the gotos in the list of the level we are leaving to the list of the level 
which we are returning (and leave the second flag on them).

* Keep a flag for whether the current switch statement started outside 
the current statement expression.  When starting a statement expression, 
save the flag's value and set it to true; restore it when ending a 
statement expression.  When starting a switch statement, save the flag's 
value and set it to false; restore it when ending a switch statement.  Do 
not allow case or default labels when the flag is true.

* Generate a testcase involving all cases of a function with two statement 
expressions inside, each of those containing two statement expressions and 
the label and goto in all possible places, i.e.

void
f (void)
{
 ^({ ^({^0;}); ^({^0;}); ^0;});
 ^({ ^({^0;}); ^({^0;}); ^0;});
 ^0;^
}

with the goto at any place marked ^ and the label on the goto or at any of 
those places other than right at the end of the function, i.e. 196 such 
functions, making sure that the correct subset are rejected.  (This is 
operating on the basis that we will continue to allow jumps *out* of 
statement expressions, as people have real uses for such, with it simply 
being unspecified which collateral expressions of the statement expression 
(subexpressions of the larger expression containing the statement 
expression not separated from it by a sequence point, e.g. foo() in foo() 
+ ({ goto a; 0; })) have been evaluated.)

(The second flag on labels is only used to avoid listing labels more than 
once at the same level of nesting; it isn't strictly required, and 
actually implementing it would mean multipurposing another one of the 
DECL_LANG_FLAG fields: C is using 0-5 with 4 already multipurposed.)



-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17913



More information about the Gcc-bugs mailing list