@@ -2151,12 +2151,33 @@ void make_narg_call(const FunctionDecl* FD, const std::string& return_type,
2151
2151
}
2152
2152
}
2153
2153
2154
+ CXXRecordDecl* rtdecl = QT->getAsCXXRecordDecl ();
2154
2155
if (refType != kNotReference ) {
2155
2156
callbuf << " (" << type_name.c_str ()
2156
2157
<< (refType == kLValueReference ? " &" : " &&" ) << " )*("
2157
2158
<< type_name.c_str () << " *)args[" << i << " ]" ;
2158
2159
} else if (isPointer) {
2159
2160
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 << " ])" ;
2160
2181
} else {
2161
2182
// pointer falls back to non-pointer case; the argument preserves
2162
2183
// the "pointerness" (i.e. doesn't reference the value).
0 commit comments