diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 944c5a8da596d..be7fc334c1854 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -884,7 +884,13 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated { /// /// Auxiliary declarations can be property wrapper backing variables, /// backing variables for 'lazy' vars, or peer macro expansions. - void visitAuxiliaryDecls(AuxiliaryDeclCallback callback) const; + /// + /// When \p visitFreestandingExpanded is true (the default), this will also + /// visit the declarations produced by a freestanding macro expansion. + void visitAuxiliaryDecls( + AuxiliaryDeclCallback callback, + bool visitFreestandingExpanded = true + ) const; using MacroCallback = llvm::function_ref; @@ -8605,8 +8611,9 @@ class MacroExpansionDecl : public Decl, public FreestandingMacroExpansion { return getExpansionInfo()->getSourceRange(); } SourceLoc getLocFromSource() const { return getExpansionInfo()->SigilLoc; } - using ExprOrStmtExpansionCallback = llvm::function_ref; - void forEachExpandedExprOrStmt(ExprOrStmtExpansionCallback) const; + + /// Enumerate the nodes produced by expanding this macro expansion. + void forEachExpandedNode(llvm::function_ref callback) const; /// Returns a discriminator which determines this macro expansion's index /// in the sequence of macro expansions within the current function. diff --git a/lib/AST/ASTWalker.cpp b/lib/AST/ASTWalker.cpp index 1238515d24d2a..c4c93044bcb11 100644 --- a/lib/AST/ASTWalker.cpp +++ b/lib/AST/ASTWalker.cpp @@ -455,15 +455,9 @@ class Traversal : public ASTVisitorvisitAuxiliaryDecls([&](Decl *decl) { - if (alreadyFailed) return; - if (!isa(decl)) - alreadyFailed = inherited::visit(decl); - }); - MED->forEachExpandedExprOrStmt([&](ASTNode expandedNode) { + MED->forEachExpandedNode([&](ASTNode expandedNode) { if (alreadyFailed) return; if (auto *expr = expandedNode.dyn_cast()) { if (!doIt(expr)) @@ -471,6 +465,10 @@ class Traversal : public ASTVisitor()) { if (!doIt(stmt)) alreadyFailed = true; + } else { + auto decl = expandedNode.get(); + if (!isa(decl)) + alreadyFailed = inherited::visit(decl); } }); } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 05af5c01269cd..ab0f6f16a8c30 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -381,7 +381,10 @@ DeclAttributes Decl::getSemanticAttrs() const { return getAttrs(); } -void Decl::visitAuxiliaryDecls(AuxiliaryDeclCallback callback) const { +void Decl::visitAuxiliaryDecls( + AuxiliaryDeclCallback callback, + bool visitFreestandingExpanded +) const { auto &ctx = getASTContext(); auto *mutableThis = const_cast(this); SourceManager &sourceMgr = ctx.SourceMgr; @@ -414,13 +417,15 @@ void Decl::visitAuxiliaryDecls(AuxiliaryDeclCallback callback) const { } } - else if (auto *med = dyn_cast(mutableThis)) { - if (auto bufferID = evaluateOrDefault( - ctx.evaluator, ExpandMacroExpansionDeclRequest{med}, {})) { - auto startLoc = sourceMgr.getLocForBufferStart(*bufferID); - auto *sourceFile = moduleDecl->getSourceFileContainingLocation(startLoc); - for (auto *decl : sourceFile->getTopLevelDecls()) - callback(decl); + if (visitFreestandingExpanded) { + if (auto *med = dyn_cast(mutableThis)) { + if (auto bufferID = evaluateOrDefault( + ctx.evaluator, ExpandMacroExpansionDeclRequest{med}, {})) { + auto startLoc = sourceMgr.getLocForBufferStart(*bufferID); + auto *sourceFile = moduleDecl->getSourceFileContainingLocation(startLoc); + for (auto *decl : sourceFile->getTopLevelDecls()) + callback(decl); + } } } @@ -10637,8 +10642,9 @@ unsigned MacroExpansionDecl::getDiscriminator() const { return getRawDiscriminator(); } -void MacroExpansionDecl::forEachExpandedExprOrStmt( - ExprOrStmtExpansionCallback callback) const { +void MacroExpansionDecl::forEachExpandedNode( + llvm::function_ref callback +) const { auto mutableThis = const_cast(this); auto bufferID = evaluateOrDefault( getASTContext().evaluator, @@ -10650,8 +10656,7 @@ void MacroExpansionDecl::forEachExpandedExprOrStmt( auto startLoc = sourceMgr.getLocForBufferStart(*bufferID); auto *sourceFile = moduleDecl->getSourceFileContainingLocation(startLoc); for (auto node : sourceFile->getTopLevelItems()) - if (node.is() || node.is()) - callback(node); + callback(node); } NominalTypeDecl * diff --git a/lib/SILGen/SILGenDecl.cpp b/lib/SILGen/SILGenDecl.cpp index 24e5021e509ea..07dd05c427f24 100644 --- a/lib/SILGen/SILGenDecl.cpp +++ b/lib/SILGen/SILGenDecl.cpp @@ -1606,11 +1606,13 @@ void SILGenFunction::visitVarDecl(VarDecl *D) { } void SILGenFunction::visitMacroExpansionDecl(MacroExpansionDecl *D) { - D->forEachExpandedExprOrStmt([&](ASTNode node) { + D->forEachExpandedNode([&](ASTNode node) { if (auto *expr = node.dyn_cast()) emitIgnoredExpr(expr); else if (auto *stmt = node.dyn_cast()) emitStmt(stmt); + else + visit(node.get()); }); } diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index 6030d6ea32ba9..4f1923c2ae36b 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -6246,11 +6246,13 @@ RValue RValueEmitter::visitMacroExpansionExpr(MacroExpansionExpr *E, } else if (auto *MED = E->getSubstituteDecl()) { Mangle::ASTMangler mangler; - MED->forEachExpandedExprOrStmt([&](ASTNode node) { + MED->forEachExpandedNode([&](ASTNode node) { if (auto *expr = node.dyn_cast()) visit(expr, C); else if (auto *stmt = node.dyn_cast()) SGF.emitStmt(stmt); + else + SGF.visit(node.get()); }); return RValue(); } diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index f3c5d3f97bf36..8efa3435ef664 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -1845,7 +1845,7 @@ class DeclChecker : public DeclVisitor { if (!isa(decl->getDeclContext())) { decl->visitAuxiliaryDecls([&](Decl *auxiliaryDecl) { this->visit(auxiliaryDecl); - }); + }, /*visitFreestandingExpanded=*/false); } if (auto *Stats = getASTContext().Stats) @@ -2061,8 +2061,7 @@ class DeclChecker : public DeclVisitor { void visitMacroExpansionDecl(MacroExpansionDecl *MED) { // Assign a discriminator. (void)MED->getDiscriminator(); - // Decls in expansion already visited as auxiliary decls. - MED->forEachExpandedExprOrStmt([&](ASTNode node) { + MED->forEachExpandedNode([&](ASTNode node) { TypeChecker::typeCheckASTNode(node, MED->getDeclContext()); }); } diff --git a/test/Macros/Inputs/syntax_macro_definitions.swift b/test/Macros/Inputs/syntax_macro_definitions.swift index f95ca9f6ec2b9..ca12537ee2413 100644 --- a/test/Macros/Inputs/syntax_macro_definitions.swift +++ b/test/Macros/Inputs/syntax_macro_definitions.swift @@ -299,6 +299,25 @@ public struct DefineDeclsWithKnownNamesMacro: DeclarationMacro { } } +public struct VarDeclMacro: CodeItemMacro { + public static func expansion( + of node: some FreestandingMacroExpansionSyntax, + in context: some MacroExpansionContext + ) throws -> [CodeBlockItemSyntax] { + let name = context.makeUniqueName("fromMacro") + return [ + "let \(name) = 23", + "use(\(name))", + """ + if true { + let \(name) = "string" + use(\(name)) + } + """ + ] + } +} + public struct WarningMacro: ExpressionMacro { public static func expansion( of macro: some FreestandingMacroExpansionSyntax, diff --git a/test/Macros/macro_expand_codeitems.swift b/test/Macros/macro_expand_codeitems.swift index db27cc3397bc4..da2dd8e009428 100644 --- a/test/Macros/macro_expand_codeitems.swift +++ b/test/Macros/macro_expand_codeitems.swift @@ -33,3 +33,10 @@ func testFreestandingMacroExpansion() { #codeItems } testFreestandingMacroExpansion() + +@freestanding(codeItem) macro varDecl() = #externalMacro(module: "MacroDefinition", type: "VarDeclMacro") + +func testVarDecl() { + func use(_ t: T) {} + #varDecl() +} diff --git a/test/Macros/top_level_freestanding.swift b/test/Macros/top_level_freestanding.swift index d0decd1d0c220..3fd9c07c1d6bd 100644 --- a/test/Macros/top_level_freestanding.swift +++ b/test/Macros/top_level_freestanding.swift @@ -50,7 +50,7 @@ func lookupGlobalFreestandingExpansion() { #anonymousTypes(public: true) { "hello" } -// CHECK-SIL: sil @$s9MacroUser03$s9A71User33_082AE7CFEFA6960C804A9FE7366EB5A0Ll14anonymousTypesfMf0_4namefMu_C5helloSSyF +// CHECK-SIL: sil @$s9MacroUser03$s9A70User33_082AE7CFEFA6960C804A9FE7366EB5A0Ll14anonymousTypesfMf_4namefMu_C5helloSSyF @main struct Main { diff --git a/test/SourceKit/Macros/macro_basic.swift b/test/SourceKit/Macros/macro_basic.swift index f7c581b0066d8..9109b45f45980 100644 --- a/test/SourceKit/Macros/macro_basic.swift +++ b/test/SourceKit/Macros/macro_basic.swift @@ -131,7 +131,7 @@ macro anonymousTypes(_: () -> String) = #externalMacro(module: "MacroDefinition" // RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=57:1 %s -- ${COMPILER_ARGS[@]} -parse-as-library | %FileCheck -check-prefix=EXPAND_MACRO_DECL %s // RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=57:2 %s -- ${COMPILER_ARGS[@]} -parse-as-library | %FileCheck -check-prefix=EXPAND_MACRO_DECL %s // EXPAND_MACRO_DECL: source.edit.kind.active: -// EXPAND_MACRO_DECL-NEXT: 57:1-57:28 (@__swiftmacro_9MacroUser33_70D4178875715FB9B8B50C58F66F8D53Ll14anonymousTypesfMf0_.swift) "class $s9MacroUser33_70D4178875715FB9B8B50C58F66F8D53Ll14anonymousTypesfMf0_4namefMu_ { +// EXPAND_MACRO_DECL-NEXT: 57:1-57:28 (@__swiftmacro_9MacroUser33_70D4178875715FB9B8B50C58F66F8D53Ll14anonymousTypesfMf_.swift) "class $s9MacroUser33_70D4178875715FB9B8B50C58F66F8D53Ll14anonymousTypesfMf_4namefMu_ { // EXPAND_MACRO_DECL-NEXT: func hello() -> String { // EXPAND_MACRO_DECL-NEXT: "hello" // EXPAND_MACRO_DECL-NEXT: } @@ -140,7 +140,7 @@ macro anonymousTypes(_: () -> String) = #externalMacro(module: "MacroDefinition" // EXPAND_MACRO_DECL-NEXT: return Self.self // EXPAND_MACRO_DECL-NEXT: } // EXPAND_MACRO_DECL-NEXT: } -// EXPAND_MACRO_DECL-NEXT: enum $s9MacroUser33_70D4178875715FB9B8B50C58F66F8D53Ll14anonymousTypesfMf0_4namefMu0_ { +// EXPAND_MACRO_DECL-NEXT: enum $s9MacroUser33_70D4178875715FB9B8B50C58F66F8D53Ll14anonymousTypesfMf_4namefMu0_ { // EXPAND_MACRO_DECL-NEXT: case apple // EXPAND_MACRO_DECL-NEXT: case banana // EXPAND_MACRO_DECL-EMPTY: @@ -148,7 +148,7 @@ macro anonymousTypes(_: () -> String) = #externalMacro(module: "MacroDefinition" // EXPAND_MACRO_DECL-NEXT: "hello" // EXPAND_MACRO_DECL-NEXT: } // EXPAND_MACRO_DECL-NEXT: } -// EXPAND_MACRO_DECL-NEXT: struct $s9MacroUser33_70D4178875715FB9B8B50C58F66F8D53Ll14anonymousTypesfMf0_4namefMu1_: Equatable { +// EXPAND_MACRO_DECL-NEXT: struct $s9MacroUser33_70D4178875715FB9B8B50C58F66F8D53Ll14anonymousTypesfMf_4namefMu1_: Equatable { // EXPAND_MACRO_DECL-NEXT: static func == (lhs: Self, rhs: Self) -> Bool { // EXPAND_MACRO_DECL-NEXT: false // EXPAND_MACRO_DECL-NEXT: }