@@ -2041,6 +2041,105 @@ namespace {
2041
2041
fd->getAttrs ().add (new (Impl.SwiftContext ) UnsafeAttr (/* Implicit=*/ true ));
2042
2042
}
2043
2043
2044
+ void generateStaticFactoryForCXXForeignRef (
2045
+ clang::ASTContext &clangCtx, ClassDecl *result,
2046
+ clang::CXXRecordDecl *cxxRecordDecl, clang::Sema &clangSema) {
2047
+
2048
+ clang::IdentifierTable &idents = clangCtx.Idents ;
2049
+ clang::IdentifierInfo *generatedFuncName = &idents.get (
2050
+ (" __returns_" + cxxRecordDecl->getNameAsString ()).c_str ());
2051
+
2052
+ // TODO/DOUBT: How to add `_Nonnull` as a qualifier on cxxRecordPtrTy
2053
+ // return type ??
2054
+ clang::QualType cxxRecordTy = clangCtx.getRecordType (cxxRecordDecl);
2055
+ clang::QualType cxxRecordPtrTy = clangCtx.getPointerType (cxxRecordTy);
2056
+ clang::FunctionProtoType::ExtProtoInfo EPI;
2057
+ clang::QualType generatedFuncTy =
2058
+ clangCtx.getFunctionType (cxxRecordPtrTy, {}, EPI);
2059
+
2060
+ // TODO: Use operatorNew directly instead of calling BuildCXXNew
2061
+ clang::FunctionDecl *operatorNew = nullptr ;
2062
+ clang::FunctionDecl *operatorDelete = nullptr ;
2063
+ bool passAlignment = false ;
2064
+ bool allocationFound = clangSema.FindAllocationFunctions (
2065
+ cxxRecordDecl->getLocation (), clang::SourceRange (),
2066
+ clang::Sema::AFS_Both, clang::Sema::AFS_Both, cxxRecordTy,
2067
+ /* IsArray*/ false , passAlignment, clang::MultiExprArg (), operatorNew,
2068
+ operatorDelete);
2069
+
2070
+ llvm::errs () << " allocationFound: " << allocationFound << " \n " ;
2071
+ if (!operatorNew || operatorNew->isDeleted () ||
2072
+ operatorNew->getAccess () == clang::AS_private ||
2073
+ operatorNew->getAccess () == clang::AS_protected) {
2074
+ return ;
2075
+ }
2076
+
2077
+ clang::CXXConstructorDecl *defaultCtorDecl = nullptr ;
2078
+ for (clang::CXXConstructorDecl *ctor : cxxRecordDecl->ctors ()) {
2079
+ if (ctor->isDefaultConstructor () && !ctor->isDeleted ()) {
2080
+ defaultCtorDecl = ctor;
2081
+ break ;
2082
+ }
2083
+ }
2084
+
2085
+ if (!defaultCtorDecl)
2086
+ return ;
2087
+
2088
+ clang::CXXMethodDecl *generatedCxxMethodDecl =
2089
+ clang::CXXMethodDecl::Create (
2090
+ clangCtx, cxxRecordDecl, cxxRecordDecl->getLocation (),
2091
+ clang::DeclarationNameInfo (generatedFuncName,
2092
+ cxxRecordDecl->getLocation ()),
2093
+ generatedFuncTy, nullptr , clang::SC_Static,
2094
+ /* UsesFPIntrin*/ false , /* isInline=*/ true ,
2095
+ clang::ConstexprSpecKind::Unspecified,
2096
+ cxxRecordDecl->getLocation ());
2097
+
2098
+ generatedCxxMethodDecl->setAccess (clang::AccessSpecifier::AS_public);
2099
+
2100
+ clang::SwiftAttrAttr *generatedReturnsRetainedAttr =
2101
+ clang::SwiftAttrAttr::Create (clangCtx, " returns_retained" );
2102
+ generatedCxxMethodDecl->addAttr (generatedReturnsRetainedAttr);
2103
+
2104
+ clang::SwiftNameAttr *generatedSwiftNameInitAttr =
2105
+ clang::SwiftNameAttr::Create (clangCtx, " init()" );
2106
+ generatedCxxMethodDecl->addAttr (generatedSwiftNameInitAttr);
2107
+
2108
+ clang::ExprResult generatedConstructExpr =
2109
+ clangSema.BuildCXXConstructExpr (
2110
+ clang::SourceLocation (), cxxRecordTy, defaultCtorDecl,
2111
+ /* Elidable*/ false , clang::MultiExprArg (),
2112
+ /* HadMultipleCandidates,*/ false ,
2113
+ /* IsListInitialization*/ false ,
2114
+ /* IsStdInitListInitialization*/ false ,
2115
+ /* RequiresZeroInit*/ true , // TODO: fix the propagation of this
2116
+ // zeroinit flag to BuildCXXNew
2117
+ clang::CXXConstructionKind::Complete, clang::SourceRange ());
2118
+
2119
+ if (generatedConstructExpr.isInvalid ())
2120
+ return ;
2121
+ clang::ExprResult generatedNewExprResult = clangSema.BuildCXXNew (
2122
+ clang::SourceRange (), /* UseGlobal*/ false , clang::SourceLocation (),
2123
+ {}, clang::SourceLocation (), clang::SourceRange (), cxxRecordTy,
2124
+ clangCtx.getTrivialTypeSourceInfo (cxxRecordTy), std::nullopt,
2125
+ clang::SourceRange (), generatedConstructExpr.get ());
2126
+
2127
+ if (generatedNewExprResult.isInvalid ())
2128
+ return ;
2129
+ clang::CXXNewExpr *generatedNewExpr =
2130
+ cast<clang::CXXNewExpr>(generatedNewExprResult.get ());
2131
+ clang::ReturnStmt *generatedRetStmt = clang::ReturnStmt::Create (
2132
+ clangCtx, clang::SourceLocation (), generatedNewExpr, nullptr );
2133
+ clang::CompoundStmt *generatedFuncBody = clang::CompoundStmt::Create (
2134
+ clangCtx, {generatedRetStmt}, clang::FPOptionsOverride (),
2135
+ clang::SourceLocation (), clang::SourceLocation ());
2136
+ generatedCxxMethodDecl->setBody (generatedFuncBody);
2137
+ generatedCxxMethodDecl->addAttr (
2138
+ clang::NoDebugAttr::CreateImplicit (clangCtx));
2139
+ if (Decl *importedInitDecl = VisitCXXMethodDecl (generatedCxxMethodDecl))
2140
+ result->addMember (importedInitDecl);
2141
+ }
2142
+
2044
2143
Decl *VisitRecordDecl (const clang::RecordDecl *decl) {
2045
2144
// Track whether this record contains fields we can't reference in Swift
2046
2145
// as stored properties.
@@ -2472,14 +2571,28 @@ namespace {
2472
2571
ctors.push_back (valueCtor);
2473
2572
}
2474
2573
2475
- // Do not allow Swift to construct foreign reference types (at least, not
2476
- // yet).
2477
2574
if (isa<StructDecl>(result)) {
2478
2575
for (auto ctor : ctors) {
2479
2576
// Add ctors directly as they cannot always be looked up from the
2480
2577
// clang decl (some are synthesized by Swift).
2481
2578
result->addMember (ctor);
2482
2579
}
2580
+ } else {
2581
+ // TODO: Make the feature flag GenerateCxxRefTypeInit actually work
2582
+ if (result->getASTContext ().LangOpts .hasFeature (
2583
+ Feature::GenerateCxxRefTypeInit)) {
2584
+ assert (isa<ClassDecl>(result) && " Expected result to be a ClassDecl "
2585
+ " for C/C++ foreign reference types" );
2586
+ if (auto *cxxRecordDecl = const_cast <clang::CXXRecordDecl *>(
2587
+ dyn_cast<clang::CXXRecordDecl>(decl))) {
2588
+ generateStaticFactoryForCXXForeignRef (
2589
+ cxxRecordDecl->getASTContext (), cast<ClassDecl>(result),
2590
+ cxxRecordDecl, Impl.getClangSema ());
2591
+ } else {
2592
+ // TODO: Synthesize the static factory for C foreign reference types
2593
+ // rdar://147532507
2594
+ }
2595
+ }
2483
2596
}
2484
2597
2485
2598
if (auto structResult = dyn_cast<StructDecl>(result)) {
0 commit comments