diff options
author | Mark Mitchell <mark@codesourcery.com> | 2005-12-27 06:09:13 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2005-12-27 06:09:13 +0000 |
commit | 3b2db49f369d82be920b0614b0edaef405efb8ae (patch) | |
tree | 7ac7d3aa381cf7fc41ba0b018b9485b01b8d2a44 /gcc/cp | |
parent | 103a4b39c223d6cded567dbc8aed82455a34aeac (diff) | |
download | gcc-3b2db49f369d82be920b0614b0edaef405efb8ae.zip gcc-3b2db49f369d82be920b0614b0edaef405efb8ae.tar.gz gcc-3b2db49f369d82be920b0614b0edaef405efb8ae.tar.bz2 |
PR c++/23171, c++/23172, c++/25417.
* c-decl.c (compound_literal_number): Remove.
(build_compound_literal): Use set_compound_literal_name.
* c-common.c (compound_literal_number): New variable.
(set_compound_literal_name): New function.
* c-common.h (set_compound_literal_name): Declare.
PR c++/23171, c++/23172, c++/25417.
* typeck.c (build_unary_op): Create temporary variables for
compound literals whose addresses are taken.
* init.c (expand_aggr_init_1): Use COMPOUND_LITERAL_P.
* decl.c (reshape_init_vector): Likewise.
(reshape_init): Give it external linkage.
(check_initializer): Use COMPOUND_LITERAL_P.
(initialize_artificial_var): Allow the initializer to be a
CONSTRUCTOR.
* call.c (make_temporary_var_for_ref_to_temp): Use
create_temporary_var.
* cp-tree.h (COMPOUND_LITERAL_P): New macro.
(rehape_init): Declare.
* typeck2.c (digest_init): Use COMPOUND_LITERAL_P.
* semantics.c (finish_compound_literal): Use reshape_init.
PR c++/23172
* g++.dg/ext/complit4.C: New test.
PR c++/25417
* g++.dg/ext/complit5.C: Likewise.
From-SVN: r109075
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/cp/call.c | 13 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 6 | ||||
-rw-r--r-- | gcc/cp/decl.c | 22 | ||||
-rw-r--r-- | gcc/cp/init.c | 5 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 4 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 136 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 3 |
8 files changed, 121 insertions, 86 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1279a44..8f27064 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,21 @@ +2005-12-26 Mark Mitchell <mark@codesourcery.com> + + PR c++/23171, c++/23172, c++/25417. + * typeck.c (build_unary_op): Create temporary variables for + compound literals whose addresses are taken. + * init.c (expand_aggr_init_1): Use COMPOUND_LITERAL_P. + * decl.c (reshape_init_vector): Likewise. + (reshape_init): Give it external linkage. + (check_initializer): Use COMPOUND_LITERAL_P. + (initialize_artificial_var): Allow the initializer to be a + CONSTRUCTOR. + * call.c (make_temporary_var_for_ref_to_temp): Use + create_temporary_var. + * cp-tree.h (COMPOUND_LITERAL_P): New macro. + (rehape_init): Declare. + * typeck2.c (digest_init): Use COMPOUND_LITERAL_P. + * semantics.c (finish_compound_literal): Use reshape_init. + 2005-12-23 Mark Mitchell <mark@codesourcery.com> PR c++/24671 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index f341240..014a826 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -6430,10 +6430,7 @@ make_temporary_var_for_ref_to_temp (tree decl, tree type) tree var; /* Create the variable. */ - var = build_decl (VAR_DECL, NULL_TREE, type); - DECL_ARTIFICIAL (var) = 1; - DECL_IGNORED_P (var) = 1; - TREE_USED (var) = 1; + var = create_temporary_var (type); /* Register the variable. */ if (TREE_STATIC (decl)) @@ -6448,12 +6445,8 @@ make_temporary_var_for_ref_to_temp (tree decl, tree type) var = pushdecl_top_level (var); } else - { - /* Create a new cleanup level if necessary. */ - maybe_push_cleanup_level (type); - /* Don't push unnamed temps. Do set DECL_CONTEXT, though. */ - DECL_CONTEXT (var) = current_function_decl; - } + /* Create a new cleanup level if necessary. */ + maybe_push_cleanup_level (type); return var; } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 86b98a0..3ac322d 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2440,6 +2440,11 @@ extern void decl_shadowed_for_var_insert (tree, tree); #define BRACE_ENCLOSED_INITIALIZER_P(NODE) \ (TREE_CODE (NODE) == CONSTRUCTOR && !TREE_TYPE (NODE)) +/* True if NODE is a compound-literal, i.e., a brace-enclosed + initializer cast to a particular type. */ +#define COMPOUND_LITERAL_P(NODE) \ + (TREE_CODE (NODE) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (NODE)) + #define EMPTY_CONSTRUCTOR_P(NODE) (TREE_CODE (NODE) == CONSTRUCTOR \ && VEC_empty (constructor_elt, \ CONSTRUCTOR_ELTS (NODE)) \ @@ -3857,6 +3862,7 @@ extern const char *cxx_comdat_group (tree); extern bool cp_missing_noreturn_ok_p (tree); extern void initialize_artificial_var (tree, tree); extern tree check_var_type (tree, tree); +extern tree reshape_init (tree, tree); extern bool have_extern_spec; diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 8a7688e..7517214 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -114,7 +114,6 @@ static void store_parm_decls (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); /* Erroneous argument lists can use this *IFF* they do not modify it. */ tree error_mark_list; @@ -4274,8 +4273,7 @@ reshape_init_vector (tree type, reshape_iter *d) gcc_assert (TREE_CODE (type) == VECTOR_TYPE); - if (TREE_CODE (d->cur->value) == CONSTRUCTOR - && TREE_HAS_CONSTRUCTOR (d->cur->value)) + if (COMPOUND_LITERAL_P (d->cur->value)) { tree value = d->cur->value; if (!same_type_p (TREE_TYPE (value), type)) @@ -4459,7 +4457,7 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p) we should add a call to reshape_init in finish_compound_literal, before calling digest_init, so changing this code would still not be necessary. */ - if (!TREE_HAS_CONSTRUCTOR (init)) + if (!COMPOUND_LITERAL_P (init)) { ++d->cur; gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init)); @@ -4499,14 +4497,13 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p) routine transforms INIT from the former form into the latter. The revised CONSTRUCTOR node is returned. */ -static tree +tree reshape_init (tree type, tree init) { VEC(constructor_elt, gc) *v; reshape_iter d; tree new_init; - gcc_assert (TREE_CODE (init) == CONSTRUCTOR); gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init)); v = CONSTRUCTOR_ELTS (init); @@ -4595,7 +4592,7 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup) /* Do not reshape constructors of vectors (they don't need to be reshaped. */ if (TREE_CODE (init) == CONSTRUCTOR - && !TREE_HAS_CONSTRUCTOR (init) + && !COMPOUND_LITERAL_P (init) && !TREE_TYPE (init)) /* ptrmemfunc */ { init = reshape_init (type, init); @@ -4618,7 +4615,6 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup) goto initialize_aggr; else if (TREE_CODE (init) == CONSTRUCTOR) { - gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init)); if (TYPE_NON_AGGREGATE_CLASS (type)) { error ("%qD must be initialized by constructor, " @@ -4837,13 +4833,17 @@ initialize_local_var (tree decl, tree init) /* DECL is a VAR_DECL for a compiler-generated variable with static storage duration (like a virtual table) whose initializer is a - compile-time constant. Initialize the variable and provide it to - the back end. */ + compile-time constant. INIT must be either a TREE_LIST of values, + or a CONSTRUCTOR. Initialize the variable and provide it to the + back end. */ void initialize_artificial_var (tree decl, tree init) { - DECL_INITIAL (decl) = build_constructor_from_list (NULL_TREE, init); + if (TREE_CODE (init) == TREE_LIST) + init = build_constructor_from_list (NULL_TREE, init); + gcc_assert (TREE_CODE (init) == CONSTRUCTOR); + DECL_INITIAL (decl) = init; DECL_INITIALIZED_P (decl) = 1; determine_visibility (decl); layout_var_decl (decl); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 54b8a08..dbdd866 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1271,11 +1271,10 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags) as TARGET_EXPRs. */ if (init && TREE_CODE (exp) == VAR_DECL - && TREE_CODE (init) == CONSTRUCTOR - && TREE_HAS_CONSTRUCTOR (init)) + && COMPOUND_LITERAL_P (init)) { /* If store_init_value returns NULL_TREE, the INIT has been - record in the DECL_INITIAL for EXP. That means there's + recorded as the DECL_INITIAL for EXP. That means there's nothing more we have to do. */ init = store_init_value (exp, init); if (init) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 6912e00..512b789 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2005,12 +2005,12 @@ finish_compound_literal (tree type, VEC(constructor_elt,gc) *initializer_list) /* Build a CONSTRUCTOR for the INITIALIZER_LIST. */ compound_literal = build_constructor (NULL_TREE, initializer_list); - /* Mark it as a compound-literal. */ if (processing_template_decl) TREE_TYPE (compound_literal) = type; else { /* Check the initialization. */ + compound_literal = reshape_init (type, compound_literal); compound_literal = digest_init (type, compound_literal); /* If the TYPE was an array type with an unknown bound, then we can figure out the dimension now. For example, something like: @@ -2023,7 +2023,9 @@ finish_compound_literal (tree type, VEC(constructor_elt,gc) *initializer_list) compound_literal, 1); } + /* Mark it as a compound-literal. */ TREE_HAS_CONSTRUCTOR (compound_literal) = 1; + return compound_literal; } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 827b3e5..01f2ebb 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -4192,75 +4192,93 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) break; } - /* Allow the address of a constructor if all the elements - are constant. */ - if (TREE_CODE (arg) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (arg) - && TREE_CONSTANT (arg)) - ; /* Anything not already handled and not a true memory reference is an error. */ - else if (TREE_CODE (argtype) != FUNCTION_TYPE - && TREE_CODE (argtype) != METHOD_TYPE - && TREE_CODE (arg) != OFFSET_REF - && !lvalue_or_else (arg, lv_addressof)) + if (TREE_CODE (argtype) != FUNCTION_TYPE + && TREE_CODE (argtype) != METHOD_TYPE + && TREE_CODE (arg) != OFFSET_REF + /* Permit users to take the address of a compound-literal + with sufficient simple elements. */ + && !(COMPOUND_LITERAL_P (arg) && TREE_STATIC (arg)) + && !lvalue_or_else (arg, lv_addressof)) return error_mark_node; if (argtype != error_mark_node) argtype = build_pointer_type (argtype); - { - tree addr; + /* In a template, we are processing a non-dependent expression + so we can just form an ADDR_EXPR with the correct type. */ + if (processing_template_decl) + { + val = build_address (arg); + if (TREE_CODE (arg) == OFFSET_REF) + PTRMEM_OK_P (val) = PTRMEM_OK_P (arg); + return val; + } - if (TREE_CODE (arg) != COMPONENT_REF - /* Inside a template, we are processing a non-dependent - expression so we can just form an ADDR_EXPR with the - correct type. */ - || processing_template_decl) - { - addr = build_address (arg); - if (TREE_CODE (arg) == OFFSET_REF) - PTRMEM_OK_P (addr) = PTRMEM_OK_P (arg); - } - else if (TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK) - { - tree fn = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1)); - - /* We can only get here with a single static member - function. */ - gcc_assert (TREE_CODE (fn) == FUNCTION_DECL - && DECL_STATIC_FUNCTION_P (fn)); - mark_used (fn); - addr = build_address (fn); - if (TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0))) - /* Do not lose object's side effects. */ - addr = build2 (COMPOUND_EXPR, TREE_TYPE (addr), - TREE_OPERAND (arg, 0), addr); - } - else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1))) - { - error ("attempt to take address of bit-field structure member %qD", - TREE_OPERAND (arg, 1)); - return error_mark_node; - } - else - { - tree object = TREE_OPERAND (arg, 0); - tree field = TREE_OPERAND (arg, 1); - gcc_assert (same_type_ignoring_top_level_qualifiers_p - (TREE_TYPE (object), decl_type_context (field))); - addr = build_address (arg); - } + /* If the user has taken the address of the compound literal, + create a variable to contain the value of the literal and + then return the address of that variable. */ + if (COMPOUND_LITERAL_P (arg)) + { + tree var; + gcc_assert (TREE_STATIC (arg)); + var = create_temporary_var (TREE_TYPE (arg)); + TREE_STATIC (var) = 1; + set_compound_literal_name (var); + initialize_artificial_var (var, arg); + arg = pushdecl (var); + /* Since each compound literal is unique, pushdecl should + never find a pre-existing variable with the same + name. */ + gcc_assert (arg == var); + } + + if (TREE_CODE (arg) != COMPONENT_REF) + { + val = build_address (arg); + if (TREE_CODE (arg) == OFFSET_REF) + PTRMEM_OK_P (val) = PTRMEM_OK_P (arg); + } + else if (TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK) + { + tree fn = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1)); + + /* We can only get here with a single static member + function. */ + gcc_assert (TREE_CODE (fn) == FUNCTION_DECL + && DECL_STATIC_FUNCTION_P (fn)); + mark_used (fn); + val = build_address (fn); + if (TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0))) + /* Do not lose object's side effects. */ + val = build2 (COMPOUND_EXPR, TREE_TYPE (val), + TREE_OPERAND (arg, 0), val); + } + else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1))) + { + error ("attempt to take address of bit-field structure member %qD", + TREE_OPERAND (arg, 1)); + return error_mark_node; + } + else + { + tree object = TREE_OPERAND (arg, 0); + tree field = TREE_OPERAND (arg, 1); + gcc_assert (same_type_ignoring_top_level_qualifiers_p + (TREE_TYPE (object), decl_type_context (field))); + val = build_address (arg); + } - if (TREE_CODE (argtype) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE) - { - build_ptrmemfunc_type (argtype); - addr = build_ptrmemfunc (argtype, addr, 0, - /*c_cast_p=*/false); - } + if (TREE_CODE (argtype) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE) + { + build_ptrmemfunc_type (argtype); + val = build_ptrmemfunc (argtype, val, 0, + /*c_cast_p=*/false); + } - return addr; - } + return val; default: break; diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 3fb80ca..9f2d5a49 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -712,8 +712,7 @@ digest_init (tree type, tree init) return process_init_constructor (type, init); else { - if (TREE_HAS_CONSTRUCTOR (init) - && TREE_CODE (type) == ARRAY_TYPE) + if (COMPOUND_LITERAL_P (init) && TREE_CODE (type) == ARRAY_TYPE) { error ("cannot initialize aggregate of type %qT with " "a compound literal", type); |