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 /gcc/cp/cp-cilkplus.c | |
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
Diffstat (limited to 'gcc/cp/cp-cilkplus.c')
-rw-r--r-- | gcc/cp/cp-cilkplus.c | 104 |
1 files changed, 104 insertions, 0 deletions
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. |