189a1d03eSRichard // RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-constant-array-index %t -- \
2*e8a3ddafSNathan James // RUN: -config='{CheckOptions: {cppcoreguidelines-pro-bounds-constant-array-index.GslHeader: "dir1/gslheader.h"}}'
389a1d03eSRichard // CHECK-FIXES: #include "dir1/gslheader.h"
489a1d03eSRichard
589a1d03eSRichard typedef __SIZE_TYPE__ size_t;
689a1d03eSRichard
789a1d03eSRichard namespace std {
889a1d03eSRichard template<typename T, size_t N>
989a1d03eSRichard struct array {
1089a1d03eSRichard T& operator[](size_t n);
1189a1d03eSRichard T& at(size_t n);
1289a1d03eSRichard };
1389a1d03eSRichard }
1489a1d03eSRichard
1589a1d03eSRichard
1689a1d03eSRichard namespace gsl {
1789a1d03eSRichard template<class T, size_t N>
1889a1d03eSRichard T& at( T(&a)[N], size_t index );
1989a1d03eSRichard
2089a1d03eSRichard template<class T, size_t N>
2189a1d03eSRichard T& at( std::array<T, N> &a, size_t index );
2289a1d03eSRichard }
2389a1d03eSRichard
const_index(int base)2489a1d03eSRichard constexpr int const_index(int base) {
2589a1d03eSRichard return base + 3;
2689a1d03eSRichard }
2789a1d03eSRichard
f(std::array<int,10> a,int pos)2889a1d03eSRichard void f(std::array<int, 10> a, int pos) {
2989a1d03eSRichard a [ pos / 2 /*comment*/] = 1;
3089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use array subscript when the index is not an integer constant expression [cppcoreguidelines-pro-bounds-constant-array-index]
3189a1d03eSRichard // CHECK-FIXES: gsl::at(a, pos / 2 /*comment*/) = 1;
3289a1d03eSRichard int j = a[pos - 1];
3389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: do not use array subscript when the index is not an integer constant expression
3489a1d03eSRichard // CHECK-FIXES: int j = gsl::at(a, pos - 1);
3589a1d03eSRichard
3689a1d03eSRichard a.at(pos-1) = 2; // OK, at() instead of []
3789a1d03eSRichard gsl::at(a, pos-1) = 2; // OK, gsl::at() instead of []
3889a1d03eSRichard
3989a1d03eSRichard a[-1] = 3;
4089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index -1 is negative [cppcoreguidelines-pro-bounds-constant-array-index]
4189a1d03eSRichard a[10] = 4;
4289a1d03eSRichard // 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]
4389a1d03eSRichard
4489a1d03eSRichard a[const_index(7)] = 3;
4589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index 10 is past the end of the array (which contains 10 elements)
4689a1d03eSRichard
4789a1d03eSRichard a[0] = 3; // OK, constant index and inside bounds
4889a1d03eSRichard a[1] = 3; // OK, constant index and inside bounds
4989a1d03eSRichard a[9] = 3; // OK, constant index and inside bounds
5089a1d03eSRichard a[const_index(6)] = 3; // OK, constant index and inside bounds
5189a1d03eSRichard }
5289a1d03eSRichard
g()5389a1d03eSRichard void g() {
5489a1d03eSRichard int a[10];
5589a1d03eSRichard for (int i = 0; i < 10; ++i) {
5689a1d03eSRichard a[i] = i;
5789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use array subscript when the index is not an integer constant expression
5889a1d03eSRichard // CHECK-FIXES: gsl::at(a, i) = i;
5989a1d03eSRichard gsl::at(a, i) = i; // OK, gsl::at() instead of []
6089a1d03eSRichard }
6189a1d03eSRichard
6289a1d03eSRichard a[-1] = 3; // flagged by clang-diagnostic-array-bounds
6389a1d03eSRichard a[10] = 4; // flagged by clang-diagnostic-array-bounds
6489a1d03eSRichard a[const_index(7)] = 3; // flagged by clang-diagnostic-array-bounds
6589a1d03eSRichard
6689a1d03eSRichard a[0] = 3; // OK, constant index and inside bounds
6789a1d03eSRichard a[1] = 3; // OK, constant index and inside bounds
6889a1d03eSRichard a[9] = 3; // OK, constant index and inside bounds
6989a1d03eSRichard a[const_index(6)] = 3; // OK, constant index and inside bounds
7089a1d03eSRichard }
7189a1d03eSRichard
7289a1d03eSRichard struct S {
7389a1d03eSRichard int& operator[](int i);
7489a1d03eSRichard };
7589a1d03eSRichard
customOperator()7689a1d03eSRichard void customOperator() {
7789a1d03eSRichard S s;
7889a1d03eSRichard int i = 0;
7989a1d03eSRichard s[i] = 3; // OK, custom operator
8089a1d03eSRichard }
81