From: graham@convex.com (Marv Graham)
Subject: 2.2.2 stdio.h <=> stdarg.h problem
Organization: Engineering, CONVEX Computer Corp., Richardson, Tx., USA
Distribution: gnu
Date: Wed, 29 Jul 1992 16:48:45 GMT

On OSF i386 systems, the standard /usr/include/stdio.h contains the lines

/*
 * (c) Copyright 1990, 1991, OPEN SOFTWARE FOUNDATION, INC.
 * ALL RIGHTS RESERVED
 */
/*
 * OSF/1 Release 1.0.1
 */
/* @(#)$RCSfile: stdio.h,v $ $Revision: 2.11.4.3 $ (OSF) $Date: 91/03/11 15:02:20 $ */
/*
 * COMPONENT_NAME: stdio.h
 *                                                                    
 * ORIGIN: IBM
 *
 * Copyright International Business Machines Corp. 1985, 1988
 * All Rights Reserved
 * Licensed Material - Property of IBM
	...
	...
	...
#ifndef _VA_LIST
#define _VA_LIST
typedef char * __va_list;
extern int  vfprintf(FILE *, const char *, __va_list );
extern int  vprintf(const char *, __va_list );
extern int  vsprintf(char *, const char *, __va_list );
#else
extern int  vfprintf(FILE *, const char *, va_list );
extern int  vprintf(const char *, va_list );
extern int  vsprintf(char *, const char *, va_list );
#endif
	...
	...
	...

###############################################################################

The GNU file gstdarg.h which eventaully becomes
	/usr/local/lib/gcc-lib/.../include/stdarg.h
contains the lines

/* stdarg.h for GNU.
   Note that the type used in va_arg is supposed to match the
   actual type **after default promotions**.
   Thus, va_arg (..., short) is not valid.  */

#ifndef _STDARG_H
#define _STDARG_H
	...
	...
	...
#ifdef _HIDDEN_VA_LIST  /* On OSF1, this means varargs.h is "half-loaded".  */
#undef _VA_LIST
#endif

/* The macro _VA_LIST_ is the same thing used by this file in Ultrix.  */
#ifndef _VA_LIST_
/* The macro _VA_LIST is used in SCO Unix 3.2.  */
#ifndef _VA_LIST
#define _VA_LIST_
#define _VA_LIST
#ifndef __svr4__
typedef char *va_list;
#else
typedef void *va_list;
#endif
#endif /* _VA_LIST */
#endif /* _VA_LIST_ */
	...
	...
	...

Since <stdio.h> does not mention _HIDDEN_VA_LIST, a source program that begins
with

#include	<stdio.h>
#include	<stdarg.h>

leaves "va_list" undefined.

The sequence

#include	<stdarg.h>
#include	<stdio.h>

defines "va_list".

If /usr/include/stdarg.h is used explicitly,
	#include	"/usr/include/stdarg.h"
there is no problem in either case.

###############################################################################

The complete program (modified in the #inlcude lines only) that led to this
report is

#ifdef FIRST
#include <stdio.h>
#include "/usr/include/stdarg.h"
#else	/* FIRST */
#include "/usr/include/stdarg.h"
#include <stdio.h>
#endif	/* FIRST */

struct spurious
{
    int anumber;
};

int first(char *fmt, ...)
{
    int pos, number;
    va_list args;
    int dummy;

    va_start(args, fmt);
    for (pos = 0; fmt[pos]; pos++)
	if (fmt[pos] == 'i')
	{
	    number = va_arg(args, int);
	    printf("%d", number);
	}
	else
	    putchar(fmt[pos]);
    va_end(args);
    putchar('\n');
    return dummy;
}

struct spurious second(char *fmt, ...)	/* same as 'first', except for the */
{					/* return type */
    int pos, number;
    va_list args;
    struct spurious dummy;

    va_start(args, fmt);
    for (pos = 0; fmt[pos]; pos++)
	if (fmt[pos] == 'i')
	{
	    number = va_arg(args, int);
	    printf("%d", number);
	}
	else
	    putchar(fmt[pos]);
    va_end(args);
    putchar('\n');
    return dummy;
}

main()
{
    first("hi there this works", 5, 20);
    second("hi there this works", 5, 20); /* no, it doesn't */
}


This program works when FIRST is either defined or not defined on the gcc
command line.


Marv Graham; Convex Computer Corp.  {uunet,sun,uiucdcs,allegra}!convex!graham
					graham@bach.convex.com

Newsgroups: gnu.gcc.bug