c++: generic lambda, fn* conv, empty class [PR98326]
authorJason Merrill <jason@redhat.com>
Mon, 8 Feb 2021 22:04:03 +0000 (17:04 -0500)
committerJason Merrill <jason@redhat.com>
Tue, 9 Feb 2021 01:51:51 +0000 (20:51 -0500)
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
gcc/testsuite/g++.dg/cpp1y/lambda-generic-empty1.C [new file with mode: 0644]

index 4d0e92c332180f9ccc9365c8fee8f1d9596a5909..1c5e15b957fd9907f871780e11aca4a305b0d6e7 100644 (file)
@@ -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 (file)
index 0000000..ffb0cf1
--- /dev/null
@@ -0,0 +1,9 @@
+// PR c++/98326
+// { dg-do compile { target c++14 } }
+
+struct A {
+    A() = default;
+    A(const A&) {}
+};
+
+void (*fptr)(A) = [](auto){};