Skip to content

Commit 828de17

Browse files
committed
[Macros] Resolve macro names using unqualified lookup that ignores expansions
The macro name resolution in the source lookup cache was only looking at macros in the current module, meaning that any names introduced by peer or declaration macros declared in one module but used in another would not be found by name lookup. Switch the source lookup cache over to using the same `forEachPotentialResolvedMacro` API that is used by lookup within types, so we have consistent name-lookup-level macro resolution in both places. ... except that would be horribly cyclic, of course, so introduce name lookup flags to ignore top-level declarations introduced by macro expansions. This is semantically correct because macro expansions are not allowed to introduce new macros anyway, because that would have been a terrible idea. Fixes rdar://107321469. Peer and declaration macros at module scope should work a whole lot better now.
1 parent 706b3e1 commit 828de17

18 files changed

+116
-38
lines changed

include/swift/AST/FileUnit.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ class FileUnit : public DeclContext, public ASTAllocated<FileUnit> {
6565
///
6666
/// This does a simple local lookup, not recursively looking through imports.
6767
virtual void lookupValue(DeclName name, NLKind lookupKind,
68+
OptionSet<ModuleLookupFlags> Flags,
6869
SmallVectorImpl<ValueDecl*> &result) const = 0;
6970

7071
/// Look up a local type declaration by its mangled name.
@@ -381,6 +382,7 @@ class BuiltinUnit final : public FileUnit {
381382
explicit BuiltinUnit(ModuleDecl &M);
382383

383384
virtual void lookupValue(DeclName name, NLKind lookupKind,
385+
OptionSet<ModuleLookupFlags> Flags,
384386
SmallVectorImpl<ValueDecl*> &result) const override;
385387

386388
/// Find all Objective-C methods with the given selector.

include/swift/AST/LookupKinds.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ enum NLOptions : unsigned {
5353
// Include @usableFromInline and @inlinable
5454
NL_IncludeUsableFromInline = 1 << 6,
5555

56+
/// Exclude names introduced by macro expansions in the top-level module.
57+
NL_ExcludeMacroExpansions = 1 << 7,
58+
5659
/// The default set of options used for qualified name lookup.
5760
///
5861
/// FIXME: Eventually, add NL_ProtocolMembers to this, once all of the
@@ -81,6 +84,13 @@ static inline NLOptions operator~(NLOptions value) {
8184

8285
void simple_display(llvm::raw_ostream &out, NLOptions options);
8386

87+
88+
/// Flags affecting module-level lookup.
89+
enum class ModuleLookupFlags : unsigned {
90+
/// Exclude names introduced by macro expansions in the top-level module.
91+
ExcludeMacroExpansions = 1 << 0,
92+
};
93+
8494
} // end namespace swift
8595

8696
#endif

include/swift/AST/Module.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,8 +728,19 @@ class ModuleDecl
728728
///
729729
/// This does a simple local lookup, not recursively looking through imports.
730730
void lookupValue(DeclName Name, NLKind LookupKind,
731+
OptionSet<ModuleLookupFlags> Flags,
731732
SmallVectorImpl<ValueDecl*> &Result) const;
732733

734+
/// Look up a (possibly overloaded) value set at top-level scope
735+
/// (but with the specified access path, which may come from an import decl)
736+
/// within the current module.
737+
///
738+
/// This does a simple local lookup, not recursively looking through imports.
739+
void lookupValue(DeclName Name, NLKind LookupKind,
740+
SmallVectorImpl<ValueDecl*> &Result) const {
741+
lookupValue(Name, LookupKind, {}, Result);
742+
}
743+
733744
/// Look up a local type declaration by its mangled name.
734745
///
735746
/// This does a simple local lookup, not recursively looking through imports.

include/swift/AST/NameLookup.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,8 @@ enum class UnqualifiedLookupFlags {
240240
// This lookup should include results that are @inlinable or
241241
// @usableFromInline.
242242
IncludeUsableFromInline = 1 << 5,
243+
/// This lookup should exclude any names introduced by macro expansions.
244+
ExcludeMacroExpansions = 1 << 6,
243245
};
244246

245247
using UnqualifiedLookupOptions = OptionSet<UnqualifiedLookupFlags>;
@@ -543,6 +545,17 @@ template <typename Result>
543545
void filterForDiscriminator(SmallVectorImpl<Result> &results,
544546
DebuggerClient *debugClient);
545547

548+
/// Call the given function body with each macro declaration and its associated
549+
/// role attribute for the given role.
550+
///
551+
/// This routine intentionally avoids calling `forEachAttachedMacro`, which
552+
/// triggers request cycles, and should only be used when resolving macro
553+
/// names for the purposes of (other) name lookup.
554+
void forEachPotentialResolvedMacro(
555+
DeclContext *moduleScopeCtx, DeclNameRef macroName, MacroRole role,
556+
llvm::function_ref<void(MacroDecl *, const MacroRoleAttr *)> body
557+
);
558+
546559
} // end namespace namelookup
547560

548561
/// Describes an inherited nominal entry.

include/swift/AST/SourceFile.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ class SourceFile final : public FileUnit {
442442
const SmallVectorImpl<ValueDecl *> &getCachedVisibleDecls() const;
443443

444444
virtual void lookupValue(DeclName name, NLKind lookupKind,
445+
OptionSet<ModuleLookupFlags> Flags,
445446
SmallVectorImpl<ValueDecl*> &result) const override;
446447

447448
virtual void lookupVisibleDecls(ImportPath::Access accessPath,

include/swift/AST/SynthesizedFileUnit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class SynthesizedFileUnit final : public FileUnit {
4444
void addTopLevelDecl(Decl *D) { TopLevelDecls.push_back(D); }
4545

4646
virtual void lookupValue(DeclName name, NLKind lookupKind,
47+
OptionSet<ModuleLookupFlags> Flags,
4748
SmallVectorImpl<ValueDecl *> &result) const override;
4849

4950
void lookupObjCMethods(

include/swift/ClangImporter/ClangModule.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class ClangModuleUnit final : public LoadedFile {
6666
virtual bool isSystemModule() const override;
6767

6868
virtual void lookupValue(DeclName name, NLKind lookupKind,
69+
OptionSet<ModuleLookupFlags> Flags,
6970
SmallVectorImpl<ValueDecl*> &results) const override;
7071

7172
virtual TypeDecl *

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@ class SerializedASTFile final : public LoadedFile {
360360
virtual bool isSystemModule() const override;
361361

362362
virtual void lookupValue(DeclName name, NLKind lookupKind,
363+
OptionSet<ModuleLookupFlags> Flags,
363364
SmallVectorImpl<ValueDecl*> &results) const override;
364365

365366
virtual StringRef

lib/AST/ASTContext.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,7 +1152,9 @@ ProtocolDecl *ASTContext::getProtocol(KnownProtocolKind kind) const {
11521152
if (!M)
11531153
return nullptr;
11541154
M->lookupValue(getIdentifier(getProtocolName(kind)),
1155-
NLKind::UnqualifiedLookup, results);
1155+
NLKind::UnqualifiedLookup,
1156+
ModuleLookupFlags::ExcludeMacroExpansions,
1157+
results);
11561158

11571159
for (auto result : results) {
11581160
if (auto protocol = dyn_cast<ProtocolDecl>(result)) {
@@ -6307,7 +6309,7 @@ Type ASTContext::getNamedSwiftType(ModuleDecl *module, StringRef name) {
63076309
if (auto module = clangUnit->getOverlayModule())
63086310
module->lookupValue(identifier, NLKind::UnqualifiedLookup, results);
63096311
} else {
6310-
file->lookupValue(identifier, NLKind::UnqualifiedLookup, results);
6312+
file->lookupValue(identifier, NLKind::UnqualifiedLookup, { }, results);
63116313
}
63126314
}
63136315

lib/AST/Module.cpp

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,6 @@ class swift::SourceLookupCache {
172172
template<typename Range>
173173
void addToMemberCache(Range decls);
174174

175-
using MacroDeclMap = llvm::DenseMap<Identifier, TinyPtrVector<MacroDecl *>>;
176-
MacroDeclMap MacroDecls;
177-
178175
using AuxiliaryDeclMap = llvm::DenseMap<DeclName, TinyPtrVector<MissingDecl *>>;
179176
AuxiliaryDeclMap TopLevelAuxiliaryDecls;
180177
SmallVector<Decl *, 4> MayHaveAuxiliaryDecls;
@@ -190,6 +187,7 @@ class swift::SourceLookupCache {
190187
void invalidate();
191188

192189
void lookupValue(DeclName Name, NLKind LookupKind,
190+
OptionSet<ModuleLookupFlags> Flags,
193191
SmallVectorImpl<ValueDecl*> &Result);
194192

195193
/// Retrieves all the operator decls. The order of the results is not
@@ -263,6 +261,10 @@ void SourceLookupCache::addToUnqualifiedLookupCache(Range decls,
263261
// a malformed context.
264262
if (ED->isInvalid()) continue;
265263

264+
if (ED->getAttrs().hasAttribute<CustomAttr>()) {
265+
MayHaveAuxiliaryDecls.push_back(ED);
266+
}
267+
266268
if (!ED->hasUnparsedMembers() || ED->maybeHasOperatorDeclarations())
267269
addToUnqualifiedLookupCache(ED->getMembers(), true);
268270
}
@@ -273,9 +275,6 @@ void SourceLookupCache::addToUnqualifiedLookupCache(Range decls,
273275
else if (auto *PG = dyn_cast<PrecedenceGroupDecl>(D))
274276
PrecedenceGroups[PG->getName()].push_back(PG);
275277

276-
else if (auto *macro = dyn_cast<MacroDecl>(D))
277-
MacroDecls[macro->getBaseIdentifier()].push_back(macro);
278-
279278
else if (auto *MED = dyn_cast<MacroExpansionDecl>(D))
280279
MayHaveAuxiliaryDecls.push_back(MED);
281280
}
@@ -353,32 +352,26 @@ void SourceLookupCache::populateAuxiliaryDeclCache() {
353352
for (auto attrConst : decl->getAttrs().getAttributes<CustomAttr>()) {
354353
auto *attr = const_cast<CustomAttr *>(attrConst);
355354
UnresolvedMacroReference macroRef(attr);
356-
auto macroName = macroRef.getMacroName().getBaseIdentifier();
357-
358-
auto found = MacroDecls.find(macroName);
359-
if (found == MacroDecls.end())
360-
continue;
361-
362-
for (const auto *macro : found->second) {
363-
macro->getIntroducedNames(MacroRole::Peer,
364-
dyn_cast<ValueDecl>(decl),
365-
introducedNames[attr]);
366-
}
355+
namelookup::forEachPotentialResolvedMacro(
356+
decl->getDeclContext()->getModuleScopeContext(),
357+
macroRef.getMacroName(), MacroRole::Peer,
358+
[&](MacroDecl *macro, const MacroRoleAttr *roleAttr) {
359+
macro->getIntroducedNames(MacroRole::Peer,
360+
dyn_cast<ValueDecl>(decl),
361+
introducedNames[attr]);
362+
});
367363
}
368364

369365
if (auto *med = dyn_cast<MacroExpansionDecl>(decl)) {
370366
UnresolvedMacroReference macroRef(med);
371-
auto macroName = macroRef.getMacroName().getBaseIdentifier();
372-
373-
auto found = MacroDecls.find(macroName);
374-
if (found == MacroDecls.end())
375-
continue;
376-
377-
for (const auto *macro : found->second) {
378-
macro->getIntroducedNames(MacroRole::Declaration,
379-
/*attachedTo*/ nullptr,
380-
introducedNames[med]);
381-
}
367+
namelookup::forEachPotentialResolvedMacro(
368+
decl->getDeclContext()->getModuleScopeContext(),
369+
macroRef.getMacroName(), MacroRole::Declaration,
370+
[&](MacroDecl *macro, const MacroRoleAttr *roleAttr) {
371+
macro->getIntroducedNames(MacroRole::Declaration,
372+
/*attachedTo*/ nullptr,
373+
introducedNames[med]);
374+
});
382375
}
383376

384377
// Add macro-introduced names to the top-level auxiliary decl cache as
@@ -425,6 +418,7 @@ SourceLookupCache::SourceLookupCache(const ModuleDecl &M)
425418
}
426419

427420
void SourceLookupCache::lookupValue(DeclName Name, NLKind LookupKind,
421+
OptionSet<ModuleLookupFlags> Flags,
428422
SmallVectorImpl<ValueDecl*> &Result) {
429423
auto I = TopLevelValues.find(Name);
430424
if (I != TopLevelValues.end()) {
@@ -433,6 +427,10 @@ void SourceLookupCache::lookupValue(DeclName Name, NLKind LookupKind,
433427
Result.push_back(Elt);
434428
}
435429

430+
// If we aren't supposed to find names introduced by macros, we're done.
431+
if (Flags.contains(ModuleLookupFlags::ExcludeMacroExpansions))
432+
return;
433+
436434
// Add top-level auxiliary decls to the result.
437435
//
438436
// FIXME: We need to not consider auxiliary decls if we're doing lookup
@@ -863,17 +861,18 @@ static bool isParsedModule(const ModuleDecl *mod) {
863861
}
864862

865863
void ModuleDecl::lookupValue(DeclName Name, NLKind LookupKind,
864+
OptionSet<ModuleLookupFlags> Flags,
866865
SmallVectorImpl<ValueDecl*> &Result) const {
867866
auto *stats = getASTContext().Stats;
868867
if (stats)
869868
++stats->getFrontendCounters().NumModuleLookupValue;
870869

871870
if (isParsedModule(this)) {
872-
getSourceLookupCache().lookupValue(Name, LookupKind, Result);
871+
getSourceLookupCache().lookupValue(Name, LookupKind, Flags, Result);
873872
return;
874873
}
875874

876-
FORWARD(lookupValue, (Name, LookupKind, Result));
875+
FORWARD(lookupValue, (Name, LookupKind, Flags, Result));
877876
}
878877

879878
TypeDecl * ModuleDecl::lookupLocalType(StringRef MangledName) const {
@@ -967,6 +966,7 @@ void ModuleDecl::lookupImportedSPIGroups(
967966
}
968967

969968
void BuiltinUnit::lookupValue(DeclName name, NLKind lookupKind,
969+
OptionSet<ModuleLookupFlags> Flags,
970970
SmallVectorImpl<ValueDecl*> &result) const {
971971
getCache().lookupValue(name.getBaseIdentifier(), lookupKind, *this, result);
972972
}
@@ -978,8 +978,9 @@ void BuiltinUnit::lookupObjCMethods(
978978
}
979979

980980
void SourceFile::lookupValue(DeclName name, NLKind lookupKind,
981+
OptionSet<ModuleLookupFlags> flags,
981982
SmallVectorImpl<ValueDecl*> &result) const {
982-
getCache().lookupValue(name, lookupKind, result);
983+
getCache().lookupValue(name, lookupKind, flags, result);
983984
}
984985

985986
void ModuleDecl::lookupVisibleDecls(ImportPath::Access AccessPath,
@@ -3922,6 +3923,7 @@ SynthesizedFileUnit::getDiscriminatorForPrivateValue(const ValueDecl *D) const {
39223923

39233924
void SynthesizedFileUnit::lookupValue(
39243925
DeclName name, NLKind lookupKind,
3926+
OptionSet<ModuleLookupFlags> Flags,
39253927
SmallVectorImpl<ValueDecl *> &result) const {
39263928
for (auto *decl : TopLevelDecls) {
39273929
if (auto VD = dyn_cast<ValueDecl>(decl)) {

lib/AST/ModuleNameLookup.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ class ModuleNameLookup {
5757
NLOptions options);
5858
};
5959

60+
// Exclude names introduced by macro expansions.
61+
enum class LocalLookupFlags {
62+
ExcludeMacroExpansions,
63+
};
6064

6165
/// Encapsulates the work done for a recursive qualified lookup into a module
6266
/// by full name.
@@ -81,12 +85,13 @@ class LookupByName : public ModuleNameLookup<LookupByName> {
8185
}
8286

8387
void doLocalLookup(ModuleDecl *module, ImportPath::Access path,
88+
OptionSet<ModuleLookupFlags> flags,
8489
SmallVectorImpl<ValueDecl *> &localDecls) {
8590
// If this import is specific to some named decl ("import Swift.Int")
8691
// then filter out any lookups that don't match.
8792
if (!path.matches(name))
8893
return;
89-
module->lookupValue(name, lookupKind, localDecls);
94+
module->lookupValue(name, lookupKind, flags, localDecls);
9095
}
9196
};
9297

@@ -112,6 +117,7 @@ class LookupVisibleDecls : public ModuleNameLookup<LookupVisibleDecls> {
112117
}
113118

114119
void doLocalLookup(ModuleDecl *module, ImportPath::Access path,
120+
OptionSet<ModuleLookupFlags> flags,
115121
SmallVectorImpl<ValueDecl *> &localDecls) {
116122
VectorDeclConsumer consumer(localDecls);
117123
module->lookupVisibleDecls(path, consumer, lookupKind);
@@ -167,9 +173,14 @@ void ModuleNameLookup<LookupStrategy>::lookupInModule(
167173
currentCount = decls.size();
168174
};
169175

176+
OptionSet<ModuleLookupFlags> currentModuleLookupFlags = {};
177+
if (options & NL_ExcludeMacroExpansions)
178+
currentModuleLookupFlags |= ModuleLookupFlags::ExcludeMacroExpansions;
179+
170180
// Do the lookup into the current module.
171181
auto *module = moduleOrFile->getParentModule();
172-
getDerived()->doLocalLookup(module, accessPath, decls);
182+
getDerived()->doLocalLookup(
183+
module, accessPath, currentModuleLookupFlags, decls);
173184
updateNewDecls(moduleScopeContext);
174185

175186
bool canReturnEarly = (initialCount != decls.size() &&
@@ -198,7 +209,7 @@ void ModuleNameLookup<LookupStrategy>::lookupInModule(
198209
return;
199210

200211
getDerived()->doLocalLookup(import.importedModule, import.accessPath,
201-
decls);
212+
{ }, decls);
202213
updateNewDecls(moduleScopeContext);
203214
};
204215

lib/AST/NameLookup.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,12 +1539,16 @@ static DeclName adjustLazyMacroExpansionNameKey(
15391539
///
15401540
/// This routine intentionally avoids calling `forEachAttachedMacro`, which
15411541
/// triggers request cycles.
1542-
static void forEachPotentialResolvedMacro(
1542+
void namelookup::forEachPotentialResolvedMacro(
15431543
DeclContext *moduleScopeCtx, DeclNameRef macroName, MacroRole role,
15441544
llvm::function_ref<void(MacroDecl *, const MacroRoleAttr *)> body
15451545
) {
15461546
ASTContext &ctx = moduleScopeCtx->getASTContext();
1547-
UnqualifiedLookupDescriptor lookupDesc{macroName, moduleScopeCtx};
1547+
UnqualifiedLookupDescriptor lookupDesc{
1548+
macroName, moduleScopeCtx, SourceLoc(),
1549+
UnqualifiedLookupFlags::ExcludeMacroExpansions
1550+
};
1551+
15481552
auto lookup = evaluateOrDefault(
15491553
ctx.evaluator, UnqualifiedLookupRequest{lookupDesc}, {});
15501554
for (auto result : lookup.allResults()) {

lib/AST/UnqualifiedLookup.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,8 @@ void UnqualifiedLookupFactory::addImportedResults(const DeclContext *const dc) {
520520
auto nlOptions = NL_UnqualifiedDefault;
521521
if (options.contains(Flags::IncludeUsableFromInline))
522522
nlOptions |= NL_IncludeUsableFromInline;
523+
if (options.contains(Flags::ExcludeMacroExpansions))
524+
nlOptions |= NL_ExcludeMacroExpansions;
523525
lookupInModule(dc, Name.getFullName(), CurModuleResults,
524526
NLKind::UnqualifiedLookup, resolutionKind, dc, nlOptions);
525527

lib/ClangImporter/ClangImporter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3344,6 +3344,7 @@ void ClangModuleUnit::getDisplayDecls(SmallVectorImpl<Decl*> &results, bool recu
33443344
}
33453345

33463346
void ClangModuleUnit::lookupValue(DeclName name, NLKind lookupKind,
3347+
OptionSet<ModuleLookupFlags> flags,
33473348
SmallVectorImpl<ValueDecl*> &results) const {
33483349
// FIXME: Ignore submodules, which are empty for now.
33493350
if (clangModule && clangModule->isSubModule())

lib/ClangImporter/DWARFImporter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class DWARFModuleUnit final : public LoadedFile {
3333
/// DWARFimporterDelegate.
3434
virtual void
3535
lookupValue(DeclName name, NLKind lookupKind,
36+
OptionSet<ModuleLookupFlags> Flags,
3637
SmallVectorImpl<ValueDecl *> &results) const override {
3738
Owner.lookupValueDWARF(name, lookupKind,
3839
getParentModule()->getName(), results);

0 commit comments

Comments
 (0)