@@ -2160,12 +2160,33 @@ void make_narg_call(const FunctionDecl* FD, const std::string& return_type,
21602160 }
21612161 }
21622162
2163+ CXXRecordDecl* rtdecl = QT->getAsCXXRecordDecl ();
21632164 if (refType != kNotReference ) {
21642165 callbuf << " (" << type_name.c_str ()
21652166 << (refType == kLValueReference ? " &" : " &&" ) << " )*("
21662167 << type_name.c_str () << " *)args[" << i << " ]" ;
21672168 } else if (isPointer) {
21682169 callbuf << " *(" << type_name.c_str () << " **)args[" << i << " ]" ;
2170+ } else if (rtdecl &&
2171+ (rtdecl->hasTrivialCopyConstructor () &&
2172+ !rtdecl->hasSimpleCopyConstructor ()) &&
2173+ rtdecl->hasMoveConstructor ()) {
2174+ // By-value construction; this may either copy or move, but there is no
2175+ // information here in terms of intent. Thus, simply assume that the
2176+ // intent is to move if there is no viable copy constructor (ie. if the
2177+ // code would otherwise fail to even compile). There does not appear to be
2178+ // a simple way of determining whether a viable copy constructor exists,
2179+ // so check for the most common case: the trivial one, but not uniquely
2180+ // available, while there is a move constructor.
2181+
2182+ // include utility header if not already included for std::move
2183+ DeclarationName DMove = &getASTContext ().Idents .get (" move" );
2184+ auto result = getSema ().getStdNamespace ()->lookup (DMove);
2185+ if (result.empty ())
2186+ Cpp::Declare (" #include <utility>" );
2187+
2188+ // move construction as needed for classes (note that this is implicit)
2189+ callbuf << " std::move(*(" << type_name.c_str () << " *)args[" << i << " ])" ;
21692190 } else {
21702191 // pointer falls back to non-pointer case; the argument preserves
21712192 // the "pointerness" (i.e. doesn't reference the value).
0 commit comments