Skip to content

Commit f467ef4

Browse files
committed
[Source manager] Start tracking generated-source info in the source manager
Establish the relationship for generated sources, whether for macro expansions or (via a small stretch) replacing function bodies with other bodies, in the source manager itself. This makes the information available for diagnostic rendering, and unifies a little bit of the representation, although it isn't used for much yet.
1 parent cb3a24e commit f467ef4

File tree

9 files changed

+132
-27
lines changed

9 files changed

+132
-27
lines changed

include/swift/AST/ASTNode.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,13 @@ namespace swift {
7272
FUNC(Decl)
7373
FUNC(Pattern)
7474
#undef FUNC
75-
75+
76+
static inline ASTNode getFromOpaqueValue(void *ptr) {
77+
ASTNode result;
78+
result.Val = decltype(result.Val)::getFromOpaqueValue(ptr);
79+
return result;
80+
}
81+
7682
SWIFT_DEBUG_DUMP;
7783
void dump(llvm::raw_ostream &OS, unsigned Indent = 0) const;
7884

include/swift/AST/SourceFile.h

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -194,15 +194,6 @@ class SourceFile final : public FileUnit {
194194
friend ASTContext;
195195

196196
public:
197-
/// For source files created to hold the source code created by expanding
198-
/// a macro, this is the AST node that describes the macro expansion.
199-
///
200-
/// The source location of this AST node is the place in the source that
201-
/// triggered the creation of the macro expansion whose resulting source
202-
/// code is in this source file. This field is only valid when
203-
/// the \c SourceFileKind is \c MacroExpansion.
204-
const ASTNode macroExpansion;
205-
206197
/// Appends the given declaration to the end of the top-level decls list. Do
207198
/// not add any additional uses of this function.
208199
void addTopLevelDecl(Decl *d);
@@ -327,8 +318,7 @@ class SourceFile final : public FileUnit {
327318
llvm::StringMap<SourceFilePathInfo> getInfoForUsedFilePaths() const;
328319

329320
SourceFile(ModuleDecl &M, SourceFileKind K, Optional<unsigned> bufferID,
330-
ParsingOptions parsingOpts = {}, bool isPrimary = false,
331-
ASTNode macroExpansion = ASTNode());
321+
ParsingOptions parsingOpts = {}, bool isPrimary = false);
332322

333323
~SourceFile();
334324

@@ -489,6 +479,15 @@ class SourceFile final : public FileUnit {
489479
return BufferID;
490480
}
491481

482+
/// For source files created to hold the source code created by expanding
483+
/// a macro, this is the AST node that describes the macro expansion.
484+
///
485+
/// The source location of this AST node is the place in the source that
486+
/// triggered the creation of the macro expansion whose resulting source
487+
/// code is in this source file. This will only produce a non-null value when
488+
/// the \c SourceFileKind is \c MacroExpansion.
489+
ASTNode getMacroExpansion() const;
490+
492491
/// When this source file is enclosed within another source file, for example
493492
/// because it describes a macro expansion, return the source file it was
494493
/// enclosed in.

include/swift/Basic/SourceManager.h

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,40 @@
2323

2424
namespace swift {
2525

26+
/// Augments a buffer that was created specifically to hold generated source
27+
/// code with the reasons for it being generated.
28+
class GeneratedSourceInfo {
29+
public:
30+
/// The kind of generated source code.
31+
enum Kind {
32+
/// The expansion of a macro.
33+
MacroExpansion,
34+
35+
/// A new function body that is replacing an existing function body.
36+
ReplacedFunctionBody,
37+
} kind;
38+
39+
/// The buffer ID for the enclosing buffer, in which originalSourceRange
40+
/// resides.
41+
unsigned originalBufferID;
42+
43+
/// The source range in the enclosing buffer where this source was generated.
44+
///
45+
/// This could point at a macro expansion or at the implicit location at
46+
/// which source code was generated. Conceptually, one can think of the
47+
/// buffer described by a \c GeneratedSource instance as replacing the
48+
/// code in the \c originalSourceRange.
49+
SourceRange originalSourceRange;
50+
51+
/// The source range in the generated-source buffer where the generated
52+
/// code exists. This might be a subrange of the buffer containing the
53+
/// generated source, but it will never be from a different buffer.
54+
SourceRange generatedSourceRange;
55+
56+
/// The opaque pointer for an ASTNode.
57+
void *astNode;
58+
};
59+
2660
/// This class manages and owns source buffers.
2761
class SourceManager {
2862
public:
@@ -51,7 +85,10 @@ class SourceManager {
5185
/// to speed up stats.
5286
mutable llvm::DenseMap<StringRef, llvm::vfs::Status> StatusCache;
5387

54-
/// Holds replaced ranges. Keys are orignal ranges, and values are new ranges
88+
/// Holds generated source information, indexed by the buffer ID.
89+
llvm::DenseMap<unsigned, GeneratedSourceInfo> GeneratedSourceInfos;
90+
91+
/// Holds replaced ranges. Keys are original ranges, and values are new ranges
5592
/// in different buffers. This is used for code completion and ASTContext
5693
/// reusing compilation.
5794
llvm::DenseMap<SourceRange, SourceRange> ReplacedRanges;
@@ -108,9 +145,12 @@ class SourceManager {
108145
const llvm::DenseMap<SourceRange, SourceRange> &getReplacedRanges() const {
109146
return ReplacedRanges;
110147
}
111-
void setReplacedRange(SourceRange Orig, SourceRange New) {
112-
ReplacedRanges[Orig] = New;
113-
}
148+
149+
/// Set the generated source information associated with a given buffer.
150+
void setGeneratedSourceInfo(unsigned bufferID, GeneratedSourceInfo);
151+
152+
/// Retrieve the generated source information for the given buffer.
153+
Optional<GeneratedSourceInfo> getGeneratedSourceInfo(unsigned bufferID) const;
114154

115155
/// Record the starting source location of a regex literal.
116156
void recordRegexLiteralStartLoc(SourceLoc loc) {

lib/AST/ASTScopeCreation.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ ASTSourceFileScope::ASTSourceFileScope(SourceFile *SF,
248248
ScopeCreator *scopeCreator)
249249
: SF(SF), scopeCreator(scopeCreator) {
250250
if (auto enclosingSF = SF->getEnclosingSourceFile()) {
251-
SourceLoc parentLoc = SF->macroExpansion.getStartLoc();
251+
SourceLoc parentLoc = SF->getMacroExpansion().getStartLoc();
252252
if (auto parentScope = findStartingScopeForLookup(enclosingSF, parentLoc)) {
253253
parentAndWasExpanded.setPointer(const_cast<ASTScopeImpl *>(parentScope));
254254
}

lib/AST/Module.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -877,10 +877,20 @@ void SourceFile::lookupClassMembers(ImportPath::Access accessPath,
877877
cache.lookupClassMembers(accessPath, consumer);
878878
}
879879

880-
SourceFile *SourceFile::getEnclosingSourceFile() const {
880+
ASTNode SourceFile::getMacroExpansion() const {
881881
if (Kind != SourceFileKind::MacroExpansion)
882882
return nullptr;
883883

884+
auto genInfo =
885+
*getASTContext().SourceMgr.getGeneratedSourceInfo(*getBufferID());
886+
return ASTNode::getFromOpaqueValue(genInfo.astNode);
887+
}
888+
889+
SourceFile *SourceFile::getEnclosingSourceFile() const {
890+
auto macroExpansion = getMacroExpansion();
891+
if (!macroExpansion)
892+
return nullptr;
893+
884894
auto sourceLoc = macroExpansion.getStartLoc();
885895
return getParentModule()->getSourceFileContainingLocation(sourceLoc);
886896
}
@@ -3263,17 +3273,13 @@ ModuleDecl::computeFileIDMap(bool shouldDiagnose) const {
32633273

32643274
SourceFile::SourceFile(ModuleDecl &M, SourceFileKind K,
32653275
Optional<unsigned> bufferID,
3266-
ParsingOptions parsingOpts, bool isPrimary,
3267-
ASTNode macroExpansion)
3276+
ParsingOptions parsingOpts, bool isPrimary)
32683277
: FileUnit(FileUnitKind::Source, M), BufferID(bufferID ? *bufferID : -1),
3269-
ParsingOpts(parsingOpts), IsPrimary(isPrimary),
3270-
macroExpansion(macroExpansion), Kind(K) {
3278+
ParsingOpts(parsingOpts), IsPrimary(isPrimary), Kind(K) {
32713279
M.getASTContext().addDestructorCleanup(*this);
32723280

32733281
assert(!IsPrimary || M.isMainModule() &&
32743282
"A primary cannot appear outside the main module");
3275-
assert(macroExpansion.isNull() == (K != SourceFileKind::MacroExpansion) &&
3276-
"Macro expansions always need an expansion node");
32773283

32783284
if (isScriptMode()) {
32793285
bool problem = M.registerEntryPointFile(this, SourceLoc(), None);

lib/Basic/SourceLoc.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,32 @@ StringRef SourceManager::extractText(CharSourceRange Range,
252252
Range.getByteLength());
253253
}
254254

255+
void SourceManager::setGeneratedSourceInfo(
256+
unsigned bufferID, GeneratedSourceInfo info
257+
) {
258+
assert(GeneratedSourceInfos.count(bufferID) == 0);
259+
GeneratedSourceInfos[bufferID] = info;
260+
261+
switch (info.kind) {
262+
case GeneratedSourceInfo::MacroExpansion:
263+
break;
264+
265+
case GeneratedSourceInfo::ReplacedFunctionBody:
266+
// Keep track of the replaced range.
267+
ReplacedRanges[info.originalSourceRange] = info.generatedSourceRange;
268+
break;
269+
}
270+
}
271+
272+
Optional<GeneratedSourceInfo> SourceManager::getGeneratedSourceInfo(
273+
unsigned bufferID
274+
) const {
275+
auto known = GeneratedSourceInfos.find(bufferID);
276+
if (known == GeneratedSourceInfos.end())
277+
return None;
278+
return known->second;
279+
}
280+
255281
Optional<unsigned>
256282
SourceManager::findBufferContainingLocInternal(SourceLoc Loc) const {
257283
assert(Loc.isValid());

lib/IDETool/CompileInstance.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,16 @@ void retypeCheckFunctionBody(AbstractFunctionDecl *func,
189189
SourceRange newRange{rangeStartLoc, rangeEndLoc};
190190

191191
// Reset the body range of the function decl, and re-typecheck it.
192-
origSM.setReplacedRange(func->getOriginalBodySourceRange(), newRange);
192+
origSM.setGeneratedSourceInfo(
193+
sliceBufferID,
194+
GeneratedSourceInfo{
195+
GeneratedSourceInfo::ReplacedFunctionBody,
196+
*func->getParentSourceFile()->getBufferID(),
197+
func->getOriginalBodySourceRange(),
198+
newRange,
199+
func
200+
}
201+
);
193202
func->setBodyToBeReparsed(newRange);
194203
(void)func->getTypecheckedBody();
195204
}

lib/IDETool/IDEInspectionInstance.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,17 @@ bool IDEInspectionInstance::performCachedOperationIfPossible(
342342
newBufferStart.getAdvancedLoc(newInfo.EndOffset));
343343

344344
auto *AFD = cast<AbstractFunctionDecl>(DC);
345-
SM.setReplacedRange(AFD->getOriginalBodySourceRange(), newBodyRange);
345+
SM.setGeneratedSourceInfo(
346+
newBufferID,
347+
GeneratedSourceInfo{
348+
GeneratedSourceInfo::ReplacedFunctionBody,
349+
*AFD->getParentSourceFile()->getBufferID(),
350+
AFD->getOriginalBodySourceRange(),
351+
newBodyRange,
352+
AFD
353+
}
354+
);
355+
346356
AFD->setBodyToBeReparsed(newBodyRange);
347357
oldSF->clearScope();
348358

lib/Sema/TypeCheckMacros.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,13 +220,22 @@ Expr *swift::expandMacroExpr(
220220
auto macroBuffer =
221221
llvm::MemoryBuffer::getMemBufferCopy(evaluatedSource, bufferName);
222222
unsigned macroBufferID = sourceMgr.addNewSourceBuffer(std::move(macroBuffer));
223+
auto macroBufferRange = sourceMgr.getRangeForBuffer(macroBufferID);
224+
GeneratedSourceInfo sourceInfo{
225+
GeneratedSourceInfo::MacroExpansion,
226+
*sourceFile->getBufferID(),
227+
expr->getSourceRange(),
228+
SourceRange(macroBufferRange.getStart(), macroBufferRange.getEnd()),
229+
ASTNode(expr).getOpaqueValue()
230+
};
231+
sourceMgr.setGeneratedSourceInfo(macroBufferID, sourceInfo);
223232
free((void*)evaluatedSource.data());
224233

225234
// Create a source file to hold the macro buffer. This is automatically
226235
// registered with the enclosing module.
227236
auto macroSourceFile = new (ctx) SourceFile(
228237
*dc->getParentModule(), SourceFileKind::MacroExpansion, macroBufferID,
229-
/*parsingOpts=*/{}, /*isPrimary=*/false, expr);
238+
/*parsingOpts=*/{}, /*isPrimary=*/false);
230239

231240
// Parse the expression.
232241
Parser parser(macroBufferID, *macroSourceFile, &ctx.Diags, nullptr, nullptr);

0 commit comments

Comments
 (0)