* 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
+2005-12-26 Mark Mitchell <mark@codesourcery.com>
+
+ 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.
+
2005-12-26 Kazu Hirata <kazu@codesourcery.com>
PR tree-optimization/25125
init_block_clear_fn (asmspec);
}
+/* The number of named compound-literals generated thus far. */
+static GTY(()) int compound_literal_number;
+
+/* Set DECL_NAME for DECL, a VAR_DECL for a compound-literal. */
+
+void
+set_compound_literal_name (tree decl)
+{
+ char *name;
+ ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal",
+ compound_literal_number);
+ compound_literal_number++;
+ DECL_NAME (decl) = get_identifier (name);
+}
+
tree
build_va_arg (tree expr, tree type)
{
extern void disable_builtin_function (const char *);
+extern void set_compound_literal_name (tree decl);
+
extern tree build_va_arg (tree, tree);
extern unsigned int c_common_init_options (unsigned int, const char **);
TREE_ASM_WRITTEN (b->decl) = 1;
}
\f
-static GTY(()) int compound_literal_number;
-
/* Build a COMPOUND_LITERAL_EXPR. TYPE is the type given in the compound
literal, which may be an incomplete array type completed by the
initializer; INIT is a CONSTRUCTOR that initializes the compound
if (TREE_STATIC (decl))
{
- /* This decl needs a name for the assembler output. We also need
- a unique suffix to be added to the name. */
- char *name;
-
- ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal",
- compound_literal_number);
- compound_literal_number++;
- DECL_NAME (decl) = get_identifier (name);
+ /* This decl needs a name for the assembler output. */
+ set_compound_literal_name (decl);
DECL_DEFER_OUTPUT (decl) = 1;
DECL_COMDAT (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
+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
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))
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;
}
#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)) \
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;
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;
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))
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));
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);
/* 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);
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, "
/* 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);
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)
/* 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:
compound_literal, 1);
}
+ /* Mark it as a compound-literal. */
TREE_HAS_CONSTRUCTOR (compound_literal) = 1;
+
return compound_literal;
}
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;
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);
+2005-12-26 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/23172
+ * g++.dg/ext/complit4.C: New test.
+
+ PR c++/25417
+ * g++.dg/ext/complit5.C: Likewise.
+
2005-12-26 Kazu Hirata <kazu@codesourcery.com>
PR tree-optimization/25125
--- /dev/null
+// PR c++/23172
+// { dg-do run }
+// { dg-options "" }
+
+int i = (int) {7};
+
+int main () {
+ if (i != 7)
+ return 1;
+}
--- /dev/null
+// PR c++/25417
+// { dg-options "" }
+
+struct object {
+ int a;
+ int b;
+};
+
+void f (int c, int d)
+{
+ object o = ((object){ a : c, b : d});
+}