https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111463
Bug ID: 111463
Summary: Access error in instantiation of template class,
incorrectly using inherited constructor of wrong type
Product: gcc
Version: 11.4.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: bckempa at iastate dot edu
Target Milestone: ---
Version: 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04) [replicated in 11.2 - Trunk]
System: x86_64-linux-gnu Ubuntu 22.04
Flags: -std=c++14
Given the case of a derived class inheriting from a base where both inherent a
templated manager class with different template arguments:
```
class EventA {};
class EventB {};
template <class Event> class Manager {};
class Base : Manager<EventA> {};
template <class T> class Derived : Base, Manager<T> {
using Foo = Manager<T>;
};
int main() {
Derived<EventB> foo;
}
```
GCC 11.2 and above gives the following error:
```
test.cpp: In instantiation of ‘class Derived<EventB>’:
test.cpp:14:21: required from here
test.cpp:10:17: error: ‘class Manager<EventA> Manager<EventA>::Manager’ is
private within this context
10 | using Foo = Manager<T>;
| ^~~~~~~~~~
test.cpp:7:7: note: declared private here
7 | class Base : private Manager<EventA> {};
| ^~~~
```
It appears that gcc is attempting to use the constructor from the base class's
inherited Manager<EventB>, which doesn't match the specified Manager<EventB>,
rather than the derived class's templated Manager<EventB> parent.
This can be worked around by adding a scope resolution operator like this:
`using Foo = ::Manager<T>;`
This was initially observed on 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04) and I've
confirmed the behavior appeared in gcc 11.2 and persists though all versions to
trunk, while gcc 4.9.0 (the first to recognize the `-std=c++14` flag) up though
gcc 11.1 all select the correct constructor and compile.
Adding the `-fno-new-ttp-matching` flag, changing the order of the inheritance
list, and replacing `Manager<T>` with an explicit `Manager<EventB>` in the
using statement all had no effect.
Replacing the template argument with an explicit `Manager<EventB>` in the
inheritance list of the derived class does fix the behavior, but then the
derived class is no longer templated defeating the purpose.