Skip to content

[clang][Modules] Adding C-API for Negative Stat Caching Diagnostics #10524

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
May 1, 2025
5 changes: 5 additions & 0 deletions clang/include/clang-c/Dependencies.h
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,11 @@ const char *clang_experimental_DepGraph_getTUContextHash(CXDepGraph);
CINDEX_LINKAGE
CXDiagnosticSet clang_experimental_DepGraph_getDiagnostics(CXDepGraph);

CINDEX_LINKAGE
CXStringSet *
clang_experimental_DependencyScannerService_getInvalidNegStatCachedPaths(
CXDependencyScannerService);

/**
* @}
*/
Expand Down
1 change: 1 addition & 0 deletions clang/test/ClangScanDeps/error-c-api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@

// CHECK: error: failed to get dependencies
// CHECK-NEXT: 'missing.h' file not found
// CHECk-NEXT: number of invalid negatively stat cached paths: 0
10 changes: 10 additions & 0 deletions clang/tools/c-index-test/core_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,16 @@ static int scanDeps(ArrayRef<const char *> Args, std::string WorkingDirectory,
clang_disposeString(Spelling);
clang_disposeDiagnostic(Diag);
}

CXStringSet *InvalidNegativeStatCachedPaths =
clang_experimental_DependencyScannerService_getInvalidNegStatCachedPaths(
Service);
if (InvalidNegativeStatCachedPaths) {
llvm::errs() << "note: number of invalid negatively stat cached paths: "
<< InvalidNegativeStatCachedPaths->Count << "\n";
clang_disposeStringSet(InvalidNegativeStatCachedPaths);
}

return 1;
}

Expand Down
23 changes: 23 additions & 0 deletions clang/tools/libclang/CDependencies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,29 @@ CXDiagnosticSet clang_experimental_DepGraph_getDiagnostics(CXDepGraph Graph) {
return unwrap(Graph)->getDiagnosticSet();
}

CXStringSet *
clang_experimental_DependencyScannerService_getInvalidNegStatCachedPaths(
CXDependencyScannerService S) {
DependencyScanningService *Service = unwrap(S);

// FIXME: CAS currently does not use the shared cache, and cannot produce
// the same diagnostics. We should add such a diagnostics to CAS as well.
if (Service->useCASFS())
return nullptr;

DependencyScanningFilesystemSharedCache &SharedCache =
Service->getSharedCache();

// Note that it is critical that this FS is the same as the default virtual
// file system we pass to the DependencyScanningWorkers.
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =
llvm::vfs::createPhysicalFileSystem();

auto InvaidNegStatCachedPaths =
SharedCache.getInvalidNegativeStatCachedPaths(*FS);
return cxstring::createRefSet(InvaidNegStatCachedPaths);
}

static std::string
lookupModuleOutput(const ModuleDeps &MD, ModuleOutputKind MOK, void *MLOContext,
std::variant<CXModuleLookupOutputCallback *,
Expand Down
34 changes: 15 additions & 19 deletions clang/tools/libclang/CXString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,31 +107,27 @@ CXString createCXString(CXStringBuf *buf) {
return Str;
}

CXStringSet *createSet(const std::vector<std::string> &Strings) {
template <typename StringTy, bool Copy>
static CXStringSet *createSetImpl(ArrayRef<StringTy> Strings) {
CXStringSet *Set = new CXStringSet;
Set->Count = Strings.size();
Set->Strings = new CXString[Set->Count];
for (unsigned SI = 0, SE = Set->Count; SI < SE; ++SI)
Set->Strings[SI] = createDup(Strings[SI]);
for (unsigned SI = 0, SE = Set->Count; SI < SE; ++SI) {
if constexpr (Copy) {
Set->Strings[SI] = createDup(Strings[SI]);
} else {
Set->Strings[SI] = createRef(Strings[SI]);
}
}
return Set;
}

CXStringSet *createSet(const llvm::StringSet<> &StringsUnordered) {
std::vector<StringRef> Strings;

for (auto SI = StringsUnordered.begin(),
SE = StringsUnordered.end(); SI != SE; ++SI)
Strings.push_back(SI->getKey());

llvm::sort(Strings);

CXStringSet *Set = new CXStringSet;
Set->Count = Strings.size();
Set->Strings = new CXString[Set->Count];
int I = 0;
for (auto SI = Strings.begin(), SE = Strings.end(); SI != SE; ++SI)
Set->Strings[I++] = createDup(*SI);
return Set;
CXStringSet *createSet(const std::vector<std::string> &Strings) {
return createSetImpl<std::string, true>(Strings);
}

CXStringSet *createRefSet(ArrayRef<StringRef> Strings) {
return createSetImpl<StringRef, false>(Strings);
}

//===----------------------------------------------------------------------===//
Expand Down
7 changes: 6 additions & 1 deletion clang/tools/libclang/CXString.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,14 @@ CXString createRef(std::string String) = delete;
/// Create a CXString object that is backed by a string buffer.
CXString createCXString(CXStringBuf *buf);

/// Create a CXStringSet object that owns the strings. Such an object should be
/// disposed with clang_disposeStringSet.
CXStringSet *createSet(const std::vector<std::string> &Strings);

/// Create a CXStringSet object that does not own the strings. Such an object
/// should still be disposed with clang_disposeStringSet.
CXStringSet *createRefSet(ArrayRef<StringRef> Strings);

CXStringSet *createSet(const llvm::StringSet<> &Strings);

/// A string pool used for fast allocation/deallocation of strings.
Expand Down Expand Up @@ -108,4 +114,3 @@ static inline StringRef getContents(const CXUnsavedFile &UF) {
}

#endif

1 change: 1 addition & 0 deletions clang/tools/libclang/libclang.map
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,7 @@ LLVM_21 {
clang_experimental_DepGraphModule_isCWDIgnored;
clang_experimental_DepGraphModule_isInStableDirs;
clang_getFullyQualifiedName;
clang_experimental_DependencyScannerService_getInvalidNegStatCachedPaths;
};

# Example of how to add a new symbol version entry. If you do add a new symbol
Expand Down