Index: clang-tidy/CMakeLists.txt =================================================================== --- clang-tidy/CMakeLists.txt +++ clang-tidy/CMakeLists.txt @@ -27,6 +27,7 @@ add_subdirectory(tool) add_subdirectory(llvm) +add_subdirectory(cppcoreguidelines) add_subdirectory(google) add_subdirectory(misc) add_subdirectory(modernize) Index: clang-tidy/Makefile =================================================================== --- clang-tidy/Makefile +++ clang-tidy/Makefile @@ -11,6 +11,6 @@ LIBRARYNAME := clangTidy include $(CLANG_LEVEL)/../../Makefile.config -DIRS = utils readability llvm google misc modernize tool +DIRS = utils readability llvm google misc modernize tool cppcoreguidelines include $(CLANG_LEVEL)/Makefile Index: clang-tidy/add_new_check.py =================================================================== --- clang-tidy/add_new_check.py +++ clang-tidy/add_new_check.py @@ -147,7 +147,8 @@ # Modifies the module to include the new check. def adapt_module(module_path, module, check_name, check_name_camel): - filename = os.path.join(module_path, module.capitalize() + 'TidyModule.cpp') + modulecpp = filter(lambda p: p.lower() == module.lower() + "tidymodule.cpp", os.listdir(module_path))[0] + filename = os.path.join(module_path, modulecpp) with open(filename, 'r') as f: lines = f.readlines() Index: clang-tidy/cppcoreguidelines/CMakeLists.txt =================================================================== --- /dev/null +++ clang-tidy/cppcoreguidelines/CMakeLists.txt @@ -0,0 +1,16 @@ +set(LLVM_LINK_COMPONENTS support) + +add_clang_library(clangTidyCppCoreGuidelinesModule + CppCoreGuidelinesTidyModule.cpp + ProBoundsPointerArithmeticCheck.cpp + ProTypeReinterpretCastCheck.cpp + + LINK_LIBS + clangAST + clangASTMatchers + clangBasic + clangLex + clangTidy + clangTidyUtils + clangTooling + ) Index: clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp =================================================================== --- /dev/null +++ clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp @@ -0,0 +1,41 @@ +//===--- CppCoreGuidelinesModule.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 "ProBoundsPointerArithmeticCheck.h" +#include "ProTypeReinterpretCastCheck.h" + +namespace clang { +namespace tidy { +namespace cppcoreguidelines { + +class CppCoreGuidelinesModule : public ClangTidyModule { +public: + void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { + CheckFactories.registerCheck( + "cppcoreguidelines-pro-bounds-pointer-arithmetic"); + CheckFactories.registerCheck( + "cppcoreguidelines-pro-type-reinterpret-cast"); + } +}; + +// Register the LLVMTidyModule using this statically initialized variable. +static ClangTidyModuleRegistry::Add + X("cppcoreguidelines-module", "Adds checks for the C++ Core Guidelines."); + +} // namespace cppcoreguidelines + +// This anchor is used to force the linker to link in the generated object file +// and thus register the CppCoreGuidelinesModule. +volatile int CppCoreGuidelinesModuleAnchorSource = 0; + +} // namespace tidy +} // namespace clang Index: clang-tidy/cppcoreguidelines/Makefile =================================================================== --- clang-tidy/cppcoreguidelines/Makefile +++ clang-tidy/cppcoreguidelines/Makefile @@ -1,4 +1,4 @@ -##===- tools/extra/clang-tidy/Makefile ---------------------*- Makefile -*-===## +##===- clang-tidy/cppcoreguidelines/Makefile ----------------------------*- Makefile -*-===## # # The LLVM Compiler Infrastructure # @@ -6,11 +6,7 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## - -CLANG_LEVEL := ../../.. -LIBRARYNAME := clangTidy -include $(CLANG_LEVEL)/../../Makefile.config - -DIRS = utils readability llvm google misc modernize tool +CLANG_LEVEL := ../../../.. +LIBRARYNAME := clangTidyCppCoreGuidelinesModule include $(CLANG_LEVEL)/Makefile Index: clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.h =================================================================== --- /dev/null +++ clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.h @@ -0,0 +1,34 @@ +//===--- ProBoundsPointerArithmeticCheck.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_CPPCOREGUIDELINES_PRO_BOUNDS_POINTER_ARITHMETIC_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_BOUNDS_POINTER_ARITHMETIC_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { + +/// Flags all kinds of pointer arithmetic +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-pro-bounds-pointer-arithmetic.html +class ProBoundsPointerArithmeticCheck : public ClangTidyCheck { +public: + ProBoundsPointerArithmeticCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_BOUNDS_POINTER_ARITHMETIC_H + Index: clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp @@ -0,0 +1,52 @@ +//===--- ProBoundsPointerArithmeticCheck.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 "ProBoundsPointerArithmeticCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { + +void ProBoundsPointerArithmeticCheck::registerMatchers(MatchFinder *Finder) { + if (!getLangOpts().CPlusPlus) + return; + + // We exclude the case where one subtracts two pointers, because that cannot + // yield an invalid pointer + Finder->addMatcher( + binaryOperator(anyOf(hasOperatorName("+"), hasOperatorName("-"), + hasOperatorName("+="), hasOperatorName("-=")), + hasEitherOperand(hasType(pointerType())), + hasEitherOperand(hasType(isInteger()))).bind("expr"), + this); + + Finder->addMatcher( + unaryOperator(anyOf(hasOperatorName("++"), hasOperatorName("--")), + hasUnaryOperand(hasType(pointerType()))).bind("expr"), + this); + + Finder->addMatcher( + arraySubscriptExpr(hasBase(implicitCastExpr(hasSourceExpression( + hasType(pointerType()))))).bind("expr"), + this); +} + +void +ProBoundsPointerArithmeticCheck::check(const MatchFinder::MatchResult &Result) { + const auto *MatchedExpr = Result.Nodes.getNodeAs("expr"); + + diag(MatchedExpr->getExprLoc(), + "do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1)"); +} + +} // namespace tidy +} // namespace clang Index: clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.h =================================================================== --- /dev/null +++ clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.h @@ -0,0 +1,33 @@ +//===--- ProTypeReinterpretCast.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_CPPCOREGUIDELINES_PRO_TYPE_REINTERPRETCAST_CHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_TYPE_REINTERPRETCAST_CHECK_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { + +/// Flags all occurrences of reinterpret_cast +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/misc-no-reinterpret-cast.html +class ProTypeReinterpretCastCheck : public ClangTidyCheck { +public: + ProTypeReinterpretCastCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_TYPE_REINTERPRETCAST_CHECK_H Index: clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.cpp @@ -0,0 +1,34 @@ +//===--- ProTypeReinterpretCastCheck.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 "ProTypeReinterpretCastCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { + +void ProTypeReinterpretCastCheck::registerMatchers(MatchFinder *Finder) { + if (!getLangOpts().CPlusPlus) + return; + + Finder->addMatcher(cxxReinterpretCastExpr().bind("cast"), this); +} + +void ProTypeReinterpretCastCheck::check(const MatchFinder::MatchResult &Result) { + const auto *MatchedCast = + Result.Nodes.getNodeAs("cast"); + diag(MatchedCast->getOperatorLoc(), + "do not use reinterpret_cast (C++ Core Guidelines, rule Type.1)"); +} + +} // namespace tidy +} // namespace clang Index: clang-tidy/tool/CMakeLists.txt =================================================================== --- clang-tidy/tool/CMakeLists.txt +++ clang-tidy/tool/CMakeLists.txt @@ -10,6 +10,7 @@ clangASTMatchers clangBasic clangTidy + clangTidyCppCoreGuidelinesModule clangTidyGoogleModule clangTidyLLVMModule clangTidyMiscModule Index: clang-tidy/tool/ClangTidyMain.cpp =================================================================== --- clang-tidy/tool/ClangTidyMain.cpp +++ clang-tidy/tool/ClangTidyMain.cpp @@ -352,6 +352,11 @@ static int LLVM_ATTRIBUTE_UNUSED LLVMModuleAnchorDestination = LLVMModuleAnchorSource; +// This anchor is used to force the linker to link the CppCoreGuidelinesModule. +extern volatile int CppCoreGuidelinesModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED CppCoreGuidelinesModuleAnchorDestination = + CppCoreGuidelinesModuleAnchorSource; + // This anchor is used to force the linker to link the GoogleModule. extern volatile int GoogleModuleAnchorSource; static int LLVM_ATTRIBUTE_UNUSED GoogleModuleAnchorDestination = Index: clang-tidy/tool/Makefile =================================================================== --- clang-tidy/tool/Makefile +++ clang-tidy/tool/Makefile @@ -16,7 +16,9 @@ include $(CLANG_LEVEL)/../../Makefile.config LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option -USEDLIBS = clangTidy.a clangTidyLLVMModule.a clangTidyGoogleModule.a \ +USEDLIBS = clangTidy.a clangTidyLLVMModule.a \ + clangTidyCppCoreGuidelinesModule.a \ + clangTidyGoogleModule.a \ clangTidyMiscModule.a clangTidyModernizeModule.a clangTidyReadability.a \ clangTidyUtils.a clangStaticAnalyzerFrontend.a \ clangStaticAnalyzerCheckers.a clangStaticAnalyzerCore.a \ Index: docs/clang-tidy/checks/cppcoreguidelines-pro-bounds-pointer-arithmetic.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/cppcoreguidelines-pro-bounds-pointer-arithmetic.rst @@ -0,0 +1,10 @@ +cppcoreguidelines-pro-bounds-pointer-arithmetic +=============================================== + +This check flags all usage of pointer arithmetic, because it could lead to an invalid pointer. +Subtraction of two pointers is not flagged by this check. + +Pointers should only refer to single objects, and pointer arithmetic is fragile and easy to get wrong. array_view is a bounds-checked, safe type for accessing arrays of data. + +This rule is part of the "Bounds safety" profile of the C++ Core Guidelines, see +https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#-bounds1-dont-use-pointer-arithmetic-use-array_view-instead Index: docs/clang-tidy/checks/cppcoreguidelines-pro-type-reinterpret-cast.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/cppcoreguidelines-pro-type-reinterpret-cast.rst @@ -0,0 +1,9 @@ +cppcoreguidelines-pro-type-reinterpret-cast +=========================================== + +This check flags all uses of reinterpret_cast in C++ code. + +Use of these casts can violate type safety and cause the program to access a variable that is actually of type X to be accessed as if it were of an unrelated type Z. + +This rule is part of the "Type safety" profile of the C++ Core Guidelines, see +https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#-type1-dont-use-reinterpret_cast. Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -2,6 +2,8 @@ ========================= .. toctree:: + cppcoreguidelines-pro-bounds-pointer-arithmetic + cppcoreguidelines-pro-type-reinterpret-cast google-build-explicit-make-pair google-build-namespaces google-build-using-namespace Index: test/clang-tidy/cppcoreguidelines-pro-bounds-pointer-arithmetic.cpp =================================================================== --- /dev/null +++ test/clang-tidy/cppcoreguidelines-pro-bounds-pointer-arithmetic.cpp @@ -0,0 +1,52 @@ +// RUN: %python %S/check_clang_tidy.py %s cppcoreguidelines-pro-bounds-pointer-arithmetic %t + + +enum E { + ENUM_LITERAL = 1 +}; + +int i = 4; +int j = 1; +int* p = 0; +int* q = 0; + +void fail() { + q = p + 4; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [cppcoreguidelines-pro-bounds-pointer-arithmetic] + q = p - 1; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [cppcoreguidelines-pro-bounds-pointer-arithmetic] + p += 4; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [cppcoreguidelines-pro-bounds-pointer-arithmetic] + q -= 1; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [cppcoreguidelines-pro-bounds-pointer-arithmetic] + p = q - ENUM_LITERAL; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [cppcoreguidelines-pro-bounds-pointer-arithmetic] + p = q + ENUM_LITERAL; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [cppcoreguidelines-pro-bounds-pointer-arithmetic] + p++; + // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [cppcoreguidelines-pro-bounds-pointer-arithmetic] + ++p; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [cppcoreguidelines-pro-bounds-pointer-arithmetic] + p--; + // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [cppcoreguidelines-pro-bounds-pointer-arithmetic] + --p; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [cppcoreguidelines-pro-bounds-pointer-arithmetic] + i = p[1]; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use pointer arithmetic (C++ Core Guidelines, rule Bounds.1) [cppcoreguidelines-pro-bounds-pointer-arithmetic] +} + +void okey() { + int a[3]; + i = a[2]; //OK, access to array + + i++; + ++i; + i--; + --i; + i += 1; + i -= 1; + i = j + 1; + i = j - 1; + + auto diff = p - q; //OK, result is arithmetic +} Index: test/clang-tidy/cppcoreguidelines-pro-type-reinterpret-cast.cpp =================================================================== --- /dev/null +++ test/clang-tidy/cppcoreguidelines-pro-type-reinterpret-cast.cpp @@ -0,0 +1,6 @@ +// RUN: %python %S/check_clang_tidy.py %s cppcoreguidelines-pro-type-reinterpret-cast %t + +int i = 0; +void* j; +void f() { j = reinterpret_cast(i); } +// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not use reinterpret_cast (C++ Core Guidelines, rule Type.1) [cppcoreguidelines-pro-type-reinterpret-cast]