https://github.com/thorsten-klein updated 
https://github.com/llvm/llvm-project/pull/176940

>From 85adc146dc8849c40b41e3949b6fc598231b7978 Mon Sep 17 00:00:00 2001
From: Thorsten Klein <[email protected]>
Date: Wed, 21 Jan 2026 13:23:25 +0100
Subject: [PATCH] added option `llvm-header-guard.HeaderDirs`

new option HeaderDirs for llvm-header-guard is added.

Defaults to `include`. When checking header guards, the header file path
is
searched for the first matching directory in this list. All parent
path
components preceding that directory are discarded, so the generated
header
  guard starts at the matched include directory.
---
 .../clang-tidy/llvm/HeaderGuardCheck.cpp      |  23 +++-
 .../clang-tidy/llvm/HeaderGuardCheck.h        |   4 +
 clang-tools-extra/docs/ReleaseNotes.rst       |   3 +
 .../clang-tidy/checks/llvm/header-guard.rst   |   8 ++
 .../clang-tidy/checkers/llvm/header-guard.cpp | 115 ++++++++++++++++++
 .../llvm/header-guard/include/correct.hpp     |   7 ++
 .../llvm/header-guard/include/missing.hpp     |   5 +
 .../llvm/header-guard/include/wrong.hpp       |   7 ++
 .../llvm/header-guard/other/correct.hpp       |   7 ++
 .../llvm/header-guard/other/missing.hpp       |   5 +
 .../llvm/header-guard/other/wrong.hpp         |   7 ++
 11 files changed, 186 insertions(+), 5 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard.cpp
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/include/correct.hpp
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/include/missing.hpp
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/include/wrong.hpp
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/other/correct.hpp
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/other/missing.hpp
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/other/wrong.hpp

diff --git a/clang-tools-extra/clang-tidy/llvm/HeaderGuardCheck.cpp 
b/clang-tools-extra/clang-tidy/llvm/HeaderGuardCheck.cpp
index ef8b6b1dfb8f7..36e837e203a89 100644
--- a/clang-tools-extra/clang-tidy/llvm/HeaderGuardCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/HeaderGuardCheck.cpp
@@ -7,6 +7,7 @@
 
//===----------------------------------------------------------------------===//
 
 #include "HeaderGuardCheck.h"
+#include "../utils/OptionsUtils.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/Support/Path.h"
 
@@ -14,7 +15,9 @@ namespace clang::tidy::llvm_check {
 
 LLVMHeaderGuardCheck::LLVMHeaderGuardCheck(StringRef Name,
                                            ClangTidyContext *Context)
-    : HeaderGuardCheck(Name, Context) {}
+    : HeaderGuardCheck(Name, Context),
+      HeaderDirs(utils::options::parseStringList(
+          Options.get("HeaderDirs", "include"))) {}
 
 std::string LLVMHeaderGuardCheck::getHeaderGuard(StringRef Filename,
                                                  StringRef OldGuard) {
@@ -27,10 +30,15 @@ std::string LLVMHeaderGuardCheck::getHeaderGuard(StringRef 
Filename,
   // Sanitize the path. There are some rules for compatibility with the 
historic
   // style in include/llvm and include/clang which we want to preserve.
 
-  // We don't want _INCLUDE_ in our guards.
-  const size_t PosInclude = Guard.rfind("include/");
-  if (PosInclude != StringRef::npos)
-    Guard = Guard.substr(PosInclude + std::strlen("include/"));
+  // consider all directories from HeaderDirs option. Stop at first found.
+  for (StringRef HeaderDir : HeaderDirs) {
+    size_t PosHeaderDir = Guard.rfind(HeaderDir.str() + "/");
+    if (PosHeaderDir != StringRef::npos) {
+      // We don't want the header dir in our guards, i.e. _INCLUDE_
+      Guard = Guard.substr(PosHeaderDir + HeaderDir.size() + 1);
+      break; // stop at first found
+    }
+  }
 
   // For clang we drop the _TOOLS_.
   const size_t PosToolsClang = Guard.rfind("tools/clang/");
@@ -64,4 +72,9 @@ std::string LLVMHeaderGuardCheck::getHeaderGuard(StringRef 
Filename,
   return StringRef(Guard).upper();
 }
 
+void LLVMHeaderGuardCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "HeaderDirs",
+                utils::options::serializeStringList(HeaderDirs));
+}
+
 } // namespace clang::tidy::llvm_check
diff --git a/clang-tools-extra/clang-tidy/llvm/HeaderGuardCheck.h 
b/clang-tools-extra/clang-tidy/llvm/HeaderGuardCheck.h
index cfc920bb85e23..a7447a5c8863d 100644
--- a/clang-tools-extra/clang-tidy/llvm/HeaderGuardCheck.h
+++ b/clang-tools-extra/clang-tidy/llvm/HeaderGuardCheck.h
@@ -21,7 +21,11 @@ class LLVMHeaderGuardCheck : public utils::HeaderGuardCheck {
   LLVMHeaderGuardCheck(StringRef Name, ClangTidyContext *Context);
 
   bool shouldSuggestEndifComment(StringRef Filename) override { return false; }
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
   std::string getHeaderGuard(StringRef Filename, StringRef OldGuard) override;
+
+private:
+  const std::vector<StringRef> HeaderDirs;
 };
 
 } // namespace clang::tidy::llvm_check
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index cfd7d277db29c..5a79e551e0d69 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -131,6 +131,9 @@ Changes in existing checks
   now uses separate note diagnostics for each uninitialized enumerator, making
   it easier to see which specific enumerators need explicit initialization.
 
+- Improved :doc:`llvm-header-guard <clang-tidy/checks/llvm/header-guard>` check
+  by adding the option `HeaderDirs` to configure header directory names.
+
 Removed checks
 ^^^^^^^^^^^^^^
 
diff --git a/clang-tools-extra/docs/clang-tidy/checks/llvm/header-guard.rst 
b/clang-tools-extra/docs/clang-tidy/checks/llvm/header-guard.rst
index 74eb10ba6fcf9..f65bea01421f0 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/llvm/header-guard.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/llvm/header-guard.rst
@@ -4,3 +4,11 @@ llvm-header-guard
 =================
 
 Finds and fixes header guards that do not adhere to LLVM style.
+
+Options
+-------
+
+.. option:: HeaderDirs
+
+   A list of directories where the include guard string will start.
+   defaults to `include`.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard.cpp
new file mode 100644
index 0000000000000..c0c5f7e63e22e
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard.cpp
@@ -0,0 +1,115 @@
+#include "header-guard/include/correct.hpp"
+#include "header-guard/include/missing.hpp"
+#include "header-guard/include/wrong.hpp"
+
+#include "header-guard/other/correct.hpp"
+#include "header-guard/other/missing.hpp"
+#include "header-guard/other/wrong.hpp"
+
+// ---------------------------------------
+// TEST 1: Use no config options (default)
+// ---------------------------------------
+// RUN: %check_clang_tidy %s llvm-header-guard %t -export-fixes=%t.1.yaml 
--header-filter=.* -- -I%S > %t.1.msg 2>&1
+// RUN: FileCheck -input-file=%t.1.msg -check-prefix=CHECK-MESSAGES1 %s
+// RUN: FileCheck -input-file=%t.1.yaml -check-prefix=CHECK-YAML1 %s
+
+// CHECK-MESSAGES1: header-guard/include/missing.hpp:1:1: warning: header is 
missing header guard [llvm-header-guard]
+// CHECK-MESSAGES1: header-guard/other/missing.hpp:1:1: warning: header is 
missing header guard [llvm-header-guard]
+// CHECK-MESSAGES1: header-guard/include/wrong.hpp:1:9: warning: header guard 
does not follow preferred style [llvm-header-guard]
+// CHECK-MESSAGES1: header-guard/other/wrong.hpp:1:9: warning: header guard 
does not follow preferred style [llvm-header-guard]
+
+// CHECK-YAML1: Message:         header is missing header guard
+// CHECK-YAML1: FilePath:        '{{.*}}/header-guard/include/missing.hpp'
+// CHECK-YAML1: ReplacementText: "#ifndef MISSING_HPP\n#define MISSING_HPP\n\n"
+// CHECK-YAML1: ReplacementText: "\n#endif\n"
+
+// CHECK-YAML1: Message:         header guard does not follow preferred style
+// CHECK-YAML1: FilePath:        '{{.*}}/header-guard/include/wrong.hpp'
+// CHECK-YAML1: ReplacementText: WRONG_HPP
+
+// CHECK-YAML1: Message:         header is missing header guard
+// CHECK-YAML1: FilePath:        '{{.*}}/header-guard/other/missing.hpp'
+// CHECK-YAML1: ReplacementText: "#ifndef 
LLVM_HEADER_GUARD_OTHER_MISSING_HPP\n#define 
LLVM_HEADER_GUARD_OTHER_MISSING_HPP\n\n"
+// CHECK-YAML1: ReplacementText: "\n#endif\n"
+// CHECK-YAML1: Message:         header guard does not follow preferred style
+// CHECK-YAML1: FilePath:        '{{.*}}/header-guard/other/wrong.hpp'
+// CHECK-YAML1: ReplacementText: LLVM_HEADER_GUARD_OTHER_WRONG_HPP
+
+// ---------------------------------------
+// TEST 2: Set option HeaderDirs=other
+// ---------------------------------------
+// RUN: %check_clang_tidy %s llvm-header-guard %t -export-fixes=%t.2.yaml 
--header-filter=.* \
+// RUN:   --config='{CheckOptions: { \
+// RUN:     llvm-header-guard.HeaderDirs: other, \
+// RUN:   }}' -- -I%S > %t.2.msg 2>&1
+// RUN: FileCheck -input-file=%t.2.msg -check-prefix=CHECK-MESSAGES2 %s
+// RUN: FileCheck -input-file=%t.2.yaml -check-prefix=CHECK-YAML2 %s
+
+// CHECK-MESSAGES2: header-guard/include/correct.hpp:1:9: warning: header 
guard does not follow preferred style [llvm-header-guard]
+// CHECK-MESSAGES2: header-guard/other/correct.hpp:1:9: warning: header guard 
does not follow preferred style [llvm-header-guard]
+// CHECK-MESSAGES2: header-guard/include/missing.hpp:1:1: warning: header is 
missing header guard [llvm-header-guard]
+// CHECK-MESSAGES2: header-guard/other/missing.hpp:1:1: warning: header is 
missing header guard [llvm-header-guard]
+// CHECK-MESSAGES2: header-guard/include/wrong.hpp:1:9: warning: header guard 
does not follow preferred style [llvm-header-guard]
+// CHECK-MESSAGES2: header-guard/other/wrong.hpp:1:9: warning: header guard 
does not follow preferred style [llvm-header-guard]
+
+// CHECK-YAML2: Message:         header guard does not follow preferred style
+// CHECK-YAML2: FilePath:        '{{.*}}/header-guard/include/correct.hpp'
+// CHECK-YAML2: ReplacementText: LLVM_HEADER_GUARD_INCLUDE_CORRECT_HPP
+// CHECK-YAML2: Message:         header is missing header guard
+// CHECK-YAML2: FilePath:        '{{.*}}/header-guard/include/missing.hpp'
+// CHECK-YAML2: ReplacementText: "#ifndef 
LLVM_HEADER_GUARD_INCLUDE_MISSING_HPP\n#define 
LLVM_HEADER_GUARD_INCLUDE_MISSING_HPP\n\n"
+// CHECK-YAML2: ReplacementText: "\n#endif\n"
+// CHECK-YAML2: Message:         header guard does not follow preferred style
+// CHECK-YAML2: FilePath:        '{{.*}}/header-guard/include/wrong.hpp'
+// CHECK-YAML2: ReplacementText: LLVM_HEADER_GUARD_INCLUDE_WRONG_HPP
+
+// CHECK-YAML2: Message:         header guard does not follow preferred style
+// CHECK-YAML2: FilePath:        '{{.*}}/header-guard/other/correct.hpp'
+// CHECK-YAML2: ReplacementText: CORRECT_HPP
+// CHECK-YAML2: Message:         header is missing header guard
+// CHECK-YAML2: FilePath:        '{{.*}}/header-guard/other/missing.hpp'
+// CHECK-YAML2: ReplacementText: "#ifndef MISSING_HPP\n#define MISSING_HPP\n\n"
+// CHECK-YAML2: ReplacementText: "\n#endif\n"
+// CHECK-YAML2: Message:         header guard does not follow preferred style
+// CHECK-YAML2: FilePath:        '{{.*}}/header-guard/other/wrong.hpp'
+// CHECK-YAML2: ReplacementText: WRONG_HPP
+
+
+// ---------------------------------------
+// TEST 3: Set option HeaderDirs=include;other
+// ---------------------------------------
+// RUN: %check_clang_tidy %s llvm-header-guard %t -export-fixes=%t.3.yaml 
--header-filter=.* \
+// RUN:   --config='{CheckOptions: { \
+// RUN:     llvm-header-guard.HeaderDirs: include;other, \
+// RUN:   }}' -- -I%S > %t.3.msg 2>&1
+// RUN: FileCheck -input-file=%t.3.msg -check-prefix=CHECK-MESSAGES3 %s
+// RUN: FileCheck -input-file=%t.3.yaml -check-prefix=CHECK-YAML3 %s
+
+// CHECK-MESSAGES2: header-guard/include/correct.hpp:1:9: warning: header 
guard does not follow preferred style [llvm-header-guard]
+// CHECK-MESSAGES2: header-guard/other/correct.hpp:1:9: warning: header guard 
does not follow preferred style [llvm-header-guard]
+// CHECK-MESSAGES3: header-guard/include/missing.hpp:1:1: warning: header is 
missing header guard [llvm-header-guard]
+// CHECK-MESSAGES3: header-guard/other/missing.hpp:1:1: warning: header is 
missing header guard [llvm-header-guard]
+// CHECK-MESSAGES3: header-guard/include/wrong.hpp:1:9: warning: header guard 
does not follow preferred style [llvm-header-guard]
+// CHECK-MESSAGES3: header-guard/other/wrong.hpp:1:9: warning: header guard 
does not follow preferred style [llvm-header-guard]
+
+// CHECK-YAML3: Message:         header is missing header guard
+// CHECK-YAML3: FilePath:        '{{.*}}/header-guard/include/missing.hpp'
+// CHECK-YAML3: ReplacementText: "#ifndef MISSING_HPP\n#define MISSING_HPP\n\n"
+// CHECK-YAML3: ReplacementText: "\n#endif\n"
+// CHECK-YAML3: Message:         header guard does not follow preferred style
+// CHECK-YAML3: FilePath:        '{{.*}}/header-guard/include/wrong.hpp'
+// CHECK-YAML3: ReplacementText: WRONG_HPP
+
+// CHECK-YAML3: Message:         header guard does not follow preferred style
+// CHECK-YAML3: FilePath:        '{{.*}}/header-guard/other/correct.hpp'
+// CHECK-YAML3: ReplacementText: CORRECT_HPP
+// CHECK-YAML3: Message:         header is missing header guard
+// CHECK-YAML3: FilePath:        '{{.*}}/header-guard/other/missing.hpp'
+// CHECK-YAML3: ReplacementText: "#ifndef MISSING_HPP\n#define MISSING_HPP\n\n"
+// CHECK-YAML3: ReplacementText: "\n#endif\n"
+// CHECK-YAML3: Message:         header guard does not follow preferred style
+// CHECK-YAML3: FilePath:        '{{.*}}/header-guard/other/wrong.hpp'
+// CHECK-YAML3: ReplacementText: WRONG_HPP
+
+
+
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/include/correct.hpp
 
b/clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/include/correct.hpp
new file mode 100644
index 0000000000000..86d9f050a7a05
--- /dev/null
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/include/correct.hpp
@@ -0,0 +1,7 @@
+#ifndef CORRECT_HPP
+#define CORRECT_HPP
+#endif
+
+// RUN: %check_clang_tidy %s llvm-header-guard correct -export-fixes=%t.yaml > 
%t.msg 2>&1
+// RUN: FileCheck -input-file=%t.msg -check-prefix=CHECK-MSG %s
+// CHECK-MSG: warning: code/includes outside of area guarded by header guard; 
consider moving it [llvm-header-guard]
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/include/missing.hpp
 
b/clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/include/missing.hpp
new file mode 100644
index 0000000000000..af6c72129a9fc
--- /dev/null
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/include/missing.hpp
@@ -0,0 +1,5 @@
+
+
+// RUN: %check_clang_tidy %s llvm-header-guard missing -export-fixes=%t.yaml > 
%t.msg 2>&1
+// RUN: FileCheck -input-file=%t.msg -check-prefix=CHECK-MSG %s
+// CHECK-MSG: :1:1: warning: header is missing header guard [llvm-header-guard]
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/include/wrong.hpp
 
b/clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/include/wrong.hpp
new file mode 100644
index 0000000000000..142fdf9ae62bf
--- /dev/null
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/include/wrong.hpp
@@ -0,0 +1,7 @@
+#ifndef HERE_IS_SOMETHING_WRONG_HPP
+#define HERE_IS_SOMETHING_WRONG_HPP
+#endif
+
+// RUN: %check_clang_tidy %s llvm-header-guard wrong -export-fixes=%t.yaml > 
%t.msg 2>&1
+// RUN: FileCheck -input-file=%t.msg -check-prefix=CHECK-MSG %s
+// CHECK-MSG: warning: header guard does not follow preferred style 
[llvm-header-guard]
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/other/correct.hpp
 
b/clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/other/correct.hpp
new file mode 100644
index 0000000000000..1f05ed0885156
--- /dev/null
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/other/correct.hpp
@@ -0,0 +1,7 @@
+#ifndef LLVM_HEADER_GUARD_OTHER_CORRECT_HPP
+#define LLVM_HEADER_GUARD_OTHER_CORRECT_HPP
+#endif
+
+// RUN: %check_clang_tidy %s llvm-header-guard correct -export-fixes=%t.yaml > 
%t.msg 2>&1
+// RUN: FileCheck -input-file=%t.msg -check-prefix=CHECK-MSG %s
+// CHECK-MSG: warning: code/includes outside of area guarded by header guard; 
consider moving it [llvm-header-guard]
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/other/missing.hpp
 
b/clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/other/missing.hpp
new file mode 100644
index 0000000000000..af6c72129a9fc
--- /dev/null
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/other/missing.hpp
@@ -0,0 +1,5 @@
+
+
+// RUN: %check_clang_tidy %s llvm-header-guard missing -export-fixes=%t.yaml > 
%t.msg 2>&1
+// RUN: FileCheck -input-file=%t.msg -check-prefix=CHECK-MSG %s
+// CHECK-MSG: :1:1: warning: header is missing header guard [llvm-header-guard]
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/other/wrong.hpp 
b/clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/other/wrong.hpp
new file mode 100644
index 0000000000000..762251322deb3
--- /dev/null
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/llvm/header-guard/other/wrong.hpp
@@ -0,0 +1,7 @@
+#ifndef SOME_WRONG_HEADER_GUARD_HPP
+#define SOME_WRONG_HEADER_GUARD_HPP
+#endif
+
+// RUN: %check_clang_tidy %s llvm-header-guard wrong -export-fixes=%t.yaml > 
%t.msg 2>&1
+// RUN: FileCheck -input-file=%t.msg -check-prefix=CHECK-MSG %s
+// CHECK-MSG: warning: header guard does not follow preferred style 
[llvm-header-guard]

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to