diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp index 3aa39d10ceb5d..e550433ddacd2 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 "CustomErrnoDeclarationCheck.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( "bugprone-casting-through-void"); + CheckFactories.registerCheck( + "bugprone-custom-errno-declaration"); CheckFactories.registerCheck( "bugprone-chained-comparison"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt index 43e85b1407f21..8cf6e6f86cd36 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 + CustomErrnoDeclarationCheck.cpp ChainedComparisonCheck.cpp CommandProcessorCheck.cpp ComparePointerToMemberVirtualFunctionCheck.cpp diff --git a/clang-tools-extra/clang-tidy/bugprone/CustomErrnoDeclarationCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/CustomErrnoDeclarationCheck.cpp new file mode 100644 index 0000000000000..e3b6e8f51bb3b --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/CustomErrnoDeclarationCheck.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 "CustomErrnoDeclarationCheck.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::bugprone { + +void CustomErrnoDeclarationCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher(varDecl(hasType(asString("int")), hasName("errno"), hasExternalFormalLinkage()).bind("errnoDecl"), this); +} + +void CustomErrnoDeclarationCheck::check(const MatchFinder::MatchResult &Result) { + const auto *MatchedDecl = Result.Nodes.getNodeAs("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 \n"); + alreadyInserted = true; +} + +} // namespace clang::tidy::bugprone diff --git a/clang-tools-extra/clang-tidy/bugprone/CustomErrnoDeclarationCheck.h b/clang-tools-extra/clang-tidy/bugprone/CustomErrnoDeclarationCheck.h new file mode 100644 index 0000000000000..a1e16d412db49 --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/CustomErrnoDeclarationCheck.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_CUSTOMERRNODECLARATIONCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_CUSTOMERRNODECLARATIONCHECK_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/custom-errno-declaration.html +class CustomErrnoDeclarationCheck : public ClangTidyCheck { +public: + CustomErrnoDeclarationCheck(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_CUSTOMERRNODECLARATIONCHECK_H diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 2581a9d3c5657..9d348501a89b6 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-custom-errno-declaration + ` check. + + Finds custom declarations of ``extern int`` variable named ``errno``. + - New :doc:`bugprone-missing-end-comparison ` check. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/custom-errno-declaration.md b/clang-tools-extra/docs/clang-tidy/checks/bugprone/custom-errno-declaration.md new file mode 100644 index 0000000000000..2fd9f51a56688 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/custom-errno-declaration.md @@ -0,0 +1,14 @@ +# bugprone-custom-errno-declaration + +Finds custom declarations of `extern int` variable named `errno`. +It is able to fix the problem by removing the line of the declaration and inserting `#include ` +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: + +```cpp +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..6401d99ca43a0 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -93,6 +93,7 @@ Clang-Tidy Checks :doc:`bugprone-copy-constructor-init `, "Yes" :doc:`bugprone-copy-constructor-mutates-argument `, :doc:`bugprone-crtp-constructor-accessibility `, "Yes" + :doc:`bugprone-custom-errno-declaration `, "Yes" :doc:`bugprone-dangling-handle `, :doc:`bugprone-default-operator-new-on-overaligned-type `, :doc:`bugprone-derived-method-shadowing-base-method `, diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/custom-errno-declaration.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/custom-errno-declaration.cpp new file mode 100644 index 0000000000000..0d87784e4d252 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/custom-errno-declaration.cpp @@ -0,0 +1,25 @@ +// RUN: %check_clang_tidy %s bugprone-custom-errno-declaration %t + +namespace cerrno_test_0 { + extern int errno; + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: errno declaration detected, include cerrno instead [bugprone-custom-errno-declaration] + // 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-custom-errno-declaration] + // 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