This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Use mode_t in open and friends


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]