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