Skip to content

Commit bbe4ff1

Browse files
committed
[Module-scope lookup] Find arbitrary names in macro expansions.
Whenever we perform a name lookup, we need to make sure to expand all macros that use `names: arbitrary`, because of course they can produce... wait for it... arbitrary names, and we don't know what they are until we instatiate them.
1 parent f96240d commit bbe4ff1

File tree

5 files changed

+62
-7
lines changed

5 files changed

+62
-7
lines changed

lib/AST/Module.cpp

+43-4
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,10 @@ class swift::SourceLookupCache {
174174

175175
using AuxiliaryDeclMap = llvm::DenseMap<DeclName, TinyPtrVector<MissingDecl *>>;
176176
AuxiliaryDeclMap TopLevelAuxiliaryDecls;
177+
178+
/// Top-level macros that produce arbitrary names.
179+
SmallVector<MissingDecl *, 4> TopLevelArbitraryMacros;
180+
177181
SmallVector<Decl *, 4> MayHaveAuxiliaryDecls;
178182
void populateAuxiliaryDeclCache();
179183

@@ -352,26 +356,46 @@ void SourceLookupCache::populateAuxiliaryDeclCache() {
352356
for (auto attrConst : decl->getAttrs().getAttributes<CustomAttr>()) {
353357
auto *attr = const_cast<CustomAttr *>(attrConst);
354358
UnresolvedMacroReference macroRef(attr);
359+
bool introducesArbitraryNames = false;
355360
namelookup::forEachPotentialResolvedMacro(
356361
decl->getDeclContext()->getModuleScopeContext(),
357362
macroRef.getMacroName(), MacroRole::Peer,
358363
[&](MacroDecl *macro, const MacroRoleAttr *roleAttr) {
364+
// First check for arbitrary names.
365+
if (roleAttr->hasNameKind(MacroIntroducedDeclNameKind::Arbitrary)) {
366+
introducesArbitraryNames = true;
367+
}
368+
359369
macro->getIntroducedNames(MacroRole::Peer,
360370
dyn_cast<ValueDecl>(decl),
361371
introducedNames[attr]);
362372
});
373+
374+
// Record this macro where appropriate.
375+
if (introducesArbitraryNames)
376+
TopLevelArbitraryMacros.push_back(MissingDecl::forUnexpandedMacro(attr, decl));
363377
}
364378

365379
if (auto *med = dyn_cast<MacroExpansionDecl>(decl)) {
366380
UnresolvedMacroReference macroRef(med);
381+
bool introducesArbitraryNames = false;
367382
namelookup::forEachPotentialResolvedMacro(
368383
decl->getDeclContext()->getModuleScopeContext(),
369384
macroRef.getMacroName(), MacroRole::Declaration,
370385
[&](MacroDecl *macro, const MacroRoleAttr *roleAttr) {
386+
// First check for arbitrary names.
387+
if (roleAttr->hasNameKind(MacroIntroducedDeclNameKind::Arbitrary)) {
388+
introducesArbitraryNames = true;
389+
}
390+
371391
macro->getIntroducedNames(MacroRole::Declaration,
372392
/*attachedTo*/ nullptr,
373393
introducedNames[med]);
374394
});
395+
396+
// Record this macro where appropriate.
397+
if (introducesArbitraryNames)
398+
TopLevelArbitraryMacros.push_back(MissingDecl::forUnexpandedMacro(med, decl));
375399
}
376400

377401
// Add macro-introduced names to the top-level auxiliary decl cache as
@@ -440,15 +464,30 @@ void SourceLookupCache::lookupValue(DeclName Name, NLKind LookupKind,
440464
? UniqueMacroNamePlaceholder
441465
: Name;
442466
auto auxDecls = TopLevelAuxiliaryDecls.find(keyName);
443-
if (auxDecls == TopLevelAuxiliaryDecls.end())
467+
468+
// Check macro expansions that could produce this name.
469+
SmallVector<MissingDecl *, 4> unexpandedDecls;
470+
if (auxDecls != TopLevelAuxiliaryDecls.end()) {
471+
unexpandedDecls.insert(
472+
unexpandedDecls.end(), auxDecls->second.begin(), auxDecls->second.end());
473+
}
474+
475+
// Check macro expansions that can produce arbitrary names.
476+
unexpandedDecls.insert(
477+
unexpandedDecls.end(),
478+
TopLevelArbitraryMacros.begin(), TopLevelArbitraryMacros.end());
479+
480+
if (unexpandedDecls.empty())
444481
return;
445482

446-
for (auto *unexpandedDecl : auxDecls->second) {
447-
// Add expanded peers and freestanding declarations to the result.
483+
// Add matching expanded peers and freestanding declarations to the results.
484+
SmallPtrSet<ValueDecl *, 4> macroExpandedDecls;
485+
for (auto *unexpandedDecl : unexpandedDecls) {
448486
unexpandedDecl->forEachMacroExpandedDecl(
449487
[&](ValueDecl *decl) {
450488
if (decl->getName().matchesRef(Name)) {
451-
Result.push_back(decl);
489+
if (macroExpandedDecls.insert(decl).second)
490+
Result.push_back(decl);
452491
}
453492
});
454493
}

lib/Sema/TypeCheckExpr.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -615,9 +615,11 @@ static Type lookupDefaultLiteralType(const DeclContext *dc,
615615
StringRef name) {
616616
auto &ctx = dc->getASTContext();
617617
DeclNameRef nameRef(ctx.getIdentifier(name));
618-
auto lookup = TypeChecker::lookupUnqualified(dc->getModuleScopeContext(),
619-
nameRef, SourceLoc(),
620-
defaultUnqualifiedLookupOptions);
618+
auto lookup = TypeChecker::lookupUnqualified(
619+
dc->getModuleScopeContext(),
620+
nameRef, SourceLoc(),
621+
defaultUnqualifiedLookupOptions | NameLookupFlags::ExcludeMacroExpansions
622+
);
621623
TypeDecl *TD = lookup.getSingleTypeResult();
622624
if (!TD)
623625
return Type();

lib/Sema/TypeCheckNameLookup.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ convertToUnqualifiedLookupOptions(NameLookupOptions options) {
217217
newOptions |= UnqualifiedLookupFlags::IncludeOuterResults;
218218
if (options.contains(NameLookupFlags::IncludeUsableFromInline))
219219
newOptions |= UnqualifiedLookupFlags::IncludeUsableFromInline;
220+
if (options.contains(NameLookupFlags::ExcludeMacroExpansions))
221+
newOptions |= UnqualifiedLookupFlags::ExcludeMacroExpansions;
220222

221223
return newOptions;
222224
}

lib/Sema/TypeChecker.h

+2
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ enum class NameLookupFlags {
160160
IncludeOuterResults = 1 << 1,
161161
// Whether to include results that are marked @inlinable or @usableFromInline.
162162
IncludeUsableFromInline = 1 << 2,
163+
/// This lookup should exclude any names introduced by macro expansions.
164+
ExcludeMacroExpansions = 1 << 3,
163165
};
164166

165167
/// A set of options that control name lookup.

test/Macros/top_level_freestanding.swift

+10
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,13 @@ struct HasInnerClosure {
5454
#freestandingWithClosure(0) { x in x }
5555
#freestandingWithClosure(1) { x in x }
5656
}
57+
58+
// Arbitrary names at global scope
59+
60+
@freestanding(declaration, names: arbitrary) macro bitwidthNumberedStructs(_ baseName: String) = #externalMacro(module: "MacroDefinition", type: "DefineBitwidthNumberedStructsMacro")
61+
62+
#bitwidthNumberedStructs("MyIntGlobal")
63+
64+
func testArbitraryAtGlobal() {
65+
_ = MyIntGlobal16()
66+
}

0 commit comments

Comments
 (0)