Skip to content

Commit 3249ca9

Browse files
committed
[Macros] Create type refinement context for MacroExpansionDecl
(cherry picked from commit 7c2a73e)
1 parent 009f505 commit 3249ca9

File tree

6 files changed

+79
-10
lines changed

6 files changed

+79
-10
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"
@@ -10065,6 +10066,13 @@ void swift::simple_display(llvm::raw_ostream &out, const Decl *decl) {
1006510066
typeRepr->print(out);
1006610067
else
1006710068
ext->getSelfNominalTypeDecl()->dumpRef(out);
10069+
} else if (auto med = dyn_cast<MacroExpansionDecl>(decl)) {
10070+
out << '#' << med->getMacroName() << " in ";
10071+
printContext(out, med->getDeclContext());
10072+
if (med->getLoc().isValid()) {
10073+
out << '@';
10074+
med->getLoc().print(out, med->getASTContext().SourceMgr);
10075+
}
1006810076
} else {
1006910077
out << "(unknown decl)";
1007010078
}

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 7 additions & 3 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
@@ -1430,7 +1431,9 @@ class InnermostAncestorFinder : private ASTWalker {
14301431
Optional<ASTNode> getInnermostMatchingNode() { return InnermostMatchingNode; }
14311432

14321433
MacroWalking getMacroWalkingBehavior() const override {
1433-
return MacroWalking::ArgumentsAndExpansion;
1434+
// This is SourceRange based finder. 'SM.rangeContains()' fails anyway when
1435+
// crossing source buffers.
1436+
return MacroWalking::Arguments;
14341437
}
14351438

14361439
PreWalkResult<Expr *> walkToExprPre(Expr *E) override {
@@ -3244,7 +3247,8 @@ class ExprAvailabilityWalker : public ASTWalker {
32443247
bool shouldWalkIntoTapExpression() override { return false; }
32453248

32463249
MacroWalking getMacroWalkingBehavior() const override {
3247-
return MacroWalking::ArgumentsAndExpansion;
3250+
// Expanded source should be type checked and diagnosed separately.
3251+
return MacroWalking::Arguments;
32483252
}
32493253

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

lib/Sema/TypeCheckDeclPrimary.cpp

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

20602060
void visitMacroExpansionDecl(MacroExpansionDecl *MED) {
2061-
// TODO: Type check attributes.
2062-
// Type checking arguments should reflect the attributes.
2063-
// e.g. '@available(macOS 999) #Future { newAPIFrom999() }'.
2064-
20652061
// Assign a discriminator.
20662062
(void)MED->getDiscriminator();
20672063
// 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: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,26 @@ public struct LocalFuncAndVarMacro: DeclarationMacro {
5757
}
5858
}
5959

60+
public struct FuncFromClosureMacro: DeclarationMacro {
61+
public static func expansion(
62+
of node: some FreestandingMacroExpansionSyntax,
63+
in context: some MacroExpansionContext
64+
) throws -> [DeclSyntax] {
65+
guard
66+
let closure = node.trailingClosure,
67+
let arg1 = node.argumentList.first?.expression else {
68+
return []
69+
}
70+
71+
return ["""
72+
func fromClosure() {
73+
print(\(arg1))
74+
\(closure.statements)
75+
}
76+
"""]
77+
}
78+
}
79+
6080
//--- test.swift
6181

6282
@freestanding(declaration, names: named(globalFunc), named(globalVar)) macro globalDecls() = #externalMacro(module: "MacroDefinition", type: "GlobalFuncAndVarMacro")
@@ -97,3 +117,44 @@ func testLocal() {
97117
}
98118
#endif
99119
}
120+
121+
@freestanding(declaration, names: named(fromClosure)) macro funcFromClosureMacro(_: String, _: () -> Void) = #externalMacro(module: "MacroDefinition", type: "FuncFromClosureMacro")
122+
123+
@available(macOS 99, *)
124+
func APIFrom99() -> String { "" }
125+
@available(macOS 999, *)
126+
func APIFrom999() -> String { "" }
127+
128+
@available(macOS 99, *)
129+
#funcFromClosureMacro(APIFrom99()) {
130+
_ = APIFrom99()
131+
if #available(macOS 999, *) {
132+
_ = APIFrom99()
133+
_ = APIFrom999()
134+
}
135+
}
136+
137+
struct S1 {
138+
@available(macOS 99, *)
139+
#funcFromClosureMacro(APIFrom99()) {
140+
_ = APIFrom99()
141+
if #available(macOS 999, *) {
142+
_ = APIFrom99()
143+
_ = APIFrom999()
144+
}
145+
}
146+
}
147+
148+
// FIXME: Diagnostics could be better.
149+
struct S2 { // expected-note 4 {{add @available attribute to enclosing struct}}
150+
// expected-note@+3 6 {{in expansion of macro 'funcFromClosureMacro' here}}
151+
// expected-error@+2 {{'APIFrom99()' is only available in macOS 99 or newer}}
152+
// expected-error@+2 {{'APIFrom99()' is only available in macOS 99 or newer}} expected-note@+2 {{add 'if #available' version check}}
153+
#funcFromClosureMacro(APIFrom99()) {
154+
_ = APIFrom99()
155+
if #available(macOS 999, *) {
156+
_ = APIFrom99()
157+
_ = APIFrom999()
158+
}
159+
}
160+
}

0 commit comments

Comments
 (0)