[clang-tidy] Add cert-dcl58-cpp (do not modify the 'std' namespace) check.

Differential Revision: https://reviews.llvm.org/D23421

llvm-svn: 295435
This commit is contained in:
Gabor Horvath 2017-02-17 08:52:51 +00:00
parent 3c35491f02
commit e2fa53030e
9 changed files with 207 additions and 0 deletions

View File

@ -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<VariadicFunctionDefCheck>("cert-dcl50-cpp");
CheckFactories.registerCheck<misc::NewDeleteOverloadsCheck>(
"cert-dcl54-cpp");
CheckFactories.registerCheck<DontModifyStdNamespaceCheck>(
"cert-dcl58-cpp");
CheckFactories.registerCheck<google::build::UnnamedNamespaceInHeaderCheck>(
"cert-dcl59-cpp");
// OOP

View File

@ -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

View File

@ -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<NamespaceDecl>("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

View File

@ -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

View File

@ -57,6 +57,11 @@ The improvements are...
Improvements to clang-tidy
--------------------------
- New `cert-dcl58-cpp
<http://clang.llvm.org/extra/clang-tidy/checks/cert-dcl58-cpp.html>`_ check
Finds modification of the ``std`` or ``posix`` namespace.
- New `readability-misleading-indentation
<http://clang.llvm.org/extra/clang-tidy/checks/readability-misleading-indentation.html>`_ check

View File

@ -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
<https://www.securecoding.cert.org/confluence/display/cplusplus/DCL58-CPP.+Do+not+modify+the+standard+namespaces>`_.

View File

@ -8,6 +8,7 @@ Clang-Tidy Checks
cert-dcl03-c (redirects to misc-static-assert) <cert-dcl03-c>
cert-dcl50-cpp
cert-dcl54-cpp (redirects to misc-new-delete-overloads) <cert-dcl54-cpp>
cert-dcl58-cpp
cert-dcl59-cpp (redirects to google-build-namespaces) <cert-dcl59-cpp>
cert-env33-c
cert-err09-cpp (redirects to misc-throw-by-value-catch-by-reference) <cert-err09-cpp>

View File

@ -0,0 +1,24 @@
#pragma clang system_header
namespace std {
template<class T, T v>
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 <bool B>
using bool_constant = integral_constant<bool, B>;
using true_type = bool_constant<true>;
using false_type = bool_constant<false>;
template<class T>
struct is_error_code_enum : false_type {};
template<class T>
void swap(T &a, T &b);
}

View File

@ -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<MyError> : std::true_type {};
template<>
void swap<MyError>(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<MyError2> : std::true_type {};
int foobar;
}
using namespace std;
int x;