@@ -149,65 +149,6 @@ substituteFunctionTypeAndParamList(ASTContext &ctx, AbstractFunctionDecl *fdecl,
149
149
return {newFnType, newParamList};
150
150
}
151
151
152
- static ValueDecl *generateSpecializedCXXFunctionTemplate (
153
- ASTContext &ctx, AbstractFunctionDecl *oldDecl, SubstitutionMap subst,
154
- clang::FunctionDecl *specialized) {
155
- auto newFnTypeAndParams = substituteFunctionTypeAndParamList (ctx, oldDecl, subst);
156
- auto newFnType = newFnTypeAndParams.first ;
157
- auto paramList = newFnTypeAndParams.second ;
158
-
159
- SmallVector<ParamDecl *, 4 > newParamsWithoutMetatypes;
160
- for (auto param : *paramList ) {
161
- if (isa<FuncDecl>(oldDecl) &&
162
- isa<MetatypeType>(param->getType ().getPointer ())) {
163
- // Metatype parameters are added synthetically to account for template
164
- // params that don't make it to the function signature. These shouldn't
165
- // exist in the resulting specialized FuncDecl. Note that this doesn't
166
- // affect constructors because all template params for a constructor
167
- // must be in the function signature by design.
168
- continue ;
169
- }
170
- newParamsWithoutMetatypes.push_back (param);
171
- }
172
- auto *newParamList =
173
- ParameterList::create (ctx, SourceLoc (), newParamsWithoutMetatypes, SourceLoc ());
174
-
175
- if (isa<ConstructorDecl>(oldDecl)) {
176
- DeclName ctorName (ctx, DeclBaseName::createConstructor (), newParamList);
177
- auto newCtorDecl = ConstructorDecl::createImported (
178
- ctx, specialized, ctorName, oldDecl->getLoc (),
179
- /* failable=*/ false , /* failabilityLoc=*/ SourceLoc (),
180
- /* Async=*/ false , /* AsyncLoc=*/ SourceLoc (),
181
- /* throws=*/ false , /* throwsLoc=*/ SourceLoc (),
182
- newParamList, /* genericParams=*/ nullptr ,
183
- oldDecl->getDeclContext ());
184
- return newCtorDecl;
185
- }
186
-
187
- // Generate a name for the specialized function.
188
- std::string newNameStr;
189
- llvm::raw_string_ostream buffer (newNameStr);
190
- std::unique_ptr<clang::MangleContext> mangler (
191
- specialized->getASTContext ().createMangleContext ());
192
- mangler->mangleName (specialized, buffer);
193
- buffer.flush ();
194
- // Add all parameters as empty parameters.
195
- auto newName = DeclName (
196
- ctx, DeclName (ctx.getIdentifier (newNameStr)).getBaseName (), newParamList);
197
-
198
- auto newFnDecl = FuncDecl::createImported (
199
- ctx, oldDecl->getLoc (), newName, oldDecl->getNameLoc (),
200
- /* Async=*/ false , oldDecl->hasThrows (), newParamList,
201
- newFnType->getResult (), /* GenericParams=*/ nullptr ,
202
- oldDecl->getDeclContext (), specialized);
203
- if (oldDecl->isStatic ()) {
204
- newFnDecl->setStatic ();
205
- newFnDecl->setImportAsStaticMember ();
206
- }
207
- newFnDecl->setSelfAccessKind (cast<FuncDecl>(oldDecl)->getSelfAccessKind ());
208
- return newFnDecl;
209
- }
210
-
211
152
// Synthesizes the body of a thunk that takes extra metatype arguments and
212
153
// skips over them to forward them along to the FuncDecl contained by context.
213
154
// This is used when importing a C++ templated function where the template params
@@ -285,8 +226,91 @@ Solution::resolveConcreteDeclRef(ValueDecl *decl,
285
226
const_cast <clang::FunctionTemplateDecl *>(
286
227
cast<clang::FunctionTemplateDecl>(decl->getClangDecl ())),
287
228
subst);
288
- auto newDecl = generateSpecializedCXXFunctionTemplate (
289
- decl->getASTContext (), cast<AbstractFunctionDecl>(decl), subst, newFn);
229
+ // We failed to specialize this function template. The compiler is going to
230
+ // exit soon. Return something valid in the meantime.
231
+ if (!newFn)
232
+ return ConcreteDeclRef (decl);
233
+
234
+ auto newDecl = cast_or_null<ValueDecl>(
235
+ decl->getASTContext ().getClangModuleLoader ()->importDeclDirectly (
236
+ newFn));
237
+
238
+ if (auto fn = dyn_cast<AbstractFunctionDecl>(newDecl)) {
239
+ // On Windows x86-64 we have to hack around the fact that
240
+ // Int -> long long -> Int64. So we re-write the parameters mapping
241
+ // Int64 -> Int.
242
+ auto triple = decl->getASTContext ().LangOpts .Target ;
243
+ if (triple.isOSWindows () && triple.isArch64Bit () &&
244
+ !triple.isWindowsCygwinEnvironment () &&
245
+ // Make sure we're substituting in at least one Int or UInt
246
+ // (technically not necessary).
247
+ llvm::any_of (subst.getReplacementTypes (), [](Type t) {
248
+ return t->isEqual (t->getASTContext ().getIntType ()) ||
249
+ t->isEqual (t->getASTContext ().getUIntType ());
250
+ })) {
251
+ auto originalFnSubst = cast<AbstractFunctionDecl>(decl)
252
+ ->getInterfaceType ()
253
+ ->getAs <GenericFunctionType>()
254
+ ->substGenericArgs (subst);
255
+ // The constructor type is a function type as follows:
256
+ // (CType.Type) -> (Generic) -> CType
257
+ // And a method's function type is as follows:
258
+ // (inout CType) -> (Generic) -> Void
259
+ // In either case, we only want the result of that function type because that
260
+ // is the function type with the generic params that need to be substituted:
261
+ // (Generic) -> CType
262
+ if (isa<ConstructorDecl>(decl) || decl->isInstanceMember () ||
263
+ decl->isStatic ())
264
+ originalFnSubst = cast<FunctionType>(originalFnSubst->getResult ().getPointer ());
265
+
266
+ SmallVector<ParamDecl *, 4 > fixedParameters;
267
+ unsigned parameterIndex = 0 ;
268
+ for (auto *newFnParam : *fn->getParameters ()) {
269
+ // If the user substituted this param with an (U)Int, use (U)Int.
270
+ auto substParamType =
271
+ originalFnSubst->getParams ()[parameterIndex].getParameterType ();
272
+ if (substParamType->isEqual (fn->getASTContext ().getIntType ()) ||
273
+ substParamType->isEqual (fn->getASTContext ().getUIntType ())) {
274
+ auto intParam =
275
+ ParamDecl::cloneWithoutType (fn->getASTContext (), newFnParam);
276
+ intParam->setInterfaceType (substParamType);
277
+ fixedParameters.push_back (intParam);
278
+ } else {
279
+ fixedParameters.push_back (newFnParam);
280
+ }
281
+ parameterIndex++;
282
+ }
283
+
284
+ auto fixedParams =
285
+ ParameterList::create (fn->getASTContext (), fixedParameters);
286
+ fn->setParameters (fixedParams);
287
+
288
+ // Now fix the result type:
289
+ if (originalFnSubst->getResult ()->isEqual (
290
+ fn->getASTContext ().getIntType ()) ||
291
+ originalFnSubst->getResult ()->isEqual (
292
+ fn->getASTContext ().getUIntType ())) {
293
+ // Constructors don't have a result.
294
+ if (auto func = dyn_cast<FuncDecl>(fn)) {
295
+ // We have to rebuild the whole function.
296
+ auto newFnDecl = FuncDecl::createImported (
297
+ func->getASTContext (), func->getNameLoc (),
298
+ func->getName (), func->getNameLoc (),
299
+ func->hasAsync (), func->hasThrows (),
300
+ fixedParams, originalFnSubst->getResult (),
301
+ /* genericParams=*/ nullptr , func->getDeclContext (), newFn);
302
+ if (func->isStatic ()) newFnDecl->setStatic ();
303
+ if (func->isImportAsStaticMember ()) newFnDecl->setImportAsStaticMember ();
304
+ if (!func->getDeclContext ()->isModuleScopeContext ()) {
305
+ newFnDecl->setSelfAccessKind (func->getSelfAccessKind ());
306
+ newFnDecl->setSelfIndex (func->getSelfIndex ());
307
+ }
308
+ newDecl = newFnDecl;
309
+ }
310
+ }
311
+ }
312
+ }
313
+
290
314
if (auto fn = dyn_cast<FuncDecl>(decl)) {
291
315
if (newFn->getNumParams () != fn->getParameters ()->size ()) {
292
316
// We added additional metatype parameters to aid template
@@ -304,9 +328,10 @@ Solution::resolveConcreteDeclRef(ValueDecl *decl,
304
328
thunk->setBodySynthesizer (synthesizeForwardingThunkBody, cast<FuncDecl>(newDecl));
305
329
thunk->setSelfAccessKind (fn->getSelfAccessKind ());
306
330
307
- return ConcreteDeclRef ( thunk) ;
331
+ newDecl = thunk;
308
332
}
309
333
}
334
+
310
335
return ConcreteDeclRef (newDecl);
311
336
}
312
337
0 commit comments