This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Builtins in `std'
#include <cstring>
using namespace std;
int foo () { return strchr ("abc", 'a') != 0; }
is not optimized while
It's better than that. It doesn't even compile.
test.C: In function `int foo()':
test.C:5: call of overloaded `strchr(const char[4], char)' is ambiguous
That's pretty amusing, but it's a bug in the library, not really
relevant to what we're talking about. It comres from the fact that
the glibc headers don't match the V3 headers, and that `<cstring>'
includes /usr/include/string.h, which it shouldn't, because that
header puts everything in the global namespace. The V3 people know
all about this problem; it's very hard to write conformant C++ headers
that don't duplicate all of your C headers.
I expect that when you tried this example, the overloadings were
slightly different, and the compiler picked the global declaration of
`strchr' (the one that shouldn't exist at all.)
This isn't optimized because the compiler doesn't create a builtin for
`::strchr'; it's created them for `std::strchr' (which I think it
shouldn't) and `__builtin_strchr' (which everyone agress that it
should).
If the library were standard-conformant, your example would be treated
exactly like the other case you give; they mean the same thing in
standard C++. Any difference in behavior is a bug in the compiler or
the library or both.
Your other example:
#include <cstring>
using namespace std;
int foo () { return std::strchr ("abc", 'a') != 0; }
is optimized because we get the declaration in `std' *and the compiler
totally ignores the body of the definition*!
The library does:
inline const char*
strchr(const char* __s1, int __n)
{ return const_cast<const char*>(::strchr(__s1, __n)); }
but the compiler doesn't care about the body. It says `Oh,
std::strchr is special, I know how to optimize that.'
Consider this program:
namespace std {
inline char *
strchr (char *s, int n) { return 0; }
}
int foo () { return std::strchr ("abc", 'a') != 0; }
Note that there are *no* header files here. This is "optimized" to:
_Z3foov:
.LFB1:
pushl %ebp
.LCFI0:
movl $.LC0, %edx
xorl %eax, %eax
testl %edx, %edx
movl %esp, %ebp
.LCFI1:
setne %al
popl %ebp
ret
We have totally ignored the definition. The compiler thinks it knows
best. This cannot possibly be adhering to the principle of least
surprise! This is only one of the many bugs here.
Clearly if strchr is present both in global namespace and in std
namespace, it is taken from global namespace.
But, you're assuming it is in the global namespace. Nothing about
`#include <cstring>' should put it there; that's what's broken. It is
nonconforming for us to put `strchr' in the global namespace, either
in the compiler or the library. Your original program only optimizes
This can be solved by the lazy builtins, where only prototype with extern "C"
would make the builtins alive.
Oh, sure, lazy builtins can solve the problem. But why?
We will have to maintain all kinds of cruft in the compiler and you
will still have to put the right declarations in the header files (to
activate them), and you will have to be very careful that you library
declarations exactly match your compiler declarations (so you *are*
coupled to the compiler anyhow).
You have helped to convince me of how much these need to go. :-)
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com