[gjs: 4/11] jsapi-util: Cast pointer to the correct type when calling ref/free-func




commit bd3d79178ef0b9aedd7cb7637c3ace8e78d3892c
Author: Philip Chimento <philip chimento gmail com>
Date:   Tue Sep 28 17:26:47 2021 -0700

    jsapi-util: Cast pointer to the correct type when calling ref/free-func
    
    In GjsAutoPointer, T* is the type of the pointer, but F* is the type of
    the pointer that ref_func/free_func accept. We need to cast to F* when
    calling these functions.
    
    Previously this mostly worked because F = void, but it would not compile
    if F != void and F != T.

 gjs/jsapi-util.h              | 12 +++++-------
 test/gjs-test-jsapi-utils.cpp | 15 +++++++++++++++
 2 files changed, 20 insertions(+), 7 deletions(-)
---
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index ddbacc84..76747552 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -151,12 +151,8 @@ struct GjsAutoPointer {
         m_ptr = ptr;
 
         if constexpr (has_free_function()) {
-            if (old_ptr) {
-                if constexpr (std::is_array_v<T>)
-                    free_func(reinterpret_cast<T*>(old_ptr));
-                else
-                    free_func(old_ptr);
-            }
+            if (old_ptr)
+                free_func(reinterpret_cast<F*>(old_ptr));
         }
     }
 
@@ -172,7 +168,9 @@ struct GjsAutoPointer {
     [[nodiscard]] constexpr std::enable_if_t<!std::is_array_v<U>, Ptr> copy()
         const {
         static_assert(has_ref_function(), "No ref function provided");
-        return m_ptr ? reinterpret_cast<Ptr>(ref_func(m_ptr)) : nullptr;
+        return m_ptr ? reinterpret_cast<Ptr>(
+                           ref_func(reinterpret_cast<F*>(m_ptr)))
+                     : nullptr;
     }
 
     template <typename C>
diff --git a/test/gjs-test-jsapi-utils.cpp b/test/gjs-test-jsapi-utils.cpp
index a6f01426..a99ca423 100644
--- a/test/gjs-test-jsapi-utils.cpp
+++ b/test/gjs-test-jsapi-utils.cpp
@@ -173,6 +173,19 @@ static void test_gjs_autopointer_dtor_no_free_pointer() {
     g_assert_cmpstr(autoptr, ==, "DO NOT FREE ME");
 }
 
+static void gobject_free(GObject* p) { g_object_unref(p); }
+static GObject* gobject_copy(GObject* p) {
+    return static_cast<GObject*>(g_object_ref(p));
+}
+
+static void test_gjs_autopointer_cast_free_func_type() {
+    // No assertions; this test fails to compile if the casts are wrong
+    using TypedAutoPointer =
+        GjsAutoPointer<GjsTestObject, GObject, gobject_free, gobject_copy>;
+    TypedAutoPointer autoptr{gjs_test_object_new()};
+    TypedAutoPointer copy{autoptr.copy()};
+}
+
 static void test_gjs_autopointer_assign_operator() {
     GjsAutoTestObject autoptr;
     auto* ptr = gjs_test_object_new();
@@ -557,6 +570,8 @@ void gjs_test_add_tests_for_jsapi_utils(void) {
     g_test_add_func(
         "/gjs/jsapi-utils/gjs-autopointer/destructor/no_free_pointer",
         test_gjs_autopointer_dtor_no_free_pointer);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/free_and_ref_funcs",
+                    test_gjs_autopointer_cast_free_func_type);
     g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/destructor/c++",
                     test_gjs_autopointer_dtor_cpp);
     g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/destructor/c++-array",


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]