I'm applying this backport to the gcc-7 branch. Jonathan was kind enough to point out it's needed tehre.

nathan
--
Nathan Sidwell
2018-01-26  Nathan Sidwell  <nat...@acm.org>

	PR c++/82878
	PR c++/78495
	* call.c (build_call_a): Don't set CALL_FROM_THUNK_P for inherited
	ctor.
	* cp-gimplify.c	(cp_genericize_r): Restore THUNK dereference
	inhibibition check removed in previous c++/78495 change.

	PR c++/82878
	* g++.dg/cpp0x/pr82878.C: New.
	* g++.dg/cpp1z/inh-ctor38.C: Check moves too.

Index: cp/call.c
===================================================================
--- cp/call.c	(revision 257087)
+++ cp/call.c	(working copy)
@@ -375,18 +375,10 @@ build_call_a (tree function, int n, tree
 
   TREE_HAS_CONSTRUCTOR (function) = (decl && DECL_CONSTRUCTOR_P (decl));
 
-  if (current_function_decl && decl
-      && flag_new_inheriting_ctors
-      && DECL_INHERITED_CTOR (current_function_decl)
-      && (DECL_INHERITED_CTOR (current_function_decl)
-	  == DECL_CLONED_FUNCTION (decl)))
-    /* Pass arguments directly to the inherited constructor.  */
-    CALL_FROM_THUNK_P (function) = true;
-
   /* Don't pass empty class objects by value.  This is useful
      for tags in STL, which are used to control overload resolution.
      We don't need to handle other cases of copying empty classes.  */
-  else if (! decl || ! DECL_BUILT_IN (decl))
+  if (! decl || ! DECL_BUILT_IN (decl))
     for (i = 0; i < n; i++)
       {
 	tree arg = CALL_EXPR_ARG (function, i);
Index: cp/cp-gimplify.c
===================================================================
--- cp/cp-gimplify.c	(revision 257087)
+++ cp/cp-gimplify.c	(working copy)
@@ -1107,6 +1107,14 @@ cp_genericize_r (tree *stmt_p, int *walk
       && omp_var_to_track (stmt))
     omp_cxx_notice_variable (wtd->omp_ctx, stmt);
 
+  /* 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;
+    }
+
   /* Dereference invisible reference parms.  */
   if (wtd->handle_invisiref_parm_p && is_invisiref_parm (stmt))
     {
Index: cp/lambda.c
===================================================================
--- cp/lambda.c	(revision 257087)
+++ cp/lambda.c	(working copy)
@@ -1072,7 +1072,6 @@ maybe_add_lambda_conv_op (tree type)
       }
   }
 
-
   if (generic_lambda_p)
     {
       if (decltype_call)
Index: testsuite/g++.dg/cpp0x/pr82878.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr82878.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/pr82878.C	(working copy)
@@ -0,0 +1,20 @@
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-O" }
+// pr 82878 erroneously unwrapped a reference parm in the lambda::_FUN
+// thunk.
+
+struct A {
+  ~A();
+  operator int ();
+};
+
+void baz ();
+
+void
+bar (A b)
+{
+  void (*lam) (A) = [](A) { baz (); };
+
+  if (auto c = b)
+    lam (c);
+}
Index: testsuite/g++.dg/cpp1z/inh-ctor38.C
===================================================================
--- testsuite/g++.dg/cpp1z/inh-ctor38.C	(revision 257087)
+++ testsuite/g++.dg/cpp1z/inh-ctor38.C	(working copy)
@@ -1,17 +1,19 @@
 // { dg-do run { target c++11 } }
 // PR78495 failed to propagate pass-by-value struct to base ctor.
 
+static int moves = 0;
+
 struct Ptr {
   void *ptr = 0;
 
   Ptr() {}
   Ptr(Ptr const&) = delete;
-  Ptr(Ptr&& other) : ptr (other.ptr) {}
+  Ptr(Ptr&& other) : ptr (other.ptr) {moves++;}
 };
 
 struct Base {
   Ptr val;
-  Base(Ptr val_) : val(static_cast<Ptr&&>(val_)) {}
+  Base(Ptr val_);
 };
 
 struct Derived: Base {
@@ -27,5 +29,13 @@ void *Foo () {
 }
 
 int main () {
-  return Foo () != 0;
+  if (Foo ())
+    return 1;
+
+  if (moves != 2)
+    return 2;
+
+  return 0;
 }
+
+Base::Base(Ptr val_) : val(static_cast<Ptr&&>(val_)) {}

Reply via email to