[clang-tidy] Do not crash when an empty directory is used in the comp… (#156873)

…ilation database

Currently a hard crash encourages people to report a bug upstream, but
this is not really a bug. Instead, print an error and use a reasonable
default (the current working directory).

Fixes #57264

Co-authored-by: Carlos Gálvez <carlos.galvez@zenseact.com>
This commit is contained in:
Carlos Galvez
2025-09-05 20:38:59 +02:00
committed by GitHub
parent 1acd429544
commit 97086d6fda
5 changed files with 29 additions and 7 deletions

View File

@@ -126,6 +126,10 @@ Improvements to clang-tidy
- Improved :program:`clang-tidy` option `-quiet` by suppressing diagnostic
count messages.
- Improved :program:`clang-tidy` by not crashing when an empty `directory`
field is used in a compilation database; the current working directory
will be used instead, and an error message will be printed.
New checks
^^^^^^^^^^

View File

@@ -0,0 +1,5 @@
[{
"directory":"/invalid/",
"file":"/tmp/",
"arguments": []
}]

View File

@@ -1,5 +1,5 @@
// UNSUPPORTED: system-windows
// RUN: not --crash clang-tidy -p %S/Inputs/empty-database %s 2>&1 | FileCheck %s
// RUN: clang-tidy -p %S/Inputs/empty-database %s 2>&1 | FileCheck %s
// CHECK: LLVM ERROR: Cannot chdir into ""!
// CHECK: 'directory' field of compilation database is empty; using the current working directory instead.

View File

@@ -0,0 +1,5 @@
// UNSUPPORTED: system-windows
// RUN: not --crash clang-tidy -p %S/Inputs/invalid-database %s 2>&1 | FileCheck %s
// CHECK: LLVM ERROR: Cannot chdir into "/invalid/"!

View File

@@ -574,6 +574,15 @@ int ClangTool::run(ToolAction *Action) {
continue;
}
for (CompileCommand &CompileCommand : CompileCommandsForFile) {
// If the 'directory' field of the compilation database is empty, display
// an error and use the working directory instead.
StringRef Directory = CompileCommand.Directory;
if (Directory.empty()) {
llvm::errs() << "'directory' field of compilation database is empty; "
"using the current working directory instead.\n";
Directory = InitialWorkingDir;
}
// FIXME: chdir is thread hostile; on the other hand, creating the same
// behavior as chdir is complex: chdir resolves the path once, thus
// guaranteeing that all subsequent relative path operations work
@@ -581,15 +590,14 @@ int ClangTool::run(ToolAction *Action) {
// difference for example on network filesystems, where symlinks might be
// switched during runtime of the tool. Fixing this depends on having a
// file system abstraction that allows openat() style interactions.
if (OverlayFileSystem->setCurrentWorkingDirectory(
CompileCommand.Directory))
llvm::report_fatal_error("Cannot chdir into \"" +
Twine(CompileCommand.Directory) + "\"!");
if (OverlayFileSystem->setCurrentWorkingDirectory(Directory))
llvm::report_fatal_error("Cannot chdir into \"" + Twine(Directory) +
"\"!");
// Now fill the in-memory VFS with the relative file mappings so it will
// have the correct relative paths. We never remove mappings but that
// should be fine.
if (SeenWorkingDirectories.insert(CompileCommand.Directory).second)
if (SeenWorkingDirectories.insert(Directory).second)
for (const auto &MappedFile : MappedFileContents)
if (!llvm::sys::path::is_absolute(MappedFile.first))
InMemoryFileSystem->addFile(