On CHERI-enabled systems we use uintptr_t as the underlying storage for
GType and therefore casting to gsize strips the upper bits from a pointer.
Fix this by casting via uintptr_t instead and introduce a new set of
macros to convert between GType and pointers.
This is required for CHERI systems such as Arm Morello, where gsize is
not large enough to hold a pointer. As GType can contain pointers, we
have to use guintptr instead.
The introspection parser isn't good enough to expand the shift symbol,
which means G_TYPE_FUNDAMENTAL_MAX is evaluated as (255 << 0).
We can use the `(value)` annotation to force the symbol value in the
introspection data.
See: GNOME/gobject-introspection#473
The compiler annotations are mainly useful for people using the symbols
directly.
To avoid getting compiler warnings for the GTypeValueTable definition
itself, we need to wrap the structure with
G_GNUC_BEGIN_IGNORE_DEPRECATIONS and G_GNUC_END_IGNORE_DEPRECATIONS.
The introspection scanner cannot deal very well with function pointers
into a plain structure. In order to document the various function
pointers in GTypeValueTable we need to create typed callbacks, and
use them to replace the anonymous function pointers inside the
structure. This not only allows us to properly document the function
pointers, but it also allows us to annotate the arguments and return
value of those function pointers.
See also: https://gitlab.gnome.org/GNOME/gobject-introspection/-/merge_requests/400#note_1721707
Most of the document was about traps, which have not existed since
commit 58cdf0b474, 10 years ago.
The rest of the document was about `GOBJECT_DEBUG`, and that information
would be more easily findable in the full GObject documentation — so
move it there and update it a bit.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
The documentation previously implicitly said in a few places that
interfaces are classed, but reading through the implementation of
`GType`, I don’t think they are. If they were, the registration of the
fundamental `G_TYPE_INTERFACE` in `gobject_init()` would specify
`G_TYPE_FLAG_CLASSED`. It only specifies `G_TYPE_FLAG_DERIVABLE`.
I think this makes sense, because you can’t subclass an interface.
Subclassing is a key property of being classed.
Tweak the `GType` tutorial to remove that implicit statement, and expand
the documentation for `G_TYPE_IS_CLASSED`.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #252
‘returns TRUE on success’ is misleading for a lot of these macros, as
they are checking whether a type has a certain property. Such a check
could be successful but return `FALSE`, by the normal meaning of the
word ‘success’.
Instead, reword the docs to spell out when `TRUE` will be returned.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
We can get a "-Wcast-align", if the target type that we cast to ("ct") has a
larger alignment than GTypeInstance.
That can happen on i686 architecture, if the GObject type has larger
alignment than the parent struct (or GObject). Since on i686, embeding
a "long long" or a "long double" in a struct still does not increase
the alignment beyond 4 bytes, this usually only happens when using the
__attribute__() to increase the alignment (or to have a field that has
the alignment increased).
It can happen on x86_64 when having a "long double" field.
The compiler warning is hard to avoid but not very useful, because it purely
operates on the pointer types at compile time. G_TYPE_CHECK_INSTANCE_CAST()
instead asserts (in non-optimized mode) that the pointer really points
to the expected GTypeInstance (and if that's the case, then the alignment
should be suitable already).
This is like in commit ed553e8e30 ('gtype: Eliminate -Wcast-align warnings
with G_TYPE_CHECK_INSTANCE_CAST'). But also fix the optimized code path.
With the unpatched G_TYPE_CHECK_INSTANCE_CAST() macro, the unit test would
now show the problem (with gcc-9.3.1-2.fc30.i686 or
gcc-12.2.1-4.fc37.x86_64):
$ export G_DISABLE_CAST_CHECKS=1
$ export CFLAGS='-Wcast-align=strict'
$ meson build
$ ninja -C build
...
In file included from ../gobject/gobject.h:26,
from ../gobject/gbinding.h:31,
from ../glib/glib-object.h:24,
from ../gobject/tests/objects-refcount1.c:2:
../gobject/tests/objects-refcount1.c: In function ‘my_test_dispose’:
../gobject/gtype.h:2523:42: warning: cast increases required alignment of target type [-Wcast-align]
2523 | # define _G_TYPE_CIC(ip, gt, ct) ((ct*) ip)
| ^
../gobject/gtype.h:517:66: note: in expansion of macro ‘_G_TYPE_CIC’
517 | #define G_TYPE_CHECK_INSTANCE_CAST(instance, g_type, c_type) (_G_TYPE_CIC ((instance), (g_type), c_type))
| ^~~~~~~~~~~
../gobject/tests/objects-refcount1.c:9:37: note: in expansion of macro ‘G_TYPE_CHECK_INSTANCE_CAST’
9 | #define MY_TEST(test) (G_TYPE_CHECK_INSTANCE_CAST ((test), G_TYPE_TEST, GTest))
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
../gobject/tests/objects-refcount1.c:96:10: note: in expansion of macro ‘MY_TEST’
96 | test = MY_TEST (object);
| ^~~~~~~
This can be used to mark entire types as deprecated,
and trigger a warning when they are instantiated
and `G_ENABLE_DIAGNOSTIC=1` is set in the environment.
There's currently no convenient macros for defining
types with the new flag, but you can do:
```c
_G_DEFINE_TYPE_EXTENDED_BEGIN (GtkAppChooserWidget,
gtk_app_chooser_widget,
GTK_TYPE_WIDGET,
G_TYPE_FLAG_DEPRECATED)
...
_G_DEFINE_TYPE_EXTENDED_END ()
```
Includes a unit test by Philip Withnall.
This reverts commit 476e33c3f3.
We’ve decided to remove `G_OS_DARWIN` in favour of recommending people
use `__APPLE__` instead. As per the discussion on #2802 and linked
issues,
* Adding a new define shifts the complexity from “which of these
platform-provided defines do I use” to “which platform-provided
defines does G_OS_DARWIN use”
* There should ideally be no cases where a user of GLib has to use
their own platform-specific code, since GLib should be providing
appropriate abstractions
* Providing a single `G_OS_DARWIN` to cover all Apple products (macOS
and iOS) hides the complexity of what the user is actually testing:
are they testing for the Mach kernel, the Carbon and/or Cocoa user
space toolkits, macOS vs iOS vs tvOS, etc
Helps: #2802
The usual use of G_DISABLE_CAST_CHECKS is to define it without giving it
a value. The value was never looked at until
f946e45a0c, where I decided it would be
cool to ignore it if defined to 0. But this broke the original usage, so
we need to revert that.
I thought it would be a good idea to look at the value in order to give
applications an off switch for the new behavior, so you could continue
to build optimized builds with cast checks enabled. We could still try
to find a way to do that in the future if desired, e.g. by introducing a
new G_ENABLE_CAST_CHECKS definition. But this doesn't seem especially
important. G_DISABLE_CAST_CHECKS is not documented anyway, so how we
handle cast checks is entirely up to GLib.
There is currently no `dllimport` attribute on any of our function,
which prevents MSVC to optimize function calls.
To fix that issue, we need to redeclare all our visibility macros for
each of our libraries, because when compiling e.g. GIO code, we need
dllimport in GLIB headers and dllexport in GIO headers. That means they
cannot use the same GLIB_AVAILABLE_* macro.
Since that's a lot of boilerplate to copy/paste after each version bump,
this MR generate all those macros using a python script.
Also simplify the meson side by using `gnu_symbol_visibility : 'hidden'`
keyword argument instead of passing the cflag manually.
This leaves only API index to add manually into glib-docs.xml when
bumping GLib version. That file cannot be generated because Meson does
not allow passing a buit file to gnome.gtkdoc()'s main_xml kwarg
unfortunately.
Cast checks are slow. We seem to have some rough consensus that they are
important for debug builds, but not for release builds. Problem is, very
few apps define G_DISABLE_CAST_CHECKS for release builds. Worse, it's
undocumented, so there's no way apps could even be expected to know
about it.
We can get the right default is almost all situations by making this
depend on the __OPTIMIZE__ preprocessor definition. This is a GCC-specific
thing, although Clang supports it too. If the compiler does not define
__OPTIMIZE__, then this commit does no harm: you can still use
G_DISABLE_CAST_CHECKS as before. When checking __OPTIMIZE__, we are
supposed to ensure our code has the same behavior as it would if we do
not, which will be true except in case the check fails (which is
programmer error).
Downside: this will not automatically do the right thing with -Og,
because __OPTIMIZE__ is always defined to 1. We don't want to disable
cast checks automatically if using -O0 or -Og. There's no way to
automatically fix this, but we can create an escape hatch by allowing
you to define G_DISABLE_CAST_CHECKS=0 to force-enable cast checks. In
practice, I don't think this matters much because -Og kinda failed:
GCC's man page says it should be a superior debugging experience to -O0,
but it optimizes variables away so it's definitely not.
Another downside: this is bad if you really *do* want cast checks in
release builds. The same solution applies: define
G_DISABLE_CAST_CHECKS=0 and you'll get your cast checks.
This makes code that sets no flags a bit more self-documenting:
using G_TYPE_FLAG_NONE makes it clearer that no special behaviour is
required than literal 0, and clearer that there is no weird casting
between types than (GTypeFlags) 0.
GTypeFlags and GTypeFundamentalFlags occupy the same namespace and the
same bitfield, so I intentionally haven't added
G_TYPE_FUNDAMENTAL_FLAGS_NONE.
Signed-off-by: Simon McVittie <smcv@collabora.com>
This reverts commit 0ddea2d8e2.
The commit was based on the misunderstanding that types
declared with G_DECLARE_FINAL_TYPE are actually non-derivable.
But that is only the case for types defined with
G_DEFINE_FINAL_TYPE.
Fixes: #2661
These have all been added manually, as I’ve finished all the files which
I can automatically detect.
All the license headers in this commit are for LGPL-2.1-or-later, and
all have been double-checked against the license paragraph in the file
header.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #1415
As noticed by Christian Hergert: We can reduce
some overhead by checking for exact type
equality first. According to Christian, around
3% of g_type_is_a calls are exact equalities.
We now guarantee that GObjects will always be allocated at least as
aligned as the basic types. If you want to put an element in your
GObject which has higher alignment requirements, we can’t guarantee it
will be aligned*. If you need it to be aligned, you’ll need to put it on
the heap (aligned appropriately), or add appropriate padding in your
GObject struct.
*Actually, GSlice will guarantee that the whole GObject is aligned to at
least the power of 2 greater than or equal to the size of the GObject,
which means any element in the GObject struct should always be
appropriate aligned if the compiler pads it appropriately. If malloc()
is used, however, it doesn’t make that guarantee, so we can’t make that
guarantee overall.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1231
Regardless of the actual alignment of the GTypeInstance in question,
these do a runtime check on the type, so if the type was originally
aligned correctly when allocated, it should be aligned correctly if the
type check succeeds. -Wcast-align is meant to warn about casts between
types, which this isn’t (if the check succeeds).
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #1231
See the reasoning in the patch for why we believe GObjects *are*
(already) as aligned as the basic types.
We want to make this guarantee so that it’s guaranteed to be safe for
people to ignore -Wcast-align warnings for GObjects which contain basic
types. This typically happens with gdouble on 32-bit ARM platforms.
The checks are slightly complicated by the need to support GObjects with
custom constructors. We should expect that a custom construction
function will chain up to g_object_constructor (which calls
g_type_create_instance() as normal), but it’s possible that someone has
done something crazy and uses a custom allocator which doesn’t return
with the same alignment as GSlice. Hand them a warning in that case. If
that is true, the code which uses their custom-constructed GObject can
presumably already deal with the alignment it gets given.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1231
When rendering the contents of the GLib documentation stored inside the
introspection data, a common behaviour is to take the first paragraph as
a summary of the symbol being documented.
The documentation is assumed to be in Markdown format, which means:
- paragraphs must be separated by newlines
- lines that have an indentation of four or more spaces are considered
code blocks
- lines that start with a `#` are considered titles
This means we need to slightly tweak the documentation in our sources to
ensure that it can be rendered appropriately by tools that are not
gtk-doc.
See issue: #2365
We want to have the ability to mark types that should not be derivable
even if they are in a deeply derivable type hierarchy; in other words,
leaf nodes in the types tree.
http://isvolatileusefulwiththreads.in/c/
It’s possible that the variables here are only marked as volatile
because they’re arguments to `g_once_*()`. Those arguments will be
modified in a subsequent commit.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #600
This function returns the most specific instantiatable type
that is a prerequisite for a given interface.
This type is necessary in particular when dealing with GValues
because a GValue contains an instance of a type.
This commit includes tests for the new API.
Rather than using a mixture of ‘instantiable’ and ‘instantiatable’
everywhere, standardise on the term which is already in the public API.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
The various `g_strdup_printf()` returns values in the implementations of GValue
lcopy_func are runtime checks which could be disabled if one wants and therefore
should be handled as such with g_return_val_if_fail()
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.
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.