diff --git a/libcxx/.clang-format b/libcxx/.clang-format
--- a/libcxx/.clang-format
+++ b/libcxx/.clang-format
@@ -39,6 +39,7 @@
                   '_LIBCPP_INLINE_VISIBILITY',
                   '_LIBCPP_CONSTEVAL',
                   '_LIBCPP_NOALIAS',
+                  '_LIBCPP_NO_SANITIZE',
                   '_LIBCPP_USING_IF_EXISTS',
                   '_LIBCPP_DEPRECATED',
                   '_LIBCPP_DEPRECATED_IN_CXX11',
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -712,6 +712,7 @@
   __utility/forward.h
   __utility/forward_like.h
   __utility/in_place.h
+  __utility/is_pointer_in_range.h
   __utility/integer_sequence.h
   __utility/move.h
   __utility/pair.h
diff --git a/libcxx/include/__config b/libcxx/include/__config
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -1089,6 +1089,12 @@
 #    define _LIBCPP_PREFERRED_NAME(x)
 #  endif
 
+#  if __has_attribute(__no_sanitize__)
+#    define _LIBCPP_NO_SANITIZE(...) __attribute__((__no_sanitize__(__VA_ARGS__)))
+#  else
+#    define _LIBCPP_NO_SANITIZE(...)
+#  endif
+
 // We often repeat things just for handling wide characters in the library.
 // When wide characters are disabled, it can be useful to have a quick way of
 // disabling it without having to resort to #if-#endif, which has a larger
diff --git a/libcxx/include/__utility/is_pointer_in_range.h b/libcxx/include/__utility/is_pointer_in_range.h
new file mode 100644
--- /dev/null
+++ b/libcxx/include/__utility/is_pointer_in_range.h
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___UTILITY_IS_POINTER_IN_RANGE_H
+#define _LIBCPP___UTILITY_IS_POINTER_IN_RANGE_H
+
+#include <__assert>
+#include <__config>
+#include <__type_traits/enable_if.h>
+#include <__type_traits/integral_constant.h>
+#include <__type_traits/is_constant_evaluated.h>
+#include <__type_traits/void_t.h>
+#include <__utility/declval.h>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <class _Tp, class _Up, class = void>
+struct __is_less_than_comparable : false_type {};
+
+template <class _Tp, class _Up>
+struct __is_less_than_comparable<_Tp, _Up, __void_t<decltype(std::declval<_Tp>() < std::declval<_Up>())> > : true_type {
+};
+
+template <class _Tp, class _Up, __enable_if_t<__is_less_than_comparable<const _Tp*, const _Up*>::value, int> = 0>
+_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_SANITIZE("address") bool __is_pointer_in_range(
+    const _Tp* __begin, const _Tp* __end, const _Up* __ptr) {
+  if (__libcpp_is_constant_evaluated()) {
+    _LIBCPP_ASSERT(__builtin_constant_p(__begin < __end), "__begin and __end do not form a range");
+
+    // If this is not a constant during constant evaluation we know that __ptr is not part of the allocation where
+    // [__begin, __end) is.
+    if (!__builtin_constant_p(__begin <= __ptr && __ptr < __end))
+      return false;
+  }
+
+  return __begin <= __ptr && __ptr < __end;
+}
+
+template <class _Tp, class _Up, __enable_if_t<!__is_less_than_comparable<const _Tp*, const _Up*>::value, int> = 0>
+_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_SANITIZE("address") bool __is_pointer_in_range(
+    const _Tp* __begin, const _Tp* __end, const _Up* __ptr) {
+  if (__libcpp_is_constant_evaluated())
+    return false;
+
+  auto __t_ptr = reinterpret_cast<const _Tp*>(__ptr);
+  return __begin <= __t_ptr && __t_ptr < __end;
+}
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___UTILITY_IS_POINTER_IN_RANGE_H
diff --git a/libcxx/include/string b/libcxx/include/string
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -563,6 +563,7 @@
 #include <__type_traits/is_allocator.h>
 #include <__type_traits/noexcept_move_assign_container.h>
 #include <__utility/auto_cast.h>
+#include <__utility/is_pointer_in_range.h>
 #include <__utility/move.h>
 #include <__utility/swap.h>
 #include <__utility/unreachable.h>
@@ -1969,14 +1970,9 @@
 
     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __invalidate_iterators_past(size_type);
 
-    template<class _Tp>
-    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
-    bool __addr_in_range(_Tp&& __t) const {
-        // assume that the ranges overlap, because we can't check during constant evaluation
-        if (__libcpp_is_constant_evaluated())
-          return true;
-        const volatile void *__p = std::addressof(__t);
-        return data() <= __p && __p <= data() + size();
+    template <class _Tp>
+    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __addr_in_range(_Tp&& __v) const {
+      return std::__is_pointer_in_range(data(), data() + size(), std::addressof(__v));
     }
 
     _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI
@@ -3064,10 +3060,6 @@
     size_type __cap = capacity();
     if (__cap - __sz + __n1 >= __n2)
     {
-        if (__libcpp_is_constant_evaluated()) {
-            __grow_by_and_replace(__cap, 0, __sz, __pos, __n1, __n2, __s);
-            return *this;
-        }
         value_type* __p = std::__to_address(__get_pointer());
         if (__n1 != __n2)
         {
@@ -3080,7 +3072,7 @@
                     traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move);
                     return __null_terminate_at(__p, __sz + (__n2 - __n1));
                 }
-                if (__p + __pos < __s && __s < __p + __sz)
+                if (std::__is_pointer_in_range(__p + __pos + 1, __p + __sz, __s))
                 {
                     if (__p + __pos + __n1 <= __s)
                         __s += __n2 - __n1;
diff --git a/libcxx/test/libcxx/utilities/is_pointer_in_range.pass.cpp b/libcxx/test/libcxx/utilities/is_pointer_in_range.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/is_pointer_in_range.pass.cpp
@@ -0,0 +1,44 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <__utility/is_pointer_in_range.h>
+#include <cassert>
+
+#include "test_macros.h"
+
+TEST_CONSTEXPR_CXX14 bool test() {
+  int i;
+  int j;
+  assert(!std::__is_pointer_in_range(&i, &i, &i));
+  assert(std::__is_pointer_in_range(&i, &i + 1, &i));
+  assert(!std::__is_pointer_in_range(&i, &i + 1, &j));
+
+#if TEST_STD_VER >= 20
+  int* arr1 = new int[]{1, 2, 3, 4};
+  int* arr2 = new int[]{5, 6, 7, 8};
+
+  assert(!std::__is_pointer_in_range(arr1, arr1 + 4, arr2));
+  assert(std::__is_pointer_in_range(arr1, arr1 + 4, arr1 + 3));
+  assert(!std::__is_pointer_in_range(arr1, arr1, arr1 + 3));
+
+  delete[] arr1;
+  delete[] arr2;
+
+#endif
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+#if TEST_STD_VER >= 14
+  static_assert(test());
+#endif
+
+  return 0;
+}