mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-12 18:05:09 +08:00
NEWS: Document removal of "new X = ..." extension.
* 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. From-SVN: r58053
This commit is contained in:
parent
98ddd678f0
commit
8e3df2def7
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
|
438
gcc/cp/decl.c
438
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);
|
||||
}
|
||||
|
||||
/* Verify INIT (the initializer for DECL), and record the
|
||||
initialization in DECL_INITIAL, if appropriate. Returns a new
|
||||
value for INIT. */
|
||||
/* 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
|
||||
check_initializer (decl, init)
|
||||
tree decl;
|
||||
tree init;
|
||||
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.
|
||||
|
||||
If the return value is non-NULL, it is an expression that must be
|
||||
evaluated dynamically to initialize DECL. */
|
||||
|
||||
static tree
|
||||
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). */
|
||||
/* Generate a cleanup, if necessary. */
|
||||
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
|
||||
{
|
||||
tree cleanup;
|
||||
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
/* 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 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);
|
||||
}
|
||||
}
|
||||
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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -1,3 +1,13 @@
|
||||
2002-10-11 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2002-10-11 Neil Booth <neil@daikokuya.co.uk>
|
||||
|
||||
* gcc.dg/cpp/assembler.S: Don't use -ansi.
|
||||
|
@ -6,15 +6,15 @@
|
||||
typedef int iArr[];
|
||||
|
||||
const iArr array4={
|
||||
{1},{2},{3},{4}
|
||||
1, 2, 3, 4
|
||||
};
|
||||
|
||||
const iArr array3={
|
||||
{1},{2},{3}
|
||||
1, 2, 3
|
||||
};
|
||||
|
||||
const iArr array5={
|
||||
{1},{2},{3},{4},{5}
|
||||
1, 2, 3, 4, 5
|
||||
};
|
||||
|
||||
int main()
|
||||
|
4
gcc/testsuite/g++.dg/init/brace1.C
Normal file
4
gcc/testsuite/g++.dg/init/brace1.C
Normal file
@ -0,0 +1,4 @@
|
||||
// { dg-do compile }
|
||||
|
||||
int i[4] = { { 3 } }; // { dg-error "brace" }
|
||||
|
5
gcc/testsuite/g++.dg/init/copy2.C
Normal file
5
gcc/testsuite/g++.dg/init/copy2.C
Normal file
@ -0,0 +1,5 @@
|
||||
// { dg-do compile }
|
||||
|
||||
struct S { S (); };
|
||||
|
||||
volatile S s[1] = { S () };
|
16
gcc/testsuite/g++.dg/init/copy3.C
Normal file
16
gcc/testsuite/g++.dg/init/copy3.C
Normal file
@ -0,0 +1,16 @@
|
||||
// { dg-do run }
|
||||
// { dg-options "-fno-elide-constructors" }
|
||||
|
||||
int copies;
|
||||
|
||||
struct S {
|
||||
S () {}
|
||||
S (const S&) { ++copies; }
|
||||
};
|
||||
|
||||
S s[1] = { S () };
|
||||
|
||||
int main () {
|
||||
if (copies != 1)
|
||||
return 1;
|
||||
}
|
@ -3,5 +3,5 @@
|
||||
// Special g++ Options:
|
||||
|
||||
int *f(){
|
||||
return new int[1] = { 1 }; // WARNING - deprecated
|
||||
return new int[1] = { 1 }; // ERROR - removed
|
||||
}
|
||||
|
@ -7,6 +7,6 @@ public:
|
||||
int DoSomething();
|
||||
};
|
||||
|
||||
int (Foo::*pA)() = { &Foo::DoSomething };
|
||||
int (Foo::*pA)() = { &Foo::DoSomething }; // ERROR -
|
||||
int (Foo::*X[1])(int) = { { &Foo::DoSomething } }; // ERROR -
|
||||
int (Foo::*Y[])(int) = { { &Foo::DoSomething, &Foo::DoSomething, 0 } }; // ERROR -
|
||||
|
Loading…
Reference in New Issue
Block a user