@@ -1534,77 +1534,132 @@ static DeclName adjustLazyMacroExpansionNameKey(
15341534 return name;
15351535}
15361536
1537+ // / Call the given function body with each macro declaration and its associated
1538+ // / role attribute for the given role.
1539+ // /
1540+ // / This routine intentionally avoids calling `forEachAttachedMacro`, which
1541+ // / triggers request cycles.
1542+ static void forEachPotentialResolvedMacro (
1543+ DeclContext *moduleScopeCtx, DeclNameRef macroName, MacroRole role,
1544+ llvm::function_ref<void (MacroDecl *, const MacroRoleAttr *)> body
1545+ ) {
1546+ ASTContext &ctx = moduleScopeCtx->getASTContext ();
1547+ UnqualifiedLookupDescriptor lookupDesc{macroName, moduleScopeCtx};
1548+ auto lookup = evaluateOrDefault (
1549+ ctx.evaluator , UnqualifiedLookupRequest{lookupDesc}, {});
1550+ for (auto result : lookup.allResults ()) {
1551+ auto *vd = result.getValueDecl ();
1552+ auto *macro = dyn_cast<MacroDecl>(vd);
1553+ if (!macro)
1554+ continue ;
1555+
1556+ auto *macroRoleAttr = macro->getMacroRoleAttr (role);
1557+ if (!macroRoleAttr)
1558+ continue ;
1559+
1560+ body (macro, macroRoleAttr);
1561+ }
1562+ }
1563+
1564+ // / For each macro with the given role that might be attached to the given
1565+ // / declaration, call the body.
1566+ static void forEachPotentialAttachedMacro (
1567+ Decl *decl, MacroRole role,
1568+ llvm::function_ref<void (MacroDecl *macro, const MacroRoleAttr *)> body
1569+ ) {
1570+ // We intentionally avoid calling `forEachAttachedMacro` in order to avoid
1571+ // a request cycle.
1572+ auto moduleScopeCtx = decl->getDeclContext ()->getModuleScopeContext ();
1573+ for (auto attrConst : decl->getSemanticAttrs ().getAttributes <CustomAttr>()) {
1574+ auto *attr = const_cast <CustomAttr *>(attrConst);
1575+ UnresolvedMacroReference macroRef (attr);
1576+ auto macroName = macroRef.getMacroName ();
1577+ forEachPotentialResolvedMacro (moduleScopeCtx, macroName, role, body);
1578+ }
1579+ }
1580+
1581+ namespace {
1582+ // / Function object that tracks macro-introduced names.
1583+ struct MacroIntroducedNameTracker {
1584+ ValueDecl *attachedTo = nullptr ;
1585+
1586+ llvm::SmallSet<DeclName, 4 > allIntroducedNames;
1587+ bool introducesArbitraryNames = false ;
1588+
1589+ // / Augment the set of names with those introduced by the given macro.
1590+ void operator ()(MacroDecl *macro, const MacroRoleAttr *attr) {
1591+ // First check for arbitrary names.
1592+ if (attr->hasNameKind (MacroIntroducedDeclNameKind::Arbitrary)) {
1593+ introducesArbitraryNames = true ;
1594+ }
1595+
1596+ // If this introduces arbitrary names, there's nothing more to do.
1597+ if (introducesArbitraryNames)
1598+ return ;
1599+
1600+ SmallVector<DeclName, 4 > introducedNames;
1601+ macro->getIntroducedNames (
1602+ attr->getMacroRole (), attachedTo, introducedNames);
1603+ for (auto name : introducedNames)
1604+ allIntroducedNames.insert (name);
1605+ }
1606+
1607+ bool shouldExpandForName (DeclName name) const {
1608+ return introducesArbitraryNames || allIntroducedNames.contains (name);
1609+ }
1610+ };
1611+ }
1612+
15371613static void
15381614populateLookupTableEntryFromMacroExpansions (ASTContext &ctx,
15391615 MemberLookupTable &table,
15401616 DeclName name,
15411617 TypeOrExtensionDecl container) {
1618+
1619+ // Trigger the expansion of member macros on the container, if any of the
1620+ // names match.
1621+ {
1622+ MacroIntroducedNameTracker nameTracker;
1623+ auto decl = container.getAsDecl ();
1624+ forEachPotentialAttachedMacro (decl, MacroRole::Member, nameTracker);
1625+ if (nameTracker.shouldExpandForName (name)) {
1626+ (void )evaluateOrDefault (
1627+ ctx.evaluator ,
1628+ ExpandSynthesizedMemberMacroRequest{decl},
1629+ false );
1630+ }
1631+ }
1632+
15421633 auto dc = container.getAsDeclContext ();
1543- auto *moduleScopeCtx = dc->getModuleScopeContext ();
15441634 auto *module = dc->getParentModule ();
15451635 auto idc = container.getAsIterableDeclContext ();
15461636 for (auto *member : idc->getCurrentMembersWithoutLoading ()) {
15471637 // Collect all macro introduced names, along with its corresponding macro
15481638 // reference. We need the macro reference to prevent adding auxiliary decls
15491639 // that weren't introduced by the macro.
1550- llvm::SmallSet<DeclName, 4 > allIntroducedNames;
1551- bool introducesArbitraryNames = false ;
1640+ MacroIntroducedNameTracker nameTracker;
15521641 if (auto *med = dyn_cast<MacroExpansionDecl>(member)) {
15531642 auto declRef = evaluateOrDefault (
15541643 ctx.evaluator , ResolveMacroRequest{med, dc},
15551644 nullptr );
15561645 if (!declRef)
15571646 continue ;
15581647 auto *macro = dyn_cast<MacroDecl>(declRef.getDecl ());
1559- if (macro->getMacroRoleAttr (MacroRole::Declaration)
1560- ->hasNameKind (MacroIntroducedDeclNameKind::Arbitrary))
1561- introducesArbitraryNames = true ;
1562- else {
1563- SmallVector<DeclName, 4 > introducedNames;
1564- macro->getIntroducedNames (MacroRole::Declaration, nullptr ,
1565- introducedNames);
1566- for (auto name : introducedNames)
1567- allIntroducedNames.insert (name);
1568- }
1648+ nameTracker (macro, macro->getMacroRoleAttr (MacroRole::Declaration));
15691649 } else if (auto *vd = dyn_cast<ValueDecl>(member)) {
1570- // We intentionally avoid calling `forEachAttachedMacro` in order to avoid
1571- // a request cycle.
1572- for (auto attrConst : member->getSemanticAttrs ().getAttributes <CustomAttr>()) {
1573- auto *attr = const_cast <CustomAttr *>(attrConst);
1574- UnresolvedMacroReference macroRef (attr);
1575- auto macroName = macroRef.getMacroName ();
1576- UnqualifiedLookupDescriptor lookupDesc{macroName, moduleScopeCtx};
1577- auto lookup = evaluateOrDefault (
1578- ctx.evaluator , UnqualifiedLookupRequest{lookupDesc}, {});
1579- for (auto result : lookup.allResults ()) {
1580- auto *vd = result.getValueDecl ();
1581- auto *macro = dyn_cast<MacroDecl>(vd);
1582- if (!macro)
1583- continue ;
1584- auto *macroRoleAttr = macro->getMacroRoleAttr (MacroRole::Peer);
1585- if (!macroRoleAttr)
1586- continue ;
1587- if (macroRoleAttr->hasNameKind (
1588- MacroIntroducedDeclNameKind::Arbitrary))
1589- introducesArbitraryNames = true ;
1590- else {
1591- SmallVector<DeclName, 4 > introducedNames;
1592- macro->getIntroducedNames (
1593- MacroRole::Peer, dyn_cast<ValueDecl>(member), introducedNames);
1594- for (auto name : introducedNames)
1595- allIntroducedNames.insert (name);
1596- }
1597- }
1598- }
1650+ nameTracker.attachedTo = dyn_cast<ValueDecl>(member);
1651+ forEachPotentialAttachedMacro (member, MacroRole::Peer, nameTracker);
15991652 }
1600- // Expand macros based on the name.
1601- if (introducesArbitraryNames || allIntroducedNames.contains (name))
1653+
1654+ // Expand macros on this member.
1655+ if (nameTracker.shouldExpandForName (name)) {
16021656 member->visitAuxiliaryDecls ([&](Decl *decl) {
16031657 auto *sf = module ->getSourceFileContainingLocation (decl->getLoc ());
16041658 // Bail out if the auxiliary decl was not produced by a macro.
16051659 if (!sf || sf->Kind != SourceFileKind::MacroExpansion) return ;
16061660 table.addMember (decl);
16071661 });
1662+ }
16081663 }
16091664}
16101665
@@ -2140,17 +2195,6 @@ QualifiedLookupRequest::evaluate(Evaluator &eval, const DeclContext *DC,
21402195 // Make sure we've resolved property wrappers, if we need them.
21412196 installPropertyWrapperMembersIfNeeded (current, member);
21422197
2143- // Expand synthesized member macros.
2144- auto &ctx = current->getASTContext ();
2145- (void )evaluateOrDefault (ctx.evaluator ,
2146- ExpandSynthesizedMemberMacroRequest{current},
2147- false );
2148- for (auto ext : current->getExtensions ()) {
2149- (void )evaluateOrDefault (ctx.evaluator ,
2150- ExpandSynthesizedMemberMacroRequest{ext},
2151- false );
2152- }
2153-
21542198 // Look for results within the current nominal type and its extensions.
21552199 bool currentIsProtocol = isa<ProtocolDecl>(current);
21562200 auto flags = OptionSet<NominalTypeDecl::LookupDirectFlags>();
0 commit comments