This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR c++/26698: g++ accepts const-incorrect code due to conversion function
- From: Simon Martin <simartin at users dot sourceforge dot net>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 07 Oct 2007 21:49:49 +0200
- Subject: [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" } */
}