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_)) {}