30
30
#include " swift/ClangImporter/ClangImporter.h"
31
31
#include " swift/IRGen/IRABIDetailsProvider.h"
32
32
#include " clang/AST/ASTContext.h"
33
+ #include " clang/AST/Attr.h"
33
34
#include " clang/AST/DeclObjC.h"
34
35
#include " llvm/ADT/STLExtras.h"
35
36
@@ -281,6 +282,25 @@ class CFunctionSignatureTypePrinter
281
282
os << " __strong" ;
282
283
printInoutTypeModifier ();
283
284
}
285
+ if (isa<clang::CXXRecordDecl>(cd->getClangDecl ())) {
286
+ if (std::find_if (
287
+ cd->getClangDecl ()->getAttrs ().begin (),
288
+ cd->getClangDecl ()->getAttrs ().end (), [](clang::Attr *attr) {
289
+ if (auto *sa = dyn_cast<clang::SwiftAttrAttr>(attr)) {
290
+ llvm::StringRef value = sa->getAttribute ();
291
+ if ((value.startswith (" retain:" ) ||
292
+ value.startswith (" release:" )) &&
293
+ !value.endswith (" :immortal" ))
294
+ return true ;
295
+ }
296
+ return false ;
297
+ }) != cd->getClangDecl ()->getAttrs ().end ()) {
298
+ // This is a shared FRT. Do not bridge it back to
299
+ // C++ as its ownership is not managed automatically
300
+ // in C++ yet.
301
+ return ClangRepresentation::unsupported;
302
+ }
303
+ }
284
304
// FIXME: Mark that this is only ObjC representable.
285
305
return ClangRepresentation::representable;
286
306
}
@@ -966,7 +986,7 @@ void DeclAndTypeClangFunctionPrinter::printTypeImplTypeSpecifier(
966
986
967
987
void DeclAndTypeClangFunctionPrinter::printCxxToCFunctionParameterUse (
968
988
Type type, StringRef name, const ModuleDecl *moduleContext, bool isInOut,
969
- bool isIndirect, std::string directTypeEncoding, bool isSelf ) {
989
+ bool isIndirect, std::string directTypeEncoding, bool forceSelf ) {
970
990
auto namePrinter = [&]() { ClangSyntaxPrinter (os).printIdentifier (name); };
971
991
if (!isKnownCxxType (type, typeMapping) &&
972
992
!hasKnownOptionalNullableCxxMapping (type)) {
@@ -1007,9 +1027,9 @@ void DeclAndTypeClangFunctionPrinter::printCxxToCFunctionParameterUse(
1007
1027
} else {
1008
1028
ClangValueTypePrinter (os, cPrologueOS, interopContext)
1009
1029
.printParameterCxxToCUseScaffold (
1010
- moduleContext,
1011
- [&]() { printTypeImplTypeSpecifier (type, moduleContext); },
1012
- namePrinter, isSelf );
1030
+ moduleContext,
1031
+ [&]() { printTypeImplTypeSpecifier (type, moduleContext); },
1032
+ namePrinter, forceSelf );
1013
1033
}
1014
1034
if (!directTypeEncoding.empty ())
1015
1035
os << ' )' ;
@@ -1153,6 +1173,82 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
1153
1173
break ;
1154
1174
}
1155
1175
}
1176
+
1177
+ auto getParamName = [&](const ParamDecl ¶m, size_t paramIndex,
1178
+ bool isConsumed) {
1179
+ std::string paramName;
1180
+ if (isConsumed)
1181
+ paramName = " consumedParamCopy_" ;
1182
+ if (param.isSelfParameter ()) {
1183
+ if (isConsumed)
1184
+ paramName += " this" ;
1185
+ else
1186
+ paramName = " *this" ;
1187
+ } else if (param.getName ().empty ()) {
1188
+ llvm::raw_string_ostream paramOS (paramName);
1189
+ if (!isConsumed)
1190
+ paramOS << " _" ;
1191
+ paramOS << paramIndex;
1192
+ } else {
1193
+ StringRef nameStr = param.getName ().str ();
1194
+ if (isConsumed)
1195
+ paramName += nameStr.str ();
1196
+ else
1197
+ paramName = nameStr;
1198
+ renameCxxParameterIfNeeded (FD, paramName);
1199
+ }
1200
+ return paramName;
1201
+ };
1202
+
1203
+ // Check if we need to copy any parameters that are consumed by Swift,
1204
+ // to ensure that Swift does not destroy the value that's owned by C++.
1205
+ // FIXME: Support non-copyable types here as well between C++ -> Swift.
1206
+ // FIXME: class types can be optimized down to an additional retain right
1207
+ // here.
1208
+ size_t paramIndex = 1 ;
1209
+ auto emitParamCopyForConsume = [&](const ParamDecl ¶m) {
1210
+ auto name = getParamName (param, paramIndex, /* isConsumed=*/ false );
1211
+ auto consumedName = getParamName (param, paramIndex, /* isConsumed=*/ true );
1212
+ std::string paramType;
1213
+
1214
+ llvm::raw_string_ostream typeOS (paramType);
1215
+
1216
+ CFunctionSignatureTypePrinter typePrinter (
1217
+ typeOS, cPrologueOS, typeMapping, OutputLanguageMode::Cxx,
1218
+ interopContext, CFunctionSignatureTypePrinterModifierDelegate (),
1219
+ moduleContext, declPrinter, FunctionSignatureTypeUse::TypeReference);
1220
+ auto result = typePrinter.visit (param.getInterfaceType (), OTK_None,
1221
+ /* isInOutParam=*/ false );
1222
+ assert (!result.isUnsupported ());
1223
+ typeOS.flush ();
1224
+
1225
+ os << " alignas(alignof(" << paramType << " )) char copyBuffer_"
1226
+ << consumedName << " [sizeof(" << paramType << " )];\n " ;
1227
+ os << " auto &" << consumedName << " = *(new(copyBuffer_" << consumedName
1228
+ << " ) " << paramType << " (" << name << " ));\n " ;
1229
+ os << " swift::" << cxx_synthesis::getCxxImplNamespaceName ()
1230
+ << " ::ConsumedValueStorageDestroyer<" << paramType << " > storageGuard_"
1231
+ << consumedName << " (" << consumedName << " );\n " ;
1232
+ };
1233
+ signature.visitParameterList (
1234
+ [&](const LoweredFunctionSignature::IndirectResultValue &) {},
1235
+ [&](const LoweredFunctionSignature::DirectParameter ¶m) {
1236
+ if (isConsumedParameter (param.getConvention ()))
1237
+ emitParamCopyForConsume (param.getParamDecl ());
1238
+ ++paramIndex;
1239
+ },
1240
+ [&](const LoweredFunctionSignature::IndirectParameter ¶m) {
1241
+ if (isConsumedParameter (param.getConvention ()))
1242
+ emitParamCopyForConsume (param.getParamDecl ());
1243
+ ++paramIndex;
1244
+ },
1245
+ [&](const LoweredFunctionSignature::GenericRequirementParameter
1246
+ &genericRequirementParam) {},
1247
+ [&](const LoweredFunctionSignature::MetadataSourceParameter
1248
+ &metadataSrcParam) {},
1249
+ [&](const LoweredFunctionSignature::ContextParameter &) {},
1250
+ [&](const LoweredFunctionSignature::ErrorResultValue &) {});
1251
+
1156
1252
auto printCallToCFunc = [&](llvm::Optional<StringRef> additionalParam) {
1157
1253
if (indirectFunctionVar)
1158
1254
os << " (* " << *indirectFunctionVar << ' )' ;
@@ -1168,13 +1264,14 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
1168
1264
needsComma = true ;
1169
1265
};
1170
1266
auto printParamUse = [&](const ParamDecl ¶m, bool isIndirect,
1267
+ bool isConsumed,
1171
1268
1172
1269
std::string directTypeEncoding) {
1173
1270
emitNewParam ();
1174
- std::string paramName;
1175
1271
if (param.isSelfParameter ()) {
1176
1272
bool needsStaticSelf = isa<ConstructorDecl>(FD) || isStaticMethod;
1177
1273
if (needsStaticSelf) {
1274
+ // Static self value is just the type's metadata value.
1178
1275
os << " swift::TypeMetadataTrait<" ;
1179
1276
CFunctionSignatureTypePrinter typePrinter (
1180
1277
os, cPrologueOS, typeMapping, OutputLanguageMode::Cxx,
@@ -1187,19 +1284,13 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
1187
1284
os << " >::getTypeMetadata()" ;
1188
1285
return ;
1189
1286
}
1190
- paramName = " *this" ;
1191
- } else if (param.getName ().empty ()) {
1192
- llvm::raw_string_ostream paramOS (paramName);
1193
- paramOS << " _" << paramIndex;
1194
- } else {
1195
- paramName = param.getName ().str ().str ();
1196
- renameCxxParameterIfNeeded (FD, paramName);
1197
1287
}
1288
+ auto paramName = getParamName (param, paramIndex, isConsumed);
1198
1289
++paramIndex;
1199
1290
printCxxToCFunctionParameterUse (param.getInterfaceType (), paramName,
1200
1291
param.getModuleContext (), param.isInOut (),
1201
1292
isIndirect, directTypeEncoding,
1202
- param.isSelfParameter ());
1293
+ !isConsumed && param.isSelfParameter ());
1203
1294
};
1204
1295
1205
1296
signature.visitParameterList (
@@ -1211,10 +1302,12 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
1211
1302
},
1212
1303
[&](const LoweredFunctionSignature::DirectParameter ¶m) {
1213
1304
printParamUse (param.getParamDecl (), /* isIndirect=*/ false ,
1305
+ isConsumedParameter (param.getConvention ()),
1214
1306
encodeTypeInfo (param, moduleContext, typeMapping));
1215
1307
},
1216
1308
[&](const LoweredFunctionSignature::IndirectParameter ¶m) {
1217
1309
printParamUse (param.getParamDecl (), /* isIndirect=*/ true ,
1310
+ isConsumedParameter (param.getConvention ()),
1218
1311
/* directTypeEncoding=*/ " " );
1219
1312
},
1220
1313
[&](const LoweredFunctionSignature::GenericRequirementParameter
0 commit comments