@@ -307,7 +307,6 @@ public func funcB() { }\n"));
307307 for (auto &command : CommandStr)
308308 Command.push_back (command.c_str ());
309309
310- auto ScanDiagnosticConsumer = std::make_shared<DependencyScanDiagnosticCollector>();
311310
312311 auto DependenciesOrErr = ScannerTool.getDependencies (Command, {}, {});
313312
@@ -329,3 +328,78 @@ public func funcB() { }\n"));
329328 ASSERT_TRUE (Dependencies->dependencies ->modules [0 ]->link_libraries ->count == 0 );
330329 swiftscan_dependency_graph_dispose (Dependencies);
331330}
331+
332+ TEST_F (ScanTest, TestStressConcurrentDiagnostics) {
333+ SmallString<256 > tempDir;
334+ ASSERT_FALSE (llvm::sys::fs::createUniqueDirectory (" ScanTest.TestStressConcurrentDiagnostics" , tempDir));
335+ SWIFT_DEFER { llvm::sys::fs::remove_directories (tempDir); };
336+
337+ // Create includes
338+ std::string IncludeDirPath = createFilename (tempDir, " include" );
339+ ASSERT_FALSE (llvm::sys::fs::create_directory (IncludeDirPath));
340+ std::string CHeadersDirPath = createFilename (IncludeDirPath, " CHeaders" );
341+ ASSERT_FALSE (llvm::sys::fs::create_directory (CHeadersDirPath));
342+
343+ // Create test input file
344+ std::string TestPathStr = createFilename (tempDir, " foo.swift" );
345+
346+ // Create imported module C modulemap/headers
347+ std::string modulemapContent = " " ;
348+ std::string testFileContent = " " ;
349+ for (int i = 0 ; i < 100 ; ++i) {
350+ std::string headerName = " A_" + std::to_string (i) + " .h" ;
351+ std::string headerContent = " void funcA_" + std::to_string (i) + " (void);" ;
352+ ASSERT_FALSE (
353+ emitFileWithContents (CHeadersDirPath, headerName, headerContent));
354+
355+ std::string moduleMapEntry = " module A_" + std::to_string (i) + " {\n " ;
356+ moduleMapEntry.append (" header \" A_" + std::to_string (i) + " .h\"\n " );
357+ moduleMapEntry.append (" export *\n " );
358+ moduleMapEntry.append (" }\n " );
359+ modulemapContent.append (moduleMapEntry);
360+ testFileContent.append (" import A_" + std::to_string (i) + " \n " );
361+ }
362+
363+ ASSERT_FALSE (emitFileWithContents (tempDir, " foo.swift" , testFileContent));
364+ ASSERT_FALSE (
365+ emitFileWithContents (CHeadersDirPath, " module.modulemap" , modulemapContent));
366+
367+ // Paths to shims and stdlib
368+ llvm::SmallString<128 > ShimsLibDir = StdLibDir;
369+ llvm::sys::path::append (ShimsLibDir, " shims" );
370+ auto Target = llvm::Triple (llvm::sys::getDefaultTargetTriple ());
371+ llvm::sys::path::append (StdLibDir, getPlatformNameForTriple (Target));
372+
373+ std::vector<std::string> BaseCommandStrArr = {
374+ TestPathStr,
375+ std::string (" -I " ) + CHeadersDirPath,
376+ std::string (" -I " ) + StdLibDir.str ().str (),
377+ std::string (" -I " ) + ShimsLibDir.str ().str (),
378+ // Pass in a flag which will cause every instantiation of
379+ // the clang scanner to fail with "unknown argument"
380+ " -Xcc" ,
381+ " -foobar"
382+ };
383+
384+ std::vector<std::string> CommandStr = BaseCommandStrArr;
385+ CommandStr.push_back (" -module-name" );
386+ CommandStr.push_back (" testConcurrentDiags" );
387+
388+ // On Windows we need to add an extra escape for path separator characters because otherwise
389+ // the command line tokenizer will treat them as escape characters.
390+ for (size_t i = 0 ; i < CommandStr.size (); ++i) {
391+ std::replace (CommandStr[i].begin (), CommandStr[i].end (), ' \\ ' , ' /' );
392+ }
393+ std::vector<const char *> Command;
394+ for (auto &command : CommandStr)
395+ Command.push_back (command.c_str ());
396+
397+ auto DependenciesOrErr = ScannerTool.getDependencies (Command, {}, {});
398+
399+ // Ensure a hollow output with diagnostic info is produced
400+ ASSERT_FALSE (DependenciesOrErr.getError ());
401+ auto Dependencies = DependenciesOrErr.get ();
402+ auto Diagnostics = Dependencies->diagnostics ;
403+ ASSERT_TRUE (Diagnostics->count > 100 );
404+ swiftscan_dependency_graph_dispose (Dependencies);
405+ }
0 commit comments