[clang-tidy] Add new check cppcoreguidelines-pro-bounds-array-to-pointer-decay
Summary: This check flags all array to pointer decays. Pointers should not be used as arrays. array_view is a bounds-checked, safe alternative to using pointers to access arrays. This rule is part of the "Bounds safety" profile of the C++ Core Guidelines, see https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#-bounds3-no-array-to-pointer-decay Reviewers: alexfh, sbenza, bkramer, aaron.ballman Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D13640 git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@251358 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
eaac82467f
Коммит
40fe18c79e
|
@ -2,6 +2,7 @@ set(LLVM_LINK_COMPONENTS support)
|
|||
|
||||
add_clang_library(clangTidyCppCoreGuidelinesModule
|
||||
CppCoreGuidelinesTidyModule.cpp
|
||||
ProBoundsArrayToPointerDecayCheck.cpp
|
||||
ProBoundsPointerArithmeticCheck.cpp
|
||||
ProTypeConstCastCheck.cpp
|
||||
ProTypeReinterpretCastCheck.cpp
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "../ClangTidyModule.h"
|
||||
#include "../ClangTidyModuleRegistry.h"
|
||||
#include "../misc/AssignOperatorSignatureCheck.h"
|
||||
#include "ProBoundsArrayToPointerDecayCheck.h"
|
||||
#include "ProBoundsPointerArithmeticCheck.h"
|
||||
#include "ProTypeConstCastCheck.h"
|
||||
#include "ProTypeReinterpretCastCheck.h"
|
||||
|
@ -26,6 +27,8 @@ namespace cppcoreguidelines {
|
|||
class CppCoreGuidelinesModule : public ClangTidyModule {
|
||||
public:
|
||||
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
|
||||
CheckFactories.registerCheck<ProBoundsArrayToPointerDecayCheck>(
|
||||
"cppcoreguidelines-pro-bounds-array-to-pointer-decay");
|
||||
CheckFactories.registerCheck<ProBoundsPointerArithmeticCheck>(
|
||||
"cppcoreguidelines-pro-bounds-pointer-arithmetic");
|
||||
CheckFactories.registerCheck<ProTypeConstCastCheck>(
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
//===--- ProBoundsArrayToPointerDecayCheck.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 "ProBoundsArrayToPointerDecayCheck.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
||||
|
||||
using namespace clang::ast_matchers;
|
||||
|
||||
namespace clang {
|
||||
namespace tidy {
|
||||
|
||||
AST_MATCHER_P(CXXForRangeStmt, hasRangeBeginEndStmt,
|
||||
ast_matchers::internal::Matcher<DeclStmt>, InnerMatcher) {
|
||||
const DeclStmt *const Stmt = Node.getBeginEndStmt();
|
||||
return (Stmt != nullptr && InnerMatcher.matches(*Stmt, Finder, Builder));
|
||||
}
|
||||
|
||||
AST_MATCHER(Stmt, isInsideOfRangeBeginEndStmt) {
|
||||
return stmt(hasAncestor(cxxForRangeStmt(
|
||||
hasRangeBeginEndStmt(hasDescendant(equalsNode(&Node))))))
|
||||
.matches(Node, Finder, Builder);
|
||||
}
|
||||
|
||||
void ProBoundsArrayToPointerDecayCheck::registerMatchers(MatchFinder *Finder) {
|
||||
if (!getLangOpts().CPlusPlus)
|
||||
return;
|
||||
|
||||
// The only allowed array to pointer decay
|
||||
// 1) just before array subscription
|
||||
// 2) inside a range-for over an array
|
||||
// 3) if it converts a string literal to a pointer
|
||||
Finder->addMatcher(
|
||||
implicitCastExpr(unless(hasParent(arraySubscriptExpr())),
|
||||
unless(hasParent(explicitCastExpr())),
|
||||
unless(isInsideOfRangeBeginEndStmt()),
|
||||
unless(hasSourceExpression(stringLiteral())))
|
||||
.bind("cast"),
|
||||
this);
|
||||
}
|
||||
|
||||
void ProBoundsArrayToPointerDecayCheck::check(
|
||||
const MatchFinder::MatchResult &Result) {
|
||||
const auto *MatchedCast = Result.Nodes.getNodeAs<ImplicitCastExpr>("cast");
|
||||
if (MatchedCast->getCastKind() != CK_ArrayToPointerDecay)
|
||||
return;
|
||||
|
||||
diag(MatchedCast->getExprLoc(), "do not implicitly decay an array into a "
|
||||
"pointer; consider using gsl::array_view or "
|
||||
"an explicit cast instead");
|
||||
}
|
||||
|
||||
} // namespace tidy
|
||||
} // namespace clang
|
|
@ -0,0 +1,34 @@
|
|||
//===--- ProBoundsArrayToPointerDecayCheck.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_ARRAY_TO_POINTER_DECAY_H
|
||||
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_BOUNDS_ARRAY_TO_POINTER_DECAY_H
|
||||
|
||||
#include "../ClangTidy.h"
|
||||
|
||||
namespace clang {
|
||||
namespace tidy {
|
||||
|
||||
/// This check flags all array to pointer decays
|
||||
///
|
||||
/// For the user-facing documentation see:
|
||||
/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-pro-bounds-array-to-pointer-decay.html
|
||||
class ProBoundsArrayToPointerDecayCheck : public ClangTidyCheck {
|
||||
public:
|
||||
ProBoundsArrayToPointerDecayCheck(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_ARRAY_TO_POINTER_DECAY_H
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
cppcoreguidelines-pro-bounds-array-to-pointer-decay
|
||||
===================================================
|
||||
|
||||
This check flags all array to pointer decays.
|
||||
|
||||
Pointers should not be used as arrays. array_view is a bounds-checked, safe alternative to using pointers to access arrays.
|
||||
|
||||
This rule is part of the "Bounds safety" profile of the C++ Core Guidelines, see
|
||||
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#-bounds3-no-array-to-pointer-decay
|
|
@ -4,6 +4,7 @@ List of clang-tidy Checks
|
|||
.. toctree::
|
||||
cert-setlongjmp
|
||||
cert-variadic-function-def
|
||||
cppcoreguidelines-pro-bounds-array-to-pointer-decay
|
||||
cppcoreguidelines-pro-bounds-pointer-arithmetic
|
||||
cppcoreguidelines-pro-type-const-cast
|
||||
cppcoreguidelines-pro-type-reinterpret-cast
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-array-to-pointer-decay %t
|
||||
#include <stddef.h>
|
||||
|
||||
namespace gsl {
|
||||
template <class T>
|
||||
class array_view {
|
||||
public:
|
||||
template <class U, size_t N>
|
||||
array_view(U (&arr)[N]);
|
||||
};
|
||||
}
|
||||
|
||||
void pointerfun(int *p);
|
||||
void arrayfun(int p[]);
|
||||
void arrayviewfun(gsl::array_view<int> &p);
|
||||
size_t s();
|
||||
|
||||
void f() {
|
||||
int a[5];
|
||||
pointerfun(a);
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not implicitly decay an array into a pointer; consider using gsl::array_view or an explicit cast instead [cppcoreguidelines-pro-bounds-array-to-pointer-decay]
|
||||
pointerfun((int *)a); // OK, explicit cast
|
||||
arrayfun(a);
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not implicitly decay an array into a pointer
|
||||
|
||||
pointerfun(a + s() - 10); // Convert to &a[g() - 10];
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not implicitly decay an array into a pointer
|
||||
|
||||
gsl::array_view<int> av(a);
|
||||
arrayviewfun(av); // OK
|
||||
|
||||
int i = a[0]; // OK
|
||||
pointerfun(&a[0]); // OK
|
||||
|
||||
for (auto &e : a) // OK, iteration internally decays array to pointer
|
||||
e = 1;
|
||||
}
|
||||
|
||||
const char *g() {
|
||||
return "clang"; // OK, decay string literal to pointer
|
||||
}
|
Загрузка…
Ссылка в новой задаче