From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id C0E0E385558E for ; Thu, 11 May 2023 20:21:28 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C0E0E385558E Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1683836488; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=WAEKpf9fSK2ZSRagPFZJfHTtl+624WOU4r8NjlF1XLo=; b=ZfPAiTq5+KFTKVoB1riErNHtBeI8LZkB3/WEDZFEob1CoUb9dNy2uq6AKTYMfF8uGBM2BQ ug56spz0akU/51NwwdXDCF3Y3UA8siQcS0KCzTk7Y4tyQY6gNGnmC+XL2ISq7TqMcwUKg/ YvFT2DirkDTRzyoxNU0OaWXHdWC9nh4= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-639-xZHYXlATOdat4Omvtn4s6Q-1; Thu, 11 May 2023 16:21:26 -0400 X-MC-Unique: xZHYXlATOdat4Omvtn4s6Q-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 7B7E38533DC; Thu, 11 May 2023 20:21:26 +0000 (UTC) Received: from localhost (unknown [10.42.28.178]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4730E40C2076; Thu, 11 May 2023 20:21:26 +0000 (UTC) From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Cc: Patrick Palka Subject: [committed] libstdc++: Use RAII types in strtod-based std::from_chars implementation Date: Thu, 11 May 2023 21:21:25 +0100 Message-Id: <20230511202125.1059353-1-jwakely@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-11.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_NONE,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Tested powerpc64le-linux. Pushed to trunk. Patrick noted that auto_ferounding could be used in floating_to_chars.cc too, which I'll do later. -- >8 -- This adds auto_locale and auto_ferounding types to use RAII for changing and restoring the local and floating-point environment when using strtod to implement std::from_chars. The destructors for the RAII objects run slightly later than the previous statements that restored the locale/fenv, but the differences are just some trivial assignments and an isinf call. Reviewed-by: Patrick Palka libstdc++-v3/ChangeLog: * src/c++17/floating_from_chars.cc [USE_STRTOD_FOR_FROM_CHARS] (auto_locale, auto_ferounding): New class types. (from_chars_impl): Use auto_locale and auto_ferounding. --- libstdc++-v3/src/c++17/floating_from_chars.cc | 88 +++++++++++++++---- 1 file changed, 69 insertions(+), 19 deletions(-) diff --git a/libstdc++-v3/src/c++17/floating_from_chars.cc b/libstdc++-v3/src/c++17/floating_from_chars.cc index 78b9d92cdc0..ebd428d5be3 100644 --- a/libstdc++-v3/src/c++17/floating_from_chars.cc +++ b/libstdc++-v3/src/c++17/floating_from_chars.cc @@ -597,6 +597,69 @@ namespace return buf.c_str(); } + // RAII type to change and restore the locale. + struct auto_locale + { +#if _GLIBCXX_HAVE_USELOCALE + // When we have uselocale we can change the current thread's locale. + const locale_t loc; + locale_t orig; + + auto_locale() + : loc(::newlocale(LC_ALL_MASK, "C", (locale_t)0)) + { + if (loc) + orig = ::uselocale(loc); + else + ec = errc{errno}; + } + + ~auto_locale() + { + if (loc) + { + ::uselocale(orig); + ::freelocale(loc); + } + } +#else + // Otherwise, we can't change the locale and so strtod can't be used. + auto_locale() = delete; +#endif + + explicit operator bool() const noexcept { return ec == errc{}; } + + errc ec{}; + + auto_locale(const auto_locale&) = delete; + auto_locale& operator=(const auto_locale&) = delete; + }; + + // RAII type to change and restore the floating-point environment. + struct auto_ferounding + { +#if _GLIBCXX_USE_C99_FENV_TR1 && defined(FE_TONEAREST) + const int rounding = std::fegetround(); + + auto_ferounding() + { + if (rounding != FE_TONEAREST) + std::fesetround(FE_TONEAREST); + } + + ~auto_ferounding() + { + if (rounding != FE_TONEAREST) + std::fesetround(rounding); + } +#else + auto_ferounding() = default; +#endif + + auto_ferounding(const auto_ferounding&) = delete; + auto_ferounding& operator=(const auto_ferounding&) = delete; + }; + // Convert the NTBS `str` to a floating-point value of type `T`. // If `str` cannot be converted, `value` is unchanged and `0` is returned. // Otherwise, let N be the number of characters consumed from `str`. @@ -607,16 +670,11 @@ namespace ptrdiff_t from_chars_impl(const char* str, T& value, errc& ec) noexcept { - if (locale_t loc = ::newlocale(LC_ALL_MASK, "C", (locale_t)0)) [[likely]] + auto_locale loc; + + if (loc) { - locale_t orig = ::uselocale(loc); - -#if _GLIBCXX_USE_C99_FENV_TR1 && defined(FE_TONEAREST) - const int rounding = std::fegetround(); - if (rounding != FE_TONEAREST) - std::fesetround(FE_TONEAREST); -#endif - + auto_ferounding rounding; const int save_errno = errno; errno = 0; char* endptr; @@ -647,14 +705,6 @@ namespace #endif const int conv_errno = std::__exchange(errno, save_errno); -#if _GLIBCXX_USE_C99_FENV_TR1 && defined(FE_TONEAREST) - if (rounding != FE_TONEAREST) - std::fesetround(rounding); -#endif - - ::uselocale(orig); - ::freelocale(loc); - const ptrdiff_t n = endptr - str; if (conv_errno == ERANGE) [[unlikely]] { @@ -675,8 +725,8 @@ namespace } return n; } - else if (errno == ENOMEM) - ec = errc::not_enough_memory; + else + ec = loc.ec; return 0; } -- 2.40.1