Fix issues that LLVM's libc++ test suite finds when setting newlib as
the C library:
  - Work around newlib's limited locale support (which AFAICT is allowed in C).
  - Teach libc++ about the rest of newlib's locale support.
  - Work around newlib's limited support for long double (expecting it
to be double when supported at all).
  - Undefine clearerr/feof/ferror (C allows these to be macros).

Note that newlib also needs changes to update its C99/C11/C++11
support, I'm sending a separate patch to the [email protected]
mailing list.
diff --git a/include/__locale b/include/__locale
index 6d75162..7cfaf2b 100644
--- a/include/__locale
+++ b/include/__locale
@@ -31,6 +31,62 @@
 #pragma GCC system_header
 #endif
 
+// Newlib doesn't have the following C extensions for locales.
+#if defined(_NEWLIB_VERSION)
+typedef void *locale_t;
+extern "C" locale_t duplocale(locale_t);
+extern "C" void freelocale(locale_t);
+extern "C" locale_t newlocale(int, const char *, locale_t);
+extern "C" locale_t uselocale(locale_t);
+#define LC_COLLATE_MASK (1 << LC_COLLATE)
+#define LC_CTYPE_MASK (1 << LC_CTYPE)
+#define LC_MESSAGES_MASK (1 << LC_MESSAGES)
+#define LC_MONETARY_MASK (1 << LC_MONETARY)
+#define LC_NUMERIC_MASK (1 << LC_NUMERIC)
+#define LC_TIME_MASK (1 << LC_TIME)
+#define LC_ALL_MASK (LC_COLLATE_MASK | LC_CTYPE_MASK | LC_MESSAGES_MASK | \
+                     LC_MONETARY_MASK | LC_NUMERIC_MASK | LC_TIME_MASK)
+#define isxdigit_l(a, L) (((void) L), isxdigit(a))
+#define iswxdigit_l(a, L) (((void) L), iswxdigit(a))
+#define isdigit_l(a, L) (((void) L), isdigit(a))
+#define iswdigit_l(a, L) (((void) L), iswdigit(a))
+#define iswcntrl_l(a, L) (((void) L), iswcntrl(a))
+#define iswcntrl_l(a, L) (((void) L), iswcntrl(a))
+#define isalpha_l(a, L) (((void) L), isalpha(a))
+#define iswalpha_l(a, L) (((void) L), iswalpha(a))
+#define ispunct_l(a, L) (((void) L), ispunct(a))
+#define iswpunct_l(a, L) (((void) L), iswpunct(a))
+#define isblank_l(a, L) (((void) L), isblank(a))
+#define iswblank_l(a, L) (((void) L), iswblank(a))
+#define isspace_l(a, L) (((void) L), isspace(a))
+#define iswspace_l(a, L) (((void) L), iswspace(a))
+#define isprint_l(a, L) (((void) L), isprint(a))
+#define iswprint_l(a, L) (((void) L), iswprint(a))
+#define islower_l(a, L) (((void) L), islower(a))
+#define iswlower_l(a, L) (((void) L), iswlower(a))
+#define isupper_l(a, L) (((void) L), isupper(a))
+#define iswupper_l(a, L) (((void) L), iswupper(a))
+#define tolower_l(a, L) (((void) L), tolower(a))
+#define towlower_l(a, L) (((void) L), towlower(a))
+#define toupper_l(a, L) (((void) L), toupper(a))
+#define towupper_l(a, L) (((void) L), towupper(a))
+#define strftime_l(a, b, c, d, L) (((void) L), strftime(a, b, c, d))
+#define strtoll_l(a, b, c, L) (((void) L), strtoll(a, b, c))
+#define strtoull_l(a, b, c, L) (((void) L), strtoull(a, b, c))
+#define strtold_l(a, b, L) (((void) L), strtold(a, b))
+#define strcoll_l(a, b, L) (((void) L), strcoll(a, b))
+#define wstrcoll_l(a, b, L) (((void) L), wstrcoll(a, b))
+#define cscoll_l(a, b, L) (((void) L), cscoll(a, b))
+#define wcscoll_l(a, b, L) (((void) L), wcscoll(a, b))
+#define strxfrm_l(a, b, c, L) (((void) L), strxfrm(a, b, c))
+#define wstrxfrm_l(a, b, c, L) (((void) L), wstrxfrm(a, b, c))
+#define csxfrm_l(a, b, c, L) (((void) L), csxfrm(a, b, c))
+#define wcsxfrm_l(a, b, c, L) (((void) L), wcsxfrm(a, b, c))
+#define sscanf_l(a, b, L, ...) (((void) L), sscanf(a, b, ##__VA_ARGS__))
+#define snprintf_l(a, b, L, c, ...) (((void) L), snprintf(a, b, c, ##__VA_ARGS__))
+#define asprintf_l(a, L, b, ...) (((void) L), asprintf(a, b, ##__VA_ARGS__))
+#endif
+
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 class _LIBCPP_TYPE_VIS locale;
@@ -375,7 +431,20 @@ public:
     static const mask punct  = _ISPUNCT;
     static const mask xdigit = _ISXDIGIT;
     static const mask blank  = _ISBLANK;
-#else  // __GLIBC__ || _WIN32 || __APPLE__ || __FreeBSD__ || __EMSCRIPTEN__ || __sun__
+#elif defined(_NEWLIB_VERSION)
+    typedef char mask; // Same type as Newlib's _ctype_ array in ctype.h.
+    // The following macros are defined in Newlib's ctype.h.
+    static const mask space  = _S;
+    static const mask print  = _P | _U | _L | _N | _B;
+    static const mask cntrl  = _C;
+    static const mask upper  = _U;
+    static const mask lower  = _L;
+    static const mask alpha  = _U | _L;
+    static const mask digit  = _N;
+    static const mask punct  = _P;
+    static const mask xdigit = _X | _N;
+    static const mask blank  = _B;
+#else // __GLIBC__ || _WIN32 || __APPLE__ || __FreeBSD__ || __EMSCRIPTEN__ || __NetBSD__ || __sun__ || _AIX || _NEWLIB_VERSION
     typedef unsigned long mask;
     static const mask space  = 1<<0;
     static const mask print  = 1<<1;
@@ -387,7 +456,7 @@ public:
     static const mask punct  = 1<<7;
     static const mask xdigit = 1<<8;
     static const mask blank  = 1<<9;
-#endif  // __GLIBC__ || _WIN32 || __APPLE__ || __FreeBSD__
+#endif  // __GLIBC__ || _WIN32 || __APPLE__ || __FreeBSD__ || __EMSCRIPTEN__ || __NetBSD__ || __sun__ || _AIX || _NEWLIB_VERSION
     static const mask alnum  = alpha | digit;
     static const mask graph  = alnum | punct;
 
diff --git a/include/cmath b/include/cmath
index 75087ae..4a88398 100644
--- a/include/cmath
+++ b/include/cmath
@@ -1382,7 +1382,11 @@ using ::log2;
 using ::log2f;
 
 inline _LIBCPP_INLINE_VISIBILITY float       log2(float __x) _NOEXCEPT       {return log2f(__x);}
+#if defined(_NEWLIB_VERSION)
+inline _LIBCPP_INLINE_VISIBILITY long double log2(long double __x) _NOEXCEPT {return __builtin_log2(__x);}
+#else
 inline _LIBCPP_INLINE_VISIBILITY long double log2(long double __x) _NOEXCEPT {return log2l(__x);}
+#endif
 
 template <class _A1>
 inline _LIBCPP_INLINE_VISIBILITY
@@ -1395,7 +1399,11 @@ using ::logb;
 using ::logbf;
 
 inline _LIBCPP_INLINE_VISIBILITY float       logb(float __x) _NOEXCEPT       {return logbf(__x);}
+#if defined(_NEWLIB_VERSION)
+inline _LIBCPP_INLINE_VISIBILITY long double logb(long double __x) _NOEXCEPT {return __builtin_logb(__x);}
+#else
 inline _LIBCPP_INLINE_VISIBILITY long double logb(long double __x) _NOEXCEPT {return logbl(__x);}
+#endif
 
 template <class _A1>
 inline _LIBCPP_INLINE_VISIBILITY
@@ -1480,6 +1488,15 @@ nextafter(_A1 __x, _A2 __y) _NOEXCEPT
 
 // nexttoward
 
+#if defined(_NEWLIB_VERSION)
+inline _LIBCPP_INLINE_VISIBILITY float       nexttoward(float __x, long double __y) _NOEXCEPT       {return __builtin_nexttoward(__x, __y);}
+inline _LIBCPP_INLINE_VISIBILITY long double nexttoward(long double __x, long double __y) _NOEXCEPT {return __builtin_nexttoward(__x, __y);}
+
+template <class _A1>
+inline _LIBCPP_INLINE_VISIBILITY
+typename enable_if<is_integral<_A1>::value, double>::type
+nexttoward(_A1 __x, long double __y) _NOEXCEPT {return __builtin_nexttoward((double)__x, __y);}
+#else
 using ::nexttoward;
 using ::nexttowardf;
 
@@ -1490,7 +1507,7 @@ template <class _A1>
 inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if<is_integral<_A1>::value, double>::type
 nexttoward(_A1 __x, long double __y) _NOEXCEPT {return nexttoward((double)__x, __y);}
-
+#endif
 // remainder
 
 using ::remainder;
@@ -1663,14 +1680,18 @@ using ::lgammal;
 using ::llrintl;
 using ::llroundl;
 using ::log1pl;
+#if !defined(_NEWLIB_VERSION)
 using ::log2l;
 using ::logbl;
+#endif
 using ::lrintl;
 using ::lroundl;
 using ::nanl;
 using ::nearbyintl;
 using ::nextafterl;
+#if !defined(_NEWLIB_VERSION)
 using ::nexttowardl;
+#endif
 using ::remainderl;
 using ::remquol;
 using ::rintl;
diff --git a/include/cstdio b/include/cstdio
index ce3af4d..a26a133 100644
--- a/include/cstdio
+++ b/include/cstdio
@@ -172,8 +172,11 @@ using ::fseek;
 using ::fsetpos;
 using ::ftell;
 using ::rewind;
+#undef clearerr
 using ::clearerr;
+#undef feof
 using ::feof;
+#undef ferror
 using ::ferror;
 using ::perror;
 
diff --git a/include/locale b/include/locale
index ac3ae7e..3dc4560 100644
--- a/include/locale
+++ b/include/locale
@@ -193,7 +193,9 @@ template <class charT> class messages_byname;
 #include <ctime>
 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
 #include <support/win32/locale_win32.h>
-#else // _LIBCPP_MSVCRT
+#elif defined(_NEWLIB_VERSION)
+// Not supported by newlib.
+#else // _WIN32
 #include <nl_types.h>
 #endif  // !_LIBCPP_MSVCRT
 
@@ -229,7 +231,7 @@ typedef _VSTD::unique_ptr<__locale_struct, decltype(&uselocale)> __locale_raii;
 // OSX has nice foo_l() functions that let you turn off use of the global
 // locale.  Linux, not so much.  The following functions avoid the locale when
 // that's possible and otherwise do the wrong thing.  FIXME.
-#if defined(__linux__) || defined(__EMSCRIPTEN__) || defined(_AIX)
+#if defined(__linux__) || defined(__EMSCRIPTEN__) || defined(_AIX) || defined(_NEWLIB_VERSION)
 
 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
 decltype(MB_CUR_MAX_L(_VSTD::declval<locale_t>()))
@@ -3673,7 +3675,7 @@ template <class _CharT>
 typename messages<_CharT>::catalog
 messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
 {
-#ifdef _WIN32
+#if defined(_WIN32) || defined(_NEWLIB_VERSION)
     return -1;
 #else // _WIN32
     catalog __cat = (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
@@ -3688,7 +3690,7 @@ typename messages<_CharT>::string_type
 messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
                          const string_type& __dflt) const
 {
-#ifdef _WIN32
+#if defined(_WIN32) || defined(_NEWLIB_VERSION)
     return __dflt;
 #else // _WIN32
     string __ndflt;
@@ -3710,7 +3712,7 @@ template <class _CharT>
 void
 messages<_CharT>::do_close(catalog __c) const
 {
-#if !defined(_WIN32)
+#if !defined(_WIN32) && !defined(_NEWLIB_VERSION)
     if (__c != -1)
         __c <<= 1;
     nl_catd __cat = (nl_catd)__c;
diff --git a/src/locale.cpp b/src/locale.cpp
index 8e7fdb4..9b5d7e4 100644
--- a/src/locale.cpp
+++ b/src/locale.cpp
@@ -42,6 +42,16 @@
 #pragma clang diagnostic ignored "-Wsign-conversion"
 #endif
 
+// Newlib doesn't have the following C extensions for locales.
+#if defined(_NEWLIB_VERSION)
+extern "C" {
+  locale_t duplocale(locale_t) { return NULL; }
+  void freelocale(locale_t) { }
+  locale_t newlocale(int, const char *, locale_t) { return NULL; }
+  locale_t uselocale(locale_t) { return NULL; }
+}
+#endif
+
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 #ifdef __cloc_defined
@@ -1037,6 +1047,9 @@ ctype<char>::classic_table()  _NOEXCEPT
     return *__ctype_b_loc();
 #elif defined(_AIX)
     return (const unsigned int *)__lc_ctype_ptr->obj->mask;
+#elif defined(_NEWLIB_VERSION)
+    // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
+    return _ctype_ + 1;
 #else
     // Platform not supported: abort so the person doing the port knows what to
     // fix
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to