Skip to content

Commit

Permalink
馃敤 Hint to compiler that not_null is not null
Browse files Browse the repository at this point in the history
The `not_null` object prevents the possibility of the underlying pointer
being null. This is information that the C++ compiler can often leverage
for optimizations if it can determine such cases.

The code has been documented with C++ attributes for GCC and clang, and
using `__assume` for MSVC, to attempt to hint to the compiler that the
pointer contained in a `not_null` can never legally be null.
  • Loading branch information
bitwizeshift committed Dec 20, 2020
1 parent 75af5bd commit 95a3e83
Showing 1 changed file with 24 additions and 1 deletion.
25 changes: 24 additions & 1 deletion include/not_null.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,16 @@ inline namespace bitwizeshift {
static constexpr auto make(T&& p) -> not_null<typename std::decay<T>::type>;
};

/// \brief Hint to the compiler that the pointer \p p can never be null
///
/// \param p the pointer that can never be null
/// \return \p p
template <typename T>
#if defined(__GNUC__) || defined(__clang__)
[[gnu::returns_nonnull]]
#endif
constexpr auto mark_nonnull(T* p) noexcept -> T*;

template <typename T, typename U>
struct not_null_is_explicit_convertible : std::integral_constant<bool,(
std::is_constructible<T,U>::value &&
Expand Down Expand Up @@ -683,6 +693,19 @@ auto NOT_NULL_NS_IMPL::detail::throw_null_pointer_error()
#endif
}

template <typename T>
inline constexpr NOT_NULL_INLINE_VISIBILITY
auto NOT_NULL_NS_IMPL::detail::mark_nonnull(T* p) noexcept -> T*
{
#if defined(_MSC_VER)
// use Microsoft's builtin '__assume' to hint to the compiler that p
// cannot be null
return (__assume(p != nullptr), p);
#else
return p; // nullability is confirmed with gnu::returns_nonnull
#endif
}

template <typename T>
inline constexpr NOT_NULL_INLINE_VISIBILITY
auto NOT_NULL_NS_IMPL::detail::not_null_factory::make(T&& p)
Expand Down Expand Up @@ -775,7 +798,7 @@ inline constexpr NOT_NULL_INLINE_VISIBILITY
auto NOT_NULL_NS_IMPL::not_null<T>::get()
const noexcept -> pointer
{
return detail::not_null_to_address(m_pointer);
return detail::mark_nonnull(detail::not_null_to_address(m_pointer));
}

template <typename T>
Expand Down

0 comments on commit 95a3e83

Please sign in to comment.