Skip to content

Commit dfa3ed9

Browse files
committed
Teach DeclContext::getParentSourceFile() to return the innermost source file
With macro expansions, and really any code generation that produces proper source locations, the parent source file of a declaration context will be a generated source file rather than the source file near the top of the declaration-context stack. Adjust the implementation of `getParentSourceFile()` to return that innermost source file by doing location-based lookup.
1 parent 514a052 commit dfa3ed9

File tree

4 files changed

+61
-2
lines changed

4 files changed

+61
-2
lines changed

lib/AST/DeclContext.cpp

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,9 +283,44 @@ ModuleDecl *DeclContext::getParentModule() const {
283283

284284
SourceFile *DeclContext::getParentSourceFile() const {
285285
const DeclContext *DC = this;
286-
while (!DC->isModuleScopeContext())
286+
SourceLoc loc;
287+
while (!DC->isModuleScopeContext()) {
288+
// If we don't have a source location yet, try to grab one from this
289+
// context.
290+
if (loc.isInvalid()) {
291+
switch (DC->getContextKind()) {
292+
case DeclContextKind::AbstractClosureExpr:
293+
loc = cast<AbstractClosureExpr>(DC)->getLoc();
294+
break;
295+
296+
case DeclContextKind::AbstractFunctionDecl:
297+
case DeclContextKind::EnumElementDecl:
298+
case DeclContextKind::ExtensionDecl:
299+
case DeclContextKind::GenericTypeDecl:
300+
case DeclContextKind::MacroDecl:
301+
case DeclContextKind::SubscriptDecl:
302+
case DeclContextKind::TopLevelCodeDecl:
303+
loc = DC->getAsDecl()->getLoc(/*SerializedOK=*/false);
304+
break;
305+
306+
case DeclContextKind::Initializer:
307+
case DeclContextKind::FileUnit:
308+
case DeclContextKind::Module:
309+
case DeclContextKind::SerializedLocal:
310+
break;
311+
}
312+
}
313+
287314
DC = DC->getParent();
288-
return const_cast<SourceFile *>(dyn_cast<SourceFile>(DC));
315+
}
316+
317+
auto fallbackSF = const_cast<SourceFile *>(dyn_cast<SourceFile>(DC));
318+
if (auto module = DC->getParentModule()) {
319+
if (auto sf = module->getSourceFileContainingLocation(loc))
320+
return sf;
321+
}
322+
323+
return fallbackSF;
289324
}
290325

291326
DeclContext *DeclContext::getModuleScopeContext() const {

lib/AST/Expr.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2029,15 +2029,19 @@ swift::_getRef__AbstractClosureExpr_getActorIsolation() {
20292029

20302030
#define FORWARD_SOURCE_LOCS_TO(CLASS, NODE) \
20312031
SourceRange CLASS::getSourceRange() const { \
2032+
if (!NODE) { return SourceRange(); } \
20322033
return (NODE)->getSourceRange(); \
20332034
} \
20342035
SourceLoc CLASS::getStartLoc() const { \
2036+
if (!NODE) { return SourceLoc(); } \
20352037
return (NODE)->getStartLoc(); \
20362038
} \
20372039
SourceLoc CLASS::getEndLoc() const { \
2040+
if (!NODE) { return SourceLoc(); } \
20382041
return (NODE)->getEndLoc(); \
20392042
} \
20402043
SourceLoc CLASS::getLoc() const { \
2044+
if (!NODE) { return SourceLoc(); } \
20412045
return (NODE)->getStartLoc(); \
20422046
}
20432047

test/Macros/Inputs/syntax_macro_definitions.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,16 @@ public class RecursiveMacro: ExpressionMacro {
167167
return "()"
168168
}
169169
}
170+
171+
public class NestedDeclInExprMacro: ExpressionMacro {
172+
public static func expansion(
173+
of macro: MacroExpansionExprSyntax, in context: inout MacroExpansionContext
174+
) -> ExprSyntax {
175+
return """
176+
{ () -> Void in
177+
struct Foo { }
178+
return ()
179+
}
180+
"""
181+
}
182+
}

test/Macros/macro_expand.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,10 @@ func testAddBlocker(a: Int, b: Int, c: Int, oa: OnlyAdds) {
9292
#recurse(true) // expected-note{{in expansion of macro 'recurse' here}}
9393
#endif
9494
}
95+
96+
// Make sure we don't crash with declarations produced by expansions.
97+
@expression macro nestedDeclInExpr: () -> Void = #externalMacro(module: "MacroDefinition", type: "NestedDeclInExprMacro")
98+
99+
func testNestedDeclInExpr() {
100+
let _: () -> Void = #nestedDeclInExpr
101+
}

0 commit comments

Comments
 (0)