This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: [3.0 regression] libstdc++ and strstr


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]