Skip to content

Commit 0473879

Browse files
authored
Merge pull request #64184 from DougGregor/macro-unique-name-lookup-type-reconstruction
[Macros] Ensure that name lookup can find uniquely-generated macro names
2 parents aea93fc + 6ab3bc2 commit 0473879

File tree

8 files changed

+111
-10
lines changed

8 files changed

+111
-10
lines changed

include/swift/AST/Decl.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8476,6 +8476,22 @@ class MacroDecl : public GenericContext, public ValueDecl {
84768476
return DeclName();
84778477
}
84788478

8479+
/// Returns a DeclName that acts as a stand-in for all unique names that
8480+
/// are manufactured by the macro expansion context's `makeUniqueName`.
8481+
static DeclName getUniqueNamePlaceholder(ASTContext &ctx);
8482+
8483+
/// Determine whether the given name is the unique-name placeholder
8484+
/// produced by `getUniqueNamePlaceholder`.
8485+
static bool isUniqueNamePlaceholder(DeclName name);
8486+
8487+
/// Determine whether the given name is one of the unique names manufactured
8488+
/// by the macro expansion context's `makeUniqueName`.
8489+
static bool isUniqueMacroName(StringRef name);
8490+
8491+
/// Determine whether the given name is one of the unique names manufactured
8492+
/// by the macro expansion context's `makeUniqueName`.
8493+
static bool isUniqueMacroName(DeclBaseName name);
8494+
84798495
/// Retrieve the definition of this macro.
84808496
MacroDefinition getDefinition() const;
84818497

lib/AST/Decl.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10073,6 +10073,39 @@ const MacroRoleAttr *MacroDecl::getMacroRoleAttr(MacroRole role) const {
1007310073
return nullptr;
1007410074
}
1007510075

10076+
DeclName MacroDecl::getUniqueNamePlaceholder(ASTContext &ctx) {
10077+
return ctx.getIdentifier("$");
10078+
}
10079+
10080+
bool MacroDecl::isUniqueNamePlaceholder(DeclName name) {
10081+
return name.getBaseName().userFacingName() == "$";
10082+
}
10083+
10084+
bool MacroDecl::isUniqueMacroName(StringRef name) {
10085+
// Unique macro names are mangled names, which always start with "$s".
10086+
if (!name.startswith("$s"))
10087+
return false;
10088+
10089+
// Unique macro names end with fMu<digits>_. Match that.
10090+
10091+
// Strip off the trailing _.
10092+
if (name.back() != '_')
10093+
return false;
10094+
name = name.drop_back();
10095+
10096+
// Strip off trailing digits. This is the discriminator.
10097+
while (isdigit(name.back()))
10098+
name = name.drop_back();
10099+
10100+
// Check for fMu.
10101+
return name.endswith("fMu");
10102+
}
10103+
10104+
bool MacroDecl::isUniqueMacroName(DeclBaseName name) {
10105+
return isUniqueMacroName(name.userFacingName());
10106+
}
10107+
10108+
1007610109
void MacroDecl::getIntroducedNames(MacroRole role, ValueDecl *attachedTo,
1007710110
SmallVectorImpl<DeclName> &names) const {
1007810111
ASTContext &ctx = getASTContext();
@@ -10134,6 +10167,21 @@ void MacroDecl::getIntroducedNames(MacroRole role, ValueDecl *attachedTo,
1013410167
break;
1013510168
}
1013610169
}
10170+
10171+
// Add the unique name, if the macro can introduce declarations anywhere.
10172+
switch (role) {
10173+
case MacroRole::Expression:
10174+
case MacroRole::Declaration:
10175+
case MacroRole::Member:
10176+
case MacroRole::Peer:
10177+
names.push_back(MacroDecl::getUniqueNamePlaceholder(getASTContext()));
10178+
break;
10179+
10180+
case MacroRole::Accessor:
10181+
case MacroRole::Conformance:
10182+
case MacroRole::MemberAttribute:
10183+
break;
10184+
}
1013710185
}
1013810186

1013910187
MacroDefinition MacroDecl::getDefinition() const {

lib/AST/Module.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ class swift::SourceLookupCache {
160160
ValueDeclMap TopLevelValues;
161161
ValueDeclMap ClassMembers;
162162
bool MemberCachePopulated = false;
163+
DeclName UniqueMacroNamePlaceholder;
163164

164165
template<typename T>
165166
using OperatorMap = llvm::DenseMap<Identifier, TinyPtrVector<T *>>;
@@ -179,6 +180,8 @@ class swift::SourceLookupCache {
179180
SmallVector<Decl *, 4> MayHaveAuxiliaryDecls;
180181
void populateAuxiliaryDeclCache();
181182

183+
SourceLookupCache(ASTContext &ctx);
184+
182185
public:
183186
SourceLookupCache(const SourceFile &SF);
184187
SourceLookupCache(const ModuleDecl &Mod);
@@ -392,15 +395,22 @@ void SourceLookupCache::populateAuxiliaryDeclCache() {
392395
MayHaveAuxiliaryDecls.clear();
393396
}
394397

398+
SourceLookupCache::SourceLookupCache(ASTContext &ctx)
399+
: UniqueMacroNamePlaceholder(MacroDecl::getUniqueNamePlaceholder(ctx)) { }
400+
395401
/// Populate our cache on the first name lookup.
396-
SourceLookupCache::SourceLookupCache(const SourceFile &SF) {
402+
SourceLookupCache::SourceLookupCache(const SourceFile &SF)
403+
: SourceLookupCache(SF.getASTContext())
404+
{
397405
FrontendStatsTracer tracer(SF.getASTContext().Stats,
398406
"source-file-populate-cache");
399407
addToUnqualifiedLookupCache(SF.getTopLevelDecls(), false);
400408
addToUnqualifiedLookupCache(SF.getHoistedDecls(), false);
401409
}
402410

403-
SourceLookupCache::SourceLookupCache(const ModuleDecl &M) {
411+
SourceLookupCache::SourceLookupCache(const ModuleDecl &M)
412+
: SourceLookupCache(M.getASTContext())
413+
{
404414
FrontendStatsTracer tracer(M.getASTContext().Stats,
405415
"module-populate-cache");
406416
for (const FileUnit *file : M.getFiles()) {
@@ -428,7 +438,10 @@ void SourceLookupCache::lookupValue(DeclName Name, NLKind LookupKind,
428438
// FIXME: We need to not consider auxiliary decls if we're doing lookup
429439
// from inside a macro argument at module scope.
430440
populateAuxiliaryDeclCache();
431-
auto auxDecls = TopLevelAuxiliaryDecls.find(Name);
441+
DeclName keyName = MacroDecl::isUniqueMacroName(Name.getBaseName())
442+
? UniqueMacroNamePlaceholder
443+
: Name;
444+
auto auxDecls = TopLevelAuxiliaryDecls.find(keyName);
432445
if (auxDecls == TopLevelAuxiliaryDecls.end())
433446
return;
434447

lib/AST/NameLookup.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,6 +1255,7 @@ class swift::MemberLookupTable : public ASTAllocated<swift::MemberLookupTable> {
12551255
}
12561256

12571257
bool isLazilyCompleteForMacroExpansion(DeclName name) const {
1258+
assert(!MacroDecl::isUniqueMacroName(name.getBaseName()));
12581259
// If we've already expanded macros for a simple name, we must have expanded
12591260
// all macros that produce names with the same base identifier.
12601261
bool isBaseNameComplete = name.isCompoundName() &&
@@ -1264,6 +1265,7 @@ class swift::MemberLookupTable : public ASTAllocated<swift::MemberLookupTable> {
12641265
}
12651266

12661267
void markLazilyCompleteForMacroExpansion(DeclName name) {
1268+
assert(!MacroDecl::isUniqueMacroName(name.getBaseName()));
12671269
LazilyCompleteNamesForMacroExpansion.insert(name);
12681270
}
12691271

@@ -1521,6 +1523,17 @@ populateLookupTableEntryFromExtensions(ASTContext &ctx,
15211523
}
15221524
}
15231525

1526+
/// Adjust the given name to make it a proper key for the lazy macro expansion
1527+
/// cache, which maps all uniquely-generated names down to a single placeholder
1528+
/// key.
1529+
static DeclName adjustLazyMacroExpansionNameKey(
1530+
ASTContext &ctx, DeclName name) {
1531+
if (MacroDecl::isUniqueMacroName(name.getBaseName()))
1532+
return MacroDecl::getUniqueNamePlaceholder(ctx);
1533+
1534+
return name;
1535+
}
1536+
15241537
static void
15251538
populateLookupTableEntryFromMacroExpansions(ASTContext &ctx,
15261539
MemberLookupTable &table,
@@ -1756,9 +1769,11 @@ DirectLookupRequest::evaluate(Evaluator &evaluator,
17561769
Table.markLazilyComplete(baseName);
17571770
}
17581771

1759-
if (!Table.isLazilyCompleteForMacroExpansion(name)) {
1760-
populateLookupTableEntryFromMacroExpansions(ctx, Table, name, decl);
1761-
Table.markLazilyCompleteForMacroExpansion(name);
1772+
DeclName macroExpansionKey = adjustLazyMacroExpansionNameKey(ctx, name);
1773+
if (!Table.isLazilyCompleteForMacroExpansion(macroExpansionKey)) {
1774+
populateLookupTableEntryFromMacroExpansions(
1775+
ctx, Table, macroExpansionKey, decl);
1776+
Table.markLazilyCompleteForMacroExpansion(macroExpansionKey);
17621777
}
17631778

17641779
// Look for a declaration with this name.

lib/Serialization/Serialization.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6137,7 +6137,8 @@ void Serializer::writeAST(ModuleOrSourceFile DC) {
61376137

61386138
for (auto D : fileDecls) {
61396139
if (isa<ImportDecl>(D) || isa<IfConfigDecl>(D) ||
6140-
isa<PoundDiagnosticDecl>(D) || isa<TopLevelCodeDecl>(D)) {
6140+
isa<PoundDiagnosticDecl>(D) || isa<TopLevelCodeDecl>(D) ||
6141+
isa<MacroExpansionDecl>(D)) {
61416142
continue;
61426143
}
61436144

test/Macros/Inputs/syntax_macro_definitions.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,8 @@ public struct AddMembers: MemberMacro {
456456
providingMembersOf decl: some DeclGroupSyntax,
457457
in context: some MacroExpansionContext
458458
) throws -> [DeclSyntax] {
459+
let uniqueClassName = context.createUniqueName("uniqueClass")
460+
459461
let storageStruct: DeclSyntax =
460462
"""
461463
struct Storage {}
@@ -481,7 +483,12 @@ public struct AddMembers: MemberMacro {
481483

482484
let initDecl: DeclSyntax =
483485
"""
484-
init() {}
486+
init() { _ = \(uniqueClassName)() }
487+
"""
488+
489+
let classDecl: DeclSyntax =
490+
"""
491+
class \(uniqueClassName) { }
485492
"""
486493

487494
return [
@@ -490,6 +497,7 @@ public struct AddMembers: MemberMacro {
490497
instanceMethod,
491498
staticMethod,
492499
initDecl,
500+
classDecl,
493501
]
494502
}
495503
}

test/Macros/macro_expand_synthesized_members.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// RUN: %target-build-swift -swift-version 5 -I %swift-host-lib-dir -L %swift-host-lib-dir -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath
33
// RUNx: %target-swift-frontend -dump-ast -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir %s -module-name MacroUser 2>&1 | %FileCheck --check-prefix CHECK-AST %s
44
// RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir -module-name MacroUser -DTEST_DIAGNOSTICS -swift-version 5
5-
// RUN: %target-build-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir -L %swift-host-lib-dir %s -o %t/main -module-name MacroUser -swift-version 5
5+
// RUN: %target-build-swift -g -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir -L %swift-host-lib-dir %s -o %t/main -module-name MacroUser -swift-version 5
66
// RUN: %target-run %t/main | %FileCheck %s
77
// REQUIRES: executable_test
88

test/Macros/top_level_freestanding.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// RUN: %target-build-swift -swift-version 5 -parse-as-library -enable-experimental-feature FreestandingMacros -I %swift-host-lib-dir -L %swift-host-lib-dir -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath
33
// RUNx: %target-swift-frontend -enable-experimental-feature FreestandingMacros -parse-as-library -emit-sil -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir %s -module-name MacroUser 2>&1 | %FileCheck --check-prefix CHECK-SIL %s
44
// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-experimental-feature FreestandingMacros -parse-as-library -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir -module-name MacroUser -DTEST_DIAGNOSTICS -swift-version 5
5-
// RUN: %target-build-swift -swift-version 5 -enable-experimental-feature FreestandingMacros -parse-as-library -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir -L %swift-host-lib-dir %s -o %t/main -module-name MacroUser -swift-version 5
5+
// RUN: %target-build-swift -g -swift-version 5 -enable-experimental-feature FreestandingMacros -parse-as-library -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir -L %swift-host-lib-dir %s -o %t/main -module-name MacroUser -swift-version 5
66
// RUN: %target-run %t/main | %FileCheck %s
77
// REQUIRES: executable_test
88

0 commit comments

Comments
 (0)