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]

PATCH to change warnings about const conversion to errors



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)
  		{


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