cppcoreguidelines-pro-bounds-constant-array-index.cpp 2.64 KB
Newer Older
1
2
// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-constant-array-index %t

3
typedef __SIZE_TYPE__ size_t;
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

namespace std {
  template<typename T, size_t N>
  struct array {
    T& operator[](size_t n);
    T& at(size_t n);
  };
}


namespace gsl {
  template<class T, size_t N>
  T& at( T(&a)[N], size_t index );

  template<class T, size_t N>
  T& at( std::array<T, N> &a, size_t index );
}

constexpr int const_index(int base) {
  return base + 3;
}

void f(std::array<int, 10> a, int pos) {
  a [ pos / 2 /*comment*/] = 1;
28
  // 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]
29
  int j = a[pos - 1];
30
  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: do not use array subscript when the index is not an integer constant expression
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

  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 negative [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;
53
    // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use array subscript when the index is not an integer constant expression
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
    // 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
}
77
78
79
80
81
82
83
84
85
86
87

struct A {
  // The compiler-generated copy constructor uses an ArraySubscriptExpr. Don't warn.
  int x[3];
};

void use_A() {
  // Force the compiler to generate a copy constructor.
  A a;
  A a2(a);
}