Skip to content

Commit 0b78b9a

Browse files
committed
[Macros] Ensure that macro expansion parsing has appropriate context.
The parser needs context to do completely reasonable things like... parse closures.
1 parent e550944 commit 0b78b9a

File tree

5 files changed

+69
-28
lines changed

5 files changed

+69
-28
lines changed

include/swift/Parse/LocalContext.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,12 @@ class LocalContext {
5858
/// True if we saw any anonymous closures. This is useful when
5959
/// parsing an initializer context, because such contexts only
6060
/// need to exist if the initializer contains closures.
61-
bool hasClosures() const { return NextClosureDiscriminator != 0; }
61+
bool hasClosures() const { return NextClosureDiscriminator != 0; }
62+
63+
/// Override the next closure discriminator value.
64+
void overrideNextClosureDiscriminator(unsigned discriminator) {
65+
NextClosureDiscriminator = discriminator;
66+
}
6267
};
6368

6469
/// Information associated with parsing the top-level context.

lib/Sema/DebuggerTestingTransform.cpp

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -32,36 +32,31 @@
3232

3333
using namespace swift;
3434

35-
namespace {
35+
ASTWalker::PostWalkResult<Expr *>
36+
DiscriminatorFinder::walkToExprPost(Expr *E) {
37+
auto *ACE = dyn_cast<AbstractClosureExpr>(E);
38+
if (!ACE)
39+
return Action::Continue(E);
3640

37-
/// Find available closure discriminators.
38-
///
39-
/// The parser typically takes care of assigning unique discriminators to
40-
/// closures, but the parser is unavailable during semantic analysis.
41-
class DiscriminatorFinder : public ASTWalker {
42-
unsigned NextDiscriminator = 0;
41+
unsigned Discriminator = ACE->getDiscriminator();
42+
assert(Discriminator != AbstractClosureExpr::InvalidDiscriminator &&
43+
"Existing closures should have valid discriminators");
44+
if (Discriminator >= NextDiscriminator)
45+
NextDiscriminator = Discriminator + 1;
46+
if (FirstDiscriminator == AbstractClosureExpr::InvalidDiscriminator ||
47+
Discriminator < FirstDiscriminator)
48+
FirstDiscriminator = Discriminator;
4349

44-
public:
45-
PostWalkResult<Expr *> walkToExprPost(Expr *E) override {
46-
auto *ACE = dyn_cast<AbstractClosureExpr>(E);
47-
if (!ACE)
48-
return Action::Continue(E);
49-
50-
unsigned Discriminator = ACE->getDiscriminator();
51-
assert(Discriminator != AbstractClosureExpr::InvalidDiscriminator &&
52-
"Existing closures should have valid discriminators");
53-
if (Discriminator >= NextDiscriminator)
54-
NextDiscriminator = Discriminator + 1;
55-
return Action::Continue(E);
56-
}
50+
return Action::Continue(E);
51+
}
5752

58-
// Get the next available closure discriminator.
59-
unsigned getNextDiscriminator() {
60-
if (NextDiscriminator == AbstractClosureExpr::InvalidDiscriminator)
61-
llvm::report_fatal_error("Out of valid closure discriminators");
62-
return NextDiscriminator++;
63-
}
64-
};
53+
unsigned DiscriminatorFinder::getNextDiscriminator() {
54+
if (NextDiscriminator == AbstractClosureExpr::InvalidDiscriminator)
55+
llvm::report_fatal_error("Out of valid closure discriminators");
56+
return NextDiscriminator++;
57+
}
58+
59+
namespace {
6560

6661
/// Instrument decls with sanity-checks which the debugger can evaluate.
6762
class DebuggerTestingTransform : public ASTWalker {

lib/Sema/TypeCheckMacros.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,26 @@ Expr *swift::expandMacroExpr(
217217
// Parse the expression.
218218
Parser parser(macroBufferID, *macroSourceFile, &ctx.Diags, nullptr, nullptr);
219219
parser.consumeTokenWithoutFeedingReceiver();
220+
221+
// Set up a "local context" for parsing, so that we have a source of
222+
// closure and local-variable discriminators.
223+
LocalContext tempContext{};
224+
parser.CurDeclContext = dc;
225+
parser.CurLocalContext = &tempContext;
226+
{
227+
DiscriminatorFinder finder;
228+
expr->walk(finder);
229+
230+
unsigned closureDiscriminator;
231+
if (finder.getFirstDiscriminator() ==
232+
AbstractClosureExpr::InvalidDiscriminator)
233+
closureDiscriminator = 0;
234+
else
235+
closureDiscriminator = finder.getFirstDiscriminator() + 1;
236+
237+
tempContext.overrideNextClosureDiscriminator(closureDiscriminator);
238+
}
239+
220240
auto parsedResult = parser.parseExpr(diag::expected_macro_expansion_expr);
221241
if (parsedResult.isParseError() || parsedResult.isNull()) {
222242
// Tack on a note to say where we expanded the macro from?

lib/Sema/TypeChecker.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,22 @@ diagnoseAndRemoveAttr(const Decl *D, const DeclAttribute *attr,
14991499
return diagnoseAttrWithRemovalFixIt(D, attr, std::forward<ArgTypes>(Args)...);
15001500
}
15011501

1502+
/// Look for closure discriminators within an AST.
1503+
class DiscriminatorFinder : public ASTWalker {
1504+
unsigned FirstDiscriminator = AbstractClosureExpr::InvalidDiscriminator;
1505+
unsigned NextDiscriminator = 0;
1506+
1507+
public:
1508+
PostWalkResult<Expr *> walkToExprPost(Expr *E) override;
1509+
1510+
// Get the next available closure discriminator.
1511+
unsigned getNextDiscriminator();
1512+
1513+
unsigned getFirstDiscriminator() const {
1514+
return FirstDiscriminator;
1515+
}
1516+
};
1517+
15021518
} // end namespace swift
15031519

15041520
#endif

test/Macros/macros.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,9 @@ func test(a: Int, b: Int) {
77
// CHECK: macro_expansion_expr type='(Int, String)'{{.*}}name=stringify
88
// CHECK-NEXT: argument_list
99
// CHECK: tuple_expr type='(Int, String)' location=Macro expansion of #stringify
10+
11+
let (b, s2) = #stringify({ () -> Bool in return true })
12+
// CHECK: macro_expansion_expr type='(() -> Bool, String)'{{.*}}name=stringify
13+
// CHECK-NEXT: argument_list
14+
// CHECK: tuple_expr type='(() -> Bool, String)' location=Macro expansion of #stringify
1015
}

0 commit comments

Comments
 (0)