7
7
#include < memory>
8
8
#include < unistd.h>
9
9
#include < unordered_set>
10
+ #include < queue>
10
11
11
12
#include < swift/AST/SourceFile.h>
12
13
#include < swift/Basic/FileTypes.h>
@@ -51,6 +52,18 @@ static void archiveFile(const SwiftExtractorConfiguration& config, swift::Source
51
52
}
52
53
}
53
54
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
+
54
67
static void extractDeclarations (const SwiftExtractorConfiguration& config,
55
68
llvm::ArrayRef<swift::Decl*> topLevelDecls,
56
69
swift::CompilerInstance& compiler,
@@ -60,7 +73,8 @@ static void extractDeclarations(const SwiftExtractorConfiguration& config,
60
73
// the same input file(s)
61
74
// We are using PID to avoid concurrent access
62
75
// 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);
64
78
std::string tempTrapName = filename.str () + ' .' + std::to_string (getpid ()) + " .trap" ;
65
79
llvm::SmallString<PATH_MAX> tempTrapPath (config.tempTrapDir );
66
80
llvm::sys::path::append (tempTrapPath, tempTrapName);
@@ -144,7 +158,31 @@ void codeql::extractSwiftFiles(const SwiftExtractorConfiguration& config,
144
158
}
145
159
}
146
160
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;
147
166
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) {
148
186
// We only extract system and builtin modules here as the other "user" modules can be built
149
187
// during the build process and then re-used at a later stage. In this case, we extract the
150
188
// user code twice: once during the module build in a form of a source file, and then as
0 commit comments