From c13e7785c2b9a4730efcd841afa33fd1800d93c8 Mon Sep 17 00:00:00 2001 From: Shane Carr Date: Thu, 26 Apr 2018 03:38:17 +0000 Subject: [PATCH] ICU-13725 Fixing NumberFormatter std::move test failure on MSVC. X-SVN-Rev: 41282 --- icu4c/source/i18n/number_fluent.cpp | 38 +++++++++++++++------ icu4c/source/i18n/unicode/numberformatter.h | 2 ++ 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/icu4c/source/i18n/number_fluent.cpp b/icu4c/source/i18n/number_fluent.cpp index c0aacf46b5d..bc43defaa3c 100644 --- a/icu4c/source/i18n/number_fluent.cpp +++ b/icu4c/source/i18n/number_fluent.cpp @@ -378,13 +378,11 @@ LocalizedNumberFormatter::LocalizedNumberFormatter(LocalizedNumberFormatter&& sr LocalizedNumberFormatter::LocalizedNumberFormatter(NFS&& src) U_NOEXCEPT : NFS(std::move(src)) { - // For the move operators, copy over the call count and compiled formatter. - auto&& srcAsLNF = static_cast(src); - fCompiled = srcAsLNF.fCompiled; - uprv_memcpy(fUnsafeCallCount, srcAsLNF.fUnsafeCallCount, sizeof(fUnsafeCallCount)); - // Reset the source object to leave it in a safe state. - srcAsLNF.fCompiled = nullptr; - uprv_memset(srcAsLNF.fUnsafeCallCount, 0, sizeof(fUnsafeCallCount)); + // For the move operators, copy over the compiled formatter. + // Note: if the formatter is not compiled, call count information is lost. + if (static_cast(src).fCompiled != nullptr) { + lnfMoveHelper(static_cast(src)); + } } LocalizedNumberFormatter& LocalizedNumberFormatter::operator=(const LNF& other) { @@ -395,13 +393,31 @@ LocalizedNumberFormatter& LocalizedNumberFormatter::operator=(const LNF& other) LocalizedNumberFormatter& LocalizedNumberFormatter::operator=(LNF&& src) U_NOEXCEPT { NFS::operator=(static_cast&&>(src)); - // For the move operators, copy over the call count and compiled formatter. + // For the move operators, copy over the compiled formatter. + // Note: if the formatter is not compiled, call count information is lost. + if (static_cast(src).fCompiled != nullptr) { + // Formatter is compiled + lnfMoveHelper(static_cast(src)); + } else { + // Reset to default values. + auto* callCount = reinterpret_cast(fUnsafeCallCount); + umtx_storeRelease(*callCount, 0); + fCompiled = nullptr; + } + return *this; +} + +void LocalizedNumberFormatter::lnfMoveHelper(LNF&& src) { + // Copy over the compiled formatter and set call count to INT32_MIN as in computeCompiled(). + // Don't copy the call count directly because doing so requires a loadAcquire/storeRelease. + // The bits themselves appear to be platform-dependent, so copying them might not be safe. + auto* callCount = reinterpret_cast(fUnsafeCallCount); + umtx_storeRelease(*callCount, INT32_MIN); fCompiled = src.fCompiled; - uprv_memcpy(fUnsafeCallCount, src.fUnsafeCallCount, sizeof(fUnsafeCallCount)); // Reset the source object to leave it in a safe state. + auto* srcCallCount = reinterpret_cast(src.fUnsafeCallCount); + umtx_storeRelease(*srcCallCount, 0); src.fCompiled = nullptr; - uprv_memset(src.fUnsafeCallCount, 0, sizeof(fUnsafeCallCount)); - return *this; } diff --git a/icu4c/source/i18n/unicode/numberformatter.h b/icu4c/source/i18n/unicode/numberformatter.h index 9b3a1ed7296..d09ab365a87 100644 --- a/icu4c/source/i18n/unicode/numberformatter.h +++ b/icu4c/source/i18n/unicode/numberformatter.h @@ -2293,6 +2293,8 @@ class U_I18N_API LocalizedNumberFormatter LocalizedNumberFormatter(impl::MacroProps &¯os, const Locale &locale); + void lnfMoveHelper(LocalizedNumberFormatter&& src); + /** * @return true if the compiled formatter is available. */ -- 2.40.0