[gnu.gcc.bug] bug in stdarg.h

wkd@asc.slb.com (06/22/89)

Using gcc-1.35, on SUN4 and SUN3, running SunOs4.0.1. The following
program crashes because 'stdarg.h' only works for arguments that are
'int' or whose size is a multiple of sizeof(int).

======================== test.c ================================

#include <stdarg.h>

void foo(int a, char b, ...)
{
    va_list ap;
    char *p;

    va_start(ap, b);
    p = va_arg(ap, char *);
    printf(p);
}


main()
{
    foo(1, 'c', "hello world\n");
}

========================= end ==================================

Here is a new stdarg.h that works correctly:

========================== stdarg.h ============================

#ifndef _STDARG_H
#define _STDARG_H

typedef char *va_list;

/* Amount of space required in an argument list for an arg of type TYPE.
   TYPE may alternatively be an expression whose type is used.  */

#define __va_rounded_size(TYPE)  \
  (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))

#if !defined(sparc) && !defined(__sparc__)
#define va_start(AP, LASTARG) 						\
 (AP = ((char *) &(LASTARG) + sizeof(LASTARG)))
#else
#define va_start(AP, LASTARG) 						\
 (__builtin_saveregs (),						\
  AP = ((char *) &(LASTARG) + sizeof(LASTARG)))
#endif

void va_end (va_list);		/* Defined in gnulib */
#define va_end(AP)

#define va_arg(AP, TYPE)						\
 (AP += __va_rounded_size (TYPE),					\
  *((TYPE *) (AP - sizeof(TYPE))))

#endif /* _STDARG_H */

=================================== end =====================================


Here are the diffs:

sake[wkd](71)% diff -btwc stdarg.h $GNU/gcc-1.35/sun4
*** stdarg.h	Thu Jun 22 09:14:18 1989
--- /nfs/hamachi/local/gnu/gcc-1.35/sun4/stdarg.h	Tue May 16 08:24:13 1989
***************
*** 11,21 ****
  
  #if !defined(sparc) && !defined(__sparc__)
  #define va_start(AP, LASTARG)                                           \
!  (AP = ((char *) &(LASTARG) + sizeof(LASTARG)))
  #else
  #define va_start(AP, LASTARG)                                           \
   (__builtin_saveregs (),                                                \
!   AP = ((char *) &(LASTARG) + sizeof(LASTARG)))
  #endif
  
  void va_end (va_list);          /* Defined in gnulib */
--- 11,21 ----
  
  #if !defined(sparc) && !defined(__sparc__)
  #define va_start(AP, LASTARG)                                           \
!  (AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
  #else
  #define va_start(AP, LASTARG)                                           \
   (__builtin_saveregs (),                                                \
!   AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
  #endif
  
  void va_end (va_list);          /* Defined in gnulib */
***************
*** 23,28 ****
  
  #define va_arg(AP, TYPE)                                                \
   (AP += __va_rounded_size (TYPE),                                       \
!   *((TYPE *) (AP - sizeof(TYPE))))
  
  #endif /* _STDARG_H */
--- 23,28 ----
  
  #define va_arg(AP, TYPE)                                                \
   (AP += __va_rounded_size (TYPE),                                       \
!   *((TYPE *) (AP - __va_rounded_size (TYPE))))
  
  #endif /* _STDARG_H */
sake[wkd](72)% 


Bill Duttweiler (wkd@ASC.SLB.COM)