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] Fix wrong-code with generic lambda (PR c++/86943)


Hi!

On the following testcase, the call to operator () is marked as
CALL_FROM_THUNK_P and therefore genericization ignores all subtrees thereof.
Unfortunately, one of the arguments is a move ctor call which is not itself
CALL_FROM_THUNK_P and thus we need to genericize its arguments, otherwise
we pass address of a temporary which holds a reference value instead of the
reference itself.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Or should CALL_FROM_THUNK_P not be set in this call (it is set in
maybe_add_lambda_conv_op and then copied over during tsubst*).

Furthermore, clang++ apparently doesn't call the move ctor + dtor at all and
uses just the originally constructed var.  Is what GCC does right, or clang?

2018-11-23  Jakub Jelinek  <jakub@redhat.com>

	PR c++/86943
	* cp-gimplify.c (cp_genericize_r): For CALL_FROM_THUNK_P CALL_EXPRs
	don't walk just DECL_P arguments, do walk more complex arguments.

	* g++.dg/cpp1y/pr86943.C: New test.

--- gcc/cp/cp-gimplify.c.jj	2018-11-17 00:16:41.924381941 +0100
+++ gcc/cp/cp-gimplify.c	2018-11-23 17:29:24.764459373 +0100
@@ -1108,6 +1108,18 @@ cp_genericize_r (tree *stmt_p, int *walk
       || (TREE_CODE (stmt) == AGGR_INIT_EXPR && AGGR_INIT_FROM_THUNK_P (stmt)))
     {
       *walk_subtrees = 0;
+      /* For CALL_EXPRs, if the arguments aren't decls, recurse into them
+	 though.  See PR86943.  */
+      if (TREE_CODE (stmt) == CALL_EXPR)
+	{
+	  unsigned int n = call_expr_nargs (stmt);
+	  for (unsigned int i = 0; i < n; i++)
+	    {
+	      tree &arg = CALL_EXPR_ARG (stmt, i);
+	      if (!DECL_P (arg))
+		cp_walk_tree (&arg, cp_genericize_r, data, NULL);
+	    }
+	}
       return NULL;
     }
 
--- gcc/testsuite/g++.dg/cpp1y/pr86943.C.jj	2018-11-23 18:04:08.260852111 +0100
+++ gcc/testsuite/g++.dg/cpp1y/pr86943.C	2018-11-23 18:03:45.798224687 +0100
@@ -0,0 +1,32 @@
+// PR c++/86943
+// { dg-do run { target c++14 } }
+
+int c[3];
+
+struct S
+{
+  S () : s (1234) { c[0]++; }
+  S (const S &) { __builtin_abort (); }
+  S (S &&x) noexcept { if (x.s != 1234) __builtin_abort (); s = 1234; x.s = 2345; c[1]++; }
+  ~S () { if (s != 1234 && s != 2345) __builtin_abort (); c[2]++; }
+  int s;
+};
+
+using F = void (*) (S);
+
+F
+foo ()
+{
+  return [] (auto val) { if (val.s != 1234) __builtin_abort (); };
+}
+
+int
+main ()
+{
+  {
+    volatile F f = foo ();
+    f ({});
+  }
+  if (c[0] + c[1] != c[2])
+    __builtin_abort ();
+}

	Jakub


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