[gnu.g++.bug] BUG in use of implicit conversions

jj@idris.id.dk (Jesper Joergensen [ris]) (02/23/90)

ENVIRONMENT
===========

    Compiler:	G++	version 1.36.4	(configured for 'vax')
    Back-end:	GCC	version 1.36.93	(configured for 'vax')
    System:	Ultrix	version 2.2-1 Worksystem v1.1 System #2
    Machine:	DEC VAXstation 2000


SUMMARY Main problem
====================

    Given a hierarchy of four different classes:
			    ID, Prod, Sum and Expr.
    with the following implicit upward conversions (using constructors):
	ID    -->  Prod
	Prod  -->  Sum
	Sum   -->  Expr
    and a single backward conversion (using conversion operators):
	Expr  -->  Sum &		(NOTICE it is a reference to Sum)
    then the call of an overloaded operator:
	Sum operator*(const Sum &, const Prod &) ;
	Sum operator*(const Sum &, const ID &  ) ;
    is flagged as ambiguous when given arguments of the classes Expr and ID
    respectively.

    The first argument of class Expr MUST be converted to class Sum, there is
    no other possibility for a match and it is possible to do it. In any case
    there will always be an exact match for the second argument of class ID, so
    no implicit conversion is needed and there is therefore no ambiguity.

    More comments follow after the example below.


SIDE ISSUE
==========

    According to my documentation (Lippman), the language does not distinguish
    between object and references to objects of the same class when type
    matching is considered. In the below example I had to define a conversion
    form  `Expr'  to  `reference to Sum'  in order to match the first argument
    of the overloaded `operator*'. If I only had a conversion from `Expr' to
    `Sum' then no match could be found at all !!

    Please check this out as well ....

    If you think that the conversion rules of the C++ language is just one hell
    of a pain in standard output then I certainly can agree with you !! Just
    thinking of trying to implement such a mess myself gives me the creeps, so
    if you make bugs in doing this part of the compiler, then you are certainly
    excused.


EXAMPLE PROGRAM WITH COMPILATION
================================

***** SESSION START *****
% cat implconvtest.cc
class ID {				// Elementary class
public:
  ID() { }
} ;

class Prod {				// First level container class
  ID member ;
public:
  Prod() { }
  Prod(const ID &id) { member = id ; }	// can be initialised from elementary
} ;

class Sum {				// Second level container class
  Prod member ;
public:
  Sum() { }				// can be initialised from first level
  Sum(const Prod &prod) { member = prod ; }
} ;

Sum operator*(const Sum &, const Prod &) ;
Sum operator*(const Sum &, const ID &  ) ;

class Expr {				// Third level container class
  Sum member ;
public:
  Expr() { }				// can be initialised from second level
  Expr(const Sum &sum) { member = sum ; }
  operator Sum &() { return member ; }	// and converted implicitly back
} ;

int main(int argc, const char *argv[]) {
  ID id ;
  Expr exp ;
  Sum sum ;
  sum = sum * id ;			// OK: exact type match !!
  sum = exp * id ;			// Why is this call ambiguous ????
					//  exp MUST be converted to Sum and
					//  then id matches second arg. exactly
  return 0 ;
}
% g++ -v implconvtest.cc -S
g++ version 1.36.4 (based on GCC 1.36.93)
 /usr/local/lib/gcc-cpp -+ -v -undef -D__GNUC__ -D__GNUG__ -D__cplusplus -Dvax -Dunix -D__vax__ -D__unix__ implconvtest.cc /usr/tmp/cc006932.cpp
GNU CPP version 1.37
 /usr/local/lib/gcc-cc1plus /usr/tmp/cc006932.cpp -quiet -dumpbase implconvtest.cc -version -o implconvtest.s
GNU C++ version 1.36.4 (based on GCC 1.36.93) (vax) compiled by GNU C version 1.36.93.
default target switches: -munix
implconvtest.cc: In function int main (int, const char **):
implconvtest.cc:36: type conversion required for type `ID'
implconvtest.cc:36: call of overloaded `op$mult' is ambiguous
% 
****** SESSION END ******

    I thought that the rule of disallowing ambiguous conversions only implied
    when a conversion was actually required, here we have an exact match for
    the second argument.

    BTW I am not sure whether it actually is the second argument that is
    causing the problem, i.e. I think that more specific error messages
    refering to argument numbers and describing the possible ambiguous
    conversions would be highly appropriate in cases like this. I had to go
    back and do the work, which the compiler had already done (incorrectly).

    The rest is up to you, good luck ....

	Jesper Jorgensen	jj@idris.id.dk

	Research associate
	Department of Computer Science
	Technical University of Denmark
	DK-2800 Lyngby
	DENMARK