https://gcc.gnu.org/g:eb2c12561c10f78e03b4eb63685f937a107305f0

commit r15-2304-geb2c12561c10f78e03b4eb63685f937a107305f0
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Mon Jul 22 20:24:19 2024 +0100

    libstdc++: Move std::optional assertions out of _M_get()
    
    Currently we implement the precondition for accessing the contained
    value of a std::optional in the _M_get() accessor in the base class.
    This means that we always check the assertions even in internal
    functions that have an explicit check for a contained value being
    present, such as value() and value_or(U&&). Although those redundant
    assertions should get optimized out in most cases, they might hurt
    inliner heuristics and generally give the compiler more work to do.
    And they won't be optimized out at all for non-optimized builds.
    
    The current assertions also result in repeated invalid bug reports, such
    as PR 91281, PR 101659, PR 102712, and PR 107894.
    
    We can move the assertions from the internal accessors to the public
    member functions where the preconditions are specified.
    
    Reviewed-by: Ville Voutilainen <ville.voutilai...@gmail.com>
    
    libstdc++-v3/ChangeLog:
    
            * include/std/optional (_Optional_base_impl::_M_get()): Move
            assertions to ...
            (optional::operator->, optional::operator*): ... here.

Diff:
---
 libstdc++-v3/include/std/optional | 40 +++++++++++++++++++++++++--------------
 1 file changed, 26 insertions(+), 14 deletions(-)

diff --git a/libstdc++-v3/include/std/optional 
b/libstdc++-v3/include/std/optional
index 48e0f3d36f29..af72004645e2 100644
--- a/libstdc++-v3/include/std/optional
+++ b/libstdc++-v3/include/std/optional
@@ -472,17 +472,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // The _M_get operations have _M_engaged as a precondition.
       constexpr _Tp&
       _M_get() noexcept
-      {
-       __glibcxx_assert(this->_M_is_engaged());
-       return static_cast<_Dp*>(this)->_M_payload._M_get();
-      }
+      { return static_cast<_Dp*>(this)->_M_payload._M_get(); }
 
       constexpr const _Tp&
       _M_get() const noexcept
-      {
-       __glibcxx_assert(this->_M_is_engaged());
-       return static_cast<const _Dp*>(this)->_M_payload._M_get();
-      }
+      { return static_cast<const _Dp*>(this)->_M_payload._M_get(); }
     };
 
   /**
@@ -958,27 +952,45 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // Observers.
       constexpr const _Tp*
       operator->() const noexcept
-      { return std::__addressof(this->_M_get()); }
+      {
+       __glibcxx_assert(this->_M_is_engaged());
+       return std::__addressof(this->_M_get());
+      }
 
       constexpr _Tp*
       operator->() noexcept
-      { return std::__addressof(this->_M_get()); }
+      {
+       __glibcxx_assert(this->_M_is_engaged());
+       return std::__addressof(this->_M_get());
+      }
 
       constexpr const _Tp&
       operator*() const& noexcept
-      { return this->_M_get(); }
+      {
+       __glibcxx_assert(this->_M_is_engaged());
+       return this->_M_get();
+      }
 
       constexpr _Tp&
       operator*()& noexcept
-      { return this->_M_get(); }
+      {
+       __glibcxx_assert(this->_M_is_engaged());
+       return this->_M_get();
+      }
 
       constexpr _Tp&&
       operator*()&& noexcept
-      { return std::move(this->_M_get()); }
+      {
+       __glibcxx_assert(this->_M_is_engaged());
+       return std::move(this->_M_get());
+      }
 
       constexpr const _Tp&&
       operator*() const&& noexcept
-      { return std::move(this->_M_get()); }
+      {
+       __glibcxx_assert(this->_M_is_engaged());
+       return std::move(this->_M_get());
+      }
 
       constexpr explicit operator bool() const noexcept
       { return this->_M_is_engaged(); }

Reply via email to