This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH for c++/69889 (ICE with lambda conversion)


Here, we were crashing because the artificial thunk returned by the lambda conversion operator was dereferencing an invisible reference parameter instead of passing it through. I needed to fix cp_genericize_r to avoid that like it already does for virtual function thunks.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 3180adca839ba43c21834ef6cb6af7bbc8eda478
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Feb 25 21:40:09 2016 -0500

    	PR c++/69889
    
    	* cp-tree.h (AGGR_INIT_FROM_THUNK_P): New.
    	* tree.c (build_aggr_init_expr): Set it.
    	* semantics.c (simplify_aggr_init_expr): Check it.
    	* cp-gimplify.c (cp_genericize_r): Don't walk into
    	a call/aggr_init from a thunk.

diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index a77b242..6af3760 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -1021,10 +1021,16 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
       && omp_var_to_track (stmt))
     omp_cxx_notice_variable (wtd->omp_ctx, stmt);
 
-  if (is_invisiref_parm (stmt)
-      /* Don't dereference parms in a thunk, pass the references through. */
-      && !(DECL_THUNK_P (current_function_decl)
-	   && TREE_CODE (stmt) == PARM_DECL))
+  /* Don't dereference parms in a thunk, pass the references through. */
+  if ((TREE_CODE (stmt) == CALL_EXPR && CALL_FROM_THUNK_P (stmt))
+      || (TREE_CODE (stmt) == AGGR_INIT_EXPR && AGGR_INIT_FROM_THUNK_P (stmt)))
+    {
+      *walk_subtrees = 0;
+      return NULL;
+    }
+
+  /* Otherwise, do dereference invisible reference parms.  */
+  if (is_invisiref_parm (stmt))
     {
       *stmt_p = convert_from_reference (stmt);
       *walk_subtrees = 0;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 88c6367..b1dc23c 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3409,6 +3409,11 @@ extern void decl_shadowed_for_var_insert (tree, tree);
 #define AGGR_INIT_ZERO_FIRST(NODE) \
   TREE_LANG_FLAG_2 (AGGR_INIT_EXPR_CHECK (NODE))
 
+/* Nonzero means that the call is the jump from a thunk to the
+   thunked-to function.  */
+#define AGGR_INIT_FROM_THUNK_P(NODE) \
+  (AGGR_INIT_EXPR_CHECK (NODE)->base.protected_flag)
+
 /* AGGR_INIT_EXPR accessors.  These are equivalent to the CALL_EXPR
    accessors, except for AGGR_INIT_EXPR_SLOT (which takes the place of
    CALL_EXPR_STATIC_CHAIN).  */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index fad233a..fd83c46 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -4067,6 +4067,7 @@ simplify_aggr_init_expr (tree *tp)
 				    AGGR_INIT_EXPR_ARGP (aggr_init_expr));
   TREE_NOTHROW (call_expr) = TREE_NOTHROW (aggr_init_expr);
   CALL_EXPR_LIST_INIT_P (call_expr) = CALL_EXPR_LIST_INIT_P (aggr_init_expr);
+  CALL_FROM_THUNK_P (call_expr) = AGGR_INIT_FROM_THUNK_P (aggr_init_expr);
 
   if (style == ctor)
     {
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index ac38ce3..9e29a42 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -464,18 +464,25 @@ build_aggr_init_expr (tree type, tree init)
     {
       slot = build_local_temp (type);
 
-      if (TREE_CODE(init) == CALL_EXPR)
-	rval = build_aggr_init_array (void_type_node, fn, slot,
-				      call_expr_nargs (init),
-				      CALL_EXPR_ARGP (init));
+      if (TREE_CODE (init) == CALL_EXPR)
+	{
+	  rval = build_aggr_init_array (void_type_node, fn, slot,
+					call_expr_nargs (init),
+					CALL_EXPR_ARGP (init));
+	  AGGR_INIT_FROM_THUNK_P (rval)
+	    = CALL_FROM_THUNK_P (init);
+	}
       else
-	rval = build_aggr_init_array (void_type_node, fn, slot,
-				      aggr_init_expr_nargs (init),
-				      AGGR_INIT_EXPR_ARGP (init));
+	{
+	  rval = build_aggr_init_array (void_type_node, fn, slot,
+					aggr_init_expr_nargs (init),
+					AGGR_INIT_EXPR_ARGP (init));
+	  AGGR_INIT_FROM_THUNK_P (rval)
+	    = AGGR_INIT_FROM_THUNK_P (init);
+	}
       TREE_SIDE_EFFECTS (rval) = 1;
       AGGR_INIT_VIA_CTOR_P (rval) = is_ctor;
       TREE_NOTHROW (rval) = TREE_NOTHROW (init);
-      CALL_EXPR_LIST_INIT_P (rval) = CALL_EXPR_LIST_INIT_P (init);
     }
   else
     rval = init;
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv10.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv10.C
new file mode 100644
index 0000000..8e806c8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv10.C
@@ -0,0 +1,34 @@
+// PR c++/69889
+// { dg-do compile { target c++11 } }
+
+template <typename F> struct Tag {
+  static void fp() { f()(0); }
+  static F f() {}
+};
+
+struct Dispatch {
+  template <typename F> Dispatch(F&&) : f(Tag<F>::fp) {}
+  void (*f)();
+};
+
+struct Empty { Empty(Empty&&); };
+
+struct Value {
+  Value();
+  template <typename U> Value(U);
+  void call(Dispatch);
+  Empty e;
+};
+
+struct EmptyValue {
+  EmptyValue(EmptyValue&&);
+  EmptyValue();
+};
+
+struct User {
+  User() {
+    Value().call([](Value) { return EmptyValue(); });
+  }
+};
+
+User user;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]