|
11 | 11 | //===----------------------------------------------------------------------===// |
12 | 12 |
|
13 | 13 | #include "SwiftDeclSynthesizer.h" |
| 14 | +#include "clang/AST/Mangle.h" |
14 | 15 | #include "swift/AST/ASTMangler.h" |
15 | 16 | #include "swift/AST/Builtins.h" |
16 | 17 | #include "swift/AST/Expr.h" |
@@ -2158,3 +2159,120 @@ SwiftDeclSynthesizer::makeComputedPropertyFromCXXMethods(FuncDecl *getter, |
2158 | 2159 |
|
2159 | 2160 | return result; |
2160 | 2161 | } |
| 2162 | + |
| 2163 | +static std::pair<BraceStmt *, bool> |
| 2164 | +synthesizeDefaultArgumentBody(AbstractFunctionDecl *afd, void *context) { |
| 2165 | + auto funcDecl = cast<FuncDecl>(afd); |
| 2166 | + auto clangParam = static_cast<const clang::ParmVarDecl *>(context); |
| 2167 | + auto clangFuncDecl = cast<clang::FunctionDecl>(clangParam->getDeclContext()); |
| 2168 | + |
| 2169 | + ASTContext &ctx = funcDecl->getASTContext(); |
| 2170 | + clang::ASTContext &clangCtx = clangParam->getASTContext(); |
| 2171 | + clang::Sema &clangSema = ctx.getClangModuleLoader()->getClangSema(); |
| 2172 | + |
| 2173 | + auto clangDeclName = clang::DeclarationName( |
| 2174 | + &clangCtx.Idents.get(("__cxx" + funcDecl->getNameStr()).str())); |
| 2175 | + auto clangDeclContext = clangCtx.getTranslationUnitDecl(); |
| 2176 | + |
| 2177 | + // The following also instantiates the default argument if needed. |
| 2178 | + auto defaultArgCallExpr = clangSema.BuildCXXDefaultArgExpr( |
| 2179 | + clang::SourceLocation(), const_cast<clang::FunctionDecl *>(clangFuncDecl), |
| 2180 | + const_cast<clang::ParmVarDecl *>(clangParam)); |
| 2181 | + if (!defaultArgCallExpr.isUsable()) |
| 2182 | + return {nullptr, /*isTypeChecked=*/true}; |
| 2183 | + |
| 2184 | + // The following requires the default argument to be instantiated. |
| 2185 | + clang::QualType clangParamTy = clangParam->getDefaultArg()->getType(); |
| 2186 | + clang::QualType funcTy = clangCtx.getFunctionType( |
| 2187 | + clangParamTy, {}, clang::FunctionProtoType::ExtProtoInfo()); |
| 2188 | + |
| 2189 | + // Synthesize `return {default expr};`. |
| 2190 | + auto defaultArgReturnStmt = clang::ReturnStmt::Create( |
| 2191 | + clangCtx, clang::SourceLocation(), defaultArgCallExpr.get(), nullptr); |
| 2192 | + |
| 2193 | + // Synthesize `ParamTy __cxx__defaultArg_XYZ() { return {default expr}; }`. |
| 2194 | + auto defaultArgFuncDecl = clang::FunctionDecl::Create( |
| 2195 | + clangCtx, clangDeclContext, clang::SourceLocation(), |
| 2196 | + clang::SourceLocation(), clangDeclName, funcTy, |
| 2197 | + clangCtx.getTrivialTypeSourceInfo(clangParamTy), |
| 2198 | + clang::StorageClass::SC_Static); |
| 2199 | + defaultArgFuncDecl->setImplicit(); |
| 2200 | + defaultArgFuncDecl->setImplicitlyInline(); |
| 2201 | + defaultArgFuncDecl->setAccess(clang::AccessSpecifier::AS_public); |
| 2202 | + defaultArgFuncDecl->setBody(defaultArgReturnStmt); |
| 2203 | + |
| 2204 | + // Import `func __cxx__defaultArg_XYZ() -> ParamTY` into Swift. |
| 2205 | + auto defaultArgGenerator = dyn_cast_or_null<FuncDecl>( |
| 2206 | + ctx.getClangModuleLoader()->importDeclDirectly(defaultArgFuncDecl)); |
| 2207 | + if (!defaultArgGenerator) |
| 2208 | + return {nullptr, /*isTypeChecked=*/true}; |
| 2209 | + |
| 2210 | + auto defaultArgGeneratorRef = new (ctx) DeclRefExpr( |
| 2211 | + ConcreteDeclRef(defaultArgGenerator), DeclNameLoc(), /*Implicit=*/true); |
| 2212 | + defaultArgGeneratorRef->setType(defaultArgGenerator->getInterfaceType()); |
| 2213 | + |
| 2214 | + // Synthesize a call to `__cxx__defaultArg_XYZ()`. |
| 2215 | + auto initCall = CallExpr::createImplicit( |
| 2216 | + ctx, defaultArgGeneratorRef, ArgumentList::createImplicit(ctx, {})); |
| 2217 | + initCall->setType(defaultArgGenerator->getResultInterfaceType()); |
| 2218 | + initCall->setThrows(nullptr); |
| 2219 | + |
| 2220 | + // Synthesize `return __cxx__defaultArg_XYZ()`. |
| 2221 | + auto returnStmt = new (ctx) ReturnStmt(SourceLoc(), initCall, |
| 2222 | + /*implicit=*/true); |
| 2223 | + |
| 2224 | + auto body = BraceStmt::create(ctx, SourceLoc(), {returnStmt}, SourceLoc(), |
| 2225 | + /*implicit=*/true); |
| 2226 | + return {body, /*isTypeChecked=*/true}; |
| 2227 | +} |
| 2228 | + |
| 2229 | +CallExpr * |
| 2230 | +SwiftDeclSynthesizer::makeDefaultArgument(const clang::ParmVarDecl *param, |
| 2231 | + const swift::Type &swiftParamTy, |
| 2232 | + SourceLoc paramLoc) { |
| 2233 | + assert(param->hasDefaultArg() && "must have a C++ default argument"); |
| 2234 | + if (!param->getIdentifier()) |
| 2235 | + // Work around an assertion failure in CXXNameMangler::mangleUnqualifiedName |
| 2236 | + // when mangling std::__fs::filesystem::path::format. |
| 2237 | + return nullptr; |
| 2238 | + |
| 2239 | + ASTContext &ctx = ImporterImpl.SwiftContext; |
| 2240 | + clang::ASTContext &clangCtx = param->getASTContext(); |
| 2241 | + auto clangFunc = |
| 2242 | + cast<clang::FunctionDecl>(param->getParentFunctionOrMethod()); |
| 2243 | + if (isa<clang::CXXConstructorDecl>(clangFunc)) |
| 2244 | + // TODO: support default arguments of constructors |
| 2245 | + // (https://github.com/apple/swift/issues/70124) |
| 2246 | + return nullptr; |
| 2247 | + |
| 2248 | + std::string s; |
| 2249 | + llvm::raw_string_ostream os(s); |
| 2250 | + std::unique_ptr<clang::ItaniumMangleContext> mangler{ |
| 2251 | + clang::ItaniumMangleContext::create(clangCtx, clangCtx.getDiagnostics())}; |
| 2252 | + os << "__defaultArg_" << param->getFunctionScopeIndex() << "_"; |
| 2253 | + ImporterImpl.getMangledName(mangler.get(), clangFunc, os); |
| 2254 | + |
| 2255 | + // Synthesize `func __defaultArg_XYZ() -> ParamTy { ... }`. |
| 2256 | + DeclName funcName(ctx, DeclBaseName(ctx.getIdentifier(s)), |
| 2257 | + ParameterList::createEmpty(ctx)); |
| 2258 | + auto funcDecl = FuncDecl::createImplicit( |
| 2259 | + ctx, StaticSpellingKind::None, funcName, paramLoc, false, false, Type(), |
| 2260 | + {}, ParameterList::createEmpty(ctx), swiftParamTy, |
| 2261 | + ImporterImpl.ImportedHeaderUnit); |
| 2262 | + funcDecl->setBodySynthesizer(synthesizeDefaultArgumentBody, (void *)param); |
| 2263 | + funcDecl->setAccess(AccessLevel::Public); |
| 2264 | + |
| 2265 | + ImporterImpl.defaultArgGenerators[param] = funcDecl; |
| 2266 | + |
| 2267 | + auto declRefExpr = new (ctx) |
| 2268 | + DeclRefExpr(ConcreteDeclRef(funcDecl), DeclNameLoc(), /*Implicit*/ true); |
| 2269 | + declRefExpr->setType(funcDecl->getInterfaceType()); |
| 2270 | + declRefExpr->setFunctionRefKind(FunctionRefKind::SingleApply); |
| 2271 | + |
| 2272 | + auto callExpr = CallExpr::createImplicit( |
| 2273 | + ctx, declRefExpr, ArgumentList::forImplicitUnlabeled(ctx, {})); |
| 2274 | + callExpr->setType(funcDecl->getResultInterfaceType()); |
| 2275 | + callExpr->setThrows(nullptr); |
| 2276 | + |
| 2277 | + return callExpr; |
| 2278 | +} |
0 commit comments