LCOV - code coverage report
Current view: top level - src/util - not_null.h (source / functions) Coverage Total Hit
Test: test_bitcoin_coverage.info Lines: 100.0 % 29 29
Test Date: 2026-10-11 07:59:32 Functions: 90.0 % 20 18
Branches: 46.5 % 316 147

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) The Bitcoin Core developers
       2                 :             : // Distributed under the MIT software license, see the accompanying
       3                 :             : // file COPYING or https://opensource.org/license/mit/.
       4                 :             : 
       5                 :             : #ifndef BITCOIN_UTIL_NOT_NULL_H
       6                 :             : #define BITCOIN_UTIL_NOT_NULL_H
       7                 :             : 
       8                 :             : #include <attributes.h>
       9                 :             : #include <util/check.h>
      10                 :             : 
      11                 :             : #include <compare>
      12                 :             : #include <concepts>
      13                 :             : #include <cstddef>
      14                 :             : #include <functional>
      15                 :             : #include <memory>
      16                 :             : #include <type_traits>
      17                 :             : #include <utility>
      18                 :             : 
      19                 :             : namespace util {
      20                 :             : 
      21                 :             : /// NotNull is intended to be used to denote that a smart pointer type can not
      22                 :             : /// hold a nullptr value.
      23                 :             : ///
      24                 :             : /// The type is more useful, the earlier in the lifetime of a pointer it is
      25                 :             : /// used. So instead of passing an existing pointer into NotNull, it is
      26                 :             : /// recommended to use the type when creating the smart pointer. E.g.:
      27                 :             : ///
      28                 :             : /// util::NotNull p{std::make_shared<Thing>()};
      29                 :             : ///
      30                 :             : /// This makes it obvious that a pointer really is not null and that the
      31                 :             : /// constructor will not fail.
      32                 :             : ///
      33                 :             : /// NotNull does *not* support raw pointers.
      34                 :             : /// The C++ language provides raw references for this use case, and the C++
      35                 :             : /// standard library provides std::reference_wrapper, where raw references can
      36                 :             : /// not be used.
      37                 :             : ///
      38                 :             : /// This type is movable, meaning that the inner pointer *is* null after a
      39                 :             : /// move. Clang-tidy static analysis is used to enforce use-after-move
      40                 :             : /// violations, so that the null should never be observed. Moreover, the
      41                 :             : /// runtime Assume check in the get() member function will ensure the same.
      42                 :             : template <class T>
      43                 :             :     requires std::is_class_v<T> && requires(T t) { { t != nullptr } -> std::convertible_to<bool>; }
      44   [ +  -  #  # ]:       20654 : class NotNull
           [ +  -  +  - ]
           [ -  +  +  -  
          -  -  -  +  +  
          -  -  -  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
           - ][ +  -  +  
          -  +  -  -  -  
          +  -  -  +  +  
          -  -  +  +  -  
          +  -  +  -  -  
          -  -  -  -  -  
           #  # ][ +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  #  #  #  
           # ][ -  +  -  
             +  -  +  +  
                      + ]
      45                 :             : {
      46                 :             : public:
      47                 :             :     template <std::convertible_to<T> U>
      48                 :             :         requires(!std::same_as<std::remove_cvref_t<U>, NotNull>)
      49                 :       19938 :     constexpr explicit NotNull(U&& u) noexcept(std::is_nothrow_constructible_v<T, U&&>)
      50         [ +  + ]:       19938 :         : m_ptr(std::forward<U>(u))
      51                 :             :     {
      52         [ +  + ]:       19938 :         Assert(m_ptr != nullptr);
      53         [ -  + ]:       19938 :     }
      54                 :             : 
      55                 :             :     template <class U>
      56                 :             :         requires std::move_constructible<U> && std::constructible_from<T, U&&>
      57                 :             :     constexpr explicit(!std::convertible_to<U, T>)
      58                 :          45 :         NotNull(NotNull<U>&& other) noexcept(std::is_nothrow_move_constructible_v<U> && std::is_nothrow_constructible_v<T, U&&>)
      59                 :          45 :         : m_ptr(std::move(other).get())
      60                 :             :     {
      61                 :          45 :         Assume(m_ptr != nullptr);
      62                 :          45 :     }
      63                 :             : 
      64                 :             :     template <class U>
      65                 :             :         requires std::convertible_to<const U&, T>
      66                 :           1 :     constexpr NotNull(const NotNull<U>& other) noexcept(std::is_nothrow_constructible_v<T, const U&>)
      67                 :           2 :         : m_ptr(other.get())
      68                 :             :     {
      69                 :           1 :         Assume(m_ptr != nullptr);
      70                 :           1 :     }
      71                 :             : 
      72                 :             :     NotNull(std::nullptr_t) = delete;
      73                 :             :     NotNull& operator=(std::nullptr_t) = delete;
      74                 :             : 
      75   [ +  -  +  - ]:         458 :     constexpr NotNull(NotNull&&) = default;
      76         [ -  + ]:           3 :     constexpr NotNull& operator=(NotNull&&) = default;
      77   [ +  -  +  - ]:           4 :     constexpr NotNull(const NotNull&) = default;
      78                 :             :     constexpr NotNull& operator=(const NotNull&) = default;
      79                 :             : 
      80   [ +  -  +  - ]:     5892748 :     constexpr const T& get() const& noexcept LIFETIMEBOUND { return Assume(m_ptr); }
      81                 :         180 :     constexpr T get() && noexcept(std::is_nothrow_move_constructible_v<T>)
      82                 :             :         requires std::move_constructible<T>
      83                 :             :     {
      84                 :         178 :         return std::move(Assume(m_ptr));
      85                 :             :     }
      86                 :             : 
      87   [ +  -  +  -  :       67470 :     constexpr decltype(auto) operator->() const LIFETIMEBOUND { return get(); }
          +  -  #  #  #  
           # ][ +  -  +  
          -  +  -  +  -  
           +  - ][ +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
           [ +  -  #  # ]
           [ +  -  +  - ]
      88   [ +  -  +  -  :     5821491 :     constexpr decltype(auto) operator*() const LIFETIMEBOUND { return *get(); }
          +  -  +  -  +  
           -  +  - ][ +  
          -  +  -  +  -  
          +  -  +  -  #  
           # ][ +  -  +  
          -  +  -  -  +  
          +  +  +  -  +  
          +  +  -  +  -  
          +  +  +  -  -  
          +  -  +  -  +  
                   +  - ]
      89                 :             : 
      90                 :             :     constexpr operator T() const& noexcept(std::is_nothrow_copy_constructible_v<T>)
      91                 :             :         requires std::copy_constructible<T>
      92                 :             :     {
      93                 :             :         return get();
      94                 :             :     }
      95                 :         134 :     constexpr operator T() && noexcept(std::is_nothrow_move_constructible_v<T>)
      96                 :             :         requires std::move_constructible<T>
      97                 :             :     {
      98                 :         134 :         return std::move(*this).get();
      99                 :             :     }
     100                 :             : 
     101                 :             :     template <class U>
     102                 :           4 :     constexpr auto operator<=>(const NotNull<U>& other) const
     103                 :             :     {
     104                 :           4 :         return std::compare_three_way{}(get(), other.get());
     105                 :             :     }
     106                 :             :     template <class U>
     107                 :           2 :     constexpr bool operator==(const NotNull<U>& other) const
     108                 :             :     {
     109                 :           2 :         return get() == other.get();
     110                 :             :     }
     111                 :             : 
     112                 :             : private:
     113                 :             :     T m_ptr;
     114                 :             : };
     115                 :             : 
     116                 :             : template <class T>
     117                 :             : NotNull(T) -> NotNull<T>;
     118                 :             : 
     119                 :             : template <typename T, typename Deleter = std::default_delete<T>>
     120                 :             : using NotNullUniquePtr = NotNull<std::unique_ptr<T, Deleter>>;
     121                 :             : 
     122                 :             : template <typename T>
     123                 :             : using NotNullSharedPtr = NotNull<std::shared_ptr<T>>;
     124                 :             : 
     125                 :             : } // namespace util
     126                 :             : 
     127                 :             : template <class T>
     128                 :             : struct std::hash<util::NotNull<T>> {
     129   [ -  -  -  -  :           4 :     std::size_t operator()(const util::NotNull<T>& v) const noexcept
                   +  + ]
     130                 :             :     {
     131   [ -  -  -  -  :           4 :         return std::hash<T>{}(v.get());
                   +  + ]
     132                 :             :     }
     133                 :             : };
     134                 :             : 
     135                 :             : #endif // BITCOIN_UTIL_NOT_NULL_H
        

Generated by: LCOV version 2.0-1