https://github.com/furtib updated 
https://github.com/llvm/llvm-project/pull/207407

>From f52244e33254f5564ce7104d61d96e0bc09f07b4 Mon Sep 17 00:00:00 2001
From: "F.Tibor" <[email protected]>
Date: Mon, 8 Jun 2026 23:43:38 +0200
Subject: [PATCH 01/15] [clang-tidy] Add llvm-regex check

---
 .../clang-tidy/llvm/CMakeLists.txt            |   1 +
 .../clang-tidy/llvm/LLVMTidyModule.cpp        |   2 +
 .../clang-tidy/llvm/RegexCheck.cpp            |  88 +++++++++++
 .../clang-tidy/llvm/RegexCheck.h              |  33 +++++
 clang-tools-extra/docs/ReleaseNotes.md        |   5 +
 .../docs/clang-tidy/checks/list.md            |   1 +
 .../docs/clang-tidy/checks/llvm/regex.rst     |  34 +++++
 .../test/clang-tidy/checkers/llvm/regex.cpp   | 140 ++++++++++++++++++
 8 files changed, 304 insertions(+)
 create mode 100644 clang-tools-extra/clang-tidy/llvm/RegexCheck.cpp
 create mode 100644 clang-tools-extra/clang-tidy/llvm/RegexCheck.h
 create mode 100644 clang-tools-extra/docs/clang-tidy/checks/llvm/regex.rst
 create mode 100644 clang-tools-extra/test/clang-tidy/checkers/llvm/regex.cpp

diff --git a/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
index bec3ba50c81c51..2f5d136108191f 100644
--- a/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
@@ -12,6 +12,7 @@ add_clang_library(clangTidyLLVMModule STATIC
   PreferRegisterOverUnsignedCheck.cpp
   PreferStaticOverAnonymousNamespaceCheck.cpp
   RedundantCastingCheck.cpp
+  RegexCheck.cpp
   TwineLocalCheck.cpp
   TypeSwitchCaseTypesCheck.cpp
   UseNewMLIROpBuilderCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp 
b/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
index 918af88c979e0a..16409770f04679 100644
--- a/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
@@ -18,6 +18,7 @@
 #include "PreferRegisterOverUnsignedCheck.h"
 #include "PreferStaticOverAnonymousNamespaceCheck.h"
 #include "RedundantCastingCheck.h"
+#include "RegexCheck.h"
 #include "TwineLocalCheck.h"
 #include "TypeSwitchCaseTypesCheck.h"
 #include "UseNewMLIROpBuilderCheck.h"
@@ -48,6 +49,7 @@ class LLVMModule : public ClangTidyModule {
         "llvm-qualified-auto");
     CheckFactories.registerCheck<RedundantCastingCheck>(
         "llvm-redundant-casting");
+    CheckFactories.registerCheck<RegexCheck>("llvm-regex");
     CheckFactories.registerCheck<TwineLocalCheck>("llvm-twine-local");
     CheckFactories.registerCheck<TypeSwitchCaseTypesCheck>(
         "llvm-type-switch-case-types");
diff --git a/clang-tools-extra/clang-tidy/llvm/RegexCheck.cpp 
b/clang-tools-extra/clang-tidy/llvm/RegexCheck.cpp
new file mode 100644
index 00000000000000..f9f2b58e424f70
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/llvm/RegexCheck.cpp
@@ -0,0 +1,88 @@
+//===--- RegexCheck.cpp - clang-tidy 
--------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegexCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "llvm/Support/Regex.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::llvm_check {
+
+void RegexCheck::registerMatchers(MatchFinder *Finder) {
+  // main matcher
+  auto IsConstllvmStringRef = qualType(
+      isConstQualified(), 
hasUnqualifiedDesugaredType(recordType(hasDeclaration(
+                              cxxRecordDecl(hasName("::llvm::StringRef"))))));
+  auto IsConstStdString = qualType(
+      isConstQualified(), 
hasUnqualifiedDesugaredType(recordType(hasDeclaration(
+                              
cxxRecordDecl(hasName("::std::basic_string"))))));
+  auto GetStringLit = ignoringImplicit(stringLiteral().bind("stringLiteral"));
+  auto GetStringLiteralFromObject =
+      ignoringImplicit(cxxConstructExpr(hasAnyArgument(GetStringLit)));
+  auto IsConstCharPtr = pointerType(pointee(builtinType(), 
isConstQualified()));
+  auto IsStdStringView = qualType(hasUnqualifiedDesugaredType(recordType(
+      hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"))))));
+  auto AnyCastedToStringRef = ignoringImplicit(anyOf(
+      stringLiteral().bind("stringLiteral"),
+      declRefExpr(to(varDecl(hasType(IsConstStdString),
+                             hasInitializer(GetStringLiteralFromObject)))),
+      declRefExpr(to(varDecl(hasType(IsConstllvmStringRef),
+                             hasInitializer(GetStringLiteralFromObject)))),
+      declRefExpr(
+          to(varDecl(hasType(IsConstCharPtr), hasInitializer(GetStringLit)))),
+      declRefExpr(to(varDecl(hasType(IsStdStringView),
+                             hasInitializer(GetStringLiteralFromObject)))),
+      memberExpr(
+          member(fieldDecl(hasType(IsConstStdString),
+                           
hasInClassInitializer(GetStringLiteralFromObject)))),
+      memberExpr(member(fieldDecl(hasType(IsConstCharPtr),
+                                  hasInClassInitializer(GetStringLit)))),
+      memberExpr(
+          member(fieldDecl(hasType(IsConstllvmStringRef),
+                           
hasInClassInitializer(GetStringLiteralFromObject)))),
+      memberExpr(member(
+          fieldDecl(hasType(IsStdStringView),
+                    hasInClassInitializer(GetStringLiteralFromObject))))));
+
+  auto IsRegexFlagsType = ignoringParenImpCasts(
+      anyOf(integerLiteral().bind("regexFlagsInt"),
+            declRefExpr(to(enumConstantDecl().bind("regexFlagEnum")))));
+  Finder->addMatcher(
+      cxxConstructExpr(
+          hasDeclaration(cxxConstructorDecl(ofClass(hasName("llvm::Regex")))),
+          hasArgument(0, ignoringImplicit(cxxConstructExpr(
+                             hasDeclaration(cxxConstructorDecl(
+                                 ofClass(hasName("::llvm::StringRef")))),
+                             hasArgument(0, AnyCastedToStringRef)))),
+          optionally(hasArgument(1, IsRegexFlagsType))),
+      this);
+}
+
+void RegexCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *DetectedPattern =
+      Result.Nodes.getNodeAs<StringLiteral>("stringLiteral");
+  if (DetectedPattern) {
+    const auto *FlagInt =
+        Result.Nodes.getNodeAs<IntegerLiteral>("regexFlagsInt");
+    const auto *FlagEnum =
+        Result.Nodes.getNodeAs<EnumConstantDecl>("regexFlagEnum");
+    uint Flag = llvm::Regex::RegexFlags::NoFlags;
+    if (FlagInt)
+      Flag = FlagInt->getValue().getZExtValue();
+    if (FlagEnum)
+      Flag = FlagEnum->getInitVal().getZExtValue();
+    const llvm::Regex TestRegex(DetectedPattern->getString(), Flag);
+    std::string RegexError;
+    if (!TestRegex.isValid(RegexError))
+      diag(DetectedPattern->getBeginLoc(), "invalid regex pattern: %0")
+          << RegexError << DetectedPattern->getSourceRange();
+  }
+}
+
+} // namespace clang::tidy::llvm_check
diff --git a/clang-tools-extra/clang-tidy/llvm/RegexCheck.h 
b/clang-tools-extra/clang-tidy/llvm/RegexCheck.h
new file mode 100644
index 00000000000000..17891713e62eeb
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/llvm/RegexCheck.h
@@ -0,0 +1,33 @@
+//===--- RegexCheck.h - clang-tidy ------------------------------*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_REGEXCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_REGEXCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::llvm_check {
+
+/// Detects malformed regex patterns used in ``llvm::Regex``.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/llvm/regex.html
+class RegexCheck : public ClangTidyCheck {
+public:
+  RegexCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+    return LangOpts.CPlusPlus;
+  }
+};
+
+} // namespace clang::tidy::llvm_check
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_REGEXCHECK_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.md 
b/clang-tools-extra/docs/ReleaseNotes.md
index 28da9da42d8ce2..a84d311ddd7889 100644
--- a/clang-tools-extra/docs/ReleaseNotes.md
+++ b/clang-tools-extra/docs/ReleaseNotes.md
@@ -98,6 +98,11 @@ infrastructure are described first, followed by 
tool-specific sections.
   Finds calls to `value_or` (and alternative spellings `valueOr`,
   `ValueOr`) on optional types where the return type is expensive to copy.
 
+- New :doc:`llvm-regex
+  <clang-tidy/checks/llvm/regex>` check.
+
+  Detects malformed regex patterns used in `llvm::Regex`.
+
 #### New check aliases
 
 #### Changes in existing checks
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.md 
b/clang-tools-extra/docs/clang-tidy/checks/list.md
index 12d8a48ee8d865..39c42a32a2258c 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.md
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.md
@@ -251,6 +251,7 @@ zircon/*
 | {doc}`llvm-prefer-register-over-unsigned 
<llvm/prefer-register-over-unsigned>` | Yes |
 | {doc}`llvm-prefer-static-over-anonymous-namespace 
<llvm/prefer-static-over-anonymous-namespace>` |  |
 | {doc}`llvm-redundant-casting <llvm/redundant-casting>` | Yes |
+| {doc}`llvm-regex <llvm/regex>` | No |
 | {doc}`llvm-twine-local <llvm/twine-local>` | Yes |
 | {doc}`llvm-type-switch-case-types <llvm/type-switch-case-types>` | Yes |
 | {doc}`llvm-use-new-mlir-op-builder <llvm/use-new-mlir-op-builder>` | Yes |
diff --git a/clang-tools-extra/docs/clang-tidy/checks/llvm/regex.rst 
b/clang-tools-extra/docs/clang-tidy/checks/llvm/regex.rst
new file mode 100644
index 00000000000000..837181a8ea4a65
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/llvm/regex.rst
@@ -0,0 +1,34 @@
+.. title:: clang-tidy - llvm-regex
+
+llvm-regex
+==========
+
+The checker detects malformed regex patterns defined in a single string literal
+to catch mistakes at compile time.
+It detects these string literals if they are defined in the regex constructor
+with a string literal, or stored in one of these non mutable container:
+
+- ``const std::string``
+- ``const char*``
+- ``const llvm::StringRef``
+- ``std::string_view``
+
+In the event that the patterns are stored as a class member, the check checks
+the initialization value, if defined, even if its overwritten by the 
constructor.
+
+Example of detection:
+
+.. code-block:: c++
+    const std::string my_regex_pattern("[0-8"); // invalid regex pattern
+    llvm::Regex my_regex(my_regex_pattern);
+
+Example of member data being overwritten:
+
+.. code-block:: c++
+    class foo{
+    public:
+      foo(llvm::StringRef regex_ptrn) : regex_prtn(regex_prtn){};
+      const llvm_StringRef regex_prtn = "("; // invalid regex pattern
+    };
+    foo bar("[0-9]");
+    llvm::Regex my_regex(bar.regex_prtn);
diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/regex.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/llvm/regex.cpp
new file mode 100644
index 00000000000000..229b35f2eb204e
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/regex.cpp
@@ -0,0 +1,140 @@
+// RUN: %check_clang_tidy -std=c++17 %s llvm-regex %t
+
+namespace std {
+  template <typename T>
+  class basic_string {
+  public:
+    basic_string(const char*);
+  };
+  using string = basic_string<char>;
+
+  template <typename T>
+  class basic_string_view {
+  public:
+    basic_string_view(const char*);
+    const char* begin() const;
+  };
+  using string_view = basic_string_view<char>;
+} // namespace std
+
+namespace llvm {
+  class StringRef {
+  public:
+    StringRef(const char*);
+    StringRef(const std::string&);
+    StringRef(const std::string_view&);
+  };
+  
+  class Regex {
+  public:
+    Regex(StringRef, unsigned int i = 0);
+    enum RegexFlags : unsigned {
+      NoFlags = 0,
+      IgnoreCase = 1,
+      Newline = 2,
+      BasicRegex = 4,
+    };
+  };
+} // namespace llvm
+
+void test_detected_faulty_patterns(){
+  llvm::Regex re1("(");
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: invalid regex pattern: 
parentheses not balanced
+
+  const std::string badStdString("(");
+  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: invalid regex pattern: 
parentheses not balanced
+  llvm::Regex re2(badStdString);
+
+  const char* badCharPtr = "[]";
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: invalid regex pattern: brackets 
([ ]) not balanced
+  llvm::Regex re3(badCharPtr);
+
+  std::string_view badStrView("+");
+  // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: invalid regex pattern: 
repetition-operator operand invalid
+  llvm::Regex re4(badStrView);
+
+  const llvm::StringRef badStrRef = "a*?";
+  // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: invalid regex pattern: 
repetition-operator operand invalid
+  llvm::Regex re5(badStrRef);
+
+  struct RegexPatterns {
+    const char* badMemberChar = "";
+    // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: invalid regex pattern: empty 
(sub)expression
+
+    const std::string badMemberStr = "(";
+    // CHECK-MESSAGES: :[[@LINE-1]]:38: warning: invalid regex pattern: 
parentheses not balanced
+
+    std::string_view badMemberStrView = "+";
+    // CHECK-MESSAGES: :[[@LINE-1]]:41: warning: invalid regex pattern: 
repetition-operator operand invalid
+
+    const llvm::StringRef badMemberStrRef = "a*?";
+    // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: invalid regex pattern: 
repetition-operator operand invalid
+  };
+
+  RegexPatterns Pats;
+
+  llvm::Regex re6(Pats.badMemberChar);
+  llvm::Regex re7(Pats.badMemberStr);
+  llvm::Regex re8(Pats.badMemberStrView);
+  llvm::Regex re9(Pats.badMemberStrRef);
+}
+
+void test_no_detection_on_mutable(){
+  std::string badMutStdString("(");
+  llvm::Regex re10(badMutStdString);
+
+  char* badMutCharPtr = "[";
+  llvm::Regex re11(badMutCharPtr);
+
+  llvm::StringRef badMutStrRef = "a*?";
+  llvm::Regex re12(badMutStrRef);
+
+  struct RegexMutPatterns {
+    char* badMutMemberChar = "";
+    std::string badMutMemberStr = "(";
+    llvm::StringRef badMutMemberStrRef = "a*?";
+  };
+
+  RegexMutPatterns mutPats;
+
+  llvm::Regex re13(mutPats.badMutMemberChar);
+  llvm::Regex re14(mutPats.badMutMemberStr);
+  llvm::Regex re15(mutPats.badMutMemberStrRef);
+}
+
+void test_no_report_on_correct_patterns(){
+  llvm::Regex re16("[0-9]");
+
+  const std::string goodStdString("test");
+  llvm::Regex re17(goodStdString);
+
+  const char* goodCharPtr = "\\[test\\]";
+  llvm::Regex re18(goodCharPtr);
+
+  std::string_view goodStrView("testi+ng");
+  llvm::Regex re19(goodStrView);
+
+  const llvm::StringRef goodStrRef = "a*b?";
+  llvm::Regex re20(goodStrRef);
+
+  struct GoodRegexPatterns {
+    const char* goodMemberChar = "[0-9]";
+    const std::string goodMemberStr = "test";
+    std::string_view goodMemberStrView = "\[test\]";
+    const llvm::StringRef goodMemberStrRef = "a*b";
+  };
+
+  GoodRegexPatterns goodPats;
+
+  llvm::Regex re21(goodPats.goodMemberChar);
+  llvm::Regex re22(goodPats.goodMemberStr);
+  llvm::Regex re23(goodPats.goodMemberStrView);
+  llvm::Regex re24(goodPats.goodMemberStrRef);
+}
+
+void test_grammar_flags(){
+  llvm::Regex re1_noflag("(", 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: invalid regex pattern: 
parentheses not balanced
+  llvm::Regex re1_basic("(", 4U);
+  llvm::Regex re2_basic("(", llvm::Regex::RegexFlags::BasicRegex);
+}

>From 52d15ebc61e54aeadb16b8b9422fcb4f5ba4d757 Mon Sep 17 00:00:00 2001
From: "F.Tibor" <[email protected]>
Date: Sat, 4 Jul 2026 10:57:53 +0200
Subject: [PATCH 02/15] Apply suggestions from code review

Co-authored-by: EugeneZelenko <[email protected]>
Co-authored-by: Zeyi Xu <[email protected]>
---
 clang-tools-extra/clang-tidy/llvm/RegexCheck.cpp          | 2 +-
 clang-tools-extra/clang-tidy/llvm/RegexCheck.h            | 2 +-
 clang-tools-extra/docs/clang-tidy/checks/list.md          | 2 +-
 clang-tools-extra/docs/clang-tidy/checks/llvm/regex.rst   | 2 +-
 clang-tools-extra/test/clang-tidy/checkers/llvm/regex.cpp | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/llvm/RegexCheck.cpp 
b/clang-tools-extra/clang-tidy/llvm/RegexCheck.cpp
index f9f2b58e424f70..57f6fa9588adf6 100644
--- a/clang-tools-extra/clang-tidy/llvm/RegexCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/RegexCheck.cpp
@@ -1,4 +1,4 @@
-//===--- RegexCheck.cpp - clang-tidy 
--------------------------------------===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang-tools-extra/clang-tidy/llvm/RegexCheck.h 
b/clang-tools-extra/clang-tidy/llvm/RegexCheck.h
index 17891713e62eeb..e18bda161ae434 100644
--- a/clang-tools-extra/clang-tidy/llvm/RegexCheck.h
+++ b/clang-tools-extra/clang-tidy/llvm/RegexCheck.h
@@ -1,4 +1,4 @@
-//===--- RegexCheck.h - clang-tidy ------------------------------*- C++ 
-*-===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.md 
b/clang-tools-extra/docs/clang-tidy/checks/list.md
index 39c42a32a2258c..2c17452e7c2f9d 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.md
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.md
@@ -251,7 +251,7 @@ zircon/*
 | {doc}`llvm-prefer-register-over-unsigned 
<llvm/prefer-register-over-unsigned>` | Yes |
 | {doc}`llvm-prefer-static-over-anonymous-namespace 
<llvm/prefer-static-over-anonymous-namespace>` |  |
 | {doc}`llvm-redundant-casting <llvm/redundant-casting>` | Yes |
-| {doc}`llvm-regex <llvm/regex>` | No |
+| {doc}`llvm-regex <llvm/regex>` |  |
 | {doc}`llvm-twine-local <llvm/twine-local>` | Yes |
 | {doc}`llvm-type-switch-case-types <llvm/type-switch-case-types>` | Yes |
 | {doc}`llvm-use-new-mlir-op-builder <llvm/use-new-mlir-op-builder>` | Yes |
diff --git a/clang-tools-extra/docs/clang-tidy/checks/llvm/regex.rst 
b/clang-tools-extra/docs/clang-tidy/checks/llvm/regex.rst
index 837181a8ea4a65..f570fac85c8674 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/llvm/regex.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/llvm/regex.rst
@@ -3,7 +3,7 @@
 llvm-regex
 ==========
 
-The checker detects malformed regex patterns defined in a single string literal
+Detects malformed regex patterns defined in a single string literal
 to catch mistakes at compile time.
 It detects these string literals if they are defined in the regex constructor
 with a string literal, or stored in one of these non mutable container:
diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/regex.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/llvm/regex.cpp
index 229b35f2eb204e..c83fa9a85c5019 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/llvm/regex.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/regex.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy -std=c++17 %s llvm-regex %t
+// RUN: %check_clang_tidy -std=c++17-or-later %s llvm-regex %t
 
 namespace std {
   template <typename T>

>From ded741a8bb4eddfb4532ff4c8ac3f18e97168c1c Mon Sep 17 00:00:00 2001
From: "F.Tibor" <[email protected]>
Date: Sat, 4 Jul 2026 11:20:06 +0200
Subject: [PATCH 03/15] Documentation fixes

---
 clang-tools-extra/docs/ReleaseNotes.md         |  5 +++--
 .../docs/clang-tidy/checks/llvm/regex.rst      | 18 ++++++++++--------
 2 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/clang-tools-extra/docs/ReleaseNotes.md 
b/clang-tools-extra/docs/ReleaseNotes.md
index a84d311ddd7889..41db9a1910c5d6 100644
--- a/clang-tools-extra/docs/ReleaseNotes.md
+++ b/clang-tools-extra/docs/ReleaseNotes.md
@@ -98,10 +98,11 @@ infrastructure are described first, followed by 
tool-specific sections.
   Finds calls to `value_or` (and alternative spellings `valueOr`,
   `ValueOr`) on optional types where the return type is expensive to copy.
 
-- New :doc:`llvm-regex
+- New {doc}`llvm-regex
   <clang-tidy/checks/llvm/regex>` check.
 
-  Detects malformed regex patterns used in `llvm::Regex`.
+  Detects malformed regex patterns defined in a single string literal
+  to catch mistakes at compile time.
 
 #### New check aliases
 
diff --git a/clang-tools-extra/docs/clang-tidy/checks/llvm/regex.rst 
b/clang-tools-extra/docs/clang-tidy/checks/llvm/regex.rst
index f570fac85c8674..604520f3d979af 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/llvm/regex.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/llvm/regex.rst
@@ -13,22 +13,24 @@ with a string literal, or stored in one of these non 
mutable container:
 - ``const llvm::StringRef``
 - ``std::string_view``
 
-In the event that the patterns are stored as a class member, the check checks
+In the event that the patterns are stored as a class member, the check verifies
 the initialization value, if defined, even if its overwritten by the 
constructor.
 
 Example of detection:
 
 .. code-block:: c++
+
     const std::string my_regex_pattern("[0-8"); // invalid regex pattern
     llvm::Regex my_regex(my_regex_pattern);
 
 Example of member data being overwritten:
 
 .. code-block:: c++
-    class foo{
-    public:
-      foo(llvm::StringRef regex_ptrn) : regex_prtn(regex_prtn){};
-      const llvm_StringRef regex_prtn = "("; // invalid regex pattern
-    };
-    foo bar("[0-9]");
-    llvm::Regex my_regex(bar.regex_prtn);
+
+  class foo{
+  public:
+    foo(llvm::StringRef regex_ptrn) : regex_prtn(regex_prtn){};
+    const llvm_StringRef regex_prtn = "("; // invalid regex pattern
+  };
+  foo bar("[0-9]");
+  llvm::Regex my_regex(bar.regex_prtn);

>From c0760c2e725d50581aee34d92cf3de957250638a Mon Sep 17 00:00:00 2001
From: "F.Tibor" <[email protected]>
Date: Sat, 4 Jul 2026 11:20:32 +0200
Subject: [PATCH 04/15] Use include <string> in test file

---
 .../test/clang-tidy/checkers/llvm/regex.cpp     | 17 +----------------
 1 file changed, 1 insertion(+), 16 deletions(-)

diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/regex.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/llvm/regex.cpp
index c83fa9a85c5019..88de3539da5831 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/llvm/regex.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/regex.cpp
@@ -1,21 +1,6 @@
 // RUN: %check_clang_tidy -std=c++17-or-later %s llvm-regex %t
 
-namespace std {
-  template <typename T>
-  class basic_string {
-  public:
-    basic_string(const char*);
-  };
-  using string = basic_string<char>;
-
-  template <typename T>
-  class basic_string_view {
-  public:
-    basic_string_view(const char*);
-    const char* begin() const;
-  };
-  using string_view = basic_string_view<char>;
-} // namespace std
+#include <string>
 
 namespace llvm {
   class StringRef {

>From d5c64b9ea8603b5561eaff18587e5d2e95c69286 Mon Sep 17 00:00:00 2001
From: "F.Tibor" <[email protected]>
Date: Sat, 4 Jul 2026 11:36:39 +0200
Subject: [PATCH 05/15] Rename checker to llvm-invalid-regex-pattern

---
 clang-tools-extra/clang-tidy/llvm/CMakeLists.txt            | 2 +-
 .../llvm/{RegexCheck.cpp => InvalidRegexPatternCheck.cpp}   | 6 +++---
 .../llvm/{RegexCheck.h => InvalidRegexPatternCheck.h}       | 6 +++---
 clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp        | 4 ++--
 clang-tools-extra/docs/ReleaseNotes.md                      | 4 ++--
 clang-tools-extra/docs/clang-tidy/checks/list.md            | 2 +-
 .../checks/llvm/{regex.rst => invalid-regex-pattern.rst}    | 6 +++---
 clang-tools-extra/test/clang-tidy/checkers/llvm/regex.cpp   | 2 +-
 8 files changed, 16 insertions(+), 16 deletions(-)
 rename clang-tools-extra/clang-tidy/llvm/{RegexCheck.cpp => 
InvalidRegexPatternCheck.cpp} (95%)
 rename clang-tools-extra/clang-tidy/llvm/{RegexCheck.h => 
InvalidRegexPatternCheck.h} (84%)
 rename clang-tools-extra/docs/clang-tidy/checks/llvm/{regex.rst => 
invalid-regex-pattern.rst} (90%)

diff --git a/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
index 2f5d136108191f..563c05d14232a0 100644
--- a/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
@@ -12,7 +12,7 @@ add_clang_library(clangTidyLLVMModule STATIC
   PreferRegisterOverUnsignedCheck.cpp
   PreferStaticOverAnonymousNamespaceCheck.cpp
   RedundantCastingCheck.cpp
-  RegexCheck.cpp
+  InvalidRegexPatternCheck.cpp
   TwineLocalCheck.cpp
   TypeSwitchCaseTypesCheck.cpp
   UseNewMLIROpBuilderCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/llvm/RegexCheck.cpp 
b/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp
similarity index 95%
rename from clang-tools-extra/clang-tidy/llvm/RegexCheck.cpp
rename to clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp
index 57f6fa9588adf6..ca23dcc8c96500 100644
--- a/clang-tools-extra/clang-tidy/llvm/RegexCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp
@@ -6,7 +6,7 @@
 //
 
//===----------------------------------------------------------------------===//
 
-#include "RegexCheck.h"
+#include "InvalidRegexPatternCheck.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "llvm/Support/Regex.h"
 
@@ -14,7 +14,7 @@ using namespace clang::ast_matchers;
 
 namespace clang::tidy::llvm_check {
 
-void RegexCheck::registerMatchers(MatchFinder *Finder) {
+void InvalidRegexPatternCheck::registerMatchers(MatchFinder *Finder) {
   // main matcher
   auto IsConstllvmStringRef = qualType(
       isConstQualified(), 
hasUnqualifiedDesugaredType(recordType(hasDeclaration(
@@ -64,7 +64,7 @@ void RegexCheck::registerMatchers(MatchFinder *Finder) {
       this);
 }
 
-void RegexCheck::check(const MatchFinder::MatchResult &Result) {
+void InvalidRegexPatternCheck::check(const MatchFinder::MatchResult &Result) {
   const auto *DetectedPattern =
       Result.Nodes.getNodeAs<StringLiteral>("stringLiteral");
   if (DetectedPattern) {
diff --git a/clang-tools-extra/clang-tidy/llvm/RegexCheck.h 
b/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.h
similarity index 84%
rename from clang-tools-extra/clang-tidy/llvm/RegexCheck.h
rename to clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.h
index e18bda161ae434..177a47b668dc16 100644
--- a/clang-tools-extra/clang-tidy/llvm/RegexCheck.h
+++ b/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.h
@@ -17,9 +17,9 @@ namespace clang::tidy::llvm_check {
 ///
 /// For the user-facing documentation see:
 /// http://clang.llvm.org/extra/clang-tidy/checks/llvm/regex.html
-class RegexCheck : public ClangTidyCheck {
+class InvalidRegexPatternCheck : public ClangTidyCheck {
 public:
-  RegexCheck(StringRef Name, ClangTidyContext *Context)
+  InvalidRegexPatternCheck(StringRef Name, ClangTidyContext *Context)
       : ClangTidyCheck(Name, Context) {}
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
@@ -30,4 +30,4 @@ class RegexCheck : public ClangTidyCheck {
 
 } // namespace clang::tidy::llvm_check
 
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_REGEXCHECK_H
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_InvalidRegexPatternCheck_H
diff --git a/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp 
b/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
index 16409770f04679..549867beec25d4 100644
--- a/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
@@ -18,7 +18,7 @@
 #include "PreferRegisterOverUnsignedCheck.h"
 #include "PreferStaticOverAnonymousNamespaceCheck.h"
 #include "RedundantCastingCheck.h"
-#include "RegexCheck.h"
+#include "InvalidRegexPatternCheck.h"
 #include "TwineLocalCheck.h"
 #include "TypeSwitchCaseTypesCheck.h"
 #include "UseNewMLIROpBuilderCheck.h"
@@ -49,7 +49,7 @@ class LLVMModule : public ClangTidyModule {
         "llvm-qualified-auto");
     CheckFactories.registerCheck<RedundantCastingCheck>(
         "llvm-redundant-casting");
-    CheckFactories.registerCheck<RegexCheck>("llvm-regex");
+    
CheckFactories.registerCheck<InvalidRegexPatternCheck>("llvm-invalid-regex-pattern");
     CheckFactories.registerCheck<TwineLocalCheck>("llvm-twine-local");
     CheckFactories.registerCheck<TypeSwitchCaseTypesCheck>(
         "llvm-type-switch-case-types");
diff --git a/clang-tools-extra/docs/ReleaseNotes.md 
b/clang-tools-extra/docs/ReleaseNotes.md
index 41db9a1910c5d6..ba0db92414488e 100644
--- a/clang-tools-extra/docs/ReleaseNotes.md
+++ b/clang-tools-extra/docs/ReleaseNotes.md
@@ -98,8 +98,8 @@ infrastructure are described first, followed by tool-specific 
sections.
   Finds calls to `value_or` (and alternative spellings `valueOr`,
   `ValueOr`) on optional types where the return type is expensive to copy.
 
-- New {doc}`llvm-regex
-  <clang-tidy/checks/llvm/regex>` check.
+- New {doc}`llvm-invalid-regex-pattern
+  <clang-tidy/checks/llvm/invalid-regex-pattern>` check.
 
   Detects malformed regex patterns defined in a single string literal
   to catch mistakes at compile time.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.md 
b/clang-tools-extra/docs/clang-tidy/checks/list.md
index 2c17452e7c2f9d..a5fb11cfc6de01 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.md
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.md
@@ -246,12 +246,12 @@ zircon/*
 | {doc}`llvm-formatv-string <llvm/formatv-string>` |  |
 | {doc}`llvm-header-guard <llvm/header-guard>` |  |
 | {doc}`llvm-include-order <llvm/include-order>` | Yes |
+| {doc}`llvm-invalid-regex-pattern <llvm/invalid-regex-pattern>` |  |
 | {doc}`llvm-namespace-comment <llvm/namespace-comment>` |  |
 | {doc}`llvm-prefer-isa-or-dyn-cast-in-conditionals 
<llvm/prefer-isa-or-dyn-cast-in-conditionals>` | Yes |
 | {doc}`llvm-prefer-register-over-unsigned 
<llvm/prefer-register-over-unsigned>` | Yes |
 | {doc}`llvm-prefer-static-over-anonymous-namespace 
<llvm/prefer-static-over-anonymous-namespace>` |  |
 | {doc}`llvm-redundant-casting <llvm/redundant-casting>` | Yes |
-| {doc}`llvm-regex <llvm/regex>` |  |
 | {doc}`llvm-twine-local <llvm/twine-local>` | Yes |
 | {doc}`llvm-type-switch-case-types <llvm/type-switch-case-types>` | Yes |
 | {doc}`llvm-use-new-mlir-op-builder <llvm/use-new-mlir-op-builder>` | Yes |
diff --git a/clang-tools-extra/docs/clang-tidy/checks/llvm/regex.rst 
b/clang-tools-extra/docs/clang-tidy/checks/llvm/invalid-regex-pattern.rst
similarity index 90%
rename from clang-tools-extra/docs/clang-tidy/checks/llvm/regex.rst
rename to 
clang-tools-extra/docs/clang-tidy/checks/llvm/invalid-regex-pattern.rst
index 604520f3d979af..2cba3766608e78 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/llvm/regex.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/llvm/invalid-regex-pattern.rst
@@ -1,7 +1,7 @@
-.. title:: clang-tidy - llvm-regex
+.. title:: clang-tidy - llvm-invalid-regex-pattern
 
-llvm-regex
-==========
+llvm-invalid-regex-pattern
+==========================
 
 Detects malformed regex patterns defined in a single string literal
 to catch mistakes at compile time.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/regex.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/llvm/regex.cpp
index 88de3539da5831..440c59eea50f01 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/llvm/regex.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/regex.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy -std=c++17-or-later %s llvm-regex %t
+// RUN: %check_clang_tidy -std=c++17-or-later %s llvm-invalid-regex-pattern %t
 
 #include <string>
 

>From b69553bca020fe7cf1eb939d21e781c90cc827aa Mon Sep 17 00:00:00 2001
From: "F.Tibor" <[email protected]>
Date: Sat, 4 Jul 2026 11:44:52 +0200
Subject: [PATCH 06/15] Missed a couple of things during renameing

---
 .../clang-tidy/llvm/InvalidRegexPatternCheck.h              | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.h 
b/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.h
index 177a47b668dc16..7adb7df285084d 100644
--- a/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.h
+++ b/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.h
@@ -6,8 +6,8 @@
 //
 
//===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_REGEXCHECK_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_REGEXCHECK_H
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_INVALIDREGEXPATTERNCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_INVALIDREGEXPATTERNCHECK_H
 
 #include "../ClangTidyCheck.h"
 
@@ -30,4 +30,4 @@ class InvalidRegexPatternCheck : public ClangTidyCheck {
 
 } // namespace clang::tidy::llvm_check
 
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_InvalidRegexPatternCheck_H
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_INVALIDREGEXPATTERNCHECK_H

>From 193f29a69aac74f123eba230cc88513c38946f59 Mon Sep 17 00:00:00 2001
From: "F.Tibor" <[email protected]>
Date: Sat, 4 Jul 2026 11:55:01 +0200
Subject: [PATCH 07/15] Use unsigned int instead of uint

---
 clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp 
b/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp
index ca23dcc8c96500..3a357093ffd183 100644
--- a/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp
@@ -72,7 +72,7 @@ void InvalidRegexPatternCheck::check(const 
MatchFinder::MatchResult &Result) {
         Result.Nodes.getNodeAs<IntegerLiteral>("regexFlagsInt");
     const auto *FlagEnum =
         Result.Nodes.getNodeAs<EnumConstantDecl>("regexFlagEnum");
-    uint Flag = llvm::Regex::RegexFlags::NoFlags;
+    unsigned int Flag = llvm::Regex::RegexFlags::NoFlags;
     if (FlagInt)
       Flag = FlagInt->getValue().getZExtValue();
     if (FlagEnum)

>From 5c5324758339dc857f97f0784b1b4f6cd2850abd Mon Sep 17 00:00:00 2001
From: "F.Tibor" <[email protected]>
Date: Sat, 4 Jul 2026 14:40:35 +0200
Subject: [PATCH 08/15] Clang-format

---
 clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp 
b/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
index 549867beec25d4..ed8d04f22a9e23 100644
--- a/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
@@ -14,11 +14,11 @@
 #include "FormatvStringCheck.h"
 #include "HeaderGuardCheck.h"
 #include "IncludeOrderCheck.h"
+#include "InvalidRegexPatternCheck.h"
 #include "PreferIsaOrDynCastInConditionalsCheck.h"
 #include "PreferRegisterOverUnsignedCheck.h"
 #include "PreferStaticOverAnonymousNamespaceCheck.h"
 #include "RedundantCastingCheck.h"
-#include "InvalidRegexPatternCheck.h"
 #include "TwineLocalCheck.h"
 #include "TypeSwitchCaseTypesCheck.h"
 #include "UseNewMLIROpBuilderCheck.h"
@@ -49,7 +49,8 @@ class LLVMModule : public ClangTidyModule {
         "llvm-qualified-auto");
     CheckFactories.registerCheck<RedundantCastingCheck>(
         "llvm-redundant-casting");
-    
CheckFactories.registerCheck<InvalidRegexPatternCheck>("llvm-invalid-regex-pattern");
+    CheckFactories.registerCheck<InvalidRegexPatternCheck>(
+        "llvm-invalid-regex-pattern");
     CheckFactories.registerCheck<TwineLocalCheck>("llvm-twine-local");
     CheckFactories.registerCheck<TypeSwitchCaseTypesCheck>(
         "llvm-type-switch-case-types");

>From 37e4c956b96d9541bf1382798b2e43eb59da0143 Mon Sep 17 00:00:00 2001
From: "F.Tibor" <[email protected]>
Date: Wed, 5 Aug 2026 13:24:02 +0200
Subject: [PATCH 09/15] Update
 clang-tools-extra/docs/clang-tidy/checks/llvm/invalid-regex-pattern.rst
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Donát Nagy <[email protected]>
---
 .../docs/clang-tidy/checks/llvm/invalid-regex-pattern.rst   | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git 
a/clang-tools-extra/docs/clang-tidy/checks/llvm/invalid-regex-pattern.rst 
b/clang-tools-extra/docs/clang-tidy/checks/llvm/invalid-regex-pattern.rst
index 2cba3766608e78..3ce072c193c9c6 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/llvm/invalid-regex-pattern.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/llvm/invalid-regex-pattern.rst
@@ -29,8 +29,8 @@ Example of member data being overwritten:
 
   class foo{
   public:
-    foo(llvm::StringRef regex_ptrn) : regex_prtn(regex_prtn){};
-    const llvm_StringRef regex_prtn = "("; // invalid regex pattern
+    foo(llvm::StringRef regex_pat) : regex_p(regex_pat){};
+    const llvm_StringRef regex_pat = "("; // invalid regex pattern
   };
   foo bar("[0-9]");
-  llvm::Regex my_regex(bar.regex_prtn);
+  llvm::Regex my_regex(bar.regex_pat);

>From 37a01e226e97e094d1880309e80a6203a0a855c1 Mon Sep 17 00:00:00 2001
From: "F.Tibor" <[email protected]>
Date: Thu, 6 Aug 2026 13:34:17 +0200
Subject: [PATCH 10/15] Reduce code duplication using anyOf

---
 .../llvm/InvalidRegexPatternCheck.cpp         | 28 ++++++-------------
 1 file changed, 9 insertions(+), 19 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp 
b/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp
index 3a357093ffd183..048a9c5328c0ef 100644
--- a/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp
@@ -30,25 +30,15 @@ void InvalidRegexPatternCheck::registerMatchers(MatchFinder 
*Finder) {
       hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"))))));
   auto AnyCastedToStringRef = ignoringImplicit(anyOf(
       stringLiteral().bind("stringLiteral"),
-      declRefExpr(to(varDecl(hasType(IsConstStdString),
-                             hasInitializer(GetStringLiteralFromObject)))),
-      declRefExpr(to(varDecl(hasType(IsConstllvmStringRef),
-                             hasInitializer(GetStringLiteralFromObject)))),
-      declRefExpr(
-          to(varDecl(hasType(IsConstCharPtr), hasInitializer(GetStringLit)))),
-      declRefExpr(to(varDecl(hasType(IsStdStringView),
-                             hasInitializer(GetStringLiteralFromObject)))),
-      memberExpr(
-          member(fieldDecl(hasType(IsConstStdString),
-                           
hasInClassInitializer(GetStringLiteralFromObject)))),
-      memberExpr(member(fieldDecl(hasType(IsConstCharPtr),
-                                  hasInClassInitializer(GetStringLit)))),
-      memberExpr(
-          member(fieldDecl(hasType(IsConstllvmStringRef),
-                           
hasInClassInitializer(GetStringLiteralFromObject)))),
-      memberExpr(member(
-          fieldDecl(hasType(IsStdStringView),
-                    hasInClassInitializer(GetStringLiteralFromObject))))));
+      declRefExpr(to(varDecl(
+          hasType(qualType(anyOf(IsConstStdString, IsConstllvmStringRef,
+                                 IsStdStringView, IsConstCharPtr))),
+          hasInitializer(anyOf(GetStringLiteralFromObject, GetStringLit))))),
+      memberExpr(member(fieldDecl(
+          hasType(qualType(anyOf(IsConstStdString, IsConstllvmStringRef,
+                                 IsStdStringView, IsConstCharPtr))),
+          hasInClassInitializer(
+              anyOf(GetStringLiteralFromObject, GetStringLit)))))));
 
   auto IsRegexFlagsType = ignoringParenImpCasts(
       anyOf(integerLiteral().bind("regexFlagsInt"),

>From 22b511015b1a5b7582b125e04314bac8bac22b8c Mon Sep 17 00:00:00 2001
From: "F.Tibor" <[email protected]>
Date: Thu, 6 Aug 2026 13:52:36 +0200
Subject: [PATCH 11/15] Change supported languages to c++17 since
 std::string_view is only available since then

---
 clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.h 
b/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.h
index 7adb7df285084d..cb6223a668344e 100644
--- a/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.h
+++ b/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.h
@@ -24,7 +24,7 @@ class InvalidRegexPatternCheck : public ClangTidyCheck {
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
   bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
-    return LangOpts.CPlusPlus;
+    return LangOpts.CPlusPlus17;
   }
 };
 

>From bd86583bcd9fa84b49900061a000260dfdecfc83 Mon Sep 17 00:00:00 2001
From: "F.Tibor" <[email protected]>
Date: Fri, 7 Aug 2026 12:36:36 +0200
Subject: [PATCH 12/15] Detect char arrays too (normal, static, const)

---
 .../llvm/InvalidRegexPatternCheck.cpp         |  7 ++++--
 .../checks/llvm/invalid-regex-pattern.rst     |  3 +++
 .../test/clang-tidy/checkers/llvm/regex.cpp   | 24 +++++++++++++++++--
 3 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp 
b/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp
index 048a9c5328c0ef..4fd1d86daf4dde 100644
--- a/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp
@@ -26,17 +26,20 @@ void InvalidRegexPatternCheck::registerMatchers(MatchFinder 
*Finder) {
   auto GetStringLiteralFromObject =
       ignoringImplicit(cxxConstructExpr(hasAnyArgument(GetStringLit)));
   auto IsConstCharPtr = pointerType(pointee(builtinType(), 
isConstQualified()));
+  auto IsCharArray = qualType(
+      hasUnqualifiedDesugaredType(arrayType(hasElementType(builtinType()))));
   auto IsStdStringView = qualType(hasUnqualifiedDesugaredType(recordType(
       hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"))))));
   auto AnyCastedToStringRef = ignoringImplicit(anyOf(
       stringLiteral().bind("stringLiteral"),
       declRefExpr(to(varDecl(
           hasType(qualType(anyOf(IsConstStdString, IsConstllvmStringRef,
-                                 IsStdStringView, IsConstCharPtr))),
+                                 IsStdStringView, IsConstCharPtr,
+                                 IsCharArray))),
           hasInitializer(anyOf(GetStringLiteralFromObject, GetStringLit))))),
       memberExpr(member(fieldDecl(
           hasType(qualType(anyOf(IsConstStdString, IsConstllvmStringRef,
-                                 IsStdStringView, IsConstCharPtr))),
+                                 IsStdStringView, IsConstCharPtr, 
IsCharArray))),
           hasInClassInitializer(
               anyOf(GetStringLiteralFromObject, GetStringLit)))))));
 
diff --git 
a/clang-tools-extra/docs/clang-tidy/checks/llvm/invalid-regex-pattern.rst 
b/clang-tools-extra/docs/clang-tidy/checks/llvm/invalid-regex-pattern.rst
index 3ce072c193c9c6..aaec7c456c74ed 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/llvm/invalid-regex-pattern.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/llvm/invalid-regex-pattern.rst
@@ -12,6 +12,9 @@ with a string literal, or stored in one of these non mutable 
container:
 - ``const char*``
 - ``const llvm::StringRef``
 - ``std::string_view``
+- ``char[]``
+- ``static char[]``
+- ``const char[]``
 
 In the event that the patterns are stored as a class member, the check verifies
 the initialization value, if defined, even if its overwritten by the 
constructor.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/regex.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/llvm/regex.cpp
index 440c59eea50f01..2d36fe5d1c5c30 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/llvm/regex.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/regex.cpp
@@ -41,6 +41,18 @@ void test_detected_faulty_patterns(){
   const llvm::StringRef badStrRef = "a*?";
   // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: invalid regex pattern: 
repetition-operator operand invalid
   llvm::Regex re5(badStrRef);
+  
+  static const char badConstStaticChar[] = "";
+  // CHECK-MESSAGES: :[[@LINE-1]]:44: warning: invalid regex pattern: empty 
(sub)expression
+  llvm::Regex regex_badConstStaticChar(badConstStaticChar);
+
+  static char badStaticChar[] = "";
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: invalid regex pattern: empty 
(sub)expression
+  llvm::Regex regex_badStaticChar(badStaticChar);
+  
+  char badCharArray[] = "";
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: invalid regex pattern: empty 
(sub)expression
+  llvm::Regex regex_badCharArray(badCharArray);
 
   struct RegexPatterns {
     const char* badMemberChar = "";
@@ -54,14 +66,22 @@ void test_detected_faulty_patterns(){
 
     const llvm::StringRef badMemberStrRef = "a*?";
     // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: invalid regex pattern: 
repetition-operator operand invalid
-  };
 
+    const char badMemberConstChar[1] = "";
+    // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: invalid regex pattern: empty 
(sub)expression
+    
+    char badMemberCharArray[1] = "";
+    // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: invalid regex pattern: empty 
(sub)expression
+  };
+  
   RegexPatterns Pats;
-
+  
   llvm::Regex re6(Pats.badMemberChar);
   llvm::Regex re7(Pats.badMemberStr);
   llvm::Regex re8(Pats.badMemberStrView);
   llvm::Regex re9(Pats.badMemberStrRef);
+  llvm::Regex regex_badMemberConstStaticChar(Pats.badMemberConstChar);
+  llvm::Regex regex_badMemberCharArray(Pats.badMemberCharArray);
 }
 
 void test_no_detection_on_mutable(){

>From 2df860e922bbdca30a61d909c6494f30986527a5 Mon Sep 17 00:00:00 2001
From: "F.Tibor" <[email protected]>
Date: Fri, 7 Aug 2026 12:40:33 +0200
Subject: [PATCH 13/15] Convert documentation to the markdown format

---
 .../checks/llvm/invalid-regex-pattern.md      | 37 ++++++++++++++++++
 .../checks/llvm/invalid-regex-pattern.rst     | 39 -------------------
 2 files changed, 37 insertions(+), 39 deletions(-)
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/llvm/invalid-regex-pattern.md
 delete mode 100644 
clang-tools-extra/docs/clang-tidy/checks/llvm/invalid-regex-pattern.rst

diff --git 
a/clang-tools-extra/docs/clang-tidy/checks/llvm/invalid-regex-pattern.md 
b/clang-tools-extra/docs/clang-tidy/checks/llvm/invalid-regex-pattern.md
new file mode 100644
index 00000000000000..ea6af2a1bb27a5
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/llvm/invalid-regex-pattern.md
@@ -0,0 +1,37 @@
+# clang-tidy - llvm-invalid-regex-pattern
+
+## llvm-invalid-regex-pattern
+
+Detects malformed regex patterns defined in a single string literal
+to catch mistakes at compile time.
+It detects these string literals if they are defined in the regex constructor
+with a string literal, or stored in one of these non mutable containers:
+
+- `const std::string`
+- `const char*`
+- `const char[]`
+- `static const char[]`
+- `const llvm::StringRef`
+- `std::string_view`
+
+In the event that the patterns are stored as a class member, the check verifies
+the initialization value, if defined, even if its overwritten by the 
constructor.
+
+Example of detection:
+
+```cpp
+const std::string my_regex_pattern("[0-8"); // invalid regex pattern
+llvm::Regex my_regex(my_regex_pattern);
+```
+
+Example of member data being overwritten:
+
+```cpp
+class foo{
+public:
+  foo(llvm::StringRef regex_pat) : regex_p(regex_pat){};
+  const llvm::StringRef regex_pat = "("; // invalid regex pattern
+};
+foo bar("[0-9]"); // pattern not checked
+llvm::Regex my_regex(bar.regex_pat);
+```
diff --git 
a/clang-tools-extra/docs/clang-tidy/checks/llvm/invalid-regex-pattern.rst 
b/clang-tools-extra/docs/clang-tidy/checks/llvm/invalid-regex-pattern.rst
deleted file mode 100644
index aaec7c456c74ed..00000000000000
--- a/clang-tools-extra/docs/clang-tidy/checks/llvm/invalid-regex-pattern.rst
+++ /dev/null
@@ -1,39 +0,0 @@
-.. title:: clang-tidy - llvm-invalid-regex-pattern
-
-llvm-invalid-regex-pattern
-==========================
-
-Detects malformed regex patterns defined in a single string literal
-to catch mistakes at compile time.
-It detects these string literals if they are defined in the regex constructor
-with a string literal, or stored in one of these non mutable container:
-
-- ``const std::string``
-- ``const char*``
-- ``const llvm::StringRef``
-- ``std::string_view``
-- ``char[]``
-- ``static char[]``
-- ``const char[]``
-
-In the event that the patterns are stored as a class member, the check verifies
-the initialization value, if defined, even if its overwritten by the 
constructor.
-
-Example of detection:
-
-.. code-block:: c++
-
-    const std::string my_regex_pattern("[0-8"); // invalid regex pattern
-    llvm::Regex my_regex(my_regex_pattern);
-
-Example of member data being overwritten:
-
-.. code-block:: c++
-
-  class foo{
-  public:
-    foo(llvm::StringRef regex_pat) : regex_p(regex_pat){};
-    const llvm_StringRef regex_pat = "("; // invalid regex pattern
-  };
-  foo bar("[0-9]");
-  llvm::Regex my_regex(bar.regex_pat);

>From f617e588cd91244613a9cbed8eb20c5bfbb041a7 Mon Sep 17 00:00:00 2001
From: "F.Tibor" <[email protected]>
Date: Fri, 7 Aug 2026 14:12:17 +0200
Subject: [PATCH 14/15] Use assert

---
 .../clang-tidy/llvm/InvalidRegexPatternCheck.cpp              | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp 
b/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp
index 4fd1d86daf4dde..ca74528332c30b 100644
--- a/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp
@@ -60,7 +60,8 @@ void InvalidRegexPatternCheck::registerMatchers(MatchFinder 
*Finder) {
 void InvalidRegexPatternCheck::check(const MatchFinder::MatchResult &Result) {
   const auto *DetectedPattern =
       Result.Nodes.getNodeAs<StringLiteral>("stringLiteral");
-  if (DetectedPattern) {
+      assert(DetectedPattern && "stringLiteral must be bound in matcher");
+
     const auto *FlagInt =
         Result.Nodes.getNodeAs<IntegerLiteral>("regexFlagsInt");
     const auto *FlagEnum =
@@ -75,7 +76,6 @@ void InvalidRegexPatternCheck::check(const 
MatchFinder::MatchResult &Result) {
     if (!TestRegex.isValid(RegexError))
       diag(DetectedPattern->getBeginLoc(), "invalid regex pattern: %0")
           << RegexError << DetectedPattern->getSourceRange();
-  }
 }
 
 } // namespace clang::tidy::llvm_check

>From 27ab432b4f1366b711e50a77e5e6f29f085a7679 Mon Sep 17 00:00:00 2001
From: "F.Tibor" <[email protected]>
Date: Fri, 7 Aug 2026 14:15:00 +0200
Subject: [PATCH 15/15] Clang format

---
 .../llvm/InvalidRegexPatternCheck.cpp         | 46 +++++++++----------
 1 file changed, 23 insertions(+), 23 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp 
b/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp
index ca74528332c30b..3d582ab54d0c4d 100644
--- a/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/InvalidRegexPatternCheck.cpp
@@ -33,15 +33,16 @@ void InvalidRegexPatternCheck::registerMatchers(MatchFinder 
*Finder) {
   auto AnyCastedToStringRef = ignoringImplicit(anyOf(
       stringLiteral().bind("stringLiteral"),
       declRefExpr(to(varDecl(
-          hasType(qualType(anyOf(IsConstStdString, IsConstllvmStringRef,
-                                 IsStdStringView, IsConstCharPtr,
-                                 IsCharArray))),
+          hasType(
+              qualType(anyOf(IsConstStdString, IsConstllvmStringRef,
+                             IsStdStringView, IsConstCharPtr, IsCharArray))),
           hasInitializer(anyOf(GetStringLiteralFromObject, GetStringLit))))),
-      memberExpr(member(fieldDecl(
-          hasType(qualType(anyOf(IsConstStdString, IsConstllvmStringRef,
-                                 IsStdStringView, IsConstCharPtr, 
IsCharArray))),
-          hasInClassInitializer(
-              anyOf(GetStringLiteralFromObject, GetStringLit)))))));
+      memberExpr(member(
+          fieldDecl(hasType(qualType(
+                        anyOf(IsConstStdString, IsConstllvmStringRef,
+                              IsStdStringView, IsConstCharPtr, IsCharArray))),
+                    hasInClassInitializer(
+                        anyOf(GetStringLiteralFromObject, GetStringLit)))))));
 
   auto IsRegexFlagsType = ignoringParenImpCasts(
       anyOf(integerLiteral().bind("regexFlagsInt"),
@@ -60,22 +61,21 @@ void InvalidRegexPatternCheck::registerMatchers(MatchFinder 
*Finder) {
 void InvalidRegexPatternCheck::check(const MatchFinder::MatchResult &Result) {
   const auto *DetectedPattern =
       Result.Nodes.getNodeAs<StringLiteral>("stringLiteral");
-      assert(DetectedPattern && "stringLiteral must be bound in matcher");
+  assert(DetectedPattern && "stringLiteral must be bound in matcher");
 
-    const auto *FlagInt =
-        Result.Nodes.getNodeAs<IntegerLiteral>("regexFlagsInt");
-    const auto *FlagEnum =
-        Result.Nodes.getNodeAs<EnumConstantDecl>("regexFlagEnum");
-    unsigned int Flag = llvm::Regex::RegexFlags::NoFlags;
-    if (FlagInt)
-      Flag = FlagInt->getValue().getZExtValue();
-    if (FlagEnum)
-      Flag = FlagEnum->getInitVal().getZExtValue();
-    const llvm::Regex TestRegex(DetectedPattern->getString(), Flag);
-    std::string RegexError;
-    if (!TestRegex.isValid(RegexError))
-      diag(DetectedPattern->getBeginLoc(), "invalid regex pattern: %0")
-          << RegexError << DetectedPattern->getSourceRange();
+  const auto *FlagInt = 
Result.Nodes.getNodeAs<IntegerLiteral>("regexFlagsInt");
+  const auto *FlagEnum =
+      Result.Nodes.getNodeAs<EnumConstantDecl>("regexFlagEnum");
+  unsigned int Flag = llvm::Regex::RegexFlags::NoFlags;
+  if (FlagInt)
+    Flag = FlagInt->getValue().getZExtValue();
+  if (FlagEnum)
+    Flag = FlagEnum->getInitVal().getZExtValue();
+  const llvm::Regex TestRegex(DetectedPattern->getString(), Flag);
+  std::string RegexError;
+  if (!TestRegex.isValid(RegexError))
+    diag(DetectedPattern->getBeginLoc(), "invalid regex pattern: %0")
+        << RegexError << DetectedPattern->getSourceRange();
 }
 
 } // namespace clang::tidy::llvm_check

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

Reply via email to