Skip to content

Commit 2d81379

Browse files
committed
[Macros] Create type refinement context for MacroExpansionDecl
1 parent 8263e15 commit 2d81379

7 files changed

+70
-9
lines changed

lib/AST/ASTWalker.cpp

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

14831483
bool shouldSkip(Decl *D) {
14841484
if (!Walker.shouldWalkMacroArgumentsAndExpansion().second &&
1485-
D->isInMacroExpansionInContext())
1485+
D->isInMacroExpansionInContext() && !Walker.Parent.isNull())
14861486
return true;
14871487

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

lib/AST/Decl.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "swift/AST/Decl.h"
1818
#include "swift/AST/ASTContext.h"
1919
#include "swift/AST/ASTMangler.h"
20+
#include "swift/AST/ASTPrinter.h"
2021
#include "swift/AST/ASTWalker.h"
2122
#include "swift/AST/AccessRequests.h"
2223
#include "swift/AST/AccessScope.h"
@@ -10078,6 +10079,13 @@ void swift::simple_display(llvm::raw_ostream &out, const Decl *decl) {
1007810079
typeRepr->print(out);
1007910080
else
1008010081
ext->getSelfNominalTypeDecl()->dumpRef(out);
10082+
} else if (auto med = dyn_cast<MacroExpansionDecl>(decl)) {
10083+
out << '#' << med->getMacroName() << " in ";
10084+
printContext(out, med->getDeclContext());
10085+
if (med->getLoc().isValid()) {
10086+
out << '@';
10087+
med->getLoc().print(out, med->getASTContext().SourceMgr);
10088+
}
1008110089
} else {
1008210090
out << "(unknown decl)";
1008310091
}

lib/AST/TypeRefinementContext.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ TypeRefinementContext::createRoot(SourceFile *SF,
5353
if (auto parentExpansion = SF->getMacroExpansion()) {
5454
if (auto parentTRC =
5555
SF->getEnclosingSourceFile()->getTypeRefinementContext()) {
56+
// FIXME: Skip `MacroExpansionDecl` context?
57+
// Expanded decl might _not_ have the attributes on 'MacroExpansionDecl'
58+
// copied so it might want wider availability than the expansion itself.
59+
// E.g. '@available(macOS 99, *) #foo' expands to 'func foo() {}' (instead
60+
// of '@available(macOS 99, *) func foo() {}'). In such cases, the
61+
// attribute should not affect the expanded 'foo'?
62+
5663
auto charRange = Ctx.SourceMgr.getRangeForBuffer(*SF->getBufferID());
5764
range = SourceRange(charRange.getStart(), charRange.getEnd());
5865
parentContext = parentTRC->findMostRefinedSubContext(

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,7 @@ class TypeRefinementContextBuilder : private ASTWalker {
473473

474474
private:
475475
MacroWalking getMacroWalkingBehavior() const override {
476+
// Expansion buffers will have their type refinement contexts built lazily.
476477
return MacroWalking::Arguments;
477478
}
478479

@@ -558,7 +559,7 @@ class TypeRefinementContextBuilder : private ASTWalker {
558559
/// Returns a new context to be introduced for the declaration, or nullptr
559560
/// if no new context should be introduced.
560561
TypeRefinementContext *getNewContextForSignatureOfDecl(Decl *D) {
561-
if (!isa<ValueDecl>(D) && !isa<ExtensionDecl>(D))
562+
if (!isa<ValueDecl>(D) && !isa<ExtensionDecl>(D) && !isa<MacroExpansionDecl>(D))
562563
return nullptr;
563564

564565
// Only introduce for an AbstractStorageDecl if it is not local. We
@@ -3192,7 +3193,8 @@ class ExprAvailabilityWalker : public ASTWalker {
31923193
bool shouldWalkIntoTapExpression() override { return false; }
31933194

31943195
MacroWalking getMacroWalkingBehavior() const override {
3195-
return MacroWalking::ArgumentsAndExpansion;
3196+
// Expanded source should be type checked and diagnosed separately.
3197+
return MacroWalking::Arguments;
31963198
}
31973199

31983200
PreWalkResult<Expr *> walkToExprPre(Expr *E) override {

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2060,10 +2060,6 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
20602060
}
20612061

20622062
void visitMacroExpansionDecl(MacroExpansionDecl *MED) {
2063-
// TODO: Type check attributes.
2064-
// Type checking arguments should reflect the attributes.
2065-
// e.g. '@available(macOS 999) #Future { newAPIFrom999() }'.
2066-
20672063
// Assign a discriminator.
20682064
(void)MED->getDiscriminator();
20692065
// Decls in expansion already visited as auxiliary decls.

test/Macros/Inputs/top_level_freestanding_other.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ var globalVar2 = { #stringify(1 + 1) }()
1111
func deprecated() -> Int { 0 }
1212

1313
var globalVar3 = #stringify({ deprecated() })
14-
// expected-note@-1 2{{in expansion of macro 'stringify' here}}
14+
// expected-note@-1 {{in expansion of macro 'stringify' here}}
1515
// expected-warning@-2{{'deprecated()' is deprecated}}
1616

1717
var globalVar4 = #stringify({ deprecated() })
18-
// expected-note@-1 2{{in expansion of macro 'stringify' here}}
18+
// expected-note@-1 {{in expansion of macro 'stringify' here}}
1919
// expected-warning@-2{{'deprecated()' is deprecated}}

test/Macros/macro_attribute_expansiondecl.swift

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
// RUN: -parse-as-library \
2121
// RUN: -dump-macro-expansions \
2222
// RUN: -plugin-path %t/plugins \
23+
// RUN: -typo-correction-limit 0 \
2324
// RUN: %t/src/test.swift
2425

2526

@@ -57,6 +58,36 @@ public struct LocalFuncAndVarMacro: DeclarationMacro {
5758
}
5859
}
5960

61+
public struct FuncWithClosureMacro: DeclarationMacro {
62+
public static func expansion(
63+
of node: some FreestandingMacroExpansionSyntax,
64+
in context: some MacroExpansionContext
65+
) throws -> [DeclSyntax] {
66+
67+
return ["func LocalFunc() {}", "var LocalVar: Int { 1 }"]
68+
}
69+
}
70+
71+
public struct FuncFromClosureMacro: DeclarationMacro {
72+
public static func expansion(
73+
of node: some FreestandingMacroExpansionSyntax,
74+
in context: some MacroExpansionContext
75+
) throws -> [DeclSyntax] {
76+
guard
77+
let closure = node.trailingClosure,
78+
let arg1 = node.argumentList.first?.expression else {
79+
return []
80+
}
81+
82+
return ["""
83+
func fromClosure() {
84+
print(\(arg1))
85+
\(closure.statements)
86+
}
87+
"""]
88+
}
89+
}
90+
6091
//--- test.swift
6192

6293
@freestanding(declaration, names: named(globalFunc), named(globalVar)) macro globalDecls() = #externalMacro(module: "MacroDefinition", type: "GlobalFuncAndVarMacro")
@@ -97,3 +128,20 @@ func testLocal() {
97128
}
98129
#endif
99130
}
131+
132+
@freestanding(declaration, names: named(fromClosure)) macro funcFromClosureMacro(_: String, _: () -> Void) = #externalMacro(module: "MacroDefinition", type: "FuncFromClosureMacro")
133+
134+
@available(macOS 99, *)
135+
func APIFrom99() -> String { "" }
136+
@available(macOS 999, *)
137+
func APIFrom999() -> String { "" }
138+
139+
@available(macOS 99, *)
140+
#funcFromClosureMacro(APIFrom99()) {
141+
_ = APIFrom99()
142+
if #available(macOS 999, *) {
143+
_ = APIFrom99()
144+
_ = APIFrom999()
145+
}
146+
}
147+

0 commit comments

Comments
 (0)