diff --git a/libstdc++-v3/libsupc++/tinfo.cc b/libstdc++-v3/libsupc++/tinfo.cc index f10e270b6ae..3fcac0469a4 100644 --- a/libstdc++-v3/libsupc++/tinfo.cc +++ b/libstdc++-v3/libsupc++/tinfo.cc @@ -26,6 +26,22 @@ #include #include "tinfo.h" + // Write own version so it's compiled with mforce-l32 and won't crash +static int strcmp_safe(const char *p1, const char *p2) { + const unsigned char *s1 = (const unsigned char *) p1; + const unsigned char *s2 = (const unsigned char *) p2; + unsigned char c1, c2; + do + { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0') + return c1 - c2; + } + while (c1 == c2); + return c1 - c2; + } + std::type_info:: ~type_info () { } @@ -43,7 +59,7 @@ operator== (const std::type_info& arg) const _GLIBCXX_NOEXCEPT take care to look at __name rather than name() when looking for the "pointer" prefix. */ return (&arg == this) - || (__name[0] != '*' && (__builtin_strcmp (name (), arg.name ()) == 0)); + || (__name[0] != '*' && (strcmp_safe (name (), arg.name ()) == 0)); #endif } diff --git a/libstdc++-v3/libsupc++/tinfo2.cc b/libstdc++-v3/libsupc++/tinfo2.cc index 533824ca032..545df820fb6 100644 --- a/libstdc++-v3/libsupc++/tinfo2.cc +++ b/libstdc++-v3/libsupc++/tinfo2.cc @@ -29,6 +29,21 @@ using std::type_info; #if !__GXX_TYPEINFO_EQUALITY_INLINE + // Write own version so it's compiled with mforce-l32 and won't crash +static int strcmp_safe(const char *p1, const char *p2) { + const unsigned char *s1 = (const unsigned char *) p1; + const unsigned char *s2 = (const unsigned char *) p2; + unsigned char c1, c2; + do + { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0') + return c1 - c2; + } + while (c1 == c2); + return c1 - c2; + } bool type_info::before (const type_info &arg) const _GLIBCXX_NOEXCEPT @@ -37,7 +52,7 @@ type_info::before (const type_info &arg) const _GLIBCXX_NOEXCEPT return name () < arg.name (); #else return (name ()[0] == '*') ? name () < arg.name () - : __builtin_strcmp (name (), arg.name ()) < 0; + : strcmp_safe (name (), arg.name ()) < 0; #endif } diff --git a/libstdc++-v3/libsupc++/typeinfo b/libstdc++-v3/libsupc++/typeinfo index 0ed47fcdfb6..345c95b3270 100644 --- a/libstdc++-v3/libsupc++/typeinfo +++ b/libstdc++-v3/libsupc++/typeinfo @@ -50,7 +50,7 @@ namespace __cxxabiv1 // must be compared), and whether comparison is to be implemented inline or // not. We used to do inline pointer comparison by default if weak symbols // are available, but even with weak symbols sometimes names are not merged -// when objects are loaded with RTLD_LOCAL, so now we always use strcmp by +// when objects are loaded with RTLD_LOCAL, so now we always use p2 by // default. For ABI compatibility, we do the strcmp inline if weak symbols // are available, and out-of-line if not. Out-of-line pointer comparison // is used where the object files are to be portable to multiple systems, @@ -115,13 +115,13 @@ namespace std bool before(const type_info& __arg) const _GLIBCXX_NOEXCEPT { return (__name[0] == '*' && __arg.__name[0] == '*') ? __name < __arg.__name - : __builtin_strcmp (__name, __arg.__name) < 0; } + : strcmp_safe (__name, __arg.__name) < 0; } bool operator==(const type_info& __arg) const _GLIBCXX_NOEXCEPT { return ((__name == __arg.__name) || (__name[0] != '*' && - __builtin_strcmp (__name, __arg.__name) == 0)); + strcmp_safe (__name, __arg.__name) == 0)); } #else // On some targets we can rely on type_info's NTBS being unique, @@ -176,6 +176,23 @@ namespace std /// Assigning type_info is not supported. type_info& operator=(const type_info&); type_info(const type_info&); + + // Write own version so it's compiled with mforce-l32 and won't crash + static int strcmp_safe(const char *p1, const char *p2) { + const unsigned char *s1 = (const unsigned char *) p1; + const unsigned char *s2 = (const unsigned char *) p2; + unsigned char c1, c2; + do + { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0') + return c1 - c2; + } + while (c1 == c2); + return c1 - c2; + } + }; /**