Skip to content

Commit

Permalink
[clang-tidy] Access checks not done classes derived of std::array
Browse files Browse the repository at this point in the history
Index accessing checks are not performed for derived classes of
of `std::array`, as only `std::array` itself and its aliases
seems to be checked.

This patch aims to extend it for derived classes such as:
```
template<class T, size_t N>
class DerivedArray : public std::array<T, N> {};
```

Reviewed By: PiotrZSL

Differential Revision: https://reviews.llvm.org/D156624
  • Loading branch information
sousajo-cc authored and PiotrZSL committed Aug 25, 2023
1 parent e9e4584 commit 41818ce
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,8 @@ void ProBoundsConstantArrayIndexCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
cxxOperatorCallExpr(
hasOverloadedOperatorName("[]"),
hasArgument(
0, hasType(hasUnqualifiedDesugaredType(recordType(hasDeclaration(
cxxRecordDecl(hasName("::std::array")).bind("type")))))),
callee(cxxMethodDecl(
ofClass(cxxRecordDecl(hasName("::std::array")).bind("type")))),
hasArgument(1, expr().bind("index")))
.bind("expr"),
this);
Expand Down
4 changes: 4 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,10 @@ Changes in existing checks
<clang-tidy/checks/cppcoreguidelines/pro-bounds-array-to-pointer-decay>` check
to ignore predefined expression (e.g., ``__func__``, ...).

- Improved :doc:`cppcoreguidelines-pro-bounds-constant-array-index
<clang-tidy/checks/cppcoreguidelines/pro-bounds-constant-array-index>` check
to perform checks on derived classes of ``std::array``.

- Improved :doc:`cppcoreguidelines-pro-type-member-init
<clang-tidy/checks/cppcoreguidelines/pro-type-member-init>` check to ignore
dependent delegate constructors.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ constexpr int const_index(int base) {
return base + 3;
}

template<class T, size_t N>
class DerivedArray : public std::array<T, N> {};

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]
Expand Down Expand Up @@ -68,6 +71,81 @@ void f(std::array<int, 10> a, int pos) {
m[const_index(6)] = 3; // OK, constant index and inside bounds
}

template<class T, size_t N>
class PrivateDerivedArray : std::array<T, N> {
public:
T& operator[](size_t n){
return std::array<T, N>::operator[](static_cast<int>(n));
};
T& at(size_t n) {
return std::array<T, N>::at(static_cast<int>(n));
};
};

void f_derived(DerivedArray<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 = DerivedArray<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

using MyPrivateArray = PrivateDerivedArray<int, 10>;
MyPrivateArray pm{};
pm [ pos / 2 /*comment*/] = 1;
int jjj = pm[pos - 1];

pm.at(pos-1) = 2; // OK, at() instead of []
pm[-1] = 3;
pm[10] = 4;

pm[const_index(7)] = 3;

pm[0] = 3; // OK, constant index and inside bounds
pm[1] = 3; // OK, constant index and inside bounds
pm[9] = 3; // OK, constant index and inside bounds
pm[const_index(6)] = 3; // OK, constant index and inside bounds
}




void g() {
int a[10];
for (int i = 0; i < 10; ++i) {
Expand Down

0 comments on commit 41818ce

Please sign in to comment.