Skip to content

Commit 4de4328

Browse files
authored
Merge pull request #10185 from The-OpenROAD-Project-staging/catch-tidy-error
run-clang-tidy-cached: surface fatal clang-tidy errors instead of caching empty output
2 parents ae0cf47 + 8a2d808 commit 4de4328

1 file changed

Lines changed: 38 additions & 1 deletion

File tree

etc/run-clang-tidy-cached.cc

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ B=${0%%.cc}; [ "$B" -nt "$0" ] || c++ -std=c++17 -o"$B" "$0" && exec "$B" "$@";
3939
#include <unistd.h>
4040

4141
#include <algorithm>
42+
#include <atomic>
4243
#include <cerrno>
4344
#include <cinttypes>
4445
#include <csignal>
@@ -308,8 +309,14 @@ class ClangTidyRunner
308309

309310
const std::string uniquifier = "." + std::to_string(getpid());
310311
std::mutex queue_access_lock;
312+
std::atomic<bool> fatal_stop{false};
313+
std::string fatal_output;
314+
std::string fatal_file;
311315
auto clang_tidy_runner = [&]() {
312316
for (;;) {
317+
if (fatal_stop.load()) {
318+
return;
319+
}
313320
filepath_contenthash_t work;
314321
{
315322
const std::lock_guard<std::mutex> lock(queue_access_lock);
@@ -328,7 +335,7 @@ class ClangTidyRunner
328335
// it is easy to find with `ps` or `top`.
329336
const std::string command = clang_tidy_ + " '" + work.first.string()
330337
+ "'" + clang_tidy_args_ + "> '" + tmp_out
331-
+ "' 2>/dev/null";
338+
+ "' 2>&1";
332339
const int r = system(command.c_str());
333340
#ifdef WIFSIGNALED
334341
// NOLINTBEGIN
@@ -340,6 +347,30 @@ class ClangTidyRunner
340347
}
341348
// NOLINTEND
342349
#endif
350+
// Detect systemic clang-tidy failure (bad config, missing compile db,
351+
// etc.): non-zero exit with no check findings in output. Abort the
352+
// run and surface the error instead of silently caching empty output.
353+
#ifdef WIFEXITED
354+
// NOLINTBEGIN
355+
if (WIFEXITED(r) && WEXITSTATUS(r) != 0) {
356+
// NOLINTEND
357+
#else
358+
if (r != 0) {
359+
#endif
360+
const std::string out = GetContent(tmp_out);
361+
static const std::regex check_finding(
362+
R"(\[[a-zA-Z0-9.]+-[a-zA-Z0-9.-]+\])");
363+
if (!std::regex_search(out, check_finding)) {
364+
bool expected = false;
365+
if (fatal_stop.compare_exchange_strong(expected, true)) {
366+
fatal_output = out;
367+
fatal_file = work.first.string();
368+
}
369+
std::error_code ignored_error;
370+
fs::remove(tmp_out, ignored_error);
371+
return;
372+
}
373+
}
343374
const std::string filter_filename = work.first.filename().string();
344375
RepairFilenameOccurences(filter_filename, tmp_out, tmp_out);
345376
fs::rename(tmp_out, final_out); // atomic replacement
@@ -356,6 +387,12 @@ class ClangTidyRunner
356387
if (print_progress) {
357388
fprintf(stderr, " \n"); // Clean out progress counter.
358389
}
390+
if (fatal_stop.load()) {
391+
std::cerr << "\nclang-tidy failed on " << fatal_file
392+
<< " (aborting; output below):\n"
393+
<< fatal_output << "\n";
394+
exit(EXIT_FAILURE);
395+
}
359396
}
360397

361398
private:

0 commit comments

Comments
 (0)