]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
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>
Fri, 12 Feb 2021 02:30:08 +0000 (21:30 -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 11b836f7bb976e13be7f57e9d6cbae4e264d46d4..8553f18f845e22b6e857df8b089f71d42b1bcf7b 100644 (file)
@@ -606,6 +606,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){};