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.

Reply via email to