https://github.com/furtib updated https://github.com/llvm/llvm-project/pull/207407
>From 05271eeb77b9d7d97184208fe6e80088147c9222 Mon Sep 17 00:00:00 2001 From: "F.Tibor" <[email protected]> Date: Mon, 8 Jun 2026 23:43:38 +0200 Subject: [PATCH 1/5] [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.rst | 5 + .../docs/clang-tidy/checks/list.rst | 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 bec3ba50c81c5..2f5d136108191 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 918af88c979e0..16409770f0467 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 0000000000000..f9f2b58e424f7 --- /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 0000000000000..17891713e62ee --- /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.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 42e4020f5f85c..221acb5f98081 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -318,6 +318,11 @@ New checks Checks for presence or absence of trailing commas in enum definitions and initializer lists. +- New :doc:`llvm-regex + <clang-tidy/checks/llvm/regex>` check. + + Detects malformed regex patterns used in ``llvm::Regex``. + New check aliases ^^^^^^^^^^^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index 2a44dc78fbc89..4b3bacfa8a42e 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -251,6 +251,7 @@ Clang-Tidy Checks :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 0000000000000..837181a8ea4a6 --- /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 0000000000000..229b35f2eb204 --- /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 1cce3f6b96c489913c8e3897c15b8b94949d2df7 Mon Sep 17 00:00:00 2001 From: "F.Tibor" <[email protected]> Date: Sat, 4 Jul 2026 10:57:53 +0200 Subject: [PATCH 2/5] 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.rst | 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 f9f2b58e424f7..57f6fa9588adf 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 17891713e62ee..e18bda161ae43 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.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index 4b3bacfa8a42e..be5305a6537ea 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -251,7 +251,7 @@ Clang-Tidy Checks :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 837181a8ea4a6..f570fac85c867 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 229b35f2eb204..c83fa9a85c501 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 39c315ecd3d5e0bf8bcf97aebd081d2c4e1f6ee7 Mon Sep 17 00:00:00 2001 From: "F.Tibor" <[email protected]> Date: Sat, 4 Jul 2026 11:20:06 +0200 Subject: [PATCH 3/5] Documentation fixes --- clang-tools-extra/docs/ReleaseNotes.rst | 11 ++++++----- .../docs/clang-tidy/checks/llvm/regex.rst | 18 ++++++++++-------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 221acb5f98081..eed1f0bfb610a 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -247,6 +247,12 @@ New checks derived type thereof. Also does similar analysis for calls to ``isa<>`` that always return ``true``. + - New :doc:`llvm-regex + <clang-tidy/checks/llvm/regex>` check. + + Detects malformed regex patterns defined in a single string literal + to catch mistakes at compile time. + - New :doc:`llvm-type-switch-case-types <clang-tidy/checks/llvm/type-switch-case-types>` check. @@ -318,11 +324,6 @@ New checks Checks for presence or absence of trailing commas in enum definitions and initializer lists. -- New :doc:`llvm-regex - <clang-tidy/checks/llvm/regex>` check. - - Detects malformed regex patterns used in ``llvm::Regex``. - 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 f570fac85c867..604520f3d979a 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 26158da48b34328f9cb5c8fe56dce95a54535eaa Mon Sep 17 00:00:00 2001 From: "F.Tibor" <[email protected]> Date: Sat, 4 Jul 2026 11:20:32 +0200 Subject: [PATCH 4/5] 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 c83fa9a85c501..88de3539da583 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 108ec1a770c8bf0c9f23459ff6c84d70a83a446a Mon Sep 17 00:00:00 2001 From: "F.Tibor" <[email protected]> Date: Sat, 4 Jul 2026 11:36:39 +0200 Subject: [PATCH 5/5] 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.rst | 4 ++-- clang-tools-extra/docs/clang-tidy/checks/list.rst | 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 2f5d136108191..563c05d14232a 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 57f6fa9588adf..ca23dcc8c9650 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 e18bda161ae43..177a47b668dc1 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 16409770f0467..549867beec25d 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.rst b/clang-tools-extra/docs/ReleaseNotes.rst index eed1f0bfb610a..e1be5993517a6 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -247,8 +247,8 @@ New checks derived type thereof. Also does similar analysis for calls to ``isa<>`` that always return ``true``. - - 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.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index be5305a6537ea..d7a0878e0eb1b 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -246,12 +246,12 @@ Clang-Tidy Checks :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 604520f3d979a..2cba3766608e7 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 88de3539da583..440c59eea50f0 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> _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
