Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 18 May 2001 03:07:06 +1000 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        Cyrille Artho <cartho@silmaril.org>
Cc:        bugs@FreeBSD.ORG, Ernst de Haan <ernst@jollem.com>
Subject:   Re: Insufficient type casts in stdargs.h
Message-ID:  <Pine.BSF.4.21.0105180247350.18957-100000@besplex.bde.org>
In-Reply-To: <3B03C53C.349F9491@silmaril.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, 17 May 2001, Cyrille Artho wrote:

> Hi,
> in FreeBSD 4.3's stdargs.h, the macro va_arg does not contain enough
> type casts. As a result, gcc 2.95.3 rejects using va_arg with void*
> arguments.
> ...
> Original source code:
> 
> parameter[n_parameters++] = va_arg(ap, void*);

The bug seems to be in your declaration of `ap' (which is not shown here).
`ap' must have type va_list (which happens to be `char *' for FreeBSD on
i386's).

> -------------------------------------------------------------------------
> 
> Linux little endian systems:
> 
> #define va_arg(AP, TYPE)                                               
> \
>  (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)),    
> \
>   *((TYPE *) (void *) ((char *) (AP) - __va_rounded_size (TYPE))))
> 
> Expanded source code:
> parameter[n_parameters++] = ( ap  = (__gnuc_va_list) ((char *) ( ap ) +
> (((sizeof (   void*  ) + sizeof (int) - 1) / sizeof (int)) * sizeof
> (int)) ),       *((  void*  *) (void *) ((char *) ( ap ) - (((sizeof (  
> void*  ) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) ))) ;

The cast to `char *' is required here because we want to do pointer
arithmetic on `AP' but the type of `AP' is `void *'.  The cast to
`void *' has no effect here, because __gnuc_va_list happens to be
`void *', but casting to __gnu_va_list is required in general.

> -------------------------------------------------------------------------
> 
> FreeBSD:
> 
> #define va_arg(ap, type) \
>         (*(type *)((ap) += __va_size(type), (ap) - __va_size(type)))
> 
> Expanded source code:
> parameter[n_parameters++] = (*(  void*  *)(( ap ) += (((sizeof(   void* 
> ) + sizeof(int) - 1) /  sizeof(int)) * sizeof(int)) , ( ap ) -
> (((sizeof(   void*  ) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
> ))
> 
> jlint.cc:141: ANSI C++ forbids using pointer of type `void *' in
> arithmetic
> jlint.cc:141: ANSI C++ forbids using pointer of type `void *' in
> arithmetic

There is no pointer of type `void *' in arithmetic here, provided `ap'
is declared correctly.  The arithmetic is `(ap) += integer' where `ap'
should have type `char *'.  The expression is a little simpler than in
Linux because `ap' has a convenient type.  This simplification is
possible because <stdarg.h> is machine-dependent.

Bruce


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.21.0105180247350.18957-100000>