mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-12 15:36:17 +01:00
Merge branch 'ebassi/final-flag' into 'main'
Add "final" type flag Closes #2321 See merge request GNOME/glib!1937
This commit is contained in:
commit
4a16a5b374
@ -17,6 +17,7 @@ G_TYPE_IS_INSTANTIATABLE
|
||||
G_TYPE_IS_DERIVABLE
|
||||
G_TYPE_IS_DEEP_DERIVABLE
|
||||
G_TYPE_IS_INTERFACE
|
||||
G_TYPE_IS_FINAL
|
||||
GTypeInterface
|
||||
GTypeInstance
|
||||
GTypeClass
|
||||
@ -113,6 +114,9 @@ G_DEFINE_TYPE_WITH_CODE
|
||||
G_DEFINE_ABSTRACT_TYPE
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_CODE
|
||||
G_DEFINE_FINAL_TYPE
|
||||
G_DEFINE_FINAL_TYPE_WITH_PRIVATE
|
||||
G_DEFINE_FINAL_TYPE_WITH_CODE
|
||||
G_ADD_PRIVATE
|
||||
G_PRIVATE_OFFSET
|
||||
G_PRIVATE_FIELD
|
||||
|
@ -143,7 +143,7 @@
|
||||
G_TYPE_FLAG_INSTANTIATABLE | \
|
||||
G_TYPE_FLAG_DERIVABLE | \
|
||||
G_TYPE_FLAG_DEEP_DERIVABLE)
|
||||
#define TYPE_FLAG_MASK (G_TYPE_FLAG_ABSTRACT | G_TYPE_FLAG_VALUE_ABSTRACT)
|
||||
#define TYPE_FLAG_MASK (G_TYPE_FLAG_ABSTRACT | G_TYPE_FLAG_VALUE_ABSTRACT | G_TYPE_FLAG_FINAL)
|
||||
#define SIZEOF_FUNDAMENTAL_INFO ((gssize) MAX (MAX (sizeof (GTypeFundamentalInfo), \
|
||||
sizeof (gpointer)), \
|
||||
sizeof (glong)))
|
||||
@ -804,6 +804,13 @@ check_derivation_I (GType parent_type,
|
||||
NODE_NAME (pnode));
|
||||
return FALSE;
|
||||
}
|
||||
if ((G_TYPE_FLAG_FINAL & GPOINTER_TO_UINT (type_get_qdata_L (pnode, static_quark_type_flags))) == G_TYPE_FLAG_FINAL)
|
||||
{
|
||||
g_warning ("cannot derive '%s' from final parent type '%s'",
|
||||
type_name,
|
||||
NODE_NAME (pnode));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -370,6 +370,18 @@ G_BEGIN_DECLS
|
||||
* Returns: %TRUE on success
|
||||
*/
|
||||
#define G_TYPE_HAS_VALUE_TABLE(type) (g_type_value_table_peek (type) != NULL)
|
||||
/**
|
||||
* G_TYPE_IS_FINAL:
|
||||
* @type: a #GType value
|
||||
*
|
||||
* Checks if @type is a final type. A final type cannot be derived any
|
||||
* further.
|
||||
*
|
||||
* Returns: %TRUE on success
|
||||
*
|
||||
* Since: 2.70
|
||||
*/
|
||||
#define G_TYPE_IS_FINAL(type) (g_type_test_flags ((type), G_TYPE_FLAG_FINAL)) GLIB_AVAILABLE_MACRO_IN_2_70
|
||||
|
||||
|
||||
/* Typedefs
|
||||
@ -1002,13 +1014,16 @@ typedef enum /*< skip >*/
|
||||
* @G_TYPE_FLAG_VALUE_ABSTRACT: Indicates an abstract value type, i.e. a type
|
||||
* that introduces a value table, but can't be used for
|
||||
* g_value_init()
|
||||
* @G_TYPE_FLAG_FINAL: Indicates a final type. A final type is a non-derivable
|
||||
* leaf node in a deep derivable type hierarchy tree. Since: 2.70
|
||||
*
|
||||
* Bit masks used to check or determine characteristics of a type.
|
||||
*/
|
||||
typedef enum /*< skip >*/
|
||||
{
|
||||
G_TYPE_FLAG_ABSTRACT = (1 << 4),
|
||||
G_TYPE_FLAG_VALUE_ABSTRACT = (1 << 5)
|
||||
G_TYPE_FLAG_ABSTRACT = (1 << 4),
|
||||
G_TYPE_FLAG_VALUE_ABSTRACT = (1 << 5),
|
||||
G_TYPE_FLAG_FINAL GLIB_AVAILABLE_ENUMERATOR_IN_2_70 = (1 << 6)
|
||||
} GTypeFlags;
|
||||
/**
|
||||
* GTypeInfo:
|
||||
@ -1685,6 +1700,57 @@ guint g_type_get_type_registration_serial (void);
|
||||
* Since: 2.38
|
||||
*/
|
||||
#define G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(TN, t_n, T_P) G_DEFINE_TYPE_EXTENDED (TN, t_n, T_P, G_TYPE_FLAG_ABSTRACT, G_ADD_PRIVATE (TN))
|
||||
/**
|
||||
* G_DEFINE_FINAL_TYPE:
|
||||
* @TN: the name of the new type, in Camel case
|
||||
* @t_n: the name of the new type, in lower case, with words
|
||||
* separated by `_` (snake case)
|
||||
* @T_P: the #GType of the parent type
|
||||
*
|
||||
* A convenience macro for type implementations.
|
||||
*
|
||||
* Similar to G_DEFINE_TYPE(), but defines a final type.
|
||||
*
|
||||
* See G_DEFINE_TYPE_EXTENDED() for an example.
|
||||
*
|
||||
* Since: 2.70
|
||||
*/
|
||||
#define G_DEFINE_FINAL_TYPE(TN, t_n, T_P) G_DEFINE_TYPE_EXTENDED (TN, t_n, T_P, G_TYPE_FLAG_FINAL, {}) GLIB_AVAILABLE_MACRO_IN_2_70
|
||||
/**
|
||||
* G_DEFINE_FINAL_TYPE_WITH_CODE:
|
||||
* @TN: the name of the new type, in Camel case
|
||||
* @t_n: the name of the new type, in lower case, with words
|
||||
* separated by `_` (snake case)
|
||||
* @T_P: the #GType of the parent type
|
||||
* @_C_: Custom code that gets inserted in the `type_name_get_type()` function.
|
||||
*
|
||||
* A convenience macro for type implementations.
|
||||
*
|
||||
* Similar to G_DEFINE_TYPE_WITH_CODE(), but defines a final type and
|
||||
* allows you to insert custom code into the `*_get_type()` function, e.g.
|
||||
* interface implementations via G_IMPLEMENT_INTERFACE().
|
||||
*
|
||||
* See G_DEFINE_TYPE_EXTENDED() for an example.
|
||||
*
|
||||
* Since: 2.70
|
||||
*/
|
||||
#define G_DEFINE_FINAL_TYPE_WITH_CODE(TN, t_n, T_P, _C_) _G_DEFINE_TYPE_EXTENDED_BEGIN (TN, t_n, T_P, G_TYPE_FLAG_FINAL) {_C_;} _G_DEFINE_TYPE_EXTENDED_END() GLIB_AVAILABLE_MACRO_IN_2_70
|
||||
/**
|
||||
* G_DEFINE_FINAL_TYPE_WITH_PRIVATE:
|
||||
* @TN: the name of the new type, in Camel case
|
||||
* @t_n: the name of the new type, in lower case, with words
|
||||
* separated by `_` (snake case)
|
||||
* @T_P: the #GType of the parent type
|
||||
*
|
||||
* A convenience macro for type implementations.
|
||||
*
|
||||
* Similar to G_DEFINE_TYPE_WITH_PRIVATE(), but defines a final type.
|
||||
*
|
||||
* See G_DEFINE_TYPE_EXTENDED() for an example.
|
||||
*
|
||||
* Since: 2.70
|
||||
*/
|
||||
#define G_DEFINE_FINAL_TYPE_WITH_PRIVATE(TN, t_n, T_P) G_DEFINE_TYPE_EXTENDED (TN, t_n, T_P, G_TYPE_FLAG_FINAL, G_ADD_PRIVATE (TN)) GLIB_AVAILABLE_MACRO_IN_2_70
|
||||
/**
|
||||
* G_DEFINE_TYPE_EXTENDED:
|
||||
* @TN: The name of the new type, in Camel case.
|
||||
|
@ -51,6 +51,7 @@ gobject_tests = {
|
||||
'source' : ['signals.c', marshalers_h, marshalers_c],
|
||||
},
|
||||
'testing' : {},
|
||||
'type-flags' : {},
|
||||
}
|
||||
|
||||
if cc.get_id() != 'msvc'
|
||||
|
88
gobject/tests/type-flags.c
Normal file
88
gobject/tests/type-flags.c
Normal file
@ -0,0 +1,88 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
// SPDX-FileCopyrightText: 2021 Emmanuele Bassi
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#define TEST_TYPE_FINAL (test_final_get_type())
|
||||
G_DECLARE_FINAL_TYPE (TestFinal, test_final, TEST, FINAL, GObject)
|
||||
|
||||
struct _TestFinal
|
||||
{
|
||||
GObject parent_instance;
|
||||
};
|
||||
|
||||
struct _TestFinalClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_FINAL_TYPE (TestFinal, test_final, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
test_final_class_init (TestFinalClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
test_final_init (TestFinal *self)
|
||||
{
|
||||
}
|
||||
|
||||
#define TEST_TYPE_FINAL2 (test_final2_get_type())
|
||||
G_DECLARE_FINAL_TYPE (TestFinal2, test_final2, TEST, FINAL2, TestFinal)
|
||||
|
||||
struct _TestFinal2
|
||||
{
|
||||
TestFinal parent_instance;
|
||||
};
|
||||
|
||||
struct _TestFinal2Class
|
||||
{
|
||||
TestFinalClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (TestFinal2, test_final2, TEST_TYPE_FINAL)
|
||||
|
||||
static void
|
||||
test_final2_class_init (TestFinal2Class *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
test_final2_init (TestFinal2 *self)
|
||||
{
|
||||
}
|
||||
|
||||
/* test_type_flags_final: Check that trying to derive from a final class
|
||||
* will result in a warning from the type system
|
||||
*/
|
||||
static void
|
||||
test_type_flags_final (void)
|
||||
{
|
||||
GType final2_type;
|
||||
|
||||
/* This is the message we print out when registering the type */
|
||||
g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_WARNING,
|
||||
"*cannot derive*");
|
||||
|
||||
/* This is the message when we fail to return from the GOnce init
|
||||
* block within the test_final2_get_type() function
|
||||
*/
|
||||
g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL,
|
||||
"*g_once_init_leave: assertion*");
|
||||
|
||||
final2_type = TEST_TYPE_FINAL2;
|
||||
g_assert_true (final2_type == G_TYPE_INVALID);
|
||||
|
||||
g_test_assert_expected_messages ();
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/type/flags/final", test_type_flags_final);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
Loading…
Reference in New Issue
Block a user