Skip to content

Commit c78491e

Browse files
authored
Merge pull request #65317 from hborla/5.9-fix-macro-expansion-walking
[5.9][Macros] Fix type-checking local pattern bindings in macro-expanded closures.
2 parents 2740ce6 + dda0a90 commit c78491e

File tree

11 files changed

+83
-25
lines changed

11 files changed

+83
-25
lines changed

include/swift/AST/Attr.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2584,12 +2584,12 @@ class DeclAttributes {
25842584

25852585
/// Predicate used to filter attributes to only the original attributes.
25862586
class OrigDeclAttrFilter {
2587-
ModuleDecl *mod;
2587+
const Decl *decl;
25882588

25892589
public:
2590-
OrigDeclAttrFilter() : mod(nullptr) {}
2590+
OrigDeclAttrFilter() : decl(nullptr) {}
25912591

2592-
OrigDeclAttrFilter(ModuleDecl *mod) : mod(mod) {}
2592+
OrigDeclAttrFilter(const Decl *decl) : decl(decl) {}
25932593

25942594
Optional<const DeclAttribute *>
25952595
operator()(const DeclAttribute *Attr) const;
@@ -2611,7 +2611,7 @@ class OrigDeclAttributes {
26112611
public:
26122612
OrigDeclAttributes() : origRange(make_range(DeclAttributes::const_iterator(nullptr), DeclAttributes::const_iterator(nullptr)), OrigDeclAttrFilter()) {}
26132613

2614-
OrigDeclAttributes(const DeclAttributes &allAttrs, ModuleDecl *mod) : origRange(make_range(allAttrs.begin(), allAttrs.end()), OrigDeclAttrFilter(mod)) {}
2614+
OrigDeclAttributes(const DeclAttributes &allAttrs, const Decl *decl) : origRange(make_range(allAttrs.begin(), allAttrs.end()), OrigDeclAttrFilter(decl)) {}
26152615

26162616
OrigFilteredRange::iterator begin() const { return origRange.begin(); }
26172617
OrigFilteredRange::iterator end() const { return origRange.end(); }

include/swift/AST/Decl.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -934,9 +934,14 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
934934

935935
SourceLoc TrailingSemiLoc;
936936

937-
/// Whether this declaration is within a generated buffer, \c false if this
938-
/// declaration was constructed from a serialized module.
939-
bool isInGeneratedBuffer() const;
937+
/// Whether this declaration is within a macro expansion relative to
938+
/// its decl context. If the decl context is itself in a macro expansion,
939+
/// the method returns \c true if this decl is in a different macro
940+
/// expansion buffer than the context.
941+
///
942+
/// \Note this method returns \c false if this declaration was
943+
/// constructed from a serialized module.
944+
bool isInMacroExpansionInContext() const;
940945

941946
/// Returns the appropriate kind of entry point to generate for this class,
942947
/// based on its attributes.

include/swift/AST/Module.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -406,10 +406,6 @@ class ModuleDecl
406406
/// \c nullptr if the source location isn't in this module.
407407
SourceFile *getSourceFileContainingLocation(SourceLoc loc);
408408

409-
/// Whether the given location is inside a generated buffer, \c false if
410-
/// the given location isn't in this module.
411-
bool isInGeneratedBuffer(SourceLoc loc);
412-
413409
// Retrieve the buffer ID and source location of the outermost location that
414410
// caused the generation of the buffer containing \p loc. \p loc and its
415411
// buffer if it isn't in a generated buffer or has no original location.

lib/AST/ASTWalker.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1481,7 +1481,7 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
14811481

14821482
bool shouldSkip(Decl *D) {
14831483
if (!Walker.shouldWalkMacroArgumentsAndExpansion().second &&
1484-
D->isInGeneratedBuffer())
1484+
D->isInMacroExpansionInContext())
14851485
return true;
14861486

14871487
if (auto *VD = dyn_cast<VarDecl>(D)) {

lib/AST/Attr.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -853,8 +853,18 @@ SourceLoc DeclAttributes::getStartLoc(bool forModifiers) const {
853853

854854
Optional<const DeclAttribute *>
855855
OrigDeclAttrFilter::operator()(const DeclAttribute *Attr) const {
856-
if (!mod || mod->isInGeneratedBuffer(Attr->AtLoc))
856+
auto declLoc = decl->getStartLoc();
857+
auto *mod = decl->getModuleContext();
858+
auto *declFile = mod->getSourceFileContainingLocation(declLoc);
859+
auto *attrFile = mod->getSourceFileContainingLocation(Attr->AtLoc);
860+
if (!declFile || !attrFile)
861+
return Attr;
862+
863+
// Only attributes in the same buffer as the declaration they're attached to
864+
// are part of the original attribute list.
865+
if (declFile->getBufferID() != attrFile->getBufferID())
857866
return None;
867+
858868
return Attr;
859869
}
860870

lib/AST/Decl.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ StringRef Decl::getDescriptiveKindName(DescriptiveDeclKind K) {
368368
}
369369

370370
OrigDeclAttributes Decl::getOriginalAttrs() const {
371-
return OrigDeclAttributes(getAttrs(), getModuleContext());
371+
return OrigDeclAttributes(getAttrs(), this);
372372
}
373373

374374
DeclAttributes Decl::getSemanticAttrs() const {
@@ -767,8 +767,22 @@ SourceRange Decl::getSourceRangeIncludingAttrs() const {
767767
return Range;
768768
}
769769

770-
bool Decl::isInGeneratedBuffer() const {
771-
return getModuleContext()->isInGeneratedBuffer(getStartLoc());
770+
bool Decl::isInMacroExpansionInContext() const {
771+
auto *dc = getDeclContext();
772+
auto parentFile = dc->getParentSourceFile();
773+
auto *mod = getModuleContext();
774+
auto *file = mod->getSourceFileContainingLocation(getStartLoc());
775+
776+
// Decls in macro expansions always have a source file. The source
777+
// file can be null if the decl is implicit or has an invalid
778+
// source location.
779+
if (!parentFile || !file)
780+
return false;
781+
782+
if (file->getBufferID() == parentFile->getBufferID())
783+
return false;
784+
785+
return file->getFulfilledMacroRole() != None;
772786
}
773787

774788
SourceLoc Decl::getLocFromSource() const {

lib/AST/Module.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -816,13 +816,6 @@ SourceFile *ModuleDecl::getSourceFileContainingLocation(SourceLoc loc) {
816816
return foundSourceFile;
817817
}
818818

819-
bool ModuleDecl::isInGeneratedBuffer(SourceLoc loc) {
820-
SourceFile *file = getSourceFileContainingLocation(loc);
821-
if (!file)
822-
return false;
823-
return file->Kind == SourceFileKind::MacroExpansion;
824-
}
825-
826819
std::pair<unsigned, SourceLoc>
827820
ModuleDecl::getOriginalLocation(SourceLoc loc) const {
828821
assert(loc.isValid());

lib/IDE/SourceEntityWalker.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -889,7 +889,7 @@ bool SemaAnnotator::shouldIgnore(Decl *D) {
889889
// by a member attribute expansion. Note that we would have already skipped
890890
// this decl if we were ignoring expansions, so no need to check that.
891891
if (auto *missing = dyn_cast<MissingDecl>(D)) {
892-
if (D->isInGeneratedBuffer())
892+
if (D->isInMacroExpansionInContext())
893893
return false;
894894
}
895895

lib/Refactoring/Refactoring.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,11 +649,20 @@ renameAvailabilityInfo(const ValueDecl *VD, Optional<RenameRefInfo> RefInfo) {
649649
AvailKind = RefactorAvailableKind::Unavailable_has_no_name;
650650
}
651651

652+
auto isInMacroExpansionBuffer = [](const ValueDecl *VD) -> bool {
653+
auto *module = VD->getModuleContext();
654+
auto *file = module->getSourceFileContainingLocation(VD->getLoc());
655+
if (!file)
656+
return false;
657+
658+
return file->getFulfilledMacroRole() != None;
659+
};
660+
652661
if (AvailKind == RefactorAvailableKind::Available) {
653662
SourceLoc Loc = VD->getLoc();
654663
if (!Loc.isValid()) {
655664
AvailKind = RefactorAvailableKind::Unavailable_has_no_location;
656-
} else if (VD->getModuleContext()->isInGeneratedBuffer(Loc)) {
665+
} else if (isInMacroExpansionBuffer(VD)) {
657666
AvailKind = RefactorAvailableKind::Unavailable_decl_in_macro;
658667
}
659668
}

test/Macros/Inputs/syntax_macro_definitions.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,3 +1373,18 @@ public struct SimpleCodeItemMacro: CodeItemMacro {
13731373
]
13741374
}
13751375
}
1376+
1377+
public struct MultiStatementClosure: ExpressionMacro {
1378+
public static func expansion(
1379+
of node: some FreestandingMacroExpansionSyntax,
1380+
in context: some MacroExpansionContext
1381+
) throws -> ExprSyntax {
1382+
return """
1383+
{
1384+
let temp = 10
1385+
let result = temp
1386+
return result
1387+
}()
1388+
"""
1389+
}
1390+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// REQUIRES: swift_swift_parser, executable_test
2+
3+
// RUN: %empty-directory(%t)
4+
// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath
5+
// RUN: %target-build-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) %s -o %t/main -module-name MacroUser -swift-version 5
6+
// RUN: %target-codesign %t/main
7+
// RUN: %target-run %t/main | %FileCheck %s
8+
9+
@freestanding(expression) public macro multiStatement() -> Int = #externalMacro(module: "MacroDefinition", type: "MultiStatementClosure")
10+
11+
func multiStatementInference() -> Int {
12+
#multiStatement()
13+
}
14+
15+
// CHECK: 10
16+
print(multiStatementInference())

0 commit comments

Comments
 (0)