This is a "why is the sky made out of bricks" type question. Ie, a question that asks why something false is true. It is not the case that in C++ your code is legal.
Live example, as you can see in gcc 4.8 this does not actually compile.
I guess the question "why does gcc 4.6 let this code compile" remains. One of the things that compilers did early on when writing template
expanders was to treat them as something similar to macros. Very little would be done when they where declared, and everything would be looked up when they where instantiated.
Compilers now tend to do more thing when the template
is declared, and less when it is instantiated. This is what the C++ standard requires, or is at least closer.
As it happens, ADL can get around this: bar
lookups that find bar
via ADL do not have to be visible at the point where foo
is written, but rather at the point of instantiation.
The gcc 4.8 error message is pretty self explanatory:
prog.cpp: In instantiation of ‘void foo(T) [with T = int]’:
prog.cpp:16:7: required from here
prog.cpp:6:10: error: ‘bar’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
bar(x); // OKAY
^
prog.cpp:10:6: note: ‘template<class T> void bar(T)’ declared here, later in the translation unit
void bar(T x)
^
these requirements may have been changed or clarified in C++11, so it is possible that gcc 4.6's behavior was legal under the C++03 standard.