77#include < memory>
88#include < unistd.h>
99#include < unordered_set>
10+ #include < queue>
1011
1112#include < swift/AST/SourceFile.h>
1213#include < swift/Basic/FileTypes.h>
@@ -51,6 +52,18 @@ static void archiveFile(const SwiftExtractorConfiguration& config, swift::Source
5152 }
5253}
5354
55+ static std::string getTrapFilename (swift::ModuleDecl& module , swift::SourceFile* primaryFile) {
56+ if (primaryFile) {
57+ return primaryFile->getFilename ().str ();
58+ }
59+ // Several modules with different name might come from .pcm (clang module) files
60+ // In this case we want to differentiate them
61+ std::string filename = module .getModuleFilename ().str ();
62+ filename += " -" ;
63+ filename += module .getName ().str ();
64+ return filename;
65+ }
66+
5467static void extractDeclarations (const SwiftExtractorConfiguration& config,
5568 llvm::ArrayRef<swift::Decl*> topLevelDecls,
5669 swift::CompilerInstance& compiler,
@@ -60,7 +73,8 @@ static void extractDeclarations(const SwiftExtractorConfiguration& config,
6073 // the same input file(s)
6174 // We are using PID to avoid concurrent access
6275 // TODO: find a more robust approach to avoid collisions?
63- llvm::StringRef filename = primaryFile ? primaryFile->getFilename () : module .getModuleFilename ();
76+ auto name = getTrapFilename (module , primaryFile);
77+ llvm::StringRef filename (name);
6478 std::string tempTrapName = filename.str () + ' .' + std::to_string (getpid ()) + " .trap" ;
6579 llvm::SmallString<PATH_MAX> tempTrapPath (config.tempTrapDir );
6680 llvm::sys::path::append (tempTrapPath, tempTrapName);
@@ -144,7 +158,31 @@ void codeql::extractSwiftFiles(const SwiftExtractorConfiguration& config,
144158 }
145159 }
146160
161+ // getASTContext().getLoadedModules() does not provide all the modules available within the
162+ // program.
163+ // We need to iterate over all the imported modules (recursively) to see the whole "universe."
164+ std::unordered_set<swift::ModuleDecl*> allModules;
165+ std::queue<swift::ModuleDecl*> worklist;
147166 for (auto & [_, module ] : compiler.getASTContext ().getLoadedModules ()) {
167+ worklist.push (module );
168+ allModules.insert (module );
169+ }
170+
171+ while (!worklist.empty ()) {
172+ auto module = worklist.front ();
173+ worklist.pop ();
174+ llvm::SmallVector<swift::ImportedModule> importedModules;
175+ // TODO: we may need more than just Exported ones
176+ module ->getImportedModules (importedModules, swift::ModuleDecl::ImportFilterKind::Exported);
177+ for (auto & imported : importedModules) {
178+ if (allModules.count (imported.importedModule ) == 0 ) {
179+ worklist.push (imported.importedModule );
180+ allModules.insert (imported.importedModule );
181+ }
182+ }
183+ }
184+
185+ for (auto & module : allModules) {
148186 // We only extract system and builtin modules here as the other "user" modules can be built
149187 // during the build process and then re-used at a later stage. In this case, we extract the
150188 // user code twice: once during the module build in a form of a source file, and then as
0 commit comments