@@ -2486,14 +2486,114 @@ namespace {
2486
2486
ctors.push_back (valueCtor);
2487
2487
}
2488
2488
2489
- // Do not allow Swift to construct foreign reference types (at least, not
2490
- // yet).
2491
2489
if (isa<StructDecl>(result)) {
2490
+ // For c++ value types, import all the constructors
2492
2491
for (auto ctor : ctors) {
2493
2492
// Add ctors directly as they cannot always be looked up from the
2494
2493
// clang decl (some are synthesized by Swift).
2495
2494
result->addMember (ctor);
2496
2495
}
2496
+ } else if (isa<ClassDecl>(result)) {
2497
+ // For C++ foreign reference types, generate a static factory method to
2498
+ // construct the object and import it as a Swift initializer.
2499
+
2500
+ // TODO: better/safer way to do this casting
2501
+ clang::CXXRecordDecl *cxxRecordDecl =
2502
+ (clang::CXXRecordDecl *)cast<clang::CXXRecordDecl>(decl);
2503
+
2504
+ ASTContext &ctx = result->getASTContext ();
2505
+ clang::ASTContext &clangCtx = cxxRecordDecl->getASTContext ();
2506
+
2507
+ // Creating a name for the new synthesized function
2508
+ clang::IdentifierTable &idents = clangCtx.Idents ;
2509
+ clang::IdentifierInfo *generatedFuncName =
2510
+ &idents.get ((" returns" + cxxRecordDecl->getNameAsString ()).c_str ());
2511
+
2512
+ // Creating the return type for the synthesized function to be the
2513
+ // pointe to cxxRecordDecl
2514
+ clang::QualType cxxRecordTy = clangCtx.getRecordType (cxxRecordDecl);
2515
+ clang::QualType cxxRecordPtrTy = clangCtx.getPointerType (cxxRecordTy);
2516
+ // TODO/DOUBT: How to add `_Nonnull` as a qualifier on cxxRecordPtrTy
2517
+ // return type ??
2518
+
2519
+ // Creating the type for the synthesized function
2520
+ clang::FunctionProtoType::ExtProtoInfo EPI;
2521
+ clang::QualType generatedFuncTy =
2522
+ clangCtx.getFunctionType (cxxRecordPtrTy, {}, EPI);
2523
+
2524
+ clang::CXXMethodDecl *generatedCxxMethodDecl =
2525
+ clang::CXXMethodDecl::Create (
2526
+ clangCtx, cxxRecordDecl, clang::SourceLocation (),
2527
+ clang::DeclarationNameInfo (generatedFuncName,
2528
+ clang::SourceLocation ()),
2529
+ generatedFuncTy, nullptr , clang::SC_Static, false , true ,
2530
+ clang::ConstexprSpecKind::Unspecified, clang::SourceLocation ());
2531
+
2532
+ // Create and attach "returns_retained" attribute to synthesized method
2533
+ clang::SwiftAttrAttr *returnsRetainedAttr =
2534
+ clang::SwiftAttrAttr::Create (clangCtx, " returns_retained" );
2535
+ generatedCxxMethodDecl->addAttr (returnsRetainedAttr);
2536
+ generatedCxxMethodDecl->setAccess (clang::AccessSpecifier::AS_public);
2537
+
2538
+ // Getting the default constructor
2539
+ clang::CXXConstructorDecl *ctorDecl = nullptr ;
2540
+ for (clang::CXXConstructorDecl *ctor : cxxRecordDecl->ctors ()) {
2541
+ if (ctor->isDefaultConstructor () && !ctor->isDeleted ()) {
2542
+ ctorDecl = ctor;
2543
+ break ;
2544
+ }
2545
+ }
2546
+
2547
+ if (ctorDecl) {
2548
+ // Build the constructor expression using the default constructor decl
2549
+ clang::ExprResult generatedConstructExpr =
2550
+ Impl.getClangSema ().BuildCXXConstructExpr (
2551
+ clang::SourceLocation (), cxxRecordTy, ctorDecl, false ,
2552
+ clang::MultiExprArg (), false , false , false ,
2553
+ true , // TODO: fix the propagation of this zeroinit flag to
2554
+ // BuildCXXNew
2555
+ clang::CXXConstructionKind::Complete, clang::SourceRange ());
2556
+
2557
+ if (!generatedConstructExpr.isInvalid ()) {
2558
+ // Build the new expr by passing the constructor expression as an
2559
+ // initializer
2560
+ clang::ExprResult generatedNewExprResult =
2561
+ Impl.getClangSema ().BuildCXXNew (
2562
+ clang::SourceRange (), false , clang::SourceLocation (), {},
2563
+ clang::SourceLocation (), clang::SourceRange (), cxxRecordTy,
2564
+ clangCtx.getTrivialTypeSourceInfo (cxxRecordTy),
2565
+ std::nullopt, clang::SourceRange (),
2566
+ generatedConstructExpr.get ());
2567
+
2568
+ if (!generatedNewExprResult.isInvalid ()) {
2569
+ // synthesizing the body of the generatedCxxMethodDecl
2570
+ clang::CXXNewExpr *generatedNewExpr =
2571
+ cast<clang::CXXNewExpr>(generatedNewExprResult.get ());
2572
+ clang::ReturnStmt *generatedRetStmt = clang::ReturnStmt::Create (
2573
+ clangCtx, clang::SourceLocation (), generatedNewExpr, nullptr );
2574
+ clang::CompoundStmt *generatedFuncBody =
2575
+ clang::CompoundStmt::Create (
2576
+ clangCtx, {generatedRetStmt}, clang::FPOptionsOverride (),
2577
+ clang::SourceLocation (), clang::SourceLocation ());
2578
+ generatedCxxMethodDecl->setBody (generatedFuncBody);
2579
+
2580
+ // Getting the appropriate decl context
2581
+ DeclBaseName initBaseName = DeclBaseName::createConstructor ();
2582
+ DeclName importedInitName (ctx, initBaseName,
2583
+ llvm::ArrayRef<Identifier>{});
2584
+ EffectiveClangContext effectiveContext (
2585
+ generatedCxxMethodDecl->getDeclContext ()->getRedeclContext ());
2586
+ auto dc = Impl.importDeclContextOf (decl, effectiveContext);
2587
+
2588
+ // Importing the synthesised method as Swift initializer and
2589
+ // adding it to result class
2590
+ Decl *importedInitDecl = importGlobalAsInitializer (
2591
+ generatedCxxMethodDecl, importedInitName, dc,
2592
+ CtorInitializerKind::Designated, std::nullopt);
2593
+ result->addMember (importedInitDecl);
2594
+ }
2595
+ }
2596
+ }
2497
2597
}
2498
2598
2499
2599
if (auto structResult = dyn_cast<StructDecl>(result)) {
0 commit comments