Error name lookup in template dependant base class

Hi,

I’m trying to compile a C++ project using clang and I’m getting some errors.
I’ve reduced my problem to the following code lines:

template
struct Base
{
void foo(int) {}
};

template
struct Derived : Base
{
void bar()
{
this->foo(2);
}

void foobar()
{
T c;
foo(c);
}
};

int main()
{
Derived x;
x.bar(); //< OK
x.foobar(); //< ERROR
}

I get the following error:

/home/achauve/dev/c++/test_clang/test_clang.cpp:18:9: error: use of undeclared identifier ‘foo’
foo(c);
^
this->
/home/achauve/dev/c++/test_clang/test_clang.cpp:26:7: note: in instantiation of member function
‘Derived::foobar’ requested here
x.foobar();
^
/home/achauve/dev/c++/test_clang/test_clang.cpp:4:10: note: must qualify identifier to find this declaration in
dependent base class
void foo(int) {}
^

In the case of foobar with a dependant template-parameter, shouldn’t the identifier be found anyway? (gcc doesn’t complain).

I’ve also looked in the directory clang/tests/cxx/temp but I’m not sure where I could put my test (what’s the exact paragraph of the standard corresponding to this issue?).

I’m using clang-2.8 and also a snapshot from the trunk (clang version 2.9 (trunk 120732)) on Unbuntu 10.10 x86-64.

Thanks,

Cheers,
Adrien

See http://clang.llvm.org/compatibility.html#dep_lookup_bases . If
you have any questions after reading that, feel free to ask.

-Eli

Thanks for the link, it’s exactly what I was searching for.

But I’m not sure my example code (ant the example on the page you pointed at) is invalid. In case of a function call where at least one argument is a template dependant name, the call should not be qualified (cf “C++ Templates The Complete Guide” by D. Vandervoorde and N. M. Josuttis, section 9.4.2 pp 136-138).

What am I missing?

Cheers,
Adrien

The rule is that (1) if the lookup at definition time doesn't find a class member and (2) there's at least one type-dependent argument then (3) we can't resolve the call at definition time because we have to do argument-dependent lookup during instantiation. ADL never find class members, though.

The bug in gcc is that it also performs unqualified lookup at instantiation time and therefore finds class members from previously-dependent base classes that it's really not supposed to find.

John.

Thanks for your response and I’m really sorry to answer so late.

I don’t think the problem is ADL here. The name of the function call is a dependant name, so the unqualified lookup is delayed until instanciation: it’s not ADL, it’s just delayed ordinary lookup. At instanciation time and when all explicit template specializations are available, lookups can be done in the base class to find members.

This example compiles without any complain on g++ and I’m going to verify with VS2010 and intel compiler, but I’m pretty sure it compiles as well using these compilers.

I’m still not sure why this is not a bug of clang.

Cheers,
Adrien

I don't think the problem is ADL here. The name of the function call is a dependant name, so the unqualified lookup is delayed until instanciation: it's not ADL, it's just delayed ordinary lookup. At instanciation time and when all explicit template specializations are available, lookups can be done in the base class to find members.

Well, no, they can't. This is what we're all trying to explain. The standard is extremely explicit about this:

C++ [temp.dep.res]p1:
  In resolving dependent names, names from the following sources are considered:
  — Declarations that are visible at the point of definition of the template.
  — Declarations from namespaces associated with the types of the function arguments both from the instantiation context and from the definition context.

This example compiles without any complain on g++ and I'm going to verify with VS2010 and intel compiler, but I'm pretty sure it compiles as well using these compilers.

g++ and VS have extremely broken template models, although g++ is fixing theirs (and had the less broken model in the first place). ICC has a very good template model which will reject this, but only if you run it in "strict" mode; otherwise you're running in a compatibility mode which carefully emulates the broken template models of g++ and VS. Clang is like ICC except we don't have an intentionally-broken compatibility mode.

John.

This is actually not the part of the standard I meant to quote, although it does apply. The better quote is [temp.dep.candidate]p1:

  For a function call that depends on a template parameter, the candidate functions are found using the usual lookup rules except that:
  — For the part of the lookup using unqualified name lookup or qualified name lookup, only function declarations from the template definition context are found.
  — For the part of the lookup using associated namespaces, only function declarations found in either the template definition context or the template instantiation context are found.

John.

Ok then, thank you very much John and Matt for your answers. I’m convinced!!

Is it a known error in “C++ Templates: The Complete Guide”, or am I getting it wrong?

Thanks again,
Adrien

P.S.: Matt, it seems that you replied only to me, but your quote was really nice so I copy it here:

From the standard [temp.dep]:

" In the definition of a class or class template, if a base class depends on a template-parameter, the base class
scope is not examined during unqualified name lookup either at the point of definition of the class template
or member or during an instantiation of the class template or member"

I just tested with intel c++ compiler 12.
Indeed, the compilation fails when using the “-strict-ansi” option.

Thanks,
Adrien