https://github.com/kaladron created https://github.com/llvm/llvm-project/pull/205839
The llvm-header-guard check previously relied on hardcoded path components like 'llvm-project' or 'llvm' to identify the repository root. This caused false positives when running in git worktrees with arbitrary directory names. This change adds a helper to dynamically detect the project root by looking for sibling 'llvm' and 'clang' directories, and canonicalizes the path to '/llvm-project/...' before running the guard calculation. Assisted-by: Automated tooling, human reviewed. >From e9883ce38260816d21cd9424ded9f6a035110583 Mon Sep 17 00:00:00 2001 From: Jeff Bailey <[email protected]> Date: Thu, 25 Jun 2026 15:45:14 +0100 Subject: [PATCH] [clang-tidy] Detect project root in llvm-header-guard The llvm-header-guard check previously relied on hardcoded path components like 'llvm-project' or 'llvm' to identify the repository root. This caused false positives when running in git worktrees with arbitrary directory names. This change adds a helper to dynamically detect the project root by looking for sibling 'llvm' and 'clang' directories, and canonicalizes the path to '/llvm-project/...' before running the guard calculation. Assisted-by: Automated tooling, human reviewed. --- .../clang-tidy/llvm/HeaderGuardCheck.cpp | 40 ++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/clang-tools-extra/clang-tidy/llvm/HeaderGuardCheck.cpp b/clang-tools-extra/clang-tidy/llvm/HeaderGuardCheck.cpp index ef8b6b1dfb8f7..857e22dda6894 100644 --- a/clang-tools-extra/clang-tidy/llvm/HeaderGuardCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvm/HeaderGuardCheck.cpp @@ -8,6 +8,7 @@ #include "HeaderGuardCheck.h" #include "clang/Tooling/Tooling.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" namespace clang::tidy::llvm_check { @@ -16,9 +17,46 @@ LLVMHeaderGuardCheck::LLVMHeaderGuardCheck(StringRef Name, ClangTidyContext *Context) : HeaderGuardCheck(Name, Context) {} +// Attempt to find the root of the LLVM project monorepo by walking up the +// directory tree from Filename and looking for a directory containing both +// 'llvm' and 'clang' subdirectories. This allows us to find the root even +// when working in git worktrees with arbitrary names. +static std::string findLLVMProjectRoot(StringRef Filename) { + SmallString<256> Path = Filename; + while (!Path.empty()) { + llvm::sys::path::remove_filename(Path); + if (Path.empty()) break; + + SmallString<256> LLVMPath = Path; + llvm::sys::path::append(LLVMPath, "llvm"); + SmallString<256> ClangPath = Path; + llvm::sys::path::append(ClangPath, "clang"); + + if (llvm::sys::fs::is_directory(LLVMPath) && llvm::sys::fs::is_directory(ClangPath)) { + return std::string(Path); + } + } + return ""; +} + std::string LLVMHeaderGuardCheck::getHeaderGuard(StringRef Filename, StringRef OldGuard) { - std::string Guard = tooling::getAbsolutePath(Filename); + std::string AbsolutePath = tooling::getAbsolutePath(Filename); + std::string Guard = AbsolutePath; + + // If we can find the LLVM project root, canonicalize the path by replacing + // the root path prefix with "/llvm-project/". This ensures the subsequent + // legacy logic (which relies on hardcoded "llvm-project" or "llvm" path + // components) works correctly regardless of the actual worktree directory name. + std::string Root = findLLVMProjectRoot(AbsolutePath); + if (!Root.empty()) { + StringRef RelativePath = StringRef(AbsolutePath).substr(Root.size()); + if (RelativePath.starts_with("/")) { + Guard = ("/llvm-project" + RelativePath).str(); + } else { + Guard = ("/llvm-project/" + RelativePath).str(); + } + } // When running under Windows, need to convert the path separators from // `\` to `/`. _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
