After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 64994 - Using G_GNUC_CONST for _get_type() functions is wrong
Using G_GNUC_CONST for _get_type() functions is wrong
Status: RESOLVED DUPLICATE of bug 446565
Product: glib
Classification: Platform
Component: gobject
1.3.x
Other Linux
: Normal normal
: ---
Assigned To: gtkdev
gtkdev
https://blogs.gnome.org/mcatanzaro/20...
: 676100 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2001-11-21 00:16 UTC by Damon Chaplin
Modified: 2017-09-14 09:52 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Test app (817 bytes, text/plain)
2001-11-22 01:09 UTC, Damon Chaplin
Details

Description Damon Chaplin 2001-11-21 00:16:14 UTC
In Glade, g_type_from_name() is returning 0 fairly often, even
though the type has been explicitly initialized with a _get_type() call.
Comment 1 Owen Taylor 2001-11-21 01:47:27 UTC
Can you provide a test case or more details?
Comment 2 Damon Chaplin 2001-11-22 01:09:28 UTC
Created attachment 6056 [details]
Test app
Comment 3 Owen Taylor 2001-11-23 14:38:44 UTC
gtk_color_selection_get_type() is __attribute__((const)) so
GCC thinks is can discard calls to it if they aren't used
anywhere. try 

volatile GType type;

I think the that the potential optimization from elimininating
repeated get_type() calls is probably worth the oddity, 
but it is certainly a gotcha that a lot of people are running
into.
Comment 4 Damon Chaplin 2001-11-26 22:47:57 UTC
Yes, that does fix it.

Though I don't like the use of G_GNUC_CONST here.
Unless it really does have significant performance advantages,
I'd take it out. It's not really correct.
Comment 5 Colin Walters 2012-05-15 14:31:36 UTC
(In reply to comment #4)
> Yes, that does fix it.
> 
> Though I don't like the use of G_GNUC_CONST here.
> Unless it really does have significant performance advantages,
> I'd take it out. It's not really correct.

That's right, we've been Doing It Wrong.

From the GCC manual:

`const'
     Many functions do not examine any values except their arguments,
     and have no effects except the return value.  Basically this is
     just slightly more strict class than the `pure' attribute below,
     since function is not allowed to read global memory.

But _get_type() functions obviously *do* read global memory, so it's wrong for
us to annotate them as const.  What we really mean is "pure":

`pure'
     Many functions have no effects except the return value and their
     return value depends only on the parameters and/or global
     variables.  Such a function can be subject to common subexpression
     elimination and loop optimization just as an arithmetic operator
     would be.
Comment 6 Colin Walters 2012-05-15 14:31:47 UTC
*** Bug 676100 has been marked as a duplicate of this bug. ***
Comment 7 Dan Winship 2012-05-15 15:17:17 UTC
The first call to a _get_type() function is neither const nor pure, because it has side effects. What we really want is __attribute__((idempotent)), which was suggested upstream a long time ago (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=32911) but never went anywhere.

Calls to a _get_type() function after the first one can be called 'const' as legitimately as they can be called 'pure', because the static variable that the _get_type() function looks at never changes after the first call, so the optimizer doesn't need to worry about it.


(Marking _get_type() functions 'pure' instead of 'const' would basically be a no-op [relative to not marking them at all], because in code like:

  gtk_button_do_this (GTK_BUTTON (widget));
  gtk_button_do_that (GTK_BUTTON (widget));

you'd need to call gtk_button_get_type() both times if it was marked 'pure', because gtk_button_do_this() might have changed global memory. If it's marked 'const', you only need to call it the first time.)
Comment 8 Colin Walters 2012-05-15 15:27:07 UTC
(In reply to comment #7)

> (Marking _get_type() functions 'pure' instead of 'const' would basically be a
> no-op [relative to not marking them at all], because in code like:
> 
>   gtk_button_do_this (GTK_BUTTON (widget));
>   gtk_button_do_that (GTK_BUTTON (widget));
> 
> you'd need to call gtk_button_get_type() both times if it was marked 'pure',
> because gtk_button_do_this() might have changed global memory. If it's marked
> 'const', you only need to call it the first time.)

True.  

The obvious long term thing we want is for the compiler to be aware of the type hierarchy...a gcc gobject-introspection plugin.  Though there are also obvious issues with that owing to the fact that one has to compile the code to get the type data =/

More medium term, yes - Behdad's suggestion of 'idempotent' makes a lot of sense.  It's probably not hard to implement at all.

But this bug should remain open until we ship correct annotations on our _get_type() functions; telling people to use volatile to subvert the optimizer is not a good long term situation.
Comment 9 Colin Walters 2012-05-15 15:34:45 UTC
(In reply to comment #7)

> (Marking _get_type() functions 'pure' instead of 'const' would basically be a
> no-op [relative to not marking them at all], because in code like:
> 
>   gtk_button_do_this (GTK_BUTTON (widget));
>   gtk_button_do_that (GTK_BUTTON (widget));

FWIW in my code, I tend to hoist GObject-style casts manually.  I.e.:

GtkWidget *mywidget;
GtkButton *mywidget_button;

mywidget = foo_widget_new ();
mywidget_button = GTK_BUTTON (mywidget);

gtk_button_do_this (mywidget_button);
gtk_button_do_that (mywidget_button);

Because it also avoids grabbing a process-global mutex at every function call.

(Well actually, more often I say "screw that shit" and just use C casts, but sadly we rely too much on GObject casts in our ecosystem due to a lack of testing)
Comment 10 Dan Winship 2012-05-15 15:36:27 UTC
(In reply to comment #8)
> But this bug should remain open until we ship correct annotations on our
> _get_type() functions; telling people to use volatile to subvert the optimizer
> is not a good long term situation.

see also bug 605976
Comment 11 Sébastien Wilmet 2015-09-15 07:37:37 UTC
gdbus-codegen has this bug too.
Comment 12 Dan Winship 2015-09-15 14:07:50 UTC
I think at this point, we might as well declare that using G_GNUC_CONST on type functions is allowed/encouraged, and g_type_ensure() is the only supported way to force a type to be registered without creating actually an object of that type.
Comment 13 Michael Catanzaro 2015-09-15 19:42:25 UTC
(In reply to Dan Winship from comment #12)
> I think at this point, we might as well declare that using G_GNUC_CONST on
> type functions is allowed/encouraged, and g_type_ensure() is the only
> supported way to force a type to be registered without creating actually an
> object of that type.

Probably, but if we recommend this, G_DECLARE_*_TYPE should then be changed to use G_GNUC_CONST. Best do that *now* before applications start relying on the opposite behavior.
Comment 14 Sébastien Wilmet 2015-09-15 21:42:52 UTC
This works *now* with the current GCC version, but what if a new optimization is added in the future that takes advantage of const functions and that breaks the whole g platform? For example interprocedural optimizations coupled with bundling…

It's safer to rely only on the API of GCC, that is, the interface, what is documented, not how it is currently used internally.
Comment 15 Philip Withnall 2017-09-14 09:48:48 UTC
Although in practical terms G_GNUC_CONST is safe to use for the moment, and I agree with Dan (comment #12) that the only way to really ensure a type is available is to use g_type_ensure(), I don’t think we should add G_GNUC_CONST into all get_type() functions. As Sébastien says, its semantics aren’t correct for what we’d be using it for.

The real fix here is to push for support for some kind of __attribute__((idempotent)) in the compilers, and use that once it’s available. That’s bug #446565, which I’m going to mark this as a duplicate of.

*** This bug has been marked as a duplicate of bug 446565 ***
Comment 16 Philip Withnall 2017-09-14 09:52:43 UTC
In the meantime, though, we can leave the existing G_GNUC_CONST attributes in place until they actually cause a problem.