@@ -2160,12 +2160,33 @@ void make_narg_call(const FunctionDecl* FD, const std::string& return_type,
2160
2160
}
2161
2161
}
2162
2162
2163
+ CXXRecordDecl* rtdecl = QT->getAsCXXRecordDecl ();
2163
2164
if (refType != kNotReference ) {
2164
2165
callbuf << " (" << type_name.c_str ()
2165
2166
<< (refType == kLValueReference ? " &" : " &&" ) << " )*("
2166
2167
<< type_name.c_str () << " *)args[" << i << " ]" ;
2167
2168
} else if (isPointer) {
2168
2169
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 << " ])" ;
2169
2190
} else {
2170
2191
// pointer falls back to non-pointer case; the argument preserves
2171
2192
// the "pointerness" (i.e. doesn't reference the value).
0 commit comments