Skip to content

Commit 200f234

Browse files
committed
[Macros] Be deliberate about walking macro arguments vs. expansions
Provide ASTWalker with a customization point to specify whether to check macro arguments (which are type checked but never emitted), the macro expansion (which is the result of applying the macro and is actually emitted into the source), or both. Provide answers for the ~115 different ASTWalker visitors throughout the code base. Fixes rdar://104042945, which concerns checking of effects in macro arguments---which we shouldn't do.
1 parent 16baee3 commit 200f234

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+590
-36
lines changed

include/swift/AST/ASTWalker.h

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,24 @@ enum class LazyInitializerWalking {
7979
InAccessor
8080
};
8181

82+
/// Specifies the behavior for walking a macro expansion, whether we want to
83+
/// see the macro arguments, the expansion, or both.
84+
enum class MacroWalking {
85+
/// Walk into the expansion of the macro, to see the semantic effect of
86+
/// the macro expansion.
87+
Expansion,
88+
89+
/// Walk into the arguments of the macro as written in the source code.
90+
///
91+
/// The actual arguments walked may not make it into the program itself,
92+
/// because they can be translated by the macro in arbitrary ways.
93+
Arguments,
94+
95+
/// Walk into both the arguments of the macro as written in the source code
96+
/// and also the macro expansion.
97+
ArgumentsAndExpansion
98+
};
99+
82100
/// An abstract class used to traverse an AST.
83101
class ASTWalker {
84102
public:
@@ -504,6 +522,24 @@ class ASTWalker {
504522
return LazyInitializerWalking::InPatternBinding;
505523
}
506524

525+
/// This method configures how the walker should walk into uses of macros.
526+
virtual MacroWalking getMacroWalkingBehavior() const = 0;
527+
528+
/// Determine whether we should walk macro arguments (as they appear in
529+
/// source) and the expansion (which is semantically part of the program).
530+
std::pair<bool, bool> shouldWalkMacroArgumentsAndExpansion() const {
531+
switch (getMacroWalkingBehavior()) {
532+
case MacroWalking::Expansion:
533+
return std::make_pair(false, true);
534+
535+
case MacroWalking::Arguments:
536+
return std::make_pair(true, false);
537+
538+
case MacroWalking::ArgumentsAndExpansion:
539+
return std::make_pair(true, true);
540+
}
541+
}
542+
507543
/// This method configures whether the walker should visit the body of a
508544
/// closure that was checked separately from its enclosing expression.
509545
///
@@ -541,10 +577,6 @@ class ASTWalker {
541577
/// TODO: Consider changing this to false by default.
542578
virtual bool shouldWalkSerializedTopLevelInternalDecls() { return true; }
543579

544-
/// Whether we should walk into expanded macros, whether it be from a
545-
/// \c MacroExpansionExpr or declarations created by attached macros.
546-
virtual bool shouldWalkMacroExpansions() { return true; }
547-
548580
/// walkToParameterListPre - This method is called when first visiting a
549581
/// ParameterList, before walking into its parameters.
550582
///

include/swift/AST/TypeDeclFinder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ class TypeReprIdentFinder : public ASTWalker {
6767
/// The function to call when a \c IdentTypeRepr is seen.
6868
llvm::function_ref<bool(const IdentTypeRepr *)> Callback;
6969

70+
MacroWalking getMacroWalkingBehavior() const override {
71+
return MacroWalking::Arguments;
72+
}
73+
7074
PostWalkAction walkToTypeReprPost(TypeRepr *TR) override;
7175

7276
public:

include/swift/IDE/SourceEntityWalker.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -201,9 +201,10 @@ class SourceEntityWalker {
201201

202202
virtual bool shouldWalkIntoGenericParams() { return true; }
203203

204-
/// Whether we should walk into expanded macros, whether it be from a
205-
/// \c MacroExpansionExpr or declarations created by attached macros.
206-
virtual bool shouldWalkMacroExpansions() { return false; }
204+
/// Only walk the arguments of a macro, to represent the source as written.
205+
virtual MacroWalking getMacroWalkingBehavior() const {
206+
return MacroWalking::Arguments;
207+
}
207208

208209
protected:
209210
SourceEntityWalker() = default;

include/swift/Sema/CompletionContextFinder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ class CompletionContextFinder : public ASTWalker {
4949
DeclContext *InitialDC;
5050

5151
public:
52+
MacroWalking getMacroWalkingBehavior() const override {
53+
return MacroWalking::Arguments;
54+
}
55+
5256
/// Finder for completion contexts within the provided initial expression.
5357
CompletionContextFinder(ASTNode initialNode, DeclContext *DC)
5458
: InitialExpr(initialNode.dyn_cast<Expr *>()), InitialDC(DC) {

include/swift/Sema/ConstraintSystem.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3376,6 +3376,11 @@ class ConstraintSystem {
33763376
CacheExprTypes(Expr *expr, ConstraintSystem &cs, bool excludeRoot)
33773377
: RootExpr(expr), CS(cs), ExcludeRoot(excludeRoot) {}
33783378

3379+
/// Walk everything in a macro
3380+
MacroWalking getMacroWalkingBehavior() const override {
3381+
return MacroWalking::ArgumentsAndExpansion;
3382+
}
3383+
33793384
PostWalkResult<Expr *> walkToExprPost(Expr *expr) override {
33803385
if (ExcludeRoot && expr == RootExpr) {
33813386
assert(!expr->getType() && "Unexpected type in root of expression!");
@@ -6954,6 +6959,10 @@ class OverloadSetCounter : public ASTWalker {
69546959
: NumOverloads(overloads)
69556960
{}
69566961

6962+
MacroWalking getMacroWalkingBehavior() const override {
6963+
return MacroWalking::Arguments;
6964+
}
6965+
69576966
PreWalkResult<Expr *> walkToExprPre(Expr *expr) override {
69586967
if (auto applyExpr = dyn_cast<ApplyExpr>(expr)) {
69596968
// If we've found function application and it's

lib/APIDigester/ModuleAnalyzerNodes.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2405,6 +2405,11 @@ class ConstExtractor: public ASTWalker {
24052405
}
24062406
return false;
24072407
}
2408+
2409+
MacroWalking getMacroWalkingBehavior() const override {
2410+
return MacroWalking::ArgumentsAndExpansion;
2411+
}
2412+
24082413
PreWalkResult<Expr *> walkToExprPre(Expr *E) override {
24092414
if (E->isSemanticallyConstExpr()) {
24102415
record(E, E);

lib/AST/ASTScopeCreation.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ class ScopeCreator final : public ASTAllocated<ScopeCreator> {
141141
PreWalkAction walkToParameterListPre(ParameterList *PL) override {
142142
return Action::SkipChildren();
143143
}
144+
145+
MacroWalking getMacroWalkingBehavior() const override {
146+
return MacroWalking::ArgumentsAndExpansion;
147+
}
144148
};
145149

146150
expr->walk(ClosureFinder(*this, parent));

lib/AST/ASTVerifier.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,10 @@ class Verifier : public ASTWalker {
271271
return Verifier(topDC->getParentModule(), DC);
272272
}
273273

274+
MacroWalking getMacroWalkingBehavior() const override {
275+
return MacroWalking::Expansion;
276+
}
277+
274278
PreWalkResult<Expr *> walkToExprPre(Expr *E) override {
275279
switch (E->getKind()) {
276280
#define DISPATCH(ID) return dispatchVisitPreExpr(static_cast<ID##Expr*>(E))

lib/AST/ASTWalker.cpp

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -430,9 +430,13 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
430430
}
431431

432432
bool visitMacroExpansionDecl(MacroExpansionDecl *MED) {
433-
if (MED->getArgs() && doIt(MED->getArgs()))
433+
bool shouldWalkArguments, shouldWalkExpansion;
434+
std::tie(shouldWalkArguments, shouldWalkExpansion) =
435+
Walker.shouldWalkMacroArgumentsAndExpansion();
436+
if (shouldWalkArguments && MED->getArgs() && doIt(MED->getArgs()))
434437
return true;
435-
if (Walker.shouldWalkMacroExpansions()) {
438+
439+
if (shouldWalkExpansion) {
436440
for (auto *decl : MED->getRewritten())
437441
if (doIt(decl))
438442
return true;
@@ -1297,20 +1301,24 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
12971301
}
12981302

12991303
Expr *visitMacroExpansionExpr(MacroExpansionExpr *E) {
1300-
ArgumentList *args = nullptr;
1301-
if (E->getArgs()) {
1302-
args = doIt(E->getArgs());
1304+
bool shouldWalkArguments, shouldWalkExpansion;
1305+
std::tie(shouldWalkArguments, shouldWalkExpansion) =
1306+
Walker.shouldWalkMacroArgumentsAndExpansion();
1307+
1308+
if (shouldWalkArguments && E->getArgs()) {
1309+
ArgumentList *args = doIt(E->getArgs());
13031310
if (!args) return nullptr;
1311+
E->setArgs(args);
13041312
}
1305-
if (Walker.shouldWalkMacroExpansions()) {
1313+
1314+
if (shouldWalkExpansion) {
13061315
Expr *rewritten = nullptr;
13071316
if (E->getRewritten()) {
13081317
rewritten = doIt(E->getRewritten());
13091318
if (!rewritten) return nullptr;
13101319
}
13111320
E->setRewritten(rewritten);
13121321
}
1313-
E->setArgs(args);
13141322
return E;
13151323
}
13161324

@@ -1425,7 +1433,8 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
14251433
}
14261434

14271435
bool shouldSkip(Decl *D) {
1428-
if (!Walker.shouldWalkMacroExpansions() && D->isInGeneratedBuffer())
1436+
if (!Walker.shouldWalkMacroArgumentsAndExpansion().second &&
1437+
D->isInGeneratedBuffer())
14291438
return true;
14301439

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

lib/AST/Decl.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7648,6 +7648,11 @@ swift::findWrappedValuePlaceholder(Expr *init) {
76487648
public:
76497649
PropertyWrapperValuePlaceholderExpr *placeholder = nullptr;
76507650

7651+
/// Only walk the arguments of a macro, to represent the source as written.
7652+
MacroWalking getMacroWalkingBehavior() const override {
7653+
return MacroWalking::Arguments;
7654+
}
7655+
76517656
virtual PreWalkResult<Expr *> walkToExprPre(Expr *E) override {
76527657
if (placeholder)
76537658
return Action::SkipChildren(E);
@@ -8343,6 +8348,11 @@ AbstractFunctionDecl::getBodyFingerprintIncludingLocalTypeMembers() const {
83438348
public:
83448349
HashCombiner(StableHasher &hasher) : hasher(hasher) {}
83458350

8351+
/// Only walk the arguments of a macro, to represent the source as written.
8352+
MacroWalking getMacroWalkingBehavior() const override {
8353+
return MacroWalking::Arguments;
8354+
}
8355+
83468356
PreWalkAction walkToDeclPre(Decl *D) override {
83478357
if (D->isImplicit())
83488358
return Action::SkipChildren();

lib/AST/Expr.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,12 @@ forEachImmediateChildExpr(llvm::function_ref<Expr *(Expr *)> callback) {
488488
struct ChildWalker : ASTWalker {
489489
llvm::function_ref<Expr *(Expr *)> callback;
490490
Expr *ThisNode;
491-
491+
492+
/// Only walk the arguments of a macro, to represent the source as written.
493+
MacroWalking getMacroWalkingBehavior() const override {
494+
return MacroWalking::Arguments;
495+
}
496+
492497
ChildWalker(llvm::function_ref<Expr *(Expr *)> callback, Expr *ThisNode)
493498
: callback(callback), ThisNode(ThisNode) {}
494499

@@ -533,6 +538,11 @@ void Expr::forEachChildExpr(llvm::function_ref<Expr *(Expr *)> callback) {
533538
struct ChildWalker : ASTWalker {
534539
llvm::function_ref<Expr *(Expr *)> callback;
535540

541+
/// Only walk the arguments of a macro, to represent the source as written.
542+
MacroWalking getMacroWalkingBehavior() const override {
543+
return MacroWalking::Arguments;
544+
}
545+
536546
ChildWalker(llvm::function_ref<Expr *(Expr *)> callback)
537547
: callback(callback) {}
538548

@@ -853,6 +863,11 @@ llvm::DenseMap<Expr *, Expr *> Expr::getParentMap() {
853863
public:
854864
llvm::DenseMap<Expr *, Expr *> &ParentMap;
855865

866+
/// Walk everything that's available.
867+
MacroWalking getMacroWalkingBehavior() const override {
868+
return MacroWalking::ArgumentsAndExpansion;
869+
}
870+
856871
explicit RecordingTraversal(llvm::DenseMap<Expr *, Expr *> &parentMap)
857872
: ParentMap(parentMap) { }
858873

@@ -1265,6 +1280,11 @@ void PackExpansionExpr::getExpandedPacks(SmallVectorImpl<ASTNode> &packs) {
12651280
struct PackCollector : public ASTWalker {
12661281
llvm::SmallVector<ASTNode, 2> packs;
12671282

1283+
/// Walk everything that's available.
1284+
MacroWalking getMacroWalkingBehavior() const override {
1285+
return MacroWalking::ArgumentsAndExpansion;
1286+
}
1287+
12681288
virtual PreWalkResult<Expr *> walkToExprPre(Expr *E) override {
12691289
// Don't walk into nested pack expansions
12701290
if (isa<PackExpansionExpr>(E)) {

lib/AST/InlinableText.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ class IsFeatureCheck : public ASTWalker {
4949
public:
5050
bool foundFeature = false;
5151

52+
/// Walk everything that's available.
53+
MacroWalking getMacroWalkingBehavior() const override {
54+
return MacroWalking::ArgumentsAndExpansion;
55+
}
56+
5257
PreWalkResult<Expr *> walkToExprPre(Expr *expr) override {
5358
if (auto unresolved = dyn_cast<UnresolvedDeclRefExpr>(expr)) {
5459
if (unresolved->getName().getBaseName().userFacingName().startswith("$"))
@@ -110,6 +115,11 @@ struct ExtractInactiveRanges : public ASTWalker {
110115
SmallVector<CharSourceRange, 4> ranges;
111116
SourceManager &sourceMgr;
112117

118+
/// Walk everything that's available.
119+
MacroWalking getMacroWalkingBehavior() const override {
120+
return MacroWalking::ArgumentsAndExpansion;
121+
}
122+
113123
explicit ExtractInactiveRanges(SourceManager &sourceMgr)
114124
: sourceMgr(sourceMgr) {}
115125

lib/AST/NameLookup.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2920,6 +2920,11 @@ CollectedOpaqueReprs swift::collectOpaqueReturnTypeReprs(TypeRepr *r, ASTContext
29202920
public:
29212921
explicit Walker(CollectedOpaqueReprs &reprs, ASTContext &ctx, DeclContext *d) : Reprs(reprs), Ctx(ctx), dc(d) {}
29222922

2923+
/// Walk everything that's available.
2924+
MacroWalking getMacroWalkingBehavior() const override {
2925+
return MacroWalking::ArgumentsAndExpansion;
2926+
}
2927+
29232928
PreWalkAction walkToTypeReprPre(TypeRepr *repr) override {
29242929

29252930
// Don't allow variadic opaque parameter or return types.

lib/AST/Pattern.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,12 @@ namespace {
167167
WalkToVarDecls(const std::function<void(VarDecl*)> &fn)
168168
: fn(fn) {}
169169

170+
/// Walk everything that's available; there shouldn't be macro expansions
171+
/// that matter anyway.
172+
MacroWalking getMacroWalkingBehavior() const override {
173+
return MacroWalking::ArgumentsAndExpansion;
174+
}
175+
170176
PostWalkResult<Pattern *> walkToPatternPost(Pattern *P) override {
171177
// Handle vars.
172178
if (auto *Named = dyn_cast<NamedPattern>(P))

lib/AST/Stmt.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,11 @@ ASTNode BraceStmt::findAsyncNode() {
245245
class FindInnerAsync : public ASTWalker {
246246
ASTNode AsyncNode;
247247

248+
/// Walk only the macro arguments.
249+
MacroWalking getMacroWalkingBehavior() const override {
250+
return MacroWalking::Arguments;
251+
}
252+
248253
PreWalkResult<Expr *> walkToExprPre(Expr *expr) override {
249254
// If we've found an 'await', record it and terminate the traversal.
250255
if (isa<AwaitExpr>(expr)) {

lib/AST/TypeRepr.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ bool TypeRepr::findIf(llvm::function_ref<bool(TypeRepr *)> pred) {
8383
explicit Walker(llvm::function_ref<bool(TypeRepr *)> pred)
8484
: Pred(pred), FoundIt(false) {}
8585

86+
/// Walk everything in a macro
87+
MacroWalking getMacroWalkingBehavior() const override {
88+
return MacroWalking::ArgumentsAndExpansion;
89+
}
90+
8691
PreWalkAction walkToTypeReprPre(TypeRepr *ty) override {
8792
if (Pred(ty)) {
8893
FoundIt = true;

lib/ConstExtract/ConstExtract.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ class NominalTypeConformanceCollector : public ASTWalker {
4747
std::vector<NominalTypeDecl *> &ConformanceDecls)
4848
: Protocols(Protocols), ConformanceTypeDecls(ConformanceDecls) {}
4949

50+
MacroWalking getMacroWalkingBehavior() const override {
51+
return MacroWalking::ArgumentsAndExpansion;
52+
}
53+
5054
PreWalkAction walkToDeclPre(Decl *D) override {
5155
if (auto *NTD = llvm::dyn_cast<NominalTypeDecl>(D))
5256
if (!isa<ProtocolDecl>(NTD))

lib/IDE/CompletionLookup.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,11 @@ bool swift::ide::canDeclContextHandleAsync(const DeclContext *DC) {
187187
const ClosureExpr *Target;
188188
bool Result = false;
189189

190+
/// Walk everything in a macro.
191+
MacroWalking getMacroWalkingBehavior() const override {
192+
return MacroWalking::ArgumentsAndExpansion;
193+
}
194+
190195
AsyncClosureChecker(const ClosureExpr *Target) : Target(Target) {}
191196

192197
PreWalkResult<Expr *> walkToExprPre(Expr *E) override {
@@ -3230,6 +3235,11 @@ void CompletionLookup::getStmtLabelCompletions(SourceLoc Loc, bool isContinue) {
32303235
public:
32313236
SmallVector<Identifier, 2> Result;
32323237

3238+
/// Walk only the arguments of a macro.
3239+
MacroWalking getMacroWalkingBehavior() const override {
3240+
return MacroWalking::Arguments;
3241+
}
3242+
32333243
LabelFinder(SourceManager &SM, SourceLoc TargetLoc, bool IsContinue)
32343244
: SM(SM), TargetLoc(TargetLoc), IsContinue(IsContinue) {}
32353245

0 commit comments

Comments
 (0)