This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH:mutable const objects
- To: egcs-patches at cygnus dot com
- Subject: PATCH:mutable const objects
- From: Nathan Sidwell <nathan at acm dot org>
- Date: Wed, 28 Oct 1998 09:24:37 +0000
- Organization: Computer Science Dept, Bristol University
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;
}