@@ -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,9 @@ class swift::SourceLookupCache {
205
207
// / guaranteed to be meaningful.
206
208
void getPrecedenceGroups (SmallVectorImpl<PrecedenceGroupDecl *> &results);
207
209
210
+ // TODO: is it valid to return const reference from here?
211
+ llvm::SmallVector<AbstractFunctionDecl *, 0 > getCustomDerivativeDecls ();
212
+
208
213
// / Look up an operator declaration.
209
214
// /
210
215
// / \param name The operator name ("+", ">>", etc.)
@@ -249,9 +254,10 @@ static Decl *getAsDecl(Decl *decl) { return decl; }
249
254
static Expr *getAsExpr (ASTNode node) { return node.dyn_cast <Expr *>(); }
250
255
static Decl *getAsDecl (ASTNode node) { return node.dyn_cast <Decl *>(); }
251
256
252
- template <typename Range>
257
+ template <typename Range>
253
258
void SourceLookupCache::addToUnqualifiedLookupCache (Range items,
254
- bool onlyOperators) {
259
+ bool onlyOperators,
260
+ bool onlyDerivatives) {
255
261
for (auto item : items) {
256
262
// In script mode, we'll see macro expansion expressions for freestanding
257
263
// macros.
@@ -268,19 +274,36 @@ void SourceLookupCache::addToUnqualifiedLookupCache(Range items,
268
274
continue ;
269
275
270
276
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.
277
+ auto getDerivative = [onlyDerivatives, VD]() -> AbstractFunctionDecl * {
278
+ if (auto *AFD = dyn_cast<AbstractFunctionDecl>(VD))
279
+ if (AFD->getAttrs ().hasAttribute <DerivativeAttr>())
280
+ return AFD;
281
+ return nullptr ;
282
+ };
283
+ if (onlyOperators && VD->isOperator ())
273
284
TopLevelValues.add (VD);
274
-
275
- if (!onlyOperators && VD->getAttrs ().hasAttribute <CustomAttr>()) {
285
+ if (onlyDerivatives)
286
+ if (AbstractFunctionDecl *AFD = getDerivative ())
287
+ CustomDerivatives.push_back (AFD);
288
+ if (!onlyOperators && !onlyDerivatives && VD->hasName ()) {
289
+ TopLevelValues.add (VD);
290
+ if (VD->getAttrs ().hasAttribute <CustomAttr>())
276
291
MayHaveAuxiliaryDecls.push_back (VD);
277
- }
292
+ if (AbstractFunctionDecl *AFD = getDerivative ())
293
+ CustomDerivatives.push_back (AFD);
278
294
}
279
295
}
280
296
281
- if (auto *NTD = dyn_cast<NominalTypeDecl>(D))
282
- if (!NTD->hasUnparsedMembers () || NTD->maybeHasOperatorDeclarations ())
283
- addToUnqualifiedLookupCache (NTD->getMembers (), true );
297
+ if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
298
+ bool onlyOperatorsArg =
299
+ (!NTD->hasUnparsedMembers () || NTD->maybeHasOperatorDeclarations ());
300
+ bool onlyDerivativesArg =
301
+ (!NTD->hasUnparsedMembers () || NTD->maybeHasDerivativeDeclarations ());
302
+ if (onlyOperatorsArg || onlyDerivativesArg) {
303
+ addToUnqualifiedLookupCache (NTD->getMembers (), onlyOperatorsArg,
304
+ onlyDerivativesArg);
305
+ }
306
+ }
284
307
285
308
if (auto *ED = dyn_cast<ExtensionDecl>(D)) {
286
309
// Avoid populating the cache with the members of invalid extension
@@ -292,8 +315,14 @@ void SourceLookupCache::addToUnqualifiedLookupCache(Range items,
292
315
MayHaveAuxiliaryDecls.push_back (ED);
293
316
}
294
317
295
- if (!ED->hasUnparsedMembers () || ED->maybeHasOperatorDeclarations ())
296
- addToUnqualifiedLookupCache (ED->getMembers (), true );
318
+ bool onlyOperatorsArg =
319
+ (!ED->hasUnparsedMembers () || ED->maybeHasOperatorDeclarations ());
320
+ bool onlyDerivativesArg =
321
+ (!ED->hasUnparsedMembers () || ED->maybeHasDerivativeDeclarations ());
322
+ if (onlyOperatorsArg || onlyDerivativesArg) {
323
+ addToUnqualifiedLookupCache (ED->getMembers (), onlyOperatorsArg,
324
+ onlyDerivativesArg);
325
+ }
297
326
}
298
327
299
328
if (auto *OD = dyn_cast<OperatorDecl>(D))
@@ -307,7 +336,8 @@ void SourceLookupCache::addToUnqualifiedLookupCache(Range items,
307
336
MayHaveAuxiliaryDecls.push_back (MED);
308
337
} else if (auto TLCD = dyn_cast<TopLevelCodeDecl>(D)) {
309
338
if (auto body = TLCD->getBody ()){
310
- addToUnqualifiedLookupCache (body->getElements (), onlyOperators);
339
+ addToUnqualifiedLookupCache (body->getElements (), onlyOperators,
340
+ onlyDerivatives);
311
341
}
312
342
}
313
343
}
@@ -488,8 +518,8 @@ SourceLookupCache::SourceLookupCache(const SourceFile &SF)
488
518
{
489
519
FrontendStatsTracer tracer (SF.getASTContext ().Stats ,
490
520
" source-file-populate-cache" );
491
- addToUnqualifiedLookupCache (SF.getTopLevelItems (), false );
492
- addToUnqualifiedLookupCache (SF.getHoistedDecls (), false );
521
+ addToUnqualifiedLookupCache (SF.getTopLevelItems (), false , false );
522
+ addToUnqualifiedLookupCache (SF.getHoistedDecls (), false , false );
493
523
}
494
524
495
525
SourceLookupCache::SourceLookupCache (const ModuleDecl &M)
@@ -499,11 +529,11 @@ SourceLookupCache::SourceLookupCache(const ModuleDecl &M)
499
529
" module-populate-cache" );
500
530
for (const FileUnit *file : M.getFiles ()) {
501
531
auto *SF = cast<SourceFile>(file);
502
- addToUnqualifiedLookupCache (SF->getTopLevelItems (), false );
503
- addToUnqualifiedLookupCache (SF->getHoistedDecls (), false );
532
+ addToUnqualifiedLookupCache (SF->getTopLevelItems (), false , false );
533
+ addToUnqualifiedLookupCache (SF->getHoistedDecls (), false , false );
504
534
505
535
if (auto *SFU = file->getSynthesizedFile ()) {
506
- addToUnqualifiedLookupCache (SFU->getTopLevelDecls (), false );
536
+ addToUnqualifiedLookupCache (SFU->getTopLevelDecls (), false , false );
507
537
}
508
538
}
509
539
}
@@ -572,6 +602,11 @@ void SourceLookupCache::getOperatorDecls(
572
602
results.append (ops.second .begin (), ops.second .end ());
573
603
}
574
604
605
+ llvm::SmallVector<AbstractFunctionDecl *, 0 >
606
+ SourceLookupCache::getCustomDerivativeDecls () {
607
+ return CustomDerivatives;
608
+ }
609
+
575
610
void SourceLookupCache::lookupOperator (Identifier name, OperatorFixity fixity,
576
611
TinyPtrVector<OperatorDecl *> &results) {
577
612
auto ops = Operators.find (name);
@@ -4008,6 +4043,23 @@ bool IsNonUserModuleRequest::evaluate(Evaluator &evaluator, ModuleDecl *mod) con
4008
4043
(!sdkOrPlatform.empty () && pathStartsWith (sdkOrPlatform, modulePath));
4009
4044
}
4010
4045
4046
+ evaluator::SideEffect CustomDerivativesRequest::evaluate (Evaluator &evaluator,
4047
+ SourceFile *sf) const {
4048
+ ModuleDecl *module = sf->getParentModule ();
4049
+ assert (isParsedModule (module));
4050
+ llvm::SmallVector<AbstractFunctionDecl *, 0 > decls =
4051
+ module->getSourceLookupCache ().getCustomDerivativeDecls ();
4052
+ for (const AbstractFunctionDecl *afd : decls) {
4053
+ for (const auto *derAttr :
4054
+ afd->getAttrs ().getAttributes <DerivativeAttr>()) {
4055
+ // Resolve derivative function configurations from `@derivative`
4056
+ // attributes by type-checking them.
4057
+ (void )derAttr->getOriginalFunction (sf->getASTContext ());
4058
+ }
4059
+ }
4060
+ return {};
4061
+ }
4062
+
4011
4063
version::Version ModuleDecl::getLanguageVersionBuiltWith () const {
4012
4064
for (auto *F : getFiles ()) {
4013
4065
auto *LD = dyn_cast<LoadedFile>(F);
0 commit comments