/* The following piece of code should not compile: According to [12.3.2/1], the conversion function operator X&() cannot be called. However, its presence tricks the compiler into thinking that I has a license to initialize a non-const X& from a const X&. This is illegal by [8.5.3/5]. I think that diagnostics is required in this case. Instead, g++ compiles this code, but the program segfaults. */ struct X { int x; X ( int i = 0 ) : x ( i ) {} operator X & ( void ) const { return ( *this ); } }; void add_one ( X & ref ) { ++ ref.x; } #include <iostream> int main ( void ) { X const a ( 2 ); add_one( a ); std::cout << a.x << '\n'; }
Hmm, we used to get a warning in 3.2.3 and before: t.cc:9: warning: conversion to a reference to the same type will never use a type conversion operator And it was rejected in 2.95.3: t.cc:9: warning: conversion to a reference to the same type will never use a type conversion operator t.cc:9: warning: conversion to a reference to the same type will never use a type conversion operator t.cc: In method `X::operator X &() const': t.cc:10: conversion from `const X' to `X &' discards qualifiers t.cc: In function `int main()': t.cc:23: conversion from `const X' to `X &' discards qualifiers t.cc:15: in passing argument 1 of `add_one(X &)'
Confirmed. We should not be calling the conversion operator. W.
When using -Wconverson: pr26698.cpp:24: warning: conversion to a reference to the same type will never use a type conversion operator Maybe this warning should be reported always?
The change was made on revision 110567 on gcc/cp/decl.c @@ -9012,7 +9011,7 @@ } if (what) - warning (0, "conversion to %s%s will never use a type " + warning (OPT_Wconversion, "conversion to %s%s will never use a type " "conversion operator", ref ? "a reference to " : "", what); }
Actually, it seems that the conditional on Wconversion was added before, at revision 100541 by mmitchel (Notice the warn_conversion flag below). @@ -8755,32 +8755,38 @@ if (operator_code == CALL_EXPR) return; - if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl)) + /* Warn about conversion operators that will never be used. */ + if (IDENTIFIER_TYPENAME_P (name) + && ! DECL_TEMPLATE_INFO (decl) + && warn_conversion + /* Warn only declaring the function; there is no need to + warn again about out-of-class definitions. */ + && class_type == current_class_type) { tree t = TREE_TYPE (name); - if (! friendp) - { - int ref = (TREE_CODE (t) == REFERENCE_TYPE); - const char *what = 0; + int ref = (TREE_CODE (t) == REFERENCE_TYPE); + const char *what = 0; - if (ref) - t = TYPE_MAIN_VARIANT (TREE_TYPE (t)); + if (ref) + t = TYPE_MAIN_VARIANT (TREE_TYPE (t)); - if (TREE_CODE (t) == VOID_TYPE) - what = "void"; - else if (t == current_class_type) + if (TREE_CODE (t) == VOID_TYPE) + what = "void"; + else if (class_type) + { + if (t == class_type) what = "the same type"; /* Don't force t to be complete here. */ else if (IS_AGGR_TYPE (t) && COMPLETE_TYPE_P (t) - && DERIVED_FROM_P (t, current_class_type)) + && DERIVED_FROM_P (t, class_type)) what = "a base class"; + } - if (what && warn_conversion) - warning (0, "conversion to %s%s will never use a type " - "conversion operator", - ref ? "a reference to " : "", what); - } + if (what) + warning (0, "conversion to %s%s will never use a type " + "conversion operator", + ref ? "a reference to " : "", what); } if (operator_code == COND_EXPR) {
Won't fix in GCC-4.0.x. Adjustine milestone.
Now in mainline things are better: 26698.C: In member function ‘X::operator X&() const’: 26698.C:25: error: invalid initialization of reference of type ‘X&’ from expression of type ‘const X’ I'm not sure whether an error at line 28 is mandatory together with the above one.
Mark?
Meant line *38* of course, sorry.
It looks to me that the change I made in Comment #5 was just an optimization; the warning was already conditionalized on warn_conversion. I just short-circuited the checking sooner. Declaring the conversion function is not illegal, so I think it's OK that we only warn conditionally. It's true that we should never use the conversion function. The error we're getting now is just a consequence of the body of the conversion function; if we put "return *new X" in there, it would compile file, and we probably wouldn't get an error about the program, even though it's still invalid. So, I do think that there's a bug somewhere; we shouldn't be considering this conversion operator when calling add_one.
By the way, confirmed the "return *new X" point.
Subject: Bug number PR c++/26698 A patch for this bug has been added to the patch tracker. The mailing list url for the patch is http://gcc.gnu.org/ml/gcc-patches/2007-10/msg00379.html
Subject: Bug 26698 Author: simartin Date: Fri Oct 12 18:43:33 2007 New Revision: 129274 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=129274 Log: gcc/cp/ 2007-10-12 Simon Martin <simartin@users.sourceforge.net> PR c++/26698 * call.c (build_user_type_conversion_1): Do not consider conversion functions to convert a (possibly cv-qualified) object to the (possibly cv-qualified) same object type (or a reference to it), to a (possibly cv-qualified) base class of that type (or a reference to it). gcc/testsuite/ 2007-10-12 Simon Martin <simartin@users.sourceforge.net> PR c++/26698 * g++.dg/conversion/op4.C: New test. Added: trunk/gcc/testsuite/g++.dg/conversion/op4.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/call.c trunk/gcc/testsuite/ChangeLog
Subject: Bug 26698 Author: simartin Date: Sat Oct 13 06:04:57 2007 New Revision: 129282 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=129282 Log: gcc/cp/ 2007-10-13 Simon Martin <simartin@users.sourceforge.net> PR c++/26698 * call.c (build_user_type_conversion_1): Do not consider conversion functions to convert a (possibly cv-qualified) object to the (possibly cv-qualified) same object type (or a reference to it), to a (possibly cv-qualified) base class of that type (or a reference to it). gcc/testsuite/ 2007-10-13 Simon Martin <simartin@users.sourceforge.net> PR c++/26698 * g++.dg/conversion/op4.C: New test. Added: branches/gcc-4_2-branch/gcc/testsuite/g++.dg/conversion/op4.C Modified: branches/gcc-4_2-branch/gcc/cp/ChangeLog branches/gcc-4_2-branch/gcc/cp/call.c branches/gcc-4_2-branch/gcc/testsuite/ChangeLog
Fixed on all the active branches.
*** Bug 36430 has been marked as a duplicate of this bug. ***