This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Allow __cplusplus=199711L to work with Solaris 2 headers


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


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