[clang-tools-extra] [clang-tidy] Add cerrno check to bugprone (PR #213015)

via cfe-commits cfe-commits at lists.llvm.org
Thu Jul 30 05:49:02 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-tools-extra

Author: Csaba Zeitvogel (zeitcsabi)

<details>
<summary>Changes</summary>

This simple check is based on the cerrno portion of MSC38-C.

---
Full diff: https://github.com/llvm/llvm-project/pull/213015.diff


8 Files Affected:

- (modified) clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp (+3) 
- (modified) clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt (+1) 
- (added) clang-tools-extra/clang-tidy/bugprone/CerrnoCheck.cpp (+38) 
- (added) clang-tools-extra/clang-tidy/bugprone/CerrnoCheck.h (+35) 
- (modified) clang-tools-extra/docs/ReleaseNotes.rst (+5) 
- (added) clang-tools-extra/docs/clang-tidy/checks/bugprone/cerrno.rst (+17) 
- (modified) clang-tools-extra/docs/clang-tidy/checks/list.rst (+1) 
- (added) clang-tools-extra/test/clang-tidy/checkers/bugprone/cerrno.cpp (+25) 


``````````diff
diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
index 3aa39d10ceb5d..54f0e7345ff97 100644
--- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -18,6 +18,7 @@
 #include "BranchCloneCheck.h"
 #include "CapturingThisInMemberVariableCheck.h"
 #include "CastingThroughVoidCheck.h"
+#include "CerrnoCheck.h"
 #include "ChainedComparisonCheck.h"
 #include "CommandProcessorCheck.h"
 #include "ComparePointerToMemberVirtualFunctionCheck.h"
@@ -144,6 +145,8 @@ class BugproneModule : public ClangTidyModule {
         "bugprone-capturing-this-in-member-variable");
     CheckFactories.registerCheck<CastingThroughVoidCheck>(
         "bugprone-casting-through-void");
+    CheckFactories.registerCheck<CerrnoCheck>(
+        "bugprone-cerrno");
     CheckFactories.registerCheck<ChainedComparisonCheck>(
         "bugprone-chained-comparison");
     CheckFactories.registerCheck<CommandProcessorCheck>(
diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
index 43e85b1407f21..6345e61b3b126 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -15,6 +15,7 @@ add_clang_library(clangTidyBugproneModule STATIC
   BugproneTidyModule.cpp
   CapturingThisInMemberVariableCheck.cpp
   CastingThroughVoidCheck.cpp
+  CerrnoCheck.cpp
   ChainedComparisonCheck.cpp
   CommandProcessorCheck.cpp
   ComparePointerToMemberVirtualFunctionCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/bugprone/CerrnoCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/CerrnoCheck.cpp
new file mode 100644
index 0000000000000..8dbb685662084
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/CerrnoCheck.cpp
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "CerrnoCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+void CerrnoCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(varDecl(hasType(asString("int")), hasName("errno"), hasExternalFormalLinkage()).bind("errnoDecl"), this);
+}
+
+void CerrnoCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedDecl = Result.Nodes.getNodeAs<VarDecl>("errnoDecl"); // NULL?
+  const SourceManager &SM = *Result.SourceManager;
+  const auto Location = MatchedDecl->getLocation();
+  const auto FileID = SM.getFileID(Location);
+
+  unsigned Line = SM.getSpellingLineNumber(MatchedDecl->getBeginLoc());
+
+  const auto Diag = diag(Location, "errno declaration detected, include cerrno instead")
+      << FixItHint::CreateRemoval(CharSourceRange::getCharRange(SM.translateLineCol(FileID, Line, 1), SM.translateLineCol(FileID, Line + 1, 1)));
+
+  if (alreadyInserted)
+    return;
+
+  Diag << FixItHint::CreateInsertion(SM.getLocForStartOfFile(FileID), "#include <cerrno>\n");
+  alreadyInserted = true;
+}
+
+} // namespace clang::tidy::bugprone
diff --git a/clang-tools-extra/clang-tidy/bugprone/CerrnoCheck.h b/clang-tools-extra/clang-tidy/bugprone/CerrnoCheck.h
new file mode 100644
index 0000000000000..7517acd28a49f
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/CerrnoCheck.h
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_BUGPRONE_CERRNOCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_CERRNOCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::bugprone {
+
+/// Warns if you declare an extern int variable named 'errno'.
+///
+/// For the user-facing documentation see:
+/// https://clang.llvm.org/extra/clang-tidy/checks/bugprone/cerrno.html
+class CerrnoCheck : public ClangTidyCheck {
+public:
+  CerrnoCheck(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;
+  }
+private:
+  bool alreadyInserted = false;
+};
+
+} // namespace clang::tidy::bugprone
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_CERRNOCHECK_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 2581a9d3c5657..e3a19dffc931a 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -224,6 +224,11 @@ New checks
 
   Finds assignments within selection statements.
 
+- New :doc:`bugprone-cerrno
+  <clang-tidy/checks/bugprone/cerrno>` check.
+
+  Warns if you declare an extern int variable named 'errno'.
+
 - New :doc:`bugprone-missing-end-comparison
   <clang-tidy/checks/bugprone/missing-end-comparison>` check.
 
diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/cerrno.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/cerrno.rst
new file mode 100644
index 0000000000000..73ec1c76901af
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/cerrno.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - bugprone-cerrno
+
+bugprone-cerrno
+===============
+
+Warns if you declare an ``extern int`` variable named ``errno`` instead of including ``<cerrno>``.
+It is able to fix the problem by removing the line of the declaration and inserting ``#include <cerrno>``
+at the top of the file.
+
+For further reading, see `the page of SEI CERT C Coding Standard
+<https://cmu-sei.github.io/secure-coding-standards/sei-cert-c-coding-standard/rules/miscellaneous-msc/msc38-c/>`_.
+
+Example:
+
+.. code-block:: c++
+
+    extern int errno;
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 2a44dc78fbc89..355401cbdccc6 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -87,6 +87,7 @@ Clang-Tidy Checks
    :doc:`bugprone-branch-clone <bugprone/branch-clone>`,
    :doc:`bugprone-capturing-this-in-member-variable <bugprone/capturing-this-in-member-variable>`,
    :doc:`bugprone-casting-through-void <bugprone/casting-through-void>`,
+   :doc:`bugprone-cerrno <bugprone/cerrno>`, "Yes"
    :doc:`bugprone-chained-comparison <bugprone/chained-comparison>`,
    :doc:`bugprone-command-processor <bugprone/command-processor>`,
    :doc:`bugprone-compare-pointer-to-member-virtual-function <bugprone/compare-pointer-to-member-virtual-function>`,
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/cerrno.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/cerrno.cpp
new file mode 100644
index 0000000000000..40109d31aa26b
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/cerrno.cpp
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s bugprone-cerrno %t
+
+namespace cerrno_test_0 {
+    extern int errno;
+    // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: errno declaration detected, include cerrno instead [bugprone-cerrno]
+    // CHECK-FIXES: {{^}}{{$}}
+} // namespace cerrno_test_0
+
+namespace cerrno_test_1 {
+    extern "C" int errno;
+    // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: errno declaration detected, include cerrno instead [bugprone-cerrno]
+    // CHECK-FIXES: {{^}}{{$}}
+} // namespace cerrno_test_1
+
+namespace cerrno_test_2 { // all cases should be ignored in this namespace
+    extern bool errno;
+
+    void foo(int errno) {}
+
+    int fooo()
+    {
+        int errno = 0;
+        return errno;
+    }
+} // namespace cerrno_test_2

``````````

</details>


https://github.com/llvm/llvm-project/pull/213015


More information about the cfe-commits mailing list