1515// ===----------------------------------------------------------------------===//
1616
1717#include " CFTypeInfo.h"
18+ #include " ClangAdapter.h"
1819#include " ClangDerivedConformances.h"
1920#include " ImporterImpl.h"
2021#include " SwiftDeclSynthesizer.h"
2122#include " swift/AST/ASTContext.h"
23+ #include " swift/AST/ASTPrinter.h"
2224#include " swift/AST/Attr.h"
2325#include " swift/AST/AvailabilityInference.h"
2426#include " swift/AST/Builtins.h"
@@ -5810,6 +5812,8 @@ namespace {
58105812
58115813 result->setMemberLoader (&Impl, 0 );
58125814
5815+ Impl.swiftifyProtocol (result);
5816+
58135817 return result;
58145818 }
58155819
@@ -6031,6 +6035,8 @@ namespace {
60316035 }
60326036 }
60336037 }
6038+
6039+ Impl.swiftifyProtocol (result);
60346040 return result;
60356041 }
60366042
@@ -9039,18 +9045,25 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
90399045}
90409046
90419047namespace {
9048+ class SwiftifyInfoPrinter ;
9049+ static bool swiftifyImpl (SwiftifyInfoPrinter &printer, const FuncDecl *MappedDecl);
9050+
90429051class SwiftifyInfoPrinter {
90439052public:
90449053 static const ssize_t SELF_PARAM_INDEX = -2 ;
90459054 static const ssize_t RETURN_VALUE_INDEX = -1 ;
9055+
9056+ protected:
90469057 clang::ASTContext &ctx;
9058+ ASTContext &SwiftContext;
90479059 llvm::raw_ostream &out;
90489060 bool firstParam = true ;
90499061 llvm::StringMap<std::string> typeMapping;
90509062
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 << " (" ;
90549067 }
90559068 ~SwiftifyInfoPrinter () { out << " )" ; }
90569069
@@ -9116,15 +9129,20 @@ class SwiftifyInfoPrinter {
91169129 out << " ]" ;
91179130 }
91189131
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 ;
91259138 }
9139+ printAvailabilityOfType (" Span" );
9140+ printSeparator ();
9141+ printAvailabilityOfType (" MutableSpan" );
9142+ out << " ]" ;
91269143 }
91279144
9145+ private:
91289146 void printParamOrReturn (ssize_t pointerIndex) {
91299147 if (pointerIndex == SELF_PARAM_INDEX)
91309148 out << " .self" ;
@@ -9133,75 +9151,191 @@ class SwiftifyInfoPrinter {
91339151 else
91349152 out << " .param(" << pointerIndex + 1 << " )" ;
91359153 }
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+ }
91369194};
9137- } // namespace
91389195
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);
91469233
9147- llvm::SmallString<128 > MacroString;
91489234 // We only attach the macro if it will produce an overload. Any __counted_by
91499235 // will produce an overload, since UnsafeBufferPointer is still an improvement
91509236 // over UnsafePointer, but std::span will only produce an overload if it also
91519237 // has lifetime information, since std::span already contains bounds info.
91529238 bool attachMacro = false ;
9153- {
9154- llvm::raw_svector_ostream out (MacroString);
91559239
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 ;
91699277 returnHasLifetimeInfo = true ;
91709278 }
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)
91999280 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 ;
92009335 printer.printTypeMapping ();
92019336 }
92029337
9203- if (attachMacro)
9204- importNontrivialAttribute (MappedDecl, MacroString);
9338+ importNontrivialAttribute (MappedDecl, MacroString);
92059339}
92069340
92079341static bool isUsingMacroName (clang::SourceManager &SM,
0 commit comments