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