PATCH:mutable const objects

Nathan Sidwell nathan@acm.org
Thu Jan 14 08:40:00 GMT 1999


Hi,
back in November I submitted a patch to stop g++ placing mutable objects in a
read only section ( http://www.cygnus.com/ml/egcs-patches/1998-Nov/0452.html ),
bug report at http://www.cygnus.com/ml/egcs-bugs/1998-Jul/0346.html . Such
behaviour causes a seg fault when the program tries to alter the mutable
member.

For reasons that I am unaware of (probably too many other things to do I
guess), that patch was never applied. Subsequent compiler changes have caused
the patch to atrophy (`patch' no longer succeeds due to other local changes).
Here is a re-diffed version of the patch against the 19990112 snapshot. The
logic of the patch remains the same, and I copy that here,

I've added a new bitfield flag, has_mutable, to the lang_type struct.
this should be set on any structure which contains at least one mutable
member (recursively). I set this in finish_struct_1. Then in
cp_finish_decl, I clear the decl's TREE_READONLY if the type is a class
with mutables.

Two new macros are involved, CLASSTYPE_HAS_MUTABLE, which directly
access a class's has_mutable flag. And TYPE_HAS_MUTABLE_P which works
for any type (arrays are traversed and non class types return 0).

I attach both the patch file and a test case I inserted into my local copy of
the testsuite (testsuite/g++.old-deja/g++.other/mutable.C seemed a sensible
place). running the g++ testsuite with and without the patch gives the
following results,

without patch
FAIL: g++.other/mutable.C  Execution test

                === g++ Summary ===

# of expected passes            4798
# of unexpected failures        1
# of expected failures          87
# of untested testcases         6

with patch
Running /local/nathan/egcs/gcc/testsuite/g++.old-deja/old-deja.exp ...

                === g++ Summary ===
    
# of expected passes            4799
# of expected failures          87
# of untested testcases         6

I hope this is satisfactory, if not let me know what I need to add.

nathan
-- 
Dr Nathan Sidwell :: Computer Science Department :: Bristol University
      You can up the bandwidth, but you can't up the speed of light      
nathan@acm.org  http://www.cs.bris.ac.uk/~nathan/  nathan@cs.bris.ac.uk
cp/ChangeLog
Thu Jan 14 14:14:32 GMT 1999  Nathan Sidwell  <nathan@acm.org>

	* cp-tree.h (struct lang_type): Added has_mutable flag.
	(CLASSTYPE_HAS_MUTABLE): New macro to access it.
	(TYPE_HAS_MUTABLE_P): New macro to read it.
	(cp_has_mutable_p): Prototype for new function.
	* class.c (finish_struct_1): Set has_mutable from members.
	* decl.c (cp_finish_decl): Clear decl's TREE_READONLY flag, if
	it contains a mutable.
	* typeck.c (cp_has_mutable_p): New function.

Index: cp/class.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/class.c,v
retrieving revision 1.124
diff -c -3 -p -r1.124 class.c
*** class.c	1998/12/16 21:15:07	1.124
--- class.c	1999/01/14 15:12:08
*************** finish_struct_1 (t, warn_anon)
*** 3316,3321 ****
--- 3316,3322 ----
    int cant_have_default_ctor;
    int cant_have_const_ctor;
    int no_const_asn_ref;
+   int has_mutable = 0;
  
    /* The index of the first base class which has virtual
       functions.  Only applied to non-virtual baseclasses.  */
*************** finish_struct_1 (t, warn_anon)
*** 3578,3583 ****
--- 3579,3587 ----
        if (TREE_CODE (TREE_TYPE (x)) == POINTER_TYPE)
  	has_pointers = 1;
  
+       if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (TREE_TYPE (x)))
+         has_mutable = 1;
+ 
        /* If any field is const, the structure type is pseudo-const.  */
        if (TREE_READONLY (x))
  	{
*************** finish_struct_1 (t, warn_anon)
*** 3794,3799 ****
--- 3798,3804 ----
    CLASSTYPE_READONLY_FIELDS_NEED_INIT (t) = const_sans_init;
    CLASSTYPE_REF_FIELDS_NEED_INIT (t) = ref_sans_init;
    CLASSTYPE_ABSTRACT_VIRTUALS (t) = abstract_virtuals;
+   CLASSTYPE_HAS_MUTABLE (t) = has_mutable;
  
    /* Effective C++ rule 11.  */
    if (has_pointers && warn_ecpp && TYPE_HAS_CONSTRUCTOR (t)
Index: cp/decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.291
diff -c -3 -p -r1.291 decl.c
*** decl.c	1999/01/06 23:37:58	1.291
--- decl.c	1999/01/14 15:12:13
*************** cp_finish_decl (decl, init, asmspec_tree
*** 7369,7374 ****
--- 7369,7377 ----
        return;
      }
  
+   if (TYPE_HAS_MUTABLE_P (type))
+     TREE_READONLY (decl) = 0;
+   
    if (processing_template_decl)
      {
        if (init && DECL_INITIAL (decl))
Index: cp/typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck.c,v
retrieving revision 1.133
diff -c -3 -p -r1.133 typeck.c
*** typeck.c	1999/01/06 20:57:36	1.133
--- typeck.c	1999/01/14 15:12:15
*************** cp_type_quals (type)
*** 7471,7473 ****
--- 7471,7485 ----
  
    return TYPE_QUALS (type);
  }
+ 
+ /* Returns non-zero if the TYPE contains a mutable member */
+ 
+ int
+ cp_has_mutable_p (type)
+      tree type;
+ {
+   while (TREE_CODE (type) == ARRAY_TYPE)
+     type = TREE_TYPE (type);
+ 
+   return CLASS_TYPE_P (type) && CLASSTYPE_HAS_MUTABLE (type);
+ }
Index: cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.186
diff -c -3 -p -r1.186 cp-tree.h
*** cp-tree.h	1999/01/12 02:06:57	1.186
--- cp-tree.h	1999/01/14 15:12:16
*************** struct lang_type
*** 726,736 ****
        unsigned has_abstract_assign_ref : 1;
        unsigned non_aggregate : 1;
        unsigned is_partial_instantiation : 1;
  
        /* The MIPS compiler gets it wrong if this struct also
  	 does not fill out to a multiple of 4 bytes.  Add a
  	 member `dummy' with new bits if you go over the edge.  */
!       unsigned dummy : 11;
      } type_flags;
  
    int n_ancestors;
--- 726,737 ----
        unsigned has_abstract_assign_ref : 1;
        unsigned non_aggregate : 1;
        unsigned is_partial_instantiation : 1;
+       unsigned has_mutable : 1;
  
        /* The MIPS compiler gets it wrong if this struct also
  	 does not fill out to a multiple of 4 bytes.  Add a
  	 member `dummy' with new bits if you go over the edge.  */
!       unsigned dummy : 10;
      } type_flags;
  
    int n_ancestors;
*************** struct lang_type
*** 1037,1042 ****
--- 1038,1047 ----
  /* Ditto, for operator=.  */
  #define TYPE_HAS_NONPUBLIC_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_nonpublic_assign_ref)
  
+ /* Nonzero means that this type contains a mutable member */
+ #define CLASSTYPE_HAS_MUTABLE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_mutable)
+ #define TYPE_HAS_MUTABLE_P(NODE) (cp_has_mutable_p (NODE))
+ 
  /* Many routines need to cons up a list of basetypes for access
     checking.  This field contains a TREE_LIST node whose TREE_VALUE
     is the main variant of the type, and whose TREE_VIA_PUBLIC
*************** extern int comp_ptr_ttypes			PROTO((tree
*** 3372,3377 ****
--- 3377,3383 ----
  extern int ptr_reasonably_similar		PROTO((tree, tree));
  extern tree build_ptrmemfunc			PROTO((tree, tree, int));
  extern int cp_type_quals                        PROTO((tree));
+ extern int cp_has_mutable_p                     PROTO((tree));
  extern int at_least_as_qualified_p              PROTO((tree, tree));
  extern int more_qualified_p                     PROTO((tree, tree));
  


More information about the Gcc-patches mailing list