This patch fixes 82878, which turned out to be a problem in genericizing
the call inside a __closure::_FUN () that we synthesize when we're
providing a non-member fn pointer for a non-capturing lambda. That call
is marked as CALL_FROM_THUNK_P, but I elided the check for that when
fixing 78495.
I think the 78495 fix is incorrect. That's when genericizing the call
from an inheriting ctor to the target ctor. That too was setting
CALL_FROM_THUNK_P.
I think the right fix for that was to not set CALL_FROM_THUNK_P. We're
generating that call inside a function whose parms have yet to be bashed
into invisrefs. So not thunky enough.
This patch restores the deleted cp_genericize_r code and elides the
setting of CALL_FROM_THUNK_P during call generation.
Jason, does this look right?
nathan
--
Nathan Sidwell
2017-11-14 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 254686)
+++ cp/call.c (working copy)
@@ -376,18 +376,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 254686)
+++ cp/cp-gimplify.c (working copy)
@@ -1078,6 +1078,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: 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 254686)
+++ 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_)) {}