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();

0 commit comments

Comments
 (0)