@@ -41,12 +41,57 @@ struct DependencyScannerServiceOptions {
4141
4242 ScanningOutputFormat getFormat () const ;
4343};
44+
45+ struct CStringsManager {
46+ SmallVector<std::unique_ptr<std::vector<const char *>>> OwnedCStr;
47+ SmallVector<std::unique_ptr<std::vector<std::string>>> OwnedStdStr;
48+
49+ // / Doesn't own the string contents.
50+ CXCStringArray createCStringsRef (ArrayRef<std::string> Strings) {
51+ OwnedCStr.push_back (std::make_unique<std::vector<const char *>>());
52+ std::vector<const char *> &CStrings = *OwnedCStr.back ();
53+ CStrings.reserve (Strings.size ());
54+ for (const auto &String : Strings)
55+ CStrings.push_back (String.c_str ());
56+ return {CStrings.data (), CStrings.size ()};
57+ }
58+
59+ // / Doesn't own the string contents.
60+ CXCStringArray createCStringsRef (const llvm::StringSet<> &StringsUnordered) {
61+ std::vector<StringRef> Strings;
62+
63+ for (auto SI = StringsUnordered.begin (), SE = StringsUnordered.end ();
64+ SI != SE; ++SI)
65+ Strings.push_back (SI->getKey ());
66+
67+ llvm::sort (Strings);
68+
69+ OwnedCStr.push_back (std::make_unique<std::vector<const char *>>());
70+ std::vector<const char *> &CStrings = *OwnedCStr.back ();
71+ CStrings.reserve (Strings.size ());
72+ for (const auto &String : Strings)
73+ CStrings.push_back (String.data ());
74+ return {CStrings.data (), CStrings.size ()};
75+ }
76+
77+ // / Gets ownership of string contents.
78+ CXCStringArray createCStringsOwned (std::vector<std::string> &&Strings) {
79+ OwnedStdStr.push_back (
80+ std::make_unique<std::vector<std::string>>(std::move (Strings)));
81+ return createCStringsRef (*OwnedStdStr.back ());
82+ }
83+ };
84+
85+ struct DependencyScannerService {
86+ DependencyScanningService Service;
87+ CStringsManager StrMgr{};
88+ };
4489} // end anonymous namespace
4590
4691DEFINE_SIMPLE_CONVERSION_FUNCTIONS (DependencyScannerServiceOptions,
4792 CXDependencyScannerServiceOptions)
4893
49- DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DependencyScanningService ,
94+ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DependencyScannerService ,
5095 CXDependencyScannerService)
5196DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DependencyScanningWorker,
5297 CXDependencyScannerWorker)
@@ -127,9 +172,9 @@ clang_experimental_DependencyScannerService_create_v0(CXDependencyMode Format) {
127172 // FIXME: Pass default CASOpts and nullptr as CachingOnDiskFileSystem now.
128173 CASOptions CASOpts;
129174 IntrusiveRefCntPtr<llvm::cas::CachingOnDiskFileSystem> FS;
130- return wrap (new DependencyScanningService (
175+ return wrap (new DependencyScannerService{ DependencyScanningService (
131176 ScanningMode::DependencyDirectivesScan, unwrap (Format), CASOpts,
132- /* CAS=*/ nullptr , /* ActionCache=*/ nullptr , FS));
177+ /* CAS=*/ nullptr , /* ActionCache=*/ nullptr , FS)} );
133178}
134179
135180ScanningOutputFormat DependencyScannerServiceOptions::getFormat () const {
@@ -165,10 +210,10 @@ clang_experimental_DependencyScannerService_create_v1(
165210 FS = llvm::cantFail (
166211 llvm::cas::createCachingOnDiskFileSystem (CAS));
167212 }
168- return wrap (new DependencyScanningService (
213+ return wrap (new DependencyScannerService{ DependencyScanningService (
169214 ScanningMode::DependencyDirectivesScan, Format, unwrap (Opts)->CASOpts ,
170215 std::move (CAS), std::move (Cache), std::move (FS),
171- unwrap (Opts)->OptimizeArgs ));
216+ unwrap (Opts)->OptimizeArgs )} );
172217}
173218
174219void clang_experimental_DependencyScannerService_dispose_v0 (
@@ -177,17 +222,17 @@ void clang_experimental_DependencyScannerService_dispose_v0(
177222}
178223
179224CXDependencyScannerWorker clang_experimental_DependencyScannerWorker_create_v0 (
180- CXDependencyScannerService Service ) {
181- ScanningOutputFormat Format = unwrap (Service )->getFormat ();
225+ CXDependencyScannerService S ) {
226+ ScanningOutputFormat Format = unwrap (S )->Service . getFormat ();
182227 bool IsIncludeTreeOutput = Format == ScanningOutputFormat::IncludeTree ||
183228 Format == ScanningOutputFormat::FullIncludeTree;
184229 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =
185230 llvm::vfs::createPhysicalFileSystem ();
186231 if (IsIncludeTreeOutput)
187- FS = llvm::cas::createCASProvidingFileSystem (unwrap (Service )->getCAS (),
232+ FS = llvm::cas::createCASProvidingFileSystem (unwrap (S )->Service . getCAS (),
188233 std::move (FS));
189234
190- return wrap (new DependencyScanningWorker (* unwrap (Service) , FS));
235+ return wrap (new DependencyScanningWorker (unwrap (S)-> Service , FS));
191236}
192237
193238void clang_experimental_DependencyScannerWorker_dispose_v0 (
@@ -223,46 +268,6 @@ struct DependencyScannerWorkerScanSettings {
223268 MLO;
224269};
225270
226- struct CStringsManager {
227- SmallVector<std::unique_ptr<std::vector<const char *>>> OwnedCStr;
228- SmallVector<std::unique_ptr<std::vector<std::string>>> OwnedStdStr;
229-
230- // / Doesn't own the string contents.
231- CXCStringArray createCStringsRef (ArrayRef<std::string> Strings) {
232- OwnedCStr.push_back (std::make_unique<std::vector<const char *>>());
233- std::vector<const char *> &CStrings = *OwnedCStr.back ();
234- CStrings.reserve (Strings.size ());
235- for (const auto &String : Strings)
236- CStrings.push_back (String.c_str ());
237- return {CStrings.data (), CStrings.size ()};
238- }
239-
240- // / Doesn't own the string contents.
241- CXCStringArray createCStringsRef (const llvm::StringSet<> &StringsUnordered) {
242- std::vector<StringRef> Strings;
243-
244- for (auto SI = StringsUnordered.begin (), SE = StringsUnordered.end ();
245- SI != SE; ++SI)
246- Strings.push_back (SI->getKey ());
247-
248- llvm::sort (Strings);
249-
250- OwnedCStr.push_back (std::make_unique<std::vector<const char *>>());
251- std::vector<const char *> &CStrings = *OwnedCStr.back ();
252- CStrings.reserve (Strings.size ());
253- for (const auto &String : Strings)
254- CStrings.push_back (String.data ());
255- return {CStrings.data (), CStrings.size ()};
256- }
257-
258- // / Gets ownership of string contents.
259- CXCStringArray createCStringsOwned (std::vector<std::string> &&Strings) {
260- OwnedStdStr.push_back (
261- std::make_unique<std::vector<std::string>>(std::move (Strings)));
262- return createCStringsRef (*OwnedStdStr.back ());
263- }
264- };
265-
266271struct DependencyGraph {
267272 TranslationUnitDeps TUDeps;
268273 SmallString<256 > SerialDiagBuf;
@@ -561,6 +566,38 @@ CXDiagnosticSet clang_experimental_DepGraph_getDiagnostics(CXDepGraph Graph) {
561566 return unwrap (Graph)->getDiagnosticSet ();
562567}
563568
569+ CXCStringArray
570+ clang_experimental_DependencyScannerService_getInvalidNegStatCachedPaths (
571+ CXDependencyScannerService S) {
572+ DependencyScanningService &Service = unwrap (S)->Service ;
573+ CStringsManager &StrMgr = unwrap (S)->StrMgr ;
574+
575+ // FIXME: CAS currently does not use the shared cache, and cannot produce
576+ // the same diagnostics. We should add such a diagnostics to CAS as well.
577+ if (Service.useCASFS ())
578+ return {nullptr , 0 };
579+
580+ DependencyScanningFilesystemSharedCache &SharedCache =
581+ Service.getSharedCache ();
582+
583+ // Note that it is critical that this FS is the same as the default virtual
584+ // file system we pass to the DependencyScanningWorkers.
585+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =
586+ llvm::vfs::createPhysicalFileSystem ();
587+
588+ auto InvaidNegStatCachedPaths =
589+ SharedCache.getInvalidNegativeStatCachedPaths (*FS);
590+
591+ // FIXME: This code here creates copies of strings from
592+ // InvaidNegStatCachedPaths. It is acceptable because this C-API is expected
593+ // to be called only at the end of a CXDependencyScannerService's lifetime.
594+ // In other words, it is called very infrequently. We can change
595+ // CStringsManager's interface to accommodate handling arbitrary StringRefs
596+ // (which may not be null terminated) if we want to avoid copying.
597+ return StrMgr.createCStringsOwned (
598+ {InvaidNegStatCachedPaths.begin (), InvaidNegStatCachedPaths.end ()});
599+ }
600+
564601static std::string
565602lookupModuleOutput (const ModuleDeps &MD, ModuleOutputKind MOK, void *MLOContext,
566603 std::variant<CXModuleLookupOutputCallback *,
0 commit comments