@@ -2531,3 +2531,131 @@ SwiftDeclSynthesizer::makeDefaultArgument(const clang::ParmVarDecl *param,
25312531
25322532 return callExpr;
25332533}
2534+
2535+ // MARK: C++ foreign reference type constructors
2536+
2537+ clang::CXXMethodDecl *
2538+ SwiftDeclSynthesizer::synthesizeStaticFactoryForCXXForeignRef (
2539+ const clang::CXXRecordDecl *cxxRecordDecl) {
2540+
2541+ clang::ASTContext &clangCtx = cxxRecordDecl->getASTContext ();
2542+ clang::Sema &clangSema = ImporterImpl.getClangSema ();
2543+
2544+ clang::QualType cxxRecordTy = clangCtx.getRecordType (cxxRecordDecl);
2545+
2546+ clang::CXXConstructorDecl *defaultCtorDecl = nullptr ;
2547+ for (clang::CXXConstructorDecl *ctor : cxxRecordDecl->ctors ()) {
2548+ if (ctor->parameters ().empty () && !ctor->isDeleted () &&
2549+ ctor->getAccess () != clang::AS_private &&
2550+ ctor->getAccess () != clang::AS_protected) {
2551+ defaultCtorDecl = ctor;
2552+ break ;
2553+ }
2554+ }
2555+ if (!defaultCtorDecl)
2556+ return nullptr ;
2557+
2558+ clang::FunctionDecl *operatorNew = nullptr ;
2559+ clang::FunctionDecl *operatorDelete = nullptr ;
2560+ bool passAlignment = false ;
2561+ bool findingAllocFuncFailed = clangSema.FindAllocationFunctions (
2562+ cxxRecordDecl->getLocation (), clang::SourceRange (), clang::Sema::AFS_Both,
2563+ clang::Sema::AFS_Both, cxxRecordTy,
2564+ /* IsArray*/ false , passAlignment, clang::MultiExprArg (), operatorNew,
2565+ operatorDelete, /* Diagnose*/ false );
2566+ if (findingAllocFuncFailed || !operatorNew || operatorNew->isDeleted () ||
2567+ operatorNew->getAccess () == clang::AS_private ||
2568+ operatorNew->getAccess () == clang::AS_protected)
2569+ return nullptr ;
2570+
2571+ clang::QualType cxxRecordPtrTy = clangCtx.getPointerType (cxxRecordTy);
2572+ // Adding `_Nonnull` to the return type of synthesized static factory
2573+ bool nullabilityCannotBeAdded =
2574+ clangSema.CheckImplicitNullabilityTypeSpecifier (
2575+ cxxRecordPtrTy, clang::NullabilityKind::NonNull,
2576+ cxxRecordDecl->getLocation (),
2577+ /* isParam=*/ false ,
2578+ /* OverrideExisting=*/ true );
2579+ assert (!nullabilityCannotBeAdded &&
2580+ " Failed to add _Nonnull specifier to synthesized "
2581+ " static factory's return type" );
2582+
2583+ clang::IdentifierTable &clangIdents = clangCtx.Idents ;
2584+ clang::IdentifierInfo *funcNameToSynthesize = &clangIdents.get (
2585+ (" __returns_" + cxxRecordDecl->getNameAsString ()).c_str ());
2586+ clang::FunctionProtoType::ExtProtoInfo EPI;
2587+ clang::QualType funcTypeToSynthesize =
2588+ clangCtx.getFunctionType (cxxRecordPtrTy, {}, EPI);
2589+
2590+ clang::CXXMethodDecl *synthesizedCxxMethodDecl = clang::CXXMethodDecl::Create (
2591+ clangCtx, const_cast <clang::CXXRecordDecl *>(cxxRecordDecl),
2592+ cxxRecordDecl->getLocation (),
2593+ clang::DeclarationNameInfo (funcNameToSynthesize,
2594+ cxxRecordDecl->getLocation ()),
2595+ funcTypeToSynthesize,
2596+ clangCtx.getTrivialTypeSourceInfo (funcTypeToSynthesize), clang::SC_Static,
2597+ /* UsesFPIntrin=*/ false , /* isInline=*/ true ,
2598+ clang::ConstexprSpecKind::Unspecified, cxxRecordDecl->getLocation ());
2599+ assert (synthesizedCxxMethodDecl &&
2600+ " Unable to synthesize static factory for c++ foreign reference type" );
2601+ synthesizedCxxMethodDecl->setAccess (clang::AccessSpecifier::AS_public);
2602+
2603+ if (!hasImmortalAttrs (cxxRecordDecl)) {
2604+ clang::SwiftAttrAttr *returnsRetainedAttrForSynthesizedCxxMethodDecl =
2605+ clang::SwiftAttrAttr::Create (clangCtx, " returns_retained" );
2606+ synthesizedCxxMethodDecl->addAttr (
2607+ returnsRetainedAttrForSynthesizedCxxMethodDecl);
2608+ }
2609+
2610+ clang::SwiftNameAttr *swiftNameInitAttrForSynthesizedCxxMethodDecl =
2611+ clang::SwiftNameAttr::Create (clangCtx, " init()" );
2612+ synthesizedCxxMethodDecl->addAttr (
2613+ swiftNameInitAttrForSynthesizedCxxMethodDecl);
2614+
2615+ clang::ExprResult synthesizedConstructExprResult =
2616+ clangSema.BuildCXXConstructExpr (
2617+ clang::SourceLocation (), cxxRecordTy, defaultCtorDecl,
2618+ /* Elidable=*/ false , clang::MultiExprArg (),
2619+ /* HadMultipleCandidates=*/ false ,
2620+ /* IsListInitialization=*/ false ,
2621+ /* IsStdInitListInitialization=*/ false ,
2622+ /* RequiresZeroInit=*/ false , clang::CXXConstructionKind::Complete,
2623+ clang::SourceRange ());
2624+ assert (!synthesizedConstructExprResult.isInvalid () &&
2625+ " Unable to synthesize constructor expression for c++ foreign "
2626+ " reference type" );
2627+ clang::CXXConstructExpr *synthesizedConstructExpr =
2628+ cast<clang::CXXConstructExpr>(synthesizedConstructExprResult.get ());
2629+
2630+ clang::ExprResult synthesizedNewExprResult = clangSema.BuildCXXNew (
2631+ clang::SourceRange (), /* UseGlobal=*/ false , clang::SourceLocation (), {},
2632+ clang::SourceLocation (), clang::SourceRange (), cxxRecordTy,
2633+ clangCtx.getTrivialTypeSourceInfo (cxxRecordTy), std::nullopt ,
2634+ clang::SourceRange (), synthesizedConstructExpr);
2635+ assert (
2636+ !synthesizedNewExprResult.isInvalid () &&
2637+ " Unable to synthesize `new` expression for c++ foreign reference type" );
2638+ clang::CXXNewExpr *synthesizedNewExpr =
2639+ cast<clang::CXXNewExpr>(synthesizedNewExprResult.get ());
2640+
2641+ clang::ReturnStmt *synthesizedRetStmt =
2642+ clang::ReturnStmt::Create (clangCtx, clang::SourceLocation (),
2643+ synthesizedNewExpr, /* VarDecl=*/ nullptr );
2644+ assert (synthesizedRetStmt && " Unable to synthesize return statement for "
2645+ " static factory of c++ foreign reference type" );
2646+
2647+ clang::CompoundStmt *synthesizedFuncBody = clang::CompoundStmt::Create (
2648+ clangCtx, {synthesizedRetStmt}, clang::FPOptionsOverride (),
2649+ clang::SourceLocation (), clang::SourceLocation ());
2650+ assert (synthesizedRetStmt && " Unable to synthesize function body for static "
2651+ " factory of c++ foreign reference type" );
2652+
2653+ synthesizedCxxMethodDecl->setBody (synthesizedFuncBody);
2654+ synthesizedCxxMethodDecl->addAttr (
2655+ clang::NoDebugAttr::CreateImplicit (clangCtx));
2656+
2657+ synthesizedCxxMethodDecl->setImplicit ();
2658+ synthesizedCxxMethodDecl->setImplicitlyInline ();
2659+
2660+ return synthesizedCxxMethodDecl;
2661+ }
0 commit comments