@@ -166,15 +166,17 @@ class swift::SourceLookupCache {
166166 ValueDeclMap TopLevelValues;
167167 ValueDeclMap ClassMembers;
168168 bool MemberCachePopulated = false ;
169+ llvm::SmallVector<AbstractFunctionDecl *, 0 > CustomDerivatives;
169170 DeclName UniqueMacroNamePlaceholder;
170171
171172 template <typename T>
172173 using OperatorMap = llvm::DenseMap<Identifier, TinyPtrVector<T *>>;
173174 OperatorMap<OperatorDecl> Operators;
174175 OperatorMap<PrecedenceGroupDecl> PrecedenceGroups;
175176
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);
178180 template <typename Range>
179181 void addToMemberCache (Range decls);
180182
@@ -205,6 +207,10 @@ class swift::SourceLookupCache {
205207 // / guaranteed to be meaningful.
206208 void getPrecedenceGroups (SmallVectorImpl<PrecedenceGroupDecl *> &results);
207209
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+
208214 // / Look up an operator declaration.
209215 // /
210216 // / \param name The operator name ("+", ">>", etc.)
@@ -249,9 +255,10 @@ static Decl *getAsDecl(Decl *decl) { return decl; }
249255static Expr *getAsExpr (ASTNode node) { return node.dyn_cast <Expr *>(); }
250256static Decl *getAsDecl (ASTNode node) { return node.dyn_cast <Decl *>(); }
251257
252- template <typename Range>
258+ template <typename Range>
253259void SourceLookupCache::addToUnqualifiedLookupCache (Range items,
254- bool onlyOperators) {
260+ bool onlyOperators,
261+ bool onlyDerivatives) {
255262 for (auto item : items) {
256263 // In script mode, we'll see macro expansion expressions for freestanding
257264 // macros.
@@ -268,19 +275,36 @@ void SourceLookupCache::addToUnqualifiedLookupCache(Range items,
268275 continue ;
269276
270277 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 ())
273285 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>())
276292 MayHaveAuxiliaryDecls.push_back (VD);
277- }
293+ if (AbstractFunctionDecl *AFD = getDerivative ())
294+ CustomDerivatives.push_back (AFD);
278295 }
279296 }
280297
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+ }
284308
285309 if (auto *ED = dyn_cast<ExtensionDecl>(D)) {
286310 // Avoid populating the cache with the members of invalid extension
@@ -292,8 +316,14 @@ void SourceLookupCache::addToUnqualifiedLookupCache(Range items,
292316 MayHaveAuxiliaryDecls.push_back (ED);
293317 }
294318
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+ }
297327 }
298328
299329 if (auto *OD = dyn_cast<OperatorDecl>(D))
@@ -307,7 +337,8 @@ void SourceLookupCache::addToUnqualifiedLookupCache(Range items,
307337 MayHaveAuxiliaryDecls.push_back (MED);
308338 } else if (auto TLCD = dyn_cast<TopLevelCodeDecl>(D)) {
309339 if (auto body = TLCD->getBody ()){
310- addToUnqualifiedLookupCache (body->getElements (), onlyOperators);
340+ addToUnqualifiedLookupCache (body->getElements (), onlyOperators,
341+ onlyDerivatives);
311342 }
312343 }
313344 }
@@ -488,8 +519,8 @@ SourceLookupCache::SourceLookupCache(const SourceFile &SF)
488519{
489520 FrontendStatsTracer tracer (SF.getASTContext ().Stats ,
490521 " 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 );
493524}
494525
495526SourceLookupCache::SourceLookupCache (const ModuleDecl &M)
@@ -499,11 +530,11 @@ SourceLookupCache::SourceLookupCache(const ModuleDecl &M)
499530 " module-populate-cache" );
500531 for (const FileUnit *file : M.getFiles ()) {
501532 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 );
504535
505536 if (auto *SFU = file->getSynthesizedFile ()) {
506- addToUnqualifiedLookupCache (SFU->getTopLevelDecls (), false );
537+ addToUnqualifiedLookupCache (SFU->getTopLevelDecls (), false , false );
507538 }
508539 }
509540}
@@ -572,6 +603,11 @@ void SourceLookupCache::getOperatorDecls(
572603 results.append (ops.second .begin (), ops.second .end ());
573604}
574605
606+ llvm::SmallVector<AbstractFunctionDecl *, 0 >
607+ SourceLookupCache::getCustomDerivativeDecls () {
608+ return CustomDerivatives;
609+ }
610+
575611void SourceLookupCache::lookupOperator (Identifier name, OperatorFixity fixity,
576612 TinyPtrVector<OperatorDecl *> &results) {
577613 auto ops = Operators.find (name);
@@ -4026,6 +4062,23 @@ bool IsNonUserModuleRequest::evaluate(Evaluator &evaluator, ModuleDecl *mod) con
40264062 return false ;
40274063}
40284064
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+
40294082version::Version ModuleDecl::getLanguageVersionBuiltWith () const {
40304083 for (auto *F : getFiles ()) {
40314084 auto *LD = dyn_cast<LoadedFile>(F);
0 commit comments