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

Reply via email to