Skip to content

Commit 6e3289d

Browse files
committed
[Macros] Compute discriminators for freestanding macro expansions.
Introduce discriminators into freestanding macro expansion expressions and declarations. Compute these discriminators alongside closure and local-declaration discriminators, checking them in the AST verifier.
1 parent f5c7e4f commit 6e3289d

File tree

9 files changed

+184
-14
lines changed

9 files changed

+184
-14
lines changed

include/swift/AST/Decl.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,10 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
725725
NumberOfVTableEntries : 2
726726
);
727727

728+
SWIFT_INLINE_BITFIELD(MacroExpansionDecl, Decl, 16,
729+
Discriminator : 16
730+
);
731+
728732
} Bits;
729733

730734
// Storage for the declaration attributes.
@@ -8452,6 +8456,8 @@ class MacroExpansionDecl : public Decl {
84528456
ConcreteDeclRef macroRef;
84538457

84548458
public:
8459+
enum : unsigned { InvalidDiscriminator = 0xFFFF };
8460+
84558461
MacroExpansionDecl(DeclContext *dc, SourceLoc poundLoc, DeclNameRef macro,
84568462
DeclNameLoc macroLoc,
84578463
SourceLoc leftAngleLoc,
@@ -8461,7 +8467,9 @@ class MacroExpansionDecl : public Decl {
84618467
: Decl(DeclKind::MacroExpansion, dc), PoundLoc(poundLoc),
84628468
Macro(macro), MacroLoc(macroLoc),
84638469
LeftAngleLoc(leftAngleLoc), RightAngleLoc(rightAngleLoc),
8464-
GenericArgs(genericArgs), ArgList(args), Rewritten({}) {}
8470+
GenericArgs(genericArgs), ArgList(args), Rewritten({}) {
8471+
Bits.MacroExpansionDecl.Discriminator = InvalidDiscriminator;
8472+
}
84658473

84668474
ArrayRef<TypeRepr *> getGenericArgs() const { return GenericArgs; }
84678475

@@ -8480,6 +8488,24 @@ class MacroExpansionDecl : public Decl {
84808488
ConcreteDeclRef getMacroRef() const { return macroRef; }
84818489
void setMacroRef(ConcreteDeclRef ref) { macroRef = ref; }
84828490

8491+
/// Returns a discriminator which determines this macro expansion's index
8492+
/// in the sequence of macro expansions within the current function.
8493+
unsigned getDiscriminator() const;
8494+
8495+
/// Retrieve the raw discriminator, which may not have been computed yet.
8496+
///
8497+
/// Only use this for queries that are checking for (e.g.) reentrancy or
8498+
/// intentionally do not want to initiate verification.
8499+
unsigned getRawDiscriminator() const {
8500+
return Bits.MacroExpansionDecl.Discriminator;
8501+
}
8502+
8503+
void setDiscriminator(unsigned discriminator) {
8504+
assert(getRawDiscriminator() == InvalidDiscriminator);
8505+
assert(discriminator != InvalidDiscriminator);
8506+
Bits.MacroExpansionDecl.Discriminator = discriminator;
8507+
}
8508+
84838509
static bool classof(const Decl *D) {
84848510
return D->getKind() == DeclKind::MacroExpansion;
84858511
}

include/swift/AST/Expr.h

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,12 @@ class alignas(8) Expr : public ASTAllocated<Expr> {
363363
: NumPadBits,
364364
NumElements : 32
365365
);
366+
367+
SWIFT_INLINE_BITFIELD(MacroExpansionExpr, Expr, (16-NumExprBits)+16,
368+
: 16 - NumExprBits, // Align and leave room for subclasses
369+
Discriminator : 16
370+
);
371+
366372
} Bits;
367373

368374
private:
@@ -6049,6 +6055,7 @@ class TypeJoinExpr final : public Expr,
60496055

60506056
class MacroExpansionExpr final : public Expr {
60516057
private:
6058+
DeclContext *DC;
60526059
SourceLoc PoundLoc;
60536060
DeclNameRef MacroName;
60546061
DeclNameLoc MacroNameLoc;
@@ -6061,19 +6068,26 @@ class MacroExpansionExpr final : public Expr {
60616068
ConcreteDeclRef macroRef;
60626069

60636070
public:
6064-
explicit MacroExpansionExpr(SourceLoc poundLoc, DeclNameRef macroName,
6071+
enum : unsigned { InvalidDiscriminator = 0xFFFF };
6072+
6073+
explicit MacroExpansionExpr(DeclContext *dc,
6074+
SourceLoc poundLoc, DeclNameRef macroName,
60656075
DeclNameLoc macroNameLoc,
60666076
SourceLoc leftAngleLoc,
60676077
ArrayRef<TypeRepr *> genericArgs,
60686078
SourceLoc rightAngleLoc,
6069-
ArgumentList *argList, bool isImplicit = false,
6079+
ArgumentList *argList,
6080+
bool isImplicit = false,
60706081
Type ty = Type())
6071-
: Expr(ExprKind::MacroExpansion, isImplicit, ty), PoundLoc(poundLoc),
6082+
: Expr(ExprKind::MacroExpansion, isImplicit, ty),
6083+
DC(dc), PoundLoc(poundLoc),
60726084
MacroName(macroName), MacroNameLoc(macroNameLoc),
60736085
LeftAngleLoc(leftAngleLoc), RightAngleLoc(rightAngleLoc),
60746086
GenericArgs(genericArgs),
60756087
ArgList(argList),
6076-
Rewritten(nullptr) { }
6088+
Rewritten(nullptr) {
6089+
Bits.MacroExpansionExpr.Discriminator = InvalidDiscriminator;
6090+
}
60776091

60786092
DeclNameRef getMacroName() const { return MacroName; }
60796093
DeclNameLoc getMacroNameLoc() const { return MacroNameLoc; }
@@ -6095,6 +6109,27 @@ class MacroExpansionExpr final : public Expr {
60956109
ConcreteDeclRef getMacroRef() const { return macroRef; }
60966110
void setMacroRef(ConcreteDeclRef ref) { macroRef = ref; }
60976111

6112+
DeclContext *getDeclContext() const { return DC; }
6113+
void setDeclContext(DeclContext *dc) { DC = dc; }
6114+
6115+
/// Returns a discriminator which determines this macro expansion's index
6116+
/// in the sequence of macro expansions within the current function.
6117+
unsigned getDiscriminator() const;
6118+
6119+
/// Retrieve the raw discriminator, which may not have been computed yet.
6120+
///
6121+
/// Only use this for queries that are checking for (e.g.) reentrancy or
6122+
/// intentionally do not want to initiate verification.
6123+
unsigned getRawDiscriminator() const {
6124+
return Bits.MacroExpansionExpr.Discriminator;
6125+
}
6126+
6127+
void setDiscriminator(unsigned discriminator) {
6128+
assert(getRawDiscriminator() == InvalidDiscriminator);
6129+
assert(discriminator != InvalidDiscriminator);
6130+
Bits.MacroExpansionExpr.Discriminator = discriminator;
6131+
}
6132+
60986133
SourceRange getSourceRange() const;
60996134

61006135
static bool classof(const Expr *E) {

lib/AST/ASTDumper.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3021,6 +3021,8 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
30213021
void visitMacroExpansionExpr(MacroExpansionExpr *E) {
30223022
printCommon(E, "macro_expansion_expr");
30233023
PrintWithColorRAII(OS, IdentifierColor) << " name=" << E->getMacroName();
3024+
PrintWithColorRAII(OS, DiscriminatorColor)
3025+
<< " discriminator=" << E->getRawDiscriminator();
30243026
if (E->getArgs()) {
30253027
OS << '\n';
30263028
printArgumentList(E->getArgs());

lib/AST/ASTVerifier.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,10 @@ class Verifier : public ASTWalker {
232232
ClosureDiscriminators;
233233
DeclContext *CanonicalTopLevelSubcontext = nullptr;
234234

235+
typedef DeclContext * MacroExpansionDiscriminatorKey;
236+
llvm::DenseMap<MacroExpansionDiscriminatorKey, SmallBitVector>
237+
MacroExpansionDiscriminators;
238+
235239
Verifier(PointerUnion<ModuleDecl *, SourceFile *> M, DeclContext *DC)
236240
: M(M),
237241
Ctx(M.is<ModuleDecl *>() ? M.get<ModuleDecl *>()->getASTContext()
@@ -2372,6 +2376,46 @@ class Verifier : public ASTWalker {
23722376
}
23732377
}
23742378

2379+
void verifyChecked(MacroExpansionExpr *expansion) {
2380+
auto dc = getCanonicalDeclContext(expansion->getDeclContext());
2381+
MacroExpansionDiscriminatorKey key{dc};
2382+
auto &discriminatorSet = MacroExpansionDiscriminators[key];
2383+
unsigned discriminator = expansion->getDiscriminator();
2384+
2385+
if (discriminator >= discriminatorSet.size()) {
2386+
discriminatorSet.resize(discriminator+1);
2387+
discriminatorSet.set(discriminator);
2388+
} else if (discriminatorSet.test(discriminator)) {
2389+
Out << "a macro expansion must have a unique discriminator "
2390+
<< "in its context\n";
2391+
expansion->dump(Out);
2392+
Out << "\n";
2393+
abort();
2394+
} else {
2395+
discriminatorSet.set(discriminator);
2396+
}
2397+
}
2398+
2399+
void verifyChecked(MacroExpansionDecl *expansion) {
2400+
auto dc = getCanonicalDeclContext(expansion->getDeclContext());
2401+
MacroExpansionDiscriminatorKey key{dc};
2402+
auto &discriminatorSet = MacroExpansionDiscriminators[key];
2403+
unsigned discriminator = expansion->getDiscriminator();
2404+
2405+
if (discriminator >= discriminatorSet.size()) {
2406+
discriminatorSet.resize(discriminator+1);
2407+
discriminatorSet.set(discriminator);
2408+
} else if (discriminatorSet.test(discriminator)) {
2409+
Out << "a macro expansion must have a unique discriminator "
2410+
<< "in its context\n";
2411+
expansion->dump(Out);
2412+
Out << "\n";
2413+
abort();
2414+
} else {
2415+
discriminatorSet.set(discriminator);
2416+
}
2417+
}
2418+
23752419
void verifyChecked(ValueDecl *VD) {
23762420
if (VD->getInterfaceType()->hasError()) {
23772421
Out << "checked decl cannot have error type\n";

lib/AST/Decl.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9860,6 +9860,18 @@ SourceRange MacroExpansionDecl::getSourceRange() const {
98609860
return SourceRange(PoundLoc, endLoc);
98619861
}
98629862

9863+
unsigned MacroExpansionDecl::getDiscriminator() const {
9864+
if (getRawDiscriminator() != InvalidDiscriminator)
9865+
return getRawDiscriminator();
9866+
9867+
auto dc = getDeclContext();
9868+
ASTContext &ctx = dc->getASTContext();
9869+
evaluateOrDefault(ctx.evaluator, LocalDiscriminatorsRequest{dc}, 0);
9870+
9871+
assert(getRawDiscriminator() != InvalidDiscriminator);
9872+
return getRawDiscriminator();
9873+
}
9874+
98639875
NominalTypeDecl *
98649876
ValueDecl::getRuntimeDiscoverableAttrTypeDecl(CustomAttr *attr) const {
98659877
auto &ctx = getASTContext();

lib/AST/Expr.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2559,6 +2559,18 @@ SourceRange MacroExpansionExpr::getSourceRange() const {
25592559
return SourceRange(PoundLoc, endLoc);
25602560
}
25612561

2562+
unsigned MacroExpansionExpr::getDiscriminator() const {
2563+
if (getRawDiscriminator() != InvalidDiscriminator)
2564+
return getRawDiscriminator();
2565+
2566+
auto dc = getDeclContext();
2567+
ASTContext &ctx = dc->getASTContext();
2568+
evaluateOrDefault(ctx.evaluator, LocalDiscriminatorsRequest{dc}, 0);
2569+
2570+
assert(getRawDiscriminator() != InvalidDiscriminator);
2571+
return getRawDiscriminator();
2572+
}
2573+
25622574
void swift::simple_display(llvm::raw_ostream &out, const ClosureExpr *CE) {
25632575
if (!CE) {
25642576
out << "(null)";

lib/Parse/ParseExpr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3367,7 +3367,7 @@ ParserResult<Expr> Parser::parseExprMacroExpansion(bool isExprBasic) {
33673367
return makeParserResult(
33683368
status,
33693369
new (Context) MacroExpansionExpr(
3370-
poundLoc, macroNameRef, macroNameLoc, leftAngleLoc,
3370+
CurDeclContext, poundLoc, macroNameRef, macroNameLoc, leftAngleLoc,
33713371
Context.AllocateCopy(genericArgs), rightAngleLoc, argList));
33723372
}
33733373

lib/Sema/CSApply.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2983,7 +2983,7 @@ namespace {
29832983
ConcreteDeclRef macroRef = resolveConcreteDeclRef(macro, locator);
29842984
if (auto newExpr = expandMacroExpr(dc, expr, macroRef, expandedType)) {
29852985
auto expansion = new (ctx) MacroExpansionExpr(
2986-
expr->getStartLoc(), DeclNameRef(macro->getName()),
2986+
dc, expr->getStartLoc(), DeclNameRef(macro->getName()),
29872987
DeclNameLoc(expr->getLoc()), SourceLoc(), { }, SourceLoc(),
29882988
nullptr, /*isImplicit=*/true, expandedType);
29892989
expansion->setMacroRef(macroRef);

lib/Sema/TypeCheckStmt.cpp

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ using namespace swift;
5858
#define DEBUG_TYPE "TypeCheckStmt"
5959

6060
namespace {
61-
class ContextualizeClosures : public ASTWalker {
61+
class ContextualizeClosuresAndMacros : public ASTWalker {
6262
DeclContext *ParentDC;
6363
public:
64-
ContextualizeClosures(DeclContext *parent) : ParentDC(parent) {}
64+
ContextualizeClosuresAndMacros(DeclContext *parent) : ParentDC(parent) {}
6565

6666
PreWalkResult<Expr *> walkToExprPre(Expr *E) override {
6767
// Autoclosures need to be numbered and potentially reparented.
@@ -105,7 +105,7 @@ namespace {
105105
// we need to walk into it with a new sequence.
106106
// Otherwise, it'll have been separately type-checked.
107107
if (!CE->isSeparatelyTypeChecked())
108-
CE->getBody()->walk(ContextualizeClosures(CE));
108+
CE->getBody()->walk(ContextualizeClosuresAndMacros(CE));
109109

110110
TypeChecker::computeCaptures(CE);
111111
return Action::SkipChildren(E);
@@ -116,6 +116,11 @@ namespace {
116116
if (DAE->isCallerSide() && DAE->getParamDecl()->isAutoClosure())
117117
DAE->getCallerSideDefaultExpr()->walk(*this);
118118

119+
// Macro expansion expressions require a DeclContext as well.
120+
if (auto macroExpansion = dyn_cast<MacroExpansionExpr>(E)) {
121+
macroExpansion->setDeclContext(ParentDC);
122+
}
123+
119124
return Action::Continue(E);
120125
}
121126

@@ -201,12 +206,12 @@ namespace {
201206
} // end anonymous namespace
202207

203208
void TypeChecker::contextualizeInitializer(Initializer *DC, Expr *E) {
204-
ContextualizeClosures CC(DC);
209+
ContextualizeClosuresAndMacros CC(DC);
205210
E->walk(CC);
206211
}
207212

208213
void TypeChecker::contextualizeTopLevelCode(TopLevelCodeDecl *TLCD) {
209-
ContextualizeClosures CC(TLCD);
214+
ContextualizeClosuresAndMacros CC(TLCD);
210215
if (auto *body = TLCD->getBody())
211216
body->walk(CC);
212217
}
@@ -225,6 +230,10 @@ namespace {
225230

226231
/// Local declaration discriminators.
227232
llvm::SmallDenseMap<Identifier, unsigned> DeclDiscriminators;
233+
234+
/// Macro expansion discriminator.
235+
unsigned NextMacroExpansionDiscriminator = 0;
236+
228237
public:
229238
SetLocalDiscriminators(
230239
unsigned initialDiscriminator = 0
@@ -281,6 +290,28 @@ namespace {
281290
return Action::SkipChildren(E);
282291
}
283292

293+
// Macro expansion expressions get a discriminator.
294+
if (auto macroExpansion = dyn_cast<MacroExpansionExpr>(E)) {
295+
if (macroExpansion->getRawDiscriminator() ==
296+
MacroExpansionExpr::InvalidDiscriminator) {
297+
macroExpansion->setDiscriminator(NextMacroExpansionDiscriminator++);
298+
}
299+
300+
// Walk the arguments.
301+
if (auto args = macroExpansion->getArgs())
302+
args->walk(*this);
303+
304+
// If there is a rewritten expression, walk it with a fresh macro
305+
// discriminator.
306+
if (auto rewritten = macroExpansion->getRewritten()) {
307+
llvm::SaveAndRestore<unsigned> savedMacroDiscriminator(
308+
NextMacroExpansionDiscriminator, 0u);
309+
rewritten->walk(*this);
310+
}
311+
312+
return Action::SkipChildren(E);
313+
}
314+
284315
// Caller-side default arguments need their @autoclosures checked.
285316
if (auto *DAE = dyn_cast<DefaultArgumentExpr>(E))
286317
if (DAE->isCallerSide() && DAE->getParamDecl()->isAutoClosure())
@@ -311,6 +342,14 @@ namespace {
311342
setLocalDiscriminator(valueDecl);
312343
}
313344

345+
// If we have a macro expansion declaration, assign a discriminator to it.
346+
if (auto macroExpansion = dyn_cast<MacroExpansionDecl>(D)) {
347+
if (macroExpansion->getRawDiscriminator() ==
348+
MacroExpansionDecl::InvalidDiscriminator) {
349+
macroExpansion->setDiscriminator(NextMacroExpansionDiscriminator++);
350+
}
351+
}
352+
314353
// But we do want to walk into the initializers of local
315354
// variables.
316355
return Action::VisitChildrenIf(isa<PatternBindingDecl>(D));
@@ -991,7 +1030,7 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
9911030
/// Type-check an entire function body.
9921031
bool typeCheckBody(BraceStmt *&S) {
9931032
bool HadError = typeCheckStmt(S);
994-
S->walk(ContextualizeClosures(DC));
1033+
S->walk(ContextualizeClosuresAndMacros(DC));
9951034
return HadError;
9961035
}
9971036

@@ -2395,7 +2434,7 @@ TypeCheckFunctionBodyRequest::evaluate(Evaluator &evaluator,
23952434
body = *optBody;
23962435
alreadyTypeChecked = true;
23972436

2398-
body->walk(ContextualizeClosures(AFD));
2437+
body->walk(ContextualizeClosuresAndMacros(AFD));
23992438
}
24002439
} else if (func->hasSingleExpressionBody() &&
24012440
func->getResultInterfaceType()->isVoid()) {

0 commit comments

Comments
 (0)