Clang-tidy (versions 13.x and 16.x) detects violations of cppcoreguidelines-pro-bounds-array-to-pointer-decay in a weirdly specific situation: when iterating over an array that is accessed through a pointer. Why does that happen? How can range-for even work after an array decays to a pointer?
Minimal example:
int main() {
int local[] { 1, 2, 3 };
static int global[] { 1, 2, 3 };
struct Wrapper {
int field[3] { 1, 2, 3 };
} wrapper;
Wrapper *pointer = &wrapper;
int (&reference)[3] = pointer->field;
for (int i : local);
for (int i : global);
for (int i : wrapper.field);
for (int i : pointer->field);
for (int i : reference);
}
$ clang-tidy-16 main.cpp --checks='-*,cppcoreguidelines-pro-bounds-array-to-pointer-decay'
(...)
main.cpp:16:13: warning: do not implicitly decay an array into a pointer; consider using gsl::array_view or an explicit cast instead [cppcoreguidelines-pro-bounds-array-to-pointer-decay]
for (int i : pointer->field);
^
Why does only pointer->field trip this warning?
Because that is what happens there. According to cppreference a temporary variable
auto&& __range = range-expressionis created. Due to the rules ofautodeduction, this will decay the array to a pointer. But that doesn't matter. Ifrange-expressionis an array, then thebegin-expris equal to__rangeand theend-expris equal to__range + __bound.The actual type of
__rangein this context is irrelevant, as long as(__range, __range + __bound)is an iterable range.One could argue that all of them should produce this warning, but apparently
clang-tidyhas suppressed some of them because they are not useful.