Skip to content

Commit 0d117c1

Browse files
committed
Don't Mutate ModuleDecl's File List When Creating Synthesized Files
See #59144 for more on why this is a bad idea. Patch out the synthesized file unit accessor to only clear the source cache, then patch up all the places that were assuming they could iterate over the module's file list and see synthesized files. rdar://94164512
1 parent 1c76e22 commit 0d117c1

File tree

6 files changed

+34
-29
lines changed

6 files changed

+34
-29
lines changed

include/swift/AST/FileUnit.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,6 @@ class FileUnit : public DeclContext, public ASTAllocated<FileUnit> {
5757

5858
/// Returns the synthesized file for this source file, creating one and
5959
/// inserting it into the module if it does not exist.
60-
///
61-
/// \warning Because this function mutates the parent module's list of files,
62-
/// it will invalidate the iterators of any upstream callers of
63-
/// \c ModuleDecl::getFiles().
6460
SynthesizedFileUnit &getOrCreateSynthesizedFile();
6561

6662
/// Look up a (possibly overloaded) value set at top-level scope

include/swift/AST/Module.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,15 @@ class ModuleDecl
317317
return { Files.begin(), Files.size() };
318318
}
319319

320+
/// Add the given file to this module.
321+
///
322+
/// FIXME: Remove this function from public view. Modules never need to add
323+
/// files once they are created.
324+
///
325+
/// \warning There are very few safe points to call this function once a
326+
/// \c ModuleDecl has been created. If you find yourself needing to insert
327+
/// a file in the middle of e.g. semantic analysis, use a \c
328+
/// SynthesizedFileUnit instead.
320329
void addFile(FileUnit &newFile);
321330

322331
/// Creates a map from \c #filePath strings to corresponding \c #fileID

lib/AST/Module.cpp

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -320,13 +320,13 @@ SourceLookupCache::SourceLookupCache(const ModuleDecl &M) {
320320
FrontendStatsTracer tracer(M.getASTContext().Stats,
321321
"module-populate-cache");
322322
for (const FileUnit *file : M.getFiles()) {
323-
if (auto *SFU = dyn_cast<SynthesizedFileUnit>(file)) {
324-
addToUnqualifiedLookupCache(SFU->getTopLevelDecls(), false);
325-
continue;
326-
}
327323
auto *SF = cast<SourceFile>(file);
328324
addToUnqualifiedLookupCache(SF->getTopLevelDecls(), false);
329325
addToUnqualifiedLookupCache(SF->getHoistedDecls(), false);
326+
327+
if (auto *SFU = file->getSynthesizedFile()) {
328+
addToUnqualifiedLookupCache(SFU->getTopLevelDecls(), false);
329+
}
330330
}
331331
}
332332

@@ -548,9 +548,13 @@ SourceFile *CodeCompletionFileRequest::evaluate(Evaluator &evaluator,
548548
llvm_unreachable("Couldn't find the completion file?");
549549
}
550550

551-
#define FORWARD(name, args) \
552-
for (const FileUnit *file : getFiles()) \
553-
file->name args;
551+
#define FORWARD(name, args) \
552+
for (const FileUnit *file : getFiles()) { \
553+
file->name args; \
554+
if (auto *synth = file->getSynthesizedFile()) { \
555+
synth->name args; \
556+
} \
557+
}
554558

555559
SourceLookupCache &ModuleDecl::getSourceLookupCache() const {
556560
if (!Cache) {
@@ -3064,16 +3068,9 @@ SynthesizedFileUnit &FileUnit::getOrCreateSynthesizedFile() {
30643068
return *thisSynth;
30653069
SynthesizedFile = new (getASTContext()) SynthesizedFileUnit(*this);
30663070
SynthesizedFileAndKind.setPointer(SynthesizedFile);
3067-
// FIXME: Mutating the module in-flight is not a good idea. Any
3068-
// callers above us in the stack that are iterating over
3069-
// the module's files will have their iterators invalidated. There's
3070-
// a strong chance that whatever analysis led to this function being
3071-
// called is doing just that!
3072-
//
3073-
// Instead we ought to just call ModuleDecl::clearLookupCache() here
3074-
// and patch out the places looking for synthesized files hanging off of
3075-
// source files.
3076-
getParentModule()->addFile(*SynthesizedFile);
3071+
// Rebuild the source lookup caches now that we have a synthesized file
3072+
// full of declarations to look into.
3073+
getParentModule()->clearLookupCache();
30773074
}
30783075
return *SynthesizedFile;
30793076
}

lib/IRGen/IRGen.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,8 +1096,9 @@ GeneratedModule IRGenRequest::evaluate(Evaluator &evaluator,
10961096
for (auto *file : filesToEmit) {
10971097
if (auto *nextSF = dyn_cast<SourceFile>(file)) {
10981098
IGM.emitSourceFile(*nextSF);
1099-
} else if (auto *nextSFU = dyn_cast<SynthesizedFileUnit>(file)) {
1100-
IGM.emitSynthesizedFileUnit(*nextSFU);
1099+
if (auto *synthSFU = file->getSynthesizedFile()) {
1100+
IGM.emitSynthesizedFileUnit(*synthSFU);
1101+
}
11011102
} else {
11021103
file->collectLinkLibraries([&IGM](LinkLibrary LinkLib) {
11031104
IGM.addLinkLibrary(LinkLib);
@@ -1341,9 +1342,10 @@ static void performParallelIRGeneration(IRGenDescriptor desc) {
13411342
if (auto *SF = dyn_cast<SourceFile>(File)) {
13421343
CurrentIGMPtr IGM = irgen.getGenModule(SF);
13431344
IGM->emitSourceFile(*SF);
1344-
} else if (auto *nextSFU = dyn_cast<SynthesizedFileUnit>(File)) {
1345-
CurrentIGMPtr IGM = irgen.getGenModule(nextSFU);
1346-
IGM->emitSynthesizedFileUnit(*nextSFU);
1345+
if (auto *synthSFU = File->getSynthesizedFile()) {
1346+
CurrentIGMPtr IGM = irgen.getGenModule(synthSFU);
1347+
IGM->emitSynthesizedFileUnit(*synthSFU);
1348+
}
13471349
} else {
13481350
File->collectLinkLibraries([&](LinkLibrary LinkLib) {
13491351
irgen.getPrimaryIGM()->addLinkLibrary(LinkLib);

lib/IRGen/IRGenRequests.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,6 @@ TinyPtrVector<FileUnit *> IRGenDescriptor::getFilesToEmit() const {
6868
TinyPtrVector<FileUnit *> files;
6969
files.push_back(primary);
7070

71-
if (auto *synthesizedFile = primary->getSynthesizedFile())
72-
files.push_back(synthesizedFile);
73-
7471
return files;
7572
}
7673

lib/TBDGen/TBDGen.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,6 +1234,10 @@ void TBDGenVisitor::visit(const TBDGenDescriptor &desc) {
12341234
llvm::for_each(Modules, [&](ModuleDecl *M) {
12351235
for (auto *file : M->getFiles()) {
12361236
visitFile(file);
1237+
1238+
// Visit synthesized file, if it exists.
1239+
if (auto *synthesizedFile = file->getSynthesizedFile())
1240+
visitFile(synthesizedFile);
12371241
}
12381242
});
12391243
}

0 commit comments

Comments
 (0)