From 55020566edcc1c3a718e43d29eb4d3f17c800472 Mon Sep 17 00:00:00 2001 From: Matthias Gehre Date: Tue, 17 Nov 2015 23:43:20 +0000 Subject: [clang-tidy] add check cppcoreguidelines-pro-bounds-constant-array-index Summary: This check flags all array subscriptions on static arrays and std::arrays that either have a non-compile-time-constant index or are out of bounds. Dynamic accesses into arrays are difficult for both tools and humans to validate as safe. array_view is a bounds-checked, safe type for accessing arrays of data. at() is another alternative that ensures single accesses are bounds-checked. If iterators are needed to access an array, use the iterators from an array_view constructed over the array. This rule is part of the "Bounds safety" profile of the C++ Core Guidelines, see https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#-bounds2-only-index-into-arrays-using-constant-expressions Reviewers: alexfh, sbenza, bkramer, aaron.ballman Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D13746 llvm-svn: 253401 --- ...eguidelines-pro-bounds-constant-array-index.cpp | 69 ++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index.cpp (limited to 'clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index.cpp') diff --git a/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index.cpp b/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index.cpp new file mode 100644 index 00000000000..aa19adf533e --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-bounds-constant-array-index.cpp @@ -0,0 +1,69 @@ +// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-constant-array-index %t -- -config='{CheckOptions: [{key: cppcoreguidelines-pro-bounds-constant-array-index.GslHeader, value: "dir1/gslheader.h"}]}' -- -std=c++11 +#include +// CHECK-FIXES: #include "dir1/gslheader.h" + +namespace gsl { + template + T& at( T(&a)[N], size_t index ); + + template + T& at( std::array &a, size_t index ); +} + +constexpr int const_index(int base) { + return base + 3; +} + +void f(std::array a, int pos) { + a [ pos / 2 /*comment*/] = 1; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use array subscript when the index is not a compile-time constant; use gsl::at() instead [cppcoreguidelines-pro-bounds-constant-array-index] + // CHECK-FIXES: gsl::at(a, pos / 2 /*comment*/) = 1; + int j = a[pos - 1]; + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: do not use array subscript when the index is not a compile-time constant; use gsl::at() instead + // CHECK-FIXES: int j = gsl::at(a, pos - 1); + + a.at(pos-1) = 2; // OK, at() instead of [] + gsl::at(a, pos-1) = 2; // OK, gsl::at() instead of [] + + a[-1] = 3; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index -1 is before the beginning of the array [cppcoreguidelines-pro-bounds-constant-array-index] + a[10] = 4; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index 10 is past the end of the array (which contains 10 elements) [cppcoreguidelines-pro-bounds-constant-array-index] + + a[const_index(7)] = 3; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index 10 is past the end of the array (which contains 10 elements) + + a[0] = 3; // OK, constant index and inside bounds + a[1] = 3; // OK, constant index and inside bounds + a[9] = 3; // OK, constant index and inside bounds + a[const_index(6)] = 3; // OK, constant index and inside bounds +} + +void g() { + int a[10]; + for (int i = 0; i < 10; ++i) { + a[i] = i; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use array subscript when the index is not a compile-time constant; use gsl::at() instead + // CHECK-FIXES: gsl::at(a, i) = i; + gsl::at(a, i) = i; // OK, gsl::at() instead of [] + } + + a[-1] = 3; // flagged by clang-diagnostic-array-bounds + a[10] = 4; // flagged by clang-diagnostic-array-bounds + a[const_index(7)] = 3; // flagged by clang-diagnostic-array-bounds + + a[0] = 3; // OK, constant index and inside bounds + a[1] = 3; // OK, constant index and inside bounds + a[9] = 3; // OK, constant index and inside bounds + a[const_index(6)] = 3; // OK, constant index and inside bounds +} + +struct S { + int& operator[](int i); +}; + +void customOperator() { + S s; + int i = 0; + s[i] = 3; // OK, custom operator +} -- cgit v1.2.3