Bug 26698 - [4.0/4.1/4.2/4.3 Regression] g++ accepts const-incorrect code due to conversion function
Summary: [4.0/4.1/4.2/4.3 Regression] g++ accepts const-incorrect code due to conversi...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.1.0
: P2 normal
Target Milestone: 4.1.3
Assignee: Not yet assigned to anyone
URL:
Keywords: accepts-invalid
: 36430 (view as bug list)
Depends on: 10915
Blocks:
  Show dependency treegraph
 
Reported: 2006-03-15 16:10 UTC by Kai-Uwe Bux
Modified: 2008-08-21 12:04 UTC (History)
8 users (show)

See Also:
Host:
Target:
Build:
Known to work: 2.95.3
Known to fail:
Last reconfirmed: 2006-05-26 15:37:05


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Kai-Uwe Bux 2006-03-15 16:10:09 UTC
/*
  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';
}
Comment 1 Andrew Pinski 2006-03-15 16:19:41 UTC
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 &)'
Comment 2 Wolfgang Bangerth 2006-05-26 15:37:05 UTC
Confirmed. We should not be calling the conversion operator.
W.
Comment 3 Manuel López-Ibáñez 2006-09-16 01:48:09 UTC
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?

Comment 4 Manuel López-Ibáñez 2006-09-16 21:14:31 UTC
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);
        }
Comment 5 Manuel López-Ibáñez 2006-09-16 21:34:49 UTC
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)
        {
Comment 6 Gabriel Dos Reis 2007-02-03 16:24:55 UTC
Won't fix in GCC-4.0.x.  Adjustine milestone.
Comment 7 Paolo Carlini 2007-09-07 00:34:08 UTC
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.
Comment 8 Paolo Carlini 2007-09-07 00:36:14 UTC
Mark?
Comment 9 Paolo Carlini 2007-09-07 00:39:03 UTC
Meant line *38* of course, sorry.
Comment 10 Mark Mitchell 2007-09-07 23:50:23 UTC
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.
Comment 11 Paolo Carlini 2007-10-02 15:47:12 UTC
By the way, confirmed the "return *new X" point.
Comment 12 patchapp@dberlin.org 2007-10-07 19:50:18 UTC
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
Comment 13 Simon Martin 2007-10-12 18:43:44 UTC
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

Comment 14 Simon Martin 2007-10-13 06:05:09 UTC
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

Comment 15 Simon Martin 2007-10-13 06:17:07 UTC
Fixed on all the active branches.
Comment 16 Paolo Carlini 2008-08-21 12:04:22 UTC
*** Bug 36430 has been marked as a duplicate of this bug. ***