diff options
author | mmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-10-11 16:50:44 +0000 |
---|---|---|
committer | mmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-10-11 16:50:44 +0000 |
commit | 2437a99cadf9e376dfda7f890c2d691663f518da (patch) | |
tree | 9c2e122fd8114e13c9a7e7b1f586fcf1e369c77d /gcc/cp | |
parent | dab33443fa07b39a8cb681c55c082180fcc6832c (diff) | |
download | gcc-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/ChangeLog | 33 | ||||
-rw-r--r-- | gcc/cp/NEWS | 4 | ||||
-rw-r--r-- | gcc/cp/class.c | 1 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 16 | ||||
-rw-r--r-- | gcc/cp/decl.c | 436 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 24 | ||||
-rw-r--r-- | gcc/cp/init.c | 35 | ||||
-rw-r--r-- | gcc/cp/parse.y | 17 | ||||
-rw-r--r-- | gcc/cp/rtti.c | 4 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 20 |
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 |