@@ -182,3 +182,70 @@ export *\n\
182182
183183 swiftscan_dependency_graph_dispose (Dependencies);
184184}
185+
186+ TEST_F (ScanTest, TestModuleDepsHash) {
187+ SmallString<256 > tempDir;
188+ ASSERT_FALSE (llvm::sys::fs::createUniqueDirectory (" ScanTest.TestModuleDepsHash" , tempDir));
189+ SWIFT_DEFER { llvm::sys::fs::remove_directories (tempDir); };
190+
191+ // Create test input file
192+ std::string TestPathStr = createFilename (tempDir, " foo.swift" );
193+ ASSERT_FALSE (emitFileWithContents (tempDir, " foo.swift" , " import A\n " ));
194+
195+ // Create includes
196+ std::string IncludeDirPath = createFilename (tempDir, " include" );
197+ ASSERT_FALSE (llvm::sys::fs::create_directory (IncludeDirPath));
198+ std::string SwiftDirPath = createFilename (IncludeDirPath, " Swift" );
199+ ASSERT_FALSE (llvm::sys::fs::create_directory (SwiftDirPath));
200+
201+ // Create imported module Swift interface files
202+ ASSERT_FALSE (emitFileWithContents (SwiftDirPath, " A.swiftinterface" ,
203+ " // swift-interface-format-version: 1.0\n \
204+ // swift-module-flags: -module-name A\n \
205+ import Swift\n \
206+ public func overlayFuncA() { }\n " ));
207+
208+ // Paths to shims and stdlib
209+ llvm::SmallString<128 > ShimsLibDir = StdLibDir;
210+ llvm::sys::path::append (ShimsLibDir, " shims" );
211+ auto Target = llvm::Triple (llvm::sys::getDefaultTargetTriple ());
212+ llvm::sys::path::append (StdLibDir, getPlatformNameForTriple (Target));
213+
214+ std::vector<std::string> BaseCommandStrArr = {
215+ TestPathStr,
216+ std::string (" -I " ) + SwiftDirPath,
217+ std::string (" -I " ) + StdLibDir.str ().str (),
218+ std::string (" -I " ) + ShimsLibDir.str ().str (),
219+ };
220+
221+ std::vector<std::string> CommandStrArrA = BaseCommandStrArr;
222+ CommandStrArrA.push_back (" -module-name" );
223+ CommandStrArrA.push_back (" A" );
224+ std::vector<std::string> CommandStrArrB = BaseCommandStrArr;
225+ CommandStrArrB.push_back (" -module-name" );
226+ CommandStrArrB.push_back (" B" );
227+
228+ // On Windows we need to add an extra escape for path separator characters because otherwise
229+ // the command line tokenizer will treat them as escape characters.
230+ for (size_t i = 0 ; i < CommandStrArrA.size (); ++i) {
231+ std::replace (CommandStrArrA[i].begin (), CommandStrArrA[i].end (), ' \\ ' , ' /' );
232+ }
233+ std::vector<const char *> CommandA;
234+ for (auto &command : CommandStrArrA) {
235+ CommandA.push_back (command.c_str ());
236+ }
237+
238+ for (size_t i = 0 ; i < CommandStrArrB.size (); ++i) {
239+ std::replace (CommandStrArrB[i].begin (), CommandStrArrB[i].end (), ' \\ ' , ' /' );
240+ }
241+ std::vector<const char *> CommandB;
242+ for (auto &command : CommandStrArrB) {
243+ CommandB.push_back (command.c_str ());
244+ }
245+
246+ auto instanceA = ScannerTool.initCompilerInstanceForScan (CommandA);
247+ auto instanceB = ScannerTool.initCompilerInstanceForScan (CommandB);
248+ // Ensure that scans that only differ in module name have distinct scanning context hashes
249+ ASSERT_NE (instanceA->get ()->getInvocation ().getModuleScanningHash (),
250+ instanceB->get ()->getInvocation ().getModuleScanningHash ());
251+ }
0 commit comments