This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH to change warnings about const conversion to errors
- To: egcs-patches at cygnus dot com
- Subject: PATCH to change warnings about const conversion to errors
- From: Mark Mitchell <mark at markmitchell dot com>
- Date: Sun, 4 Oct 1998 11:36:56 -0700
- Cc: Jason Merrill <jason at cygnus dot com>
- Reply-to: mark at markmitchell dot com
Historically, g++ has been very lenient about const correctness. For
example, you were allowed to call non-const member functions on a
const object, receiving only a warning in the process. Jason and I
agreed that it's time to bring g++'s behavior in line with most other
compilers, and make these real errors. (One reason is that abuse of
const might lead to very hard to find bugs at program run-time.) Use
explicit casts if you really want to subvert the type system.
In addition, I noticed that we did not correctly flag
int f();
const volatile int& i = f();
as erroneous; you can bind a const reference to an rvalue only if the
reference is not also volatile.
--
Mark Mitchell mark@markmitchell.com
Mark Mitchell Consulting http://www.markmitchell.com
1998-10-04 Mark Mitchell <mark@markmitchell.com>
* call.c (build_over_call): Make pedwarns about dropped qualifiers
into full-fledged errors.
* cvt.c (convert_to_reference): Likewise.
* typeck.c (convert_for_assignment): Likewise.
Index: testsuite/g++.old-deja/g++.brendan/crash39.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.brendan/crash39.C,v
retrieving revision 1.4
diff -c -p -r1.4 crash39.C
*** crash39.C 1997/10/07 22:41:18 1.4
--- crash39.C 1998/10/04 18:01:36
*************** public:
*** 29,33 ****
#include <string>
class foo {public: foo () {}};
! class bar {public: bar (foo& dflt);};
class baz: public bar {public: baz (): bar (foo ()) {}};
--- 29,33 ----
#include <string>
class foo {public: foo () {}};
! class bar {public: bar (const foo& dflt);};
class baz: public bar {public: baz (): bar (foo ()) {}};
Index: testsuite/g++.old-deja/g++.brendan/reference1.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.brendan/reference1.C,v
retrieving revision 1.1.1.1
diff -c -p -r1.1.1.1 reference1.C
*** reference1.C 1997/08/19 07:35:07 1.1.1.1
--- reference1.C 1998/10/04 18:01:36
***************
*** 12,21 ****
extern "C" void printf (char *, ...);
struct base {
! int data_member;
base () {}
! void function_member ();
};
base base_object;
--- 12,21 ----
extern "C" void printf (char *, ...);
struct base {
! mutable int data_member;
base () {}
! void function_member () const;
};
base base_object;
*************** int call_count = 0;
*** 26,32 ****
int main ()
{
! base& base_ref = base_returning_function ();
base_ref.function_member ();
base_ref.function_member ();
--- 26,32 ----
int main ()
{
! const base& base_ref = base_returning_function ();
base_ref.function_member ();
base_ref.function_member ();
*************** base base_returning_function ()
*** 48,53 ****
return local_base_object;
}
! void base::function_member ()
{
}
--- 48,53 ----
return local_base_object;
}
! void base::function_member () const
{
}
Index: testsuite/g++.old-deja/g++.mike/p785.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.mike/p785.C,v
retrieving revision 1.4
diff -c -p -r1.4 p785.C
*** p785.C 1998/05/06 21:08:43 1.4
--- p785.C 1998/10/04 18:01:56
*************** and this notice must be preserved on all
*** 6883,6889 ****
typedef void (*GctNameRefProcedure)(GctNameRef&);
typedef GctNameRef (*GctNameRefMapper)(GctNameRef&);
! typedef GctNameRef (*GctNameRefCombiner)(GctNameRef&, GctNameRef&);
typedef int (*GctNameRefPredicate)(GctNameRef&);
typedef int (*GctNameRefComparator)(GctNameRef&, GctNameRef&);
--- 6883,6890 ----
typedef void (*GctNameRefProcedure)(GctNameRef&);
typedef GctNameRef (*GctNameRefMapper)(GctNameRef&);
! typedef GctNameRef& (*GctNameRefCombiner)(const GctNameRef&,
! const GctNameRef&);
typedef int (*GctNameRefPredicate)(GctNameRef&);
typedef int (*GctNameRefComparator)(GctNameRef&, GctNameRef&);
*************** public:
*** 6916,6926 ****
GctNameRefList();
GctNameRefList(GctNameRef& head);
GctNameRefList(GctNameRef& head, GctNameRefList& tl);
! GctNameRefList(GctNameRefList& a);
GctNameRefList(Pix p);
~GctNameRefList();
! GctNameRefList& operator = (GctNameRefList& a);
int null();
int valid();
--- 6917,6927 ----
GctNameRefList();
GctNameRefList(GctNameRef& head);
GctNameRefList(GctNameRef& head, GctNameRefList& tl);
! GctNameRefList(const GctNameRefList& a);
GctNameRefList(Pix p);
~GctNameRefList();
! GctNameRefList& operator = (const GctNameRefList& a);
int null();
int valid();
*************** inline void dereference(GctNameRefListNo
*** 7003,7013 ****
}
! inline GctNameRefListNode* newGctNameRefListNode(GctNameRef& h)
{
GctNameRefListNode* p = new GctNameRefListNode;
p->ref = 1;
! p->hd = h;
return p;
}
--- 7004,7014 ----
}
! inline GctNameRefListNode* newGctNameRefListNode(const GctNameRef& h)
{
GctNameRefListNode* p = new GctNameRefListNode;
p->ref = 1;
! p->hd = (GctNameRef&) h;
return p;
}
*************** inline GctNameRefList::GctNameRefList(Gc
*** 7048,7056 ****
reference(P->tl);
}
! inline GctNameRefList::GctNameRefList(GctNameRefList& a)
{
! reference(a.P);
P = a.P;
}
--- 7049,7058 ----
reference(P->tl);
}
! inline GctNameRefList::GctNameRefList(const GctNameRefList& a)
{
! GctNameRefList& gl = (GctNameRefList&) a;
! reference(gl.P);
P = a.P;
}
*************** public:
*** 7151,7157 ****
static init_NilGctNameRefListNode NilGctNameRefListNode_initializer;
! GctNameRefList& GctNameRefList::operator = (GctNameRefList& a)
{
reference(a.P);
dereference(P);
--- 7153,7159 ----
static init_NilGctNameRefListNode NilGctNameRefListNode_initializer;
! GctNameRefList& GctNameRefList::operator = (const GctNameRefList& a)
{
reference(a.P);
dereference(P);
Index: testsuite/g++.old-deja/g++.other/ref1.C
===================================================================
RCS file: ref1.C
diff -N ref1.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- ref1.C Sun Oct 4 11:01:56 1998
***************
*** 0 ****
--- 1,10 ----
+ // Build don't link:
+
+ int f();
+
+ void g()
+ {
+ const int& i = f(); // OK
+ int& j = f(); // ERROR - initialization of non-const reference
+ const volatile int& k = f(); // ERROR - initialization of volatile ref
+ }
Index: cp/call.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/call.c,v
retrieving revision 1.107
diff -c -p -r1.107 call.c
*** call.c 1998/09/15 17:04:53 1.107
--- call.c 1998/10/04 18:07:26
*************** build_over_call (cand, args, flags)
*** 3297,3304 ****
char *p = (dv && dc ? "const and volatile"
: dc ? "const" : dv ? "volatile" : "");
! cp_pedwarn ("passing `%T' as `this' argument of `%#D' discards %s",
! TREE_TYPE (argtype), fn, p);
}
/* [class.mfct.nonstatic]: If a nonstatic member function of a class
X is called for an object that is not of type X, or of a type
--- 3297,3304 ----
char *p = (dv && dc ? "const and volatile"
: dc ? "const" : dv ? "volatile" : "");
! cp_error ("passing `%T' as `this' argument of `%#D' discards %s",
! TREE_TYPE (argtype), fn, p);
}
/* [class.mfct.nonstatic]: If a nonstatic member function of a class
X is called for an object that is not of type X, or of a type
Index: cp/cvt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cvt.c,v
retrieving revision 1.33
diff -c -p -r1.33 cvt.c
*** cvt.c 1998/10/03 23:11:08 1.33
--- cvt.c 1998/10/04 18:07:40
*************** convert_to_reference (reftype, expr, con
*** 450,473 ****
tree ttl = TREE_TYPE (reftype);
tree ttr = lvalue_type (expr);
! if (! real_lvalue_p (expr) && ! TYPE_READONLY (ttl))
{
! if (decl)
! /* Ensure semantics of [dcl.init.ref] */
! cp_pedwarn ("initialization of non-const reference `%#T' from rvalue `%T'",
! reftype, intype);
else
! cp_pedwarn ("conversion to non-const `%T' from rvalue `%T'",
! reftype, intype);
}
else if (! (convtype & CONV_CONST))
{
if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
! cp_pedwarn ("conversion from `%T' to `%T' discards const",
! ttr, reftype);
else if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
! cp_pedwarn ("conversion from `%T' to `%T' discards volatile",
! ttr, reftype);
}
}
--- 450,483 ----
tree ttl = TREE_TYPE (reftype);
tree ttr = lvalue_type (expr);
! /* [dcl.init.ref] says that if an rvalue is used to
! initialize a reference, then the reference must be to a
! non-volatile const type. */
! if (! real_lvalue_p (expr)
! && (!TYPE_READONLY (ttl) || TYPE_VOLATILE (ttl)))
{
! char* msg;
!
! if (TYPE_VOLATILE (ttl) && decl)
! msg = "initialization of volatile reference type `%#T'";
! else if (TYPE_VOLATILE (ttl))
! msg = "conversion to volatile reference type `%#T'";
! else if (decl)
! msg = "initialization of non-const reference type `%#T'";
else
! msg = "conversion to non-const reference type `%#T'";
!
! cp_error (msg, reftype);
! cp_error ("from rvalue of type `%T'", intype);
}
else if (! (convtype & CONV_CONST))
{
if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
! cp_error ("conversion from `%T' to `%T' discards const",
! ttr, reftype);
else if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
! cp_error ("conversion from `%T' to `%T' discards volatile",
! ttr, reftype);
}
}
Index: cp/typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck.c,v
retrieving revision 1.112
diff -c -p -r1.112 typeck.c
*** typeck.c 1998/10/03 23:11:19 1.112
--- typeck.c 1998/10/04 18:08:04
*************** convert_for_assignment (type, rhs, errty
*** 6808,6827 ****
if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
{
if (fndecl)
! cp_pedwarn ("passing `%T' as argument %P of `%D' discards const",
! rhstype, parmnum, fndecl);
else
! cp_pedwarn ("%s to `%T' from `%T' discards const",
! errtype, type, rhstype);
}
if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
{
if (fndecl)
! cp_pedwarn ("passing `%T' as argument %P of `%D' discards volatile",
! rhstype, parmnum, fndecl);
else
! cp_pedwarn ("%s to `%T' from `%T' discards volatile",
! errtype, type, rhstype);
}
}
--- 6808,6827 ----
if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
{
if (fndecl)
! cp_error ("passing `%T' as argument %P of `%D' discards const",
! rhstype, parmnum, fndecl);
else
! cp_error ("%s to `%T' from `%T' discards const",
! errtype, type, rhstype);
}
if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
{
if (fndecl)
! cp_error ("passing `%T' as argument %P of `%D' discards volatile",
! rhstype, parmnum, fndecl);
else
! cp_error ("%s to `%T' from `%T' discards volatile",
! errtype, type, rhstype);
}
}
*************** convert_for_assignment (type, rhs, errty
*** 6874,6892 ****
if (string_conv_p (type, rhs, 1))
/* converting from string constant to char *, OK. */;
else if (fndecl)
! cp_pedwarn ("passing `%T' as argument %P of `%D' discards const",
! rhstype, parmnum, fndecl);
else
! cp_pedwarn ("%s to `%T' from `%T' discards const",
errtype, type, rhstype);
}
else if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
{
if (fndecl)
! cp_pedwarn ("passing `%T' as argument %P of `%D' discards volatile",
rhstype, parmnum, fndecl);
else
! cp_pedwarn ("%s to `%T' from `%T' discards volatile",
errtype, type, rhstype);
}
else if (TREE_CODE (ttl) == TREE_CODE (ttr)
--- 6874,6892 ----
if (string_conv_p (type, rhs, 1))
/* converting from string constant to char *, OK. */;
else if (fndecl)
! cp_error ("passing `%T' as argument %P of `%D' discards const",
! rhstype, parmnum, fndecl);
else
! cp_error ("%s to `%T' from `%T' discards const",
errtype, type, rhstype);
}
else if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
{
if (fndecl)
! cp_error ("passing `%T' as argument %P of `%D' discards volatile",
rhstype, parmnum, fndecl);
else
! cp_error ("%s to `%T' from `%T' discards volatile",
errtype, type, rhstype);
}
else if (TREE_CODE (ttl) == TREE_CODE (ttr)
*************** convert_for_assignment (type, rhs, errty
*** 6948,6967 ****
if (const_parity)
{
if (fndecl)
! cp_pedwarn ("passing `%T' as argument %P of `%D' discards const",
! rhstype, parmnum, fndecl);
else
! cp_pedwarn ("%s to `%T' from `%T' discards const",
errtype, type, rhstype);
}
if (volatile_parity)
{
if (fndecl)
! cp_pedwarn ("passing `%T' as argument %P of `%D' discards volatile",
! rhstype, parmnum, fndecl);
else
! cp_pedwarn ("%s to `%T' from `%T' discards volatile",
! errtype, type, rhstype);
}
if (unsigned_parity > 0)
{
--- 6948,6967 ----
if (const_parity)
{
if (fndecl)
! cp_error ("passing `%T' as argument %P of `%D' discards const",
! rhstype, parmnum, fndecl);
else
! cp_error ("%s to `%T' from `%T' discards const",
errtype, type, rhstype);
}
if (volatile_parity)
{
if (fndecl)
! cp_error ("passing `%T' as argument %P of `%D' discards volatile",
! rhstype, parmnum, fndecl);
else
! cp_error ("%s to `%T' from `%T' discards volatile",
! errtype, type, rhstype);
}
if (unsigned_parity > 0)
{