OK.
On Wed, May 16, 2018 at 2:44 PM, Marek Polacek <[email protected]> wrote: > On Wed, May 16, 2018 at 01:53:50PM -0400, Jason Merrill wrote: >> You should be able to avoid duplication here by using cp_get_callee >> rather than *_FN. > > Even better, thanks! > > Bootstrapped/regtested on x86_64-linux, ok for trunk? > > 2018-05-16 Marek Polacek <[email protected]> > > 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..4d04785f2b9 100644 > --- gcc/cp/call.c > +++ gcc/cp/call.c > @@ -319,15 +319,17 @@ 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) > + bool nothrow = decl && TREE_NOTHROW (decl); > + tree callee = cp_get_callee (call); > + if (callee) > + nothrow |= TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (callee))); > + else if (TREE_CODE (call) == CALL_EXPR > + && internal_fn_flags (CALL_EXPR_IFN (call)) & ECF_NOTHROW) > nothrow = true; > > if (!nothrow && at_function_scope_p () && cfun && cp_function_chain) > diff --git gcc/cp/tree.c gcc/cp/tree.c > index ecb88df23b9..db81da91676 100644 > --- gcc/cp/tree.c > +++ gcc/cp/tree.c > @@ -2987,7 +2987,7 @@ bot_manip (tree* tp, int* walk_subtrees, void* data_) > > /* Make a copy of this node. */ > t = copy_tree_r (tp, walk_subtrees, NULL); > - if (TREE_CODE (*tp) == CALL_EXPR) > + if (TREE_CODE (*tp) == CALL_EXPR || TREE_CODE (*tp) == AGGR_INIT_EXPR) > set_flags_from_callee (*tp); > if (data.clear_location && EXPR_HAS_LOCATION (*tp)) > SET_EXPR_LOCATION (*tp, input_location); > diff --git gcc/testsuite/g++.dg/cpp0x/initlist-throw1.C > gcc/testsuite/g++.dg/cpp0x/initlist-throw1.C > index e69de29bb2d..264c6c7a7a0 100644 > --- gcc/testsuite/g++.dg/cpp0x/initlist-throw1.C > +++ gcc/testsuite/g++.dg/cpp0x/initlist-throw1.C > @@ -0,0 +1,29 @@ > +// PR c++/85363 > +// { dg-do run { target c++11 } } > + > +int > +init (int f) > +{ > + throw f; > +} > + > +struct X { > + X (int f) : n {init (f)} {} > + int n; > +}; > + > +struct P { > + X x{20}; > +}; > + > +int > +main () > +{ > + try { > + P p {}; > + } > + catch (int n) { > + return 0; > + } > + return 1; > +} > diff --git gcc/testsuite/g++.dg/cpp0x/initlist-throw2.C > gcc/testsuite/g++.dg/cpp0x/initlist-throw2.C > index e69de29bb2d..2bb05834d9e 100644 > --- gcc/testsuite/g++.dg/cpp0x/initlist-throw2.C > +++ gcc/testsuite/g++.dg/cpp0x/initlist-throw2.C > @@ -0,0 +1,33 @@ > +// PR c++/85363 > +// { dg-do run { target c++11 } } > + > +int > +init (int f) > +{ > + throw f; > +} > + > +struct X { > + X () : n {init (42)} {} > + int n; > +}; > + > +struct P { > + struct R { > + struct Q { > + X x = {}; > + } q; > + } r; > +}; > + > +int > +main () > +{ > + try { > + P p {}; > + } > + catch (int n) { > + return 0; > + } > + return 1; > +}
