------- Comment #11 from rakdver at gcc dot gnu dot org 2006-01-22 21:49 ------- This ICE works this way: to build_throw, we get expression exp that looks like
TARGET_EXPR <D.2066, b ? aggr_init_expr (... t1 ...) : aggr_init_expr (... t2 ...)> Where t1 and t2 are TARGET_EXPRs with cleanups (*). build_throw generates code TARGET_EXPR <D.2069, __cxa_allocate_exception (1)>; try { *(struct logic_error *) D.2069 = exp; } catch { __cxa_free_exception (D.2069); }; __cxa_throw (D.2069, (void *) &_ZTI11logic_error, 0B); This is a problem, since exp (that contains cleanups) is withing the try statement, and gimplify_cleanup_expr expects that there never is a compound statement between cleanup and cleanup_point_expr (except for COND_EXPRs). For comparison, with void foo(bool b) { throw logic_error(1); } exp is TARGET_EXPR <D.2066, aggr_init_expr (... t1 ...)> In this case, however, stabilize_init will allow to pre-evaluate t1, and the produced code is (where exp' is exp with t1 replaced by tmp): TARGET_EXPR <tmp, t1> TARGET_EXPR <D.2069, __cxa_allocate_exception (1)>; try { *(struct logic_error *) D.2069 = exp'; } catch { __cxa_free_exception (D.2069); }; __cxa_throw (D.2069, (void *) &_ZTI11logic_error, 0B); Here gimplify_cleanup_expr has no problem, since t1 is outside of the try statement. Now the question is whether we can persuade throw_expr to also evaluate (the relevant parts of) exp outside of the try statement. Answering this question is far beyond my understanding of c++ frontend; stabilize_init claims that /* If the initializer is a COND_EXPR, we can't preevaluate anything. */ if (TREE_CODE (t) == COND_EXPR) return false; which might suggest that it is not possible, but the statement is too vague for me to be sure. If it is somehow possible, it would be much preferable. The other possibility is to teach gimplify_cleanup_expr to deal with try statements, which basically means to rewrite it completely from scratch. -------------- (*) The exact expression is TARGET_EXPR <D.2066 init: bD.2024 ? TARGET_EXPR <D.2062 init: aggr_init_expr (__comp_ctor ; 0B, (struct string &) &TARGET_EXPR <D.2061 init: aggr_init_expr (__comp_ctor ; 0B, 0, (struct allocator &) (struct allocator *) &TARGET_EXPR <D.2045 init: {} clean: __comp_dtor (&D.2045); > D.2061) > D.2062) > : TARGET_EXPR <D.2065 init: aggr_init_expr (__comp_ctor ; 0B, (struct string &) &TARGET_EXPR <D.2064 init: aggr_init_expr (__comp_ctor ; 0B, 1, (struct allocator &) (struct allocator *) &TARGET_EXPR <D.2063 init: {} clean: __comp_dtor (&D.2063); > D.2064) > D.2065) >; >; -- rakdver at gcc dot gnu dot org changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |mark at codesourcery dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24996