This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR c++/26698: g++ accepts const-incorrect code due to conversion function


Hi all.

This PR was opened because we would not handle the following snippet
properly:

=== cut here ===
struct X {
       int x;
       X ( int i = 0 )
         : x ( i )
       {}
       operator X & ( void ) const {
         return ( *this );
       }
};
void add_one ( X & ref ) {
       ++ ref.x;
}
int main ( void ) {
       X const a ( 2 );
       add_one( a );
}
=== cut here ===

At the time this PR was opened, we would accept it without complaining,
while there are two problems:
      1. The body of "operator X&" is invalid because it returns a
non-const reference to the const object it's called on.
      2. This operator should not be considered when calling add_one,
because the standard states that "A conversion function is never used 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)".

The first point is now properly rejected, but the second one is still
present.

The attached patch modifies build_user_type_conversion_1 so that
conversion operators are not considered when they should not according
to the standard.

I have successfully regtested it on i386-apple-darwin8.10.1. Is it OK
for the mainline? For 4.2 after 4.2.2 is released?

Best regards,
Simon

:ADDPATCH c++:





2007-10-07  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).





Index: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c	(revision 129069)
+++ gcc/cp/call.c	(working copy)
@@ -2601,7 +2601,22 @@ build_user_type_conversion_1 (tree totyp
     ctors = lookup_fnfields (totype, complete_ctor_identifier, 0);
 
   if (IS_AGGR_TYPE (fromtype))
-    conv_fns = lookup_conversions (fromtype);
+    {
+      tree to_main = TYPE_MAIN_VARIANT (non_reference (totype));
+      tree from_main = TYPE_MAIN_VARIANT (fromtype);
+      if (same_type_p (to_main, from_main) ||
+	  (CLASS_TYPE_P (to_main) && CLASS_TYPE_P (from_main)
+	   && DERIVED_FROM_P (to_main, from_main)))
+	{
+	  /* [class.conv.fct] A conversion function is never used 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)...  */
+	}
+      else
+	conv_fns = lookup_conversions (fromtype);
+    }
 
   candidates = 0;
   flags |= LOOKUP_NO_CONVERSION;





2007-10-07  Simon Martin  <simartin@users.sourceforge.net>

	PR c++/26698
	* g++.dg/conversion/op4.C: New test.





/* PR c++/26698 */
/* { dg-do "compile" } */

struct X {
  int x;
  X (int i = 0) : x (i) {}
  operator X& (void) const {
    return *(new X);
  }
};

void add_one (X & ref) { /* { dg-error "in passing argument" } */
  ++ ref.x;
}

void foo() {
  X const a (2);
  add_one(a); /* { dg-error "invalid initialization of reference of type" } */
}






Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]