[cfe-dev] clang ignoring global function declaration depending on include/declaration order

Douglas Gregor dgregor at apple.com
Mon Jun 13 07:05:45 PDT 2011


On Jun 13, 2011, at 2:38 AM, Titus von Boxberg wrote:

> Am 13.06.2011 um 07:17 schrieb Miles Bader:
> 
>> Cédric Venet <cedric.venet at laposte.net>
>> writes:
>>> // this only work on gcc (and most compiler other than clang):
>>> template<class T> int bar2(T a) { return a+foo2(); }
>>> int foo2();
>> 
>> This actually _doesn't_ work with any version of g++ I have (4.1 - 4.7):
>> 
>>  t.cc: In function ‘int bar2(T)’:
>>  t.cc:6:49: error: there are no arguments to ‘foo2’ that depend on a template parameter, so a declaration of ‘foo2’ must be available [-fpermissive]
>>  t.cc:6:49: note: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of an undeclared name is deprecated)
> 
> Thanks for the replies!
> 
> I managed to forge a sample code that produces my problem.
> The following snippet is compileable with g++ but not with clang++.
> For clang namespace N has to be dropped, or operator<<
> has to be declared before Out<T>.
> 
> I have to admit that I currently do not understand this behaviour,
> and I was unaware that this declaration order is necessary.

Clang is correct to reject this code, because functions declared after the template definition can only be found via ADL. This is a fairly common compatibility issue (most compilers incorrectly accept this code) documented gere:

	http://clang.llvm.org/compatibility.html#dep_lookup

Note that Clang recently got some improved diagnostics that point out the issue:

t.cpp:23:12: error: call to function 'operator<<' that is neither visible in the
      template definition nor found by argument dependent lookup
 std::cout << t << std::endl;
           ^
t.cpp:39:9: note: in instantiation of member function 'Out<N::B>::out' requested
      here
Out<B>::out(b);
        ^
t.cpp:30:16: note: 'operator<<' should be declared prior to the call site or in
      namespace 'N'
std::ostream &  operator<<(std::ostream & _str, const B & _b) {
                ^

	- Doug






More information about the cfe-dev mailing list