[libcxx-commits] [PATCH] D69505: [libcxx] [Windows] Store the lconv struct returned from localeconv in locale_t

Martin Storsjö via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Wed Oct 30 01:44:40 PDT 2019


mstorsjo added a comment.

In D69505#1726163 <https://reviews.llvm.org/D69505#1726163>, @rnk wrote:

> Exciting. =/ So, successive calls to localeconv_l would invalidate the result from the last call.


It's even worse than that. If you call `localeconv_l` with a locale other than the currently set thread specific locale, `__libcpp_locale_guard` will temporarily set the one we want to inspect, then receive the `lconv *` return pointer, and then reset the thread specific locale to what it was before the function was called. When the thread specific locale is reset on return, the `lconv *` pointer we're returning is invalidated.

So currently, `localeconv_l` never works, unless it's used on the currently set locale.

> I could live with that if it was possible to make it private to libcxx.

Any suggestions on how to achieve that? Everything in `include/locale`, `include/__locale` and `include/support/win32/locale_win32.h` ends up included by callers. This current patch changes the ABI of the `locale_t` class on windows, but is that part of the API/ABI that users of libcxx are expected to use, or is it just a helper that accidentally ends up visible? (The `locale_t` class ends up defined without any enclosing namespace whatsoever, at the moment.)

One way could be to add some wrapper around the `localeconv_l` calls in src/locale.cpp. Ideally a wrapper that still returns `lconv *` for compatibility with everything else, but which can be made to allocate temp storage on the stack for windows. But I struggle to see a neat way of doing it.

One way that does come to mind is something preprocessor based, like this:

  #ifdef _WIN32
  #define GET_LCONV_PTR(var, loc) \
    lconv_storage lcs##var; \
    { \
      __libcpp_locale_guard __current(loc); \
      lcs.store(localeconv()); \
    } \
    lconv *var = lcs##var.getPtr()
  #else
  #define GET_LCONV_PTR(var, loc) \
    lconv *var = localeconv_l(loc)
  #endif


Repository:
  rCXX libc++

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D69505/new/

https://reviews.llvm.org/D69505





More information about the libcxx-commits mailing list