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

Reply via email to