15
15
// ===----------------------------------------------------------------------===//
16
16
17
17
#include " CFTypeInfo.h"
18
+ #include " ClangAdapter.h"
18
19
#include " ClangDerivedConformances.h"
19
20
#include " ImporterImpl.h"
20
21
#include " SwiftDeclSynthesizer.h"
21
22
#include " swift/AST/ASTContext.h"
23
+ #include " swift/AST/ASTPrinter.h"
22
24
#include " swift/AST/Attr.h"
23
25
#include " swift/AST/AvailabilityInference.h"
24
26
#include " swift/AST/Builtins.h"
@@ -5810,6 +5812,8 @@ namespace {
5810
5812
5811
5813
result->setMemberLoader (&Impl, 0 );
5812
5814
5815
+ Impl.swiftifyProtocol (result);
5816
+
5813
5817
return result;
5814
5818
}
5815
5819
@@ -6031,6 +6035,8 @@ namespace {
6031
6035
}
6032
6036
}
6033
6037
}
6038
+
6039
+ Impl.swiftifyProtocol (result);
6034
6040
return result;
6035
6041
}
6036
6042
@@ -9039,18 +9045,25 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
9039
9045
}
9040
9046
9041
9047
namespace {
9048
+ class SwiftifyInfoPrinter ;
9049
+ static bool swiftifyImpl (SwiftifyInfoPrinter &printer, const FuncDecl *MappedDecl);
9050
+
9042
9051
class SwiftifyInfoPrinter {
9043
9052
public:
9044
9053
static const ssize_t SELF_PARAM_INDEX = -2 ;
9045
9054
static const ssize_t RETURN_VALUE_INDEX = -1 ;
9055
+
9056
+ protected:
9046
9057
clang::ASTContext &ctx;
9058
+ ASTContext &SwiftContext;
9047
9059
llvm::raw_ostream &out;
9048
9060
bool firstParam = true ;
9049
9061
llvm::StringMap<std::string> typeMapping;
9050
9062
9051
- SwiftifyInfoPrinter (clang::ASTContext &ctx, llvm::raw_ostream &out)
9052
- : ctx(ctx), out(out) {
9053
- out << " @_SwiftifyImport(" ;
9063
+ public:
9064
+ SwiftifyInfoPrinter (clang::ASTContext &ctx, ASTContext &SwiftContext, llvm::raw_ostream &out)
9065
+ : ctx(ctx), SwiftContext(SwiftContext), out(out) {
9066
+ out << " (" ;
9054
9067
}
9055
9068
~SwiftifyInfoPrinter () { out << " )" ; }
9056
9069
@@ -9116,15 +9129,20 @@ class SwiftifyInfoPrinter {
9116
9129
out << " ]" ;
9117
9130
}
9118
9131
9119
- private:
9120
- void printSeparator () {
9121
- if (!firstParam) {
9122
- out << " , " ;
9123
- } else {
9124
- firstParam = false ;
9132
+ void printAvailability () {
9133
+ printSeparator ();
9134
+ out << " availability: [ " ;
9135
+ if (!SwiftContext. LangOpts . Target . isOSDarwin () && !SwiftContext. LangOpts . Target . isDriverKit ()) {
9136
+ out << " :] " ;
9137
+ return ;
9125
9138
}
9139
+ printAvailabilityOfType (" Span" );
9140
+ printSeparator ();
9141
+ printAvailabilityOfType (" MutableSpan" );
9142
+ out << " ]" ;
9126
9143
}
9127
9144
9145
+ private:
9128
9146
void printParamOrReturn (ssize_t pointerIndex) {
9129
9147
if (pointerIndex == SELF_PARAM_INDEX)
9130
9148
out << " .self" ;
@@ -9133,75 +9151,191 @@ class SwiftifyInfoPrinter {
9133
9151
else
9134
9152
out << " .param(" << pointerIndex + 1 << " )" ;
9135
9153
}
9154
+
9155
+ ValueDecl *getDecl (StringRef DeclName) {
9156
+ SmallVector<ValueDecl *, 1 > decls;
9157
+ SwiftContext.lookupInSwiftModule (DeclName, decls);
9158
+ assert (decls.size () == 1 );
9159
+ if (decls.size () != 1 ) return nullptr ;
9160
+ return decls[0 ];
9161
+ }
9162
+
9163
+ StringRef getDarwinOSString () {
9164
+ auto Target = SwiftContext.LangOpts .Target ;
9165
+ if (Target.isMacOSX ()) {
9166
+ return " macOS" ;
9167
+ } else if (Target.isTvOS ()) {
9168
+ return " tvOS" ;
9169
+ } else if (Target.isiOS ()) {
9170
+ return " iOS" ;
9171
+ } else if (Target.isWatchOS ()) {
9172
+ return " watchOS" ;
9173
+ } else if (Target.isXROS ()) {
9174
+ return " visionOS" ;
9175
+ }
9176
+ llvm_unreachable (" unknown darwin OS" );
9177
+ }
9178
+
9179
+ void printAvailabilityOfType (StringRef Name) {
9180
+ ValueDecl *D = getDecl (Name);
9181
+ auto Availability = AvailabilityInference::availableRange (D);
9182
+
9183
+ out << " \" " << Name << " \" :" << " \" " << getDarwinOSString () << " " << Availability.getVersionString () << " \" " ;
9184
+ }
9185
+
9186
+ protected:
9187
+ void printSeparator () {
9188
+ if (!firstParam) {
9189
+ out << " , " ;
9190
+ } else {
9191
+ firstParam = false ;
9192
+ }
9193
+ }
9136
9194
};
9137
- } // namespace
9138
9195
9139
- void ClangImporter::Implementation::swiftify (FuncDecl *MappedDecl) {
9140
- if (!SwiftContext.LangOpts .hasFeature (Feature::SafeInteropWrappers))
9141
- return ;
9142
- auto ClangDecl =
9143
- dyn_cast_or_null<clang::FunctionDecl>(MappedDecl->getClangDecl ());
9144
- if (!ClangDecl)
9145
- return ;
9196
+ class SwiftifyProtocolInfoPrinter : public SwiftifyInfoPrinter {
9197
+ public:
9198
+ SwiftifyProtocolInfoPrinter (clang::ASTContext &ctx, ASTContext &SwiftContext, llvm::raw_ostream &out)
9199
+ : SwiftifyInfoPrinter(ctx, SwiftContext, out) {}
9200
+
9201
+ bool printMethod (const FuncDecl *Method) {
9202
+ // don't emit .method() if we know it's going to be empty
9203
+ if (!isa_and_nonnull<clang::ObjCMethodDecl>(Method->getClangDecl ()))
9204
+ return false ;
9205
+
9206
+ printSeparator ();
9207
+ out << " .method(signature: \" " ;
9208
+ printMethodSignature (Method);
9209
+ out << " \" , paramInfo: [" ;
9210
+ // reset firstParam inside paramInfo array. At this point firstParam will
9211
+ // always be false, so no need to save the current value.
9212
+ assert (!firstParam);
9213
+ firstParam = true ;
9214
+ bool hadAttributes = swiftifyImpl (*this , Method);
9215
+ firstParam = false ;
9216
+ out << " ])" ;
9217
+ return hadAttributes;
9218
+ }
9219
+
9220
+ private:
9221
+ void printMethodSignature (const FuncDecl *Method) {
9222
+ auto options = PrintOptions::printForDiagnostics (AccessLevel::Private, true );
9223
+ StreamPrinter printer (out);
9224
+ Method->print (printer, options);
9225
+ }
9226
+ };
9227
+
9228
+ static bool swiftifyImpl (SwiftifyInfoPrinter &printer, const FuncDecl *MappedDecl) {
9229
+ const clang::Decl *ClangDecl = MappedDecl->getClangDecl ();
9230
+ auto FuncD = dyn_cast<clang::FunctionDecl>(ClangDecl);
9231
+ auto MethodD = dyn_cast<clang::ObjCMethodDecl>(ClangDecl);
9232
+ assert (FuncD || MethodD);
9146
9233
9147
- llvm::SmallString<128 > MacroString;
9148
9234
// We only attach the macro if it will produce an overload. Any __counted_by
9149
9235
// will produce an overload, since UnsafeBufferPointer is still an improvement
9150
9236
// over UnsafePointer, but std::span will only produce an overload if it also
9151
9237
// has lifetime information, since std::span already contains bounds info.
9152
9238
bool attachMacro = false ;
9153
- {
9154
- llvm::raw_svector_ostream out (MacroString);
9155
9239
9156
- SwiftifyInfoPrinter printer (getClangASTContext (), out);
9157
- bool returnIsStdSpan = printer.registerStdSpanTypeMapping (
9158
- MappedDecl->getResultInterfaceType (), ClangDecl->getReturnType ());
9159
- if (auto CAT =
9160
- ClangDecl->getReturnType ()->getAs <clang::CountAttributedType>()) {
9161
- printer.printCountedBy (CAT, SwiftifyInfoPrinter::RETURN_VALUE_INDEX);
9162
- attachMacro = true ;
9163
- }
9164
- bool returnHasLifetimeInfo = false ;
9165
- if (SwiftDeclConverter::getImplicitObjectParamAnnotation<
9166
- clang::LifetimeBoundAttr>(ClangDecl)) {
9167
- printer.printLifetimeboundReturn (SwiftifyInfoPrinter::SELF_PARAM_INDEX,
9168
- true );
9240
+ clang::QualType returnType = FuncD ? FuncD->getReturnType () : MethodD->getReturnType ();
9241
+ bool returnIsStdSpan = printer.registerStdSpanTypeMapping (
9242
+ MappedDecl->getResultInterfaceType (), returnType);
9243
+ if (auto CAT = returnType->getAs <clang::CountAttributedType>()) {
9244
+ printer.printCountedBy (CAT, SwiftifyInfoPrinter::RETURN_VALUE_INDEX);
9245
+ attachMacro = true ;
9246
+ }
9247
+ bool returnHasLifetimeInfo = false ;
9248
+ if (FuncD && SwiftDeclConverter::getImplicitObjectParamAnnotation<clang::LifetimeBoundAttr>(FuncD)) {
9249
+ printer.printLifetimeboundReturn (SwiftifyInfoPrinter::SELF_PARAM_INDEX,
9250
+ true );
9251
+ returnHasLifetimeInfo = true ;
9252
+ }
9253
+
9254
+ auto parameters = FuncD ? FuncD->parameters () : MethodD->parameters ();
9255
+ for (auto [index, clangParam] : llvm::enumerate (parameters)) {
9256
+ auto clangParamTy = clangParam->getType ();
9257
+ auto swiftParam = MappedDecl->getParameters ()->get (index);
9258
+ bool paramHasBoundsInfo = false ;
9259
+ if (auto CAT = clangParamTy->getAs <clang::CountAttributedType>()) {
9260
+ printer.printCountedBy (CAT, index);
9261
+ attachMacro = paramHasBoundsInfo = true ;
9262
+ }
9263
+ bool paramIsStdSpan = printer.registerStdSpanTypeMapping (
9264
+ swiftParam->getInterfaceType (), clangParamTy);
9265
+ paramHasBoundsInfo |= paramIsStdSpan;
9266
+
9267
+ bool paramHasLifetimeInfo = false ;
9268
+ if (clangParam->hasAttr <clang::NoEscapeAttr>()) {
9269
+ printer.printNonEscaping (index);
9270
+ paramHasLifetimeInfo = true ;
9271
+ }
9272
+ if (clangParam->hasAttr <clang::LifetimeBoundAttr>()) {
9273
+ printer.printLifetimeboundReturn (
9274
+ index, !paramHasBoundsInfo &&
9275
+ swiftParam->getInterfaceType ()->isEscapable ());
9276
+ paramHasLifetimeInfo = true ;
9169
9277
returnHasLifetimeInfo = true ;
9170
9278
}
9171
- for (auto [index, clangParam] : llvm::enumerate (ClangDecl->parameters ())) {
9172
- auto clangParamTy = clangParam->getType ();
9173
- auto swiftParam = MappedDecl->getParameters ()->get (index);
9174
- bool paramHasBoundsInfo = false ;
9175
- if (auto CAT = clangParamTy->getAs <clang::CountAttributedType>()) {
9176
- printer.printCountedBy (CAT, index);
9177
- attachMacro = paramHasBoundsInfo = true ;
9178
- }
9179
- bool paramIsStdSpan = printer.registerStdSpanTypeMapping (
9180
- swiftParam->getInterfaceType (), clangParamTy);
9181
- paramHasBoundsInfo |= paramIsStdSpan;
9182
-
9183
- bool paramHasLifetimeInfo = false ;
9184
- if (clangParam->hasAttr <clang::NoEscapeAttr>()) {
9185
- printer.printNonEscaping (index);
9186
- paramHasLifetimeInfo = true ;
9187
- }
9188
- if (clangParam->hasAttr <clang::LifetimeBoundAttr>()) {
9189
- printer.printLifetimeboundReturn (
9190
- index, !paramHasBoundsInfo &&
9191
- swiftParam->getInterfaceType ()->isEscapable ());
9192
- paramHasLifetimeInfo = true ;
9193
- returnHasLifetimeInfo = true ;
9194
- }
9195
- if (paramIsStdSpan && paramHasLifetimeInfo)
9196
- attachMacro = true ;
9197
- }
9198
- if (returnIsStdSpan && returnHasLifetimeInfo)
9279
+ if (paramIsStdSpan && paramHasLifetimeInfo)
9199
9280
attachMacro = true ;
9281
+ }
9282
+ if (returnIsStdSpan && returnHasLifetimeInfo)
9283
+ attachMacro = true ;
9284
+
9285
+ return attachMacro;
9286
+ }
9287
+ } // namespace
9288
+
9289
+ void ClangImporter::Implementation::swiftifyProtocol (
9290
+ NominalTypeDecl *MappedDecl) {
9291
+ if (!SwiftContext.LangOpts .hasFeature (Feature::SafeInteropWrappers))
9292
+ return ;
9293
+ if (!isa<ProtocolDecl, ClassDecl>(MappedDecl))
9294
+ return ;
9295
+
9296
+ llvm::SmallString<128 > MacroString;
9297
+ {
9298
+ llvm::raw_svector_ostream out (MacroString);
9299
+ out << " @_SwiftifyImportProtocol" ;
9300
+
9301
+ bool hasBoundsAttributes = false ;
9302
+ SwiftifyProtocolInfoPrinter printer (getClangASTContext (), SwiftContext, out);
9303
+ for (Decl *SwiftMember : cast<IterableDeclContext>(MappedDecl)->getAllMembers ()) {
9304
+ FuncDecl *SwiftDecl = dyn_cast<FuncDecl>(SwiftMember);
9305
+ if (!SwiftDecl)
9306
+ continue ;
9307
+ hasBoundsAttributes |=
9308
+ printer.printMethod (SwiftDecl);
9309
+ }
9310
+
9311
+ if (!hasBoundsAttributes)
9312
+ return ;
9313
+ printer.printAvailability ();
9314
+ printer.printTypeMapping ();
9315
+ }
9316
+
9317
+ importNontrivialAttribute (MappedDecl, MacroString);
9318
+ }
9319
+
9320
+ void ClangImporter::Implementation::swiftify (
9321
+ FuncDecl *MappedDecl) {
9322
+ if (!SwiftContext.LangOpts .hasFeature (Feature::SafeInteropWrappers))
9323
+ return ;
9324
+ if (!isa_and_nonnull<clang::FunctionDecl>(MappedDecl->getClangDecl ()))
9325
+ return ;
9326
+
9327
+ llvm::SmallString<128 > MacroString;
9328
+ {
9329
+ llvm::raw_svector_ostream out (MacroString);
9330
+ out << " @_SwiftifyImport" ;
9331
+
9332
+ SwiftifyInfoPrinter printer (getClangASTContext (), SwiftContext, out);
9333
+ if (!swiftifyImpl (printer, MappedDecl))
9334
+ return ;
9200
9335
printer.printTypeMapping ();
9201
9336
}
9202
9337
9203
- if (attachMacro)
9204
- importNontrivialAttribute (MappedDecl, MacroString);
9338
+ importNontrivialAttribute (MappedDecl, MacroString);
9205
9339
}
9206
9340
9207
9341
static bool isUsingMacroName (clang::SourceManager &SM,
0 commit comments