[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.
This commit is contained in:
Doug Gregor
2023-04-05 23:38:55 -07:00
parent f96240d2d8
commit bbe4ff1e56
5 changed files with 62 additions and 7 deletions

View File

@@ -174,6 +174,10 @@ class swift::SourceLookupCache {
using AuxiliaryDeclMap = llvm::DenseMap<DeclName, TinyPtrVector<MissingDecl *>>;
AuxiliaryDeclMap TopLevelAuxiliaryDecls;
/// Top-level macros that produce arbitrary names.
SmallVector<MissingDecl *, 4> TopLevelArbitraryMacros;
SmallVector<Decl *, 4> MayHaveAuxiliaryDecls;
void populateAuxiliaryDeclCache();
@@ -352,26 +356,46 @@ void SourceLookupCache::populateAuxiliaryDeclCache() {
for (auto attrConst : decl->getAttrs().getAttributes<CustomAttr>()) {
auto *attr = const_cast<CustomAttr *>(attrConst);
UnresolvedMacroReference macroRef(attr);
bool introducesArbitraryNames = false;
namelookup::forEachPotentialResolvedMacro(
decl->getDeclContext()->getModuleScopeContext(),
macroRef.getMacroName(), MacroRole::Peer,
[&](MacroDecl *macro, const MacroRoleAttr *roleAttr) {
// First check for arbitrary names.
if (roleAttr->hasNameKind(MacroIntroducedDeclNameKind::Arbitrary)) {
introducesArbitraryNames = true;
}
macro->getIntroducedNames(MacroRole::Peer,
dyn_cast<ValueDecl>(decl),
introducedNames[attr]);
});
// Record this macro where appropriate.
if (introducesArbitraryNames)
TopLevelArbitraryMacros.push_back(MissingDecl::forUnexpandedMacro(attr, decl));
}
if (auto *med = dyn_cast<MacroExpansionDecl>(decl)) {
UnresolvedMacroReference macroRef(med);
bool introducesArbitraryNames = false;
namelookup::forEachPotentialResolvedMacro(
decl->getDeclContext()->getModuleScopeContext(),
macroRef.getMacroName(), MacroRole::Declaration,
[&](MacroDecl *macro, const MacroRoleAttr *roleAttr) {
// First check for arbitrary names.
if (roleAttr->hasNameKind(MacroIntroducedDeclNameKind::Arbitrary)) {
introducesArbitraryNames = true;
}
macro->getIntroducedNames(MacroRole::Declaration,
/*attachedTo*/ nullptr,
introducedNames[med]);
});
// Record this macro where appropriate.
if (introducesArbitraryNames)
TopLevelArbitraryMacros.push_back(MissingDecl::forUnexpandedMacro(med, decl));
}
// Add macro-introduced names to the top-level auxiliary decl cache as
@@ -440,14 +464,29 @@ void SourceLookupCache::lookupValue(DeclName Name, NLKind LookupKind,
? UniqueMacroNamePlaceholder
: Name;
auto auxDecls = TopLevelAuxiliaryDecls.find(keyName);
if (auxDecls == TopLevelAuxiliaryDecls.end())
// Check macro expansions that could produce this name.
SmallVector<MissingDecl *, 4> unexpandedDecls;
if (auxDecls != TopLevelAuxiliaryDecls.end()) {
unexpandedDecls.insert(
unexpandedDecls.end(), auxDecls->second.begin(), auxDecls->second.end());
}
// Check macro expansions that can produce arbitrary names.
unexpandedDecls.insert(
unexpandedDecls.end(),
TopLevelArbitraryMacros.begin(), TopLevelArbitraryMacros.end());
if (unexpandedDecls.empty())
return;
for (auto *unexpandedDecl : auxDecls->second) {
// Add expanded peers and freestanding declarations to the result.
// Add matching expanded peers and freestanding declarations to the results.
SmallPtrSet<ValueDecl *, 4> macroExpandedDecls;
for (auto *unexpandedDecl : unexpandedDecls) {
unexpandedDecl->forEachMacroExpandedDecl(
[&](ValueDecl *decl) {
if (decl->getName().matchesRef(Name)) {
if (macroExpandedDecls.insert(decl).second)
Result.push_back(decl);
}
});

View File

@@ -615,9 +615,11 @@ static Type lookupDefaultLiteralType(const DeclContext *dc,
StringRef name) {
auto &ctx = dc->getASTContext();
DeclNameRef nameRef(ctx.getIdentifier(name));
auto lookup = TypeChecker::lookupUnqualified(dc->getModuleScopeContext(),
auto lookup = TypeChecker::lookupUnqualified(
dc->getModuleScopeContext(),
nameRef, SourceLoc(),
defaultUnqualifiedLookupOptions);
defaultUnqualifiedLookupOptions | NameLookupFlags::ExcludeMacroExpansions
);
TypeDecl *TD = lookup.getSingleTypeResult();
if (!TD)
return Type();

View File

@@ -217,6 +217,8 @@ convertToUnqualifiedLookupOptions(NameLookupOptions options) {
newOptions |= UnqualifiedLookupFlags::IncludeOuterResults;
if (options.contains(NameLookupFlags::IncludeUsableFromInline))
newOptions |= UnqualifiedLookupFlags::IncludeUsableFromInline;
if (options.contains(NameLookupFlags::ExcludeMacroExpansions))
newOptions |= UnqualifiedLookupFlags::ExcludeMacroExpansions;
return newOptions;
}

View File

@@ -160,6 +160,8 @@ enum class NameLookupFlags {
IncludeOuterResults = 1 << 1,
// Whether to include results that are marked @inlinable or @usableFromInline.
IncludeUsableFromInline = 1 << 2,
/// This lookup should exclude any names introduced by macro expansions.
ExcludeMacroExpansions = 1 << 3,
};
/// A set of options that control name lookup.

View File

@@ -54,3 +54,13 @@ struct HasInnerClosure {
#freestandingWithClosure(0) { x in x }
#freestandingWithClosure(1) { x in x }
}
// Arbitrary names at global scope
@freestanding(declaration, names: arbitrary) macro bitwidthNumberedStructs(_ baseName: String) = #externalMacro(module: "MacroDefinition", type: "DefineBitwidthNumberedStructsMacro")
#bitwidthNumberedStructs("MyIntGlobal")
func testArbitraryAtGlobal() {
_ = MyIntGlobal16()
}