The __declspec(dllexport) attribute in itself doesn't imply
'extern' - thus any intended variable declaration with
GLIB_VAR/GOBJECT_VAR would actually be a variable definition. With
C compilers defaulting to -fcommon, this isn't an issue, but
upcoming compilers (GCC 10 and Clang 11) will default to -fno-common,
ending up with duplicate definitions of these variables.
Rename the variables involved so that people get a slightly more
obvious critical warning when they try to ref an object which has
already been finalised.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Making this validation code public allows projects to validate a
GParamSpec name before creating it. While hard-coded GParamSpec don't
need this, we can't afford crashing the main program for dynamically
generated GParamSpec from user-created data.
In such case, we will need to validate the param names and return errors
instead of trying to create a GParamSpec with invalid names.
Includes modifications from Philip Withnall and Emmanuele Bassi to
rearrange the new function addition and split it into one function for
GParamSpecs and one for GSignals.
When calling `g_set_object()` for a type derived from `GObject`, GCC 9.2
was giving the following strict aliasing warning:
```
../../source/malcontent/libmalcontent-ui/user-controls.c:1001:21: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
1001 | if (g_set_object (&self->user, user))
/opt/gnome/install/include/glib-2.0/gobject/gobject.h:744:33: note: in definition of macro ‘g_set_object’
744 | (g_set_object) ((GObject **) (object_ptr), (GObject *) (new_object)) \
| ^~~~~~~~~~
```
This was due to the `(GObject **)` cast.
Pass the pointer through a union to squash this warning. We already do
some size and type checks of the dereferenced type, which should catch
casual errors. The `g_object_ref()` and `g_object_unref()` calls which
subsequently happen inside the `g_set_object()` function also do some
dynamic type checks.
Add a test.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
As with `g_variant_new()` (or any varargs function which takes integer
literals of differing widths), callers need to be careful to ensure
their integer literals have the right width.
Tweak the documentation for `g_object_new()`, `g_object_set()` and
`g_object_get()` to clarify this. The documentation for `g_object_get()`
shows that it is not subject to the same caveats, since it operates on
pointers.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Closes: #833
While we automatically define cleanup functions for the module, we don't
do it for the module class.
This will allow to manage the ownership of the class when reffing it
without having to cast it to GTypeClass.
The `G_TYPE_IS_INSTANTIATABLE()` check is redundant with a precondition
on the function.
The `g_type_class_peek()` check seems like a pointless restriction: it
should be possible to check for a signal from a class init function.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #650
Use the new g_type_interface_instantiable_prerequisite() to check
compatibility for transform functions.
In particular, this allows interfaces (in my case GDK_TYPE_PAINTABLE) to
be transformed to/from any GObject type (in my case G_TYPE_OBJECT) using
the transform function registered to tranform between any 2 objects
(g_value_object_transform_value() does a type check and uses NULL if the
types don't match).
And this in turn allows be to g_object_bind_property() a gobject-typed
generic property (GtkListItem::item) to a GtkImage::paintable.
Use the newly added g_type_interface_instantiable_prerequisite() to
allow closure return values being interfaces by looking up the
instantiable type for the interface and usings its GValue accessors.
There is (at most) a single GType that is instantiable and a
prerequisite for an interface. This function returns that type.
This type is necessary in particular when dealing with GValues because a
GValue contains an instance of a type.
The format has never previously been specified. It can be anything, but
for sanity’s sake disallow empty strings.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #358
It provides more useful output on failure, and isn’t compiled out when
building with `G_DISABLE_ASSERT`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
It provides more useful output on failure, and isn’t compiled out when
building with `G_DISABLE_ASSERT`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
This will allow subsequent testing of property name canonicalisation.
This test introduces no functional changes.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #358
Rather than adding a canonicalised and non-canonicalised version of the
signal to `g_signal_key_bsa`, just add the canonicalised version. Signal
lookups always use the canonicalised key (since the previous commit).
This saves space in `g_signal_key_bsa`, which should speed up lookups;
and it saves significant space in the global `GQuark` table (a 9.6%
reduction in entries in that table, by a rough test using
gnome-software).
We have to be a little more relaxed on the signal name validation than
we are for property name validation, as GTK installs a
`-gtk-private-changed` signal which violates the signal naming rules.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Previously, we’d look up the signal name as passed to (for example)
`g_signal_lookup()`, and rely on the fact that signals are inserted
twice into `g_signal_key_bsa`; once in canonical form and once not.
In preparation for only inserting signals into `g_signal_key_bsa` once,
we now try looking up a signal with the given signal name and, if that
fails, try canonicalising the name and trying again.
This is a performance hit on lookups for non-canonical names, but
shouldn’t affect the performance of lookups for canonical names. If
people want performance, they should use canonical names.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #358
This eliminates a call from every call site of signal_id_lookup(). It
introduces no functional changes, but allows subsequent refactoring.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Since signal names are the same as property names, reference between the
two. Improve the formatting, and make it clearer that `_` is
discouraged.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #358
Interned strings are never freed, so we don’t need to take a copy of
them when returning them in a #GValue. This is a minor memory allocation
improvement, with no functional changes.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Rather than interning a property name string which isn’t canonicalised,
canonicalise it first, and enforce stricter validation on inputs.
The previous code was not incorrect (since the property machinery would
have canonicalised the property names itself, internally), but would
have resulted in non-canonical property names getting into the GQuark
table unnecessarily. With the new code, the interned property names from
property installation time should be consistently reused.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #358
Inline with the stricter version of the property naming rules from the
documentation, tighten up the validation of property names at
installation time.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
It provides more useful output on failure, and isn’t compiled out when
building with `G_DISABLE_ASSERT`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
The documentation says that parameter names must be alphanumeric (plus
`-` or `_`) and that canonicalisation turns `_` into `-`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #358
There’s no need to have the property naming documentation in two places,
with one version of it being stricter than the other. Rationalise it to
one place, link to that consistently, and settle on the stricter
version.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #358
We cannot just call
G_PARAM_SPEC_GET_CLASS (pspec)->value_set_default (pspec, &dflt_value);
without initializing the GValue first. It would call
param_string_set_default(), which would set the pointer value
to a cloned string (which later never gets released, because
the GValue is not known to hold a string).
Fixes: 6ad799ac67
Since we have the type of the GValue we're going to initialize, we can
allow passing an empty (but valid) GValue when retrieving the default
value of a GParamSpec.
This will eliminate additional checks and an unnecessary reset.
If we're cross-compiling, the installed-tests are useful even if we
can't run them on the build machine: we can copy them to the host
machine (possibly via a distro package like Debian's libglib2.0-tests)
and run them there.
While I'm changing the build-tests condition anyway, deduplicate it.
Based on a patch by Helmut Grohne.
Bug-Debian: https://bugs.debian.org/941509
Signed-off-by: Simon McVittie <smcv@collabora.com>
I don’t think these could be hit in practice due to the guarantees of
the type system, but the static analyser doesn’t know that — so make the
assertions clearer to shut it up.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1767
The static analyser can’t yet work out how `g_autofree` works, so
disable those tests.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1767
The macros for the probes confuse the static analyser, and are often
called with arguments which the analyser things shouldn’t be used any
more (for example, the address of a block of memory which has just been
freed).
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1767