On Wed, May 16, 2018 at 1:37 PM, Marek Polacek <pola...@redhat.com> wrote: > On Wed, May 16, 2018 at 11:35:56AM -0400, Jason Merrill wrote: >> On Wed, May 16, 2018 at 11:15 AM, Marek Polacek <pola...@redhat.com> wrote: >> > This PR has been on my mind for quite some time but I've not found a >> > solution >> > that I'd like. Maybe one of you can think of something better. >> > >> > The problem in this test is that in C++11, .eh optimizes out the catch, >> > so the exception is never caught. That is because lower_catch doesn't >> > think that the region may throw (eh_region_may_contain_throw). That's >> > so because P::P () is marked as TREE_NOTHROW, which is wrong, because >> > it calls X::X() which calls init() with throw. TREE_NOTHROW is set in >> > finish_function: >> > >> > /* If this function can't throw any exceptions, remember that. */ >> > if (!processing_template_decl >> > && !cp_function_chain->can_throw >> > && !flag_non_call_exceptions >> > && !decl_replaceable_p (fndecl)) >> > TREE_NOTHROW (fndecl) = 1; >> > >> > P::P() should have been marked as can_throw in set_flags_from_callee, but >> > when >> > processing X::X() cfun is null, so we can't set it. P::P() is created only >> > later via implicitly_declare_fn. >> >> This should be handled by bot_manip (under break_out_target_exprs, >> under get_nsdmi), but it seems that it currently only calls >> set_flags_from_callee for CALL_EXPR, not for AGGR_INIT_EXPR as we have >> in this case. > > Ah, nice! So, this tweaks set_flags_from_callee to also work for > AGGR_INIT_EXPRs. > > Bootstrapped/regtested on x86_64-linux, ok for trunk? > > 2018-05-16 Marek Polacek <pola...@redhat.com> > > PR c++/85363 > * call.c (set_flags_from_callee): Handle AGGR_INIT_EXPRs too. > * tree.c (bot_manip): Call set_flags_from_callee for > AGGR_INIT_EXPRs too. > > * g++.dg/cpp0x/initlist-throw1.C: New test. > * g++.dg/cpp0x/initlist-throw2.C: New test. > > diff --git gcc/cp/call.c gcc/cp/call.c > index 09a3618b007..11b40747932 100644 > --- gcc/cp/call.c > +++ gcc/cp/call.c > @@ -319,16 +319,23 @@ build_call_n (tree function, int n, ...) > void > set_flags_from_callee (tree call) > { > - bool nothrow; > - tree decl = get_callee_fndecl (call); > + /* Handle both CALL_EXPRs and AGGR_INIT_EXPRs. */ > + tree decl = cp_get_callee_fndecl_nofold (call); > > /* We check both the decl and the type; a function may be known not to > throw without being declared throw(). */ > - nothrow = decl && TREE_NOTHROW (decl); > - if (CALL_EXPR_FN (call)) > - nothrow |= TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (call)))); > - else if (internal_fn_flags (CALL_EXPR_IFN (call)) & ECF_NOTHROW) > - nothrow = true; > + bool nothrow = decl && TREE_NOTHROW (decl); > + if (TREE_CODE (call) == CALL_EXPR) > + { > + if (CALL_EXPR_FN (call)) > + nothrow > + |= TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (call)))); > + else if (internal_fn_flags (CALL_EXPR_IFN (call)) & ECF_NOTHROW) > + nothrow = true; > + } > + else if (AGGR_INIT_EXPR_FN (call)) > + nothrow > + |= TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (AGGR_INIT_EXPR_FN (call))));
You should be able to avoid duplication here by using cp_get_callee rather than *_FN. Jason