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
This commit is contained in:
Alexandre Oliva 2002-05-14 17:20:47 +00:00 committed by Alexandre Oliva
parent e5f5feea65
commit 94e6e4c4f3
8 changed files with 143 additions and 38 deletions

View File

@ -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++.

View File

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

View File

@ -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 *));

View File

@ -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);

View File

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

View File

@ -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. */

View File

@ -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[] =
{

View File

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