Summary:
The code
struct A {
int x[3];
};
gets an compiler-generated copy constructor that uses ArraySubscriptExpr (see below).
Previously, the check would generate a warning on that copy constructor.
This commit disables the warning on implicitly generated code.
AST:
|-CXXConstructorDecl 0x337b3c8 <col:8> col:8 implicit used constexpr A 'void (const struct A &) noexcept' inline
| |-ParmVarDecl 0x337b510 <col:8> col:8 used 'const struct A &'
| |-CXXCtorInitializer Field 0x3379238 'x' 'int [3]'
| | `-ImplicitCastExpr 0x337e158 <col:8> 'int' <LValueToRValue>
| | `-ArraySubscriptExpr 0x337e130 <col:8> 'const int' lvalue
| | |-ImplicitCastExpr 0x337e118 <col:8> 'const int *' <ArrayToPointerDecay>
| | | `-MemberExpr 0x337dfc8 <col:8> 'int const[3]' lvalue .x 0x3379238
| | | `-DeclRefExpr 0x337dfa0 <col:8> 'const struct A' lvalue ParmVar 0x337b510 '' 'const struct A &'
| | `-ImplicitCastExpr 0x337e098 <col:8> 'unsigned long' <LValueToRValue>
| | `-DeclRefExpr 0x337e070 <col:8> 'unsigned long' lvalue Var 0x337e010 '__i0' 'unsigned long'
Reviewers: alexfh, aaron.ballman
Subscribers: aemerson, nemanjai, cfe-commits
Differential Revision: https://reviews.llvm.org/D22381
llvm-svn: 275993
88 lines
2.7 KiB
C++
88 lines
2.7 KiB
C++
// 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; use gsl::at() instead [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; use gsl::at() instead
|
|
|
|
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;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use array subscript when the index is not an integer constant expression; 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
|
|
}
|
|
|
|
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);
|
|
}
|