瀏覽代碼

chore(pretty-print): rewrite pretty printers

 support compressed pairs
greatbridf 7 月之前
父節點
當前提交
eedcf95ee9
共有 3 個文件被更改,包括 500 次插入439 次删除
  1. 11 0
      .gdbinit
  2. 380 391
      gblibstdc++/include/memory
  3. 109 48
      pretty-print.py

+ 11 - 0
.gdbinit

@@ -0,0 +1,11 @@
+source pretty-print.py
+set pagination off
+set print pretty on
+set output-radix 16
+
+symbol-file build/kernel.out
+target remote:1234
+
+# layout src
+b process.cpp:271
+c

+ 380 - 391
gblibstdc++/include/memory

@@ -10,8 +10,7 @@
 namespace std {
 
 template <typename T>
-constexpr T* addressof(T& arg) noexcept
-{
+constexpr T* addressof(T& arg) noexcept {
     return __builtin_addressof(arg);
 }
 
@@ -38,79 +37,87 @@ const T* addressof(const T&&) = delete;
 
 namespace __helpers {
 
-template <typename Ptr, typename = void>
-struct pointer_difference_type
-{ using type = std::ptrdiff_t; };
+    template <typename Ptr, typename = void>
+    struct pointer_difference_type {
+        using type = std::ptrdiff_t;
+    };
 
-template <typename Ptr>
-struct pointer_difference_type<Ptr,
-    std::void_t<typename Ptr::difference_type>>
-{ using type = typename Ptr::difference_type; };
+    template <typename Ptr>
+    struct pointer_difference_type<Ptr,
+                                   std::void_t<typename Ptr::difference_type>> {
+        using type = typename Ptr::difference_type;
+    };
 
-template <typename Ptr>
-using pointer_difference_type_t =
-    typename pointer_difference_type<Ptr>::type;
+    template <typename Ptr>
+    using pointer_difference_type_t =
+        typename pointer_difference_type<Ptr>::type;
 
-template <typename Base, typename T>
-struct rebind;
+    template <typename Base, typename T>
+    struct rebind;
 
-template <template <typename, typename...> typename Template,
-    typename NewType, typename OldType, typename... Args>
-struct rebind<Template<OldType, Args...>, NewType> {
-    using type = Template<NewType, Args...>;
-};
+    template <template <typename, typename...> typename Template,
+              typename NewType, typename OldType, typename... Args>
+    struct rebind<Template<OldType, Args...>, NewType> {
+        using type = Template<NewType, Args...>;
+    };
 
-template <typename Ptr, typename T, typename = void>
-struct try_rebind { using type = typename rebind<Ptr, T>::type; };
+    template <typename Ptr, typename T, typename = void>
+    struct try_rebind {
+        using type = typename rebind<Ptr, T>::type;
+    };
 
-template <typename Ptr, typename T>
-struct try_rebind<Ptr, T,
-    std::void_t<typename Ptr::template rebind<T>>> {
-    using type = typename Ptr::template rebind<T>;
-};
+    template <typename Ptr, typename T>
+    struct try_rebind<Ptr, T, std::void_t<typename Ptr::template rebind<T>>> {
+        using type = typename Ptr::template rebind<T>;
+    };
 
-template <typename Ptr, typename = void>
-struct pointer_element {};
+    template <typename Ptr, typename = void>
+    struct pointer_element {};
 
-template <typename Ptr>
-struct pointer_element<Ptr, std::enable_if_t<
-    std::is_same_v<void, std::void_t<typename Ptr::element_type>>
->> { using type = typename Ptr::element_type; };
+    template <typename Ptr>
+    struct pointer_element<
+        Ptr, std::enable_if_t<std::is_same_v<
+                 void, std::void_t<typename Ptr::element_type>>>> {
+        using type = typename Ptr::element_type;
+    };
 
-template <template <typename, typename...> typename Template,
-    typename T, typename... Args>
-struct pointer_element<Template<T, Args...>, void>
-{ using type = T; };
+    template <template <typename, typename...> typename Template, typename T,
+              typename... Args>
+    struct pointer_element<Template<T, Args...>, void> {
+        using type = T;
+    };
 
-template <typename Ptr, typename = void>
-struct pointer_traits_impl {};
+    template <typename Ptr, typename = void>
+    struct pointer_traits_impl {};
 
-template <typename Ptr>
-struct pointer_traits_impl<Ptr,
-    std::void_t<typename pointer_element<Ptr>::type>> {
-    using pointer = Ptr;
-    using element_type = typename pointer_element<Ptr>::type;
-    using difference_type = pointer_difference_type_t<Ptr>;
+    template <typename Ptr>
+    struct pointer_traits_impl<
+        Ptr, std::void_t<typename pointer_element<Ptr>::type>> {
+        using pointer = Ptr;
+        using element_type = typename pointer_element<Ptr>::type;
+        using difference_type = pointer_difference_type_t<Ptr>;
 
-    template <typename U>
-    using rebind = typename try_rebind<Ptr, U>::type;
+        template <typename U>
+        using rebind = typename try_rebind<Ptr, U>::type;
 
-    static pointer pointer_to(element_type& ref)
-    { return Ptr::pointer_to(ref); }
-};
+        static pointer pointer_to(element_type& ref) {
+            return Ptr::pointer_to(ref);
+        }
+    };
 
-template <typename T>
-struct pointer_traits_impl<T*, void> {
-    using pointer = T*;
-    using element_type = T;
-    using difference_type = std::ptrdiff_t;
+    template <typename T>
+    struct pointer_traits_impl<T*, void> {
+        using pointer = T*;
+        using element_type = T;
+        using difference_type = std::ptrdiff_t;
 
-    template <typename U>
-    using rebind = U*;
+        template <typename U>
+        using rebind = U*;
 
-    static pointer pointer_to(element_type& ref)
-    { return std::addressof(ref); }
-};
+        static pointer pointer_to(element_type& ref) {
+            return std::addressof(ref);
+        }
+    };
 
 } // namespace __helpers
 
@@ -119,160 +126,170 @@ struct pointer_traits : public __helpers::pointer_traits_impl<Ptr> {};
 
 namespace __helpers {
 
-template <typename Alloc, typename = void>
-struct allocator_pointer
-{ using type = typename Alloc::value_type*; };
+    template <typename Alloc, typename = void>
+    struct allocator_pointer {
+        using type = typename Alloc::value_type*;
+    };
 
-template <typename Alloc>
-struct allocator_pointer<Alloc,
-    std::void_t<typename Alloc::pointer>>
-{ using type = typename Alloc::pointer; };
+    template <typename Alloc>
+    struct allocator_pointer<Alloc, std::void_t<typename Alloc::pointer>> {
+        using type = typename Alloc::pointer;
+    };
 
-template <typename Alloc>
-using allocator_pointer_t =
-    typename allocator_pointer<Alloc>::type;
+    template <typename Alloc>
+    using allocator_pointer_t = typename allocator_pointer<Alloc>::type;
 
+    template <typename Alloc, typename Pointer, typename = void>
+    struct allocator_const_pointer {
+        using type = typename std::pointer_traits<Pointer>::template rebind<
+            const typename Alloc::value_type>;
+    };
 
-template <typename Alloc, typename Pointer, typename = void>
-struct allocator_const_pointer {
-    using type = typename std::pointer_traits<Pointer>::template
-        rebind<const typename Alloc::value_type>;
-};
+    template <typename Alloc, typename Pointer>
+    struct allocator_const_pointer<Alloc, Pointer,
+                                   std::void_t<typename Alloc::const_pointer>> {
+        using type = typename Alloc::const_pointer;
+    };
 
-template <typename Alloc, typename Pointer>
-struct allocator_const_pointer<Alloc, Pointer,
-    std::void_t<typename Alloc::const_pointer>>
-{ using type = typename Alloc::const_pointer; };
+    template <typename Alloc, typename Pointer>
+    using allocator_const_pointer_t =
+        typename allocator_const_pointer<Alloc, Pointer>::type;
 
-template <typename Alloc, typename Pointer>
-using allocator_const_pointer_t =
-    typename allocator_const_pointer<Alloc, Pointer>::type;
+    template <typename Alloc, typename Pointer, typename = void>
+    struct allocator_void_pointer {
+        using type =
+            typename std::pointer_traits<Pointer>::template rebind<void>;
+    };
 
+    template <typename Alloc, typename Pointer>
+    struct allocator_void_pointer<Alloc, Pointer,
+                                  std::void_t<typename Alloc::void_pointer>> {
+        using type = typename Alloc::void_pointer;
+    };
 
-template <typename Alloc, typename Pointer, typename = void>
-struct allocator_void_pointer {
-    using type = typename std::pointer_traits<Pointer>::template
-        rebind<void>;
-};
+    template <typename Alloc, typename Pointer>
+    using allocator_void_pointer_t =
+        typename allocator_void_pointer<Alloc, Pointer>::type;
 
-template <typename Alloc, typename Pointer>
-struct allocator_void_pointer<Alloc, Pointer,
-    std::void_t<typename Alloc::void_pointer>>
-{ using type = typename Alloc::void_pointer; };
+    template <typename Alloc, typename Pointer, typename = void>
+    struct allocator_const_void_pointer {
+        using type =
+            typename std::pointer_traits<Pointer>::template rebind<const void>;
+    };
 
-template <typename Alloc, typename Pointer>
-using allocator_void_pointer_t =
-    typename allocator_void_pointer<Alloc, Pointer>::type;
+    template <typename Alloc, typename Pointer>
+    struct allocator_const_void_pointer<
+        Alloc, Pointer, std::void_t<typename Alloc::const_void_pointer>> {
+        using type = typename Alloc::const_void_pointer;
+    };
 
+    template <typename Alloc, typename Pointer>
+    using allocator_const_void_pointer_t =
+        typename allocator_const_void_pointer<Alloc, Pointer>::type;
 
-template <typename Alloc, typename Pointer, typename = void>
-struct allocator_const_void_pointer {
-    using type = typename std::pointer_traits<Pointer>::template
-        rebind<const void>;
-};
+    template <typename Alloc, typename = void>
+    struct allocator_difference_type {
+        using type = std::ptrdiff_t;
+    };
+    template <typename Alloc>
+    struct allocator_difference_type<
+        Alloc, std::void_t<typename Alloc::difference_type>> {
+        using type = typename Alloc::difference_type;
+    };
+    template <typename Alloc>
+    using allocator_difference_type_t =
+        typename allocator_difference_type<Alloc>::type;
 
-template <typename Alloc, typename Pointer>
-struct allocator_const_void_pointer<Alloc, Pointer,
-    std::void_t<typename Alloc::const_void_pointer>>
-{ using type = typename Alloc::const_void_pointer; };
-
-template <typename Alloc, typename Pointer>
-using allocator_const_void_pointer_t =
-    typename allocator_const_void_pointer<Alloc, Pointer>::type;
-
-
-template <typename Alloc, typename = void>
-struct allocator_difference_type
-{ using type = std::ptrdiff_t; };
-template <typename Alloc>
-struct allocator_difference_type<Alloc,
-    std::void_t<typename Alloc::difference_type>>
-{ using type = typename Alloc::difference_type; };
-template <typename Alloc>
-using allocator_difference_type_t =
-    typename allocator_difference_type<Alloc>::type;
-
-template <typename Alloc, typename = void>
-struct allocator_size_type
-{ using type = std::size_t; };
-template <typename Alloc>
-struct allocator_size_type<Alloc,
-    std::void_t<typename Alloc::size_type>>
-{ using type = typename Alloc::size_type; };
-template <typename Alloc>
-using allocator_size_type_t =
-    typename allocator_size_type<Alloc>::type;
-
-template <typename Alloc, typename = void>
-struct allocator_prop_copy
-{ using type = std::false_type; };
-template <typename Alloc>
-struct allocator_prop_copy<Alloc,
-    std::void_t<typename Alloc::propagate_on_container_copy_assignment>>
-{ using type = typename Alloc::propagate_on_container_copy_assignment; };
-template <typename Alloc>
-using allocator_prop_copy_t =
-    typename allocator_prop_copy<Alloc>::type;
-
-template <typename Alloc, typename = void>
-struct allocator_prop_move
-{ using type = std::false_type; };
-template <typename Alloc>
-struct allocator_prop_move<Alloc,
-    std::void_t<typename Alloc::propagate_on_container_move_assignment>>
-{ using type = typename Alloc::propagate_on_container_move_assignment; };
-template <typename Alloc>
-using allocator_prop_move_t =
-    typename allocator_prop_move<Alloc>::type;
-
-template <typename Alloc, typename = void>
-struct allocator_prop_swap
-{ using type = std::false_type; };
-template <typename Alloc>
-struct allocator_prop_swap<Alloc,
-    std::void_t<typename Alloc::propagate_on_container_swap>>
-{ using type = typename Alloc::propagate_on_container_swap; };
-template <typename Alloc>
-using allocator_prop_swap_t =
-    typename allocator_prop_swap<Alloc>::type;
-
-template <typename Alloc, typename = void>
-struct is_always_equal
-{ using type = std::false_type; };
-template <typename Alloc>
-struct is_always_equal<Alloc,
-    std::void_t<typename Alloc::is_always_equal>>
-{ using type = typename Alloc::is_always_equal; };
-template <typename Alloc>
-using is_always_equal_t =
-    typename is_always_equal<Alloc>::type;
-
-template <typename Alloc, typename = void>
-struct allocator_select_on_copy {
-    static constexpr Alloc get(const Alloc& alloc)
-    { return alloc; }
-};
+    template <typename Alloc, typename = void>
+    struct allocator_size_type {
+        using type = std::size_t;
+    };
+    template <typename Alloc>
+    struct allocator_size_type<Alloc, std::void_t<typename Alloc::size_type>> {
+        using type = typename Alloc::size_type;
+    };
+    template <typename Alloc>
+    using allocator_size_type_t = typename allocator_size_type<Alloc>::type;
 
-template <typename Alloc>
-struct allocator_select_on_copy<Alloc, std::enable_if_t<
-    std::is_same_v<void, std::void_t<decltype(
-        std::declval<Alloc>().select_on_container_copy_construction()
-    )>> >> {
-    static constexpr Alloc get(const Alloc& alloc)
-    { return alloc.select_on_container_copy_construction(); }
-};
+    template <typename Alloc, typename = void>
+    struct allocator_prop_copy {
+        using type = std::false_type;
+    };
+    template <typename Alloc>
+    struct allocator_prop_copy<
+        Alloc,
+        std::void_t<typename Alloc::propagate_on_container_copy_assignment>> {
+        using type = typename Alloc::propagate_on_container_copy_assignment;
+    };
+    template <typename Alloc>
+    using allocator_prop_copy_t = typename allocator_prop_copy<Alloc>::type;
 
-template <typename Allocator, typename T, typename = void>
-struct allocator_rebind_type {
-    using type = typename rebind<Allocator, T>::type;
-};
+    template <typename Alloc, typename = void>
+    struct allocator_prop_move {
+        using type = std::false_type;
+    };
+    template <typename Alloc>
+    struct allocator_prop_move<
+        Alloc,
+        std::void_t<typename Alloc::propagate_on_container_move_assignment>> {
+        using type = typename Alloc::propagate_on_container_move_assignment;
+    };
+    template <typename Alloc>
+    using allocator_prop_move_t = typename allocator_prop_move<Alloc>::type;
 
-template <typename Allocator, typename T>
-struct allocator_rebind_type<Allocator, T, std::void_t<
-    typename Allocator::template rebind<T>::other
->> {
-    using type = typename Allocator::template rebind<T>::other;
-};
+    template <typename Alloc, typename = void>
+    struct allocator_prop_swap {
+        using type = std::false_type;
+    };
+    template <typename Alloc>
+    struct allocator_prop_swap<
+        Alloc, std::void_t<typename Alloc::propagate_on_container_swap>> {
+        using type = typename Alloc::propagate_on_container_swap;
+    };
+    template <typename Alloc>
+    using allocator_prop_swap_t = typename allocator_prop_swap<Alloc>::type;
+
+    template <typename Alloc, typename = void>
+    struct is_always_equal {
+        using type = std::false_type;
+    };
+    template <typename Alloc>
+    struct is_always_equal<Alloc,
+                           std::void_t<typename Alloc::is_always_equal>> {
+        using type = typename Alloc::is_always_equal;
+    };
+    template <typename Alloc>
+    using is_always_equal_t = typename is_always_equal<Alloc>::type;
+
+    template <typename Alloc, typename = void>
+    struct allocator_select_on_copy {
+        static constexpr Alloc get(const Alloc& alloc) { return alloc; }
+    };
+
+    template <typename Alloc>
+    struct allocator_select_on_copy<
+        Alloc,
+        std::enable_if_t<std::is_same_v<
+            void,
+            std::void_t<
+                decltype(std::declval<Alloc>()
+                             .select_on_container_copy_construction())>>>> {
+        static constexpr Alloc get(const Alloc& alloc) {
+            return alloc.select_on_container_copy_construction();
+        }
+    };
+
+    template <typename Allocator, typename T, typename = void>
+    struct allocator_rebind_type {
+        using type = typename rebind<Allocator, T>::type;
+    };
+
+    template <typename Allocator, typename T>
+    struct allocator_rebind_type<
+        Allocator, T,
+        std::void_t<typename Allocator::template rebind<T>::other>> {
+        using type = typename Allocator::template rebind<T>::other;
+    };
 
 } // namespace __helpers
 
@@ -290,29 +307,30 @@ struct allocator {
     constexpr ~allocator() = default;
 
     // throws std::bad_alloc
-    [[nodiscard]] constexpr T* allocate(std::size_t n)
-    { return static_cast<T*>(::operator new(n * sizeof(T))); }
+    [[nodiscard]] constexpr T* allocate(std::size_t n) {
+        return static_cast<T*>(::operator new(n * sizeof(T)));
+    }
 
     // TODO: check allocated size
-    constexpr void deallocate(T* ptr, std::size_t)
-    { ::operator delete(ptr); }
+    constexpr void deallocate(T* ptr, std::size_t) { ::operator delete(ptr); }
 };
 
 template <typename T1, typename T2>
-constexpr bool operator==(const allocator<T1>&, const allocator<T2>&) noexcept
-{ return true; }
+constexpr bool operator==(const allocator<T1>&, const allocator<T2>&) noexcept {
+    return true;
+}
 
 template <typename T, typename... Args>
-constexpr std::enable_if_t<std::is_same_v<T*,
-    decltype(::new(std::declval<void*>()) T(std::declval<Args>()...))> , T*>
-construct_at(T* p, Args&&... args)
-{
+constexpr std::enable_if_t<
+    std::is_same_v<T*, decltype(::new(std::declval<void*>())
+                                    T(std::declval<Args>()...))>,
+    T*>
+construct_at(T* p, Args&&... args) {
     return ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
 }
 
 template <typename T>
-constexpr void destroy_at(T* p)
-{
+constexpr void destroy_at(T* p) {
     // TODO: destroy array
     p->~T();
 }
@@ -321,89 +339,86 @@ template <typename Allocator>
 struct allocator_traits {
     using allocator_type = Allocator;
     using value_type = typename Allocator::value_type;
-    using pointer =
-        __helpers::allocator_pointer_t<Allocator>;
+    using pointer = __helpers::allocator_pointer_t<Allocator>;
     using const_pointer =
         __helpers::allocator_const_pointer_t<Allocator, pointer>;
     using void_pointer =
         __helpers::allocator_void_pointer_t<Allocator, pointer>;
     using const_void_pointer =
         __helpers::allocator_const_void_pointer_t<Allocator, pointer>;
-    using difference_type =
-        __helpers::allocator_difference_type_t<Allocator>;
-    using size_type =
-        __helpers::allocator_size_type_t<Allocator>;
+    using difference_type = __helpers::allocator_difference_type_t<Allocator>;
+    using size_type = __helpers::allocator_size_type_t<Allocator>;
     using propagate_on_container_copy_assignment =
         __helpers::allocator_prop_copy_t<Allocator>;
     using propagate_on_container_move_assignment =
         __helpers::allocator_prop_move_t<Allocator>;
     using propagate_on_container_swap =
         __helpers::allocator_prop_swap_t<Allocator>;
-    using is_always_equal =
-        __helpers::is_always_equal_t<Allocator>;
+    using is_always_equal = __helpers::is_always_equal_t<Allocator>;
 
     template <typename T>
     using rebind_alloc =
         typename __helpers::allocator_rebind_type<Allocator, T>::type;
 
-    [[nodiscard]] static constexpr pointer allocate(Allocator& alloc, size_type n)
-    { return alloc.allocate(n); }
-    static constexpr void deallocate(Allocator& alloc, pointer p, size_type n)
-    { return alloc.deallocate(p, n); }
+    [[nodiscard]] static constexpr pointer allocate(Allocator& alloc,
+                                                    size_type n) {
+        return alloc.allocate(n);
+    }
+    static constexpr void deallocate(Allocator& alloc, pointer p, size_type n) {
+        return alloc.deallocate(p, n);
+    }
     template <typename T, typename... Args>
-    static constexpr void construct(Allocator&, T* p, Args&&... args)
-    { std::construct_at(p, std::forward<Args>(args)...); }
+    static constexpr void construct(Allocator&, T* p, Args&&... args) {
+        std::construct_at(p, std::forward<Args>(args)...);
+    }
     template <typename T>
-    static constexpr void destroy(Allocator&, T* p)
-    { std::destroy_at(p); }
+    static constexpr void destroy(Allocator&, T* p) {
+        std::destroy_at(p);
+    }
 
-    static constexpr Allocator
-        select_on_container_copy_construction(const Allocator& alloc)
-    { return __helpers::allocator_select_on_copy<Allocator>::get(alloc); }
+    static constexpr Allocator select_on_container_copy_construction(
+        const Allocator& alloc) {
+        return __helpers::allocator_select_on_copy<Allocator>::get(alloc);
+    }
 };
 
 template <typename T>
 struct default_delete {
     __GBLIBCPP_CONSTEXPR default_delete() noexcept = default;
 
-    template <typename U, std::enable_if_t<std::is_convertible_v<U*, T*>, bool> = true>
+    template <typename U,
+              std::enable_if_t<std::is_convertible_v<U*, T*>, bool> = true>
     __GBLIBCPP_CONSTEXPR default_delete(const default_delete<U>&) noexcept {}
 
-    __GBLIBCPP_CONSTEXPR void operator()(T* p) const
-    {
-        delete p;
-    }
+    __GBLIBCPP_CONSTEXPR void operator()(T* p) const { delete p; }
 };
 
 // TODO: weak_ptr
 template <typename T>
 class shared_ptr {
-public:
+   public:
     using element_type = std::remove_extent_t<T>;
     using pointer = element_type*; // TODO: pointer_traits
     using const_pointer = const element_type*;
     using reference = element_type&;
     using const_reference = const element_type&;
 
-private:
+   private:
     struct control_block_base {
         std::size_t ref_count;
         std::size_t weak_count;
         pointer ptr;
 
         constexpr control_block_base(std::size_t ref_count,
-            std::size_t weak_count, pointer ptr)
-            : ref_count(ref_count)
-            , weak_count(weak_count)
-            , ptr(ptr)
-        {
-        }
+                                     std::size_t weak_count, pointer ptr)
+            : ref_count(ref_count), weak_count(weak_count), ptr(ptr) {}
 
         virtual constexpr ~control_block_base() = default;
         virtual constexpr void do_delete() = 0;
 
-        // template <typename U, std::enable_if_t<std::is_convertible_v<T*, U*>, bool> = true>
-        // constexpr operator typename shared_ptr<U>::control_block_base*() const
+        // template <typename U, std::enable_if_t<std::is_convertible_v<T*, U*>,
+        // bool> = true> constexpr operator typename
+        // shared_ptr<U>::control_block_base*() const
         // {
         //     return this;
         // }
@@ -415,36 +430,32 @@ private:
 
         virtual constexpr ~control_block() = default;
 
-        constexpr control_block(std::size_t ref_count, std::size_t weak_count, pointer ptr)
-            : control_block_base { ref_count, weak_count, ptr }, Deleter{} { }
+        constexpr control_block(std::size_t ref_count, std::size_t weak_count,
+                                pointer ptr)
+            : control_block_base{ref_count, weak_count, ptr}, Deleter{} {}
 
         template <typename UDeleter>
-        constexpr control_block(std::size_t ref_count,
-            std::size_t weak_count, pointer ptr, UDeleter&& deleter)
-            : control_block_base { ref_count, weak_count, ptr }
-            , Deleter(std::forward<UDeleter>(deleter))
-        {
-        }
+        constexpr control_block(std::size_t ref_count, std::size_t weak_count,
+                                pointer ptr, UDeleter&& deleter)
+            : control_block_base{ref_count, weak_count, ptr}
+            , Deleter(std::forward<UDeleter>(deleter)) {}
 
-        virtual constexpr void do_delete() override
-        {
+        virtual constexpr void do_delete() override {
             if (this->Base::ptr)
                 this->Deleter::operator()(this->Base::ptr);
             this->Base::ptr = nullptr;
         }
     };
 
-    control_block_base* cb {};
-    pointer ptr {};
+    control_block_base* cb{};
+    pointer ptr{};
 
-    void inc_ref()
-    {
+    void inc_ref() {
         if (cb)
             ++cb->ref_count; // TODO: lock and atomic
     }
 
-    void dec_ref()
-    {
+    void dec_ref() {
         if (cb && --cb->ref_count == 0) {
             cb->do_delete();
             if (cb->weak_count == 0)
@@ -452,141 +463,112 @@ private:
         }
     }
 
-private:
-    template <typename Deleter>
-    using rebind_allocator = typename std::allocator_traits<Deleter>::template rebind_alloc<control_block<Deleter>>;
+   private:
+    template <typename Allocator, typename Deleter>
+    using rebound_allocator = typename std::allocator_traits<
+        Allocator>::template rebind_alloc<control_block<Deleter>>;
+
+    template <typename Allocator, typename Deleter>
+    using rebound_traits =
+        typename std::allocator_traits<rebound_allocator<Allocator, Deleter>>;
 
     template <typename U>
     friend class shared_ptr;
 
-public:
+   public:
     __GBLIBCPP_CONSTEXPR shared_ptr() noexcept = default;
-    __GBLIBCPP_CONSTEXPR shared_ptr(std::nullptr_t) noexcept { }
+    __GBLIBCPP_CONSTEXPR shared_ptr(std::nullptr_t) noexcept : shared_ptr{} {}
 
     template <typename U, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
     __GBLIBCPP_CONSTEXPR explicit shared_ptr(U* p) // TODO: array type
-        : cb(new control_block<default_delete<T>> { 1, 0, p })
-        , ptr(p)
-    {
-    }
+        : cb(new control_block<default_delete<T>>{1, 0, p}), ptr(p) {}
 
-    template <typename U, typename Deleter, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
+    template <typename U, typename Deleter,
+              enable_if_t<is_convertible_v<U*, T*>, bool> = true>
     __GBLIBCPP_CONSTEXPR explicit shared_ptr(U* p, Deleter d)
-        : cb(new control_block<Deleter> { 1, 0, p, d })
-        , ptr(p)
-    {
-    }
+        : cb(new control_block<Deleter>{1, 0, p, d}), ptr(p) {}
 
     template <typename Deleter>
     __GBLIBCPP_CONSTEXPR explicit shared_ptr(std::nullptr_t, Deleter d)
-        : cb(new control_block<Deleter> { 1, 0, nullptr, d })
-    {
-    }
-
-    template <typename U, typename Deleter, typename Allocator,
-        enable_if_t<is_convertible_v<U*, T*>, bool> = true>
-    __GBLIBCPP_CONSTEXPR explicit shared_ptr(U* p, Deleter d, Allocator alloc)
-    {
-        cb = std::allocator_traits<
-            rebind_allocator<Deleter>>::allocate(alloc, 1);
+        : cb(new control_block<Deleter>{1, 0, nullptr, d}) {}
 
-        std::allocator_traits<
-            rebind_allocator<Deleter>>::construct(alloc, cb, 1, 0, p, d);
+    template <typename U, typename Deleter, typename Alloc,
+              enable_if_t<is_convertible_v<U*, T*>, bool> = true>
+    __GBLIBCPP_CONSTEXPR explicit shared_ptr(U* p, Deleter d, Alloc alloc) {
+        cb = rebound_traits<Alloc, Deleter>::allocate(alloc, 1);
+        rebound_traits<Alloc, Deleter>::construct(alloc, cb, 1, 0, p, d);
 
         ptr = p;
     }
 
-    template <typename Deleter, typename Allocator>
-    __GBLIBCPP_CONSTEXPR explicit shared_ptr(std::nullptr_t, Deleter d, Allocator alloc)
-    {
-        cb = std::allocator_traits<
-            rebind_allocator<Deleter>>::allocate(alloc, 1);
-
-        std::allocator_traits<
-            rebind_allocator<Deleter>>::construct(alloc, cb, 1, 0, nullptr, d);
+    template <typename Deleter, typename Alloc>
+    __GBLIBCPP_CONSTEXPR explicit shared_ptr(std::nullptr_t, Deleter d,
+                                             Alloc alloc) {
+        cb = rebound_traits<Alloc, Deleter>::allocate(alloc, 1);
+        rebound_traits<Alloc, Deleter>::construct(alloc, cb, 1, 0, nullptr, d);
     }
 
     __GBLIBCPP_CONSTEXPR
     shared_ptr(const shared_ptr& other) noexcept
-        : cb(other.cb)
-        , ptr(other.ptr)
-    {
+        : cb(other.cb), ptr(other.ptr) {
         inc_ref();
     }
 
     __GBLIBCPP_CONSTEXPR
     shared_ptr(shared_ptr&& other) noexcept
         : cb(std::exchange(other.cb, nullptr))
-        , ptr(std::exchange(other.ptr, nullptr))
-    {
-    }
+        , ptr(std::exchange(other.ptr, nullptr)) {}
 
     template <typename U, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
-    __GBLIBCPP_CONSTEXPR
-    shared_ptr(const shared_ptr<U>& other) noexcept
-        : cb((control_block_base*)other.cb)
-        , ptr((T*)other.ptr)
-    {
+    __GBLIBCPP_CONSTEXPR shared_ptr(const shared_ptr<U>& other) noexcept
+        : cb((control_block_base*)other.cb), ptr((T*)other.ptr) {
         inc_ref();
     }
 
     template <typename U, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
-    __GBLIBCPP_CONSTEXPR
-    shared_ptr(shared_ptr<U>&& other) noexcept
+    __GBLIBCPP_CONSTEXPR shared_ptr(shared_ptr<U>&& other) noexcept
         : cb((control_block_base*)std::exchange(other.cb, nullptr))
-        , ptr((T*)std::exchange(other.ptr, nullptr))
-    {
-    }
+        , ptr((T*)std::exchange(other.ptr, nullptr)) {}
 
     // TODO: weak_ptr and unique_ptr
 
     __GBLIBCPP_CONSTEXPR
-    ~shared_ptr()
-    {
+    ~shared_ptr() {
         dec_ref();
         cb = nullptr;
         ptr = nullptr;
     }
 
     __GBLIBCPP_CONSTEXPR
-    shared_ptr& operator=(const shared_ptr& other) noexcept
-    {
-        shared_ptr { other }.swap(*this);
+    shared_ptr& operator=(const shared_ptr& other) noexcept {
+        shared_ptr{other}.swap(*this);
         return *this;
     }
 
     template <typename U, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
-    __GBLIBCPP_CONSTEXPR shared_ptr& operator=(const shared_ptr<U>& other) noexcept
-    {
-        shared_ptr { other }.swap(*this);
+    __GBLIBCPP_CONSTEXPR shared_ptr& operator=(
+        const shared_ptr<U>& other) noexcept {
+        shared_ptr{other}.swap(*this);
         return *this;
     }
 
     __GBLIBCPP_CONSTEXPR
-    shared_ptr& operator=(shared_ptr&& other) noexcept
-    {
-        shared_ptr { move(other) }.swap(*this);
+    shared_ptr& operator=(shared_ptr&& other) noexcept {
+        shared_ptr{move(other)}.swap(*this);
         return *this;
     }
 
     template <typename U, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
-    __GBLIBCPP_CONSTEXPR shared_ptr& operator=(shared_ptr<U>&& other) noexcept
-    {
-        shared_ptr { move(other) }.swap(*this);
+    __GBLIBCPP_CONSTEXPR shared_ptr& operator=(shared_ptr<U>&& other) noexcept {
+        shared_ptr{move(other)}.swap(*this);
         return *this;
     }
 
     __GBLIBCPP_CONSTEXPR
-    element_type* get() const noexcept
-    {
-        return cb ? ptr : nullptr;
-    }
+    element_type* get() const noexcept { return cb ? ptr : nullptr; }
 
     __GBLIBCPP_CONSTEXPR
-    explicit operator bool() const noexcept
-    {
-        return get();
-    }
+    explicit operator bool() const noexcept { return get(); }
 
     __GBLIBCPP_CONSTEXPR
     T& operator*() const noexcept { return *get(); }
@@ -599,150 +581,157 @@ public:
     long use_count() const noexcept { return cb ? cb->ref_count : 0; }
 
     __GBLIBCPP_CONSTEXPR
-    bool owner_before(const shared_ptr& other) const noexcept
-    {
+    bool owner_before(const shared_ptr& other) const noexcept {
         return cb < other.cb;
     }
 
     __GBLIBCPP_CONSTEXPR
-    void swap(shared_ptr& other) noexcept
-    {
+    void swap(shared_ptr& other) noexcept {
         std::swap(cb, other.cb);
         std::swap(ptr, other.ptr);
     }
 
     __GBLIBCPP_CONSTEXPR
-    void reset() noexcept
-    {
-        shared_ptr {}.swap(*this);
-    }
+    void reset() noexcept { shared_ptr{}.swap(*this); }
 
     template <typename U, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
-    __GBLIBCPP_CONSTEXPR void reset(U* p) noexcept
-    {
-        shared_ptr { p }.swap(*this);
+    __GBLIBCPP_CONSTEXPR void reset(U* p) noexcept {
+        shared_ptr{p}.swap(*this);
     }
 
-    template <typename U, typename Deleter, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
-    __GBLIBCPP_CONSTEXPR void reset(U* p, Deleter d) noexcept
-    {
-        shared_ptr { p, d }.swap(*this);
+    template <typename U, typename Deleter,
+              enable_if_t<is_convertible_v<U*, T*>, bool> = true>
+    __GBLIBCPP_CONSTEXPR void reset(U* p, Deleter d) noexcept {
+        shared_ptr{p, d}.swap(*this);
     }
 
     template <typename U, typename Deleter, typename Allocator,
-        enable_if_t<is_convertible_v<U*, T*>, bool> = true>
-    __GBLIBCPP_CONSTEXPR void reset(U* p, Deleter d, Allocator alloc)
-    {
-        shared_ptr { p, d, alloc }.swap(*this);
+              enable_if_t<is_convertible_v<U*, T*>, bool> = true>
+    __GBLIBCPP_CONSTEXPR void reset(U* p, Deleter d, Allocator alloc) {
+        shared_ptr{p, d, alloc}.swap(*this);
     }
 };
 
 template <typename T, typename Deleter = std::default_delete<T>>
 class unique_ptr {
-public:
+   public:
     using element_type = T;
     using deleter_type = Deleter;
     using pointer = element_type*;
 
-private:
+    template <typename U, typename UDeleter>
+    friend class unique_ptr;
+
+   private:
     impl::compressed_pair<pointer, deleter_type> data;
 
-public:
-    __GBLIBCPP_CONSTEXPR unique_ptr() noexcept: data{impl::default_construct_t{}} { }
-    __GBLIBCPP_CONSTEXPR unique_ptr(std::nullptr_t) noexcept: unique_ptr{} { }
-    __GBLIBCPP_CONSTEXPR unique_ptr(pointer p) noexcept: data{p, deleter_type{}} { }
-    __GBLIBCPP_CONSTEXPR unique_ptr(pointer p, const deleter_type& d) noexcept: data{p, d} { }
-    __GBLIBCPP_CONSTEXPR unique_ptr(pointer p, deleter_type&& d) noexcept: data{p, std::move(d)} { }
+   public:
+    __GBLIBCPP_CONSTEXPR unique_ptr() noexcept
+        : data{impl::default_construct_t{}} {}
+    __GBLIBCPP_CONSTEXPR unique_ptr(std::nullptr_t) noexcept : unique_ptr{} {}
+    __GBLIBCPP_CONSTEXPR unique_ptr(pointer p) noexcept
+        : data{p, deleter_type{}} {}
+    __GBLIBCPP_CONSTEXPR unique_ptr(pointer p, const deleter_type& d) noexcept
+        : data{p, d} {}
+    __GBLIBCPP_CONSTEXPR unique_ptr(pointer p, deleter_type&& d) noexcept
+        : data{p, std::move(d)} {}
     __GBLIBCPP_CONSTEXPR unique_ptr(const unique_ptr&) = delete;
 
     __GBLIBCPP_CONSTEXPR unique_ptr(unique_ptr&& other) noexcept
-        : data{std::exchange(other.data.first(), nullptr), std::move(other.data.second())} { }
-
-    template <typename U, typename E, std::enable_if_t<
-        !std::is_array_v<U> && std::is_convertible_v<U*, T*>
-            && std::is_convertible_v<E, Deleter>, bool> = true>
+        : data{std::exchange(other.data.first(), nullptr),
+               std::move(other.data.second())} {}
+
+    template <
+        typename U, typename E,
+        std::enable_if_t<!std::is_array_v<U> && std::is_convertible_v<U*, T*> &&
+                             std::is_convertible_v<E, Deleter>,
+                         bool> = true>
     __GBLIBCPP_CONSTEXPR unique_ptr(unique_ptr<U, E>&& other) noexcept
-        : data{std::exchange(other.data.first(), nullptr), std::move(other.data.second())} { }
+        : data{std::exchange(other.data.first(), nullptr),
+               std::move(other.data.second())} {}
 
     __GBLIBCPP_CONSTEXPR ~unique_ptr() { reset(); }
 
     __GBLIBCPP_CONSTEXPR unique_ptr& operator=(const unique_ptr&) = delete;
-    __GBLIBCPP_CONSTEXPR unique_ptr& operator=(std::nullptr_t) noexcept
-    {
+    __GBLIBCPP_CONSTEXPR unique_ptr& operator=(std::nullptr_t) noexcept {
         reset();
         return *this;
     }
 
-    __GBLIBCPP_CONSTEXPR unique_ptr& operator=(unique_ptr&& other) noexcept
-    {
+    __GBLIBCPP_CONSTEXPR unique_ptr& operator=(unique_ptr&& other) noexcept {
         reset(other.release());
         get_deleter() = std::move(other.get_deleter());
         return *this;
     }
 
-    template <typename U, typename E, std::enable_if_t<
-        !std::is_array_v<U> && std::is_convertible_v<U*, T*>
-            && std::is_assignable_v<Deleter&, E&&>, bool> = true>
-    __GBLIBCPP_CONSTEXPR unique_ptr& operator=(unique_ptr<U, E>&& other) noexcept
-    {
+    template <
+        typename U, typename E,
+        std::enable_if_t<!std::is_array_v<U> && std::is_convertible_v<U*, T*> &&
+                             std::is_assignable_v<Deleter&, E&&>,
+                         bool> = true>
+    __GBLIBCPP_CONSTEXPR unique_ptr& operator=(
+        unique_ptr<U, E>&& other) noexcept {
         reset(other.release());
         get_deleter() = std::move(other.get_deleter());
         return *this;
     }
 
-    __GBLIBCPP_CONSTEXPR void swap(unique_ptr& other) noexcept
-    {
+    __GBLIBCPP_CONSTEXPR void swap(unique_ptr& other) noexcept {
         std::swap(data, other.data);
     }
 
     __GBLIBCPP_CONSTEXPR pointer get() const noexcept { return data.first(); }
-    __GBLIBCPP_CONSTEXPR deleter_type& get_deleter() noexcept { return data.second(); }
-    __GBLIBCPP_CONSTEXPR const deleter_type& get_deleter() const noexcept { return data.second(); }
+    __GBLIBCPP_CONSTEXPR deleter_type& get_deleter() noexcept {
+        return data.second();
+    }
+    __GBLIBCPP_CONSTEXPR const deleter_type& get_deleter() const noexcept {
+        return data.second();
+    }
 
-    __GBLIBCPP_CONSTEXPR pointer release() noexcept
-    {
+    __GBLIBCPP_CONSTEXPR pointer release() noexcept {
         pointer ret = get();
         data.first() = nullptr;
         return ret;
     }
 
-    __GBLIBCPP_CONSTEXPR void reset(pointer p = pointer{}) noexcept
-    {
+    __GBLIBCPP_CONSTEXPR void reset(pointer p = pointer{}) noexcept {
         pointer old = release();
         data.first() = p;
         if (old)
             get_deleter()(old);
     }
 
-    __GBLIBCPP_CONSTEXPR explicit operator bool() const noexcept { return get(); }
+    __GBLIBCPP_CONSTEXPR explicit operator bool() const noexcept {
+        return get();
+    }
     __GBLIBCPP_CONSTEXPR pointer operator->() const noexcept { return get(); }
 
     __GBLIBCPP_CONSTEXPR std::add_lvalue_reference_t<T> operator*() const
-        noexcept(noexcept(*std::declval<pointer>())) { return *get(); }
+        noexcept(noexcept(*std::declval<pointer>())) {
+        return *get();
+    }
 };
 
 // TODO: use only one allocation
 template <typename T, typename... Args>
-std::shared_ptr<T> make_shared(Args&&... args)
-{
+std::shared_ptr<T> make_shared(Args&&... args) {
     return std::shared_ptr<T>(new T(std::forward<Args>(args)...));
 }
 
 template <typename T, typename... Args>
-__GBLIBCPP_CONSTEXPR std::unique_ptr<T> make_unique(Args&&... args)
-{
+__GBLIBCPP_CONSTEXPR std::unique_ptr<T> make_unique(Args&&... args) {
     return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
 }
 
 template <typename T>
-__GBLIBCPP_CONSTEXPR void swap(std::shared_ptr<T>& lhs, std::shared_ptr<T>& rhs) noexcept
-{
+__GBLIBCPP_CONSTEXPR void swap(std::shared_ptr<T>& lhs,
+                               std::shared_ptr<T>& rhs) noexcept {
     lhs.swap(rhs);
 }
 
 template <typename T, typename D>
-__GBLIBCPP_CONSTEXPR void swap(std::unique_ptr<T, D>& lhs, std::unique_ptr<T, D>& rhs) noexcept
-{
+__GBLIBCPP_CONSTEXPR void swap(std::unique_ptr<T, D>& lhs,
+                               std::unique_ptr<T, D>& rhs) noexcept {
     lhs.swap(rhs);
 }
 

+ 109 - 48
pretty-print.py

@@ -1,8 +1,23 @@
 import gdb.printing
 import re
 
-def create_iter(item, end, idx):
-    return vectorPrinter._iterator(item, end, idx)
+def parseCompressedPairElement(elem: gdb.Value) -> gdb.Value:
+    return elem[elem.type.fields()[0]]
+
+def parseCompressedPair(cpair: gdb.Value) -> tuple[gdb.Value, gdb.Value]:
+    fields = cpair.type.fields()
+
+    first = cpair[fields[0]]
+    second = cpair[fields[1]]
+
+    return parseCompressedPairElement(first), parseCompressedPairElement(second)
+
+def delegateChildren(val: gdb.Value):
+    try:
+        for field in val.type.fields():
+            yield field.name, val[field]
+    except TypeError:
+        yield '[value]', val
 
 class vectorPrinter:
     class _iterator:
@@ -18,7 +33,7 @@ class vectorPrinter:
         def __next__(self):
             if self.item >= self.end:
                 raise StopIteration
-            key = '[%d]' % self.idx
+            key = str(self.idx)
             iter = self.item.dereference()
             self.item += 1
             self.idx += 1
@@ -35,8 +50,9 @@ class vectorPrinter:
 
     def children(self):
         if self.val['m_size'] == 0:
-            return [ ('<vector of size 0>', '') ]
-        return self._iterator(self.val['m_data'], self.val['m_data'] + self.val['m_size'], 0)
+            return []
+        data, alloc = parseCompressedPair(self.val['m_data'])
+        return self._iterator(data, data + self.val['m_size'], 0)
 
 def _leftmost(node):
     ret = node
@@ -64,28 +80,33 @@ def _next(node):
 
 class rbtreePrinter:
     def __init__(self, type, val):
-        self.type = type
-        self.val = val['tree']
+        self.type: gdb.Type = type
+        self.val: gdb.Value = val['tree']
 
     def to_string(self):
-        return "%s of size %d" % (self.type, self.val['_size'])
+        return "%s of size %d" % (self.type, self.num_children())
 
     def display_hint(self):
         return 'array'
 
+    def num_children(self):
+        size, _ = parseCompressedPair(self.val['size_data'])
+        return size
+
     def children(self):
-        yield 'root', self.val['root']
-        if self.val['root'] == 0:
-            return
+        root, alloc = parseCompressedPair(self.val['root_data'])
+        size, comp = parseCompressedPair(self.val['size_data'])
 
-        yield 'size', self.val['_size']
+        # yield '[alloc]', alloc
+        # yield '[comp]', comp
+        # yield '[root]', root
+        if root == 0:
+            return
 
-        nd = _leftmost(self.val['root'].dereference())
-        i = 0
-        while True:
-            yield "[%d]" % i, nd['value']
+        nd = _leftmost(root.dereference())
+        for i in range(size):
+            yield str(i), nd['value']
             nd = _next(nd)
-            i += 1
             if nd == None:
                 break
 
@@ -94,19 +115,19 @@ class stringPrinter:
         self.val = val
 
     def to_string(self):
-        if self.val['m_data']['stackdata']['end'] == 0:
-            return self.val['m_data']['stackdata']['str'].string()
-        return self.val['m_data']['heapdata']['m_ptr'].string()
+        data, alloc = parseCompressedPair(self.val['m_data'])
+        data = data['in']
 
-    def num_children(self):
-        return 0
+        if data['stackdata']['end'] == 0:
+            return data['stackdata']['str'].string()
+        return data['heapdata']['m_ptr'].string()
 
     def display_hint(self):
         return 'string'
 
 class listPrinter:
     def __init__(self, val):
-        self.val: gdb.Field = val
+        self.val: gdb.Value = val
         self.type: gdb.Type = val.type
 
         this_type = self.type.unqualified().strip_typedefs()
@@ -116,26 +137,24 @@ class listPrinter:
         self.value_node_type = gdb.lookup_type(this_type.tag + '::node').pointer()
 
     def to_string(self):
-        if self.type.tag == None and self.val == 0:
-            return 'nullptr of std::list'
-        return "std::list of size %d" % self.val['m_size']
+        size, alloc = parseCompressedPair(self.val['m_pair'])
+        return 'std::list of size %d' % size
 
     def display_hint(self):
         return 'array'
 
-    def children(self):
-        if self.type.tag == None and self.val == 0:
-            return
+    def num_children(self):
+        size, alloc = parseCompressedPair(self.val['m_pair'])
+        return size
 
+    def children(self):
         head = self.val['m_head']
 
-        yield 'head', head.address
-
         node = head['next']
         idx = 0
         while node != head.address:
             nodeval = node.reinterpret_cast(self.value_node_type)
-            yield '[%d]' % idx, nodeval['value']
+            yield str(idx), nodeval['value']
             idx += 1
             node = node['next']
 
@@ -206,15 +225,11 @@ class tuplePrinter:
                 yield 'tuple of size 0', ''
 
 class functionPrinter:
-    def __init__(self, val):
+    def __init__(self, val: gdb.Value):
         self.val = val
 
     def to_string(self):
-        return self.val.type.tag
-
-    def children(self):
-        print(self.val['_data'].type)
-        yield 'function data', self.val['_data']
+        return self.val.type.name
 
 class referenceWrapperPrinter:
     def __init__(self, val):
@@ -227,15 +242,58 @@ class referenceWrapperPrinter:
         yield 'addr', self.val['_ptr'].cast(gdb.lookup_type('void').pointer())
         yield 'reference', self.val['_ptr']
 
-def build_pretty_printer(val):
-    type = val.type
+class sharedPointerPrinter:
+    def __init__(self, val: gdb.Value):
+        self.val = val
+        self.pointer = val['ptr']
+        self.controlBlock = val['cb']
+
+    def to_string(self):
+        if self.pointer == 0:
+            return 'nullptr of %s' % self.val.type.name
+
+        refCount = self.controlBlock['ref_count']
+        weakCount = self.controlBlock['weak_count']
+        realPointer = self.controlBlock['ptr']
+        return '%s to 0x%x, ref(%d), wref(%d), cb(0x%x), memp(0x%x)' % (
+                self.val.type.name,
+                self.pointer,
+                refCount,
+                weakCount,
+                self.controlBlock,
+                realPointer)
+
+    def children(self):
+        if self.pointer == 0:
+            return []
+
+        content = self.pointer.dereference()
+        return delegateChildren(content)
+
+class uniquePointerPrinter:
+    def __init__(self, val: gdb.Value):
+        self.val = val
+        self.data = val['data']
+
+    def to_string(self):
+        pointer, deleter = parseCompressedPair(self.data)
+        if pointer == 0:
+            return 'nullptr of %s' % self.val.type.name
+
+        return "%s to 0x%x" % (self.val.type.name, pointer)
 
-    if type.code == gdb.TYPE_CODE_REF:
-        type = type.target()
-    if type.code == gdb.TYPE_CODE_PTR:
-        type = type.target()
+    def children(self):
+        pointer, deleter = parseCompressedPair(self.data)
+        yield '[deleter]', deleter
+
+        if pointer == 0:
+            return
 
-    type = type.unqualified().strip_typedefs()
+        for item in delegateChildren(pointer.dereference()):
+            yield item
+
+def build_pretty_printer(val: gdb.Value):
+    type: gdb.Type = val.type.unqualified().strip_typedefs()
     typename = type.tag
 
     if typename == None:
@@ -253,9 +311,6 @@ def build_pretty_printer(val):
     if re.compile(r"^std::reference_wrapper<.*>$").match(typename):
         return referenceWrapperPrinter(val)
 
-    # if re.compile(r"^std::list<.*, .*>::node$").match(typename):
-    #     return None
-
     if re.compile(r"^std::list<.*, .*>::_iterator<.*?>$").match(typename):
         return listIteratorPrinter(val)
 
@@ -280,6 +335,12 @@ def build_pretty_printer(val):
     if re.compile(r"^std::basic_string<.*>$").match(typename):
         return stringPrinter(val)
 
+    if re.compile(r"^std::shared_ptr<.*>$").match(typename):
+        return sharedPointerPrinter(val)
+
+    if re.compile(r"^std::unique_ptr<.*>$").match(typename):
+        return uniquePointerPrinter(val)
+
     return None
 
 gdb.pretty_printers.append(build_pretty_printer)