diff options
author | Alexandre Oliva <aoliva@redhat.com> | 2002-05-14 17:20:47 +0000 |
---|---|---|
committer | Alexandre Oliva <aoliva@gcc.gnu.org> | 2002-05-14 17:20:47 +0000 |
commit | 94e6e4c4f3d7533ab1de7b709e3b3305d3d8e52d (patch) | |
tree | 8e6a21c939257492f2f1761473f122f6de4c33dd /gcc | |
parent | e5f5feea65f904d95c6f7aded34f8d2f447141e9 (diff) | |
download | gcc-94e6e4c4f3d7533ab1de7b709e3b3305d3d8e52d.zip gcc-94e6e4c4f3d7533ab1de7b709e3b3305d3d8e52d.tar.gz gcc-94e6e4c4f3d7533ab1de7b709e3b3305d3d8e52d.tar.bz2 |
cp-tree.h (struct lang_type): Added non_zero_init.
* cp-tree.h (struct lang_type): Added non_zero_init.
(CLASS_NON_ZERO_INIT_P): New macro.
(zero_init_p, force_store_init_value, build_forced_zero_init): Declare.
* class.c (check_field_decls): Test non_zero_init.
* cvt.c (convert_to_pointer_force): Use cp_convert_to_pointer for
zero-to-NULL conversions.
* decl.c (obscure_complex_init): Don't reset DECL_INITIAL of a
type that needs zero-initialization without zeros.
(check_initializer_decl): Compute zero-initializer for types
that require a non-trivial one.
* init.c (build_forced_zero_init): New function.
(build_default_init): Use it.
* tree.c (zero_init_p): New function.
* typeck2.c (force_store_init_value): New function.
(process_init_constructor): Create non-trivial zero-initializers
for array members and class fields.
From-SVN: r53461
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 19 | ||||
-rw-r--r-- | gcc/cp/class.c | 3 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 14 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 9 | ||||
-rw-r--r-- | gcc/cp/decl.c | 16 | ||||
-rw-r--r-- | gcc/cp/init.c | 62 | ||||
-rw-r--r-- | gcc/cp/tree.c | 23 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 35 |
8 files changed, 143 insertions, 38 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 12e90cf..b5dcccd 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,22 @@ +2002-05-14 Alexandre Oliva <aoliva@redhat.com> + + * cp-tree.h (struct lang_type): Added non_zero_init. + (CLASS_NON_ZERO_INIT_P): New macro. + (zero_init_p, force_store_init_value, build_forced_zero_init): Declare. + * class.c (check_field_decls): Test non_zero_init. + * cvt.c (convert_to_pointer_force): Use cp_convert_to_pointer for + zero-to-NULL conversions. + * decl.c (obscure_complex_init): Don't reset DECL_INITIAL of a + type that needs zero-initialization without zeros. + (check_initializer_decl): Compute zero-initializer for types + that require a non-trivial one. + * init.c (build_forced_zero_init): New function. + (build_default_init): Use it. + * tree.c (zero_init_p): New function. + * typeck2.c (force_store_init_value): New function. + (process_init_constructor): Create non-trivial zero-initializers + for array members and class fields. + 2002-05-14 Neil Booth <neil@daikokuya.demon.co.uk> * lang-specs.h: Remove redundant -lang-c++. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 98f32dc..64b528a 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -3405,6 +3405,9 @@ check_field_decls (t, access_decls, empty_p, to be allowed in POD structs. */ CLASSTYPE_NON_POD_P (t) = 1; + if (! zero_init_p (type)) + CLASSTYPE_NON_ZERO_INIT_P (t) = 1; + /* If any field is const, the structure type is pseudo-const. */ if (CP_TYPE_CONST_P (type)) { diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 0f2ad7c..a1d4ddb 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1240,6 +1240,8 @@ struct lang_type unsigned is_partial_instantiation : 1; unsigned java_interface : 1; + unsigned non_zero_init : 1; + /* When adding a flag here, consider whether or not it ought to apply to a template instance if it applies to the template. If so, make sure to copy it in instantiate_class_template! */ @@ -1247,7 +1249,7 @@ struct lang_type /* There are some bits left to fill out a 32-bit word. Keep track of this by updating the size of this bitfield whenever you add or remove a flag. */ - unsigned dummy : 8; + unsigned dummy : 7; int vsize; @@ -1501,9 +1503,14 @@ struct lang_type #define CLASSTYPE_HAS_MUTABLE(NODE) (TYPE_LANG_SPECIFIC (NODE)->has_mutable) #define TYPE_HAS_MUTABLE_P(NODE) (cp_has_mutable_p (NODE)) -/* Nonzero means that this class type is a non-POD class. */ +/* Nonzero means that this class type is a non-POD class. */ #define CLASSTYPE_NON_POD_P(NODE) (TYPE_LANG_SPECIFIC (NODE)->non_pod_class) +/* Nonzero means that this class contains pod types whose default + initialization is not a zero initialization (namely, pointers to + data members). */ +#define CLASSTYPE_NON_ZERO_INIT_P(NODE) (TYPE_LANG_SPECIFIC (NODE)->non_zero_init) + /* Nonzero if this class is "nearly empty", i.e., contains only a virtual function table pointer. */ #define CLASSTYPE_NEARLY_EMPTY_P(NODE) \ @@ -3912,6 +3919,7 @@ extern tree build_init PARAMS ((tree, tree, int)); extern int is_aggr_type PARAMS ((tree, int)); extern tree get_aggr_from_typedef PARAMS ((tree, int)); extern tree get_type_value PARAMS ((tree)); +extern tree build_forced_zero_init PARAMS ((tree)); extern tree build_member_call PARAMS ((tree, tree, tree)); extern tree build_offset_ref PARAMS ((tree, tree)); extern tree resolve_offset_ref PARAMS ((tree)); @@ -4230,6 +4238,7 @@ extern tree cxx_unsave_expr_now PARAMS ((tree)); extern tree cxx_maybe_build_cleanup PARAMS ((tree)); extern void init_tree PARAMS ((void)); extern int pod_type_p PARAMS ((tree)); +extern int zero_init_p PARAMS ((tree)); extern tree canonical_type_variant PARAMS ((tree)); extern void unshare_base_binfos PARAMS ((tree)); extern int member_p PARAMS ((tree)); @@ -4376,6 +4385,7 @@ extern int abstract_virtuals_error PARAMS ((tree, tree)); #define my_friendly_assert(EXP, N) (void) \ (((EXP) == 0) ? (fancy_abort (__FILE__, __LINE__, __FUNCTION__), 0) : 0) +extern tree force_store_init_value PARAMS ((tree, tree)); extern tree store_init_value PARAMS ((tree, tree)); extern tree digest_init PARAMS ((tree, tree, tree *)); extern tree build_scoped_ref PARAMS ((tree, tree, tree *)); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index fc57dd3..0c43fc3 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -1,6 +1,6 @@ /* Language-level data type conversion for GNU C++. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GNU CC. @@ -288,13 +288,6 @@ convert_to_pointer_force (type, expr) register tree intype = TREE_TYPE (expr); register enum tree_code form = TREE_CODE (intype); - if (integer_zerop (expr)) - { - expr = build_int_2 (0, 0); - TREE_TYPE (expr) = type; - return expr; - } - if (form == POINTER_TYPE) { intype = TYPE_MAIN_VARIANT (intype); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index c854cb7..6c5b979 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -7592,7 +7592,13 @@ obscure_complex_init (decl, init) NULL_TREE); else #endif - DECL_INITIAL (decl) = error_mark_node; + { + if (zero_init_p (TREE_TYPE (decl))) + DECL_INITIAL (decl) = error_mark_node; + /* Otherwise, force_store_init_value will have already stored a + zero-init initializer in DECL_INITIAL, that should be + retained. */ + } return init; } @@ -7838,8 +7844,16 @@ check_initializer (decl, init) if (init) init = obscure_complex_init (decl, init); } + else if (!DECL_EXTERNAL (decl) && !zero_init_p (type)) + { + force_store_init_value (decl, build_forced_zero_init (type)); + + if (init) + goto process_init; + } else if (init) { + process_init: if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type)) { if (TREE_CODE (type) == ARRAY_TYPE) diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 49ecf7c..9827307 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1,6 +1,6 @@ /* Handle initialization things in C++. Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GNU CC. @@ -156,6 +156,44 @@ initialize_vtbl_ptrs (addr) dfs_marked_real_bases_queue_p, type); } +/* Types containing pointers to data members cannot be + zero-initialized with zeros, because the NULL value for such + pointers is -1. + + TYPE is a type that requires such zero initialization. The + returned value is the initializer. */ + +tree +build_forced_zero_init (type) + tree type; +{ + tree init = NULL; + + if (AGGREGATE_TYPE_P (type) && !TYPE_PTRMEMFUNC_P (type)) + { + /* This is a default initialization of an aggregate, but not one of + non-POD class type. We cleverly notice that the initialization + rules in such a case are the same as for initialization with an + empty brace-initialization list. */ + init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, NULL_TREE); + } + else if (TREE_CODE (type) == REFERENCE_TYPE) + /* --if T is a reference type, no initialization is performed. */ + return NULL_TREE; + else + { + init = integer_zero_node; + + if (TREE_CODE (type) == ENUMERAL_TYPE) + /* We must make enumeral types the right type. */ + init = fold (build1 (NOP_EXPR, type, init)); + } + + init = digest_init (type, init, 0); + + return init; +} + /* [dcl.init]: To default-initialize an object of type T means: @@ -182,28 +220,8 @@ build_default_init (type) anything with a CONSTRUCTOR for arrays here, as that would imply copy-initialization. */ return NULL_TREE; - else if (AGGREGATE_TYPE_P (type) && !TYPE_PTRMEMFUNC_P (type)) - { - /* This is a default initialization of an aggregate, but not one of - non-POD class type. We cleverly notice that the initialization - rules in such a case are the same as for initialization with an - empty brace-initialization list. */ - init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, NULL_TREE); - } - else if (TREE_CODE (type) == REFERENCE_TYPE) - /* --if T is a reference type, no initialization is performed. */ - return NULL_TREE; - else - { - init = integer_zero_node; - - if (TREE_CODE (type) == ENUMERAL_TYPE) - /* We must make enumeral types the right type. */ - init = fold (build1 (NOP_EXPR, type, init)); - } - init = digest_init (type, init, 0); - return init; + return build_forced_zero_init (type); } /* Subroutine of emit_base_init. */ diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 02d5a4b..9a52cc0 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1,6 +1,6 @@ /* Language-dependent node constructors for parse phase of GNU compiler. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GNU CC. @@ -1901,6 +1901,27 @@ pod_type_p (t) return 1; } +/* Returns 1 iff zero initialization of type T means actually storing + zeros in it. */ + +int +zero_init_p (t) + tree t; +{ + t = strip_array_types (t); + + /* NULL pointers to data members are initialized with -1. */ + if (TYPE_PTRMEM_P (t)) + return 0; + + /* Classes that contain types that can't be zero-initialized, cannot + be zero-initialized themselves. */ + if (CLASS_TYPE_P (t) && CLASSTYPE_NON_ZERO_INIT_P (t)) + return 0; + + return 1; +} + /* Table of valid C++ attributes. */ const struct attribute_spec cxx_attribute_table[] = { diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 38daa08..b837503 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -1,7 +1,7 @@ /* Report error messages, build initializers, and perform some front-end optimizations for C++ compiler. Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GNU CC. @@ -420,6 +420,28 @@ store_init_value (decl, init) DECL_INITIAL (decl) = value; return NULL_TREE; } + +/* Same as store_init_value, but used for known-to-be-valid static + initializers. Used to introduce a static initializer even in data + structures that may require dynamic initialization. */ + +tree +force_store_init_value (decl, init) + tree decl, init; +{ + tree type = TREE_TYPE (decl); + int needs_constructing = TYPE_NEEDS_CONSTRUCTING (type); + + TYPE_NEEDS_CONSTRUCTING (type) = 0; + + init = store_init_value (decl, init); + if (init) + abort (); + + TYPE_NEEDS_CONSTRUCTING (type) = needs_constructing; + + return init; +} /* Digest the parser output INIT as an initializer for type TYPE. Return a C expression of type TYPE to represent the initial value. @@ -732,6 +754,8 @@ process_init_constructor (type, init, elts) next1 = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, NULL_TREE); next1 = digest_init (TREE_TYPE (type), next1, 0); } + else if (! zero_init_p (TREE_TYPE (type))) + next1 = build_forced_zero_init (TREE_TYPE (type)); else /* The default zero-initialization is fine for us; don't add anything to the CONSTRUCTOR. */ @@ -848,9 +872,12 @@ process_init_constructor (type, init, elts) && (!init || TREE_HAS_CONSTRUCTOR (init))) warning ("missing initializer for member `%D'", field); - /* The default zero-initialization is fine for us; don't - add anything to the CONSTRUCTOR. */ - continue; + if (! zero_init_p (TREE_TYPE (field))) + next1 = build_forced_zero_init (TREE_TYPE (field)); + else + /* The default zero-initialization is fine for us; don't + add anything to the CONSTRUCTOR. */ + continue; } if (next1 == error_mark_node) |