Index: clang-tools-extra/clang-tidy/CMakeLists.txt =================================================================== --- clang-tools-extra/clang-tidy/CMakeLists.txt +++ clang-tools-extra/clang-tidy/CMakeLists.txt @@ -38,4 +38,5 @@ add_subdirectory(mpi) add_subdirectory(performance) add_subdirectory(readability) +add_subdirectory(safety) add_subdirectory(utils) Index: clang-tools-extra/clang-tidy/safety/CMakeLists.txt =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/safety/CMakeLists.txt @@ -0,0 +1,14 @@ +set(LLVM_LINK_COMPONENTS support) + +add_clang_library(clangTidySafetyModule + SafetyTidyModule.cpp + NoVectorBoolCheck.cpp + + LINK_LIBS + clangAST + clangASTMatchers + clangBasic + clangLex + clangTidy + clangTidyUtils + ) Index: clang-tools-extra/clang-tidy/safety/NoVectorBoolCheck.h =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/safety/NoVectorBoolCheck.h @@ -0,0 +1,36 @@ +//===--- NoVectorBoolCheck.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_SAFETY_NO_VECTOR_BOOL_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_SAFETY_NO_VECTOR_BOOL_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace safety { + +/// This check finds instances of `std::vector`. +/// No fix is offered. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/safety-no-vector-bool.html +class NoVectorBoolCheck : public ClangTidyCheck { +public: + NoVectorBoolCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace safety +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_SAFETY_NO_VECTOR_BOOL_H Index: clang-tools-extra/clang-tidy/safety/NoVectorBoolCheck.cpp =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/safety/NoVectorBoolCheck.cpp @@ -0,0 +1,58 @@ +//===--- NoVectorBoolCheck.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 "NoVectorBoolCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace safety { + +void NoVectorBoolCheck::registerMatchers(MatchFinder *Finder) { + const auto isVectorBool = classTemplateSpecializationDecl( + hasName("::std::vector"), + hasTemplateArgument(0, refersToType(booleanType())), + hasTemplateArgument(1, refersToType(hasDeclaration(cxxRecordDecl( + matchesName("::std::allocator")))))); + + Finder->addMatcher(fieldDecl(hasType(isVectorBool)).bind("member"), this); + + Finder->addMatcher(varDecl(hasType(isVectorBool)).bind("variable"), this); + + Finder->addMatcher( + functionDecl(returns(hasDeclaration(isVectorBool))).bind("function"), + this); +} + +void NoVectorBoolCheck::check(const MatchFinder::MatchResult &Result) { + if (const auto *MatchedDecl = Result.Nodes.getNodeAs("member")) { + diag(MatchedDecl->getLocation(), + "member %0 is an instance of std::vector") + << MatchedDecl; + } else if (const auto *MatchedDecl = + Result.Nodes.getNodeAs("variable")) { + diag(MatchedDecl->getLocation(), + " variable %0 is an instance of std::vector") + << MatchedDecl; + } else if (const auto *MatchedDecl = + Result.Nodes.getNodeAs("function")) { + diag(MatchedDecl->getLocation(), + " function %0 returns an instance of std::vector") + << MatchedDecl; + } else { + llvm_unreachable("Unhandled binding in the matcher."); + } +} + +} // namespace safety +} // namespace tidy +} // namespace clang Index: clang-tools-extra/clang-tidy/safety/SafetyTidyModule.cpp =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/safety/SafetyTidyModule.cpp @@ -0,0 +1,38 @@ +//===------- SafetyTidyModule.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 "../ClangTidy.h" +#include "../ClangTidyModule.h" +#include "../ClangTidyModuleRegistry.h" +#include "NoVectorBoolCheck.h" + +namespace clang { +namespace tidy { +namespace safety { + +class SafetyModule : public ClangTidyModule { +public: + void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { + CheckFactories.registerCheck( + "safety-no-vector-bool"); + } +}; + +// Register the SafetyModule using this statically initialized variable. +static ClangTidyModuleRegistry::Add + X("safety-module", "Adds safety-critical checks."); + +} // namespace safety + +// This anchor is used to force the linker to link in the generated object file +// and thus register the SafetyModule. +volatile int SafetyModuleAnchorSource = 0; + +} // namespace tidy +} // namespace clang Index: clang-tools-extra/clang-tidy/tool/CMakeLists.txt =================================================================== --- clang-tools-extra/clang-tidy/tool/CMakeLists.txt +++ clang-tools-extra/clang-tidy/tool/CMakeLists.txt @@ -23,6 +23,7 @@ clangTidyMPIModule clangTidyPerformanceModule clangTidyReadabilityModule + clangTidySafetyModule clangTooling ) Index: clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp =================================================================== --- clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp +++ clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp @@ -475,6 +475,11 @@ static int LLVM_ATTRIBUTE_UNUSED ReadabilityModuleAnchorDestination = ReadabilityModuleAnchorSource; +// This anchor is used to force the linker to link the SafetyModule. +extern volatile int SafetyModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED SafetyModuleAnchorDestination = + SafetyModuleAnchorSource; + } // namespace tidy } // namespace clang Index: clang-tools-extra/docs/clang-tidy/checks/list.rst =================================================================== --- clang-tools-extra/docs/clang-tidy/checks/list.rst +++ clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -152,3 +152,4 @@ readability-simplify-boolean-expr readability-static-definition-in-anonymous-namespace readability-uniqueptr-delete-release + safety-no-vector-bool Index: clang-tools-extra/docs/clang-tidy/checks/safety-no-vector-bool.rst =================================================================== --- /dev/null +++ clang-tools-extra/docs/clang-tidy/checks/safety-no-vector-bool.rst @@ -0,0 +1,10 @@ +.. title:: clang-tidy - safety-no-vector-bool + +safety-no-vector-bool +===================== + +``std::vector`` cannot be accessed safely concurrently in the same way as +other ``std::vector`` specializations and is banned by some +safefty-critical-c++ standards like High Integrity C++. + +This check finds instances of ``std::vector``. No fix is offered. Index: clang-tools-extra/test/clang-tidy/safety-no-vector-bool.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/safety-no-vector-bool.cpp @@ -0,0 +1,37 @@ +// RUN: %check_clang_tidy %s safety-no-vector-bool %t + +namespace std +{ + template + class allocator {}; + + template > + class vector {}; +} + +std::vector v0; +// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: variable 'v0' is an instance of std::vector [safety-no-vector-bool] + +std::vector vb(); +// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: function 'vb' returns an instance of std::vector [safety-no-vector-bool] + +class C { + std::vector v_; +// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: member 'v_' is an instance of std::vector [safety-no-vector-bool] +}; + +typedef bool BoolTypedef; +std::vector v1; +// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: variable 'v1' is an instance of std::vector [safety-no-vector-bool] + +using vbool = std::vector; +vbool v2; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: variable 'v2' is an instance of std::vector [safety-no-vector-bool] + +std::vector v3; + +template +class user_allocator {}; + +std::vector> v4; +