File: pro-bounds-constant-array-index.cpp

package info (click to toggle)
llvm-toolchain-17 1%3A17.0.6-22
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,799,624 kB
  • sloc: cpp: 6,428,607; ansic: 1,383,196; asm: 793,408; python: 223,504; objc: 75,364; f90: 60,502; lisp: 33,869; pascal: 15,282; sh: 9,684; perl: 7,453; ml: 4,937; awk: 3,523; makefile: 2,889; javascript: 2,149; xml: 888; fortran: 619; cs: 573
file content (130 lines) | stat: -rw-r--r-- 4,402 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-constant-array-index %t

typedef __SIZE_TYPE__ size_t;

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;
  // 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]
  int j = a[pos - 1];
  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: do not use array subscript when the index is not an integer constant expression

  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

  using MyArray = std::array<int, 10>;
  MyArray m{};
  m [ pos / 2 /*comment*/] = 1;
  // 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]
  int jj = m[pos - 1];
  // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use array subscript when the index is not an integer constant expression

  m.at(pos-1) = 2; // OK, at() instead of []
  gsl::at(m, pos-1) = 2; // OK, gsl::at() instead of []
  m[-1] = 3;
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: std::array<> index -1 is negative [cppcoreguidelines-pro-bounds-constant-array-index]
  m[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]

  m[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)

  m[0] = 3; // OK, constant index and inside bounds
  m[1] = 3; // OK, constant index and inside bounds
  m[9] = 3; // OK, constant index and inside bounds
  m[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 an integer constant expression
    // 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
}

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

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

  // Force the compiler to generate a move constructor.
  A a3 = (A&&) a;
}

void lambdaCapture() {
  int arr[3];

  // Capturing an array by value uses an ArraySubscriptExpr. Don't warn. 
  [arr](){};
}

#if __cplusplus >= 201703L
void structuredBindings() {
  int arr[3];

  // Creating structured bindings by value uses an ArraySubscriptExpr. Don't warn.
  auto [a,b,c] = arr;
}
#endif
} // namespace ArrayInitIndexExpr