Skip to content

Commit b129d7e

Browse files
committed
[Macros] Teach name lookup in macro expansions to look in expansion context
Teach ASTScope how to reason about macro expansions. When we create an ASTScope for a source file that represents a macro expansion, its parent scope node is the macro expansion itself. When performing unqualified lookup (of any form), find the starting source file based on the location, not on the source file provided---this ensures that we start lookups within the macro expansion (for example). The effect of this is to enable macro expansions to work in nested contexts, where they refer to names in the scope in which the macro is expanded. This is decidedly unhiegenic, but it fits with our syntactic model.
1 parent 0f9a706 commit b129d7e

File tree

5 files changed

+30
-8
lines changed

5 files changed

+30
-8
lines changed

include/swift/AST/ASTScope.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ class ASTScopeImpl : public ASTAllocated<ASTScopeImpl> {
128128
friend class GenericTypeOrExtensionWherePortion;
129129
friend class IterableTypeBodyPortion;
130130
friend class ScopeCreator;
131+
friend class ASTSourceFileScope;
131132

132133
#pragma mark - tree state
133134
protected:

lib/AST/ASTScope.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ using namespace ast_scope;
4141
void ASTScope::unqualifiedLookup(
4242
SourceFile *SF, SourceLoc loc,
4343
namelookup::AbstractASTScopeDeclConsumer &consumer) {
44+
if (loc.isValid()) {
45+
SF = SF->getParentModule()->getSourceFileContainingLocation(loc);
46+
}
47+
4448
if (auto *s = SF->getASTContext().Stats)
4549
++s->getFrontendCounters().NumASTScopeLookups;
4650
ASTScopeImpl::unqualifiedLookup(SF, loc, consumer);

lib/AST/ASTScopeCreation.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,14 @@ void ASTSourceFileScope::expandFunctionBody(AbstractFunctionDecl *AFD) {
246246

247247
ASTSourceFileScope::ASTSourceFileScope(SourceFile *SF,
248248
ScopeCreator *scopeCreator)
249-
: SF(SF), scopeCreator(scopeCreator) {}
249+
: SF(SF), scopeCreator(scopeCreator) {
250+
if (auto enclosingSF = SF->getEnclosingSourceFile()) {
251+
SourceLoc parentLoc = SF->macroExpansion.getStartLoc();
252+
if (auto parentScope = findStartingScopeForLookup(enclosingSF, parentLoc)) {
253+
parentAndWasExpanded.setPointer(const_cast<ASTScopeImpl *>(parentScope));
254+
}
255+
}
256+
}
250257

251258
#pragma mark NodeAdder
252259

lib/AST/ASTVerifier.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3690,6 +3690,8 @@ class Verifier : public ASTWalker {
36903690
if (Parent.isNull())
36913691
return;
36923692

3693+
// An alternative enclosing scope, used for macro expansions.
3694+
SourceRange AltEnclosing;
36933695
if (Parent.getAsModule()) {
36943696
return;
36953697
} else if (Decl *D = Parent.getAsDecl()) {
@@ -3720,15 +3722,22 @@ class Verifier : public ASTWalker {
37203722

37213723
if (E->isImplicit())
37223724
return;
3723-
3725+
3726+
if (auto expansion = dyn_cast<MacroExpansionExpr>(E)) {
3727+
if (auto rewritten = expansion->getRewritten())
3728+
AltEnclosing = rewritten->getSourceRange();
3729+
}
3730+
37243731
Enclosing = E->getSourceRange();
37253732
} else if (TypeRepr *TyR = Parent.getAsTypeRepr()) {
37263733
Enclosing = TyR->getSourceRange();
37273734
} else {
37283735
llvm_unreachable("impossible parent node");
37293736
}
37303737

3731-
if (!Ctx.SourceMgr.rangeContains(Enclosing, Current)) {
3738+
if (!Ctx.SourceMgr.rangeContains(Enclosing, Current) &&
3739+
!(AltEnclosing.isValid() &&
3740+
Ctx.SourceMgr.rangeContains(AltEnclosing, Current))) {
37323741
Out << "child source range not contained within its parent: ";
37333742
printEntity();
37343743
Out << "\n parent range: ";

test/Macros/macros.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
// REQUIRES: OS=macosx
33
// REQUIRES: asserts
44

5-
let a = 1, b = 1
6-
let s = #stringify(a + b)
7-
// CHECK: macro_expansion_expr type='(Int, String)'{{.*}}name=stringify
8-
// CHECK-NEXT: argument_list
9-
// CHECK: tuple_expr type='(Int, String)' location=Macro expansion of #stringify
5+
func test(a: Int, b: Int) {
6+
let s = #stringify(a + b)
107

8+
// CHECK: macro_expansion_expr type='(Int, String)'{{.*}}name=stringify
9+
// CHECK-NEXT: argument_list
10+
// CHECK: tuple_expr type='(Int, String)' location=Macro expansion of #stringify
11+
}

0 commit comments

Comments
 (0)