"using namespace" seemingly not effective

clang++ (default flags, trunk version) does not grok the following code:

namespace outer {
   void f(int &);
   void g();
   namespace inner {
     void f(long &);
   }
}

void
outer::g()
{
   using namespace outer::inner;
   int i;
   f(i);
   long l;
   f(l);
}

t.cpp:16:3: error: no matching function for call to 'f'
   f(l);
   ^
t.cpp:2:8: note: candidate function not viable: no known conversion from 'long' to 'int &' for 1st argument
   void f(int &);
        ^

I find this rather odd, considering that there is an explicit "using namespace" directive. I'm not sufficiently familiar with the C++ name lookup rules, but I could have understood if f(int &) became invisible. But the other way round is very surprising.

(this isn't really a C++ language support forum, but anyway)

Notice that the second call does work - so clearly something about the
name lookup is working. And the first call that errors points directly
to the candidate you intended to call (via the using directive) but
explains why it can't call that version.

If you remove the namespaces from this example you'll get the same
error, try it & see:

void f(long&);
int main() {
  f(3);
}

& the reason is that the parameter is a long /reference/. References
have to refer to something - and the something you've provided (int i)
is not a long. An int is not a long, though it can be converted to one
- that won't happen implicitly for the purpose of binding a reference
to something, as that would result in rather subtle behavior. If the
temporary created by such a conversion were bound to the reference
then any mutation within 'f' would not be visible in 'i' (because the
mutation would be of the temporary long created by the conversion).
The reference cannot be converted because it is a different thing,
fundamentally - there's no runtime polymorphism here ("int" is not a
subclass of "long" (nor the other way around)).

Hmm, right you are - shows how well I can read/think at this hour on a
Saturday morning. Apologies for that.

GCC 4.7 compiles this code without error & I tend to agree with it so
far as I can imagine, though there might be some subtle feature of the
language I'm missing here (that's an appropriate caveat with pretty
much anything in C++ though). I'd say it's worthy of a PR and/or some
other further investigation.

I looked up the rules, and the using directive should put the f(long &) declaration in the outer namespace, like this:

namespace outer {
   void f(int &);
   void f(long &);
   void g();
}

void
outer::g()
{
    int i;
    f(i);
    long l;
    f(l);
}

(This follows from "During unqualified name lookup […], the names appear as if they were declared in the nearest enclosing namespace which contains both the using-directive and the nominated namespace." in [namespace.udir] in C++98.)

It seems that clang considers treats the global namespace as the nearest enclosing namespace in this case, ignoring the namespace that is implied by the function's declarator-id.

I filed a bug: http://llvm.org/bugs/show_bug.cgi?id=15973