]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/69024 ([cilkpus] cilk_spawn is broken for initializations with implicit...
authorRyan Burn <contact@rnburn.com>
Wed, 27 Apr 2016 20:41:52 +0000 (20:41 +0000)
committerJeff Law <law@gcc.gnu.org>
Wed, 27 Apr 2016 20:41:52 +0000 (14:41 -0600)
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

14 files changed:
gcc/c-family/ChangeLog
gcc/c-family/c-common.h
gcc/c-family/cilk.c
gcc/cp/ChangeLog
gcc/cp/cp-cilkplus.c
gcc/cp/cp-cilkplus.h [new file with mode: 0644]
gcc/cp/cp-gimplify.c
gcc/cp/cp-tree.h
gcc/cp/lambda.c
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cilk-plus/CK/pr68001.cc
gcc/testsuite/g++.dg/cilk-plus/CK/pr68997.cc [new file with mode: 0644]
gcc/testsuite/g++.dg/cilk-plus/CK/pr69024.cc [new file with mode: 0644]

index 1d87d9dd81514316ba84f569e5b627bd0f5be480..ac3be53941748303d251d9fea345e35ef3b908c4 100644 (file)
@@ -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.
index b631e7d1af542b9d6cc397ffc8b26337dac3fcb9..1309549617f418675dba805e200ee9cf8dec1179 100644 (file)
@@ -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 */
index 0b876b9fd6c3438527af051136a3ff760fd008b2..69a79baffead7cc7c037d994b536877205cb2f0a 100644 (file)
@@ -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;
index b21666b8e84b000ee0515ca3b030b14566d80de5..1219f82db98c8802f962a4b4b52ba7d87aed204a 100644 (file)
@@ -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
index 3b6cda2bcd07703bd29a021b305a53832eb739a8..7cde09968c09e8e4fcd3892bfed924a71d6adc45 100644 (file)
 #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 (file)
index 0000000..a93711e
--- /dev/null
@@ -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 */
index 30ac660906d259a59e77a38a0b157184e1a3233a..de04bcbb190095f3f22ae3f489fe200ce1d70bf6 100644 (file)
@@ -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);
index 0e46ae17f0ccd21b36f99435fd3caccf1b78a6ce..4c548c9ba969314676df6492482f2a1765af569a 100644 (file)
@@ -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,
index 374a78b1b4f1087097b463c7e27d9c862b7366d6..08d6d8205cf0d76a182cb359b3110e3533fb2ebf 100644 (file)
@@ -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.  */
 
index 98a0cd42fea824860d860c0f51f24e5fb3c22be6..7fb3c014ace3e51e892d22ccbcaed3bfba9eb95d 100644 (file)
@@ -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"
 
 \f
 /* The lexer.  */
index b1ab13d203e4d1e6dba14ed4e4838d5fd843f898..6189bee94ac4e841e7cadfcb9a6cc07693dacc22 100644 (file)
@@ -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.
index 07f7c5f2d55503a1f9c611f799298932fe5ae20d..bf2fefa03b4885383eadcfb4a7d7db412253fc7c 100644 (file)
@@ -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 (file)
index 0000000..b442bf9
--- /dev/null
@@ -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 (file)
index 0000000..b87dc1a
--- /dev/null
@@ -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 ();
+}