@@ -2531,3 +2531,131 @@ SwiftDeclSynthesizer::makeDefaultArgument(const clang::ParmVarDecl *param,
2531
2531
2532
2532
return callExpr;
2533
2533
}
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