[gnu.g++.bug] Two G++ bugs

schmidt@zola.ics.uci.edu (Doug Schmidt) (08/22/89)

In article <8908211701.AA23169@Neon.Stanford.EDU>, robert@NEON (James R. Kennedy) writes:
>The following illustrates two bugs in g++ version 1.36.0- (version as
>of 2:33 AM PDT, Monday 21 Aug). Sun4, SunOS 4.0.
>
>Bug 1: Variable-length array parameters broken (see p. 46 of manual).
>Bug 2: Segmentation violation rears its ugly head again.
>
>------------------ begin winge.cc -----------------------
>#include <stream.h>
>
>void gripe(char c[a], int a)
>
>{
>cout << c[0];
>}
>
>
>main()
>
>{
>gripe("T", 2);
>}
>------------------- end winge.cc -------------------------

Several points:

1.  Even if variable-length array parameters *did* work in G++, you've
    incorrectly used them in function `gripe'.  Variable length array
    parameters are actually a GCC extension, and your example would
    need to be re-written as:

    void gripe(int a, char c[a]) { /* ... */ }

    to work there.  Note that you must declare the `a' BEFORE trying
    to use it as the size-specifier in GCC.  If you think about how
    this is parsed (i.e., left-to-right) the semantics make sense.

2.  This extension does not yet work with G++.  Upon reflection,
    you'll probably see the dilemma facing C++ (that does *not* face
    GCC).  The problem is default parameters.  For example, consider
    the following cases:
    
    const int a = 10;

    /* Should print 10, regardless of what the value of the
       actual parameter for the first argument is, since default
       parameters ignore other names in the parameter list. */
    void gripe1 (int a, int j = a) { printf ("%d\n", j); }

    /* b[a] is a 10 character array of char, independent of what
       int a is! */
    void gripe2 (int a, char b[a]);

    So the problem with supporting that GCC extension in G++ is that
    can't necessarily throw parameters names into the symbol table
    while parsing the formal parameter list, since you might end
    up hiding global names that should be used according to the
    C++ default parameter semantics.
    
    If anyone sees a clean way around this that supports both
    the C++ semantics and the GCC extension semantics I'd like to
    hear it!
    
3.  The g++ manual is incorrect, I'll make that change.

  Doug
--
Master Swordsman speak of humility;             | schmidt@ics.uci.edu (ARPA)
Philosophers speak of truth;                    | office: (714) 856-4034
Saints and wisemen speak of the Tao of no doubt;
The moon, sun, and sea speaks for itself. -- Hiroshi Hamada

sysdoc@boingo.med.jhu.edu (The Doctor) (01/24/90)

There seems to be a bug in the g++ compiler when the compiler
flag -fthis-is-variable is given. The bug seems to be that
the compiler does not alloca() memory for the object prior to
some of the constructor call executing when the "new" operator
is used. Although I realize that -fthis-is-vairable is
discouraged flag, I have been trying to compile the OOPS 
smalltalk like object library that was originally designed for
AT&T C++. The object file i/o really requires using "this" as
a variable. Following is code that breaks:

--------------------------------------------------------------
/*
 * a few more tests for streams
 *
 */

#include <stream.h>
#include <SFile.h>
#include <PlotFile.h>
#include <std.h>
#include <assert.h>
#include <sys/file.h>

void t1()
{
	ostream* sout = new ostream(creat("/tmp/tStream.out", 0664));

	*sout << "Hello from the stream testor\n";
	delete sout;

	istream* sin = new istream(open("/tmp/tStream.out", O_RDONLY));
	char ch;

  while(*sin >> ch) cout << ch;

	delete sin;
	}

main()
{
  t1();

  cout << "\nFinal names & states:\n";
  cout << "cin:      " << cin.name()  << "\t" << cin.rdstate() << "\n";
  cout << "cout:     " << cout.name() << "\t" << cout.rdstate() << "\n";
  cout << "cerr:     " << cerr.name() << "\t" << cerr.rdstate() << "\n";
  cout << "\nend of test.\n";
}

--------------------------------------------------------------

This code produces a segmentation fault when run after compilation
with the -fthis-is-variable. Following is a gdb run showing the
location of the fault:

--------------------------------------------------------------
GDB 3.2, Copyright (C) 1988 Free Software Foundation, Inc.
There is ABSOLUTELY NO WARRANTY for GDB; type "info warranty" for details.
GDB is free software and you are welcome to distribute copies of it
 under certain conditions; type "info copying" to see the conditions.
Reading symbol data from /data/usr/local/src/libg++/tests/tStream...done.
Type "help" for a list of commands.
(gdb) dir ../src
Source directories searched: /data/usr/local/src/libg++/tests:/data/usr/local/src/libg++/tests/../src
(gdb) run
Starting program: /data/usr/local/src/libg++/tests/tStream 

Program received signal 11, Segmentation fault
Reading in symbols for stream.cc...done.
0x293c in __7ostreami ($this=(ostream *) 0x0, filedesc=3) (stream.cc line 78) 
78           : state(_good), ownbuf(1)
(gdb) list
73      {
74        bp = new Filebuf(fileptr);
75      }
76      
77      ostream::ostream(int filedesc)
78           : state(_good), ownbuf(1)
79      {
80        bp = new filebuf(filedesc);
81      }
82      
(gdb) print this
$1 = (ostream *) 0x0
(gdb) up
Reading in symbols for tStream.cc...done.
#1  0x20e0 in t1__Fv () (tStream.cc line 15)
15              ostream* sout = new ostream(creat("/tmp/tStream.out", 0664)); 
(gdb) list
10      #include <assert.h>
11      #include <sys/file.h>
12      
13      void t1()
14      {
15              ostream* sout = new ostream(creat("/tmp/tStream.out", 0664));
16      
17              *sout << "Hello from the stream testor\n";
18              delete sout;
19      
(gdb)
--------------------------------------------------------------

Following is the compilation process which resulted in the above 
gdb session. This was compiled and run on a Sun 4/280 running
Sun OS v3.2 BSD Unix. The error was also observed on a Sun 3/160
running Sun OS v3.5 BSD Unix.
--------------------------------------------------------------
g++  -I../g++-include -g -O -fstrength-reduce  -felide-constructors -fschedule-insns -fdelayed-branch  -fsave-memoized -fthis-is-variable -Wall -v -pipe -c  tStream.cc
gcc version 1.36.1 (based on GCC 1.36)
 /usr/local/bin/lib/gcc-cpp -+ -v -I../g++-include -undef -D__GNUC__ -D__GNUG__ -D__cplusplus -Dsparc -Dsun -Dunix -D__sparc__ -D__sun__ -D__unix__ -D__OPTIMIZE__ -Wall tStream.cc |
 /usr/local/bin/lib/gcc-cc1plus -quiet -dumpbase tStream.cc -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -fthis-is-variable -g -O -Wall -version -o - |
 as - -o tStream.o
GNU C++ version 1.36.1 (based on GCC 1.36) (sparc) compiled by GNU C version 1.36.
default target switches: -mfpu -mepilogue -msun-asm
GNU CPP version 1.36
g++  tStream.o  -o tStream -L../src -lg++ -lm 
--------------------------------------------------------------


When the program is compiled as below (without the -fthis-is-variable
the program runs correctly:
--------------------------------------------------------------
g++  -I../g++-include -g -O -fstrength-reduce  -felide-constructors -fschedule-insns -fdelayed-branch  -fsave-memoized -Wall -v -pipe -c  tStream.cc
gcc version 1.36.1 (based on GCC 1.36)
 /usr/local/bin/lib/gcc-cpp -+ -v -I../g++-include -undef -D__GNUC__ -D__GNUG__ -D__cplusplus -Dsparc -Dsun -Dunix -D__sparc__ -D__sun__ -D__unix__ -D__OPTIMIZE__ -Wall tStream.cc |
 /usr/local/bin/lib/gcc-cc1plus -quiet -dumpbase tStream.cc -fstrength-reduce -felide-constructors -fschedule-insns -fdelayed-branch -fsave-memoized -g -O -Wall -version -o - |
 as - -o tStream.o
GNU C++ version 1.36.1 (based on GCC 1.36) (sparc) compiled by GNU C version 1.36.
default target switches: -mfpu -mepilogue -msun-asm
GNU CPP version 1.36
g++  tStream.o  -o tStream -L../src -lg++ -lm 

*Boingo[523]tests% tStream
Hellofromthestreamtestor
Final names & states:
cin:      (stdin)       0
cout:     (stdout)      0
cerr:     (stderr)      0

end of test.
*Boingo[524]tests% 
--------------------------------------------------------------

Another problem I have had is that the -traditional flag does
not do what the documentation says it should. The following code
does not compile with the -traditional flag:
--------------------------------------------------------------
static int b;

function(int dumb)
	{
	const int a = 1;
	extern int b;
	char *p;

	printf(a==p);
	}

*Boingo[425]mpredit% g++ -traditional -v -c test.c
gcc version 1.36.1 (based on GCC 1.36)
 /usr/local/bin/lib/gcc-cpp -+ -v -undef -D__GNUC__ -D__GNUG__ -D__cplusplus -Dsparc -Dsun -Dunix -D__sparc__ -D__sun__ -D__unix__ -traditional test.c /usr/tmp/cca22967.cpp
GNU CPP version 1.36
 /usr/local/bin/lib/gcc-cc1plus /usr/tmp/cca22967.cpp -quiet -dumpbase test.c -traditional -version -o /usr/tmp/cca22967.s
GNU C++ version 1.36.1 (based on GCC 1.36) (sparc) compiled by GNU C version 1.36.
default target switches: -mfpu -mepilogue -msun-asm
test.c: In function int function (...):
test.c:9: warning: implicit declaration of function `printf'
test.c:9: comparison between pointer and integer
*Boingo[426]mpredit%  
--------------------------------------------------------------

I believe that this should compile correctly. In general it seems that
-traditional does not act at all like it is documented or as it works
in gcc.

I hope that the above reports are complete and helpful. I am amazed by
the amount of great stuff available for free from gnu. Thanks to all
of you for a great effort.

Derek Ney
derek@boingo.med.jhu.edu (128.220.55.210)
(301)955-5173