@@ -2151,12 +2151,33 @@ void make_narg_call(const FunctionDecl* FD, const std::string& return_type,
21512151 }
21522152 }
21532153
2154+ CXXRecordDecl* rtdecl = QT->getAsCXXRecordDecl ();
21542155 if (refType != kNotReference ) {
21552156 callbuf << " (" << type_name.c_str ()
21562157 << (refType == kLValueReference ? " &" : " &&" ) << " )*("
21572158 << type_name.c_str () << " *)args[" << i << " ]" ;
21582159 } else if (isPointer) {
21592160 callbuf << " *(" << type_name.c_str () << " **)args[" << i << " ]" ;
2161+ } else if (rtdecl &&
2162+ (rtdecl->hasTrivialCopyConstructor () &&
2163+ !rtdecl->hasSimpleCopyConstructor ()) &&
2164+ rtdecl->hasMoveConstructor ()) {
2165+ // By-value construction; this may either copy or move, but there is no
2166+ // information here in terms of intent. Thus, simply assume that the
2167+ // intent is to move if there is no viable copy constructor (ie. if the
2168+ // code would otherwise fail to even compile). There does not appear to be
2169+ // a simple way of determining whether a viable copy constructor exists,
2170+ // so check for the most common case: the trivial one, but not uniquely
2171+ // available, while there is a move constructor.
2172+
2173+ // include utility header if not already included for std::move
2174+ DeclarationName DMove = &getASTContext ().Idents .get (" move" );
2175+ auto result = getSema ().getStdNamespace ()->lookup (DMove);
2176+ if (result.empty ())
2177+ Cpp::Declare (" #include <utility>" );
2178+
2179+ // move construction as needed for classes (note that this is implicit)
2180+ callbuf << " std::move(*(" << type_name.c_str () << " *)args[" << i << " ])" ;
21602181 } else {
21612182 // pointer falls back to non-pointer case; the argument preserves
21622183 // the "pointerness" (i.e. doesn't reference the value).
0 commit comments