@@ -166,15 +166,17 @@ class swift::SourceLookupCache {
166
166
ValueDeclMap TopLevelValues;
167
167
ValueDeclMap ClassMembers;
168
168
bool MemberCachePopulated = false ;
169
+ llvm::SmallVector<AbstractFunctionDecl *, 0 > CustomDerivatives;
169
170
DeclName UniqueMacroNamePlaceholder;
170
171
171
172
template <typename T>
172
173
using OperatorMap = llvm::DenseMap<Identifier, TinyPtrVector<T *>>;
173
174
OperatorMap<OperatorDecl> Operators;
174
175
OperatorMap<PrecedenceGroupDecl> PrecedenceGroups;
175
176
176
- template <typename Range>
177
- void addToUnqualifiedLookupCache (Range decls, bool onlyOperators);
177
+ template <typename Range>
178
+ void addToUnqualifiedLookupCache (Range decls, bool onlyOperators,
179
+ bool onlyDerivatives);
178
180
template <typename Range>
179
181
void addToMemberCache (Range decls);
180
182
@@ -205,6 +207,10 @@ class swift::SourceLookupCache {
205
207
// / guaranteed to be meaningful.
206
208
void getPrecedenceGroups (SmallVectorImpl<PrecedenceGroupDecl *> &results);
207
209
210
+ // / Retrieves all the function decls marked as @derivative. The order of the
211
+ // / results is not guaranteed to be meaningful.
212
+ llvm::SmallVector<AbstractFunctionDecl *, 0 > getCustomDerivativeDecls ();
213
+
208
214
// / Look up an operator declaration.
209
215
// /
210
216
// / \param name The operator name ("+", ">>", etc.)
@@ -249,9 +255,10 @@ static Decl *getAsDecl(Decl *decl) { return decl; }
249
255
static Expr *getAsExpr (ASTNode node) { return node.dyn_cast <Expr *>(); }
250
256
static Decl *getAsDecl (ASTNode node) { return node.dyn_cast <Decl *>(); }
251
257
252
- template <typename Range>
258
+ template <typename Range>
253
259
void SourceLookupCache::addToUnqualifiedLookupCache (Range items,
254
- bool onlyOperators) {
260
+ bool onlyOperators,
261
+ bool onlyDerivatives) {
255
262
for (auto item : items) {
256
263
// In script mode, we'll see macro expansion expressions for freestanding
257
264
// macros.
@@ -268,19 +275,36 @@ void SourceLookupCache::addToUnqualifiedLookupCache(Range items,
268
275
continue ;
269
276
270
277
if (auto *VD = dyn_cast<ValueDecl>(D)) {
271
- if (onlyOperators ? VD->isOperator () : VD->hasName ()) {
272
- // Cache the value under both its compound name and its full name.
278
+ auto getDerivative = [onlyDerivatives, VD]() -> AbstractFunctionDecl * {
279
+ if (auto *AFD = dyn_cast<AbstractFunctionDecl>(VD))
280
+ if (AFD->getAttrs ().hasAttribute <DerivativeAttr>())
281
+ return AFD;
282
+ return nullptr ;
283
+ };
284
+ if (onlyOperators && VD->isOperator ())
273
285
TopLevelValues.add (VD);
274
-
275
- if (!onlyOperators && VD->getAttrs ().hasAttribute <CustomAttr>()) {
286
+ if (onlyDerivatives)
287
+ if (AbstractFunctionDecl *AFD = getDerivative ())
288
+ CustomDerivatives.push_back (AFD);
289
+ if (!onlyOperators && !onlyDerivatives && VD->hasName ()) {
290
+ TopLevelValues.add (VD);
291
+ if (VD->getAttrs ().hasAttribute <CustomAttr>())
276
292
MayHaveAuxiliaryDecls.push_back (VD);
277
- }
293
+ if (AbstractFunctionDecl *AFD = getDerivative ())
294
+ CustomDerivatives.push_back (AFD);
278
295
}
279
296
}
280
297
281
- if (auto *NTD = dyn_cast<NominalTypeDecl>(D))
282
- if (!NTD->hasUnparsedMembers () || NTD->maybeHasOperatorDeclarations ())
283
- addToUnqualifiedLookupCache (NTD->getMembers (), true );
298
+ if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
299
+ bool onlyOperatorsArg =
300
+ (!NTD->hasUnparsedMembers () || NTD->maybeHasOperatorDeclarations ());
301
+ bool onlyDerivativesArg =
302
+ (!NTD->hasUnparsedMembers () || NTD->maybeHasDerivativeDeclarations ());
303
+ if (onlyOperatorsArg || onlyDerivativesArg) {
304
+ addToUnqualifiedLookupCache (NTD->getMembers (), onlyOperatorsArg,
305
+ onlyDerivativesArg);
306
+ }
307
+ }
284
308
285
309
if (auto *ED = dyn_cast<ExtensionDecl>(D)) {
286
310
// Avoid populating the cache with the members of invalid extension
@@ -292,8 +316,14 @@ void SourceLookupCache::addToUnqualifiedLookupCache(Range items,
292
316
MayHaveAuxiliaryDecls.push_back (ED);
293
317
}
294
318
295
- if (!ED->hasUnparsedMembers () || ED->maybeHasOperatorDeclarations ())
296
- addToUnqualifiedLookupCache (ED->getMembers (), true );
319
+ bool onlyOperatorsArg =
320
+ (!ED->hasUnparsedMembers () || ED->maybeHasOperatorDeclarations ());
321
+ bool onlyDerivativesArg =
322
+ (!ED->hasUnparsedMembers () || ED->maybeHasDerivativeDeclarations ());
323
+ if (onlyOperatorsArg || onlyDerivativesArg) {
324
+ addToUnqualifiedLookupCache (ED->getMembers (), onlyOperatorsArg,
325
+ onlyDerivativesArg);
326
+ }
297
327
}
298
328
299
329
if (auto *OD = dyn_cast<OperatorDecl>(D))
@@ -307,7 +337,8 @@ void SourceLookupCache::addToUnqualifiedLookupCache(Range items,
307
337
MayHaveAuxiliaryDecls.push_back (MED);
308
338
} else if (auto TLCD = dyn_cast<TopLevelCodeDecl>(D)) {
309
339
if (auto body = TLCD->getBody ()){
310
- addToUnqualifiedLookupCache (body->getElements (), onlyOperators);
340
+ addToUnqualifiedLookupCache (body->getElements (), onlyOperators,
341
+ onlyDerivatives);
311
342
}
312
343
}
313
344
}
@@ -488,8 +519,8 @@ SourceLookupCache::SourceLookupCache(const SourceFile &SF)
488
519
{
489
520
FrontendStatsTracer tracer (SF.getASTContext ().Stats ,
490
521
" source-file-populate-cache" );
491
- addToUnqualifiedLookupCache (SF.getTopLevelItems (), false );
492
- addToUnqualifiedLookupCache (SF.getHoistedDecls (), false );
522
+ addToUnqualifiedLookupCache (SF.getTopLevelItems (), false , false );
523
+ addToUnqualifiedLookupCache (SF.getHoistedDecls (), false , false );
493
524
}
494
525
495
526
SourceLookupCache::SourceLookupCache (const ModuleDecl &M)
@@ -499,11 +530,11 @@ SourceLookupCache::SourceLookupCache(const ModuleDecl &M)
499
530
" module-populate-cache" );
500
531
for (const FileUnit *file : M.getFiles ()) {
501
532
auto *SF = cast<SourceFile>(file);
502
- addToUnqualifiedLookupCache (SF->getTopLevelItems (), false );
503
- addToUnqualifiedLookupCache (SF->getHoistedDecls (), false );
533
+ addToUnqualifiedLookupCache (SF->getTopLevelItems (), false , false );
534
+ addToUnqualifiedLookupCache (SF->getHoistedDecls (), false , false );
504
535
505
536
if (auto *SFU = file->getSynthesizedFile ()) {
506
- addToUnqualifiedLookupCache (SFU->getTopLevelDecls (), false );
537
+ addToUnqualifiedLookupCache (SFU->getTopLevelDecls (), false , false );
507
538
}
508
539
}
509
540
}
@@ -572,6 +603,11 @@ void SourceLookupCache::getOperatorDecls(
572
603
results.append (ops.second .begin (), ops.second .end ());
573
604
}
574
605
606
+ llvm::SmallVector<AbstractFunctionDecl *, 0 >
607
+ SourceLookupCache::getCustomDerivativeDecls () {
608
+ return CustomDerivatives;
609
+ }
610
+
575
611
void SourceLookupCache::lookupOperator (Identifier name, OperatorFixity fixity,
576
612
TinyPtrVector<OperatorDecl *> &results) {
577
613
auto ops = Operators.find (name);
@@ -4026,6 +4062,23 @@ bool IsNonUserModuleRequest::evaluate(Evaluator &evaluator, ModuleDecl *mod) con
4026
4062
return false ;
4027
4063
}
4028
4064
4065
+ evaluator::SideEffect CustomDerivativesRequest::evaluate (Evaluator &evaluator,
4066
+ SourceFile *sf) const {
4067
+ ModuleDecl *module = sf->getParentModule ();
4068
+ assert (isParsedModule (module));
4069
+ llvm::SmallVector<AbstractFunctionDecl *, 0 > decls =
4070
+ module->getSourceLookupCache ().getCustomDerivativeDecls ();
4071
+ for (const AbstractFunctionDecl *afd : decls) {
4072
+ for (const auto *derAttr :
4073
+ afd->getAttrs ().getAttributes <DerivativeAttr>()) {
4074
+ // Resolve derivative function configurations from `@derivative`
4075
+ // attributes by type-checking them.
4076
+ (void )derAttr->getOriginalFunction (sf->getASTContext ());
4077
+ }
4078
+ }
4079
+ return {};
4080
+ }
4081
+
4029
4082
version::Version ModuleDecl::getLanguageVersionBuiltWith () const {
4030
4083
for (auto *F : getFiles ()) {
4031
4084
auto *LD = dyn_cast<LoadedFile>(F);
0 commit comments