This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: [3.0 regression] libstdc++ and strstr
- To: gcc-bugs at gcc dot gnu dot org
- Subject: Re: [3.0 regression] libstdc++ and strstr
- From: Loren James Rittle <rittle at latour dot rsch dot comm dot mot dot com>
- Date: Wed, 16 May 2001 17:46:50 -0500 (CDT)
- Cc: pfeifer at dbai dot tuwien dot ac dot at
- Organization: Networks and Infrastructure Lab (IL02/2240), Motorola Labs
In article <Pine.BSF.4.33.0105160925490.21904-100000@deneb.dbai.tuwien.ac.at>
you write:
> The following most trivial code snippet fails to compile with current
> CVS sources on the GCC 3.0 branch on i686-pc-linux-gnu:
>
> #include <string>
>
> using namespace std;
>
> char *f() {
> strstr("aba","b");
> }
[fails]
and it should fail but not for the current reason it fails. ;-) It
should fail because std::strstr is only supposed to be provided by
<cstring> not <string>. If we tweak that minor issue:
#include <cstring>
using namespace std;
void f() {
strstr("aba","b");
}
It still fails exactly as you observed. Unfortunately, this is a
well-known problem of libstdc++-v3 and its direct use of ISO C89 (C99)
headers.
Given the precise function signatures involved:
>From <string.h>, ISO C89 and C99:
char* strstr (const char* __s1, const char* __s2);
[Which is used by <string> and <cstring> in the libstdc++-v3 implementation.]
>From <cstring>, ISO C++98:
const char* strstr (const char* __s1, const char* __s2);
char* strstr ( char* __s1, const char* __s2);
until the raw C headers are shadowed/hidden properly, I don't know how
this example could compile cleanly.
If the signature from <string.h> exactly matched either one of those
to be provided by <cstring>, there is a way (i.e. cute trick) to make
it work without too much pain.
Here is the technique: add 'extern "C"' over the definition that
matches the standard C header version. The C++ standard says that
names defined by C may have extern "C" linkage even when provided by
the new style of header names and in namespace std.
#include <stdio.h>
extern "C" void foo (const char* __s);
namespace bar
{
extern "C" inline void foo (const char* __s) { printf ("const\n"); }
inline void foo (char* __s) { printf ("non-const\n"); }
}
int main ()
{
char* s = "l";
using namespace bar;
foo ("l");
foo (s);
}
Since the return types don't match, this trick doesn't work in this
particular case. Bummer. Unfortunately, this appears to be the case
for all names where C++ subtly changes the signature (while
overloading it to boot) (don't remind me that the return type isn't
part of the function signature, while true, it is also true that two
extern "C" function signatures must match in the return type).
Regards,
Loren