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