diff options
author | Ryan Burn <contact@rnburn.com> | 2016-04-27 20:41:52 +0000 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2016-04-27 14:41:52 -0600 |
commit | 6bc2bb1821cc65ff6e463cb1fc930c5d152fe04d (patch) | |
tree | 01aff7302afade8fb5843d89091bb1813cde6002 | |
parent | 85a7c9263c2554811e9fc0e1ce7bec3b3bf6b7f5 (diff) | |
download | gcc-6bc2bb1821cc65ff6e463cb1fc930c5d152fe04d.zip gcc-6bc2bb1821cc65ff6e463cb1fc930c5d152fe04d.tar.gz gcc-6bc2bb1821cc65ff6e463cb1fc930c5d152fe04d.tar.bz2 |
re PR c++/69024 ([cilkpus] cilk_spawn is broken for initializations with implicit conversion operators defined)
PR c++/69024
PR c++/68997
* cilk.c (cilk_ignorable_spawn_rhs_op): Change to external linkage.
(cilk_recognize_spawn): Renamed from recognize_spawn and change to
external linkage.
(cilk_detect_and_unwrap): Corresponding changes.
(extract_free_variables): Don't extract free variables from
AGGR_INIT_EXPR slot.
* c-common.h (cilk_ignorable_spawn_rhs_op): Prototype.
(cilk_recognize_spawn): Likewise.
PR c++/69024
PR c++/68997
* cp-gimplify.c (cp_gimplify_expr): Call cilk_cp_detect_spawn_and_unwrap
instead of cilk_detect_spawn_and_unwrap.
* cp-cilkplus.c (is_conversion_operator_function_decl_p): New.
(find_spawn): New.
(cilk_cp_detect_spawn_and_unwrap): New.
* lambda.c: Include cp-cilkplus.h.
* parser.c: Include cp-cilkplus.h.
* cp-tree.h (cpp_validate_cilk_plus_loop): Move prototype into...
* cp-cilkpus.h: New file.
PR c++/69024
PR c++/68997
* g++.dg/cilk-plus/CK/pr68001.cc: Fix to not depend on broken
diagnostic.
* g++.dg/cilk-plus/CK/pr69024.cc: New test.
* g++.dg/cilk-plus/CK/pr68997.cc: New test.
Co-Authored-By: Jeff Law <law@redhat.com>
From-SVN: r235534
-rw-r--r-- | gcc/c-family/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 3 | ||||
-rw-r--r-- | gcc/c-family/cilk.c | 23 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/cp/cp-cilkplus.c | 104 | ||||
-rw-r--r-- | gcc/cp/cp-cilkplus.h | 28 | ||||
-rw-r--r-- | gcc/cp/cp-gimplify.c | 9 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 3 | ||||
-rw-r--r-- | gcc/cp/lambda.c | 1 | ||||
-rw-r--r-- | gcc/cp/parser.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cilk-plus/CK/pr68001.cc | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cilk-plus/CK/pr68997.cc | 68 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cilk-plus/CK/pr69024.cc | 38 |
14 files changed, 305 insertions, 12 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 1d87d9d..ac3be53 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,16 @@ +2015-04-27 Ryan Burn <contact@rnburn.com> + + PR c++/69024 + PR c++/68997 + * cilk.c (cilk_ignorable_spawn_rhs_op): Change to external linkage. + (cilk_recognize_spawn): Renamed from recognize_spawn and change to + external linkage. + (cilk_detect_and_unwrap): Corresponding changes. + (extract_free_variables): Don't extract free variables from + AGGR_INIT_EXPR slot. + * c-common.h (cilk_ignorable_spawn_rhs_op): Prototype. + (cilk_recognize_spawn): Likewise. + 2016-04-27 Bernd Schmidt <bschmidt@redhat.com> * c.opt (Wmemset-elt-size): New option. diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index b631e7d..1309549 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1468,4 +1468,7 @@ extern bool reject_gcc_builtin (const_tree, location_t = UNKNOWN_LOCATION); extern void warn_duplicated_cond_add_or_warn (location_t, tree, vec<tree> **); extern bool valid_array_size_p (location_t, tree, tree); +extern bool cilk_ignorable_spawn_rhs_op (tree); +extern bool cilk_recognize_spawn (tree, tree *); + #endif /* ! GCC_C_COMMON_H */ diff --git a/gcc/c-family/cilk.c b/gcc/c-family/cilk.c index 0b876b9..69a79ba 100644 --- a/gcc/c-family/cilk.c +++ b/gcc/c-family/cilk.c @@ -185,7 +185,7 @@ call_graph_add_fn (tree fndecl) A comparison to constant is simple enough to allow, and is used to convert to bool. */ -static bool +bool cilk_ignorable_spawn_rhs_op (tree exp) { enum tree_code code = TREE_CODE (exp); @@ -223,8 +223,8 @@ unwrap_cilk_spawn_stmt (tree *tp, int *walk_subtrees, void *) /* Returns true when EXP is a CALL_EXPR with _Cilk_spawn in front. Unwraps CILK_SPAWN_STMT wrapper from the CALL_EXPR in *EXP0 statement. */ -static bool -recognize_spawn (tree exp, tree *exp0) +bool +cilk_recognize_spawn (tree exp, tree *exp0) { bool spawn_found = false; if (TREE_CODE (exp) == CILK_SPAWN_STMT) @@ -292,7 +292,7 @@ cilk_detect_spawn_and_unwrap (tree *exp0) /* Now we should have a CALL_EXPR with a CILK_SPAWN_STMT wrapper around it, or return false. */ - if (recognize_spawn (exp, exp0)) + if (cilk_recognize_spawn (exp, exp0)) return true; return false; } @@ -1250,6 +1250,21 @@ extract_free_variables (tree t, struct wrapper_data *wd, 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; diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b21666b..1219f82 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,18 @@ +2015-04-27 Ryan Burn <contact@rnburn.com> + Jeff Law <law@redhat.com> + + PR c++/69024 + PR c++/68997 + * cp-gimplify.c (cp_gimplify_expr): Call cilk_cp_detect_spawn_and_unwrap + instead of cilk_detect_spawn_and_unwrap. + * cp-cilkplus.c (is_conversion_operator_function_decl_p): New. + (find_spawn): New. + (cilk_cp_detect_spawn_and_unwrap): New. + * lambda.c: Include cp-cilkplus.h. + * parser.c: Include cp-cilkplus.h. + * cp-tree.h (cpp_validate_cilk_plus_loop): Move prototype into... + * cp-cilkpus.h: New file. + 2016-04-27 Nathan Sidwell <nathan@acm.org> * constexpr.c (get_fundef_copy): Use the original function for diff --git a/gcc/cp/cp-cilkplus.c b/gcc/cp/cp-cilkplus.c index 3b6cda2..7cde099 100644 --- a/gcc/cp/cp-cilkplus.c +++ b/gcc/cp/cp-cilkplus.c @@ -26,6 +26,110 @@ #include "cp-tree.h" #include "tree-iterator.h" #include "cilk.h" +#include "c-family/c-common.h" + +/* Return TRUE if T is a FUNCTION_DECL for a type-conversion operator. */ + +static bool +is_conversion_operator_function_decl_p (tree t) +{ + if (TREE_CODE (t) != FUNCTION_DECL) + return false; + + return DECL_NAME (t) && IDENTIFIER_TYPENAME_P (DECL_NAME (t)); +} + +/* Recursively traverse EXP to search for a CILK_SPAWN_STMT subtree. + Return the CILK_SPAWN_STMT subtree if found; otherwise, the last subtree + searched. */ + +static tree +find_spawn (tree exp) +{ + /* Happens with C++ TARGET_EXPR. */ + if (exp == NULL_TREE) + return exp; + + if (cilk_ignorable_spawn_rhs_op (exp)) + return find_spawn (TREE_OPERAND (exp, 0)); + + switch (TREE_CODE (exp)) + { + case AGGR_INIT_EXPR: + { + /* Check for initialization via a constructor call that represents + implicit conversion. */ + if (AGGR_INIT_VIA_CTOR_P (exp) && aggr_init_expr_nargs (exp) == 2) + return find_spawn (AGGR_INIT_EXPR_ARG (exp, 1)); + + /* Check for initialization via a call to a type-conversion + operator. */ + tree fn = AGGR_INIT_EXPR_FN (exp); + if (TREE_CODE (fn) == ADDR_EXPR + && is_conversion_operator_function_decl_p (TREE_OPERAND (fn, 0)) + && aggr_init_expr_nargs (exp) == 1) + return find_spawn (AGGR_INIT_EXPR_ARG (exp, 0)); + } + break; + + case CALL_EXPR: + { + /* Check for a call to a type-conversion operator. */ + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); + if (is_conversion_operator_function_decl_p (fndecl) + && call_expr_nargs (exp) == 1) + return find_spawn (CALL_EXPR_ARG (exp, 0)); + } + break; + + case TARGET_EXPR: + return find_spawn (TARGET_EXPR_INITIAL (exp)); + + case CLEANUP_POINT_EXPR: + case COMPOUND_EXPR: + case EXPR_STMT: + return find_spawn (TREE_OPERAND (exp, 0)); + + default: + break; + } + + return exp; +} + +/* Return 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. + In addition to this, it also unwraps the CILK_SPAWN_STMT cover from the + CALL_EXPR that is being spawned. + + Note that `=' in C++ may turn into a CALL_EXPR rather than a + MODIFY_EXPR. */ + +bool +cilk_cp_detect_spawn_and_unwrap (tree *exp0) +{ + tree exp = *exp0; + + if (!TREE_SIDE_EFFECTS (exp)) + return false; + + /* Strip off any conversion to void. It does not affect whether spawn + is supported here. */ + if (TREE_CODE (exp) == CONVERT_EXPR && VOID_TYPE_P (TREE_TYPE (exp))) + exp = TREE_OPERAND (exp, 0); + + if (TREE_CODE (exp) == MODIFY_EXPR || TREE_CODE (exp) == INIT_EXPR) + exp = TREE_OPERAND (exp, 1); + + exp = find_spawn (exp); + if (exp == NULL_TREE) + return false; + + /* Now we should have a CALL_EXPR with a CILK_SPAWN_STMT wrapper around + it, or return false. */ + return cilk_recognize_spawn (exp, exp0); +} /* Callback for cp_walk_tree to validate the body of a pragma simd loop or _cilk_for loop. diff --git a/gcc/cp/cp-cilkplus.h b/gcc/cp/cp-cilkplus.h new file mode 100644 index 0000000..a93711e --- /dev/null +++ b/gcc/cp/cp-cilkplus.h @@ -0,0 +1,28 @@ +/* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c. + + Copyright (C) 2002-2016 Free Software Foundation, Inc. + Contributed by Jason Merrill <jason@redhat.com> + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#ifndef GCC_CP_CILKPLUS_H +#define GCC_CP_CILKPLUS_H + +extern bool cilk_cp_detect_spawn_and_unwrap (tree *); +extern bool cpp_validate_cilk_plus_loop (tree); + +#endif /* ! GCC_CP_CILKPLUS_H */ diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index 30ac660..de04bcb 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see #include "gimplify.h" #include "c-family/c-ubsan.h" #include "cilk.h" +#include "cp-cilkplus.h" /* Forward declarations. */ @@ -615,7 +616,7 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) case INIT_EXPR: if (fn_contains_cilk_spawn_p (cfun)) { - if (cilk_detect_spawn_and_unwrap (expr_p)) + if (cilk_cp_detect_spawn_and_unwrap (expr_p)) { cilk_cp_gimplify_call_params_in_spawned_fn (expr_p, pre_p, post_p); @@ -633,7 +634,7 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) modify_expr_case: { if (fn_contains_cilk_spawn_p (cfun) - && cilk_detect_spawn_and_unwrap (expr_p) + && cilk_cp_detect_spawn_and_unwrap (expr_p) && !seen_error ()) { cilk_cp_gimplify_call_params_in_spawned_fn (expr_p, pre_p, post_p); @@ -734,7 +735,7 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) case CILK_SPAWN_STMT: gcc_assert(fn_contains_cilk_spawn_p (cfun) - && cilk_detect_spawn_and_unwrap (expr_p)); + && cilk_cp_detect_spawn_and_unwrap (expr_p)); if (!seen_error ()) { @@ -745,7 +746,7 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) case CALL_EXPR: if (fn_contains_cilk_spawn_p (cfun) - && cilk_detect_spawn_and_unwrap (expr_p) + && cilk_cp_detect_spawn_and_unwrap (expr_p) && !seen_error ()) { cilk_cp_gimplify_call_params_in_spawned_fn (expr_p, pre_p, post_p); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 0e46ae1..4c548c9 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6873,9 +6873,6 @@ extern void vtv_save_class_info (tree); extern void vtv_recover_class_info (void); extern void vtv_build_vtable_verify_fndecl (void); -/* In cp-cilkplus.c. */ -extern bool cpp_validate_cilk_plus_loop (tree); - /* In cp/cp-array-notations.c */ extern tree expand_array_notation_exprs (tree); bool cilkplus_an_triplet_types_ok_p (location_t, tree, tree, tree, diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c index 374a78b..08d6d82 100644 --- a/gcc/cp/lambda.c +++ b/gcc/cp/lambda.c @@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-iterator.h" #include "toplev.h" #include "gimplify.h" +#include "cp-cilkplus.h" /* Constructor for a lambda expression. */ diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 98a0cd4..7fb3c01 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -39,6 +39,7 @@ along with GCC; see the file COPYING3. If not see #include "gomp-constants.h" #include "c-family/c-indentation.h" #include "context.h" +#include "cp-cilkplus.h" /* The lexer. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b1ab13d..6189bee 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2015-04-27 Ryan Burn <contact@rnburn.com> + + PR c++/69024 + PR c++/68997 + * g++.dg/cilk-plus/CK/pr68001.cc: Fix to not depend on broken + diagnostic. + * g++.dg/cilk-plus/CK/pr69024.cc: New test. + * g++.dg/cilk-plus/CK/pr68997.cc: New test. + 2016-04-27 Eric Botcazou <ebotcazou@adacore.com> * gnat.dg/limited_with4.ad[sb]: New test. diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/pr68001.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/pr68001.cc index 07f7c5f..bf2fefa 100644 --- a/gcc/testsuite/g++.dg/cilk-plus/CK/pr68001.cc +++ b/gcc/testsuite/g++.dg/cilk-plus/CK/pr68001.cc @@ -11,7 +11,7 @@ std::vector<double> f() { int main() { - std::vector<double> x = _Cilk_spawn f(); /* { dg-error "invalid use of" } */ + std::vector<double> x = _Cilk_spawn f (); std::vector<double> y = f(); _Cilk_sync; return 0; diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/pr68997.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/pr68997.cc new file mode 100644 index 0000000..b442bf9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/CK/pr68997.cc @@ -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 (); +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/pr69024.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/pr69024.cc new file mode 100644 index 0000000..b87dc1a --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/CK/pr69024.cc @@ -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 (); +} |