Skip to content

Commit 9c91d1b

Browse files
authored
[Macros] Fix lookup of macro-produced variables (#65939)
Calling `getInnermostDeclContext()->getParentSourceFile()` on a macro-produced decl does not seem to be a reliable way to obtain the macro expansion source file, because `PatternBindingDecl` is not a `DeclContext` and `getInnermostDeclContext()` falls back outside the macro expansion file. This patch switches to using `getSourceFileContainingLocation` when possible. Resolves rdar://109376568.
1 parent f2dcbb5 commit 9c91d1b

8 files changed

+57
-7
lines changed

lib/AST/Decl.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10341,9 +10341,12 @@ void MissingDecl::forEachMacroExpandedDecl(MacroExpandedDeclCallback callback) {
1034110341
auto *baseDecl = unexpandedMacro.baseDecl;
1034210342
if (!macroRef || !baseDecl)
1034310343
return;
10344+
auto *module = getModuleContext();
1034410345

1034510346
baseDecl->visitAuxiliaryDecls([&](Decl *auxiliaryDecl) {
10346-
auto *sf = auxiliaryDecl->getInnermostDeclContext()->getParentSourceFile();
10347+
SourceFile *sf = auxiliaryDecl->getLoc()
10348+
? module->getSourceFileContainingLocation(auxiliaryDecl->getLoc())
10349+
: auxiliaryDecl->getInnermostDeclContext()->getParentSourceFile();
1034710350
// We only visit auxiliary decls that are macro expansions associated with
1034810351
// this macro reference.
1034910352
if (auto *med = macroRef.dyn_cast<MacroExpansionDecl *>()) {

lib/AST/DeclContext.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1040,7 +1040,10 @@ void IterableDeclContext::addMemberSilently(Decl *member, Decl *hint,
10401040
return;
10411041

10421042
// Synthesized member macros can add new members in a macro expansion buffer.
1043-
auto *memberSourceFile = member->getInnermostDeclContext()->getParentSourceFile();
1043+
SourceFile *memberSourceFile = member->getLoc()
1044+
? member->getModuleContext()
1045+
->getSourceFileContainingLocation(member->getLoc())
1046+
: member->getInnermostDeclContext()->getParentSourceFile();
10441047
if (memberSourceFile->getFulfilledMacroRole() == MacroRole::Member ||
10451048
memberSourceFile->getFulfilledMacroRole() == MacroRole::Peer)
10461049
return;

test/Macros/Inputs/freestanding_macro_library.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,6 @@ public macro bitwidthNumberedStructs(_ baseName: String) = #externalMacro(module
1212

1313
@freestanding(expression)
1414
public macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "MacroDefinition", type: "StringifyMacro")
15+
16+
@freestanding(declaration, names: named(value))
17+
public macro varValue() = #externalMacro(module: "MacroDefinition", type: "VarValueMacro")

test/Macros/Inputs/macro_library.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,6 @@ public macro addCompletionHandler() = #externalMacro(module: "MacroDefinition",
3838

3939
@attached(peer, names: suffixed(Builder))
4040
public macro AddClassReferencingSelf() = #externalMacro(module: "MacroDefinition", type: "AddClassReferencingSelfMacro")
41+
42+
@attached(peer, names: named(value))
43+
public macro declareVarValuePeer() = #externalMacro(module: "MacroDefinition", type: "VarValueMacro")

test/Macros/Inputs/syntax_macro_definitions.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,3 +1413,24 @@ public struct MultiStatementClosure: ExpressionMacro {
14131413
"""
14141414
}
14151415
}
1416+
1417+
public struct VarValueMacro: DeclarationMacro, PeerMacro {
1418+
public static func expansion(
1419+
of macro: some FreestandingMacroExpansionSyntax,
1420+
in context: some MacroExpansionContext
1421+
) -> [DeclSyntax] {
1422+
return [
1423+
"var value: Int { 1 }"
1424+
]
1425+
}
1426+
1427+
public static func expansion(
1428+
of node: AttributeSyntax,
1429+
providingPeersOf declaration: some DeclSyntaxProtocol,
1430+
in context: some MacroExpansionContext
1431+
) throws -> [DeclSyntax] {
1432+
return [
1433+
"var value: Int { 1 }"
1434+
]
1435+
}
1436+
}

test/Macros/macro_attribute_expansiondecl.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,9 @@ public struct FuncFromClosureMacro: DeclarationMacro {
8686
@available(SwiftStdlib 9999, *)
8787
#globalDecls
8888

89-
func testGlobal() { // expected-note {{add @available attribute to enclosing global function}}
89+
func testGlobal() { // expected-note 2 {{add @available attribute to enclosing global function}}
9090
globalFunc() // expected-error {{'globalFunc()' is only available in macOS 9999 or newer}} expected-note {{add 'if #available' version check}}
91-
// FIXME(109376568): Global variable introduced by macro expansion not found
92-
_ = globalVar // expected-error {{cannot find 'globalVar' in scope}}
91+
_ = globalVar // expected-error {{'globalVar' is only available in macOS 9999 or newer}} expected-note {{add 'if #available' version check}}
9392
}
9493

9594
struct S {

test/Macros/macro_expand_peers.swift

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ import macro_library
3131
macro addCompletionHandler() = #externalMacro(module: "MacroDefinition", type: "AddCompletionHandler")
3232
@attached(peer, names: suffixed(Builder))
3333
macro AddClassReferencingSelf() = #externalMacro(module: "MacroDefinition", type: "AddClassReferencingSelfMacro")
34+
@attached(peer, names: named(value))
35+
macro declareVarValuePeer() = #externalMacro(module: "MacroDefinition", type: "VarValueMacro")
3436
#endif
3537

3638
@attached(peer, names: arbitrary)
@@ -166,8 +168,6 @@ struct S2 {
166168
macro myPropertyWrapper() =
167169
#externalMacro(module: "MacroDefinition", type: "PropertyWrapperMacro")
168170

169-
struct Date { }
170-
171171
struct MyWrapperThingy<T> {
172172
var storage: T
173173

@@ -192,3 +192,14 @@ struct S3 {
192192
self._x = MyWrapperThingy(storage: x)
193193
}
194194
}
195+
196+
@declareVarValuePeer
197+
struct Date {
198+
@declareVarValuePeer
199+
func foo() {}
200+
}
201+
202+
func testVarPeer() {
203+
_ = value
204+
_ = Date().value
205+
}

test/Macros/top_level_freestanding.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ macro anonymousTypes(public: Bool = false, _: () -> String) = #externalMacro(mod
3232
macro freestandingWithClosure<T>(_ value: T, body: (T) -> T) = #externalMacro(module: "MacroDefinition", type: "EmptyDeclarationMacro")
3333
@freestanding(declaration, names: arbitrary) macro bitwidthNumberedStructs(_ baseName: String) = #externalMacro(module: "MacroDefinition", type: "DefineBitwidthNumberedStructsMacro")
3434
@freestanding(expression) macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "MacroDefinition", type: "StringifyMacro")
35+
@freestanding(declaration, names: named(value)) macro varValue() = #externalMacro(module: "MacroDefinition", type: "VarValueMacro")
3536
#endif
3637

3738
// Test unqualified lookup from within a macro expansion
@@ -79,3 +80,9 @@ func testArbitraryAtGlobal() {
7980

8081
// DIAG_BUFFERS: @__swiftmacro_9MacroUser33_{{.*}}9stringifyfMf1_{{.*}}warning: 'deprecated()' is deprecated
8182
// DIAG_BUFFERS: @__swiftmacro_9MacroUser33_{{.*}}9stringifyfMf2_{{.*}}warning: 'deprecated()' is deprecated
83+
84+
#varValue
85+
86+
func testGlobalVariable() {
87+
_ = value
88+
}

0 commit comments

Comments
 (0)