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