[gnu.gcc.bug] sun386i bug

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;
}