Allow __cplusplus=199711L to work with Solaris 2 headers
Marc Glisse
marc.glisse@inria.fr
Mon Mar 14 21:16:00 GMT 2011
On Mon, 14 Mar 2011, Rainer Orth wrote:
> I checked what happens in a Solaris 11/x86 bootstrap if I fix
> libcpp/init.c to define __cplusplus correctly as in the following patch:
Cool.
> In file included from /vol/gcc/src/hg/trunk/solaris/libstdc++-v3/include/precompiled/stdc++.h:42:0:
> /vol/gcc/obj/gcc-4.6.0-20110311/11-gcc-cplusplus/i386-pc-solaris2.11/libstdc++-v3/include/cmath: In function 'double std::abs(double)':
> /vol/gcc/obj/gcc-4.6.0-20110311/11-gcc-cplusplus/i386-pc-solaris2.11/libstdc++-v3/include/cmath:82:3: error: redefinition of 'double std::abs(double)'
>
> inline double
> abs(double __x)
> { return __builtin_fabs(__x); }
>
> /usr/include/iso/math_iso.h:159:16: error: 'double std::abs(double)' previously defined here
>
> inline double abs(double __X) { return fabs(__X); }
>
> There are many more of those. To avoid them, I've changed
> <iso/math_iso.h> to read
>
> -#if __cplusplus >= 199711L
> +#if __cplusplus >= 199711L && !defined(__GNUG__)
>
> While this certainly works, I'm unclear if the Solaris definition is
> actually wrong (I don't think so, but am ignorant of C++). Depending on
> the analysis, I'll try to get necessary fixes into Solaris 11, and have
> some hope of success since I've got decent contacts into Solaris
> engineering. This is one of the reasons for posting this so shortly
> after the discussions in the PR.
Those definitions are right, but since solaris is almost the only system
that provides them, libstdc++ provides them as well. When glibc started
providing a few of those, libstdc++ started making those extra definitions
conditional (see cstring for an example). Best would be to continue this
work.
> /usr/include/iso/stdlib_iso.h:129:14: error: previous declaration of 'void* std::bsearch(const void*, const void*, std::size_t, std::size_t, int (*)(const void*, const void*))' with 'C' linkage
> /usr/include/iso/stdlib_iso.h:134:38: error: conflicts with new declaration with 'C++' linkage
>
> extern void *bsearch(const void *, const void *, size_t, size_t,
> int (*)(const void *, const void *));
> #if __cplusplus >= 199711L
> extern "C++" {
> void *bsearch(const void *, const void *, size_t, size_t,
> int (*)(const void *, const void *));
> }
> #endif /* __cplusplus >= 199711L */
>
> One more, can again be avoided by adding && !defined(__GNUG__)
Yup. I used to fixinclude them out. I am not sure we really want something
as radical as !defined(__GNUG__) in solaris. There is still a slight
chance that bug 2316 might be fixed next time the ABI gets broken.
> /* Define to 1 if you have the <complex.h> header file. */
> -#define HAVE_COMPLEX_H 1
> +/* #undef HAVE_COMPLEX_H */
>
> This was due to the following:
>
> In file included from /usr/include/stdio.h:81:0,
> from conftest.cpp:34:
> /usr/include/iso/stdio_iso.h: In function 'int std::getchar()':
> /usr/include/iso/stdio_iso.h:362:41: error: 'getc' was not declared in this scope
> /usr/include/iso/stdio_iso.h: In function 'int std::putchar(int)':
> /usr/include/iso/stdio_iso.h:363:52: error: 'putc' was not declared in this scope
> In file included from conftest.cpp:34:0:
> /usr/include/stdio.h: At global scope:
> /usr/include/stdio.h:122:12: error: 'std::getc' has not been declared
> /usr/include/stdio.h:125:12: error: 'std::putc' has not been declared
>
> For some reason, std::getc, std::putc are declared only if
> !_STRICT_STDC, which is defined due to __STRICT_ANSI__. I've hacked
> around this again, but suppose this isn't the right solution.
Shouldn't you still have the extern declaration of getc and putc higher in
the file?
> It turns out that std::time_{get, put}, std::__timepunct are
> incompatible, which is due to <iso/time_iso.h>:
>
>> diff -u0 baseline_symbols.txt current_symbols.txt |grep __timepunct|/vol/gcc/bin/c++filt
> -FUNC:std::__timepunct<char>::_M_put(char*, unsigned long, char const*, tm const*) const@@GLIBCXX_3.4
> +FUNC:std::__timepunct<char>::_M_put(char*, unsigned long, char const*, std::tm const*) const@@GLIBCXX_3.4
> -FUNC:std::__timepunct<wchar_t>::_M_put(wchar_t*, unsigned long, wchar_t const*, tm const*) const@@GLIBCXX_3.4
> +FUNC:std::__timepunct<wchar_t>::_M_put(wchar_t*, unsigned long, wchar_t const*, std::tm const*) const@@GLIBCXX_3.4
>
> There's a change from tm * to std::tm * here, which I've avoided by
> <iso/time_iso.h> hackery.
I used to hack the mangling function. Note that, although it doesn't
affect libstdc++, we may want to change the mangling for the couple other
structs that move to namespace std, or also move those out of namespace
std.
> Afterwards, testsuite results both from make check-g++ and in
> libstdc++-v3 are unchanged, with four exceptions:
>
> FAIL: 22_locale/time_put/put/wchar_t/1.cc execution test
>
> Assertion failed: result1 == L"Sun", file /vol/gcc/src/hg/trunk/solaris/libstdc++-v3/testsuite/22_locale/time_put/put/wchar_t/1.cc, line 56, function test01
>
> The same binary works with original libstdc++.so.6.
>
> When the test passes, I find:
>
> (gdb) p result1
> $3 = {static npos = <optimized out>,
> _M_dataplus = {<std::allocator<wchar_t>> = {<__gnu_cxx::new_allocator<wchar_t>> = {<No data fields>}, <No data fields>},
> _M_p = 0x41a0f8 L"S\000\000\000u\000\000\000n\000\000\000"}}
>
> When it fails, I get this instead:
>
> (gdb) p result1
> $3 = {static npos = <optimized out>,
> _M_dataplus = {<std::allocator<wchar_t>> = {<__gnu_cxx::new_allocator<wchar_t>> = {<No data fields>}, <No data fields>}, _M_p = 0x41a0f8 L"%\000\000\000"}}
>
> config/locale/generic/time_members.cc (wcsftime) returns different results:
>
> * pass:
>
> (gdb) p __s
> $15 = 0xfffffd7fffdff1d0 L"S\000\000\000u\000\000\000n\000\000\000"
>
> * fail:
>
> (gdb) p __s
> $15 = 0xfffffd7fffdff1f0 L"%\000\000\000"
>
> I found that pass uses __wcsftime_xpg5, fail uses wcsftime. The change
> can be reproduced with this testcase:
>
> extern "C" {
> namespace std {
> #pragma redefine_extname wcsftime __wcsftime_xpg5
> struct tm;
> typedef unsigned size_t;
> extern size_t wcsftime(wchar_t *, size_t, const wchar_t *, const struct tm *);
> }
> }
>
> using std::wcsftime;
>
> int
> main (void)
> {
> wcsftime (0, 0, 0, 0);
> }
>
> If namespace std is present, main actually calls wcsftime, while without
> it the call goes to __wcsftime_xpg5. This seems to be a bad interaction
> of #pragma redefine_extname and namespaces. With the Sun Studio CC, the
> test works as expected.
>
> If this analysis is considered correct, I can file a c++ PR for the
> issue.
PR 30112.
--
Marc Glisse
More information about the Libstdc++
mailing list