https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127698
Bug ID: 127698
Summary: Inconsistency in -Wunused-but-set-variable related to
pack expansion
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: ivan.lazaric.gcc at gmail dot com
Target Milestone: ---
```cpp
// snippet 1
struct span {
int* ptr;
span(int* ptr) : ptr(ptr) {}
int& operator[](int idx) { return ptr[idx]; }
};
template<auto... Is>
void bump(span arr) {
int counter = 0;
((arr[counter++] += Is), ...);
}
void instantiate() {
int arr[2]{};
bump<1, 2>(arr);
bump<>(arr);
}
```
```cpp
// snippet 2
template<auto... Is>
void bump(int* arr) {
int counter = 0;
((arr[counter++] += Is), ...);
}
void instantiate() {
int arr[2]{};
bump<1, 2>(arr);
bump<>(arr);
}
```
Compilation flags: " -Wunused-but-set-variable=2 -O3"
(or stronger warnings, like "-Wunused")
The two snippets only differ in what `arr` in `bump()` is,
a class vs a pointer. But on `bump<>(arr);` line in `instantiate()`,
snippet 1 warns, while snippet 2 doesn't.
Also noting, snippet 1 warns since GCC 16, not before.
If we change snippet 1 to modify `arr.ptr[counter++]` instead:
```cpp
// snippet 1.5
struct span {
int* ptr;
span(int* ptr) : ptr(ptr) {}
int& operator[](int idx) { return ptr[idx]; }
};
template<auto... Is>
void bump(span arr) {
int counter = 0;
((arr.ptr[counter++] += Is), ...);
}
void instantiate() {
int arr[2]{};
bump<1, 2>(arr);
bump<>(arr);
}
```
This doesn't warn, like snippet 2, so it seems the discrepancy
is related to class `operator[]` being used in pack expansion.
Snippet 1: https://godbolt.org/z/7xanvq8T8
Snippet 2: https://godbolt.org/z/1G1aWcKan
Snippet 1.5: https://godbolt.org/z/jx873EMdr