Search code examples
c++templatesgccclang

Gcc vs clang difference in qualified class member lookup within template


The following code produces different results when compiled using gcc 14.2 or clang 19.1:

namespace mylib {
    template <typename Type> void Function(const Type& t) {
        // Note: explicit Type:: qualification
        t.Type::Foo();
    }
}

class Type {
    public:
        void Foo() const {
            std::cout << "Base function";
        }
};

class DerivedType: public Type {
    public:
        void Foo() const {
            std::cout << "Derived function";
        }
};

int main() {
    mylib::Function(DerivedType{});
}
  • in gcc 14.2: DerivedType::Foo() is called.
  • in clang 19.1: Type::Foo() is called.

Any idea which behavior should be considered correct, if any?

Note: the two compilers produce the same output if class Type is renamed to something different from the Function template argument, in which case DerivedType::Foo is called also by clang.


Solution

  • This is (currently open) CWG issue 1089.

    Per the current rules, lookup for Type is performed, at instantiation, in the context of the class type of t first and the template parameter with the same name can only be found during the unqualified lookup attempt following this first lookup if Type is not found in the class context.

    Here Type can be found in the class scope DerivedType of t's type, naming the base class and Type::Foo will then refer to the member function of that Type base class.

    So Clang is correct here.