From: gb@cs.purdue.edu (Gerald Baumgartner)
Subject: G++ 2.2.2: possible bug in memory (de)allocation in cp-decl.c
Organization: Department of Computer Science, Purdue University
Distribution: gnu
Date: Fri, 4 Sep 1992 20:42:01 GMT

I was running cc1plus in xcodecenter with cp-decl.c loaded in source
and got the following warning message in `finish_function':

	cp-decl.c:10165, W#30, Using a pointer
		( current_function_return_value )
		which points into freed memory,
		address <0x89c918>.

The error happened when compiling iostream.h.

Afterwards the compilation proceeded normally, and the executable worked
correctly (it was only a `Hello World.' program).

I tried to cut down the input file as much as possible, it's included
at the end of the message.  The input is a part of iostream.h after
preprocessing.  Some classes have been deleted to shorten it.  When
trying to delete more (even classes that don't seem to be used, such
as backupbuf), the error doesn't occur anymore.

Here's how to reproduce it:

   - Load cc1plus into xcodecenter.  I used the Makefile goal

	ccenter:
		#use . $(srcdir) $(srcdir)/config
		#setopt load_flags $(LDFLAGS) $(INCLUDES)
		#setopt program_name cc1plus
		#setopt tab_stop 8
		ranlib $(LIBGCC2)
		#load $(CPLUS_OBJS) $(OBJS) $(LIBGCC2) $(LIBS)
		#link

   - `unload cp-decl.o' and `load cp-decl.c'.

   - `run -quiet test.i', where test.i is the test file from below

   - First there a several seemingly harmless warning messages:

	cp-decl.c:8753, Using a bad pointer in a comparison
		(operation '==').
		Pointer = 0x6, low bound = 0x0, high bound = 0x0.
	cp-decl.c:4479, Retrieving a <pointer> from allocated
		data at <0x80886c>.
		The object stored there is a <int>.

   - Then there's the message mentioned above:

	cp-decl.c:10165, W#30, Using a pointer
		( current_function_return_value )
		which points into freed memory,
		address <0x89c918>.

   - At that point looking at the value of `input_filename' and `lineno'
     tells us that we are compiling in line 131 of iostream.h.

   - With YYDEBUG and SPEW_DEBUG enabled and `spew_debug = 1', those
     are the tokens read right before the error occurs:

                ## 3445 ##<262:TYPESPEC> 
                ## 3446 ##<258:IDENTIFIER> 
                ## 3447 ##<61: = > 
                ## 3448 ##<258:IDENTIFIER> 
                ## 3449 ##<318:POINTSAT> 
                ## 3450 ##<258:IDENTIFIER> 
                ## 3451 ##<298:LEFT_RIGHT> 
                ## 3452 ##<59: ; > 
                ## 3453 ##<269:IF> 
                ## 3454 ##<40: ( > 
                ## 3455 ##<258:IDENTIFIER> 
                ## 3456 ##<309:EQCOMPARE> 
                ## 3457 ##<40: ( > 
                ## 3458 ##<45: - > 
                ## 3459 ##<264:CONSTANT> 
                ## 3460 ##<41: ) > 
                ## 3461 ##<41: ) > 
                ## 3462 ##<258:IDENTIFIER> 
                ## 3463 ##<40: ( > 
                ## 3464 ##<259:TYPENAME> 
                ## 3465 ##<300:SCOPE> 
                ## 3466 ##<258:IDENTIFIER> 
                ## 3467 ##<41: ) > 
                ## 3468 ##<59: ; > 
                ## 3469 ##<279:RETURN> 
                ## 3470 ##<258:IDENTIFIER> 
                ## 3471 ##<59: ; > 
                ## 3472 ##<125: } > 
                ## 3473 ##<339:END_OF_SAVED_INPUT> 
                ## 3474 ##<123: { > 
                ## 3475 ##<279:RETURN> 
                ## 3476 ##<258:IDENTIFIER> 
                ## 3477 ##<59: ; > 
                ## 3478 ##<125: } > 

   - If compilation is continued, these are the next few tokens being
     read:

                ## 3479 ##<339:END_OF_SAVED_INPUT> 
                ## 3480 ##<123: { > 
                ## 3481 ##<269:IF> 
                ## 3482 ##<40: ( > 
                ## 3483 ##<258:IDENTIFIER> 
                ## 3484 ##<298:LEFT_RIGHT> 
                ## 3485 ##<307:ANDAND> 
                ## 3486 ##<258:IDENTIFIER> 
                ## 3487 ##<318:POINTSAT> 
                ## 3488 ##<258:IDENTIFIER> 
                ## 3489 ##<40: ( > 
                ## 3490 ##<258:IDENTIFIER> 
                ## 3491 ##<41: ) > 
                ## 3492 ##<309:EQCOMPARE> 
                ## 3493 ##<40: ( > 
                ## 3494 ##<45: - > 
                ## 3495 ##<264:CONSTANT> 
                ## 3496 ##<41: ) > 
                ## 3497 ##<41: ) > 
                ## 3498 ##<258:IDENTIFIER> 
                ## 3499 ##<40: ( > 
                ## 3500 ##<259:TYPENAME> 
                ## 3501 ##<300:SCOPE> 
                ## 3502 ##<258:IDENTIFIER> 
                ## 3503 ##<41: ) > 
                ## 3504 ##<59: ; > 

The problem could also be in xcodecenter.  But since the error is
reported also when other files are loaded in source (cp-type2.c,
cp-typeck.c, cp-parse.c, cp-spew.c) or when loading a different
version of cc1plus (which contains some of my own additions), I assume
that the problem is in cc1plus and not xcodecenter.

Here's the test file test.i.  Line 131 of iostream.h is line 362 of test.i.
The error happens when compiling the body of istream::gcount.

--Gerald

-----%<-----(cut here)--------------------------------------------------
# 1 "test.cc"
# 1 "/homes/gb/lib/g++-include/iostream.h" 1 3
#pragma interface
# 1 "/homes/gb/lib/g++-include/streambuf.h" 1 3
#pragma interface
# 1 "/homes/gb/lib/g++-include/_G_config.h" 1 3
# 23 "/homes/gb/lib/g++-include/streambuf.h" 2 3

class ostream; class streambuf; class backupbuf;

extern "C" int __underflow(streambuf*);
extern "C" int __overflow(streambuf*, int);

typedef long  streamoff;
typedef long  streampos;  

typedef unsigned long __fmtflags;
typedef unsigned char __iostate;

struct _ios_fields {  
    streambuf *_strbuf;
    ostream* _tie;
    int _width;
    __fmtflags _flags;
    char _fill;
    __iostate _state;
    unsigned short _precision;
};

# 87 "/homes/gb/lib/g++-include/streambuf.h" 3

class ios : public _ios_fields {
  public:
    typedef __fmtflags fmtflags;
    typedef __iostate iostate;
    enum io_state {
	goodbit = 0 ,
	eofbit = 1 ,
	failbit = 2 ,
	badbit = 4  };
    enum open_mode {
	in = 1 ,
	out = 2 ,
	ate = 4 ,
	app = 8 ,
	trunc = 16 ,
	nocreate = 32 ,
	noreplace = 64  };
    enum seek_dir { beg, cur, end};
    enum { skipws=01, left=02, right=04, internal=010,
	   dec=020, oct=040, hex=0100,
	   showbase=0200, showpoint=0400, uppercase=01000, showpos=02000,
	   scientific=04000, fixed=0100000, unitbuf=020000, stdio=040000,
	   dont_close=0x80000000  
	   };
    ostream* tie() const { return _tie; }
    ostream* tie(ostream* val) { ostream* save=_tie; _tie=val; return save; }
    char fill() const { return _fill; }
    char fill(char newf) { char oldf = _fill; _fill = newf; return oldf; }
    fmtflags flags() const { return _flags; }
    fmtflags flags(fmtflags new_val) {
	fmtflags old_val = _flags; _flags = new_val; return old_val; }
    int precision() const { return _precision; }
    int precision(int newp) {
	unsigned short oldp = _precision; _precision = (unsigned short)newp;
	return oldp; }
    fmtflags setf(fmtflags val) {
	fmtflags oldbits = _flags;
	_flags |= val; return oldbits; }
    fmtflags setf(fmtflags val, fmtflags mask) {
	fmtflags oldbits = _flags;
	_flags = (_flags & ~mask) | (val & mask); return oldbits; }
    fmtflags unsetf(fmtflags mask) {
	fmtflags oldbits = _flags & mask;
	_flags &= ~mask; return oldbits; }
    int width() const { return _width; }
    int width(int val) { int save = _width; _width = val; return save; }
    static const unsigned long basefield;
    static const unsigned long adjustfield;
    static const unsigned long floatfield;
    streambuf* rdbuf() const { return _strbuf; }
    void clear(iostate state = 0) { _state = state; }
    void set(iostate flag) { _state |= flag; }  
    int good() const { return _state == 0; }
    int eof() const { return _state & ios::eofbit; }
    int fail() const { return _state & (ios::badbit|ios::failbit); }
    int bad() const { return _state & ios::badbit; }
    int rdstate() const { return _state; }
    operator void*() const { return fail() ? (void*)0 : (void*)(-1); }
    int operator!() const { return fail(); }
  protected:
    ios(streambuf* sb = 0, ostream* tie = 0);
    ~ios();
};

typedef ios::seek_dir _seek_dir;

class streammarker {
    friend class streambuf;
    friend int __underflow(streambuf*);
    struct streammarker *_next;   
    streambuf *_sbuf;  
    streampos _spos;  
    void set_streampos(streampos sp) { _spos = sp; }
    void set_offset(int offset) { _pos = offset; _spos = (streampos)(-2); }
    int _pos;
  public:
    streammarker(streambuf *sb);
    ~streammarker();
    int saving() { return  _spos == -2; }
    int delta(streammarker&);
    int delta();
};

struct __streambuf {
    int _flags;		 
    char* _gptr;	 
    char* _egptr;	 
    char* _eback;	 
    char* _pbase;	 
    char* _pptr;	 
    char* _epptr;	 
    char* _base;	 
    char* _ebuf;	 
    struct streambuf *_chain;
    friend class streammarker;
    char *_other_gbase;  
    char *_aux_limit;   
    char *_other_egptr;  
    streammarker *_markers;
    unsigned short _cur_column;
    char _unused;
    char _shortbuf[1];
};

extern unsigned __adjust_column(unsigned start, const char *line, int count);

struct streambuf : private __streambuf {
    friend class ios;
    friend class istream;
    friend class ostream;
    friend class streammarker;
    friend int __underflow(streambuf*);
  protected:
    static streambuf* _list_all;  
    streambuf*& xchain() { return _chain; }
    void _un_link();
    void _link_in();
    char* gptr() const { return _gptr; }
    char* pptr() const { return _pptr; }
    char* egptr() const { return _egptr; }
    char* epptr() const { return _epptr; }
    char* pbase() const { return _pbase; }
    char* eback() const { return _eback; }
    char* ebuf() const { return _ebuf; }
    char* base() const { return _base; }
    void xput_char(char c) { *_pptr++ = c; }
    int xflags() { return _flags; }
    int xflags(int f) { int fl = _flags; _flags = f; return fl; }
    void xsetflags(int f) { _flags |= f; }
    void xsetflags(int f, int mask) { _flags = (_flags & ~mask) | (f & mask); }
    void gbump(int n) { _gptr += n; }
    void pbump(int n) { _pptr += n; }
    void setb(char* b, char* eb, int a=0);
    void setp(char* p, char* ep) { _pbase=_pptr=p; _epptr=ep; }
    void setg(char* eb, char* g, char *eg) { _eback=eb; _gptr=g; _egptr=eg; }
    char *shortbuf() { return _shortbuf; }
    int in_backup() { return _flags & 0x100 ; }
    char *Gbase() { return in_backup() ? _other_gbase : _eback; }
    char *eGptr() { return in_backup() ? _other_egptr : _egptr; }
    char *Bbase() { return in_backup() ? _eback : _other_gbase; }
    char *Bptr() { return _aux_limit; }
    char *eBptr() { return in_backup() ? _egptr : _other_egptr; }
    char *Nbase() { return _other_gbase; }
    char *eNptr() { return _other_egptr; }
    int have_backup() { return _other_gbase != ((void*)0) ; }
    int have_markers() { return _markers != ((void*)0) ; }
    int _least_marker();
    void switch_to_main_get_area();
    void switch_to_backup_area();
    void free_backup_area();
    void unsave_markers();  
    int put_mode() { return _flags & 0x800 ; }
    int switch_to_get_mode();
    streambuf(int flags=0);
  public:
    static int flush_all();
    static void flush_all_linebuffered();  
    virtual int underflow() = 0;  
    virtual int overflow(int c = (-1) ) = 0;  
    virtual int doallocate();
    virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out);
    virtual streampos seekpos(streampos pos, int mode = ios::in|ios::out);
    int seekmark(streammarker& mark, int delta = 0);
    int sputbackc(char c);
    int sungetc();
    virtual ~streambuf();
    int unbuffered() { return _flags & 2  ? 1 : 0; }
    int linebuffered() { return _flags & 0x200  ? 1 : 0; }
    void unbuffered(int i)
	{ if (i) _flags |= 2 ; else _flags &= ~2 ; }
    void linebuffered(int i)
	{ if (i) _flags |= 0x200 ; else _flags &= ~0x200 ; }
    int allocate() {  
	if (base() || unbuffered()) return 0;
	else return doallocate(); }
    void allocbuf() { if (base() == ((void*)0) ) doallocbuf(); }
    void doallocbuf();
    virtual int sync();
    virtual int pbackfail(int c);
    virtual int ungetfail();
    virtual streambuf* setbuf(char* p, int len);
    int in_avail() { return _egptr - _gptr; }
    int out_waiting() { return _pptr - _pbase; }
    virtual int sputn(const char* s, int n);
    int padn(char pad, int n);  
    virtual int sgetn(char* s, int n);
    int ignore(int);
    virtual int get_column();
    virtual int set_column(int);
    long sgetline(char* buf, int  n, char delim, int putback_delim);
    int sbumpc() {
	if (_gptr >= _egptr && __underflow(this) == (-1) ) return (-1) ;
	else return *(unsigned char*)_gptr++; }
    int sgetc() {
	if (_gptr >= _egptr && __underflow(this) == (-1) ) return (-1) ;
	else return *(unsigned char*)_gptr; }
    int snextc() {
	if (++_gptr >= _egptr && __underflow(this) == (-1) ) return (-1) ;
	else return *(unsigned char*)_gptr; }
    int sputc(int c) {
	if (_pptr >= _epptr) return __overflow(this, (unsigned char)c);
	return *_pptr++ = c, (unsigned char)c; }
    void stossc() { if (_gptr < _egptr) _gptr++; }
    int vscan(char const *fmt0, char *  ap, ios::iostate* = ((void*)0) );
    int vform(char const *fmt0, char *  ap);
};

class backupbuf : public streambuf {
    friend class streammarker;
  protected:
    backupbuf(int flags=0) : streambuf(flags|0x4000 ) { }
  public:
    virtual int pbackfail(int c);
    virtual int underflow();
    virtual int overflow(int c = (-1) );
};

inline ios::ios(streambuf* sb  , ostream* tie  ) {
		_tie = tie; _strbuf=sb; _state=0; _width=0; _fill=' ';
		_flags=ios::skipws; _precision=6; }
inline ios::~ios() {
    if (!(_flags & (unsigned int)ios::dont_close)) delete _strbuf; }

# 25 "/homes/gb/lib/g++-include/iostream.h" 2 3

class istream; class ostream;
typedef ios& (*__manip)(ios&);
typedef istream& (*__imanip)(istream&);
typedef ostream& (*__omanip)(ostream&);

extern istream& ws(istream& ins);
extern ostream& flush(ostream& outs);
extern ostream& endl(ostream& outs);
extern ostream& ends(ostream& outs);

class ostream : public ios
{
    void do_osfx();
  public:
    ostream() { }
    ostream(streambuf* sb, ostream* tied=((void*)0) );
    int opfx() { if (!good()) return 0; if (_tie) _tie->flush(); return 1; }
    void osfx() { if (flags() & (ios::unitbuf|ios::stdio))
		      do_osfx(); }
    streambuf* ostreambuf() const { return _strbuf; }
    ostream& flush();
    ostream& put(char c) { _strbuf->sputc(c); return *this; }
    ostream& write(const char *s, int n);
    ostream& write(const unsigned char *s, int n) { return write((const char*)s, n);}

    ostream& write(const signed char *s, int n) { return write((const char*)s, n);}
    ostream& write(const void *s, int n) { return write((const char*)s, n);}
    ostream& seekp(streampos);
    ostream& seekp(streamoff, _seek_dir);
    ostream& form(const char *format ...);
    ostream& vform(const char *format, char *  args);
};

extern ostream& operator<<(ostream&, char c);
inline ostream& operator<<(ostream& os, unsigned char c)
{ return os << (char)c; }

extern ostream& operator<<(ostream &os, signed char c) { return os << (char)c;}

extern ostream& operator<<(ostream&, const char *s);
inline ostream& operator<<(ostream& os, const unsigned char *s)
{ return os << (const char*)s; }

inline ostream& operator<<(ostream& os, const signed char *s)
{ return os << (const char*)s; }

extern ostream& operator<<(ostream&, void *p);
extern ostream& operator<<(ostream&, int n);
extern ostream& operator<<(ostream&, long n);
extern ostream& operator<<(ostream&, unsigned int n);
extern ostream& operator<<(ostream&, unsigned long n);
inline ostream& operator<<(ostream& os, short n) {return os << (int)n;}
inline ostream& operator<<(ostream& os, unsigned short n)
{return os << (unsigned int)n;}
extern ostream& operator<<(ostream&, float n);
extern ostream& operator<<(ostream&, double n);
inline ostream& operator<<(ostream& os, __omanip func) { return (*func)(os); }
inline ostream& operator<<(ostream& os, __manip func) {(*func)(os); return os;}
extern ostream& operator<<(ostream&, streambuf*);

class istream : public ios
{
    int  _gcount;

    int _skip_ws();
  public:
    istream() { _gcount = 0; }
    istream(streambuf* sb, ostream*tied=((void*)0) );
    streambuf* istreambuf() const { return _strbuf; }
    istream& get(char& c);
    istream& get(unsigned char& c) { return get((char&)c); }
    istream& get(signed char& c)  { return get((char&)c); }
    istream& read(char *ptr, int n);
    istream& read(unsigned char *ptr, int n) { return read((char*)ptr, n); }
    istream& read(signed char *ptr, int n) { return read((char*)ptr, n); }
    istream& read(void *ptr, int n) { return read((char*)ptr, n); }
    istream& getline(char* ptr, int len, char delim = '\n');
    istream& get(char* ptr, int len, char delim = '\n');
    istream& get(streambuf& sb, char delim = '\n');
    istream& gets(char **s, char delim = '\n');
    int ipfx(int need) {
	if (!good()) { set(ios::failbit); return 0; }
	if (_tie && (need == 0 || rdbuf()->in_avail() < need)) _tie->flush();
	if (!need && (flags() & ios::skipws)) return _skip_ws();
	return 1;
    }
    int ipfx0() {  
	if (!good()) { set(ios::failbit); return 0; }
	if (_tie) _tie->flush();
	if (flags() & ios::skipws) return _skip_ws();
	return 1;
    }
    int ipfx1() {  
	if (!good()) { set(ios::failbit); return 0; }
	if (_tie && rdbuf()->in_avail() == 0) _tie->flush();
	return 1;
    }
    int get() { if (!ipfx1()) return (-1) ;
		int ch = _strbuf->sbumpc();
		if (ch == (-1) ) set(ios::eofbit);
		return ch; }
    int peek() { if (!ipfx1()) return (-1) ;
		int ch = _strbuf->sgetc();
		if (ch == (-1) ) set(ios::eofbit);
		return ch; }
    int  gcount() { return _gcount; }
    istream& ignore(int n=1, int delim = (-1) );
    istream& seekg(streampos);
    istream& seekg(streamoff, _seek_dir);
    streampos tellg();
    istream& putback(char ch) {
	if (good() && _strbuf->sputbackc(ch) == (-1) ) clear(ios::badbit);
	return *this;}
    istream& unget() {
	if (good() && _strbuf->sungetc() == (-1) ) clear(ios::badbit);
	return *this;}
    istream& scan(const char *format ...);
    istream& vscan(const char *format, char *  args);
};

Newsgroups: gnu.g++.bug