Skip to content

Commit 0caa453

Browse files
committed
[Macros] Teach SILGen to visit declartions produced by freestanding macros
Fixes a crash where local variables introduced by a freestanding declaration macro would not get SIL emitted for them, rdar://109721114.
1 parent 4325c0a commit 0caa453

File tree

8 files changed

+48
-16
lines changed

8 files changed

+48
-16
lines changed

include/swift/AST/Decl.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8605,8 +8605,9 @@ class MacroExpansionDecl : public Decl, public FreestandingMacroExpansion {
86058605
return getExpansionInfo()->getSourceRange();
86068606
}
86078607
SourceLoc getLocFromSource() const { return getExpansionInfo()->SigilLoc; }
8608-
using ExprOrStmtExpansionCallback = llvm::function_ref<void(ASTNode)>;
8609-
void forEachExpandedExprOrStmt(ExprOrStmtExpansionCallback) const;
8608+
8609+
/// Enumerate the nodes produced by expanding this macro expansion.
8610+
void forEachExpandedNode(llvm::function_ref<void(ASTNode)> callback) const;
86108611

86118612
/// Returns a discriminator which determines this macro expansion's index
86128613
/// in the sequence of macro expansions within the current function.

lib/AST/ASTWalker.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -458,19 +458,18 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
458458
// Visit auxiliary decls, which may be decls from macro expansions.
459459
bool alreadyFailed = false;
460460
if (shouldWalkExpansion) {
461-
MED->visitAuxiliaryDecls([&](Decl *decl) {
462-
if (alreadyFailed) return;
463-
if (!isa<VarDecl>(decl))
464-
alreadyFailed = inherited::visit(decl);
465-
});
466-
MED->forEachExpandedExprOrStmt([&](ASTNode expandedNode) {
461+
MED->forEachExpandedNode([&](ASTNode expandedNode) {
467462
if (alreadyFailed) return;
468463
if (auto *expr = expandedNode.dyn_cast<Expr *>()) {
469464
if (!doIt(expr))
470465
alreadyFailed = true;
471466
} else if (auto *stmt = expandedNode.dyn_cast<Stmt *>()) {
472467
if (!doIt(stmt))
473468
alreadyFailed = true;
469+
} else {
470+
auto decl = expandedNode.get<Decl *>();
471+
if (!isa<VarDecl>(decl))
472+
alreadyFailed = inherited::visit(decl);
474473
}
475474
});
476475
}

lib/AST/Decl.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10637,8 +10637,9 @@ unsigned MacroExpansionDecl::getDiscriminator() const {
1063710637
return getRawDiscriminator();
1063810638
}
1063910639

10640-
void MacroExpansionDecl::forEachExpandedExprOrStmt(
10641-
ExprOrStmtExpansionCallback callback) const {
10640+
void MacroExpansionDecl::forEachExpandedNode(
10641+
llvm::function_ref<void(ASTNode)> callback
10642+
) const {
1064210643
auto mutableThis = const_cast<MacroExpansionDecl *>(this);
1064310644
auto bufferID = evaluateOrDefault(
1064410645
getASTContext().evaluator,
@@ -10650,8 +10651,7 @@ void MacroExpansionDecl::forEachExpandedExprOrStmt(
1065010651
auto startLoc = sourceMgr.getLocForBufferStart(*bufferID);
1065110652
auto *sourceFile = moduleDecl->getSourceFileContainingLocation(startLoc);
1065210653
for (auto node : sourceFile->getTopLevelItems())
10653-
if (node.is<Expr *>() || node.is<Stmt *>())
10654-
callback(node);
10654+
callback(node);
1065510655
}
1065610656

1065710657
NominalTypeDecl *

lib/SILGen/SILGenDecl.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1606,11 +1606,13 @@ void SILGenFunction::visitVarDecl(VarDecl *D) {
16061606
}
16071607

16081608
void SILGenFunction::visitMacroExpansionDecl(MacroExpansionDecl *D) {
1609-
D->forEachExpandedExprOrStmt([&](ASTNode node) {
1609+
D->forEachExpandedNode([&](ASTNode node) {
16101610
if (auto *expr = node.dyn_cast<Expr *>())
16111611
emitIgnoredExpr(expr);
16121612
else if (auto *stmt = node.dyn_cast<Stmt *>())
16131613
emitStmt(stmt);
1614+
else
1615+
visit(node.get<Decl *>());
16141616
});
16151617
}
16161618

lib/SILGen/SILGenExpr.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6246,11 +6246,13 @@ RValue RValueEmitter::visitMacroExpansionExpr(MacroExpansionExpr *E,
62466246
}
62476247
else if (auto *MED = E->getSubstituteDecl()) {
62486248
Mangle::ASTMangler mangler;
6249-
MED->forEachExpandedExprOrStmt([&](ASTNode node) {
6249+
MED->forEachExpandedNode([&](ASTNode node) {
62506250
if (auto *expr = node.dyn_cast<Expr *>())
62516251
visit(expr, C);
62526252
else if (auto *stmt = node.dyn_cast<Stmt *>())
62536253
SGF.emitStmt(stmt);
6254+
else
6255+
SGF.visit(node.get<Decl *>());
62546256
});
62556257
return RValue();
62566258
}

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2061,8 +2061,11 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
20612061
void visitMacroExpansionDecl(MacroExpansionDecl *MED) {
20622062
// Assign a discriminator.
20632063
(void)MED->getDiscriminator();
2064-
// Decls in expansion already visited as auxiliary decls.
2065-
MED->forEachExpandedExprOrStmt([&](ASTNode node) {
2064+
MED->forEachExpandedNode([&](ASTNode node) {
2065+
// Decls in expansion already visited as auxiliary decls.
2066+
if (node.is<Decl *>())
2067+
return;
2068+
20662069
TypeChecker::typeCheckASTNode(node, MED->getDeclContext());
20672070
});
20682071
}

test/Macros/Inputs/syntax_macro_definitions.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,24 @@ public struct DefineDeclsWithKnownNamesMacro: DeclarationMacro {
299299
}
300300
}
301301

302+
public struct VarDeclMacro: DeclarationMacro {
303+
public static func expansion(
304+
of node: some FreestandingMacroExpansionSyntax,
305+
in context: some MacroExpansionContext
306+
) throws -> [DeclSyntax] {
307+
return [
308+
"""
309+
let fromMacro = 23
310+
use(fromMacro)
311+
if true {
312+
let fromMacro = "string"
313+
use(fromMacro)
314+
}
315+
"""
316+
]
317+
}
318+
}
319+
302320
public struct WarningMacro: ExpressionMacro {
303321
public static func expansion(
304322
of macro: some FreestandingMacroExpansionSyntax,

test/Macros/macro_expand.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,13 @@ func testFileID(a: Int, b: Int) {
151151

152152
testFileID(a: 1, b: 2)
153153

154+
@freestanding(declaration, names: named(fromMacro)) macro varDecl() = #externalMacro(module: "MacroDefinition", type: "VarDeclMacro")
155+
156+
func testVarDecl() {
157+
func use<T>(_ t: T) {}
158+
#varDecl()
159+
}
160+
154161
@freestanding(expression) macro stringifyAndTry<T>(_ value: T) -> (T, String) =
155162
#externalMacro(module: "MacroDefinition", type: "StringifyAndTryMacro")
156163

0 commit comments

Comments
 (0)