1616
1717#include " ImporterImpl.h"
1818#include " swift/AST/ASTContext.h"
19+ #include " swift/AST/ASTPrinter.h"
1920#include " swift/AST/Decl.h"
2021#include " swift/AST/DiagnosticsClangImporter.h"
2122#include " swift/AST/ParameterList.h"
@@ -151,6 +152,7 @@ class SwiftifyInfoPrinter {
151152 out << " \" " ;
152153 }
153154
155+ protected:
154156 void printSeparator () {
155157 if (!firstParam) {
156158 out << " , " ;
@@ -159,6 +161,7 @@ class SwiftifyInfoPrinter {
159161 }
160162 }
161163
164+ private:
162165 void printParamOrReturn (ssize_t pointerIndex) {
163166 if (pointerIndex == SELF_PARAM_INDEX)
164167 out << " .self" ;
@@ -296,12 +299,25 @@ static StringRef getAttributeName(const clang::CountAttributedType *CAT) {
296299 llvm_unreachable (" CountAttributedType cannot be ended_by" );
297300 }
298301}
302+
303+ template <typename T>
304+ static bool getImplicitObjectParamAnnotation (const clang::ObjCMethodDecl* D) {
305+ return false ; // Only C++ methods have implicit params
306+ }
307+
308+ static size_t getNumParams (const clang::ObjCMethodDecl* D) {
309+ return D->param_size ();
310+ }
311+ static size_t getNumParams (const clang::FunctionDecl* D) {
312+ return D->getNumParams ();
313+ }
299314} // namespace
300315
316+ template <typename T>
301317static bool swiftifyImpl (ClangImporter::Implementation &Self,
302318 SwiftifyInfoPrinter &printer,
303319 const AbstractFunctionDecl *MappedDecl,
304- const clang::FunctionDecl *ClangDecl) {
320+ const T *ClangDecl) {
305321 DLOG (" Checking " << *ClangDecl << " for bounds and lifetime info\n " );
306322
307323 // FIXME: for private macro generated functions we do not serialize the
@@ -310,13 +326,6 @@ static bool swiftifyImpl(ClangImporter::Implementation &Self,
310326 ClangDecl->getAccess () == clang::AS_private)
311327 return false ;
312328
313- {
314- UnaliasedInstantiationVisitor visitor;
315- visitor.TraverseType (ClangDecl->getType ());
316- if (visitor.hasUnaliasedInstantiation )
317- return false ;
318- }
319-
320329 clang::ASTContext &clangASTContext = Self.getClangASTContext ();
321330
322331 // We only attach the macro if it will produce an overload. Any __counted_by
@@ -332,9 +341,10 @@ static bool swiftifyImpl(ClangImporter::Implementation &Self,
332341 swiftReturnTy = ctorDecl->getResultInterfaceType ();
333342 else
334343 ABORT (" Unexpected AbstractFunctionDecl subclass." );
344+ clang::QualType clangReturnTy = ClangDecl->getReturnType ();
335345 bool returnIsStdSpan = printer.registerStdSpanTypeMapping (
336- swiftReturnTy, ClangDecl-> getReturnType () );
337- auto *CAT = ClangDecl-> getReturnType () ->getAs <clang::CountAttributedType>();
346+ swiftReturnTy, clangReturnTy );
347+ auto *CAT = clangReturnTy ->getAs <clang::CountAttributedType>();
338348 if (SwiftifiableCAT (clangASTContext, CAT, swiftReturnTy)) {
339349 printer.printCountedBy (CAT, SwiftifyInfoPrinter::RETURN_VALUE_INDEX);
340350 DLOG (" Found bounds info '" << clang::QualType (CAT, 0 ) << " ' on return value\n " );
@@ -361,13 +371,13 @@ static bool swiftifyImpl(ClangImporter::Implementation &Self,
361371 size_t swiftNumParams = MappedDecl->getParameters ()->size () -
362372 (ClangDecl->isVariadic () ? 1 : 0 );
363373 ASSERT ((MappedDecl->isImportAsInstanceMember () == isClangInstanceMethod) ==
364- (ClangDecl-> getNumParams () == swiftNumParams));
374+ (getNumParams (ClangDecl ) == swiftNumParams));
365375
366376 size_t selfParamIndex = MappedDecl->isImportAsInstanceMember ()
367377 ? MappedDecl->getSelfIndex ()
368- : ClangDecl-> getNumParams ();
378+ : getNumParams (ClangDecl );
369379 for (auto [index, clangParam] : llvm::enumerate (ClangDecl->parameters ())) {
370- auto clangParamTy = clangParam->getType ();
380+ clang::QualType clangParamTy = clangParam->getType ();
371381 int mappedIndex = index < selfParamIndex ? index :
372382 index > selfParamIndex ? index - 1 :
373383 SwiftifyInfoPrinter::SELF_PARAM_INDEX;
@@ -383,13 +393,12 @@ static bool swiftifyImpl(ClangImporter::Implementation &Self,
383393 auto *CAT = clangParamTy->getAs <clang::CountAttributedType>();
384394 if (CAT && mappedIndex == SwiftifyInfoPrinter::SELF_PARAM_INDEX) {
385395 Self.diagnose (HeaderLoc (clangParam->getLocation ()),
386- diag::warn_clang_ignored_bounds_on_self,
387- getAttributeName (CAT));
388- auto swiftName = ClangDecl->getAttr <clang::SwiftNameAttr>();
396+ diag::warn_clang_ignored_bounds_on_self, getAttributeName (CAT));
397+ auto swiftName = ClangDecl->template getAttr <clang::SwiftNameAttr>();
389398 ASSERT (swiftName &&
390399 " free function mapped to instance method without swift_name??" );
391400 Self.diagnose (HeaderLoc (swiftName->getLocation ()),
392- diag::note_swift_name_instance_method);
401+ diag::note_swift_name_instance_method);
393402 } else if (SwiftifiableCAT (clangASTContext, CAT, swiftParamTy)) {
394403 printer.printCountedBy (CAT, mappedIndex);
395404 DLOG (" Found bounds info '" << clangParamTy << " ' on parameter '"
@@ -401,7 +410,7 @@ static bool swiftifyImpl(ClangImporter::Implementation &Self,
401410 paramHasBoundsInfo |= paramIsStdSpan;
402411
403412 bool paramHasLifetimeInfo = false ;
404- if (clangParam->hasAttr <clang::NoEscapeAttr>()) {
413+ if (clangParam->template hasAttr <clang::NoEscapeAttr>()) {
405414 DLOG (" Found noescape attribute on parameter '" << *clangParam << " '\n " );
406415 printer.printNonEscaping (mappedIndex);
407416 paramHasLifetimeInfo = true ;
@@ -435,6 +444,47 @@ static bool swiftifyImpl(ClangImporter::Implementation &Self,
435444 return attachMacro;
436445}
437446
447+ class SwiftifyProtocolInfoPrinter : public SwiftifyInfoPrinter {
448+ private:
449+ ClangImporter::Implementation &ImporterImpl;
450+
451+ public:
452+ SwiftifyProtocolInfoPrinter (ClangImporter::Implementation &ImporterImpl,
453+ clang::ASTContext &ctx, ASTContext &SwiftContext,
454+ llvm::raw_ostream &out,
455+ MacroDecl &SwiftifyImportDecl)
456+ : SwiftifyInfoPrinter(ctx, SwiftContext, out, SwiftifyImportDecl),
457+ ImporterImpl (ImporterImpl) {}
458+
459+ bool printMethod (const FuncDecl *Method) {
460+ // don't emit .method() if we know it's going to be empty
461+ auto ClangDecl = dyn_cast_or_null<clang::ObjCMethodDecl>(Method->getClangDecl ());
462+ if (!ClangDecl)
463+ return false ;
464+
465+ printSeparator ();
466+ out << " .method(signature: \" " ;
467+ printMethodSignature (Method);
468+ out << " \" , paramInfo: [" ;
469+ // reset firstParam inside paramInfo array. At this point firstParam will
470+ // always be false, so no need to save the current value.
471+ assert (!firstParam);
472+ firstParam = true ;
473+ bool hadAttributes = swiftifyImpl (ImporterImpl, *this , Method, ClangDecl);
474+ firstParam = false ;
475+ out << " ])" ;
476+ return hadAttributes;
477+ }
478+
479+ private:
480+ void printMethodSignature (const FuncDecl *Method) {
481+ auto options =
482+ PrintOptions::printForDiagnostics (AccessLevel::Private, true );
483+ StreamPrinter printer (out);
484+ Method->print (printer, options);
485+ }
486+ };
487+
438488void ClangImporter::Implementation::swiftify (AbstractFunctionDecl *MappedDecl) {
439489 if (!SwiftContext.LangOpts .hasFeature (Feature::SafeInteropWrappers) ||
440490 SwiftContext.ClangImporterOpts .DisableSafeInteropWrappers )
@@ -443,6 +493,13 @@ void ClangImporter::Implementation::swiftify(AbstractFunctionDecl *MappedDecl) {
443493 if (!ClangDecl)
444494 return ;
445495
496+ {
497+ UnaliasedInstantiationVisitor visitor;
498+ visitor.TraverseType (ClangDecl->getType ());
499+ if (visitor.hasUnaliasedInstantiation )
500+ return ;
501+ }
502+
446503 MacroDecl *SwiftifyImportDecl = dyn_cast_or_null<MacroDecl>(getKnownSingleDecl (SwiftContext, " _SwiftifyImport" ));
447504 if (!SwiftifyImportDecl)
448505 return ;
@@ -479,3 +536,43 @@ void ClangImporter::Implementation::swiftify(AbstractFunctionDecl *MappedDecl) {
479536 }
480537}
481538
539+ void ClangImporter::Implementation::swiftifyProtocol (
540+ NominalTypeDecl *MappedDecl) {
541+ if (!SwiftContext.LangOpts .hasFeature (Feature::SafeInteropWrappers) ||
542+ SwiftContext.ClangImporterOpts .DisableSafeInteropWrappers )
543+ return ;
544+ if (!isa<ProtocolDecl, ClassDecl>(MappedDecl))
545+ return ;
546+
547+ MacroDecl *SwiftifyImportDecl = dyn_cast_or_null<MacroDecl>(
548+ getKnownSingleDecl (SwiftContext, " _SwiftifyImportProtocol" ));
549+ if (!SwiftifyImportDecl)
550+ return ;
551+
552+ DLOG (" Checking " << MappedDecl->getName () << " protocol for methods with bounds and lifetime info\n " );
553+ llvm::SmallString<128 > MacroString;
554+ {
555+ llvm::raw_svector_ostream out (MacroString);
556+ out << " @_SwiftifyImportProtocol" ;
557+
558+ bool hasBoundsAttributes = false ;
559+ SwiftifyProtocolInfoPrinter printer (*this , getClangASTContext (),
560+ SwiftContext, out, *SwiftifyImportDecl);
561+ for (Decl *SwiftMember :
562+ cast<IterableDeclContext>(MappedDecl)->getAllMembers ()) {
563+ FuncDecl *SwiftDecl = dyn_cast<FuncDecl>(SwiftMember);
564+ if (!SwiftDecl)
565+ continue ;
566+ hasBoundsAttributes |= printer.printMethod (SwiftDecl);
567+ }
568+
569+ if (!hasBoundsAttributes)
570+ return ;
571+ printer.printAvailability ();
572+ printer.printTypeMapping ();
573+ }
574+
575+ DLOG (" Attaching safe interop macro: " << MacroString << " \n " );
576+ importNontrivialAttribute (MappedDecl, MacroString);
577+ }
578+
0 commit comments