[gnu.g++.bug] G++ enum problem, Version 1.35.0, Sun4-os4.0.3

cheeks@CENTRAL.SUN.COM (Mark Costlow) (07/25/89)

[sorry if you've seen this before.  I mistakenly posted it instead of
 sending it to the mailing list]

Following is a description of what we believe to be a bug in g++ 1.35.0.
This is on a Sun4 under SunOS 4.0.3.

The bug in g++ apparently works like this.  In a method
that has a typedef'ed enum as an argument, that parameter
is encoded in the method's function name as _$E_n, where
"n" indicates that this is the nth enum that has been
typedef'ed.  When a library is complied that defines numerous
enum types in different modules, they each generate _E_0 when
they are used as arguments because the compiler doesn't see
all the enums at once.  But when an application refers to
more than one of these modules, the enums begin generating
different function names.

The workaround I came up with was to change
  typedef enum { X, Y, Z ... } NewType;
to
  typedef int NewType;
  enum { X, Y, Z ... } ;

The real fix would be to include the type name in the function
name instead of the index - eg. "_E_NewType" instead of "_E_0".


Run the rest of this message through sh to extract the test case t hat I worked
up along with a sample run.  (It compiles under cfront but not g++).

Mark Costlow
....texsun!xochitl!cheeks

#---------------------------------- cut here ----------------------------------
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by  <cheeks@argon> on Fri Jul 21 17:08:43 1989
#
# This archive contains:
#	testdir	
#
# Existing files will not be overwritten.
# Error checking via wc(1) will be performed.

LANG=""; export LANG

echo mkdir - testdir
mkdir testdir

if test -f testdir/test_class_one.c
then
	echo Ok to overwrite existing file testdir/test_class_one.c\?
	read answer
	case "$answer" in
	[yY]*)	echo Proceeding;;
	*)	echo Aborting; exit 1;;
	esac
	rm -f testdir/test_class_one.c
	if test -f testdir/test_class_one.c
	then
		echo Error: could not remove testdir/test_class_one.c, aborting
		exit 1
	fi
fi
echo x - testdir/test_class_one.c
cat >testdir/test_class_one.c <<'@EOF'
#include <stdio.h>
#include "test_class_one.h"

test_class_one::test_class_one() { printf("I don't do anything\n"); };
test_class_one::~test_class_one() { printf("Neither do I\n"); };
void test_class_one::test_func_one(NewTypeOne i) { printf("Got %d\n", i); };
@EOF
set `wc -lwc <testdir/test_class_one.c`
if test $1$2$3 != 625261
then
	echo ERROR: wc results of testdir/test_class_one.c are $* should be 6 25 261
fi

chmod 644 testdir/test_class_one.c

if test -f testdir/test_class_one.h
then
	echo Ok to overwrite existing file testdir/test_class_one.h\?
	read answer
	case "$answer" in
	[yY]*)	echo Proceeding;;
	*)	echo Aborting; exit 1;;
	esac
	rm -f testdir/test_class_one.h
	if test -f testdir/test_class_one.h
	then
		echo Error: could not remove testdir/test_class_one.h, aborting
		exit 1
	fi
fi
echo x - testdir/test_class_one.h
cat >testdir/test_class_one.h <<'@EOF'
typedef enum {A, B, C} NewTypeOne;

class test_class_one {
public:
    test_class_one();
    ~test_class_one();
    void test_func_one(NewTypeOne);
};
@EOF
set `wc -lwc <testdir/test_class_one.h`
if test $1$2$3 != 815151
then
	echo ERROR: wc results of testdir/test_class_one.h are $* should be 8 15 151
fi

chmod 644 testdir/test_class_one.h

if test -f testdir/test_class_two.c
then
	echo Ok to overwrite existing file testdir/test_class_two.c\?
	read answer
	case "$answer" in
	[yY]*)	echo Proceeding;;
	*)	echo Aborting; exit 1;;
	esac
	rm -f testdir/test_class_two.c
	if test -f testdir/test_class_two.c
	then
		echo Error: could not remove testdir/test_class_two.c, aborting
		exit 1
	fi
fi
echo x - testdir/test_class_two.c
cat >testdir/test_class_two.c <<'@EOF'
#include <stdio.h>
#include "test_class_two.h"

test_class_two::test_class_two() { printf("I don't do anything\n"); };
test_class_two::~test_class_two() { printf("Neither do I\n"); };
void test_class_two::test_func_two(NewTypeTwo i) { printf("Got %d\n", i); };
@EOF
set `wc -lwc <testdir/test_class_two.c`
if test $1$2$3 != 625261
then
	echo ERROR: wc results of testdir/test_class_two.c are $* should be 6 25 261
fi

chmod 644 testdir/test_class_two.c

if test -f testdir/test_class_two.h
then
	echo Ok to overwrite existing file testdir/test_class_two.h\?
	read answer
	case "$answer" in
	[yY]*)	echo Proceeding;;
	*)	echo Aborting; exit 1;;
	esac
	rm -f testdir/test_class_two.h
	if test -f testdir/test_class_two.h
	then
		echo Error: could not remove testdir/test_class_two.h, aborting
		exit 1
	fi
fi
echo x - testdir/test_class_two.h
cat >testdir/test_class_two.h <<'@EOF'
typedef enum {X, Y, Z} NewTypeTwo;

class test_class_two {
public:
    test_class_two();
    ~test_class_two();
    void test_func_two(NewTypeTwo);
};


@EOF
set `wc -lwc <testdir/test_class_two.h`
if test $1$2$3 != 1015153
then
	echo ERROR: wc results of testdir/test_class_two.h are $* should be 10 15 153
fi

chmod 644 testdir/test_class_two.h

if test -f testdir/test_code.c
then
	echo Ok to overwrite existing file testdir/test_code.c\?
	read answer
	case "$answer" in
	[yY]*)	echo Proceeding;;
	*)	echo Aborting; exit 1;;
	esac
	rm -f testdir/test_code.c
	if test -f testdir/test_code.c
	then
		echo Error: could not remove testdir/test_code.c, aborting
		exit 1
	fi
fi
echo x - testdir/test_code.c
cat >testdir/test_code.c <<'@EOF'
#include <stream.h>
#include "test_class_one.h"
#include "test_class_two.h"

main()
{
    test_class_one *tc1 = new test_class_one;
    test_class_two *tc2 = new test_class_two;

    cout << "Hello world ...\n";
    tc1->test_func_one(A);
    tc2->test_func_two(X);

    cout << "Hello again ...\n";
    tc1->test_func_one(B);
    tc2->test_func_two(Y);

    cout << "Hello for the last time ...\n";
    tc1->test_func_one(C);
    tc2->test_func_two(Z);
}
@EOF
set `wc -lwc <testdir/test_code.c`
if test $1$2$3 != 2143456
then
	echo ERROR: wc results of testdir/test_code.c are $* should be 21 43 456
fi

chmod 644 testdir/test_code.c

if test -f testdir/test_code.h
then
	echo Ok to overwrite existing file testdir/test_code.h\?
	read answer
	case "$answer" in
	[yY]*)	echo Proceeding;;
	*)	echo Aborting; exit 1;;
	esac
	rm -f testdir/test_code.h
	if test -f testdir/test_code.h
	then
		echo Error: could not remove testdir/test_code.h, aborting
		exit 1
	fi
fi
echo x - testdir/test_code.h
cat >testdir/test_code.h <<'@EOF'
typedef enum {A, B, C} NewTypeOne;
typedef enum {X, Y, Z} NewTypeTwo;
@EOF
set `wc -lwc <testdir/test_code.h`
if test $1$2$3 != 21270
then
	echo ERROR: wc results of testdir/test_code.h are $* should be 2 12 70
fi

chmod 644 testdir/test_code.h

if test -f testdir/Makefile
then
	echo Ok to overwrite existing file testdir/Makefile\?
	read answer
	case "$answer" in
	[yY]*)	echo Proceeding;;
	*)	echo Aborting; exit 1;;
	esac
	rm -f testdir/Makefile
	if test -f testdir/Makefile
	then
		echo Error: could not remove testdir/Makefile, aborting
		exit 1
	fi
fi
echo x - testdir/Makefile
cat >testdir/Makefile <<'@EOF'
CC = g++ -v

OBJS = test_code.o test_class_one.o test_class_two.o

all: clean test_code 

test_code: $(OBJS) 
	$(CC) -o test_code $(OBJS)

test_code.o: test_code.c
	$(CC) -c test_code.c

test_class_one.o: test_class_one.c
	$(CC) -c test_class_one.c

test_class_two.o: test_class_two.c
	$(CC) -c test_class_two.c

clean: 
	rm -f *.o test_code
@EOF
set `wc -lwc <testdir/Makefile`
if test $1$2$3 != 2038342
then
	echo ERROR: wc results of testdir/Makefile are $* should be 20 38 342
fi

chmod 644 testdir/Makefile

if test -f testdir/Sample_Run
then
	echo Ok to overwrite existing file testdir/Sample_Run\?
	read answer
	case "$answer" in
	[yY]*)	echo Proceeding;;
	*)	echo Aborting; exit 1;;
	esac
	rm -f testdir/Sample_Run
	if test -f testdir/Sample_Run
	then
		echo Error: could not remove testdir/Sample_Run, aborting
		exit 1
	fi
fi
echo x - testdir/Sample_Run
cat >testdir/Sample_Run <<'@EOF'
Script started on Fri Jul 21 16:37:36 1989
<sodium> [1] ->make CC="CC -v"
rm -f *.o test_code
CC -v -c test_code.c
CC  test_code.c:
cc  -c  -v test_code..c
/lib/cpp -undef -Dunix -Dsun -Dsparc test_code..c >/tmp/cpp.07149.0.i
/lib/ccom - </tmp/cpp.07149.0.i >/tmp/ccom.07149.1.s
rm /tmp/cpp.07149.0.i
/bin/as -o test_code..o -Q /tmp/ccom.07149.1.s
rm /tmp/ccom.07149.1.s
CC -v -c test_class_one.c
CC  test_class_one.c:
cc  -c  -v test_class_one..c
/lib/cpp -undef -Dunix -Dsun -Dsparc test_class_one..c >/tmp/cpp.07161.0.i
/lib/ccom - </tmp/cpp.07161.0.i >/tmp/ccom.07161.1.s
rm /tmp/cpp.07161.0.i
/bin/as -o test_class_one..o -Q /tmp/ccom.07161.1.s
rm /tmp/ccom.07161.1.s
CC -v -c test_class_two.c
CC  test_class_two.c:
cc  -c  -v test_class_two..c
/lib/cpp -undef -Dunix -Dsun -Dsparc test_class_two..c >/tmp/cpp.07173.0.i
/lib/ccom - </tmp/cpp.07173.0.i >/tmp/ccom.07173.1.s
rm /tmp/cpp.07173.0.i
/bin/as -o test_class_two..o -Q /tmp/ccom.07173.1.s
rm /tmp/ccom.07173.1.s
CC -v -o test_code test_code.o test_class_one.o test_class_two.o
cc   -o test_code  -v test_code.o test_class_one.o test_class_two.o -lC
/bin/ld -dc -dp -e start -X -o test_code /usr/lib/crt0.o test_code.o test_class_one.o test_class_two.o -lC -lc
/bin/ld -dc -dp -e start -X -o test_code /usr/lib/crt0.o __ctdt.o test_code.o test_class_one.o test_class_two.o -lC -lc
<sodium> [2] ->./test_code
I don't do anything
I don't do anything
Hello world ...
Got 0
Got 0
Hello again ...
Got 1
Got 1
Hello for the last time ...
Got 2
Got 2
<sodium> [3] ->make CC="g++ -v"
rm -f *.o test_code
g++ -v -c test_code.c
g++ version 1.35.0
 /usr/local/lib/gcc-cpp -+ -v -undef -D__GNU__ -D__GNUG__ -D__cplusplus -Dsparc -Dsun -Dunix -D__sparc__ -D__sun__ -D__unix__ test_code.c /tmp/cca07208.cpp
GNU CPP version 1.35
 /usr/local/lib/gcc-cc1plus /tmp/cca07208.cpp -quiet -dumpbase test_code.c -noreg -version -o /tmp/cca07208.s
GNU C++ version 1.35.0 (sparc) compiled by GNU C version 1.35.
 as /tmp/cca07208.s -o test_code.o
g++ -v -c test_class_one.c
g++ version 1.35.0
 /usr/local/lib/gcc-cpp -+ -v -undef -D__GNU__ -D__GNUG__ -D__cplusplus -Dsparc -Dsun -Dunix -D__sparc__ -D__sun__ -D__unix__ test_class_one.c /tmp/cca07212.cpp
GNU CPP version 1.35
 /usr/local/lib/gcc-cc1plus /tmp/cca07212.cpp -quiet -dumpbase test_class_one.c -noreg -version -o /tmp/cca07212.s
GNU C++ version 1.35.0 (sparc) compiled by GNU C version 1.35.
 as /tmp/cca07212.s -o test_class_one.o
g++ -v -c test_class_two.c
g++ version 1.35.0
 /usr/local/lib/gcc-cpp -+ -v -undef -D__GNU__ -D__GNUG__ -D__cplusplus -Dsparc -Dsun -Dunix -D__sparc__ -D__sun__ -D__unix__ test_class_two.c /tmp/cca07216.cpp
GNU CPP version 1.35
 /usr/local/lib/gcc-cc1plus /tmp/cca07216.cpp -quiet -dumpbase test_class_two.c -noreg -version -o /tmp/cca07216.s
GNU C++ version 1.35.0 (sparc) compiled by GNU C version 1.35.
 as /tmp/cca07216.s -o test_class_two.o
g++ -v -o test_code test_code.o test_class_one.o test_class_two.o
g++ version 1.35.0
 /usr/local/lib/gcc-ld++ -o test_code -C /usr/local/lib/crt0+.o test_code.o test_class_one.o test_class_two.o -lg++ /usr/local/lib/gcc-gnulib -lc
test_code.o: Undefined symbol _test_func_two_PStest_class_two_E$_1 referenced from text
test_code.o: Undefined symbol _test_func_two_PStest_class_two_E$_1 referenced from text
test_code.o: Undefined symbol _test_func_two_PStest_class_two_E$_1 referenced from text

*** Error code 1
make: Fatal error: Command failed for target `test_code'
<sodium> [4] ->^D
script done on Fri Jul 21 16:38:22 1989
@EOF
set `wc -lwc <testdir/Sample_Run`
if test $1$2$3 != 774103504
then
	echo ERROR: wc results of testdir/Sample_Run are $* should be 77 410 3504
fi

chmod 644 testdir/Sample_Run

chmod 755 testdir

exit 0

Mark Costlow
....texsun!xochitl!cheeks

grunwald@flute.cs.uiuc.edu (Dirk Grunwald) (07/30/89)

I also ran into this bug in 1.35.1+ and forgot to report it. Another
workaround is to change your function to use `int' and not the enum.
--
Dirk Grunwald -- Univ. of Illinois 		  (grunwald@flute.cs.uiuc.edu)