This revision was automatically updated to reflect the committed changes.
Closed by commit rL318902: Allow to set locale on Windows. (authored by 
mstorsjo).

Changed prior to commit:
  https://reviews.llvm.org/D40181?vs=123923&id=124055#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D40181

Files:
  libcxx/trunk/include/__config
  libcxx/trunk/include/__locale
  libcxx/trunk/include/support/win32/locale_win32.h
  libcxx/trunk/src/support/win32/locale_win32.cpp

Index: libcxx/trunk/src/support/win32/locale_win32.cpp
===================================================================
--- libcxx/trunk/src/support/win32/locale_win32.cpp
+++ libcxx/trunk/src/support/win32/locale_win32.cpp
@@ -18,21 +18,7 @@
 // FIXME: base currently unused. Needs manual work to construct the new locale
 locale_t newlocale( int mask, const char * locale, locale_t /*base*/ )
 {
-    return _create_locale( mask, locale );
-}
-
-locale_t uselocale( locale_t newloc )
-{
-    locale_t old_locale = _get_current_locale();
-    if ( newloc == NULL )
-        return old_locale;
-    // uselocale sets the thread's locale by definition, so unconditionally use thread-local locale
-    _configthreadlocale( _ENABLE_PER_THREAD_LOCALE );
-    // uselocale sets all categories
-    // disable setting locale on Windows temporarily because the structure is opaque (PR31516)
-    //setlocale( LC_ALL, newloc->locinfo->lc_category[LC_ALL].locale );
-    // uselocale returns the old locale_t
-    return old_locale;
+    return {_create_locale( LC_ALL, locale ), locale};
 }
 
 decltype(MB_CUR_MAX) MB_CUR_MAX_L( locale_t __l )
Index: libcxx/trunk/include/support/win32/locale_win32.h
===================================================================
--- libcxx/trunk/include/support/win32/locale_win32.h
+++ libcxx/trunk/include/support/win32/locale_win32.h
@@ -14,6 +14,7 @@
 #include <__config>
 #include <stdio.h>
 #include <xlocinfo.h> // _locale_t
+#include <__nullptr>
 
 #define LC_COLLATE_MASK _M_COLLATE
 #define LC_CTYPE_MASK _M_CTYPE
@@ -28,13 +29,77 @@
                      | LC_NUMERIC_MASK \
                      | LC_TIME_MASK )
 
-#define locale_t _locale_t
+class locale_t {
+public:
+    locale_t()
+        : __locale(nullptr), __locale_str(nullptr) {}
+    locale_t(std::nullptr_t)
+        : __locale(nullptr), __locale_str(nullptr) {}
+    locale_t(_locale_t __locale, const char* __locale_str)
+        : __locale(__locale), __locale_str(__locale_str) {}
+
+    friend bool operator==(const locale_t& __left, const locale_t& __right) {
+        return __left.__locale == __right.__locale;
+    }
+
+    friend bool operator==(const locale_t& __left, int __right) {
+        return __left.__locale == nullptr && __right == 0;
+    }
+
+    friend bool operator==(const locale_t& __left, std::nullptr_t) {
+        return __left.__locale == nullptr;
+    }
+
+    friend bool operator==(int __left, const locale_t& __right) {
+        return __left == 0 && nullptr == __right.__locale;
+    }
+
+    friend bool operator==(std::nullptr_t, const locale_t& __right) {
+        return nullptr == __right.__locale;
+    }
+
+    friend bool operator!=(const locale_t& __left, const locale_t& __right) {
+        return !(__left == __right);
+    }
+
+    friend bool operator!=(const locale_t& __left, int __right) {
+        return !(__left == __right);
+    }
+
+    friend bool operator!=(const locale_t& __left, std::nullptr_t __right) {
+        return !(__left == __right);
+    }
+
+    friend bool operator!=(int __left, const locale_t& __right) {
+        return !(__left == __right);
+    }
+
+    friend bool operator!=(std::nullptr_t __left, const locale_t& __right) {
+        return !(__left == __right);
+    }
+
+    operator bool() const {
+        return __locale != nullptr;
+    }
+
+    const char* __get_locale() const { return __locale_str; }
+
+    operator _locale_t() const {
+        return __locale;
+    }
+private:
+    _locale_t __locale;
+    const char* __locale_str;
+};
 
 // Locale management functions
 #define freelocale _free_locale
 // FIXME: base currently unused. Needs manual work to construct the new locale
 locale_t newlocale( int mask, const char * locale, locale_t base );
-locale_t uselocale( locale_t newloc );
+// uselocale can't be implemented on Windows because Windows allows partial modification
+// of thread-local locale and so _get_current_locale() returns a copy while uselocale does
+// not create any copies.
+// We can still implement raii even without uselocale though.
 
 
 lconv *localeconv_l( locale_t loc );
Index: libcxx/trunk/include/__locale
===================================================================
--- libcxx/trunk/include/__locale
+++ libcxx/trunk/include/__locale
@@ -49,7 +49,7 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-#if !defined(_LIBCPP_LOCALE__L_EXTENSIONS) || defined(_LIBCPP_MSVCRT)
+#if !defined(_LIBCPP_LOCALE__L_EXTENSIONS)
 struct __libcpp_locale_guard {
   _LIBCPP_INLINE_VISIBILITY
   __libcpp_locale_guard(locale_t& __loc) : __old_loc_(uselocale(__loc)) {}
@@ -65,6 +65,32 @@
   __libcpp_locale_guard(__libcpp_locale_guard const&);
   __libcpp_locale_guard& operator=(__libcpp_locale_guard const&);
 };
+#elif defined(_LIBCPP_MSVCRT_LIKE)
+struct __libcpp_locale_guard {
+    __libcpp_locale_guard(locale_t __l) :
+        __status(_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)),
+        __locale_collate(setlocale(LC_COLLATE, __l.__get_locale())),
+        __locale_ctype(setlocale(LC_CTYPE, __l.__get_locale())),
+        __locale_monetary(setlocale(LC_MONETARY, __l.__get_locale())),
+        __locale_numeric(setlocale(LC_NUMERIC, __l.__get_locale())),
+        __locale_time(setlocale(LC_TIME, __l.__get_locale()))
+        // LC_MESSAGES is not supported on Windows.
+    {}
+    ~__libcpp_locale_guard() {
+        setlocale(LC_COLLATE, __locale_collate);
+        setlocale(LC_CTYPE, __locale_ctype);
+        setlocale(LC_MONETARY, __locale_monetary);
+        setlocale(LC_NUMERIC, __locale_numeric);
+        setlocale(LC_TIME, __locale_time);
+        _configthreadlocale(__status);
+    }
+    int __status;
+    char* __locale_collate;
+    char* __locale_ctype;
+    char* __locale_monetary;
+    char* __locale_numeric;
+    char* __locale_time;
+};
 #endif
 
 
Index: libcxx/trunk/include/__config
===================================================================
--- libcxx/trunk/include/__config
+++ libcxx/trunk/include/__config
@@ -890,7 +890,7 @@
 #define _LIBCPP_NONUNIQUE_RTTI_BIT (1ULL << 63)
 #endif
 
-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(_LIBCPP_MSVCRT) ||   \
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(_LIBCPP_MSVCRT_LIKE) || \
     defined(__sun__) || defined(__NetBSD__) || defined(__CloudABI__)
 #define _LIBCPP_LOCALE__L_EXTENSIONS 1
 #endif
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to