Commit 6bc2bb18 by Ryan Burn Committed by Jeff Law

re PR c++/69024 ([cilkpus] cilk_spawn is broken for initializations with…

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
parent 85a7c926
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.
......
......@@ -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 */
......@@ -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;
......
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
......
......@@ -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.
......
/* 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 */
......@@ -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);
......
......@@ -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,
......
......@@ -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. */
......
......@@ -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. */
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.
......
......@@ -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;
......
/* { 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 ();
}
/* { 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 ();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment