Hi,
I'm new to clang:
I started to use clang/llvm 2.9 built from macports on a SL mac.
I encountered the following bug:
clang++ ignores a global function declaration.
Whether the issue occurs is depending on the order of include files.
The software compiles fine with g++ 4.5.1
I also compared the clang preprocessor outputs of the file
for the working and the faulty case. The only differences I can see
are the declaration order and line numbers of includes.
The ignored global function is declared in both clang preprocessor outputs.
Is this bug already known?
How can I provide additional information or maybe even analyze this bug?
Thanks
Regards
Titus
clang++ ignores a global function declaration.
Whether the issue occurs is depending on the order of include files.
what do you mean ignore?
if the problem is due to template definition using a non dependent function before declaring it, then this is not a bug but better respect of the standard.
exemple:
// this work on gcc and clang
int foo();
template<class T> int bar(T a) { return a+foo(); }
// this only work on gcc (and most compiler other than clang):
template<class T> int bar2(T a) { return a+foo2(); }
int foo2();
int main() {
return bar(5.)+bar2(5.);
}
notice that this is not true for dependent name lookup.
regards,
Cédric
Cédric Venet <cedric.venet@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)
-miles
Cédric Venet <cedric.venet@laposte.net>
writes:
// this only work on gcc (and most compiler other than clang):
template 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):
Indeed - I expect the only thing, if anything, that accepts this is Microsoft’s C++ compiler (it’s missing the whole two-phase lookup thing entirely).
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.
Regards
Titus
// --- start
#include <iostream>
#define __USENAMESPACENFORB__ 1
#if __USENAMESPACENFORB__
namespace N {
#endif
class B {
int b;
public:
B(int _b) : b(_b) {}
int getB(void) const { return b; }
};
#if __USENAMESPACENFORB__
}
using namespace N;
#endif
template <typename T>
struct Out {
static void out(const T& t) {
std::cout << t << std::endl;
}
};
// When this operator<< is declared after O::Out it
// does not compile with clang++ if __USENAMESPACENFORB__ is 1
// g++ compiles it in both cases
std::ostream & operator<<(std::ostream & _str, const B & _b) {
_str << _b.getB();
return _str;
}
int main(void) {
int a = 33;
B b(5);
Out<int>::out(a);
Out<B>::out(b);
}
// --- end
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
clang supports a -fdelayed-template-parsing mode to be able to parse such code.
Using -fdelayed-template-parsing, the parsing of the body of templated
functions is postponed to the end of the translation unit to make sure
all the names are available.