This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH] Use mode_t in open and friends
- From: Rasmus Villemoes <rv at rasmusvillemoes dot dk>
- To: libc-alpha at sourceware dot org
- Date: Tue, 06 May 2014 11:36:53 +0200
- Subject: Re: [PATCH] Use mode_t in open and friends
- Authentication-results: sourceware.org; auth=none
- References: <87k3afhsua dot fsf at rasmusvillemoes dot dk> <87a9banc4i dot fsf at igel dot home> <20140503092848 dot GC15537 at domone dot podge> <53651EB2 dot 10100 at redhat dot com>
Pedro Alves <palves@redhat.com> writes:
> On 05/03/2014 10:28 AM, OndÅej BÃlka wrote:
>> On Thu, Apr 24, 2014 at 02:30:21PM +0200, Andreas Schwab wrote:
>>> Rasmus Villemoes <rv@rasmusvillemoes.dk> writes:
>>>
>>>> The sole varargs argument to open and friends has type mode_t, not int.
>>>
>>> Varargs use the promoted type, but mode_t traditionally has been
>>> unsigned short.
>>>
>> So which solution do you prefer? Adding a custom type for that as
>> suggested in sibling threads? What about just adding a cast like
>>
>> mode = (mode_t) va_arg (arg, int);
>>
That requires sizeof(mode_t) <= sizeof(int) - which (I think) is the
case on all current and probably also all future platforms, but nothing
guarantees it.
> Might be overkill for this instance alone, but another option
> would be letting the compiler do the work.
Yes, that is definitely the best way. It would be nice if gcc exposed
something like __builtin_promoted_type(T) so one could simply say
va_arg(arg, __builtin_promoted_type(mode_t)); or even better if gcc had
a switch to simply DTRT when it encounters a va_arg with a
non-self-promoting type. gcc certainly already contains the
infrastructure to do this.
> Can be done with C11's _Generic, or GCC's
> __builtin_choose_expr/__builtin_types_compatible_p.
>
> Here's how it might look with the latter:
>
> mode = __unpromoted_va_arg (arg, mode_t);
>
> #define __maybe_va_arg(list, type, unpromoted, promoted, else_expr) \
> __builtin_choose_expr (__builtin_types_compatible_p (type, unpromoted), \
> va_arg (list, promoted), \
> else_expr)
>
> /* Like va_arg, but accepts unpromoted types. */
> #define __promoted_va_arg(list, type) \
> (type) __maybe_va_arg (list, type, float, double, \
> __maybe_va_arg (list, type, char, int, \
> __maybe_va_arg (list, type, short int, int, \
> __maybe_va_arg (list, type, unsigned char, unsigned int, \
> __maybe_va_arg (list, type, unsigned short int, unsigned int, \
> va_arg (list, type))))))
This seems to solve it, but as you say, it may be overkill. I don't
think there are functions other than open and derivatives with this
legacy problem. Since mode_t is guaranteed to be an integer type, I
think
mode = __builtin_choose_expr(sizeof(mode_t) < sizeof(int),
va_arg(ap, int),
va_arg(ap, mode_t));
would be sufficient.
Rasmus