tuck@jason.cs.unc.edu (Russ Tuck) (12/08/89)
The example programs below define classes A and B. A has operator+, and
B has a user-defined conversion to A. The issue is an expression which
uses A's + on B's objects, via the B->A conversion.
I posted almost the same program to comp.lang.c++ yesterday, because cfront
2.0 seemed to be in error. Jonathan Shopiro of AT&T confirmed via mail
that there is a probable bug in cfront, and suggested a workaround which
is probably also better programming practice. (The workaround is to have
the conversion return an A (value) instead of an A& (reference).)
Unfortunately, the workaround reveals a bug in g++ 1.36.1.
Here are the details...
g++ = GNU g++ 1.36.1
CC.new = AT&T cfront 2.0
piglet = Sun-3/60, SunOS 4.0.3
[Bug 1: conversion fails.]
tuck@piglet> cat type2ae.C
class A {
public:
A();
friend const A operator+ (const A& lsrc, const A& rsrc);
};
class B {
public:
B();
operator const A();
};
main()
{
A a0;
B b0, b1;
a0 = b0 + b1;
}
tuck@piglet> g++ -v -c type2ae.C
gcc version 1.36.1 (based on GCC 1.36)
/usr/softlab/contrib/lib/m68k_sunos/gcc-cpp -+ -v -undef -D__GNUC__ -D__GNUG__ -D__cplusplus -Dmc68000 -Dsun -Dunix -D__mc68000__ -D__sun__ -D__unix__ -Dmc68010 type2ae.C /usr/tmp/cca01090.cpp
GNU CPP version 1.36
/usr/softlab/contrib/lib/m68k_sunos/gcc-cc1plus /usr/tmp/cca01090.cpp -quiet -dumpbase type2ae.C -version -o /usr/tmp/cca01090.s
GNU C++ version 1.36.1 (based on GCC 1.36) (68k, MIT syntax) compiled by GNU C version 1.36.
default target switches:
type2ae.C: In function int main ():
type2ae.C:18: default type conversion for type `B' failed
tuck@piglet> CC.new -c type2ae.C
CC type2ae.C:
cc -c type2ae.c
[Bug 2 (related): g++ gets fatal signal when stub fn defns are added.]
tuck@piglet> cat type2af.C
class A {
public:
A();
friend const A operator+ (const A& lsrc, const A& rsrc);
};
class B {
public:
B();
operator const A();
};
extern "C" {
#include <stdio.h>
}
A::A()
{
printf("A::A();\n");
}
const A operator+(const A& lsrc, const A& rsrc)
{
printf("const A operator+(const A& lsrc, const A& rsrc)\n");
A ta;
return(ta);
}
B::B()
{
printf("B::B();\n");
}
B::operator const A()
{
printf("operator const A()\n");
A* pa = new A;
return(*pa);
}
main()
{
A a0;
B b0, b1;
a0 = b0 + b1;
}
[diff to show nothing changed, just added defns]
tuck@piglet> diff type2ae.C type2af.C
diff type2ae.C type2af.C
12a13,40
> extern "C" {
> #include <stdio.h>
> }
>
> A::A()
> {
> printf("A::A();\n");
> }
>
> const A operator+(const A& lsrc, const A& rsrc)
> {
> printf("const A operator+(const A& lsrc, const A& rsrc)\n");
> A ta;
> return(ta);
> }
>
> B::B()
> {
> printf("B::B();\n");
> }
>
> B::operator const A()
> {
> printf("operator const A()\n");
> A* pa = new A;
> return(*pa);
> }
>
tuck@piglet> g++ -v -c type2af.C
gcc version 1.36.1 (based on GCC 1.36)
/usr/softlab/contrib/lib/m68k_sunos/gcc-cpp -+ -v -undef -D__GNUC__ -D__GNUG__ -D__cplusplus -Dmc68000 -Dsun -Dunix -D__mc68000__ -D__sun__ -D__unix__ -Dmc68010 type2af.C /usr/tmp/cca01134.cpp
GNU CPP version 1.36
/usr/softlab/contrib/lib/m68k_sunos/gcc-cc1plus /usr/tmp/cca01134.cpp -quiet -dumpbase type2af.C -version -o /usr/tmp/cca01134.s
GNU C++ version 1.36.1 (based on GCC 1.36) (68k, MIT syntax) compiled by GNU C version 1.36.
default target switches:
type2af.C: In method B::operator const class A ():
type2af.C:38: Segmentation violation
g++: Program cc1plus got fatal signal 11.
tuck@piglet> CC.new type2af.C
CC type2af.C:
"type2af.C", line 22: warning: lsrc not used
"type2af.C", line 22: warning: rsrc not used
cc -L/usr/local/lib/CC2.0 type2af.c -lC
tuck@piglet> a.out
A::A();
B::B();
B::B();
operator const A()
A::A();
operator const A()
A::A();
const A operator+(const A& lsrc, const A& rsrc)
A::A();
[This is the similar program which shows the cfront error. g++ does fine.]
[The only difference is that the conversion is to A& instead of A. ]
tuck@piglet> diff type2af.C type2ag.C
10c10
< operator const A();
---
> operator const A&();
34c34
< B::operator const A()
---
> B::operator const A&()
tuck@piglet> cat type2ag.C
class A {
public:
A();
friend const A operator+ (const A& lsrc, const A& rsrc);
};
class B {
public:
B();
operator const A&();
};
extern "C" {
#include <stdio.h>
}
A::A()
{
printf("A::A();\n");
}
const A operator+(const A& lsrc, const A& rsrc)
{
printf("const A operator+(const A& lsrc, const A& rsrc)\n");
A ta;
return(ta);
}
B::B()
{
printf("B::B();\n");
}
B::operator const A&()
{
printf("operator const A()\n");
A* pa = new A;
return(*pa);
}
main()
{
A a0;
B b0, b1;
a0 = b0 + b1;
}
tuck@piglet> g++ -v type2ag.C -lg++
gcc version 1.36.1 (based on GCC 1.36)
/usr/softlab/contrib/lib/m68k_sunos/gcc-cpp -+ -v -undef -D__GNUC__ -D__GNUG__ -D__cplusplus -Dmc68000 -Dsun -Dunix -D__mc68000__ -D__sun__ -D__unix__ -Dmc68010 type2ag.C /usr/tmp/cca01166.cpp
GNU CPP version 1.36
/usr/softlab/contrib/lib/m68k_sunos/gcc-cc1plus /usr/tmp/cca01166.cpp -quiet -dumpbase type2ag.C -version -o /usr/tmp/cca01166.s
GNU C++ version 1.36.1 (based on GCC 1.36) (68k, MIT syntax) compiled by GNU C version 1.36.
default target switches:
/usr/softlab/contrib/lib/m68k_sunos/gcc-as -mc68010 -o type2ag.o /usr/tmp/cca01166.s
/usr/softlab/contrib/lib/m68k_sunos/gcc-ld /lib/crt0.o type2ag.o -lg++ -lg++ /usr/softlab/contrib/lib/m68k_sunos/gcc-gnulib -lc
tuck@piglet> a.out
A::A();
B::B();
B::B();
operator const A()
A::A();
operator const A()
A::A();
const A operator+(const A& lsrc, const A& rsrc)
A::A();
tuck@piglet> CC.new type2ag.C
CC type2ag.C:
"type2ag.C", line 22: warning: lsrc not used
"type2ag.C", line 22: warning: rsrc not used
"type2ag.C", line 46: error: ambiguous use of overloaded +: B and B
1 error
[Now for completeness, here's the preprocessor output from the file that ]
[causes the fatal signal. ]
tuck@piglet> g++ -v -E type2af.C
gcc version 1.36.1 (based on GCC 1.36)
/usr/softlab/contrib/lib/m68k_sunos/gcc-cpp -+ -v -undef -D__GNUC__ -D__GNUG__ -D__cplusplus -Dmc68000 -Dsun -Dunix -D__mc68000__ -D__sun__ -D__unix__ -Dmc68010 type2af.C
GNU CPP version 1.36
# 1 "type2af.C"
class A {
public:
A();
friend const A operator+ (const A& lsrc, const A& rsrc);
};
class B {
public:
B();
operator const A();
};
extern "C" {
# 1 "/usr/softlab/contrib/include/g++-include/stdio.h" 1
#pragma once
# 79 "/usr/softlab/contrib/include/g++-include/stdio.h"
# 108 "/usr/softlab/contrib/include/g++-include/stdio.h"
extern struct _iobuf {
int _cnt;
char* _ptr;
char* _base;
int _bufsiz;
short _flag;
char _file;
} _iob[];
# 171 "/usr/softlab/contrib/include/g++-include/stdio.h"
extern "C" {
int _doprnt(const char*, void*, struct _iobuf *);
int _doscan( struct _iobuf *, const char*, ...);
int _filbuf( struct _iobuf *);
int _flsbuf(unsigned, struct _iobuf *);
int fclose( struct _iobuf *);
struct _iobuf * fdopen(int, const char*);
int fflush( struct _iobuf *);
int fgetc( struct _iobuf *);
char* fgets(char*, int, struct _iobuf *);
struct _iobuf * fopen(const char*, const char*);
int fprintf( struct _iobuf *, const char* ...);
int fputc(int, struct _iobuf *);
int fputs(const char*, struct _iobuf *);
int fread(void*, int, int, struct _iobuf *);
struct _iobuf * freopen(const char*, const char*, struct _iobuf *);
int fscanf( struct _iobuf *, const char* ...);
int fseek( struct _iobuf *, long, int);
long ftell( struct _iobuf *);
int fwrite(const void*, int, int, struct _iobuf *);
char* gets(char*);
int getw( struct _iobuf *);
int pclose( struct _iobuf *);
struct _iobuf * popen(const char*, const char*);
int printf(const char* ...);
void puts(const char*);
int putw(int, struct _iobuf *);
int rewind( struct _iobuf *);
int scanf(const char* ...);
void setbuf( struct _iobuf *, char*);
void setbuffer( struct _iobuf *, char*, int);
void setlinebuf( struct _iobuf *);
void setvbuf( struct _iobuf *, char*, int, int);
int sscanf(char*, const char* ...);
struct _iobuf * tmpfile();
int ungetc(int, struct _iobuf *);
int vfprintf( struct _iobuf *, const char*, ...);
int vprintf(const char*, ... );
char* sprintf(char*, const char* ...);
char* vsprintf(char*, const char*, ...);
}
# 14 "type2af.C" 2
}
A::A()
{
printf("A::A();\n");
}
const A operator+(const A& lsrc, const A& rsrc)
{
printf("const A operator+(const A& lsrc, const A& rsrc)\n");
A ta;
return(ta);
}
B::B()
{
printf("B::B();\n");
}
B::operator const A()
{
printf("operator const A()\n");
A* pa = new A;
return(*pa);
}
main()
{
A a0;
B b0, b1;
a0 = b0 + b1;
}