Bug 80178

Summary: Class with deleted copy and move constructors uses wrong argument passing ABI
Product: gcc Reporter: Jonathan Wakely <redi>
Component: c++Assignee: Jason Merrill <jason>
Status: RESOLVED FIXED    
Severity: normal CC: jason, richard-gccbugzilla, webrown.cpp
Priority: P3 Keywords: ABI, wrong-code
Version: 6.3.1   
Target Milestone: 8.0   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2017-04-04 00:00:00
Attachments: fix

Description Jonathan Wakely 2017-03-24 18:09:15 UTC
We pass this in a register, but I think the ABI says it should be an invisible reference, because both the copy ctor and move ctor are deleted.

struct A {
  A();
  A &operator=(A &&o);
  void *p;
};
void foo(A);
void bar() {
  foo({});
}

In this example they're implicitly defined as deleted because of the user-provided move assignment operator, but the result is the same whether implicitly or explicitly deleted.

EDG passes this by invisible reference. Clang passes by value, but that's acknowledged to be a bug.
Comment 1 Jason Merrill 2017-03-28 16:28:55 UTC
Hmm, I don't see anything in the ABI about deleted constructors, and a deleted function isn't non-trivial (nor trivial).

That said, I agree that it makes sense for a class with only deleted copy/move ctors to be passed by invisible reference in the case of copy-list-initialization.
Comment 2 Jonathan Wakely 2017-03-28 16:58:08 UTC
This example came from a Clang discussion, and they might also be changing how they handle this. We might want to bring it up on the cxxabi list if there's any doubt what the right behaviour is.

CCing Richard, as I discussed it with him last week.
Comment 3 Jason Merrill 2017-04-05 18:57:00 UTC
Created attachment 41138 [details]
fix

Here's a fix.  I'm nervous about applying it at this point in GCC 7, though.
Comment 4 Jason Merrill 2017-05-08 19:08:39 UTC
Author: jason
Date: Mon May  8 19:08:07 2017
New Revision: 247757

URL: https://gcc.gnu.org/viewcvs?rev=247757&root=gcc&view=rev
Log:
	PR c++/80178 - parameter passing for uncopyable classes

	* tree.c (type_has_nontrivial_copy_init): True for classes with only
	deleted copy/move ctors.
	(remember_deleted_copy, maybe_warn_parm_abi): New.
	* decl.c (require_complete_types_for_parms, check_function_type):
	Call maybe_warn_parm_abi.
	* call.c (convert_for_arg_passing, build_cxx_call): Likewise.

Added:
    trunk/gcc/testsuite/g++.dg/abi/invisiref1.C
    trunk/gcc/testsuite/g++.dg/abi/invisiref1a.C
Modified:
    trunk/gcc/common.opt
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/call.c
    trunk/gcc/cp/cp-tree.h
    trunk/gcc/cp/decl.c
    trunk/gcc/cp/tree.c
Comment 5 Jason Merrill 2017-05-19 18:50:09 UTC
Fixed for gcc 8.