@@ -2538,29 +2538,29 @@ SwiftDeclSynthesizer::synthesizeStaticFactoryForCXXForeignRef(
2538
2538
2539
2539
clang::ASTContext &clangCtx = cxxRecordDecl->getASTContext ();
2540
2540
clang::Sema &clangSema = ImporterImpl.getClangSema ();
2541
+ clang::SourceLocation cxxRecordDeclLoc = cxxRecordDecl->getLocation ();
2541
2542
2542
2543
clang::QualType cxxRecordTy = clangCtx.getRecordType (cxxRecordDecl);
2543
2544
2544
- clang::CXXConstructorDecl *defaultCtorDecl = nullptr ;
2545
+ // Todo: synthesize static factories for all available ctors
2546
+ clang::CXXConstructorDecl *selectedCtorDecl = nullptr ;
2545
2547
for (clang::CXXConstructorDecl *ctor : cxxRecordDecl->ctors ()) {
2546
- if (ctor->parameters ().empty () && !ctor->isDeleted () &&
2547
- ctor->getAccess () != clang::AS_private &&
2548
+ if (!ctor->isDeleted () && ctor->getAccess () != clang::AS_private &&
2548
2549
ctor->getAccess () != clang::AS_protected) {
2549
- defaultCtorDecl = ctor;
2550
+ selectedCtorDecl = ctor;
2550
2551
break ;
2551
2552
}
2552
2553
}
2553
- if (!defaultCtorDecl )
2554
+ if (!selectedCtorDecl )
2554
2555
return nullptr ;
2555
2556
2556
2557
clang::FunctionDecl *operatorNew = nullptr ;
2557
2558
clang::FunctionDecl *operatorDelete = nullptr ;
2558
2559
bool passAlignment = false ;
2559
2560
bool findingAllocFuncFailed = clangSema.FindAllocationFunctions (
2560
- cxxRecordDecl->getLocation (), clang::SourceRange (), clang::Sema::AFS_Both,
2561
- clang::Sema::AFS_Both, cxxRecordTy,
2562
- /* IsArray*/ false , passAlignment, clang::MultiExprArg (), operatorNew,
2563
- operatorDelete, /* Diagnose*/ false );
2561
+ cxxRecordDeclLoc, clang::SourceRange (), clang::Sema::AFS_Both,
2562
+ clang::Sema::AFS_Both, cxxRecordTy, /* IsArray=*/ false , passAlignment,
2563
+ clang::MultiExprArg (), operatorNew, operatorDelete, /* Diagnose=*/ false );
2564
2564
if (findingAllocFuncFailed || !operatorNew || operatorNew->isDeleted () ||
2565
2565
operatorNew->getAccess () == clang::AS_private ||
2566
2566
operatorNew->getAccess () == clang::AS_protected)
@@ -2570,81 +2570,111 @@ SwiftDeclSynthesizer::synthesizeStaticFactoryForCXXForeignRef(
2570
2570
// Adding `_Nonnull` to the return type of synthesized static factory
2571
2571
bool nullabilityCannotBeAdded =
2572
2572
clangSema.CheckImplicitNullabilityTypeSpecifier (
2573
- cxxRecordPtrTy, clang::NullabilityKind::NonNull,
2574
- cxxRecordDecl->getLocation (),
2575
- /* isParam=*/ false ,
2576
- /* OverrideExisting=*/ true );
2573
+ cxxRecordPtrTy, clang::NullabilityKind::NonNull, cxxRecordDeclLoc,
2574
+ /* isParam=*/ false , /* OverrideExisting=*/ true );
2577
2575
assert (!nullabilityCannotBeAdded &&
2578
2576
" Failed to add _Nonnull specifier to synthesized "
2579
2577
" static factory's return type" );
2580
2578
2581
2579
clang::IdentifierTable &clangIdents = clangCtx.Idents ;
2582
2580
clang::IdentifierInfo *funcNameToSynthesize = &clangIdents.get (
2583
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 ());
2584
2586
clang::FunctionProtoType::ExtProtoInfo EPI;
2585
2587
clang::QualType funcTypeToSynthesize =
2586
- clangCtx.getFunctionType (cxxRecordPtrTy, {} , EPI);
2588
+ clangCtx.getFunctionType (cxxRecordPtrTy, paramTypes , EPI);
2587
2589
2588
2590
clang::CXXMethodDecl *synthesizedCxxMethodDecl = clang::CXXMethodDecl::Create (
2589
2591
clangCtx, const_cast <clang::CXXRecordDecl *>(cxxRecordDecl),
2590
- cxxRecordDecl->getLocation (),
2591
- clang::DeclarationNameInfo (funcNameToSynthesize,
2592
- cxxRecordDecl->getLocation ()),
2592
+ cxxRecordDeclLoc,
2593
+ clang::DeclarationNameInfo (funcNameToSynthesize, cxxRecordDeclLoc),
2593
2594
funcTypeToSynthesize,
2594
2595
clangCtx.getTrivialTypeSourceInfo (funcTypeToSynthesize), clang::SC_Static,
2595
2596
/* UsesFPIntrin=*/ false , /* isInline=*/ true ,
2596
- clang::ConstexprSpecKind::Unspecified, cxxRecordDecl->getLocation ());
2597
- assert (synthesizedCxxMethodDecl &&
2598
- " Unable to synthesize static factory for c++ foreign reference type" );
2597
+ clang::ConstexprSpecKind::Unspecified, cxxRecordDeclLoc);
2599
2598
synthesizedCxxMethodDecl->setAccess (clang::AccessSpecifier::AS_public);
2600
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
+
2601
2612
if (!hasImmortalAttrs (cxxRecordDecl)) {
2602
2613
clang::SwiftAttrAttr *returnsRetainedAttrForSynthesizedCxxMethodDecl =
2603
2614
clang::SwiftAttrAttr::Create (clangCtx, " returns_retained" );
2604
2615
synthesizedCxxMethodDecl->addAttr (
2605
2616
returnsRetainedAttrForSynthesizedCxxMethodDecl);
2606
2617
}
2607
2618
2608
- clang::SwiftNameAttr *swiftNameInitAttrForSynthesizedCxxMethodDecl =
2609
- clang::SwiftNameAttr::Create (clangCtx, " init()" );
2610
- synthesizedCxxMethodDecl->addAttr (
2611
- swiftNameInitAttrForSynthesizedCxxMethodDecl);
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
+ }
2639
+
2640
+ llvm::SmallVector<clang::Expr *, 8 > convertedCtorArgs;
2641
+ if (clangSema.CompleteConstructorCall (selectedCtorDecl, cxxRecordTy, ctorArgs,
2642
+ cxxRecordDeclLoc, convertedCtorArgs))
2643
+ return nullptr ;
2612
2644
2613
2645
clang::ExprResult synthesizedConstructExprResult =
2614
2646
clangSema.BuildCXXConstructExpr (
2615
- clang::SourceLocation () , cxxRecordTy, defaultCtorDecl ,
2616
- /* Elidable=*/ false , clang::MultiExprArg () ,
2647
+ cxxRecordDeclLoc , cxxRecordTy, selectedCtorDecl ,
2648
+ /* Elidable=*/ false , convertedCtorArgs ,
2617
2649
/* HadMultipleCandidates=*/ false ,
2618
2650
/* IsListInitialization=*/ false ,
2619
2651
/* IsStdInitListInitialization=*/ false ,
2620
2652
/* RequiresZeroInit=*/ false , clang::CXXConstructionKind::Complete,
2621
- clang::SourceRange ());
2653
+ clang::SourceRange (cxxRecordDeclLoc, cxxRecordDeclLoc ));
2622
2654
assert (!synthesizedConstructExprResult.isInvalid () &&
2623
2655
" Unable to synthesize constructor expression for c++ foreign "
2624
2656
" reference type" );
2625
- clang::CXXConstructExpr *synthesizedConstructExpr =
2626
- cast<clang::CXXConstructExpr>(synthesizedConstructExprResult.get ());
2657
+ clang::Expr *synthesizedConstructExpr = synthesizedConstructExprResult.get ();
2627
2658
2628
2659
clang::ExprResult synthesizedNewExprResult = clangSema.BuildCXXNew (
2629
2660
clang::SourceRange (), /* UseGlobal=*/ false , clang::SourceLocation (), {},
2630
2661
clang::SourceLocation (), clang::SourceRange (), cxxRecordTy,
2631
2662
clangCtx.getTrivialTypeSourceInfo (cxxRecordTy), std::nullopt,
2632
- clang::SourceRange (), synthesizedConstructExpr);
2663
+ clang::SourceRange (cxxRecordDeclLoc, cxxRecordDeclLoc),
2664
+ synthesizedConstructExpr);
2633
2665
assert (
2634
2666
!synthesizedNewExprResult.isInvalid () &&
2635
2667
" Unable to synthesize `new` expression for c++ foreign reference type" );
2636
2668
clang::CXXNewExpr *synthesizedNewExpr =
2637
2669
cast<clang::CXXNewExpr>(synthesizedNewExprResult.get ());
2638
2670
2639
- clang::ReturnStmt *synthesizedRetStmt =
2640
- clang::ReturnStmt::Create (clangCtx, clang::SourceLocation (),
2641
- synthesizedNewExpr, /* VarDecl=*/ nullptr );
2671
+ clang::ReturnStmt *synthesizedRetStmt = clang::ReturnStmt::Create (
2672
+ clangCtx, cxxRecordDeclLoc, synthesizedNewExpr, nullptr );
2642
2673
assert (synthesizedRetStmt && " Unable to synthesize return statement for "
2643
2674
" static factory of c++ foreign reference type" );
2644
-
2645
2675
clang::CompoundStmt *synthesizedFuncBody = clang::CompoundStmt::Create (
2646
2676
clangCtx, {synthesizedRetStmt}, clang::FPOptionsOverride (),
2647
- clang::SourceLocation (), clang::SourceLocation () );
2677
+ cxxRecordDeclLoc, cxxRecordDeclLoc );
2648
2678
assert (synthesizedRetStmt && " Unable to synthesize function body for static "
2649
2679
" factory of c++ foreign reference type" );
2650
2680
0 commit comments