@@ -2534,27 +2534,17 @@ SwiftDeclSynthesizer::makeDefaultArgument(const clang::ParmVarDecl *param,
2534
2534
2535
2535
// MARK: C++ foreign reference type constructors
2536
2536
2537
- clang::CXXMethodDecl *
2537
+ llvm::SmallVector< clang::CXXMethodDecl *, 4 >
2538
2538
SwiftDeclSynthesizer::synthesizeStaticFactoryForCXXForeignRef (
2539
2539
const clang::CXXRecordDecl *cxxRecordDecl) {
2540
2540
2541
2541
clang::ASTContext &clangCtx = cxxRecordDecl->getASTContext ();
2542
2542
clang::Sema &clangSema = ImporterImpl.getClangSema ();
2543
- clang::SourceLocation cxxRecordDeclLoc = cxxRecordDecl->getLocation ();
2544
2543
2545
2544
clang::QualType cxxRecordTy = clangCtx.getRecordType (cxxRecordDecl);
2545
+ clang::SourceLocation cxxRecordDeclLoc = cxxRecordDecl->getLocation ();
2546
2546
2547
- // Todo: synthesize static factories for all available ctors
2548
- clang::CXXConstructorDecl *selectedCtorDecl = nullptr ;
2549
- for (clang::CXXConstructorDecl *ctor : cxxRecordDecl->ctors ()) {
2550
- if (!ctor->isDeleted () && ctor->getAccess () != clang::AS_private &&
2551
- ctor->getAccess () != clang::AS_protected) {
2552
- selectedCtorDecl = ctor;
2553
- break ;
2554
- }
2555
- }
2556
- if (!selectedCtorDecl)
2557
- return nullptr ;
2547
+ llvm::SmallVector<clang::CXXMethodDecl *, 4 > synthesizedFactories;
2558
2548
2559
2549
clang::FunctionDecl *operatorNew = nullptr ;
2560
2550
clang::FunctionDecl *operatorDelete = nullptr ;
@@ -2566,7 +2556,7 @@ SwiftDeclSynthesizer::synthesizeStaticFactoryForCXXForeignRef(
2566
2556
if (findingAllocFuncFailed || !operatorNew || operatorNew->isDeleted () ||
2567
2557
operatorNew->getAccess () == clang::AS_private ||
2568
2558
operatorNew->getAccess () == clang::AS_protected)
2569
- return nullptr ;
2559
+ return synthesizedFactories ;
2570
2560
2571
2561
clang::QualType cxxRecordPtrTy = clangCtx.getPointerType (cxxRecordTy);
2572
2562
// Adding `_Nonnull` to the return type of synthesized static factory
@@ -2579,113 +2569,132 @@ SwiftDeclSynthesizer::synthesizeStaticFactoryForCXXForeignRef(
2579
2569
" static factory's return type" );
2580
2570
2581
2571
clang::IdentifierTable &clangIdents = clangCtx.Idents ;
2582
- clang::IdentifierInfo *funcNameToSynthesize = &clangIdents.get (
2583
- (" __returns_" + cxxRecordDecl->getNameAsString ()).c_str ());
2584
-
2585
- llvm::SmallVector<clang::QualType, 4 > paramTypes;
2586
- for (const auto *param : selectedCtorDecl->parameters ())
2587
- paramTypes.push_back (param->getType ());
2588
- clang::FunctionProtoType::ExtProtoInfo EPI;
2589
- clang::QualType funcTypeToSynthesize =
2590
- clangCtx.getFunctionType (cxxRecordPtrTy, paramTypes, EPI);
2591
-
2592
- clang::CXXMethodDecl *synthesizedCxxMethodDecl = clang::CXXMethodDecl::Create (
2593
- clangCtx, const_cast <clang::CXXRecordDecl *>(cxxRecordDecl),
2594
- cxxRecordDeclLoc,
2595
- clang::DeclarationNameInfo (funcNameToSynthesize, cxxRecordDeclLoc),
2596
- funcTypeToSynthesize,
2597
- clangCtx.getTrivialTypeSourceInfo (funcTypeToSynthesize), clang::SC_Static,
2598
- /* UsesFPIntrin=*/ false , /* isInline=*/ true ,
2599
- clang::ConstexprSpecKind::Unspecified, cxxRecordDeclLoc);
2600
- synthesizedCxxMethodDecl->setAccess (clang::AccessSpecifier::AS_public);
2601
-
2602
- llvm::SmallVector<clang::ParmVarDecl *, 4 > synthesizedParams;
2603
- for (unsigned int i = 0 ; i < selectedCtorDecl->getNumParams (); ++i) {
2604
- auto *origParam = selectedCtorDecl->getParamDecl (i);
2605
- auto *param = clang::ParmVarDecl::Create (
2606
- clangCtx, synthesizedCxxMethodDecl, cxxRecordDeclLoc, cxxRecordDeclLoc,
2607
- origParam->getIdentifier (), origParam->getType (),
2608
- clangCtx.getTrivialTypeSourceInfo (origParam->getType ()), clang::SC_None,
2609
- nullptr );
2610
- synthesizedParams.push_back (param);
2611
- }
2612
- synthesizedCxxMethodDecl->setParams (synthesizedParams);
2613
2572
2614
- if (!hasImmortalAttrs (cxxRecordDecl)) {
2615
- clang::SwiftAttrAttr *returnsRetainedAttrForSynthesizedCxxMethodDecl =
2616
- clang::SwiftAttrAttr::Create (clangCtx, " returns_retained" );
2573
+ for (clang::CXXConstructorDecl *selectedCtorDecl : cxxRecordDecl->ctors ()) {
2574
+ if (selectedCtorDecl->isDeleted () ||
2575
+ selectedCtorDecl->getAccess () == clang::AS_private ||
2576
+ selectedCtorDecl->getAccess () == clang::AS_protected ||
2577
+ selectedCtorDecl->isCopyOrMoveConstructor ())
2578
+ continue ;
2579
+
2580
+ unsigned int ctorParamCount = selectedCtorDecl->getNumParams ();
2581
+ std::string funcName = " __returns_" + cxxRecordDecl->getNameAsString ();
2582
+ if (ctorParamCount > 0 )
2583
+ funcName += " _" + std::to_string (ctorParamCount) + " _params" ;
2584
+ clang::IdentifierInfo *funcNameToSynthesize = &clangIdents.get (funcName);
2585
+
2586
+ llvm::SmallVector<clang::QualType, 4 > paramTypes;
2587
+ for (const auto *param : selectedCtorDecl->parameters ())
2588
+ paramTypes.push_back (param->getType ());
2589
+ clang::FunctionProtoType::ExtProtoInfo EPI;
2590
+ clang::QualType funcTypeToSynthesize =
2591
+ clangCtx.getFunctionType (cxxRecordPtrTy, paramTypes, EPI);
2592
+
2593
+ clang::CXXMethodDecl *synthesizedCxxMethodDecl =
2594
+ clang::CXXMethodDecl::Create (
2595
+ clangCtx, const_cast <clang::CXXRecordDecl *>(cxxRecordDecl),
2596
+ cxxRecordDeclLoc,
2597
+ clang::DeclarationNameInfo (funcNameToSynthesize, cxxRecordDeclLoc),
2598
+ funcTypeToSynthesize,
2599
+ clangCtx.getTrivialTypeSourceInfo (funcTypeToSynthesize),
2600
+ clang::SC_Static, /* UsesFPIntrin=*/ false , /* isInline=*/ true ,
2601
+ clang::ConstexprSpecKind::Unspecified, cxxRecordDeclLoc);
2602
+ assert (
2603
+ synthesizedCxxMethodDecl &&
2604
+ " Unable to synthesize static factory for c++ foreign reference type" );
2605
+ synthesizedCxxMethodDecl->setAccess (clang::AccessSpecifier::AS_public);
2606
+
2607
+ llvm::SmallVector<clang::ParmVarDecl *, 4 > synthesizedParams;
2608
+ for (unsigned int i = 0 ; i < ctorParamCount; ++i) {
2609
+ auto *origParam = selectedCtorDecl->getParamDecl (i);
2610
+ auto *param = clang::ParmVarDecl::Create (
2611
+ clangCtx, synthesizedCxxMethodDecl, cxxRecordDeclLoc,
2612
+ cxxRecordDeclLoc, origParam->getIdentifier (), origParam->getType (),
2613
+ clangCtx.getTrivialTypeSourceInfo (origParam->getType ()),
2614
+ clang::SC_None, nullptr );
2615
+ synthesizedParams.push_back (param);
2616
+ }
2617
+ synthesizedCxxMethodDecl->setParams (synthesizedParams);
2618
+
2619
+ if (!hasImmortalAttrs (cxxRecordDecl)) {
2620
+ clang::SwiftAttrAttr *returnsRetainedAttrForSynthesizedCxxMethodDecl =
2621
+ clang::SwiftAttrAttr::Create (clangCtx, " returns_retained" );
2622
+ synthesizedCxxMethodDecl->addAttr (
2623
+ returnsRetainedAttrForSynthesizedCxxMethodDecl);
2624
+ }
2625
+
2626
+ std::string swiftInitStr = " init(" ;
2627
+ for (unsigned i = 0 ; i < ctorParamCount; ++i) {
2628
+ swiftInitStr += " _:" ;
2629
+ }
2630
+ swiftInitStr += " )" ;
2631
+ clang::SwiftNameAttr *swiftNameAttr =
2632
+ clang::SwiftNameAttr::Create (clangCtx, swiftInitStr);
2633
+ synthesizedCxxMethodDecl->addAttr (swiftNameAttr);
2634
+
2635
+ llvm::SmallVector<clang::Expr *, 8 > ctorArgs;
2636
+ for (auto *param : synthesizedParams) {
2637
+ ctorArgs.push_back (clang::DeclRefExpr::Create (
2638
+ clangCtx, clang::NestedNameSpecifierLoc (), clang::SourceLocation (),
2639
+ param,
2640
+ /* RefersToEnclosingVariableOrCapture=*/ false , clang::SourceLocation (),
2641
+ param->getType (), clang::VK_LValue));
2642
+ }
2643
+ llvm::SmallVector<clang::Expr *, 8 > ctorArgsToAdd;
2644
+ if (clangSema.CompleteConstructorCall (selectedCtorDecl, cxxRecordTy,
2645
+ ctorArgs, cxxRecordDeclLoc,
2646
+ ctorArgsToAdd))
2647
+ continue ;
2648
+
2649
+ clang::ExprResult synthesizedConstructExprResult =
2650
+ clangSema.BuildCXXConstructExpr (
2651
+ cxxRecordDeclLoc, cxxRecordTy, selectedCtorDecl,
2652
+ /* Elidable=*/ false , ctorArgsToAdd,
2653
+ /* HadMultipleCandidates=*/ false ,
2654
+ /* IsListInitialization=*/ false ,
2655
+ /* IsStdInitListInitialization=*/ false ,
2656
+ /* RequiresZeroInit=*/ false , clang::CXXConstructionKind::Complete,
2657
+ clang::SourceRange (cxxRecordDeclLoc, cxxRecordDeclLoc));
2658
+ assert (!synthesizedConstructExprResult.isInvalid () &&
2659
+ " Unable to synthesize constructor expression for c++ foreign "
2660
+ " reference type" );
2661
+ clang::Expr *synthesizedConstructExpr =
2662
+ synthesizedConstructExprResult.get ();
2663
+
2664
+ clang::ExprResult synthesizedNewExprResult = clangSema.BuildCXXNew (
2665
+ clang::SourceRange (), /* UseGlobal=*/ false , clang::SourceLocation (), {},
2666
+ clang::SourceLocation (), clang::SourceRange (), cxxRecordTy,
2667
+ clangCtx.getTrivialTypeSourceInfo (cxxRecordTy), std::nullopt,
2668
+ clang::SourceRange (cxxRecordDeclLoc, cxxRecordDeclLoc),
2669
+ synthesizedConstructExpr);
2670
+ assert (
2671
+ !synthesizedNewExprResult.isInvalid () &&
2672
+ " Unable to synthesize `new` expression for c++ foreign reference type" );
2673
+ clang::CXXNewExpr *synthesizedNewExpr =
2674
+ cast<clang::CXXNewExpr>(synthesizedNewExprResult.get ());
2675
+
2676
+ clang::ReturnStmt *synthesizedRetStmt = clang::ReturnStmt::Create (
2677
+ clangCtx, cxxRecordDeclLoc, synthesizedNewExpr, nullptr );
2678
+ assert (synthesizedRetStmt &&
2679
+ " Unable to synthesize return statement for "
2680
+ " static factory of c++ foreign reference type" );
2681
+
2682
+ clang::CompoundStmt *synthesizedFuncBody = clang::CompoundStmt::Create (
2683
+ clangCtx, {synthesizedRetStmt}, clang::FPOptionsOverride (),
2684
+ cxxRecordDeclLoc, cxxRecordDeclLoc);
2685
+ assert (synthesizedRetStmt &&
2686
+ " Unable to synthesize function body for static "
2687
+ " factory of c++ foreign reference type" );
2688
+
2689
+ synthesizedCxxMethodDecl->setBody (synthesizedFuncBody);
2617
2690
synthesizedCxxMethodDecl->addAttr (
2618
- returnsRetainedAttrForSynthesizedCxxMethodDecl);
2619
- }
2691
+ clang::NoDebugAttr::CreateImplicit (clangCtx));
2620
2692
2621
- std::string swiftInitSig = " init(" ;
2622
- bool first = true ;
2623
- for (auto *param : selectedCtorDecl->parameters ()) {
2624
- if (!first)
2625
- swiftInitSig += " :_" ;
2626
- swiftInitSig += " )" ;
2627
- first = false ;
2628
- }
2629
- clang::SwiftNameAttr *swiftNameAttr =
2630
- clang::SwiftNameAttr::Create (clangCtx, swiftInitSig);
2631
- synthesizedCxxMethodDecl->addAttr (swiftNameAttr);
2632
-
2633
- llvm::SmallVector<clang::Expr *, 8 > ctorArgs;
2634
- for (auto *param : synthesizedParams) {
2635
- ctorArgs.push_back (clang::DeclRefExpr::Create (
2636
- clangCtx, clang::NestedNameSpecifierLoc (), clang::SourceLocation (),
2637
- param,
2638
- /* RefersToEnclosingVariableOrCapture=*/ false , clang::SourceLocation (),
2639
- param->getType (), clang::VK_LValue));
2640
- }
2693
+ synthesizedCxxMethodDecl->setImplicit ();
2694
+ synthesizedCxxMethodDecl->setImplicitlyInline ();
2641
2695
2642
- llvm::SmallVector<clang::Expr *, 8 > convertedCtorArgs;
2643
- if (clangSema.CompleteConstructorCall (selectedCtorDecl, cxxRecordTy, ctorArgs,
2644
- cxxRecordDeclLoc, convertedCtorArgs))
2645
- return nullptr ;
2696
+ synthesizedFactories.push_back (synthesizedCxxMethodDecl);
2697
+ }
2646
2698
2647
- clang::ExprResult synthesizedConstructExprResult =
2648
- clangSema.BuildCXXConstructExpr (
2649
- cxxRecordDeclLoc, cxxRecordTy, selectedCtorDecl,
2650
- /* Elidable=*/ false , convertedCtorArgs,
2651
- /* HadMultipleCandidates=*/ false ,
2652
- /* IsListInitialization=*/ false ,
2653
- /* IsStdInitListInitialization=*/ false ,
2654
- /* RequiresZeroInit=*/ false , clang::CXXConstructionKind::Complete,
2655
- clang::SourceRange (cxxRecordDeclLoc, cxxRecordDeclLoc));
2656
- assert (!synthesizedConstructExprResult.isInvalid () &&
2657
- " Unable to synthesize constructor expression for c++ foreign "
2658
- " reference type" );
2659
- clang::Expr *synthesizedConstructExpr = synthesizedConstructExprResult.get ();
2660
-
2661
- clang::ExprResult synthesizedNewExprResult = clangSema.BuildCXXNew (
2662
- clang::SourceRange (), /* UseGlobal=*/ false , clang::SourceLocation (), {},
2663
- clang::SourceLocation (), clang::SourceRange (), cxxRecordTy,
2664
- clangCtx.getTrivialTypeSourceInfo (cxxRecordTy), std::nullopt,
2665
- clang::SourceRange (cxxRecordDeclLoc, cxxRecordDeclLoc),
2666
- synthesizedConstructExpr);
2667
- assert (
2668
- !synthesizedNewExprResult.isInvalid () &&
2669
- " Unable to synthesize `new` expression for c++ foreign reference type" );
2670
- clang::CXXNewExpr *synthesizedNewExpr =
2671
- cast<clang::CXXNewExpr>(synthesizedNewExprResult.get ());
2672
-
2673
- clang::ReturnStmt *synthesizedRetStmt = clang::ReturnStmt::Create (
2674
- clangCtx, cxxRecordDeclLoc, synthesizedNewExpr, nullptr );
2675
- assert (synthesizedRetStmt && " Unable to synthesize return statement for "
2676
- " static factory of c++ foreign reference type" );
2677
- clang::CompoundStmt *synthesizedFuncBody = clang::CompoundStmt::Create (
2678
- clangCtx, {synthesizedRetStmt}, clang::FPOptionsOverride (),
2679
- cxxRecordDeclLoc, cxxRecordDeclLoc);
2680
- assert (synthesizedRetStmt && " Unable to synthesize function body for static "
2681
- " factory of c++ foreign reference type" );
2682
-
2683
- synthesizedCxxMethodDecl->setBody (synthesizedFuncBody);
2684
- synthesizedCxxMethodDecl->addAttr (
2685
- clang::NoDebugAttr::CreateImplicit (clangCtx));
2686
-
2687
- synthesizedCxxMethodDecl->setImplicit ();
2688
- synthesizedCxxMethodDecl->setImplicitlyInline ();
2689
-
2690
- return synthesizedCxxMethodDecl;
2699
+ return synthesizedFactories;
2691
2700
}
0 commit comments