DASCHBACH@CHEMISTRY.UTAH.EDU (06/15/89)
/*
** gnu-cc-bug.c
**
** This program will execute the print statement at line 171 for n >= 7.
** With this example the return should allways be 1.00 and the print
** statement should never be reached. When the print statement is
** executed the *correct* value of 1.00 appears. This indicates to
** me a timing problem of some sort, I have seen similar things on
** other machines in FORTRAN.
**
** If the return type for 'trivial_func' is changed to 'void' or to 'int'
** no error obtains. If the return value for 'trivial_func' is used,
** eg. 'ytemp = (*derivs)(1.0,&yout);', then no error obtains.
**
** If the call to '(*derivs)' outside of the loop is asigned to
** ytemp, and not the call inside, then the error obtains for
** n >= 8.
**
** It is my understanding that ignoring a return from a function is
** allowed, certainly this is common practice for many library functions
** returning 'int'.
**
** I understand that the returning of a double which is unused is not
** good practice, and is allmost certainly slower, but this code is a
** massive reduction of the code in which the bug was found.
**
** This code runs as expected when compiled with the Sun cc on the
** Sun 386i/250 and the Sun 4/280, both running SunOS 4.0.1. Also works
** on the Multiflow Trace TRACE/UNIX 4.1.5, and Microsoft C 5.1 on a PC
**
** If ignoring the return on a function called through a pointer is not
** allowed then I am sorry to trouble you. However I have been unable to
** find any refernce which states this. Certainly examples can be found
** where the return type is int and it is ignored.
**
** define NO_BUG1 to assign the return value
** define NO_BUG2 to use return type int
** defint NO_BUG3 to use return type void
**
** Info:
**
** GNU CC version 1.35
** compiled using 'gcc -g -o bug gnu-cc-bug.c'
** | 'gcc -g -o no_bug1 -DNO_BUG1 gnu-cc-bug.c'
** | 'gcc -g -o no_bug2 -DNO_BUG2 gnu-cc-bug.c'
** | 'gcc -g -o no_bug3 -DNO_BUG3 gnu-cc-bug.c'
**
** tm: tm-sun386i.h
** md: i386.md
**
** Machine: Sun 386i/250
** OS: SunOS 4.0.1
**
** I am using the Sun assembler and linker. I have been able to get GNU CC
** working with the GNU as and ld, but any program compiled with this setup
** crashes 'segmentaion fault (core dump)'.
** It appeared to me that with the hastles of COFF object format etc.
** and no debugging support, it was easiest to use the Sun assembler
** and loader. I have had no problems running dbx with this arrangement.
**
** Thanks.
** John L. Daschbach
** Department of Chemistry
** University of Utah
** Salt Lake City, UT 84112
**
** daschbach@chemistry.utah.edu
*/
/*-------------------------------------------------------------------------*/
#include <stdio.h>
/*-------------------------------------------------------------------------*/
extern int main();
extern void mid_pnt();
#if defined(NO_BUG1)
extern double trivial_func();
#elif defined(NO_BUG2)
extern int trivial_func();
#elif defined(NO_BUG3)
extern void trivial_func();
#else
extern double trivial_func();
#endif
/*-------------------------------------------------------------------------*/
double yout=0.0;
int nstep=100;
/*-------------------------------------------------------------------------*/
int
main(argc,argv)
int argc;
char **argv;
{
mid_pnt(nstep,&yout,trivial_func);
exit(0);
}
/*-------------------------------------------------------------------------*/
/*
**
** trivial_func()
**
** This trivial function allways returns 1.0
*/
#if defined(NO_BUG1)
double
#elif defined(NO_BUG2)
int
#elif defined(NO_BUG3)
void
#else
double
#endif
trivial_func(yout)
double *yout;
{
*yout = 1.0;
#if defined(NO_BUG2)
return(1);
#elif defined(NO_BUG3)
return;
#else
return( *yout );
#endif
}
/*-------------------------------------------------------------------------*/
/*
** mid_pnt()
**
**
*/
void
mid_pnt(nstep,yout,derivs)
int nstep;
double *yout;
#if defined(NO_BUG1)
double (*derivs)();
#elif defined(NO_BUG2)
int (*derivs)();
#elif defined(NO_BUG3)
void (*derivs)();
#else
double (*derivs)();
#endif
{
int n;
#if defined(NO_BUG1)
double ytemp;
ytemp = (*derivs)(yout);
#else
(*derivs)(yout);
#endif
for( n = 2; n <= nstep; n++ ) {
#if defined(NO_BUG1)
ytemp = (*derivs)(yout);
#else
(*derivs)(yout); /* note that *yout will *allways* be 1.00 */
#endif
/* the next section executes for n >= 7 on the sun386i/250
however in the print statement *yout is *allways* 1.00.
the next statement can be changed to any value > 0.0
and the if clause will be true. A test for equality == 0.0
will also evaluate to TRUE */
if ( *yout < 1.0 )
printf("mid_pnt() ERROR n %4d yout %le\n",n,*yout);
}
return;
}