[gnu.g++.bug] Pointer to method bug on Sun4

rick@ADS.COM (Rick Chestek) (02/06/90)

I have a code fragment which executes differently on a Sun 4 and a
Sun 3.  The Sun 3 version executes as intended; the Sun 4 version
does not.

The code has a method, make_child, which I invoke three different
ways in this fragment.  On a Sun 4, the third technique returns
a different answer from the first two.  On the Sun 3, all 3 techniques
return the same value.  The technique that fails is the case where
the method is called via a pointer.  When the technique fails, the
returned value is the value of address of the object, i.e. "this"
(although my code fragment doesn't print this to demonstrate it).



Also, to be honest, I'm not sure that the compilation of this code is
really correct in either case; I appear unable to treat the ptr in the
same manner as a function name as my copy of Lippmann indicates; i.e.
in the code below you will find the line:

          (*m_c_ptr)();

My reading of Lippman indicates that I should be able to use:

	  m_c_ptr();

but this results in compile time errors.  I have also had troubles
using the pointer from outside the class (i.e. I haven't been
able to get anything like   (parent->*m_child_ptr)()   through the
compiler) so I created the make_child2 method.  I don't believe
that this should be necessary.


Here is the source, as produced by the command "g++ -E":

-----------------------------------------------------------------------------
# 1 "test.C"
# 1 "/usr/local/gnu/lib/g++-include/stream.h" 1
 
 





















 


#pragma once


 
 


# 1 "/usr/local/gnu/lib/g++-include/File.h" 1
 
 






















#pragma once


# 1 "/usr/local/gnu/lib/g++-include/builtin.h" 1
 

 





















 





#pragma once



typedef void (*one_arg_error_handler_t)(const char*);
typedef void (*two_arg_error_handler_t)(const char*, const char*);



# 1 "/usr/local/gnu/lib/g++-include/stddef.h" 1
 
 






















#pragma once



 


typedef unsigned long   size_t;
typedef long int	    ptrdiff_t;




typedef	unsigned char	wchar_t;








# 40 "/usr/local/gnu/lib/g++-include/builtin.h" 2

# 1 "/usr/local/gnu/lib/g++-include/std.h" 1
 
 























#pragma once



# 1 "/usr/local/gnu/lib/g++-include/stdio.h" 1
 
 





















 




























#pragma once


 












# 79 "/usr/local/gnu/lib/g++-include/stdio.h"





# 114 "/usr/local/gnu/lib/g++-include/stdio.h"










 






















# 156 "/usr/local/gnu/lib/g++-include/stdio.h"


 
 

 


extern  struct  _iobuf {
    int      _cnt;
    char*    _ptr;
    char*    _base;
    int _bufsiz; 
    short 	_flag;
    char 	_file;
     
} _iob[];

typedef struct _iobuf FILE;








# 193 "/usr/local/gnu/lib/g++-include/stdio.h"






























extern "C" {

int    _doprnt(const char*, void*, FILE*);
int    _doscan(FILE*, const char*, ...);
int    _filbuf(FILE*);
int    _flsbuf(unsigned, FILE*);
int    fclose(FILE*);
FILE*  fdopen(int, const char*);
int    fflush(FILE*);
int    fgetc(FILE*);
char*  fgets(char*, int, FILE *);
FILE*  fopen(const char*, const char*);
int    fprintf(FILE*, const char* ...);
int    fputc(int, FILE*);
int    fputs(const char*, FILE*);
int    fread(void*, int, int, FILE*);
FILE*  freopen(const char*, const char*, FILE*);
int    fscanf(FILE*, const char* ...);
int    fseek(FILE*, long, int);
long   ftell(FILE *);
int    fwrite(const void*, int, int, FILE*);
char*  gets(char*);
int    getw(FILE*);
int    pclose(FILE*);
FILE*  popen(const char*, const char*);
int    printf(const char* ...);
int    puts(const char*);
int    putw(int, FILE*);
int    rewind(FILE*);
int    scanf(const char* ...);
int    setbuf(FILE*, char*);
int    setbuffer(FILE*, char*, int);
int    setlinebuf(FILE*);
int    setvbuf(FILE*, char*, int, int);
int    sscanf(char*, const char* ...);
FILE*  tmpfile();
int    ungetc(int, FILE*);
int    vfprintf(FILE*, const char*, ...);

 
 

int    vprintf(const char*, ... );





char*  sprintf(char*, const char* ...);
char*  vsprintf(char*, const char*, ...);


}
















# 30 "/usr/local/gnu/lib/g++-include/std.h" 2


extern "C" {
void volatile _exit(int);
void volatile abort(void);
int       abs(int);
int       access(const char*, int);
int       acct(const char*);
unsigned  alarm(unsigned);
double    atof(const char*);
int       atoi(const char*);
long      atol(const char*);
int       bind(int, void*, int);
int       brk(void*);
int       bsearch (const void *, const void *, unsigned long, 
                   unsigned long, auto int (*ptf)(const void*, const void*));
void*     calloc(unsigned, unsigned);
void      cfree(void*);
int       chdir(const char*);
int       chmod(const char*, int);
int       chown(const char*, int, int);
long      clock(void);
int       close(int);



int       creat(const char*, unsigned long int);

char*     crypt(const char*, const char*);
char*     ctermid(char*);
char*     cuserid(char*);
double    drand48(void);
int       dup(int);
int       dup2(int, int);
int       dysize(int);
char*     ecvt(double, int, int*, int*);
char*     encrypt(char*, int);
double    erand(short*);
int       execl(const char*, const char *, ...);
int       execle(const char*, const char *, ...);
int       execlp(const char*, const char*, ...);
int       exect(const char*,  const char**,  char**);
int       execv(const char*,  const char**);
int       execve(const char*, const char**, char**);
int       execvp(const char*,  const char**);
void volatile exit(int);
int       fchmod(int, int);
int       fchown(int, int, int);
int       fcntl(int, int, ...);
char*     fcvt(double, int, int*, int*);
int       ffs(int);
int       flock(int, int);
int       fork(void);
void      free(void*);
int       fsync(int);
long      ftok(const char*, int);
int       ftruncate(int, unsigned long);
char*     gcvt(double, int, char*);
char*     getcwd(char*, int);
int       getdomainname(char*, int);
int       getdtablesize(void);
int       getegid(void);
char*     getenv(const char*);
int       geteuid(void);
int       getgid(void);
int       getgroups(int, int*);
long      gethostid(void);
int       gethostname(char*, int);
char*     getlogin(void);
int       getopt(int, const char**, const char*);
int       getpagesize(void);
char*     getpass(const char*);
int       getpgrp(void);
int       getpid(void);
int       getppid(void);
int       getpriority(int, int);
int       getpw(int, char*);
unsigned  getuid(void);
char*     getwd(char*);
char*     initstate(unsigned, char*, int);
int       ioctl(int, int, char*);
int       isatty(int);
long      jrand48(short*);
int       kill(int, int);
int       killpg(int, int);
void      lcong48(short*);
int       link(const char*, const char*);
int       listen(int, int);
int       lock(int, int, long);
long      lrand48(void);
long      lseek(int, long, int);
void*     malloc(unsigned);
unsigned  malloc_usable_size(void*);
void*     memalign(unsigned, unsigned);
void*     memccpy(void*, const void*, int, int);
void*     memchr(const void*, int, int);
int       memcmp(const void*, const void*, int);
void*     memcpy(void*, const void*, int);
void*     memset(void*, int, int);
int       mkdir(const char*, int);
int       mknod(const char*, int, int);
int       mkstemp(char*);
char*     mktemp(char*);
long      mrand48(void);
int       nice(int);
long      nrand48(short*);



int       open(const char*, int, ...);

void volatile pause(void);
void      perror(const char*);
int       pipe(int*);
int       profil(char*, int, int, int);
int       psignal(unsigned, char*);
int       ptrace(int, int, int, int);
int       putenv(const char*);
int       qsort(void*, int, unsigned, auto (*ptf)(void*,void*));
int       rand(void);
long      random(void);
int       read(int, void*, unsigned);
int       readlink(const char*, char*, int);
void*     realloc(void*, unsigned);
int       rename(const char*, const char*);
int       rmdir(const char*);               
void*     sbrk(int);              
short*    seed48(short*);
int       send(int, char*, int, int);
int       setgid(int);
int       sethostname(char*, int);
int       setkey(const char*);
int       setpgrp(int, int);
int       setpriority(int, int, int);
int       setregid(int, int);
int       setreuid(int, int);
char*     setstate(char*);
int       setuid(int);
int       sigblock(int);
int       siginterrupt(int, int);
int       sigpause(int);
int       sigsetmask(int);
unsigned  sleep(unsigned);
int       socket(int, int, int);
int       srand(int);
void      srand48(long);
void      srandom(int);
int       stime(long*);
char*     strcat(char*, const char*);
char*     strchr(const char*, int);
int       strcmp(const char*, const char*);
char*     strcpy(char*, const char*);
int       strcspn(const char*, const char*);
char*     strdup(const char*);
int       strlen(const char*);
char*     strncat(char*, const char*, int);
int       strncmp(const char*, const char*, int);
char*     strncpy(char*, const char*, int);
char*     strpbrk(const char*, const char*);
char*     strrchr(const char*, int);
int       strspn(const char*, const char*);
double    strtod(const char*, char**);
char*     strtok(char*, const char*);
long      strtol(const char*, char**, int);
void      swab(void*, void*, int);
int       symlink(const char*, const char*);
int       syscall(int, ...);
int       system(const char*);
char*     tempnam(char*, char*);
int       tgetent(char*, char*);
int       tgetnum(char*);
int       tgetflag(char*);
char*     tgetstr(char *, char **);
char*     tgoto(char*, int, int);
long      time(long*);
char*     tmpnam(char*);
int       tputs(char *, int, auto int (*)());
int       truncate(const char*, unsigned long);
char*     ttyname(int);
int       ttyslot(void);
unsigned  ualarm(unsigned, unsigned);
long      ulimit(int, long);
int       umask(int);
int       unlink(const char*);
unsigned  usleep(unsigned);
int       vadvise(int);
void*     valloc(unsigned);
int       vfork(void);
int       vhangup(void);
int       wait(int*);
int       write(int, const void*, unsigned);


}









extern "C" {
int       bcmp(const void*, const void*, int);
void      bcopy(const void*, void*, int);
void      bzero(void*, int);
char*     index(const char*, int);
char*     rindex(const char*, int);
}


extern char**   environ;
extern volatile int errno;
extern char*    sys_errlist[];
extern int      sys_nerr;                  
extern char*    optarg;
extern int      opterr;
extern int      optind;


extern "C" void* alloca(unsigned long);









# 41 "/usr/local/gnu/lib/g++-include/builtin.h" 2

# 1 "/usr/local/gnu/lib/g++-include/math.h" 1
 
 























#pragma once







# 64 "/usr/local/gnu/lib/g++-include/math.h"

extern "C" {

double  acos(double);
double  acosh(double);
double  asin(double);
double  asinh(double);
double  atan(double);
double  atan2(double, double);
double  atanh(double);
double  cbrt(double);
double  ceil(double);
double  copysign(double,double);
double  cos(double);
double  cosh(double);
double  drem(double,double);
double  erf(double);
double  erfc(double);
double  exp(double);
double  expm1(double);
double  fabs(double);
double  finite(double);
double  floor(double);
double  frexp(double, int*);
double  gamma(double);
double  hypot(double,double);
double  infnan(int);

int     isinf(double);
int     isnan(double);

double  j0(double);
double  j1(double);
double  jn(int, double);
double  ldexp(double, int);
double  lgamma(double);
double  log(double);
double  log10(double);
double  log1p(double);
double  logb(double);
double  modf(double, double*);
double  pow(double, double);
double  rint(double);
double  scalb(double, int);
double  sin(double);
double  sinh(double);
double  sqrt(double);
double  tan(double);
double  tanh(double);
double  y0(double);
double  y1(double);
double  yn(int, double);

double aint(double);
double anint(double);
int irint(double);
int nint(double);
}



 

 


struct libm_exception
{
  int type;
  char* name;
  double arg1, arg2, retval;
};








extern "C" int matherr(libm_exception*);



# 1 "/usr/local/gnu/lib/g++-include/values.h" 1
 
 























#pragma once



































# 161 "/usr/local/gnu/lib/g++-include/values.h"









# 148 "/usr/local/gnu/lib/g++-include/math.h" 2


 





 






 

















































# 42 "/usr/local/gnu/lib/g++-include/builtin.h" 2


long         gcd(long, long);
long         lg(unsigned long); 
double       pow(double, long);
long         pow(long, long);

double       start_timer();
double       return_elapsed_time(double last_time = 0.0);

char*        itoa(long x, int base = 10, int width = 0);
char*        itoa(unsigned long x, int base = 10, int width = 0);

char*        itoa(long long x, int base = 10, int width = 0);
char*        itoa(unsigned long long x, int base = 10, int width = 0);

char*        dtoa(double x, char cvt = 'g', int width = 0, int prec = 6);

char*        hex(long x, int width = 0);
char*        hex(unsigned long x, int width = 0);
char*        oct(long x, int width = 0);
char*        oct(unsigned long x, int width = 0);
char*        dec(long x, int width = 0);
char*        dec(unsigned long x, int width = 0);

char*        form(const char* fmt ...);
char*        chr(char ch, int width = 0);
char*        str(const char* s, int width = 0);

unsigned int hashpjw(const char*);
unsigned int multiplicativehash(int);
unsigned int foldhash(double);

extern void default_one_arg_error_handler(const char*);
extern void default_two_arg_error_handler(const char*, const char*);

extern two_arg_error_handler_t lib_error_handler;

extern two_arg_error_handler_t 
       set_lib_error_handler(two_arg_error_handler_t f);

 

static inline double abs(double arg) 
{
  return (arg < 0.0)? -arg : arg;
}

static inline float abs(float arg) 
{
  return (arg < 0.0)? -arg : arg;
}

static inline short abs(short arg) 
{
  return (arg < 0)? -arg : arg;
}

static inline long abs(long arg) 
{
  return (arg < 0)? -arg : arg;
}

static inline int sign(long arg)
{
  return (arg == 0) ? 0 : ( (arg > 0) ? 1 : -1 );
}

static inline int sign(double arg)
{
  return (arg == 0.0) ? 0 : ( (arg > 0.0) ? 1 : -1 );
}

static inline long sqr(long arg)
{
  return arg * arg;
}

static inline double sqr(double arg)
{
  return arg * arg;
}

static inline int even(long arg)
{
  return !(arg & 1);
}

static inline int odd(long arg)
{
  return (arg & 1);
}

static inline long lcm(long x, long y)
{
  return x / gcd(x, y) * y;
}

static inline void setbit(long& x, long b)
{
  x |= (1 << b);
}

static inline void clearbit(long& x, long b)
{
  x &= ~(1 << b);
}

static inline int testbit(long x, long b)
{
  return ((x & (1 << b)) != 0);
}

 


# 28 "/usr/local/gnu/lib/g++-include/File.h" 2




enum io_mode                     
{
  io_readonly   = 0,            
  io_writeonly  = 1,
  io_readwrite  = 2, 
  io_appendonly = 3,
  io_append     = 4,             
};

enum access_mode                 
{
  a_createonly  = 0,             
  a_create      = 1,             
  a_useonly     = 2,             
  a_use         = 3,             
};

enum state_value                 
{ 
  _good         = 0,             
  _eof          = 1,             
  _fail         = 2,             
  _bad          = 4              
};


class Filebuf;

class File
{
  friend class  Filebuf;
protected:
  FILE*         fp;               
  char*         nm;               
  char          rw;               
                                  
  state_value   state;            
  long          stat;             

  void          initialize();
  void          reinitialize(const char*);
  char         *readline (int chunk_number, char terminator);

public:
                File();
                File(const char* filename, io_mode m, access_mode a);
                File(const char* filename, const char* m);   
                File(int filedesc, io_mode m);
                File(FILE* fileptr);
                File(int sz, char* buf, io_mode m);

                ~File();

 

  File&         open(const char* filename, io_mode m, access_mode a);
  File&         open(const char* filename, const char* m);
  File&         open(int  filedesc, io_mode m);
  File&         open(FILE* fileptr);

  File&         close();
  File&         remove();

 

  int           filedesc();
  const char*   name();
  void          setname(const char* newname);
  int           iocount();

  int           rdstate();
  int           eof();
  int           fail();
  int           bad();
  int           good();

 

  int           readable();
  int           writable();
  int           is_open();

                operator void*();

 

  void          error();
  void          clear(state_value f = _good);  
  void          set(state_value f);  
  void          unset(state_value f);  
  File&         failif(int cond);
  void          check_state();

 

  File&         get(char& c);
  File&         put(char  c);
  File&         unget(char c);
  File&         putback(char c);  

 

  File&         put(const char* s);
  File&         get    (char* s, int n, char terminator = '\n');
  File&         getline(char* s, int n, char terminator = '\n');
  File&         gets   (char **s, char terminator = '\n');

 

  File&         read(void* x, int sz, int n);
  File&         write(void* x, int sz, int n);

 

  File&         form(const char* ...);
  File&         scan(const char* ...);

 

  File&         flush();
  File&         flush(char ch);  
  int           fill();          

 

  File&         seek(long pos, int seek_mode=0);  
  long          tell();

 

  File&         setbuf(int buffer_kind);  
  File&         setbuf(int size, char* buf);
  File&         raw();
};


 

extern void  verbose_File_error_handler(char*);
extern void  quiet_File_error_handler(char*);
extern void  fatal_File_error_handler(char*);
extern one_arg_error_handler_t File_error_handler;
extern one_arg_error_handler_t set_File_error_handler(one_arg_error_handler_t);

 



inline int File::filedesc()
{ 
  return   ((fp)->_file) ;
}

inline const char* File::name()
{ 
  return nm; 
}

inline int File::iocount()
{ 
  return stat; 
}

inline void File::clear(state_value flag)
{ 
  state = flag;
}

inline void File::set(state_value flag)
{ 
  state = state_value(int(state) | int(flag));
}

inline void File::unset(state_value flag)
{ 
  state = state_value(int(state) & ~int(flag));
}

inline int File::readable()
{ 
  if (fp != 0) { if (    (((fp)->_flag&   00020 )!=0) ) set(_eof); if (  (((fp)->_flag&   00040 )!=0) ) set(_bad);}
  return (state == _good && (rw & 01));
}

inline int File::writable()
{ 
  if (fp != 0 &&   (((fp)->_flag&   00040 )!=0) ) set(_bad);
  return ((int(state) & (int(_fail)|int(_bad))) == 0 && (rw & 02));
}

inline int File::is_open()
{ 
  return (fp != 0);
}


inline File& File::raw()
{ 
  return this->File::setbuf(   00004 ); 
}

inline void File::check_state()  
{
  if (fp != 0)
  {
    if (    (((fp)->_flag&   00020 )!=0) )
      set(_eof);
    else
      unset(_eof);
    if (  (((fp)->_flag&   00040 )!=0) )
      set(_bad);
  }
}

inline File& File::failif(int cond)
{ 
  if (cond) set(_fail);  return *this; 
}

inline File& File::get(char& c)
{ 
  if (readable())
  {
    int ch = (--(fp)->_cnt>=0?(int)(*(unsigned char*)(fp)->_ptr++):_filbuf(fp)) ;
    c = ch;
    failif (ch ==       (-1) );
  }
  return *this;
}

inline File& File::put(char  c) 
{ 
  return failif (!writable() ||  (--( fp)->_cnt>=0? ((int)((unsigned char)((*( fp)->_ptr++=(unsigned)(c))))):_flsbuf((unsigned)(c), fp))  ==       (-1) );
}

inline File& File::unget(char c)
{ 
  return failif(!is_open() || !(rw & 01) || ungetc(c, fp) ==       (-1) );
} 

inline File& File::putback(char c)
{ 
  return failif (!is_open() || !(rw & 01) || ungetc(c, fp) ==       (-1) );
}

inline File& File::read(void* x, int sz, int n)
{ 
  return failif (!readable() || (stat = fread(x, sz, n, fp)) != n);
} 

inline File& File::write(void* x, int sz, int n) 
{ 
  return failif (!writable() || (stat = fwrite(x, sz, n, fp)) != n);
}

inline File& File::flush()
{ 
  return failif(!is_open() || fflush(fp) ==       (-1) );
}

inline File& File::flush(char ch)
{ 
  return failif(!is_open() || _flsbuf(ch, fp) ==       (-1) );
}

inline int File::fill()
{ 
  failif(!is_open() || (stat = _filbuf(fp)) ==       (-1) );
  return stat;
}

inline File& File::seek(long pos, int seek_mode)
{ 
  return failif (!is_open() || fseek(fp, pos, seek_mode) < 0); 
}

inline long File::tell()
{ 
  failif (!is_open() || ((stat = ftell(fp)) < 0));
  return stat;
}

inline int File::rdstate()
{ 
  check_state();  return state;  
}                                

inline File::operator void*()
{ 
  check_state();  return (int(state) & (int(_bad)|int(_fail)))? 0 : this ; 
}

inline int File::eof()
{ 
  check_state(); return state & _eof; 
}

inline int File::fail()
{ 
  check_state(); return state & _fail; 
}

inline int File::bad()
{ 
  check_state(); return state & _bad; 
}

inline int File::good()
{ 
  check_state(); return rdstate() == _good; 
}


 


# 34 "/usr/local/gnu/lib/g++-include/stream.h" 2

# 1 "/usr/local/gnu/lib/g++-include/streambuf.h" 1
 
 






















#pragma once


 










 









enum open_mode  
{ 
  input=0, 
  output=1, 
  append=2 
}; 

class streambuf
{
public:
  char*       base;           
  char*       pptr;           
  char*       gptr;           
  char*       eptr;           

  char        alloc;          

              streambuf();
              streambuf(char* buf, int buflen);
 
  virtual    ~streambuf();

  int         doallocate();
  int         allocate();


  int         must_overflow(int ch);  

  virtual int overflow(int c =       (-1) );  
  virtual int underflow();            

  int         sgetc();           
  int         snextc();          
  void        stossc();          

  int         sputback(char);    

  int         sputc(int c =       (-1) );  

  virtual streambuf*  setbuf(char* buf, int buflen, int preloaded_count = 0);
                                 

 

  int         sputs(const char* s);            
  int         sputsn(const char* s, int len);  

  virtual const char* name();


  virtual streambuf*  open(const char* name, open_mode m);
  virtual streambuf*  open(const char* filename, io_mode m, access_mode a);
  virtual streambuf*  open(const char* filename, const char* m);
  virtual streambuf*  open(int  filedesc, io_mode m);
  virtual streambuf*  open(FILE* fileptr);

  virtual int         is_open();
  virtual int         close();

  virtual void        error();
};


class filebuf: public streambuf
{
public:
  int         fd;
  char        opened;

  int         overflow(int c =       (-1) );
  int         underflow();

              filebuf();
              filebuf(int newfd);
              filebuf(int newfd, char* buf, int buflen);

             ~filebuf();

  streambuf*  open(const char* name, open_mode m);
  int         is_open();
  int         close();
};

class Filebuf: public streambuf  
{
public:
  File*       Fp;

  void        init_streambuf_ptrs();

  int         overflow(int c =       (-1) );
  int         underflow();

              Filebuf();
              Filebuf(const char* filename, io_mode m, access_mode a);
              Filebuf(const char* filename, const char* m);   
              Filebuf(int filedesc, io_mode m);
              Filebuf(FILE* fileptr);
  
             ~Filebuf();

  const char* name();
  streambuf*  setbuf(char* buf, int buflen, int preloaded_count = 0);

  streambuf*  open(const char* filename, io_mode m, access_mode a);
  streambuf*  open(const char* filename, const char* m);
  streambuf*  open(int  filedesc, io_mode m);
  streambuf*  open(FILE* fileptr);

  int         is_open();
  int         close();

  void        error();
};


inline int streambuf::must_overflow(int ch)
{

  return pptr >= eptr || ch == '\n';



}


inline int streambuf::allocate()
{
  return (base == 0)? doallocate() : 0; 
}

inline int streambuf::sgetc()
{
  return (gptr >= pptr)? underflow() : int(*gptr);
}


inline int streambuf::snextc()
{
  ++gptr;
  return (gptr >= pptr)? underflow() : int(*gptr);
}


inline void streambuf::stossc()
{
  if (gptr >= pptr) underflow(); else gptr++;
}


inline int streambuf::sputback(char ch)
{
  return (gptr > base)? (*--gptr = ch) :       (-1) ;
}

inline int streambuf::sputc(int ch)
{
  return must_overflow(ch)? overflow(ch) :  (*pptr++ = char(ch));
}


# 35 "/usr/local/gnu/lib/g++-include/stream.h" 2


class whitespace                 
{                                
  char filler;                     
};

class istream;

class ostream
{
  friend class istream;
protected:
  streambuf*    bp;
  state_value   state;            
  char          ownbuf;           
  
public:
                ostream(const char* filename, io_mode m, access_mode a);
                ostream(const char* filename, const char* m);
                ostream(int filedesc, io_mode m);
                ostream(FILE* fileptr);
                ostream(int sz, char* buf);
                ostream(int filedesc, char* buf, int buflen);
                ostream(int filedesc);
                ostream(streambuf* s);

               ~ostream();

  ostream&      open(const char* filename, io_mode m, access_mode a);
  ostream&      open(const char* filename, const char* m);
  ostream&      open(int  filedesc, io_mode m);
  ostream&      open(FILE* fileptr);
  ostream&      open(const char* filenam, open_mode m);

  ostream&      close();
  ostream&      flush();

 

  int           rdstate();
  int           eof();
  int           fail();
  int           bad();
  int           good();

 

  int           readable();
  int           writable();
  int           is_open();

                operator void*();
  int           operator !();

  const char*   name();

  char*         bufptr();

 

  void          error();
  void          clear(state_value f = _good);  
  void          set(state_value f);  
  void          unset(state_value);  
  ostream&      failif(int cond);

 

  ostream&      put(char  c);
  ostream&      put(const char* s);
  ostream&      put(const char* s, int slen);
           
 

  ostream&      form(const char* fmt, ...);           

  ostream&      operator << (short  n);
  ostream&      operator << (unsigned short n);
  ostream&      operator << (int    n);
  ostream&      operator << (unsigned int n);
  ostream&      operator << (long   n);
  ostream&      operator << (unsigned long n);

  ostream&      operator << (long long n);
  ostream&      operator << (unsigned long long n);

  ostream&      operator << (float  n);
  ostream&      operator << (double n);
  ostream&      operator << (const char* s);


  ostream&      operator << (char   c);


};


class istream
{
  friend void   eatwhite(istream& s);
protected:
  streambuf*    bp;
  state_value   state;            
  ostream*      tied_to;
  char          skipws;
  char          ownbuf;
  void          _flush();
  char*         readline (int chunk_number, char terminator);
  
public:
                istream(const char* filename, io_mode m, access_mode a, 
                        int sk=1, ostream* t = 0);
                istream(const char* filename, const char* m, 
                        int sk=1, ostream* t = 0);
                istream(int filedesc, io_mode m, int sk=1, ostream* t = 0);
                istream(FILE* fileptr, int sk=1, ostream* t = 0);
                istream(int sz, char* buf, int sk=1, ostream* t = 0);
                istream(int filedesc, int sk=1, ostream* t = 0);
                istream(int filedesc, char* buf, int buflen, 
                        int sk=1, ostream* t = 0);
                istream(streambuf* s, int sk=1, ostream* t = 0);

               ~istream();

  istream&      open(const char* filename, io_mode m, access_mode a);
  istream&      open(const char* filename, const char* m);
  istream&      open(int  filedesc, io_mode m);
  istream&      open(FILE* fileptr);
  istream&      open(const char* filenam, open_mode m);

  istream&      close();

  ostream*      tie(ostream* s);
  int           skip(int);

 

  int           rdstate();
  int           eof();
  int           fail();
  int           bad();
  int           good();

 

  int           readable();
  int           writable();
  int           is_open();

                operator void*();
  int           operator !();

  const char*   name();

  char*         bufptr();

 

  void          error();
  void          clear(state_value f = _good);  
  void          set(state_value f);  
  void          unset(state_value f);  
  istream&      failif(int cond);

 

  istream&      get(char& c);
  istream&      unget(char c);
  istream&      putback(char c);  

  istream&      get    (char* s, int n, char terminator = '\n');
  istream&      getline(char* s, int n, char terminator = '\n');
  istream&      gets   (char **s, char terminator = '\n');


  istream&      operator >> (char&   c);
  istream&      operator >> (short&  n);
  istream&      operator >> (unsigned short& n);
  istream&      operator >> (int&    n);
  istream&      operator >> (unsigned int& n);
  istream&      operator >> (long&   n);
  istream&      operator >> (unsigned long& n);

  istream&      operator >> (long long& n);
  istream&      operator >> (unsigned long long& n);

  istream&      operator >> (float&  n);
  istream&      operator >> (double& n);
  istream&      operator >> (char*   s);
  istream&      operator >> (whitespace& w);
};

 

extern istream  cin;              
extern ostream  cout;             
extern ostream  cerr;             

extern whitespace WS;             


inline void ostream::clear(state_value flag)
{
  state = flag;
}

inline void ostream::set(state_value flag)
{
  state = state_value(int(state) | int(flag));
}

inline void ostream::unset(state_value flag)
{
  state = state_value(int(state) & ~int(flag));
}

inline int ostream::rdstate()
{
  return int(state);
}

inline int ostream::good()
{
  return state == _good;
}

inline int ostream::eof()
{
  return int(state) & int(_eof);
}

inline int ostream::fail()
{
  return int(state) & int(_fail);
}

inline int ostream::bad()
{
  return int(state) & int(_bad);
}

inline ostream::operator void*()
{
  return (state == _good)? this : 0;
}

inline int ostream::operator !()
{
  return (state != _good);
}

inline ostream& ostream::failif(int cond)
{
  if (cond) set(_fail); return *this;
}

inline int ostream::is_open()
{
  return bp->is_open();
}

inline int ostream::readable()
{
  return 0;
}

inline int ostream::writable()
{
  return (bp != 0) && (state == _good);
}


inline char* ostream::bufptr()
{
  return bp->base;
}

inline ostream& ostream::flush()
{
  bp->overflow(); return *this;
}

inline ostream& ostream::close()
{
  bp->overflow(); bp->close();  return *this;
}

inline ostream& ostream::put(char ch)
{
  return failif((state != _good) || bp->sputc(ch) ==       (-1) );
}


inline ostream& ostream::operator << (char ch)
{
  return failif((state != _good) || bp->sputc(ch) ==       (-1) );
}


inline ostream& ostream::put(const char* s)
{
  return failif((state != _good) || bp->sputs(s) ==       (-1) );
}

inline ostream& ostream::put(const char* s, int len)
{
  return failif((state != _good) || bp->sputsn(s, len) ==       (-1) );
}

inline ostream& ostream::operator << (const char* s)
{
  return failif((state != _good) || bp->sputs(s) ==       (-1) );
}


  

 

inline void istream::clear(state_value flag)
{
  state = flag;
}

inline void istream::set(state_value flag)
{
  state = state_value(int(state) | int(flag));
}

inline void istream::unset(state_value flag)
{
  state = state_value(int(state) & ~int(flag));
}

inline int istream::rdstate()
{
  return int(state);
}

inline int istream::good()
{
  return state == _good;
}

inline int istream::eof()
{
  return int(state) & int(_eof);
}

inline int istream::fail()
{
  return int(state) & int(_fail);
}

inline int istream::bad()
{
  return int(state) & int(_bad);
}

inline istream::operator void*()
{
  return (state == _good)? this : 0;
}

inline int istream::operator !()
{
  return (state != _good);
}

inline istream& istream::failif(int cond)
{
  if (cond) set(_fail); return *this;
}

inline int istream::is_open()
{
  return bp->is_open();
}

inline int istream::readable()
{
  return (bp != 0) && (bp->is_open()) && (state == _good);
}

inline int istream::writable()
{
  return 0;
}

inline void istream::_flush()
{
  if(tied_to != 0) tied_to->flush();
}


inline char* istream::bufptr()
{
  return bp->base;
}


inline istream& istream::close()
{
  bp->close();  return *this;
}


inline int istream::skip(int sk)
{
  int was = skipws; skipws = sk; return was;
}

inline ostream* istream::tie(ostream* s)
{
  ostream* was = tied_to; tied_to = s; return was;
}

inline istream& istream::unget(char c)
{
  if (bp->sputback(c) ==       (-1) ) set(_fail); return *this;
}

inline istream& istream::putback(char c)
{
  if (bp->sputback(c) ==       (-1) ) set(_fail); return *this;
}

inline void eatwhite(istream& s)
{
  s >> WS;
}


# 1 "test.C" 2


class childptr;
typedef childptr* (childptr::*make_child_ptr)();  
                                                  
                                                  

class childptr
{
 public:
    childptr();                       
    childptr* make_child();           
    childptr* make_child2();          

    make_child_ptr m_c_ptr;           

    };

 
childptr* childptr::make_child()
{
    childptr* newchild;

    newchild = new childptr;
    cout << "childptr::make_child returning " << (int)newchild << "\n";
    return (newchild);
    }



 
childptr* childptr::make_child2()
{
    (*m_c_ptr)();  
                          
    }




childptr::childptr()    
{
    m_c_ptr = make_child;
    }



main()
{
    childptr parent;
    childptr* parent2;
    childptr* child;

    
     
    child = parent.make_child();
    cout << "parent.make_child yielded: " << (int)child << "\n\n";

     
    parent2 = new childptr;
    child = parent2->make_child();
    cout << "parent->make_child() yielded: " << (int)child << "\n\n";

     
    child = parent2->make_child2();
    cout << "parent->make_child2() yielded: " << (int)child << "\n\n";

    }

    

tiemann@arkesden.eng.sun.com (Michael Tiemann) (02/12/90)

    I have a code fragment which executes differently on a Sun 4 and a
    Sun 3.  The Sun 3 version executes as intended; the Sun 4 version
    does not.

    The code has a method, make_child, which I invoke three different
    ways in this fragment.  On a Sun 4, the third technique returns
    a different answer from the first two.  On the Sun 3, all 3 techniques
    return the same value.  The technique that fails is the case where
    the method is called via a pointer.  When the technique fails, the
    returned value is the value of address of the object, i.e. "this"
    (although my code fragment doesn't print this to demonstrate it).

What you have found is not a bug in GNU C++, but a bug in your
program.  Since I have seen others bitten before, I am posting it to
the net.  Had you run GNU C++ with -Wall or -Wreturn-type, the
compiler would have found it for you.

    Also, to be honest, I'm not sure that the compilation of this code is
    really correct in either case; I appear unable to treat the ptr in the
    same manner as a function name as my copy of Lippmann indicates; i.e.
    in the code below you will find the line:

	      (*m_c_ptr)();

    My reading of Lippman indicates that I should be able to use:

	      m_c_ptr();

I consider it bad practice to auto-dereference pointer-to-member
functions.  It is better that people see that they are really
pointers.  Otherwise, someone unfamiliar with the code could waste
time looking for the definition of m_c_ptr as a function.

    but this results in compile time errors.  I have also had troubles
    using the pointer from outside the class (i.e. I haven't been
    able to get anything like   (parent->*m_child_ptr)()   through the
    compiler) so I created the make_child2 method.  I don't believe
    that this should be necessary.

Probably another misunderstanding.  If you want to use m_c_ptr in this
way, you have to do this:

	(parent->*(parent->m_c_ptr))()

You are not the first to run into this problem.

    Here is the source, as produced by the command "g++ -E" [edited by MDT]:

extern "C" void printf (char *, ...);
class childptr;
typedef childptr* (childptr::*make_child_ptr)();
class childptr
{
 public:
  childptr();
  childptr* make_child();
  childptr* make_child2();
  make_child_ptr m_c_ptr;
};
childptr* childptr::make_child()
{
  childptr* newchild;
  newchild = new childptr;
  printf ("childptr::make_child returning %d\n", (int)newchild);
  return (newchild);
}
childptr* childptr::make_child2()
{
  (*m_c_ptr)();
//^^^^^^^^^^^^^ bug: should be return (*m_c_ptr)();
}
childptr::childptr()
{
  m_c_ptr = make_child;
}
main()
{
  childptr parent;
  childptr* parent2;
  childptr* child;
  child = parent.make_child();
  printf ("parent.make_child yielded: %d\n\n", (int)child);
  parent2 = new childptr;
  child = parent2->make_child();
  printf ("parent->make_child() yielded: %d\n\n", (int)child);
  child = parent2->make_child2();
  printf ("parent->make_child2() yielded: %d\n\n", (int)child);
}