This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: Allow __cplusplus=199711L to work with Solaris 2 headers
- From: Marc Glisse <marc dot glisse at inria dot fr>
- To: Rainer Orth <ro at CeBiTec dot Uni-Bielefeld dot DE>
- Cc: libstdc++ at gcc dot gnu dot org
- Date: Mon, 14 Mar 2011 22:16:28 +0100 (CET)
- Subject: Re: Allow __cplusplus=199711L to work with Solaris 2 headers
- References: <yddfwqpqwnh.fsf@manam.CeBiTec.Uni-Bielefeld.DE>
- Reply-to: libstdc++ at gcc dot gnu dot org
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