Index: gcc/c-family/cilk.c =================================================================== --- gcc/c-family/cilk.c (revision 231902) +++ gcc/c-family/cilk.c (working copy) @@ -192,7 +192,7 @@ switch (TREE_CODE_CLASS (code)) { case tcc_expression: - return code == ADDR_EXPR; + return code == ADDR_EXPR || code == COMPOUND_EXPR; case tcc_comparison: /* We need the spawn as operand 0 for now. That's where it appears in the only case we really care about, conversion @@ -252,6 +252,78 @@ return spawn_found; } +static bool +is_conversion_operator_function_decl_p (tree t) { + if (TREE_CODE (t) != FUNCTION_DECL) + return false; + + return DECL_NAME (t) && TREE_LANG_FLAG_4 (DECL_NAME (t)); +} + +static bool +is_conversion_operator_call_p (tree t) { + tree fndecl; + + if (TREE_CODE (t) != CALL_EXPR) + return false; + + fndecl = TREE_OPERAND (CALL_EXPR_FN (t), 0); + return call_expr_nargs (t) == 1 + && is_conversion_operator_function_decl_p (fndecl); +} + +static bool +is_unary_constructor_aggr_init_p (tree t) { + if (TREE_CODE (t) != AGGR_INIT_EXPR) + return false; + + return VL_EXP_OPERAND_LENGTH (t) == 5 && TREE_LANG_FLAG_0 (t); +} + +static bool +is_conversion_operator_aggr_init_p (tree t) { + tree fn; + + if (TREE_CODE (t) != AGGR_INIT_EXPR) + return false; + + fn = TREE_OPERAND (t, 1); + return VL_EXP_OPERAND_LENGTH (t) == 4 + && TREE_CODE (fn) == ADDR_EXPR + && is_conversion_operator_function_decl_p (TREE_OPERAND (fn, 0)); +} + +static tree +find_spawn (tree exp) +{ + /* Happens with C++ TARGET_EXPR. */ + if (exp == NULL_TREE) + return exp; + + else if (is_unary_constructor_aggr_init_p (exp)) + return find_spawn (TREE_OPERAND (exp, 4)); + + else if (is_conversion_operator_aggr_init_p (exp)) + return find_spawn (TREE_OPERAND (exp, 3)); + + else if (is_conversion_operator_call_p (exp)) + return find_spawn (CALL_EXPR_ARG (exp, 0)); + + else if (cilk_ignorable_spawn_rhs_op (exp)) + return find_spawn (TREE_OPERAND (exp, 0)); + + else if (TREE_CODE (exp) == TARGET_EXPR) + return find_spawn (TARGET_EXPR_INITIAL (exp)); + + else if (TREE_CODE (exp) == CLEANUP_POINT_EXPR + || TREE_CODE (exp) == EXPR_STMT) + return find_spawn (TREE_OPERAND (exp, 0)); + + else + return exp; +} + + /* Returns true if *EXP0 is a recognized form of spawn. Recognized forms are, after conversion to void, a call expression at outer level or an assignment at outer level with the right hand side being a spawned call. @@ -275,20 +347,7 @@ if (TREE_CODE (exp) == MODIFY_EXPR || TREE_CODE (exp) == INIT_EXPR) exp = TREE_OPERAND (exp, 1); - while (cilk_ignorable_spawn_rhs_op (exp)) - exp = TREE_OPERAND (exp, 0); - - if (TREE_CODE (exp) == TARGET_EXPR) - if (TARGET_EXPR_INITIAL (exp) - && TREE_CODE (TARGET_EXPR_INITIAL (exp)) != AGGR_INIT_EXPR) - exp = TARGET_EXPR_INITIAL (exp); - - /* Happens with C++ TARGET_EXPR. */ - if (exp == NULL_TREE) - return false; - - while (TREE_CODE (exp) == CLEANUP_POINT_EXPR || TREE_CODE (exp) == EXPR_STMT) - exp = TREE_OPERAND (exp, 0); + exp = find_spawn (exp); /* Now we should have a CALL_EXPR with a CILK_SPAWN_STMT wrapper around it, or return false. */ @@ -592,6 +651,11 @@ for (p = wd->parms; p; p = TREE_CHAIN (p)) DECL_CONTEXT (p) = fndecl; + /* The statement containing the spawn expression might create temporaries with + destructors defined; if so we need to add a CLEANUP_POINT_EXPR to ensure + the expression is properly gimplified. */ + stmt = fold_build_cleanup_point_expr (void_type_node, stmt); + gcc_assert (!DECL_SAVED_TREE (fndecl)); cilk_install_body_with_frame_cleanup (fndecl, stmt, (void *) wd); gcc_assert (DECL_SAVED_TREE (fndecl)); @@ -1246,6 +1310,21 @@ return; case AGGR_INIT_EXPR: + { + int len = 0; + int ii = 0; + extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ); + if (TREE_CODE (TREE_OPERAND (t, 0)) == INTEGER_CST) + { + len = TREE_INT_CST_LOW (TREE_OPERAND (t, 0)); + + for (ii = 3; ii < len; ii++) + extract_free_variables (TREE_OPERAND (t, ii), wd, ADD_READ); + extract_free_variables (TREE_TYPE (t), wd, ADD_READ); + } + break; + } + case CALL_EXPR: { int len = 0; Index: gcc/testsuite/g++.dg/cilk-plus/CK/pr68997.cc =================================================================== --- gcc/testsuite/g++.dg/cilk-plus/CK/pr68997.cc (revision 0) +++ gcc/testsuite/g++.dg/cilk-plus/CK/pr68997.cc (working copy) @@ -0,0 +1,68 @@ +/* { dg-do compile } */ +/* { dg-options "-std=c++11 -fcilkplus" } */ + +struct A1 { + A1 () {} + A1 (const A1&) {} +}; + +A1 fa1 () { + return A1 (); +} + +struct A2 { + A2 () {} + A2 (A2&&) {} +}; + +A2 fa2 () { + A2 (); +} + +struct B1 { +}; + +B1 fb1 () { + return B1 (); +} + +struct A3 { + A3 (const B1&) {} +}; + +struct A4 { + A4 (B1) {} +}; + +struct B2 { + B2 () {} + B2 (const B2&) {} +}; + +B2 fb2 () { + return B2 (); +} + +struct A5 { + A5 (B2) {} +}; + +void t1 () { + A1 a1 = _Cilk_spawn fa1 (); +} + +void t2 () { + A2 a2 = _Cilk_spawn fa2 (); +} + +void t3 () { + A3 a3 = _Cilk_spawn fb1 (); +} + +void t4 () { + A4 a4 = _Cilk_spawn fb1 (); +} + +void t5 () { + A5 a5 = _Cilk_spawn fb2 (); +} Index: gcc/testsuite/g++.dg/cilk-plus/CK/pr69024.cc =================================================================== --- gcc/testsuite/g++.dg/cilk-plus/CK/pr69024.cc (revision 0) +++ gcc/testsuite/g++.dg/cilk-plus/CK/pr69024.cc (working copy) @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-fcilkplus" } */ + +struct A1 { +}; + +struct A2 { + A2 () {} + A2 (const A2&) {} +}; + +struct B1 { + operator A1 () { + return A1 (); + } +}; + +B1 fb1 () { + return B1 (); +} + +struct B2 { + operator A2 () { + return A2 (); + } +}; + +B2 fb2 () { + return B2 (); +} + +void t1 () { + A1 a1 = _Cilk_spawn fb1 (); +} + +void t2 () { + A2 a2 = _Cilk_spawn fb2 (); +} Index: gcc/testsuite/g++.dg/cilk-plus/CK/pr69048.cc =================================================================== --- gcc/testsuite/g++.dg/cilk-plus/CK/pr69048.cc (revision 0) +++ gcc/testsuite/g++.dg/cilk-plus/CK/pr69048.cc (working copy) @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-fcilkplus" } */ + +struct A { + ~A () {} +}; + +A f () { + return A (); +} + +void t1 () { + _Cilk_spawn f (); +} Index: gcc/testsuite/g++.dg/cilk-plus/CK/pr68001.cc =================================================================== --- gcc/testsuite/g++.dg/cilk-plus/CK/pr68001.cc (revision 231902) +++ gcc/testsuite/g++.dg/cilk-plus/CK/pr68001.cc (working copy) @@ -11,7 +11,7 @@ int main() { - std::vector x = _Cilk_spawn f(); /* { dg-error "invalid use of" } */ + std::vector x = _Cilk_spawn f (); std::vector y = f(); _Cilk_sync; return 0;