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] c++/78495 inherited ctor and inivis-ref parm


Bug 78495 is a wrong code bug caused by an invisiref parm. When building the inherited ctor, we use forward_parm to create a forwarding reference. That code generation considers the type of the parm to be 'T'. We thus end up with a tree that looks like *&PARM

The subsequent call gets 'CALL_FROM_THUNK' set. We need that set so code generation doesn't copy pass-by-invisiref objects that are specified by the C abi (but not specified so by the C++ abi) (POD structs, commonly).

cp_genericize is used to mutate invisiref parm_decls from T to &T and bash their uses from PARM to *PARM (with suitable checking of &PARM turning into plain PARM). However it explicitly skips genericizing the args of a CALL_FROM_THUNK tree. Thus we end up taking the address of the reference parm itself.

That appears to be incorrect now we have forward_parm. This patch deletes that skipping.

ok?

nathan
--
Nathan Sidwell
2017-01-20  Nathan Sidwell  <nathan@acm.org>

	PR c++/78495 - wrong code inherited ctor and invisi-ref parm
	* cp-gimplify.c (cp_generize_r): Don't skip thunks.

	PR c++/79495
	* g++.dg/cpp1z/inh-ctor38.C: New.

Index: cp/cp-gimplify.c
===================================================================
--- cp/cp-gimplify.c	(revision 244596)
+++ cp/cp-gimplify.c	(working copy)
@@ -1103,15 +1103,7 @@ 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;
-    }
-
-  /* Otherwise, do dereference invisible reference parms.  */
+  /* Dereference invisible reference parms.  */
   if (wtd->handle_invisiref_parm_p && is_invisiref_parm (stmt))
     {
       *stmt_p = convert_from_reference (stmt);
Index: testsuite/g++.dg/cpp1z/inh-ctor38.C
===================================================================
--- testsuite/g++.dg/cpp1z/inh-ctor38.C	(revision 0)
+++ testsuite/g++.dg/cpp1z/inh-ctor38.C	(working copy)
@@ -0,0 +1,31 @@
+// { dg-do run { target c++11 } }
+// PR78495 failed to propagate pass-by-value struct to base ctor.
+
+struct Ptr {
+  void *ptr = 0;
+
+  Ptr() {}
+  Ptr(Ptr const&) = delete;
+  Ptr(Ptr&& other) : ptr (other.ptr) {}
+};
+
+struct Base {
+  Ptr val;
+  Base(Ptr val_) : val(static_cast<Ptr&&>(val_)) {}
+};
+
+struct Derived: Base {
+  using Base::Base;
+};
+
+void *Foo () {
+  Ptr ptr;
+
+  Derived d(static_cast<Ptr&&>(ptr));
+
+  return d.val.ptr;
+}
+
+int main () {
+  return Foo () != 0;
+}

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