Skip to content

Commit 6da5e7e

Browse files
committed
[cxx-interop] Fix (U)Int substituted params on Windows.
Re-write the parameter list to use (U)Int if that was one of the substituted parameters. This is required because Windows will incorrectly map Int -> long long -> Int64.
1 parent 04d4e9d commit 6da5e7e

File tree

1 file changed

+54
-2
lines changed

1 file changed

+54
-2
lines changed

lib/Sema/CSApply.cpp

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ Solution::resolveConcreteDeclRef(ValueDecl *decl,
231231
if (!newFn)
232232
return ConcreteDeclRef(decl);
233233

234-
auto newDecl = cast<ValueDecl>(decl->getASTContext().getClangModuleLoader()->importDeclDirectly(newFn));
234+
auto newDecl = cast_or_null<ValueDecl>(decl->getASTContext().getClangModuleLoader()->importDeclDirectly(newFn));
235235

236236
if (auto fn = dyn_cast<FuncDecl>(decl)) {
237237
if (newFn->getNumParams() != fn->getParameters()->size()) {
@@ -250,9 +250,61 @@ Solution::resolveConcreteDeclRef(ValueDecl *decl,
250250
thunk->setBodySynthesizer(synthesizeForwardingThunkBody, cast<FuncDecl>(newDecl));
251251
thunk->setSelfAccessKind(fn->getSelfAccessKind());
252252

253-
return ConcreteDeclRef(thunk);
253+
newDecl = thunk;
254+
}
255+
}
256+
257+
if (auto fn = dyn_cast<AbstractFunctionDecl>(newDecl)) {
258+
// On Windows x86-64 we have to hack around the fact that
259+
// Int -> long long -> Int64. So we re-write the parameters mapping
260+
// Int64 -> Int.
261+
auto triple = decl->getASTContext().LangOpts.Target;
262+
if (triple.isOSWindows() && triple.isArch64Bit() &&
263+
!triple.isWindowsCygwinEnvironment() &&
264+
// Make sure we're substituting in at least one Int or UInt
265+
// (technically not necessary).
266+
llvm::any_of(subst.getReplacementTypes(),[](Type t) {
267+
return t->isEqual(t->getASTContext().getIntType()) ||
268+
t->isEqual(t->getASTContext().getUIntType());
269+
})) {
270+
auto originalFnSubst = cast<AbstractFunctionDecl>(decl)->getInterfaceType()->getAs<GenericFunctionType>()->substGenericArgs(subst);
271+
assert(fn->getParameters()->size() == originalFnSubst->getParams().size());
272+
SmallVector<ParamDecl *, 4> fixedParameters;
273+
unsigned parameterIndex = 0;
274+
for (auto *newFnParam : *fn->getParameters()) {
275+
// If the user substituted this param with an (U)Int, use (U)Int.
276+
auto substParamType = originalFnSubst->getParams()[parameterIndex].getParameterType();
277+
if (substParamType->isEqual(fn->getASTContext().getIntType()) ||
278+
substParamType->isEqual(fn->getASTContext().getUIntType())) {
279+
auto intParam = ParamDecl::cloneWithoutType(fn->getASTContext(), newFnParam);
280+
intParam->setInterfaceType(substParamType);
281+
fixedParameters.push_back(intParam);
282+
} else {
283+
fixedParameters.push_back(newFnParam);
284+
}
285+
parameterIndex++;
286+
}
287+
288+
assert(fn->getParameters()->size() == fixedParameters.size());
289+
290+
auto fixedParams = ParameterList::create(fn->getASTContext(), fixedParameters);
291+
fn->setParameters(fixedParams);
292+
293+
// Now fix the result type:
294+
if (originalFnSubst->getResult()->isEqual(fn->getASTContext().getIntType()) ||
295+
originalFnSubst->getResult()->isEqual(fn->getASTContext().getUIntType())) {
296+
// Constructors don't have a result.
297+
if (auto func = dyn_cast<FuncDecl>(fn)) {
298+
newDecl = FuncDecl::createImplicit(
299+
func->getASTContext(), func->getStaticSpelling(), func->getName(),
300+
func->getNameLoc(), func->hasAsync(), func->hasThrows(),
301+
/*genericParams=*/nullptr, fixedParams,
302+
originalFnSubst->getResult(), func->getDeclContext());
303+
}
304+
}
254305
}
255306
}
307+
256308
return ConcreteDeclRef(newDecl);
257309
}
258310

0 commit comments

Comments
 (0)