Qualified name lookup using a type pack is not considered a pack
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
Consider the following program:
```c++
struct X {
int i;
};
struct Y {
int i;
};
struct Z : X, Y {};
void g(int, int);
template
void f(T z) {
g(z.Bases::i...);
}
int main() {
f(Z{});
}
```
Currently Clang complains:
```
:13:17: error: pack expansion does not contain any unexpanded parameter packs
13 | g(z.Bases::i...);
| ~~~~~~~~~~^
```
GCC and MSVC compile this to call `g(0, 0)`.
Clang *does* accept it if `z` is not dependently typed:
```c++
template
void f(Z z) {
g(z.Bases::i...);
}
```
[[basic.lookup.qual.general]p3](https://wg21.link/basic.lookup.qual.general#3) is pertinent. It appears there is a situation where an expression is dependently a pack based on a template parameter, so this might be a standard defect.
For example, GCC currently accepts:
```c++
struct X {
int i;
};
struct Y {
int i;
};
struct A : X, Y {
using Bases = void;
};
void g(int, int);
template
void f(T z) { // GCC no longer accepts with non-dependent z `template void f(Z z) {`
g(z.Bases::i...);
}
int main() {
f(A{});
}
```
But MSVC doesn't accept this, failing when trying to instantiate `f(A{})`.
Contributor guide
Research direction
Start by compiling the two reduced C++ programs with Clang and compare their behavior with GCC and MSVC, focusing on dependent qualified lookup and pack-expansion rules. Trace the compiler's semantic handling of z.Bases::i... and consult [basic.lookup.qual.general]p3; done means resolving the standard interpretation and making the reported valid case behave consistently without regressing the contrasting example.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100