summaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2002-10-11 16:50:44 +0000
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2002-10-11 16:50:44 +0000
commit2437a99cadf9e376dfda7f890c2d691663f518da (patch)
tree9c2e122fd8114e13c9a7e7b1f586fcf1e369c77d /gcc/cp
parentdab33443fa07b39a8cb681c55c082180fcc6832c (diff)
downloadgcc-2437a99cadf9e376dfda7f890c2d691663f518da.tar.gz
* NEWS: Document removal of "new X = ..." extension.
* class.c (initialize_array): Set TREE_HAS_CONSTRUCTOR on brace-enclosed initializers. * cp-tree.h (CP_AGGREGATE_TYPE_P): New macro. (initialize_local_var): Remove declaration. (expand_static_init): Likewise. * decl.c (next_initializable_field): New function. (reshape_init): Likewise. (check_initializer): Use them. Build dynamic initializer for aggregates here too. (initialize_local_var): Simplify, and incorporate cleanup insertion code as well. (destroy_local_var): Remove. (cp_finish_decl): Tidy. (expand_static_init): Fold checks for whether or not a variable needs initialization into this function. Simplify. * decl2.c (do_static_initialization): Simplify. * init.c (build_init): Do not set TREE_SIDE_EFFECTS when it will be done for us automatically. (expand_default_init): Handle brace-enclosed initializers correctly. (expand_aggr_init_1): Remove RTL-generation code. (build_vec_init): Remove "new X = ..." support. * parse.y (new_initializer): Likewise. * rtti.c (get_pseudo_ti_init): Set TREE_HAS_CONSTRUCTOR on brace-enclosed initializer. (create_pseudo_type_info): Likewise. * typeck2.c (store_init_value): Don't try to handle digest_init being called more than once. (digest_init): Tidy handling of brace-enclosed initializers. * g++.dg/init/array1.C: Remove invalid braces. * g++.dg/init/brace1.C: New test. * g++.dg/init/copy2.C: Likewise. * g++.dg/init/copy3.C: Likewise. * g++.old-deja/g++.ext/arrnew.C: Change WARNING to ERROR. * g++.old-deja/g++.mike/p9129.C: Add ERROR on invalid use of braces. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@58053 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog33
-rw-r--r--gcc/cp/NEWS4
-rw-r--r--gcc/cp/class.c1
-rw-r--r--gcc/cp/cp-tree.h16
-rw-r--r--gcc/cp/decl.c436
-rw-r--r--gcc/cp/decl2.c24
-rw-r--r--gcc/cp/init.c35
-rw-r--r--gcc/cp/parse.y17
-rw-r--r--gcc/cp/rtti.c4
-rw-r--r--gcc/cp/typeck2.c20
10 files changed, 401 insertions, 189 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 0c5af6eea00..c2a44c397a7 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,36 @@
+2002-10-11 Mark Mitchell <mark@codesourcery.com>
+
+ * NEWS: Document removal of "new X = ..." extension.
+ * class.c (initialize_array): Set TREE_HAS_CONSTRUCTOR on
+ brace-enclosed initializers.
+ * cp-tree.h (CP_AGGREGATE_TYPE_P): New macro.
+ (initialize_local_var): Remove declaration.
+ (expand_static_init): Likewise.
+ * decl.c (next_initializable_field): New function.
+ (reshape_init): Likewise.
+ (check_initializer): Use them. Build dynamic initializer for
+ aggregates here too.
+ (initialize_local_var): Simplify, and incorporate cleanup
+ insertion code as well.
+ (destroy_local_var): Remove.
+ (cp_finish_decl): Tidy.
+ (expand_static_init): Fold checks for whether or not a variable
+ needs initialization into this function. Simplify.
+ * decl2.c (do_static_initialization): Simplify.
+ * init.c (build_init): Do not set TREE_SIDE_EFFECTS when it will
+ be done for us automatically.
+ (expand_default_init): Handle brace-enclosed initializers
+ correctly.
+ (expand_aggr_init_1): Remove RTL-generation code.
+ (build_vec_init): Remove "new X = ..." support.
+ * parse.y (new_initializer): Likewise.
+ * rtti.c (get_pseudo_ti_init): Set TREE_HAS_CONSTRUCTOR on
+ brace-enclosed initializer.
+ (create_pseudo_type_info): Likewise.
+ * typeck2.c (store_init_value): Don't try to handle digest_init
+ being called more than once.
+ (digest_init): Tidy handling of brace-enclosed initializers.
+
2002-10-10 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* decl.c (typename_hash): Use htab_hash_pointer.
diff --git a/gcc/cp/NEWS b/gcc/cp/NEWS
index caee3fb48b0..85642b587d9 100644
--- a/gcc/cp/NEWS
+++ b/gcc/cp/NEWS
@@ -1,3 +1,7 @@
+*** Changes in GCC 3.3:
+
+* The "new X = 3" extension has been removed; you must now use "new X(3)".
+
*** Changes in GCC 3.1:
* -fhonor-std and -fno-honor-std have been removed. -fno-honor-std was
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 267bd78e031..5b5332579b1 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6994,6 +6994,7 @@ initialize_array (decl, inits)
context = DECL_CONTEXT (decl);
DECL_CONTEXT (decl) = NULL_TREE;
DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE, inits);
+ TREE_HAS_CONSTRUCTOR (DECL_INITIAL (decl)) = 1;
cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
DECL_CONTEXT (decl) = context;
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 5701a505f5d..97b7177d14b 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2437,8 +2437,18 @@ struct lang_decl GTY(())
|| TYPE_PTRMEM_P (TYPE) \
|| TYPE_PTRMEMFUNC_P (TYPE))
-/* Nonzero for _TYPE means that the _TYPE defines
- at least one constructor. */
+/* [dcl.init.aggr]
+
+ An aggregate is an array or a class with no user-declared
+ constructors, no private or protected non-static data members, no
+ base classes, and no virtual functions. */
+#define CP_AGGREGATE_TYPE_P(TYPE) \
+ (TREE_CODE (TYPE) == ARRAY_TYPE \
+ || (CLASS_TYPE_P (TYPE) \
+ && !CLASSTYPE_NON_AGGREGATE (TYPE)))
+
+/* Nonzero for a class type means that the class type has a
+ user-declared constructor. */
#define TYPE_HAS_CONSTRUCTOR(NODE) (TYPE_LANG_FLAG_1 (NODE))
/* When appearing in an INDIRECT_REF, it means that the tree structure
@@ -3667,8 +3677,6 @@ extern void start_decl_1 PARAMS ((tree));
extern void cp_finish_decl PARAMS ((tree, tree, tree, int));
extern void finish_decl PARAMS ((tree, tree, tree));
extern void maybe_inject_for_scope_var PARAMS ((tree));
-extern void initialize_local_var PARAMS ((tree, tree, int));
-extern void expand_static_init PARAMS ((tree, tree));
extern tree start_handler_parms PARAMS ((tree, tree));
extern int complete_array_type PARAMS ((tree, tree, int));
extern tree build_ptrmemfunc_type PARAMS ((tree));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 735aa1ba2e4..f4651dbefcd 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -121,11 +121,10 @@ static void pop_labels PARAMS ((tree));
static void maybe_deduce_size_from_array_init PARAMS ((tree, tree));
static void layout_var_decl PARAMS ((tree));
static void maybe_commonize_var PARAMS ((tree));
-static tree check_initializer PARAMS ((tree, tree));
+static tree check_initializer (tree, tree, int);
static void make_rtl_for_nonlocal_decl PARAMS ((tree, tree, const char *));
static void save_function_data PARAMS ((tree));
static void check_function_type PARAMS ((tree, tree));
-static void destroy_local_var PARAMS ((tree));
static void begin_constructor_body PARAMS ((void));
static void finish_constructor_body PARAMS ((void));
static void begin_destructor_body PARAMS ((void));
@@ -143,6 +142,10 @@ static tree push_cp_library_fn PARAMS ((enum tree_code, tree));
static tree build_cp_library_fn PARAMS ((tree, enum tree_code, tree));
static void store_parm_decls PARAMS ((tree));
static int cp_missing_noreturn_ok_p PARAMS ((tree));
+static void initialize_local_var (tree, tree);
+static void expand_static_init (tree, tree);
+static tree next_initializable_field (tree);
+static tree reshape_init (tree, tree *);
#if defined (DEBUG_BINDING_LEVELS)
static void indent PARAMS ((void));
@@ -7727,14 +7730,220 @@ check_for_uninitialized_const_var (decl)
error ("uninitialized const `%D'", decl);
}
+/* FIELD is a FIELD_DECL or NULL. In the former case, the value
+ returned is the next FIELD_DECL (possibly FIELD itself) that can be
+ initialized. If there are no more such fields, the return value
+ will be NULL. */
+
+static tree
+next_initializable_field (tree field)
+{
+ while (field
+ && (TREE_CODE (field) != FIELD_DECL
+ || (DECL_C_BIT_FIELD (field) && !DECL_NAME (field))
+ || DECL_ARTIFICIAL (field)))
+ field = TREE_CHAIN (field);
+
+ return field;
+}
+
+/* Undo the brace-elision allowed by [dcl.init.aggr] in a
+ brace-enclosed aggregate initializer.
+
+ *INITP is one of a list of initializers describing a brace-enclosed
+ initializer for an entity of the indicated aggregate TYPE. It may
+ not presently match the shape of the TYPE; for example:
+
+ struct S { int a; int b; };
+ struct S a[] = { 1, 2, 3, 4 };
+
+ Here *INITP will point to TREE_LIST of four elements, rather than a
+ list of two elements, each itself a list of two elements. This
+ routine transforms INIT from the former form into the latter. The
+ revised initializer is returned. */
+
+static tree
+reshape_init (tree type, tree *initp)
+{
+ tree inits;
+ tree old_init;
+ tree old_init_value;
+ tree new_init;
+ bool brace_enclosed_p;
+
+ old_init = *initp;
+ old_init_value = (TREE_CODE (*initp) == TREE_LIST
+ ? TREE_VALUE (*initp) : old_init);
+
+ /* If the initializer is brace-enclosed, pull initializers from the
+ enclosed elements. Advance past the brace-enclosed initializer
+ now. */
+ if (TREE_CODE (old_init_value) == CONSTRUCTOR
+ && TREE_HAS_CONSTRUCTOR (old_init_value))
+ {
+ *initp = TREE_CHAIN (old_init);
+ TREE_CHAIN (old_init) = NULL_TREE;
+ inits = CONSTRUCTOR_ELTS (old_init_value);
+ initp = &inits;
+ brace_enclosed_p = true;
+ }
+ else
+ {
+ inits = NULL_TREE;
+ brace_enclosed_p = false;
+ }
+
+ /* A non-aggregate type is always initialized with a single
+ initializer. */
+ if (!CP_AGGREGATE_TYPE_P (type))
+ {
+ *initp = TREE_CHAIN (old_init);
+ TREE_CHAIN (old_init) = NULL_TREE;
+ /* It is invalid to initialize a non-aggregate type with a
+ brace-enclosed initializer. */
+ if (brace_enclosed_p)
+ {
+ error ("brace-enclosed initializer used to initialize `%T'",
+ type);
+ if (TREE_CODE (old_init) == TREE_LIST)
+ TREE_VALUE (old_init) = error_mark_node;
+ else
+ old_init = error_mark_node;
+ }
+
+ return old_init;
+ }
+
+ /* [dcl.init.aggr]
+
+ All implicit type conversions (clause _conv_) are considered when
+ initializing the aggregate member with an initializer from an
+ initializer-list. If the initializer can initialize a member,
+ the member is initialized. Otherwise, if the member is itself a
+ non-empty subaggregate, brace elision is assumed and the
+ initializer is considered for the initialization of the first
+ member of the subaggregate. */
+ if (CLASS_TYPE_P (type)
+ && !brace_enclosed_p
+ && can_convert_arg (type, TREE_TYPE (old_init_value), old_init_value))
+ {
+ *initp = TREE_CHAIN (old_init);
+ TREE_CHAIN (old_init) = NULL_TREE;
+ return old_init;
+ }
+
+ if (TREE_CODE (old_init) == STRING_CST
+ && TREE_CODE (type) == ARRAY_TYPE
+ && char_type_p (TREE_TYPE (type)))
+ {
+ /* [dcl.init.string]
+
+ A char array (whether plain char, signed char, or unsigned char)
+ can be initialized by a string-literal (optionally enclosed in
+ braces); a wchar_t array can be initialized by a wide
+ string-literal (optionally enclosed in braces). */
+ new_init = old_init;
+ /* Move past the initializer. */
+ *initp = TREE_CHAIN (old_init);
+ TREE_CHAIN (old_init) = NULL_TREE;
+ }
+ else
+ {
+ /* Build a CONSTRUCTOR to hold the contents of the aggregate. */
+ new_init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
+ TREE_HAS_CONSTRUCTOR (new_init) = 1;
+
+ if (CLASS_TYPE_P (type))
+ {
+ tree field;
+
+ field = next_initializable_field (TYPE_FIELDS (type));
+
+ if (!field)
+ {
+ /* [dcl.init.aggr]
+
+ An initializer for an aggregate member that is an
+ empty class shall have the form of an empty
+ initializer-list {}. */
+ if (!brace_enclosed_p)
+ error ("initializer for `%T' must be brace-enclosed",
+ type);
+ }
+ else
+ {
+ /* Loop through the initializable fields, gathering
+ initializers. */
+ while (*initp && field)
+ {
+ tree field_init;
+
+ field_init = reshape_init (TREE_TYPE (field), initp);
+ TREE_CHAIN (field_init) = CONSTRUCTOR_ELTS (new_init);
+ CONSTRUCTOR_ELTS (new_init) = field_init;
+ /* [dcl.init.aggr]
+
+ When a union is initialized with a brace-enclosed
+ initializer, the braces shall only contain an
+ initializer for the first member of the union. */
+ if (TREE_CODE (type) == UNION_TYPE)
+ break;
+ if (TREE_PURPOSE (field_init))
+ field = TREE_PURPOSE (field_init);
+ field = next_initializable_field (TREE_CHAIN (field));
+ }
+ }
+ }
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ tree index;
+ tree max_index;
+
+ /* If the bound of the array is known, take no more initializers
+ than are allowed. */
+ max_index = (TYPE_DOMAIN (type)
+ ? array_type_nelts (type) : NULL_TREE);
+ /* Loop through the array elements, gathering initializers. */
+ for (index = size_zero_node;
+ *initp && (!max_index || !tree_int_cst_lt (max_index, index));
+ index = size_binop (PLUS_EXPR, index, size_one_node))
+ {
+ tree element_init;
+
+ element_init = reshape_init (TREE_TYPE (type), initp);
+ TREE_CHAIN (element_init) = CONSTRUCTOR_ELTS (new_init);
+ CONSTRUCTOR_ELTS (new_init) = element_init;
+ if (TREE_PURPOSE (element_init))
+ index = TREE_PURPOSE (element_init);
+ }
+ }
+ else
+ abort ();
+
+ /* The initializers were placed in reverse order in the
+ CONSTRUCTOR. */
+ CONSTRUCTOR_ELTS (new_init) = nreverse (CONSTRUCTOR_ELTS (new_init));
+
+ if (TREE_CODE (old_init) == TREE_LIST)
+ new_init = build_tree_list (TREE_PURPOSE (old_init), new_init);
+ }
+
+ /* If this was a brace-enclosed initializer and all of the
+ initializers were not used up, there is a problem. */
+ if (brace_enclosed_p && *initp)
+ error ("too many initializers for `%T'", type);
+
+ return new_init;
+}
+
/* Verify INIT (the initializer for DECL), and record the
- initialization in DECL_INITIAL, if appropriate. Returns a new
- value for INIT. */
+ initialization in DECL_INITIAL, if appropriate.
+
+ If the return value is non-NULL, it is an expression that must be
+ evaluated dynamically to initialize DECL. */
static tree
-check_initializer (decl, init)
- tree decl;
- tree init;
+check_initializer (tree decl, tree init, int flags)
{
tree type = TREE_TYPE (decl);
@@ -7790,22 +7999,49 @@ check_initializer (decl, init)
init = grok_reference_init (decl, type, init);
else if (init)
{
+ if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))
+ init = reshape_init (type, &init);
+
+ /* If DECL has an array type without a specific bound, deduce the
+ array size from the initializer. */
+ maybe_deduce_size_from_array_init (decl, init);
+ type = TREE_TYPE (decl);
+ if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))
+ TREE_TYPE (init) = type;
+
if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
{
if (TREE_CODE (type) == ARRAY_TYPE)
- init = digest_init (type, init, (tree *) 0);
+ goto initialize_aggr;
else if (TREE_CODE (init) == CONSTRUCTOR
&& TREE_HAS_CONSTRUCTOR (init))
{
if (TYPE_NON_AGGREGATE_CLASS (type))
{
error ("`%D' must be initialized by constructor, not by `{...}'",
- decl);
+ decl);
init = error_mark_node;
}
else
goto dont_use_constructor;
}
+ else
+ {
+ int saved_stmts_are_full_exprs_p;
+
+ initialize_aggr:
+ saved_stmts_are_full_exprs_p = 0;
+ if (building_stmt_tree ())
+ {
+ saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
+ current_stmt_tree ()->stmts_are_full_exprs_p = 1;
+ }
+ init = build_aggr_init (decl, init, flags);
+ if (building_stmt_tree ())
+ current_stmt_tree ()->stmts_are_full_exprs_p =
+ saved_stmts_are_full_exprs_p;
+ return init;
+ }
}
else
{
@@ -7816,25 +8052,26 @@ check_initializer (decl, init)
}
else if (DECL_EXTERNAL (decl))
;
- else if (TYPE_P (type)
- && (IS_AGGR_TYPE (type) || TYPE_NEEDS_CONSTRUCTING (type)))
+ else if (TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))
+ goto initialize_aggr;
+ else if (IS_AGGR_TYPE (type))
{
tree core_type = strip_array_types (type);
- if (! TYPE_NEEDS_CONSTRUCTING (core_type))
- {
- if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
- error ("structure `%D' with uninitialized const members", decl);
- if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
- error ("structure `%D' with uninitialized reference members",
- decl);
- }
+ if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
+ error ("structure `%D' with uninitialized const members", decl);
+ if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
+ error ("structure `%D' with uninitialized reference members",
+ decl);
check_for_uninitialized_const_var (decl);
}
else
check_for_uninitialized_const_var (decl);
+ if (init && init != error_mark_node)
+ init = build (INIT_EXPR, type, decl, init);
+
return init;
}
@@ -7968,35 +8205,25 @@ maybe_inject_for_scope_var (decl)
/* Generate code to initialize DECL (a local variable). */
-void
-initialize_local_var (decl, init, flags)
+static void
+initialize_local_var (decl, init)
tree decl;
tree init;
- int flags;
{
tree type = TREE_TYPE (decl);
- /* If the type is bogus, don't bother initializing the variable. */
- if (type == error_mark_node)
- return;
+ my_friendly_assert (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == RESULT_DECL,
+ 20021010);
+ my_friendly_assert (!TREE_STATIC (decl), 20021010);
- if (DECL_SIZE (decl) == NULL_TREE && !TREE_STATIC (decl))
+ if (DECL_SIZE (decl) == NULL_TREE)
{
/* If we used it already as memory, it must stay in memory. */
DECL_INITIAL (decl) = NULL_TREE;
TREE_ADDRESSABLE (decl) = TREE_USED (decl);
}
- /* Local statics are handled differently from ordinary automatic
- variables. */
- if (TREE_STATIC (decl))
- {
- if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
- || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
- expand_static_init (decl, init);
- return;
- }
-
if (DECL_SIZE (decl) && type != error_mark_node)
{
int already_used;
@@ -8004,14 +8231,15 @@ initialize_local_var (decl, init, flags)
/* Compute and store the initial value. */
already_used = TREE_USED (decl) || TREE_USED (type);
- if (init || TYPE_NEEDS_CONSTRUCTING (type))
+ /* Perform the initialization. */
+ if (init)
{
int saved_stmts_are_full_exprs_p;
my_friendly_assert (building_stmt_tree (), 20000906);
saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
- finish_expr_stmt (build_aggr_init (decl, init, flags));
+ finish_expr_stmt (init);
current_stmt_tree ()->stmts_are_full_exprs_p =
saved_stmts_are_full_exprs_p;
}
@@ -8030,39 +8258,19 @@ initialize_local_var (decl, init, flags)
else if (already_used)
TREE_USED (decl) = 1;
}
-}
-
-/* Generate code to destroy DECL (a local variable). */
-
-static void
-destroy_local_var (decl)
- tree decl;
-{
- tree type = TREE_TYPE (decl);
- tree cleanup;
-
- /* Only variables get cleaned up. */
- if (TREE_CODE (decl) != VAR_DECL)
- return;
-
- /* And only things with destructors need cleaning up. */
- if (type == error_mark_node
- || TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
- return;
- if (TREE_CODE (decl) == VAR_DECL &&
- (DECL_EXTERNAL (decl) || TREE_STATIC (decl)))
- /* We don't clean up things that aren't defined in this
- translation unit, or that need a static cleanup. The latter
- are handled by finish_file. */
- return;
-
- /* Compute the cleanup. */
- cleanup = cxx_maybe_build_cleanup (decl);
+ /* Generate a cleanup, if necessary. */
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ {
+ tree cleanup;
- /* Record the cleanup required for this declaration. */
- if (DECL_SIZE (decl) && cleanup)
- finish_decl_cleanup (decl, cleanup);
+ /* Compute the cleanup. */
+ cleanup = cxx_maybe_build_cleanup (decl);
+
+ /* Record the cleanup required for this declaration. */
+ if (DECL_SIZE (decl) && cleanup)
+ finish_decl_cleanup (decl, cleanup);
+ }
}
/* Finish processing of a declaration;
@@ -8193,7 +8401,7 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
make_decl_rtl (decl, asmspec);
}
else if (TREE_CODE (decl) == RESULT_DECL)
- init = check_initializer (decl, init);
+ init = check_initializer (decl, init, flags);
else if (TREE_CODE (decl) == VAR_DECL)
{
/* Only PODs can have thread-local storage. Other types may require
@@ -8205,12 +8413,12 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
already initialized DECL. */
if (!DECL_INITIALIZED_P (decl)
/* If !DECL_EXTERNAL then DECL is being defined. In the
- case of a static data memberm initialized inside the
+ case of a static data member initialized inside the
class-specifier, there can be an initializer even if DECL
is *not* defined. */
&& (!DECL_EXTERNAL (decl) || init))
{
- init = check_initializer (decl, init);
+ init = check_initializer (decl, init, flags);
/* Thread-local storage cannot be dynamically initialized. */
if (DECL_THREAD_LOCAL (decl) && init)
{
@@ -8218,15 +8426,6 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
"initialized", decl);
init = NULL_TREE;
}
- /* If DECL has an array type without a specific bound, deduce the
- array size from the initializer. Note that this must be done
- after check_initializer is called because of cases like this:
-
- struct S { int a; int b; };
- struct S a[] = { 1, 2 };
-
- which creates a one-element array, not a two-element array. */
- maybe_deduce_size_from_array_init (decl, init);
/* Handle:
[dcl.init]
@@ -8283,7 +8482,9 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
else
abstract_virtuals_error (decl, strip_array_types (type));
- if (TREE_CODE (decl) == FUNCTION_DECL)
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_TYPE (decl) == error_mark_node)
+ /* No initialization required. */
;
else if (DECL_EXTERNAL (decl)
&& ! (DECL_LANG_SPECIFIC (decl)
@@ -8292,35 +8493,25 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
if (init)
DECL_INITIAL (decl) = init;
}
- else if (TREE_CODE (CP_DECL_CONTEXT (decl)) == FUNCTION_DECL)
+ else
{
- /* This is a local declaration. */
- if (doing_semantic_analysis_p ())
- maybe_inject_for_scope_var (decl);
- /* Initialize the local variable. But, if we're building a
- statement-tree, we'll do the initialization when we
- expand the tree. */
- if (processing_template_decl)
+ /* A variable definition. */
+ if (DECL_FUNCTION_SCOPE_P (decl))
{
- if (init || DECL_INITIAL (decl) == error_mark_node)
- DECL_INITIAL (decl) = init;
- }
- else
- {
- /* If we're not building RTL, then we need to do so
- now. */
- my_friendly_assert (building_stmt_tree (), 20000906);
- /* Initialize the variable. */
- initialize_local_var (decl, init, flags);
- /* Clean up the variable. */
- destroy_local_var (decl);
+ /* This is a local declaration. */
+ if (doing_semantic_analysis_p ())
+ maybe_inject_for_scope_var (decl);
+ /* Initialize the local variable. */
+ if (processing_template_decl)
+ {
+ if (init || DECL_INITIAL (decl) == error_mark_node)
+ DECL_INITIAL (decl) = init;
+ }
+ else if (!TREE_STATIC (decl))
+ initialize_local_var (decl, init);
}
- }
- else if (TREE_STATIC (decl) && type != error_mark_node)
- {
- /* Cleanups for static variables are handled by `finish_file'. */
- if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
- || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+
+ if (TREE_STATIC (decl))
expand_static_init (decl, init);
}
finish_end0:
@@ -8600,12 +8791,27 @@ register_dtor_fn (decl)
finish_expr_stmt (build_function_call (get_atexit_node (), args));
}
-void
+/* DECL is a VAR_DECL with static storage duration. INIT, if present,
+ is its initializer. Generate code to handle the construction
+ and destruction of DECL. */
+
+static void
expand_static_init (decl, init)
tree decl;
tree init;
{
- tree oldstatic = value_member (decl, static_aggregates);
+ tree oldstatic;
+
+ my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 20021010);
+ my_friendly_assert (TREE_STATIC (decl), 20021010);
+
+ /* Some variables require no initialization. */
+ if (!init
+ && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
+ && TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
+ return;
+
+ oldstatic = value_member (decl, static_aggregates);
if (oldstatic)
{
@@ -8655,15 +8861,7 @@ expand_static_init (decl, init)
then_clause = begin_compound_stmt (/*has_no_scope=*/0);
/* Do the initialization itself. */
- if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
- || (init && TREE_CODE (init) == TREE_LIST))
- assignment = build_aggr_init (decl, init, 0);
- else if (init)
- /* The initialization we're doing here is just a bitwise
- copy. */
- assignment = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
- else
- assignment = NULL_TREE;
+ assignment = init ? init : NULL_TREE;
/* Once the assignment is complete, set TEMP to 1. Since the
construction of the static object is complete at this point,
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index cab1c01188b..afa65a09279 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -2508,34 +2508,24 @@ finish_static_initialization_or_destruction (guard_if_stmt)
DECL_STATIC_FUNCTION_P (current_function_decl) = 0;
}
-/* Generate code to do the static initialization of DECL. The
- initialization is INIT. If DECL may be initialized more than once
- in different object files, GUARD is the guard variable to
- check. PRIORITY is the priority for the initialization. */
+/* Generate code to do the initialization of DECL, a VAR_DECL with
+ static storage duration. The initialization is INIT. */
static void
do_static_initialization (decl, init)
tree decl;
tree init;
{
- tree expr;
tree guard_if_stmt;
/* Set up for the initialization. */
guard_if_stmt
= start_static_initialization_or_destruction (decl,
/*initp=*/1);
-
- /* Do the initialization itself. */
- if (IS_AGGR_TYPE (TREE_TYPE (decl))
- || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
- expr = build_aggr_init (decl, init, 0);
- else
- {
- expr = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
- TREE_SIDE_EFFECTS (expr) = 1;
- }
- finish_expr_stmt (expr);
+
+ /* Perform the initialization. */
+ if (init)
+ finish_expr_stmt (init);
/* If we're using __cxa_atexit, register a a function that calls the
destructor for the object. */
@@ -2567,7 +2557,7 @@ do_static_destruction (decl)
/* Actually do the destruction. */
guard_if_stmt = start_static_initialization_or_destruction (decl,
- /*initp=*/0);
+ /*initp=*/0);
finish_expr_stmt (build_cleanup (decl));
finish_static_initialization_or_destruction (guard_if_stmt);
}
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 156822f40bf..051548ecb02 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -1041,8 +1041,6 @@ expand_member_init (tree name, tree init)
The virtual function table pointer cannot be set up here, because
we do not really know its type.
- Virtual baseclass pointers are also set up here.
-
This never calls operator=().
When initializing, nothing is CONST.
@@ -1144,10 +1142,8 @@ build_init (decl, init, flags)
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
expr = build_aggr_init (decl, init, flags);
else
- {
- expr = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
- TREE_SIDE_EFFECTS (expr) = 1;
- }
+ expr = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
+
return expr;
}
@@ -1184,9 +1180,17 @@ expand_default_init (binfo, true_exp, exp, init, flags)
have already built up the constructor call so we could wrap it
in an exception region. */;
else if (TREE_CODE (init) == CONSTRUCTOR)
- /* A brace-enclosed initializer has whatever type is
- required. There's no need to convert it. */
- ;
+ {
+ if (!TYPE_HAS_CONSTRUCTOR (type))
+ /* A brace-enclosed initializer has whatever type is
+ required. There's no need to convert it. */
+ ;
+ else
+ init = ocp_convert (type,
+ TREE_VALUE (CONSTRUCTOR_ELTS (init)),
+ CONV_IMPLICIT | CONV_FORCE_TEMP,
+ flags);
+ }
else
init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
@@ -1259,6 +1263,7 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, flags)
tree type = TREE_TYPE (exp);
my_friendly_assert (init != error_mark_node && type != error_mark_node, 211);
+ my_friendly_assert (building_stmt_tree (), 20021010);
/* Use a function returning the desired type to initialize EXP for us.
If the function is a constructor, and its first argument is
@@ -1273,12 +1278,7 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, flags)
/* If store_init_value returns NULL_TREE, the INIT has been
record in the DECL_INITIAL for EXP. That means there's
nothing more we have to do. */
- if (!store_init_value (exp, init))
- {
- if (!building_stmt_tree ())
- expand_decl_init (exp);
- }
- else
+ if (store_init_value (exp, init))
finish_expr_stmt (build (INIT_EXPR, type, exp, init));
return;
}
@@ -2725,10 +2725,6 @@ build_vec_init (base, init, from_array)
if (maxindex == error_mark_node)
return error_mark_node;
- /* For g++.ext/arrnew.C. */
- if (init && TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == NULL_TREE)
- init = digest_init (atype, init, 0);
-
if (init
&& (from_array == 2
? (!CLASS_TYPE_P (type) || !TYPE_HAS_COMPLEX_ASSIGN_REF (type))
@@ -2745,7 +2741,6 @@ build_vec_init (base, init, from_array)
store_constructor will handle the semantics for us. */
stmt_expr = build (INIT_EXPR, atype, base, init);
- TREE_SIDE_EFFECTS (stmt_expr) = 1;
return stmt_expr;
}
diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y
index b404e6a2fda..104c4a70ed0 100644
--- a/gcc/cp/parse.y
+++ b/gcc/cp/parse.y
@@ -1351,21 +1351,12 @@ new_initializer:
error ("`%T' is not a valid expression", $2.t);
$$ = error_mark_node;
}
- /* GNU extension so people can use initializer lists. Note that
- this alters the meaning of `new int = 1', which was previously
- syntactically valid but semantically invalid.
- This feature is now deprecated and will be removed in a future
- release. */
| '=' init
{
- if (pedantic)
- pedwarn ("ISO C++ forbids initialization of new expression with `='");
- cp_deprecated ("new initializer lists extension");
- if (TREE_CODE ($2) != TREE_LIST
- && TREE_CODE ($2) != CONSTRUCTOR)
- $$ = build_tree_list (NULL_TREE, $2);
- else
- $$ = $2;
+ /* This was previously allowed as an extension, but
+ was removed in G++ 3.3. */
+ error ("initialization of new expression with `='");
+ $$ = error_mark_node;
}
;
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 1d692fc4793..d6ddf131bc1 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -1096,10 +1096,12 @@ get_pseudo_ti_init (type, var_desc, non_public_p)
base_init = tree_cons (NULL_TREE, offset, base_init);
base_init = tree_cons (NULL_TREE, tinfo, base_init);
base_init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, base_init);
+ TREE_HAS_CONSTRUCTOR (base_init) = 1;
base_inits = tree_cons (NULL_TREE, base_init, base_inits);
}
base_inits = build (CONSTRUCTOR,
NULL_TREE, NULL_TREE, base_inits);
+ TREE_HAS_CONSTRUCTOR (base_inits) = 1;
base_inits = tree_cons (NULL_TREE, base_inits, NULL_TREE);
/* Prepend the number of bases. */
base_inits = tree_cons (NULL_TREE,
@@ -1163,7 +1165,7 @@ create_pseudo_type_info VPARAMS((const char *real_name, int ident, ...))
/* Create the pseudo type. */
pseudo_type = make_aggr_type (RECORD_TYPE);
finish_builtin_type (pseudo_type, pseudo_name, fields, ix, ptr_type_node);
- TYPE_HAS_CONSTRUCTOR (pseudo_type) = 1;
+ CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type;
result = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE);
TINFO_REAL_NAME (result) = get_identifier (real_name);
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index fa7f705019d..cc712b91bef 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -367,15 +367,8 @@ store_init_value (decl, init)
/* End of special C++ code. */
- /* We might have already run this bracketed initializer through
- digest_init. Don't do so again. */
- if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init)
- && TREE_TYPE (init)
- && TYPE_MAIN_VARIANT (TREE_TYPE (init)) == TYPE_MAIN_VARIANT (type))
- value = init;
- else
- /* Digest the specified initializer into an expression. */
- value = digest_init (type, init, (tree *) 0);
+ /* Digest the specified initializer into an expression. */
+ value = digest_init (type, init, (tree *) 0);
/* Store the expression if valid; else report error. */
@@ -439,8 +432,7 @@ digest_init (type, init, tail)
enum tree_code code = TREE_CODE (type);
tree element = NULL_TREE;
tree old_tail_contents = NULL_TREE;
- /* Nonzero if INIT is a braced grouping, which comes in as a CONSTRUCTOR
- tree node which has no TREE_TYPE. */
+ /* Nonzero if INIT is a braced grouping. */
int raw_constructor;
/* By default, assume we use one element from a list.
@@ -471,10 +463,8 @@ digest_init (type, init, tail)
if (TREE_CODE (init) == NON_LVALUE_EXPR)
init = TREE_OPERAND (init, 0);
- if (TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == type)
- return init;
-
- raw_constructor = TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == 0;
+ raw_constructor = (TREE_CODE (init) == CONSTRUCTOR
+ && TREE_HAS_CONSTRUCTOR (init));
if (raw_constructor
&& CONSTRUCTOR_ELTS (init) != 0