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