Skip to content

[libc++] Guard additional headers with _LIBCPP_HAS_LOCALIZATION #131921

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Apr 4, 2025

Conversation

ldionne
Copy link
Member

@ldionne ldionne commented Mar 18, 2025

There were some remaining headers that were not guarded with _LIBCPP_HAS_LOCALIZATION, leading to errors when trying to use modules on platforms that don't support localization (since all the headers get pulled in when building the 'std' module). This patch brings these headers in line with what we do for every other header that depends on localization.

This patch also requires including <picolibc.h> from <__configuration/platform.h> in order to define _NEWLIB_VERSION. In the long term, we should use a better approach for doing that, such as defining a macro in the __config_site header.

@ldionne ldionne added this to the LLVM 20.X Release milestone Mar 18, 2025
@ldionne ldionne requested a review from a team as a code owner March 18, 2025 21:37
@github-project-automation github-project-automation bot moved this to Needs Triage in LLVM Release Status Mar 18, 2025
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Mar 18, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 18, 2025

@llvm/pr-subscribers-libcxx

Author: Louis Dionne (ldionne)

Changes

There were some remaining headers that were not guarded with _LIBCPP_HAS_LOCALIZATION, leading to errors when trying to use modules on platforms that don't support localization (since all the headers get pulled in when building the 'std' module).

This patch brings these headers in line with what we do for every other header that depends on localization.


Patch is 56.97 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/131921.diff

4 Files Affected:

  • (modified) libcxx/include/__locale (+91-86)
  • (modified) libcxx/include/__locale_dir/locale_base_api.h (+60-56)
  • (modified) libcxx/include/fstream (+42-43)
  • (modified) libcxx/include/regex (+166-158)
diff --git a/libcxx/include/__locale b/libcxx/include/__locale
index 5ae3228989749..47323046fab38 100644
--- a/libcxx/include/__locale
+++ b/libcxx/include/__locale
@@ -11,32 +11,35 @@
 #define _LIBCPP___LOCALE
 
 #include <__config>
-#include <__locale_dir/locale_base_api.h>
-#include <__memory/addressof.h>
-#include <__memory/shared_count.h>
-#include <__mutex/once_flag.h>
-#include <__type_traits/make_unsigned.h>
-#include <__utility/no_destroy.h>
-#include <__utility/private_constructor_tag.h>
-#include <cctype>
-#include <clocale>
-#include <cstdint>
-#include <cstdlib>
-#include <string>
+
+#if _LIBCPP_HAS_LOCALIZATION
+
+#  include <__locale_dir/locale_base_api.h>
+#  include <__memory/addressof.h>
+#  include <__memory/shared_count.h>
+#  include <__mutex/once_flag.h>
+#  include <__type_traits/make_unsigned.h>
+#  include <__utility/no_destroy.h>
+#  include <__utility/private_constructor_tag.h>
+#  include <cctype>
+#  include <clocale>
+#  include <cstdint>
+#  include <cstdlib>
+#  include <string>
 
 // Some platforms require more includes than others. Keep the includes on all plaforms for now.
-#include <cstddef>
-#include <cstring>
+#  include <cstddef>
+#  include <cstring>
 
-#if _LIBCPP_HAS_WIDE_CHARACTERS
-#  include <cwchar>
-#else
-#  include <__std_mbstate_t.h>
-#endif
+#  if _LIBCPP_HAS_WIDE_CHARACTERS
+#    include <cwchar>
+#  else
+#    include <__std_mbstate_t.h>
+#  endif
 
-#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
-#  pragma GCC system_header
-#endif
+#  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#    pragma GCC system_header
+#  endif
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
@@ -86,9 +89,9 @@ public:
   // locale operations:
   string name() const;
   bool operator==(const locale&) const;
-#if _LIBCPP_STD_VER <= 17
+#  if _LIBCPP_STD_VER <= 17
   _LIBCPP_HIDE_FROM_ABI bool operator!=(const locale& __y) const { return !(*this == __y); }
-#endif
+#  endif
   template <class _CharT, class _Traits, class _Allocator>
   _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool
   operator()(const basic_string<_CharT, _Traits, _Allocator>&, const basic_string<_CharT, _Traits, _Allocator>&) const;
@@ -238,9 +241,9 @@ long collate<_CharT>::do_hash(const char_type* __lo, const char_type* __hi) cons
 }
 
 extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS collate<char>;
-#if _LIBCPP_HAS_WIDE_CHARACTERS
+#  if _LIBCPP_HAS_WIDE_CHARACTERS
 extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS collate<wchar_t>;
-#endif
+#  endif
 
 // template <class CharT> class collate_byname;
 
@@ -265,7 +268,7 @@ protected:
   string_type do_transform(const char_type* __lo, const char_type* __hi) const override;
 };
 
-#if _LIBCPP_HAS_WIDE_CHARACTERS
+#  if _LIBCPP_HAS_WIDE_CHARACTERS
 template <>
 class _LIBCPP_EXPORTED_FROM_ABI collate_byname<wchar_t> : public collate<wchar_t> {
   __locale::__locale_t __l_;
@@ -284,7 +287,7 @@ protected:
       const char_type* __lo1, const char_type* __hi1, const char_type* __lo2, const char_type* __hi2) const override;
   string_type do_transform(const char_type* __lo, const char_type* __hi) const override;
 };
-#endif
+#  endif
 
 template <class _CharT, class _Traits, class _Allocator>
 bool locale::operator()(const basic_string<_CharT, _Traits, _Allocator>& __x,
@@ -297,7 +300,7 @@ bool locale::operator()(const basic_string<_CharT, _Traits, _Allocator>& __x,
 
 class _LIBCPP_EXPORTED_FROM_ABI ctype_base {
 public:
-#if defined(_LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE)
+#  if defined(_LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE)
   typedef unsigned long mask;
   static const mask space  = 1 << 0;
   static const mask print  = 1 << 1;
@@ -309,14 +312,14 @@ public:
   static const mask punct  = 1 << 7;
   static const mask xdigit = 1 << 8;
   static const mask blank  = 1 << 9;
-#  if defined(__BIONIC__)
+#    if defined(__BIONIC__)
   // Historically this was a part of regex_traits rather than ctype_base. The
   // historical value of the constant is preserved for ABI compatibility.
   static const mask __regex_word = 0x8000;
-#  else
+#    else
   static const mask __regex_word = 1 << 10;
-#  endif // defined(__BIONIC__)
-#elif defined(__GLIBC__)
+#    endif // defined(__BIONIC__)
+#  elif defined(__GLIBC__)
   typedef unsigned short mask;
   static const mask space  = _ISspace;
   static const mask print  = _ISprint;
@@ -328,12 +331,12 @@ public:
   static const mask punct  = _ISpunct;
   static const mask xdigit = _ISxdigit;
   static const mask blank  = _ISblank;
-#  if defined(__mips__) || (BYTE_ORDER == BIG_ENDIAN)
+#    if defined(__mips__) || (BYTE_ORDER == BIG_ENDIAN)
   static const mask __regex_word = static_cast<mask>(_ISbit(15));
-#  else
+#    else
   static const mask __regex_word = 0x80;
-#  endif
-#elif defined(_LIBCPP_MSVCRT_LIKE)
+#    endif
+#  elif defined(_LIBCPP_MSVCRT_LIKE)
   typedef unsigned short mask;
   static const mask space        = _SPACE;
   static const mask print        = _BLANK | _PUNCT | _ALPHA | _DIGIT;
@@ -346,16 +349,16 @@ public:
   static const mask xdigit       = _HEX;
   static const mask blank        = _BLANK;
   static const mask __regex_word = 0x4000; // 0x8000 and 0x0100 and 0x00ff are used
-#  define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
-#  define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
-#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
-#  ifdef __APPLE__
+#    define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
+#    define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
+#  elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
+#    ifdef __APPLE__
   typedef uint32_t mask;
-#  elif defined(__FreeBSD__)
+#    elif defined(__FreeBSD__)
   typedef unsigned long mask;
-#  elif defined(__NetBSD__)
+#    elif defined(__NetBSD__)
   typedef unsigned short mask;
-#  endif
+#    endif
   static const mask space  = _CTYPE_S;
   static const mask print  = _CTYPE_R;
   static const mask cntrl  = _CTYPE_C;
@@ -366,16 +369,16 @@ public:
   static const mask punct  = _CTYPE_P;
   static const mask xdigit = _CTYPE_X;
 
-#  if defined(__NetBSD__)
+#    if defined(__NetBSD__)
   static const mask blank = _CTYPE_BL;
   // NetBSD defines classes up to 0x2000
   // see sys/ctype_bits.h, _CTYPE_Q
   static const mask __regex_word = 0x8000;
-#  else
+#    else
   static const mask blank        = _CTYPE_B;
   static const mask __regex_word = 0x80;
-#  endif
-#elif defined(_AIX)
+#    endif
+#  elif defined(_AIX)
   typedef unsigned int mask;
   static const mask space        = _ISSPACE;
   static const mask print        = _ISPRINT;
@@ -388,7 +391,7 @@ public:
   static const mask xdigit       = _ISXDIGIT;
   static const mask blank        = _ISBLANK;
   static const mask __regex_word = 0x8000;
-#elif defined(_NEWLIB_VERSION)
+#  elif defined(_NEWLIB_VERSION)
   // Same type as Newlib's _ctype_ array in newlib/libc/include/ctype.h.
   typedef char mask;
   // In case char is signed, static_cast is needed to avoid warning on
@@ -405,11 +408,11 @@ public:
   static const mask blank  = static_cast<mask>(_B);
   // mask is already fully saturated, use a different type in regex_type_traits.
   static const unsigned short __regex_word = 0x100;
-#  define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
-#  define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
-#  define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
-#elif defined(__MVS__)
-#  if defined(__NATIVE_ASCII_F)
+#    define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
+#    define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
+#    define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
+#  elif defined(__MVS__)
+#    if defined(__NATIVE_ASCII_F)
   typedef unsigned int mask;
   static const mask space  = _ISSPACE_A;
   static const mask print  = _ISPRINT_A;
@@ -421,7 +424,7 @@ public:
   static const mask punct  = _ISPUNCT_A;
   static const mask xdigit = _ISXDIGIT_A;
   static const mask blank  = _ISBLANK_A;
-#  else
+#    else
   typedef unsigned short mask;
   static const mask space  = __ISSPACE;
   static const mask print  = __ISPRINT;
@@ -433,11 +436,11 @@ public:
   static const mask punct  = __ISPUNCT;
   static const mask xdigit = __ISXDIGIT;
   static const mask blank  = __ISBLANK;
-#  endif
+#    endif
   static const mask __regex_word = 0x8000;
-#else
-#  error unknown rune table for this platform -- do you mean to define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE?
-#endif
+#  else
+#    error unknown rune table for this platform -- do you mean to define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE?
+#  endif
   static const mask alnum = alpha | digit;
   static const mask graph = alnum | punct;
 
@@ -451,7 +454,7 @@ public:
 template <class _CharT>
 class _LIBCPP_TEMPLATE_VIS ctype;
 
-#if _LIBCPP_HAS_WIDE_CHARACTERS
+#  if _LIBCPP_HAS_WIDE_CHARACTERS
 template <>
 class _LIBCPP_EXPORTED_FROM_ABI ctype<wchar_t> : public locale::facet, public ctype_base {
 public:
@@ -516,7 +519,7 @@ protected:
   virtual const char_type*
   do_narrow(const char_type* __low, const char_type* __high, char __dfault, char* __dest) const;
 };
-#endif // _LIBCPP_HAS_WIDE_CHARACTERS
+#  endif // _LIBCPP_HAS_WIDE_CHARACTERS
 
 inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_isascii(int __c) { return (__c & ~0x7F) == 0; }
 
@@ -581,25 +584,25 @@ public:
 
   static locale::id id;
 
-#ifdef _CACHED_RUNES
+#  ifdef _CACHED_RUNES
   static const size_t table_size = _CACHED_RUNES;
-#else
+#  else
   static const size_t table_size = 256; // FIXME: Don't hardcode this.
-#endif
+#  endif
   _LIBCPP_HIDE_FROM_ABI const mask* table() const _NOEXCEPT { return __tab_; }
   static const mask* classic_table() _NOEXCEPT;
-#if defined(__GLIBC__) || defined(__EMSCRIPTEN__)
+#  if defined(__GLIBC__) || defined(__EMSCRIPTEN__)
   static const int* __classic_upper_table() _NOEXCEPT;
   static const int* __classic_lower_table() _NOEXCEPT;
-#endif
-#if defined(__NetBSD__)
+#  endif
+#  if defined(__NetBSD__)
   static const short* __classic_upper_table() _NOEXCEPT;
   static const short* __classic_lower_table() _NOEXCEPT;
-#endif
-#if defined(__MVS__)
+#  endif
+#  if defined(__MVS__)
   static const unsigned short* __classic_upper_table() _NOEXCEPT;
   static const unsigned short* __classic_lower_table() _NOEXCEPT;
-#endif
+#  endif
 
 protected:
   ~ctype() override;
@@ -634,7 +637,7 @@ protected:
   const char_type* do_tolower(char_type* __low, const char_type* __high) const override;
 };
 
-#if _LIBCPP_HAS_WIDE_CHARACTERS
+#  if _LIBCPP_HAS_WIDE_CHARACTERS
 template <>
 class _LIBCPP_EXPORTED_FROM_ABI ctype_byname<wchar_t> : public ctype<wchar_t> {
   __locale::__locale_t __l_;
@@ -659,7 +662,7 @@ protected:
   const char_type*
   do_narrow(const char_type* __low, const char_type* __high, char __dfault, char* __dest) const override;
 };
-#endif // _LIBCPP_HAS_WIDE_CHARACTERS
+#  endif // _LIBCPP_HAS_WIDE_CHARACTERS
 
 template <class _CharT>
 inline _LIBCPP_HIDE_FROM_ABI bool isspace(_CharT __c, const locale& __loc) {
@@ -825,7 +828,7 @@ protected:
 
 // template <> class codecvt<wchar_t, char, mbstate_t>
 
-#if _LIBCPP_HAS_WIDE_CHARACTERS
+#  if _LIBCPP_HAS_WIDE_CHARACTERS
 template <>
 class _LIBCPP_EXPORTED_FROM_ABI codecvt<wchar_t, char, mbstate_t> : public locale::facet, public codecvt_base {
   __locale::__locale_t __l_;
@@ -904,7 +907,7 @@ protected:
   virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const;
   virtual int do_max_length() const _NOEXCEPT;
 };
-#endif // _LIBCPP_HAS_WIDE_CHARACTERS
+#  endif // _LIBCPP_HAS_WIDE_CHARACTERS
 
 // template <> class codecvt<char16_t, char, mbstate_t> // deprecated in C++20
 
@@ -986,7 +989,7 @@ protected:
   virtual int do_max_length() const _NOEXCEPT;
 };
 
-#if _LIBCPP_HAS_CHAR8_T
+#  if _LIBCPP_HAS_CHAR8_T
 
 // template <> class codecvt<char16_t, char8_t, mbstate_t> // C++20
 
@@ -1067,7 +1070,7 @@ protected:
   virtual int do_max_length() const _NOEXCEPT;
 };
 
-#endif
+#  endif
 
 // template <> class codecvt<char32_t, char, mbstate_t> // deprecated in C++20
 
@@ -1149,7 +1152,7 @@ protected:
   virtual int do_max_length() const _NOEXCEPT;
 };
 
-#if _LIBCPP_HAS_CHAR8_T
+#  if _LIBCPP_HAS_CHAR8_T
 
 // template <> class codecvt<char32_t, char8_t, mbstate_t> // C++20
 
@@ -1230,7 +1233,7 @@ protected:
   virtual int do_max_length() const _NOEXCEPT;
 };
 
-#endif
+#  endif
 
 // template <class _InternT, class _ExternT, class _StateT> class codecvt_byname
 
@@ -1252,17 +1255,17 @@ codecvt_byname<_InternT, _ExternT, _StateT>::~codecvt_byname() {}
 _LIBCPP_SUPPRESS_DEPRECATED_POP
 
 extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char, char, mbstate_t>;
-#if _LIBCPP_HAS_WIDE_CHARACTERS
+#  if _LIBCPP_HAS_WIDE_CHARACTERS
 extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<wchar_t, char, mbstate_t>;
-#endif
+#  endif
 extern template class _LIBCPP_DEPRECATED_IN_CXX20
 _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char16_t, char, mbstate_t>; // deprecated in C++20
 extern template class _LIBCPP_DEPRECATED_IN_CXX20
 _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char32_t, char, mbstate_t>; // deprecated in C++20
-#if _LIBCPP_HAS_CHAR8_T
+#  if _LIBCPP_HAS_CHAR8_T
 extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char16_t, char8_t, mbstate_t>; // C++20
 extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char32_t, char8_t, mbstate_t>; // C++20
-#endif
+#  endif
 
 template <size_t _Np>
 struct __narrow_to_utf8 {
@@ -1442,7 +1445,7 @@ protected:
   string __grouping_;
 };
 
-#if _LIBCPP_HAS_WIDE_CHARACTERS
+#  if _LIBCPP_HAS_WIDE_CHARACTERS
 template <>
 class _LIBCPP_EXPORTED_FROM_ABI numpunct<wchar_t> : public locale::facet {
 public:
@@ -1471,7 +1474,7 @@ protected:
   char_type __thousands_sep_;
   string __grouping_;
 };
-#endif // _LIBCPP_HAS_WIDE_CHARACTERS
+#  endif // _LIBCPP_HAS_WIDE_CHARACTERS
 
 // template <class charT> class numpunct_byname
 
@@ -1494,7 +1497,7 @@ private:
   void __init(const char*);
 };
 
-#if _LIBCPP_HAS_WIDE_CHARACTERS
+#  if _LIBCPP_HAS_WIDE_CHARACTERS
 template <>
 class _LIBCPP_EXPORTED_FROM_ABI numpunct_byname<wchar_t> : public numpunct<wchar_t> {
 public:
@@ -1510,8 +1513,10 @@ protected:
 private:
   void __init(const char*);
 };
-#endif // _LIBCPP_HAS_WIDE_CHARACTERS
+#  endif // _LIBCPP_HAS_WIDE_CHARACTERS
 
 _LIBCPP_END_NAMESPACE_STD
 
+#endif // _LIBCPP_HAS_LOCALIZATION
+
 #endif // _LIBCPP___LOCALE
diff --git a/libcxx/include/__locale_dir/locale_base_api.h b/libcxx/include/__locale_dir/locale_base_api.h
index 92916944227d7..bbc30b1cfe03f 100644
--- a/libcxx/include/__locale_dir/locale_base_api.h
+++ b/libcxx/include/__locale_dir/locale_base_api.h
@@ -111,59 +111,61 @@
 //  int     __sscanf(const char*, __locale_t, const char*, ...);     // required by the headers
 // }
 
-#if defined(__APPLE__)
-#  include <__locale_dir/support/apple.h>
-#elif defined(__FreeBSD__)
-#  include <__locale_dir/support/freebsd.h>
-#elif defined(_LIBCPP_MSVCRT_LIKE)
-#  include <__locale_dir/support/windows.h>
-#elif defined(__Fuchsia__)
-#  include <__locale_dir/support/fuchsia.h>
-#elif defined(__linux__)
-#  include <__locale_dir/support/linux.h>
-#else
+#if _LIBCPP_HAS_LOCALIZATION
+
+#  if defined(__APPLE__)
+#    include <__locale_dir/support/apple.h>
+#  elif defined(__FreeBSD__)
+#    include <__locale_dir/support/freebsd.h>
+#  elif defined(_LIBCPP_MSVCRT_LIKE)
+#    include <__locale_dir/support/windows.h>
+#  elif defined(__Fuchsia__)
+#    include <__locale_dir/support/fuchsia.h>
+#  elif defined(__linux__)
+#    include <__locale_dir/support/linux.h>
+#  else
 
 // TODO: This is a temporary definition to bridge between the old way we defined the locale base API
 //       (by providing global non-reserved names) and the new API. As we move individual platforms
 //       towards the new way of defining the locale base API, this should disappear since each platform
 //       will define those directly.
-#  if defined(_AIX) || defined(__MVS__)
-#    include <__locale_dir/locale_base_api/ibm.h>
-#  elif defined(__ANDROID__)
-#    include <__locale_dir/locale_base_api/android.h>
-#  elif defined(__OpenBSD__)
-#    include <__locale_dir/locale_base_api/openbsd.h>
-#  elif defined(__wasi__) || _LIBCPP_HAS_MUSL_LIBC
-#    include <__locale_dir/locale_base_api/musl.h>
-#  endif
-
-#  include <__locale_dir/locale_base_api/bsd_locale_fallbacks.h>
-
-#  include <__cstddef/size_t.h>
-#  include <__utility/forward.h>
-#  include <ctype.h>
-#  include <string.h>
-#  include <time.h>
-#  if _LIBCPP_HAS_WIDE_CHARACTERS
-#    include <wctype.h>
-#  endif
+#    if defined(_AIX) || defined(__MVS__)
+#      include <__locale_dir/locale_base_api/ibm.h>
+#    elif defined(__ANDROID__)
+#      include <__locale_dir/locale_base_api/android.h>
+#    elif defined(__OpenBSD__)
+#      include <__locale_dir/locale_base_api/openbsd.h>
+#    elif defined(__wasi__) || _LIBCPP_HAS_MUSL_LIBC
+#      include <__locale_dir/locale_base_api/musl.h>
+#    endif
+
+#    include <__locale_dir/locale_base_api/bsd_locale_fallbacks.h>
+
+#    include <__cstddef/size_t.h>
+#    include <__utility/forward.h>
+#    include <ctype.h>
+#    include <string.h>
+#    include <time.h>
+#    if _LIBCPP_HAS_WIDE_CHARACTERS
+#      include <wctype.h>
+#    endif
 _LIBCPP_BEGIN_NAMESPACE_STD
 namespace __locale {
 //
 // Locale management
 //
-#  define _LIBCPP_COLLATE_MASK LC_COLLATE_MASK
-#  define _LIBCPP_CTYPE_MASK LC_CTYPE_MASK
-#  define _LIBCPP_MONETARY_MASK LC_MONETARY_MASK
-#  define _LIBCPP_NUMERIC_MASK LC_NUMERIC_MASK
-#  define _LIBCPP_TIME_MASK LC_TIME_MASK
-#  define _LIBCPP_MESSAGES_MASK LC_MESSAGES_MASK
-#  define _LIBCPP_ALL_MASK LC_ALL_MASK
-#  define _LIBCPP_LC_ALL LC_ALL
+#    define _LIBCPP_COLLATE_MASK LC_COLLATE_MASK
+#    define _LIBCPP_CTYPE_MASK LC_CTYPE_MASK
+#    define _LIBCPP_MONETARY_MASK LC_MONETARY_MASK
+#    define _LIBCPP_NUMERIC_MASK LC_NUMERIC_MASK
+#    define _LIBCPP_TIME_MASK LC_TIME_MASK
+#    define _LIBCPP_MESSAGES_MASK LC_MESSAGES_MASK
+#    define _LIBCPP_ALL_MASK LC_ALL_MASK
+#    define _LIBCPP_LC_ALL LC_ALL
 
 using __locale_t _LIBCPP_NODEBUG = locale_t;
 
-#  if defined(_LIBCPP_BUILDING_LIBRARY)
+#    if defined(_LIBCPP_BUILDING_LIBRARY)
 using __lconv_t _LIBCPP_NODEBUG = lconv;
 
 inline _LIBCPP_HIDE_FROM_ABI __locale_t __newlocale(int __category_mask, const char* __name, __locale_t __loc) {
@@ -177,7 +179,7 @@ inline _LIBCPP_HIDE_FROM_ABI char* __setlocale(int __category, char const* __loc
 inline _LIBCPP_HIDE_FROM_ABI void __freelocale(__locale_t __loc) { freelocale(__loc); }
 
 inline _LIBCPP_HIDE_FROM_ABI __lconv_t* __localeconv(__locale_t& __loc) { return __libcpp_localeconv_l(__loc); }
-#  endif // _LIBCPP_BUILDING_LIBRARY
+#    endif // _LIBCPP_BUILDING_LIBRARY
 
 //
 // Strtonum functions
@@ -206,15 +208,15 @@ __strtoull(const char* __nptr, char** __endptr, int __base, __locale_t __loc) {
 //
 // Character manipulation functions
 //
-#  if defined(_LIBCPP_BUILDING_LIBRARY)
+#    if defined(_LIBCPP_BUILDING_LIBRARY)
 inline _LIBCPP_HIDE_FROM_ABI int __islower(int __ch, __locale_t __loc) { return islower_l(__ch, __loc); }
 inline _LIBCPP_HIDE_FROM_ABI int __isupper(int __ch, __locale_t __loc) { return isupper_l(__ch, __loc); }
-#  endif
+#    endif
 
 inline _LIBCPP_HIDE_FROM_ABI int __isdigit(int __ch, __locale_t __loc) { return isdigit_l(__ch, __loc); }
 inline _LIBCPP_HIDE_FROM_ABI int __isxdigit(int __ch, __locale_t __loc) { return isxdigit_l(__ch, __loc); }
 
-#  if defined(_LIBCPP_BUILDING_LIBRARY)
+#    if defined(_LIBCPP_BUILDING_LIBRARY)
 inline _LIBCPP_HIDE_FROM_ABI int __strcoll(const char* __s1, const char* __s2, __locale_t __loc) {
   return strcoll_l(__s1, __s2, __loc);
 }
@@ -224,7 +226,7 @@ inline _LIBCPP_HIDE_FROM_ABI size_t __strxfrm(char* __dest, const char* __src, s
 inline _LIBCPP_HIDE_FROM_ABI int __toupper(int __ch, __locale_t __loc) { return toupper_l(__ch, __loc); }
 inline _LIBCPP_HIDE_FROM_ABI int __tolower(int __ch, __locale_t __loc) { return tolower_l(__ch, __loc); }
 
-#    if _LIBCPP_HAS_WIDE_CHARACTERS
+#      if _LIBCPP_HAS_WIDE_CHARACTERS
 inline _LIBCPP_HIDE_FROM_ABI int __wcscoll(const wchar_t* __s1, const wchar_t* __s2, __locale_t __loc) {
   return wcscoll_l(__s1, __s2, __loc);
 }
@@ -246,7 +248,7 @@ inline _LIBCPP_HIDE_FROM_ABI int __iswpunct(wint_t __ch, __locale_t __loc) { ret
 inline _LIBCPP_HIDE_FROM_ABI int __iswxdigit(wint_t __ch, __locale_t __loc) { return iswxdigit_l(__ch, __loc); }
 inline _LIBCPP_HIDE_FROM_ABI wint_t __towupper(wint_t __ch, __locale_t __loc) { return towupper_l(_...
[truncated]

Copy link
Member

@mordante mordante left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, LGTM!

@github-project-automation github-project-automation bot moved this from Needs Triage to Needs Merge in LLVM Release Status Mar 19, 2025
@ldionne
Copy link
Member Author

ldionne commented Mar 19, 2025

@mplatings @domin144 This patch is failing in the CI with e.g.:

/usr/local/bin/c++ <...>/llvm-project/libcxx-ci/libcxx/test/std/depr/depr.str.strstreams/depr.strstreambuf/depr.strstreambuf.members/overflow.pass.cpp --sysroot=<...>/llvm-project/libcxx-ci/build/armv7m-picolibc/install --target=armv7m-none-eabi -nostdinc++ -I <...>/llvm-project/libcxx-ci/build/armv7m-picolibc/libcxx/test-suite-install/include/c++/v1 -I <...>/llvm-project/libcxx-ci/build/armv7m-picolibc/libcxx/test-suite-install/include/c++/v1 -I <...>/llvm-project/libcxx-ci/libcxx/test/support -Wno-atomic-alignment -include picolibc.h -std=c++26 -Werror -Wall -D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER -D_LIBCPP_ENABLE_EXPERIMENTAL -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_NONE -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS -D_LIBCPP_ENABLE_CXX26_REMOVED_STRSTREAM -lc++experimental -nostdlib -nostdlib++ -L <...>/llvm-project/libcxx-ci/build/armv7m-picolibc/libcxx/test-suite-install/lib -lc++ -lc++abi -lc -lm -lclang_rt.builtins -lsemihost -lcrt0-semihost -T <...>/llvm-project/libcxx-ci/build/armv7m-picolibc/install/lib/picolibcpp.ld -Wl,--defsym=__flash=0x0 -Wl,--defsym=__flash_size=0x400000 -Wl,--defsym=__ram=0x21000000 -Wl,--defsym=__ram_size=0x1000000 -Wl,--defsym=__stack_size=0x1000 -o <...>/llvm-project/libcxx-ci/build/armv7m-picolibc/libcxx/test/std/depr/depr.str.strstreams/depr.strstreambuf/depr.strstreambuf.members/Output/overflow.pass.cpp.dir/t.tmp.exe
# .---command stderr------------
# | ld.lld: error: undefined symbol: std::__1::basic_streambuf<char, std::__1::char_traits<char>>::seekoff(long, std::__1::ios_base::seekdir, unsigned int)
# | >>> referenced by iostream.cpp
# | >>>               iostream.cpp.obj:(vtable for std::__1::__stdinbuf<char>) in archive <...>/llvm-project/libcxx-ci/build/armv7m-picolibc/libcxx/test-suite-install/lib/libc++.a
# | >>> referenced by iostream.cpp
# | >>>               iostream.cpp.obj:(vtable for std::__1::__stdoutbuf<char>) in archive <...>/llvm-project/libcxx-ci/build/armv7m-picolibc/libcxx/test-suite-install/lib/libc++.a
# | >>> did you mean: std::__1::basic_streambuf<char, std::__1::char_traits<char>>::seekoff(long long, std::__1::ios_base::seekdir, unsigned int)
# | >>> defined in: <...>/llvm-project/libcxx-ci/build/armv7m-picolibc/libcxx/test-suite-install/lib/libc++.a(ios.instantiations.cpp.obj)
# | clang++: error: ld.lld command failed with exit code 1 (use -v to see invocation)
# `-----------------------------
# error: command failed with exit status: 1

I tracked it down a bit and it looks like what might be happening is a mismatch in the definition of the std::streamoff type here. This could result in basic_streambuf::seekoff being requested as basic_streambuf::seekoff(long, ...) but provided as basic_streambuf::seekoff(long long, ...). Sadly, it's difficult for me to debug this further without having access to the platform. Can you please help out? I'm a bit puzzled as to why this patch is triggering this issue.

@mplatings
Copy link
Collaborator

@DavidSpickett

@ldionne
Copy link
Member Author

ldionne commented Mar 19, 2025

Sorry, it feels like I keep pinging the wrong person about Picolibc. I'm a bit confused. Should we modify this entry in BOT_OWNERS.txt?

N: Linaro Toolchain Working Group
E: [email protected]
D: Arm platforms

Should we add David Spickett explicitly and mention picolibc? Somehow I keep forgetting that our Picolibc builds are maintained by the Linaro group.

@ldionne
Copy link
Member Author

ldionne commented Mar 20, 2025

Gentle ping @DavidSpickett -- this issue is a bit time sensitive for us because this broke actual stuff in the LLVM 20 release.

@ldionne
Copy link
Member Author

ldionne commented Mar 24, 2025

I just pinged [email protected] to get assistance.

@maxim-kuvyrkov
Copy link
Contributor

I just pinged [email protected] to get assistance.

Thanks for pinging linaro-toolchain@ -- David is on vacation this week.

@ceseo , would you please investigate this?

@DavidSpickett
Copy link
Collaborator

Last week I was on holiday, I'm back now so I can take this on instead.

The host machines being AArch64 should be irrelevant given that picolib is all cross compiled and emulated, so I will make some instructions that can work anywhere and see what I find in the process.

@dominik-wojt-2311446
Copy link

Hi, indeed, I am no longer maintaining the picolibc tests.
This error reminds me of #74072

Maybe _NEWLIB_VERSION is not defined in some context where libcxx/include/__fwd/ios.h is included. (just a guess)

#if defined(_NEWLIB_VERSION)
// On newlib, off_t is 'long int'
using streamoff = long int; // for char_traits in <string>
#else
using streamoff = long long; // for char_traits in <string>
#endif

@dominik-wojt-2311446
Copy link

I confirmed the hypothesis, by adding #include <limits.h> to ios.h before _NEWLIB_VERSION macro is checked. With this extra include the tests pass.

Other tests used to have the same problem and a workaround was introduced in test config armv7m-picolibc-libc++.cfg.in:

config.substitutions.append(('%{compile_flags}',
   (...)
    # Various libc++ headers check for the definition of _NEWLIB_VERSION
    # which for picolibc is defined in picolibc.h.
    ' -include picolibc.h'
))

Now, as some specializations are compiled during build step a proper solution for build time (not just for test) is needed.
There is an option to extend flags in run-buildbot, but this would be another workaroud: we would be sure, that the flag is properly recognized during build and test, but user could still include the libc++ headers and miss the flag.

function test-armv7m-picolibc() {
   (...)
    flags="--sysroot=${INSTALL_DIR} -include picolibc.h"

Adding #include <limits.h> (or some other c header, which includes picolibc.h) to ios.h and all other headers checking for _NEWLIB_VERSION would be a robust solution. We would need to accept, that all other targets are also affected though.

@ldionne
Copy link
Member Author

ldionne commented Mar 25, 2025

Thanks a lot for the analysis. We have a kind of precedent for this type of check here:

# if __has_include(<features.h>)

We could check for #if __has_include(<picolibc.h>)? I'm not a big fan of this because I think it's really brittle to start checking for whether arbitrarily named headers exist and then include that, but that could work. WDYT?

@domin144
Copy link
Contributor

I like the idea. This would limit the effect on other platforms.

@DavidSpickett
Copy link
Collaborator

Here are the instructions to reproduce this on any machine:

# If you have qemu-system-arm >= 9.0.2 installed already, skip this.
$ wget https://download.qemu.org/qemu-9.0.2.tar.xz
$ cd qemu-9.0.2/
$ ./configure --prefix=/usr/local --target-list=arm-softmmu
$ make -j$(nproc)
$ sudo make install

# Probably have this if you have tested libcxx on this machine already.
$ sudo apt install python3-psutil

$ cd llvm-project
# Note: if this complains about a missing symbol __head_size_min, make sure the clang is calling a recent lld as the linker.
$ export CC=<your clang>
$ export CXX=<your clang++>

# Downloads and builds picilibc, runs libcxx tests on qemu-system-arm.
$ ./libcxx/utils/ci/run-buildbot armv7m-picolibc

Picolibc version used is 1.8.9 (picolibc/picolibc@48fbc20).

I've made sure current main passes, will reproduce the PR's failures next, and read through Dominik's suggestion.

@DavidSpickett
Copy link
Collaborator

DavidSpickett commented Mar 26, 2025

Should we add David Spickett explicitly and mention picolibc? Somehow I keep forgetting that our Picolibc builds are maintained by the Linaro group.

I will add myself and a couple of other Linaro colleagues' GitHub names to the file.

#133120

@ldionne
Copy link
Member Author

ldionne commented Mar 26, 2025

@DavidSpickett I can't get those commands to work. Looks like you're missing tar xf and also there are some assumptions about dependencies already being installed (I tried in a brand new ubuntu:latest Docker container).

@ldionne
Copy link
Member Author

ldionne commented Mar 26, 2025

I have this patch, but I actually struggle to see how that would fix anything since all of the failing tests show an explicit -include <picolibc.h> on the compiler command-line. So they're already including <picolibc.h> first thing in the compilation:

diff --git a/libcxx/include/__configuration/platform.h b/libcxx/include/__configuration/platform.h
index 8d0f8f63f521..e2f8353cf7d5 100644
--- a/libcxx/include/__configuration/platform.h
+++ b/libcxx/include/__configuration/platform.h
@@ -42,6 +42,13 @@
 #  endif
 #endif
 
+// This is required in order for _NEWLIB_VERSION to be defined in places where we use it.
+// TODO: We shouldn't be including arbitrarily-named headers from libc++ since this can break valid
+//       user code. Move code paths that need _NEWLIB_VERSION to another customization mechanism.
+#if defined(__linux__) && __has_include(<picolibc.h>)
+#  include <picolibc.h>
+#endif
+
 #ifndef __BYTE_ORDER__
 #  error                                                                                                               \
       "Your compiler doesn't seem to define __BYTE_ORDER__, which is required by libc++ to know the endianness of your target platform"
diff --git a/libcxx/test/configs/armv7m-picolibc-libc++.cfg.in b/libcxx/test/configs/armv7m-picolibc-libc++.cfg.in
index 7aedfde89916..9bff5021494e 100644
--- a/libcxx/test/configs/armv7m-picolibc-libc++.cfg.in
+++ b/libcxx/test/configs/armv7m-picolibc-libc++.cfg.in
@@ -11,10 +11,6 @@ config.substitutions.append(('%{compile_flags}',
     # "large atomic operation may incur significant performance penalty; the
     # access size (4 bytes) exceeds the max lock-free size (0 bytes)"
     ' -Wno-atomic-alignment'
-
-    # Various libc++ headers check for the definition of _NEWLIB_VERSION
-    # which for picolibc is defined in picolibc.h.
-    ' -include picolibc.h'
 ))
 config.substitutions.append(('%{link_flags}',
     '-nostdlib -nostdlib++ -L %{lib-dir} -lc++ -lc++abi'

Plus, as I said earlier, I don't think that patch is really the right thing to do.

@domin144
Copy link
Contributor

This looks good except for __linux__. Picolibc is mainly for bare metal, so the __linux__ define will not be there. Removing __linux__ should get the tests passing.

Currently the tests do have explicit -include <picolibc.h> in their commandline, but they link against the prebuilt specializations (libcxx/src/ios.instantiations.cpp), which have been compiled in the library build step (not test build step) and at that step the flag was not added. (At least this is how I think it works).

Plus, as I said earlier, I don't think that patch is really the right thing to do.

It's hard for me to judge. I think it's better than relying on users for including picolibc.h (or some C header) before including libcxx.
Alternatively, one of below could be done:

  • detect picolibc during cmake configure step and record this in __config_site
  • when compiling libc++ against picolibc add some option to the cmake commadline (like -D LIBCXX_EXTRA_SITE_DEFINES=_LIBCPP_INCLUDE_PICOLIBC_H or -D LIBCXX_EXTRA_SITE_DEFINES=_LIBCPP_STREAMOFF_IS_DOUBLE)

after that one of these can be done:

  • include picolibc.h (e.g. in platform.h as you did) only if __config_site has the define added above,
  • don't include picolibc.h at all and use the config from __config_site directly instead of _NEWLIB_VERSION

These are poorly informed ideas - I am new to the libc++ configuration.

@ldionne
Copy link
Member Author

ldionne commented Mar 26, 2025

Currently the tests do have explicit -include <picolibc.h> in their commandline, but they link against the prebuilt specializations (libcxx/src/ios.instantiations.cpp), which have been compiled in the library build step (not test build step) and at that step the flag was not added. (At least this is how I think it works).

Ah, yes, that makes sense!

detect picolibc during cmake configure step and record this in __config_site

That's what I want to do indeed. I think you have very good suggestions in fact, I'll think about it further.

For the meantime, I'll go ahead and try that fix to unblock this patch landing. I think <picolibc.h> is a sufficiently rare name that it shouldn't conflict with many headers named the same in existing projects. Thanks a lot for your input.

@domin144
Copy link
Contributor

Just some more notes:

  • config-ix.cmake already detects picolibc,
  • picolibc does not always define off_t to be long (newlib/libc/include/sys/_types.h):
#ifndef __machine_off_t_defined
#if __SIZEOF_SIZE_T__ == 8 && __SIZEOF_LONG__ < 8
typedef __uint64_t _off_t;
#else
typedef long _off_t;
#endif
#endif

Possible better check to add to config-ix.cmake:

set(_LIBCPP_STREAMOFF_TYPE "long long")
check_cxx_source_compiles("
#include <stdio.h>
template<typename T, typename U> struct is_same;
template<typename T> struct is_same<T, T> {
  typedef bool type;
};
const is_same<off_t, long>::type x = true;
int main() {return 0;}
" STREAM_OFF_T_IS_LONG)
if(STREAM_OFF_T_IS_LONG)
  set(_LIBCPP_STREAMOFF_TYPE "long")
endif()

This would change the type only if off_t is defined and is long.

@DavidSpickett
Copy link
Collaborator

DavidSpickett commented Mar 27, 2025

The instructions I posted were done on a real machine that, if I had thought about this first, I would have realised that ti had built qemu before. Apologies for that.

These commands work on a ubuntu:noble image via Docker. It uses the AArch64 release of llvm, otherwise it should work on any host:

apt update && \
  DEBIAN_FRONTEND=noninteractive apt install curl unzip cmake python3-psutil wget xz-utils gcc g++ python3-venv ninja-build bzip2 libglib2.0-dev git make -y --no-install-recommends && \
  wget https://download.qemu.org/qemu-9.0.2.tar.xz && \
  tar -xvf qemu-9.0.2.tar.xz && \
  cd qemu-9.0.2 && \
  ./configure --prefix=/usr/local --target-list=arm-softmmu && \
  make -j$(nproc) && \
  make install && \
  cd .. && \
  wget https://github.com/llvm/llvm-project/releases/download/llvmorg-19.1.7/clang+llvm-19.1.7-aarch64-linux-gnu.tar.xz && \
  tar -xvf clang+llvm-19.1.7-aarch64-linux-gnu.tar.xz && \
  export CC=/clang+llvm-19.1.7-aarch64-linux-gnu/bin/clang && \
  export CXX=/clang+llvm-19.1.7-aarch64-linux-gnu/bin/clang++ && \
  export PATH=$PATH:/clang+llvm-19.1.7-aarch64-linux-gnu/bin/ && \
  git clone https://github.com/llvm/llvm-project.git && \
  cd llvm-project && \
  ./libcxx/utils/ci/run-buildbot armv7m-picolibc

Btw, given this is run in simulation, if it would help you to have this done using the "normal" CI machines and Docker image, I can look into porting the commands into that.

(Linaro remains committed to supporting the configuration regardless of where it runs)

If there is a follow up to this you'd like to see done, or a change in picolib that would help, we can handle that. I just can't promise to do it right now, as I need time to understand the issue fully.

@ldionne
Copy link
Member Author

ldionne commented Mar 27, 2025

Ack, thanks and no worries for the reproduction steps. I do think it would be helpful to have a way to reproduce those easily, something similar to run-buildbot-container. Side question: I noticed that the linaro bots are now talking over 1.5 hours for each run. I don't think that was the case before. Has anything happened recently with those machines that could result in a change like this, or is it something we might have done in the test suite?

@DavidSpickett
Copy link
Collaborator

We've had performance gremlins in our infrastructure in the past, so I doubt it is the test suite. I'm going to add some more capacity for the moment, to unblock your PRs, and then check if the build times are legitimate.

@tstellar tstellar moved this from Needs Merge to Needs Pull Request in LLVM Release Status Mar 31, 2025
@ldionne
Copy link
Member Author

ldionne commented Apr 1, 2025

Can't repro the issue locally on our Docker image. Rebasing to see if that was a CI fluke.

@ldionne ldionne force-pushed the review/localization-fixes-with-modules branch from 3690a8a to 3131fef Compare April 1, 2025 18:46
ldionne added 6 commits April 3, 2025 18:43
There were some remaining headers that were not guarded with
_LIBCPP_HAS_LOCALIZATION, leading to errors when trying to use
modules on platforms that don't support localization (since all
the headers get pulled in when building the 'std' module).

This patch brings these headers in line with what we do for
every other header that depends on localization.
@ldionne ldionne force-pushed the review/localization-fixes-with-modules branch from 3131fef to 82cdc64 Compare April 3, 2025 22:43
@ldionne ldionne merged commit 4090910 into llvm:main Apr 4, 2025
80 checks passed
@ldionne ldionne deleted the review/localization-fixes-with-modules branch April 4, 2025 15:48
@github-project-automation github-project-automation bot moved this from Needs Pull Request to Done in LLVM Release Status Apr 4, 2025
@ldionne
Copy link
Member Author

ldionne commented Apr 4, 2025

/cherry-pick 4090910

@llvmbot
Copy link
Member

llvmbot commented Apr 4, 2025

Failed to cherry-pick: 4090910

https://github.com/llvm/llvm-project/actions/runs/14269170990

Please manually backport the fix and push it to your github fork. Once this is done, please create a pull request

ldionne added a commit to ldionne/llvm-project that referenced this pull request Apr 4, 2025
…#131921)

There were some remaining headers that were not guarded with
_LIBCPP_HAS_LOCALIZATION, leading to errors when trying to use modules
on platforms that don't support localization (since all the headers get
pulled in when building the 'std' module). This patch brings these
headers in line with what we do for every other header that depends on
localization.

This patch also requires including <picolibc.h> from
<__configuration/platform.h> in order to define _NEWLIB_VERSION. In the
long term, we should use a better approach for doing that, such as
defining a macro in the __config_site header.

(cherry picked from commit 4090910)
@ldionne
Copy link
Member Author

ldionne commented Apr 4, 2025

Cherry-pick is #134406

ldionne added a commit to ldionne/llvm-project that referenced this pull request Apr 4, 2025
…#131921)

There were some remaining headers that were not guarded with
_LIBCPP_HAS_LOCALIZATION, leading to errors when trying to use modules
on platforms that don't support localization (since all the headers get
pulled in when building the 'std' module). This patch brings these
headers in line with what we do for every other header that depends on
localization.

This patch also requires including <picolibc.h> from
<__configuration/platform.h> in order to define _NEWLIB_VERSION. In the
long term, we should use a better approach for doing that, such as
defining a macro in the __config_site header.

(cherry picked from commit 4090910)
swift-ci pushed a commit to swiftlang/llvm-project that referenced this pull request Apr 15, 2025
…#131921)

There were some remaining headers that were not guarded with
_LIBCPP_HAS_LOCALIZATION, leading to errors when trying to use modules
on platforms that don't support localization (since all the headers get
pulled in when building the 'std' module). This patch brings these
headers in line with what we do for every other header that depends on
localization.

This patch also requires including <picolibc.h> from
<__configuration/platform.h> in order to define _NEWLIB_VERSION. In the
long term, we should use a better approach for doing that, such as
defining a macro in the __config_site header.

(cherry picked from commit 4090910)
inglorion added a commit to inglorion/llvm-project that referenced this pull request Aug 8, 2025
Fixes llvm#152763.

llvm#131921 added some code to
pull in a definition of _NEWLIB_VERSION if it exists. It does this
by checking __has_include(<picolibc.h>) and including it if so.
However, this does not work for systems that have newlib rather
than picolibc. This change instead checks for and includes
_newlib_version.h, which should work for both newlib and picolibc.
inglorion added a commit to inglorion/llvm-project that referenced this pull request Aug 11, 2025
Fixes llvm#152763.

llvm#131921 added some code to
pull in a definition of _NEWLIB_VERSION if it exists. It does this
by checking __has_include(<picolibc.h>) and including it if so.
However, this does not work for systems that have newlib rather
than picolibc. With this change, we check for either picolibc.h
or _newlib_version.h, which works for both newlib and picolibc.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. release:cherry-pick-failed
Projects
Development

Successfully merging this pull request may close these issues.

8 participants