From e2fa53030e1457060e5b88d4168be9c5b121054c Mon Sep 17 00:00:00 2001 From: Gabor Horvath Date: Fri, 17 Feb 2017 08:52:51 +0000 Subject: [PATCH] [clang-tidy] Add cert-dcl58-cpp (do not modify the 'std' namespace) check. Differential Revision: https://reviews.llvm.org/D23421 llvm-svn: 295435 --- .../clang-tidy/cert/CERTTidyModule.cpp | 3 + .../clang-tidy/cert/CMakeLists.txt | 1 + .../cert/DontModifyStdNamespaceCheck.cpp | 49 ++++++++++++++ .../cert/DontModifyStdNamespaceCheck.h | 36 ++++++++++ clang-tools-extra/docs/ReleaseNotes.rst | 5 ++ .../docs/clang-tidy/checks/cert-dcl58-cpp.rst | 21 ++++++ .../docs/clang-tidy/checks/list.rst | 1 + .../Inputs/Headers/system-header-simulation.h | 24 +++++++ .../test/clang-tidy/cert-dcl58-cpp.cpp | 67 +++++++++++++++++++ 9 files changed, 207 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/cert/DontModifyStdNamespaceCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/cert/DontModifyStdNamespaceCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/cert-dcl58-cpp.rst create mode 100644 clang-tools-extra/test/clang-tidy/Inputs/Headers/system-header-simulation.h create mode 100644 clang-tools-extra/test/clang-tidy/cert-dcl58-cpp.cpp diff --git a/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp b/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp index d28f013aadf0..1f1f7d7a7534 100644 --- a/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp @@ -17,6 +17,7 @@ #include "../misc/StaticAssertCheck.h" #include "../misc/ThrowByValueCatchByReferenceCheck.h" #include "CommandProcessorCheck.h" +#include "DontModifyStdNamespaceCheck.h" #include "FloatLoopCounter.h" #include "LimitedRandomnessCheck.h" #include "SetLongJmpCheck.h" @@ -37,6 +38,8 @@ public: CheckFactories.registerCheck("cert-dcl50-cpp"); CheckFactories.registerCheck( "cert-dcl54-cpp"); + CheckFactories.registerCheck( + "cert-dcl58-cpp"); CheckFactories.registerCheck( "cert-dcl59-cpp"); // OOP diff --git a/clang-tools-extra/clang-tidy/cert/CMakeLists.txt b/clang-tools-extra/clang-tidy/cert/CMakeLists.txt index 7a6b44a0272e..0bd2a3e66977 100644 --- a/clang-tools-extra/clang-tidy/cert/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/cert/CMakeLists.txt @@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS support) add_clang_library(clangTidyCERTModule CERTTidyModule.cpp CommandProcessorCheck.cpp + DontModifyStdNamespaceCheck.cpp FloatLoopCounter.cpp LimitedRandomnessCheck.cpp SetLongJmpCheck.cpp diff --git a/clang-tools-extra/clang-tidy/cert/DontModifyStdNamespaceCheck.cpp b/clang-tools-extra/clang-tidy/cert/DontModifyStdNamespaceCheck.cpp new file mode 100644 index 000000000000..e5759a5215a6 --- /dev/null +++ b/clang-tools-extra/clang-tidy/cert/DontModifyStdNamespaceCheck.cpp @@ -0,0 +1,49 @@ +//===--- DontModifyStdNamespaceCheck.cpp - clang-tidy----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DontModifyStdNamespaceCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace cert { + +void DontModifyStdNamespaceCheck::registerMatchers(MatchFinder *Finder) { + if (!getLangOpts().CPlusPlus) + return; + + Finder->addMatcher( + namespaceDecl(unless(isExpansionInSystemHeader()), + anyOf(hasName("std"), hasName("posix")), + has(decl(unless(anyOf( + functionDecl(isExplicitTemplateSpecialization()), + cxxRecordDecl(isExplicitTemplateSpecialization())))))) + .bind("nmspc"), + this); +} + +void DontModifyStdNamespaceCheck::check( + const MatchFinder::MatchResult &Result) { + const auto *N = Result.Nodes.getNodeAs("nmspc"); + + // Only consider top level namespaces. + if (N->getParent() != Result.Context->getTranslationUnitDecl()) + return; + + diag(N->getLocation(), + "modification of %0 namespace can result in undefined behavior") + << N; +} + +} // namespace cert +} // namespace tidy +} // namespace clang diff --git a/clang-tools-extra/clang-tidy/cert/DontModifyStdNamespaceCheck.h b/clang-tools-extra/clang-tidy/cert/DontModifyStdNamespaceCheck.h new file mode 100644 index 000000000000..0cc23f79cab3 --- /dev/null +++ b/clang-tools-extra/clang-tidy/cert/DontModifyStdNamespaceCheck.h @@ -0,0 +1,36 @@ +//===--- DontModifyStdNamespaceCheck.h - clang-tidy--------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_DONT_MODIFY_STD_NAMESPACE_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_DONT_MODIFY_STD_NAMESPACE_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace cert { + +/// Modification of the std or posix namespace can result in undefined behavior. +/// This check warns for such modifications. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/cert-msc53-cpp.html +class DontModifyStdNamespaceCheck : public ClangTidyCheck { +public: + DontModifyStdNamespaceCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace cert +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_DONT_MODIFY_STD_NAMESPACE_H diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 4561a660fdf3..e793a4ada07c 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -57,6 +57,11 @@ The improvements are... Improvements to clang-tidy -------------------------- +- New `cert-dcl58-cpp + `_ check + + Finds modification of the ``std`` or ``posix`` namespace. + - New `readability-misleading-indentation `_ check diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert-dcl58-cpp.rst b/clang-tools-extra/docs/clang-tidy/checks/cert-dcl58-cpp.rst new file mode 100644 index 000000000000..a86d1b981ee2 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/cert-dcl58-cpp.rst @@ -0,0 +1,21 @@ +.. title:: clang-tidy - cert-dcl58-cpp + +cert-dcl58-cpp +============== + +Modification of the ``std`` or ``posix`` namespace can result in undefined +behavior. +This check warns for such modifications. + +Examples: + +.. code-block:: c++ + + namespace std { + int x; // May cause undefined behavior. + } + + +This check corresponds to the CERT C++ Coding Standard rule +`DCL58-CPP. Do not modify the standard namespaces +`_. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index f1088a62402b..216e0b70c8df 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -8,6 +8,7 @@ Clang-Tidy Checks cert-dcl03-c (redirects to misc-static-assert) cert-dcl50-cpp cert-dcl54-cpp (redirects to misc-new-delete-overloads) + cert-dcl58-cpp cert-dcl59-cpp (redirects to google-build-namespaces) cert-env33-c cert-err09-cpp (redirects to misc-throw-by-value-catch-by-reference) diff --git a/clang-tools-extra/test/clang-tidy/Inputs/Headers/system-header-simulation.h b/clang-tools-extra/test/clang-tidy/Inputs/Headers/system-header-simulation.h new file mode 100644 index 000000000000..0df5305e5afb --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/Inputs/Headers/system-header-simulation.h @@ -0,0 +1,24 @@ +#pragma clang system_header + +namespace std { + +template +struct integral_constant { + static constexpr T value = v; + typedef T value_type; + typedef integral_constant type; + constexpr operator value_type() const noexcept { return value; } +}; + +template +using bool_constant = integral_constant; +using true_type = bool_constant; +using false_type = bool_constant; + +template +struct is_error_code_enum : false_type {}; + +template +void swap(T &a, T &b); +} + diff --git a/clang-tools-extra/test/clang-tidy/cert-dcl58-cpp.cpp b/clang-tools-extra/test/clang-tidy/cert-dcl58-cpp.cpp new file mode 100644 index 000000000000..34ee368dffe2 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/cert-dcl58-cpp.cpp @@ -0,0 +1,67 @@ +// RUN: %check_clang_tidy %s cert-dcl58-cpp %t -- -- -std=c++1z -I %S/Inputs/Headers + +#include "system-header-simulation.h" + +namespace A { + namespace B { + int b; + } +} + +namespace A { + namespace B { + int c; + } +} + +namespace posix { +// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: modification of 'posix' namespace can result in undefined behavior [cert-dcl58-cpp] + namespace vmi { + } +} + +namespace std { +// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: modification of 'std' namespace can + int stdInt; +} + +namespace foobar { + namespace std { + int bar; + } +} + +namespace posix::a { +// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: modification of 'posix' namespace +} + +enum class MyError { + ErrorA, + ErrorB +}; + +namespace std { +template <> +struct is_error_code_enum : std::true_type {}; + +template<> +void swap(MyError &a, MyError &b); +} + +enum class MyError2 { + Error2A, + Error2B +}; + +namespace std { +// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: modification of 'std' namespace +template <> +struct is_error_code_enum : std::true_type {}; + +int foobar; +} + +using namespace std; + +int x; +