aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2005-12-27 06:09:13 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2005-12-27 06:09:13 +0000
commit3b2db49f369d82be920b0614b0edaef405efb8ae (patch)
tree7ac7d3aa381cf7fc41ba0b018b9485b01b8d2a44 /gcc/cp
parent103a4b39c223d6cded567dbc8aed82455a34aeac (diff)
downloadgcc-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/ChangeLog18
-rw-r--r--gcc/cp/call.c13
-rw-r--r--gcc/cp/cp-tree.h6
-rw-r--r--gcc/cp/decl.c22
-rw-r--r--gcc/cp/init.c5
-rw-r--r--gcc/cp/semantics.c4
-rw-r--r--gcc/cp/typeck.c136
-rw-r--r--gcc/cp/typeck2.c3
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);