Re: Problem with type safety and the "sentinel" attribute


On Fri, Jun 09, 2006 at 07:30:25PM +0200, Tim Janik wrote:
> On Fri, 9 Jun 2006, Kaveh R. Ghazi wrote:
> >>  void print_string_array (const char *array_name,
> >>                                 const char *string, ...) __attribute__
> >>                                 ((__sentinel__));
> >>
> >>   print_string_array ("empty_array", NULL); /* gcc warns, but shouldn't 
> >*/
> >>
> >> The only way out for keeping the sentinel attribute and avoiding the
> >> warning is using
> >>
> >> static void print_string_array (const char *array_name, ...)
> >> __attribute__ ((__sentinel__));
> >
> >I think you could maintain typesafety and silence the warning by
> >keeping the more specific prototype and adding an extra NULL, e.g.:
> >
> >print_string_array ("empty_array", NULL, NULL);
> >
> >Doesn't seem elegant, but it does the job.
> this is an option for a limited set of callers, yes.

For the statistics, by adding the __sentinel__ attribute to the beast
codebase, I have about 50 of those sentinel warnings that I don't need.
So the double NULL termination would make quite some code more messy
than it should be. 

> >> By the way, there is already an existing gcc bug, which is about the
> >> same thing (NULL passed within named args), but wants to have it the
> >> way it works now:
> >>
> >>
> >
> >Correct, the feature as I envisioned it expected the sentinel to
> >appear in the variable arguments only.  This PR reflects when I found
> >out it didn't do that and got around to fixing it.  Note the "buggy"
> >behavior wasn't exactly what you wanted either because GCC got fooled
> >by a sentinel in *any* of the named arguments, not just the last one.

Ah, I see.

> >> so if it gets changed, then gcc might need to support both
> >>  - NULL termination within the last named parameter allowed
> >>  - NULL termination only allowed within varargs parameters (like it is
> >>    now)
> >
> >I'm not against this enhancement, but you need to specify a syntax
> >that allows the old behavior but also allows doing it your way.
> >
> >Hmm, perhaps we could check for attribute "nonnull" on the last named
> >argument, if it exists then that can't be the sentinel, if it's not
> >there then it does what you want.  This is not completely backwards
> >compatible because anyone wanting the existing behavior has to add the
> >attribute nonnull.  But there's precedent for this when attribute
> >printf split out whether the format specifier could be null...
> >
> >We could also create a new attribute name for the new behavior.  This
> >would preserve backwards compatibility.  I like this idea better.
> i agree here. as far as the majority of the GLib and Gtk+ APIs are 
> concerned,
> we don't really need the flexibility of the sentinel attribute but rather
> a compiler check on whether the last argument used in a function call
> is NULL or 0 (regardless of whether it's the last named arg or already part
> of the varargs list).
> that's also why the actual sentinel wrapper in GLib looks like this:
>   #define G_GNUC_NULL_TERMINATED __attribute__((__sentinel__))
> so, if i was to make a call on this issue, i'd either introduce
> __attribute__((__null_terminated__)) with the described semantics,
> or have __attribute__((__sentinel__(-1))) work essentially like
> __attribute__((__sentinel__(0))) while also accepting 0 in the position
> of the last named argument.

I also like the backwards compatible way better than trying to somehow
modifying the attribute; it may break something now, or - which would
also be bad - it may make something that somebody will want to check
with the sentinel attribute in some future program impossible.

The only case that I ever needed was NULL termination, so I think
implementing one of the two proposals Tim made would be sufficient.
Personally I like __attribute__((__null_terminated__)) better, because
a -1 sentinel may be less intuitive to read in the source code. So this
would be my suggestion for a "syntax specification".

> >Next you need to recruit someone to implement this enhancement, or
> >submit a patch. :-) Although given that you can silence the warning by
> >adding an extra NULL at the call site, I'm not sure it's worth it.
> i would say this is definitely worth it, because the issue also shows up in
> other code that is widely used:
>   gpointer    g_object_new       (GType           object_type,
>                                   const gchar    *first_property_name,
>                                                   ...);
> that's for instance a function which is called in many projects. 
> putting the burden on the caller is clearly the wrong trade off here.
> so please take this as a vote for the worthiness of a fix ;)

Good. Of course I would be happy if somebody with knowledge of the
compiler source could implement it. I never hacked gcc code before.
But since you suggested sending a patch, I'll at least try to implement
a new __null_terminated__ attribute, and ask for help if I can't figure
out what to do.

   Cu... Stefan
Stefan Westerfeld, Hamburg/Germany,

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