Noisy when choosing T::operator Type() vs T::op const Type() const

Jim Carter jimc@math.ucla.edu
Sun Sep 17 14:54:00 GMT 2000


This is a followup to the bug message repeated below, and the answer from
the developers.  At UCLA-Mathnet we are getting considerable resistance to
gcc v2.95.2.  Faculty (and programmers) are upset that correct code which 
formerly compiled cleanly now spews warning messages.  I have spent the last
week putting explicit casts into a rather large library that used to compile
without warnings; I'm about half way through.  When developing C++
material it's very difficult to find the actual error messages among the 
numerous warnings.  And clearly we can't use this compiler in the student
lab for our C++ courses.  Our "rules of engagement" allow us to apply 
official patches, but not to maintain a customized source tree for basic
infrastructure.  Thus, we aren't going to be able to use gcc v2.95.2.  We
are going to have to either roll back to the latest version of egcs that
didn't have the message, or use Sun's product (which we have a license for),
dealing with its various idiosyncracies.

How about a compromise?  In the documentation, the node "Trouble" : "C++
Misunderstandings" appears to be a collection of responses to similar
situations.  Let's add another section explaining the situation and declaring
that the compiler is right and the complainers are wrong.  Then, lose the
message.  If this patch were accepted as official, we could use gcc v2.95.2.

I've included the appropriate patches (vs. the unmodified 2.95.2 sources).

James F. Carter        Voice 310 825 2897	FAX 310 206 6673
UCLA-Mathnet;  6115 MSA; 405 Hilgard Ave.; Los Angeles, CA, USA  90095-1555
Internet: jimc@math.ucla.edu (finger for PGP key)
UUCP:...!{ucsd,ames,ncar,gatech,purdue,rutgers,decvax,uunet}!math.ucla.edu!jimc

==== Patch:

*** ./gcc/gcc.texi.orig	Sun Aug  8 23:47:01 1999
--- ./gcc/gcc.texi	Sun Sep 17 10:59:00 2000
***************
*** 1654,1663 ****
--- 1654,1664 ----
  
  @menu
  * Static Definitions::  Static member declarations are not definitions
  * Temporaries::         Temporaries may vanish before you expect
  * Copy Assignment::     Copy Assignment operators copy virtual bases twice
+ * Conversion to Const:: C++ converts first, then makes it const
  @end menu
  
  @node Static Definitions
  @subsection Declare @emph{and} Define Static Members
  
***************
*** 1802,1811 ****
--- 1803,1853 ----
  
  If application code relies on copy-assignment, a user-defined
  copy-assignment operator removes any uncertainties. With such an
  operator, the application can define whether and how the virtual base
  subobject is assigned.
+ 
+ @node Conversion to Const
+ @subsection C++ Converts First, Then Makes It Const
+ 
+ In type conversion, generally a qualified object (const or volatile) will be
+ converted to a similarly qualified result.  In rare cases these conversions 
+ are distinguishable.  For example:
+ 
+ @example
+ class Thing@{
+   int content;
+   int hitcount;
+ public:
+   Thing() : content(0), hitcount(0) @{ @}
+   operator int& () @{
+     hitcount++;
+     return content;
+   @}
+   operator const int& () const @{
+     return content;
+   @}
+ @};
+ @end example
+ 
+ The hit count is incremented whenever the non-const Thing is referred to,
+ but this could not be done for a const Thing.  In a context where an 
+ unqualified object is available but a qualified one is wanted, which conversion
+ should be used?  In this example, which only needs a const reference to the
+ integer in the Thing, should the hit counter be incremented?
+ 
+ @example
+   Thing t;
+   int i = t;
+ @end example
+ 
+ The rule is to get the available object to the required type without regard for
+ qualifiers on the goal, and then to add qualifiers as needed.  Thus the
+ non-const conversion would be used and the hit counter would be incremented.
+ Some people expect the goal's qualifier to be taken into account at the 
+ earliest step, causing the const conversion to be chosen, but that is not what
+ the C++ standard specifies, besides being a nightmare to implement.
  
  @node Protoize Caveats
  @section Caveats of using @code{protoize}
  
  The conversion programs @code{protoize} and @code{unprotoize} can
*** ./gcc/cp/call.c.orig	Wed Jun 16 04:26:24 1999
--- ./gcc/cp/call.c	Sun Sep 17 10:15:01 2000
***************
*** 4322,4331 ****
--- 4322,4332 ----
  	    }
  	  winner = comp;
  	}
      }
  
+ #ifdef ALLOW_EXTREMELY_ANNOYING_MESSAGES
    /* warn about confusing overload resolution for user-defined conversions,
       either between a constructor and a conversion op, or between two
       conversion ops.  */
    if (winner && cand1->second_conv
        && ((DECL_CONSTRUCTOR_P (cand1->fn)
***************
*** 4355,4364 ****
--- 4356,4366 ----
  	    }
  	  else
  	    add_warning (w, l);
  	}
      }
+ #endif /*ALLOW_EXTREMELY_ANNOYING_MESSAGES*/
  
    if (winner)
      return winner;
  
    /* or, if not that,


==== Original bug message:

// bug01.C -- Noisy when choosing T::operator Type() vs T::op const Type() const
/*
Type T can be converted to B by T::operator B&(), but there's also a conversion
T::operator const B&() const.  (Similarly for pointers.)  In a situation where
non-const T is available but const B is wanted, gcc could choose either
conversion.  It considers T::operator B&() to be better, probably correctly.
The complaint is, it issues a warning message.  If it knows T::operator B&() is
better, it should shut up and use it!

(Feature request: a pragma that could cause the compiler to spit out, only for
selected small code sections, what it thinks it's trying to accomplish, what
functions are candidates, which one it chose, and why.  In other words,
preserve this bug plus other similar warning messages, but only when the user
engages the pragma.)

Version:	gcc v2.95.2
Configure:	--prefix=/usr/local --enable-shared \
		--enable-languages=c++,f77,java
Environment:	i686-pc-linux-gnu 
		(Slackware 7.1, kernel 2.2.16, Intel Pentium 3)
Command line:	g++ bug01.C
Submitted-date:	2000-09-10 (actually submitted)
To:		gcc-bugs@gcc.gnu.org
Submitter:	James F. Carter <jimc@math.ucla.edu>

James F. Carter        Voice 310 825 2897	FAX 310 206 6673
UCLA-Mathnet;  6115 MSA; 405 Hilgard Ave.; Los Angeles, CA, USA  90095-1555
Internet: jimc@math.ucla.edu (finger for PGP key)
UUCP:...!{ucsd,ames,ncar,gatech,purdue,rutgers,decvax,uunet}!math.ucla.edu!jimc

Output complained about:

bug01.C: In function `int main()':
bug01.C:44: warning: choosing `T::operator int &()' over `T::operator const int &() const'
bug01.C:44: warning:   for conversion from `T' to `int'
bug01.C:44: warning:   because conversion sequence for the argument is better
*/

class T {
  private:
    int content;
  public:
    T() { }
    T(int c) : content(c) { }
    T(const T& t) : content(t.content) { }
    
    operator int& () { return content; }
    operator const int& () const { return content; }
};

int main() {
    T t(0);
    int c = t;		// <== Message here
    return c;
}

====== Response from the developer

>From aoliva@redhat.com Tue Sep 12 12:12:46 2000
Date: 12 Sep 2000 00:47:09 -0300
From: Alexandre Oliva <aoliva@redhat.com>
To: Jim Carter <jimc@math.ucla.edu>
Cc: gcc-bugs@gcc.gnu.org
Subject: Re: Noisy when choosing T::operator Type() vs T::op const Type()
    const

On Sep 10, 2000, Jim Carter <jimc@math.ucla.edu> wrote:

> // bug01.C -- Noisy when choosing T::operator Type() vs T::op const
> Type() const

The warning is in place because, without it, we used to get too many
``bug'' reports about GCC picking the ``wrong'' member function.
Disabling it by default would make it useless.  We might have a
command-line switch to disable it, though.

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                  aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist    *Please* write to mailing lists, not to me



More information about the Gcc-bugs mailing list