mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Macros] Top-level freestanding macros (#63553)
Allow freestanding macros to be used at top-level. - Parse top-level `#…` as `MacroExpansionDecl` when we are not in scripting mode. - Add macro expansion decls to the source lookup cache with name-driven lazy expansion. Not supporting arbitrary name yet. - Experimental support for script mode and brace-level declaration macro expansions: When type-checking a `MacroExpansionExpr`, assign it a substitute `MacroExpansionDecl` if the macro reference resolves to a declaration macro. This doesn’t work quite fully yet and will be enabled in a future fix.
This commit is contained in:
@@ -176,7 +176,7 @@ class swift::SourceLookupCache {
|
||||
|
||||
using AuxiliaryDeclMap = llvm::DenseMap<DeclName, TinyPtrVector<MissingDecl *>>;
|
||||
AuxiliaryDeclMap TopLevelAuxiliaryDecls;
|
||||
SmallVector<ValueDecl *, 4> MayHaveAuxiliaryDecls;
|
||||
SmallVector<Decl *, 4> MayHaveAuxiliaryDecls;
|
||||
void populateAuxiliaryDeclCache();
|
||||
|
||||
public:
|
||||
@@ -267,11 +267,14 @@ void SourceLookupCache::addToUnqualifiedLookupCache(Range decls,
|
||||
if (auto *OD = dyn_cast<OperatorDecl>(D))
|
||||
Operators[OD->getName()].push_back(OD);
|
||||
|
||||
if (auto *PG = dyn_cast<PrecedenceGroupDecl>(D))
|
||||
else if (auto *PG = dyn_cast<PrecedenceGroupDecl>(D))
|
||||
PrecedenceGroups[PG->getName()].push_back(PG);
|
||||
|
||||
if (auto *macro = dyn_cast<MacroDecl>(D))
|
||||
else if (auto *macro = dyn_cast<MacroDecl>(D))
|
||||
MacroDecls[macro->getBaseIdentifier()].push_back(macro);
|
||||
|
||||
else if (auto *MED = dyn_cast<MacroExpansionDecl>(D))
|
||||
MayHaveAuxiliaryDecls.push_back(MED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,9 +329,11 @@ void SourceLookupCache::addToMemberCache(Range decls) {
|
||||
}
|
||||
|
||||
void SourceLookupCache::populateAuxiliaryDeclCache() {
|
||||
using MacroRef = llvm::PointerUnion<MacroExpansionDecl *, CustomAttr *>;
|
||||
for (auto *decl : MayHaveAuxiliaryDecls) {
|
||||
// Gather macro-introduced peer names.
|
||||
llvm::SmallDenseMap<CustomAttr *, llvm::SmallVector<DeclName, 2>> introducedNames;
|
||||
llvm::SmallDenseMap<MacroRef, llvm::SmallVector<DeclName, 2>>
|
||||
introducedNames;
|
||||
|
||||
// This code deliberately avoids `forEachAttachedMacro`, because it
|
||||
// will perform overload resolution and possibly invoke unqualified
|
||||
@@ -353,17 +358,32 @@ void SourceLookupCache::populateAuxiliaryDeclCache() {
|
||||
|
||||
for (const auto *macro : found->second) {
|
||||
macro->getIntroducedNames(MacroRole::Peer,
|
||||
decl, introducedNames[attr]);
|
||||
dyn_cast<ValueDecl>(decl),
|
||||
introducedNames[attr]);
|
||||
}
|
||||
}
|
||||
|
||||
if (auto *med = dyn_cast<MacroExpansionDecl>(decl)) {
|
||||
UnresolvedMacroReference macroRef(med);
|
||||
auto macroName = macroRef.getMacroName().getBaseIdentifier();
|
||||
|
||||
auto found = MacroDecls.find(macroName);
|
||||
if (found == MacroDecls.end())
|
||||
continue;
|
||||
|
||||
for (const auto *macro : found->second) {
|
||||
macro->getIntroducedNames(MacroRole::Declaration,
|
||||
/*attachedTo*/ nullptr,
|
||||
introducedNames[med]);
|
||||
}
|
||||
}
|
||||
|
||||
// Add macro-introduced names to the top-level auxiliary decl cache as
|
||||
// unexpanded peer decls represented by a MissingDecl.
|
||||
// unexpanded decls represented by a MissingDecl.
|
||||
for (auto macroNames : introducedNames) {
|
||||
auto *macroAttr = macroNames.getFirst();
|
||||
auto macroRef = macroNames.getFirst();
|
||||
for (auto name : macroNames.getSecond()) {
|
||||
auto *placeholder =
|
||||
MissingDecl::forUnexpandedPeer(macroAttr, decl);
|
||||
auto *placeholder = MissingDecl::forUnexpandedMacro(macroRef, decl);
|
||||
name.addToLookupTable(TopLevelAuxiliaryDecls, placeholder);
|
||||
}
|
||||
}
|
||||
@@ -397,11 +417,11 @@ SourceLookupCache::SourceLookupCache(const ModuleDecl &M) {
|
||||
void SourceLookupCache::lookupValue(DeclName Name, NLKind LookupKind,
|
||||
SmallVectorImpl<ValueDecl*> &Result) {
|
||||
auto I = TopLevelValues.find(Name);
|
||||
if (I == TopLevelValues.end()) return;
|
||||
|
||||
Result.reserve(I->second.size());
|
||||
for (ValueDecl *Elt : I->second)
|
||||
Result.push_back(Elt);
|
||||
if (I != TopLevelValues.end()) {
|
||||
Result.reserve(I->second.size());
|
||||
for (ValueDecl *Elt : I->second)
|
||||
Result.push_back(Elt);
|
||||
}
|
||||
|
||||
// Add top-level auxiliary decls to the result.
|
||||
//
|
||||
@@ -414,9 +434,9 @@ void SourceLookupCache::lookupValue(DeclName Name, NLKind LookupKind,
|
||||
|
||||
for (auto *unexpandedDecl : auxDecls->second) {
|
||||
// Add expanded peers to the result.
|
||||
unexpandedDecl->forEachExpandedPeer(
|
||||
[&](ValueDecl *expandedPeer) {
|
||||
Result.push_back(expandedPeer);
|
||||
unexpandedDecl->forEachMacroExpandedDecl(
|
||||
[&](ValueDecl *decl) {
|
||||
Result.push_back(decl);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -3891,6 +3911,19 @@ void FileUnit::getTopLevelDeclsWhereAttributesMatch(
|
||||
Results.erase(newEnd, Results.end());
|
||||
}
|
||||
|
||||
void FileUnit::getTopLevelDeclsWithAuxiliaryDecls(
|
||||
SmallVectorImpl<Decl*> &results) const {
|
||||
SmallVector<Decl *, 32> nonExpandedDecls;
|
||||
nonExpandedDecls.reserve(results.capacity());
|
||||
getTopLevelDecls(nonExpandedDecls);
|
||||
for (auto *decl : nonExpandedDecls) {
|
||||
decl->visitAuxiliaryDecls([&](Decl *auxDecl) {
|
||||
results.push_back(auxDecl);
|
||||
});
|
||||
results.push_back(decl);
|
||||
}
|
||||
}
|
||||
|
||||
void FileUnit::dumpDisplayDecls() const {
|
||||
SmallVector<Decl *, 32> Decls;
|
||||
getDisplayDecls(Decls);
|
||||
|
||||
Reference in New Issue
Block a user