From bdbca69e0720fa9062fe71782235141f629ae006 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 8 Feb 2021 17:04:03 -0500 Subject: [PATCH] c++: generic lambda, fn* conv, empty class [PR98326] Here, in the thunk returned from the captureless lambda conversion to pointer-to-function, we try to pass through invisible reference parameters by reference, without doing a copy. The empty class copy optimization was messing that up. gcc/cp/ChangeLog: PR c++/98326 PR c++/20408 * cp-gimplify.c (simple_empty_class_p): Don't touch an invisiref parm. gcc/testsuite/ChangeLog: PR c++/98326 * g++.dg/cpp1y/lambda-generic-empty1.C: New test. --- gcc/cp/cp-gimplify.c | 12 ++++++++++++ gcc/testsuite/g++.dg/cpp1y/lambda-generic-empty1.C | 9 +++++++++ 2 files changed, 21 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-empty1.C diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index 4d0e92c..1c5e15b 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -324,6 +324,18 @@ simple_empty_class_p (tree type, tree op, tree_code code) && TYPE_HAS_TRIVIAL_DESTRUCTOR (type)) /* The TARGET_EXPR is itself a simple copy, look through it. */ return simple_empty_class_p (type, TARGET_EXPR_INITIAL (op), code); + + if (TREE_CODE (op) == PARM_DECL + && TREE_ADDRESSABLE (TREE_TYPE (op))) + { + tree fn = DECL_CONTEXT (op); + if (DECL_THUNK_P (fn) + || lambda_static_thunk_p (fn)) + /* In a thunk, we pass through invisible reference parms, so this isn't + actually a copy. */ + return false; + } + return (TREE_CODE (op) == EMPTY_CLASS_EXPR || code == MODIFY_EXPR diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-empty1.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-empty1.C new file mode 100644 index 0000000..ffb0cf1 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-empty1.C @@ -0,0 +1,9 @@ +// PR c++/98326 +// { dg-do compile { target c++14 } } + +struct A { + A() = default; + A(const A&) {} +}; + +void (*fptr)(A) = [](auto){}; -- 2.7.4