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:mutable const objects


Here's a patch which fixes
http://www.cygnus.com/ml/egcs-bugs/1998-Jul/0346.html where a constant
object with a mutable member and a simple initializer would be placed in
.rodata rather than .data (ore equivalent sections on other
architectures). There was some discussion at
http://www.cygnus.com/ml/egcs/1998-Aug/0050.html about how to fix this.

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, after any DECL_INITIAL is attached, if that is
TREE_CONSTANT, I check whether the type is a class with mutables. If so,
the TREE_CONSTANT is removed. 

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

A test case is included which the current egcs places all the static
objects in rodata (and consequently segfaults at runtime).

I've stayed clear of the tortuous nature of SELECT_SECTION, this is just
a C++ patch.

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
egcs/gcc/cp/ChangeLog

Tue Oct 27 16:09:18 GMT 1998  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): New macro to read it.
	(cp_has_mutable): Prototype for new function.
	* class.c(finish_struct_1): Set has_mutable from members.
	* decl.c(cp_finish_decl): Check has_mutable to inhibit constant
	initializer.
	* typeck.c(cp_has_mutable): New function.

Index: egcs/gcc/cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.159
diff -c -3 -p -r1.159 cp-tree.h
*** cp-tree.h	1998/10/23 14:52:56	1.159
--- cp-tree.h	1998/10/27 17:44:36
*************** struct lang_type
*** 655,660 ****
--- 655,661 ----
        unsigned has_complex_assign_ref : 1;
        unsigned has_abstract_assign_ref : 1;
        unsigned non_aggregate : 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
*************** struct lang_type
*** 950,955 ****
--- 951,962 ----
  /* 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(NODE)        \
+     (TREE_CODE (NODE) == ARRAY_TYPE ? cp_has_mutable (NODE) \
+     : CLASS_TYPE_P (NODE) && CLASSTYPE_HAS_MUTABLE (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
*** 3197,3202 ****
--- 3204,3210 ----
  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                       PROTO((tree));
  extern int at_least_as_qualified_p              PROTO((tree, tree));
  extern int more_qualified_p                     PROTO((tree, tree));
  
Index: egcs/gcc/cp/class.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/class.c,v
retrieving revision 1.98
diff -c -3 -p -r1.98 class.c
*** class.c	1998/10/23 14:52:55	1.98
--- class.c	1998/10/27 17:44:39
*************** finish_struct_1 (t, warn_anon)
*** 3288,3293 ****
--- 3288,3294 ----
    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)
*** 3546,3551 ****
--- 3547,3555 ----
        if (TREE_CODE (TREE_TYPE (x)) == POINTER_TYPE)
  	has_pointers = 1;
  
+       if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE (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)
*** 3761,3766 ****
--- 3765,3771 ----
    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: egcs/gcc/cp/decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.244
diff -c -3 -p -r1.244 decl.c
*** decl.c	1998/10/25 23:15:00	1.244
--- decl.c	1998/10/27 17:44:43
*************** cp_finish_decl (decl, init, asmspec_tree
*** 7714,7719 ****
--- 7714,7725 ----
  		}
  	    }
  	}
+ 
+     /* if it looks constant, but has a mutable, then mark it non-constant */
+     if (DECL_INITIAL (decl) && TREE_CONSTANT (DECL_INITIAL (decl))
+         && TYPE_HAS_MUTABLE (TREE_TYPE (decl)))
+       TREE_CONSTANT (DECL_INITIAL (decl)) = 0;
+       
      finish_end0:
  
        /* Undo call to `pushclass' that was done in `start_decl'
Index: egcs/gcc/cp/typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck.c,v
retrieving revision 1.119
diff -c -3 -p -r1.119 typeck.c
*** typeck.c	1998/10/23 14:53:28	1.119
--- typeck.c	1998/10/27 17:44:45
*************** cp_type_quals (type)
*** 7630,7632 ****
--- 7630,7644 ----
  
    return TYPE_QUALS (type);
  }
+ 
+ /* Returns non-zero if the TYPE contains a mutable member */
+ 
+ int
+ cp_has_mutable (type)
+      tree type;
+ {
+   while (TREE_CODE (type) == ARRAY_TYPE)
+     type = TREE_TYPE (type);
+ 
+   return CLASS_TYPE_P (type) && CLASSTYPE_HAS_MUTABLE (type);
+ }
struct A
{
  mutable int i;
};

struct B
{
  A a;
};

struct C
{
  A a[1];
};
static const A a = {0};
static const B b = {{0}};
static const C c = {{{0}}};
static const A aa[] = {{0}};
static const B bb[] = {{{0}}};
static const C cc[] = {{{{0}}}};
int main(int argc, char **argv)
{
  switch(argc)
    {
      case 1:
        a.i = 5;
      case 2:
        b.a.i = 5;
      case 3:
        c.a[0].i = 5;
      case 4:
        aa[0].i = 5;
      case 5:
        bb[0].a.i = 5;
      case 6:
        cc[0].a[0].i = 5;
    }
  return 0;
}

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