Skip to content

Commit 0407610

Browse files
committed
[Macros] Don't parse the macro expansion buffer twice.
Each macro expansion buffer was getting parsed twice: once by ParseSourceFileRequest (which is used by unqualified name lookup) and once to parse the expression when type-checking the expanded macro. This meant that the same code had two ASTs. Hilarity ensures. Stop directly invoking the parser on macro-expanded code. Instead, go through ParseSourceFileRequest *as is always the right way*, and dig out the expression we want.
1 parent c1a85c1 commit 0407610

File tree

6 files changed

+35
-22
lines changed

6 files changed

+35
-22
lines changed

include/swift/Basic/SourceManager.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323

2424
namespace swift {
2525

26+
class DeclContext;
27+
2628
/// Augments a buffer that was created specifically to hold generated source
2729
/// code with the reasons for it being generated.
2830
class GeneratedSourceInfo {
@@ -53,8 +55,11 @@ class GeneratedSourceInfo {
5355
/// generated source, but it will never be from a different buffer.
5456
SourceRange generatedSourceRange;
5557

56-
/// The opaque pointer for an ASTNode.
58+
/// The opaque pointer for an ASTNode for which this buffer was generated.
5759
void *astNode;
60+
61+
/// The declaration context in which this buffer logically resides.
62+
DeclContext *declContext;
5863
};
5964

6065
/// This class manages and owns source buffers.

lib/IDETool/CompileInstance.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,8 @@ void retypeCheckFunctionBody(AbstractFunctionDecl *func,
196196
*func->getParentSourceFile()->getBufferID(),
197197
func->getOriginalBodySourceRange(),
198198
newRange,
199-
func
199+
func,
200+
nullptr
200201
}
201202
);
202203
func->setBodyToBeReparsed(newRange);

lib/IDETool/IDEInspectionInstance.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,8 @@ bool IDEInspectionInstance::performCachedOperationIfPossible(
349349
*AFD->getParentSourceFile()->getBufferID(),
350350
AFD->getOriginalBodySourceRange(),
351351
newBodyRange,
352-
AFD
352+
AFD,
353+
nullptr
353354
}
354355
);
355356

lib/Parse/ParseRequests.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,14 @@ SourceFileParsingResult ParseSourceFileRequest::evaluate(Evaluator &evaluator,
164164
Parser parser(*bufferID, *SF, /*SIL*/ nullptr, state);
165165
PrettyStackTraceParser StackTrace(parser);
166166

167+
// If the buffer is generated source information that is conceptually within
168+
// a particular declaration context, use that for the parser's declaration
169+
// context instead of the source file.
170+
if (auto generatedInfo = ctx.SourceMgr.getGeneratedSourceInfo(*bufferID)) {
171+
if (generatedInfo->declContext)
172+
parser.CurDeclContext = generatedInfo->declContext;
173+
}
174+
167175
SmallVector<ASTNode, 128> items;
168176
parser.parseTopLevelItems(items);
169177

lib/Sema/TypeCheckMacros.cpp

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
#include "swift/Basic/StringExtras.h"
3030
#include "swift/Demangling/Demangler.h"
3131
#include "swift/Parse/Lexer.h"
32-
#include "swift/Parse/Parser.h"
3332
#include "swift/Subsystems.h"
3433

3534
using namespace swift;
@@ -129,12 +128,8 @@ Expr *swift::expandMacroExpr(
129128
ASTContext &ctx = dc->getASTContext();
130129
SourceManager &sourceMgr = ctx.SourceMgr;
131130

132-
// FIXME: Introduce a more robust way to ensure that we can get the "exported"
133-
// source file for a given context. If it's within a macro expansion, it
134-
// may not have a C++ SourceFile, but will have a Syntax tree.
135-
//
136-
// FIXME^2: And find a better name for "exportedSourceFile".
137-
auto sourceFile = dc->getParentSourceFile();
131+
auto moduleDecl = dc->getParentModule();
132+
auto sourceFile = moduleDecl->getSourceFileContainingLocation(expr->getLoc());
138133
if (!sourceFile)
139134
return nullptr;
140135

@@ -225,7 +220,8 @@ Expr *swift::expandMacroExpr(
225220
*sourceFile->getBufferID(),
226221
expr->getSourceRange(),
227222
SourceRange(macroBufferRange.getStart(), macroBufferRange.getEnd()),
228-
ASTNode(expr).getOpaqueValue()
223+
ASTNode(expr).getOpaqueValue(),
224+
dc
229225
};
230226
sourceMgr.setGeneratedSourceInfo(macroBufferID, sourceInfo);
231227
free((void*)evaluatedSource.data());
@@ -236,24 +232,22 @@ Expr *swift::expandMacroExpr(
236232
*dc->getParentModule(), SourceFileKind::MacroExpansion, macroBufferID,
237233
/*parsingOpts=*/{}, /*isPrimary=*/false);
238234

239-
// Parse the expression.
240-
Parser parser(macroBufferID, *macroSourceFile, &ctx.Diags, nullptr, nullptr);
241-
parser.consumeTokenWithoutFeedingReceiver();
242-
243-
// Set up a "local context" for parsing, so that we have a source of
244-
// closure and local-variable discriminators.
245-
parser.CurDeclContext = dc;
235+
// Retrieve the parsed expression from the list of top-level items.
236+
auto topLevelItems = macroSourceFile->getTopLevelItems();
237+
Expr *expandedExpr = nullptr;
238+
if (topLevelItems.size() == 1) {
239+
expandedExpr = topLevelItems.front().dyn_cast<Expr *>();
240+
}
246241

247-
auto parsedResult = parser.parseExpr(diag::expected_macro_expansion_expr);
248-
if (parsedResult.isParseError() || parsedResult.isNull()) {
249-
// Tack on a note to say where we expanded the macro from?
242+
if (!expandedExpr) {
243+
ctx.Diags.diagnose(
244+
macroBufferRange.getStart(), diag::expected_macro_expansion_expr);
250245
return nullptr;
251246
}
252247

253248
// Type-check the expanded expression.
254249
// FIXME: Would like to pass through type checking options like "discarded"
255250
// that are captured by TypeCheckExprOptions.
256-
Expr *expandedExpr = parsedResult.get();
257251
constraints::ContextualTypeInfo contextualType {
258252
TypeLoc::withoutLoc(expandedType),
259253
// FIXME: Add a contextual type purpose for macro expansion.

test/Macros/macro_expand.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ struct Outer {
4949
var value: Int = 0
5050
func test() {
5151
_ = #stringify(1 + value)
52+
53+
_ = #stringify({ x in
54+
x + 1
55+
})
5256
}
5357
}
5458

0 commit comments

Comments
 (0)