aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2006-05-25 20:18:26 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2006-05-25 20:18:26 +0000
commite92fb50114706dd60fc43ccec488a7ac99b5fa9b (patch)
tree622ad082d8859f1f7dcb1eac879fee90193bb6e0 /gcc
parent05a58ad48d4bad7dff39cc2c2b5263bbb89cab38 (diff)
downloadgcc-e92fb50114706dd60fc43ccec488a7ac99b5fa9b.zip
gcc-e92fb50114706dd60fc43ccec488a7ac99b5fa9b.tar.gz
gcc-e92fb50114706dd60fc43ccec488a7ac99b5fa9b.tar.bz2
re PR c++/20103 (ICE in create_tmp_var with C99 style struct initializer)
PR c++/20103 * gimplify.c (gimplify_decl_expr): Do not call gimple_add_tmp_var for anonymous variables explicitly declared by front ends. PR c++/20103 * decl.c (cp_make_fname_decl): Don't set DECL_INITIAL to error_mark_node to indicate an initialization is OK. (start_decl): Likewise. Adjust call to start_decl_1. (start_decl_1): Add initialized parameter. Simplify. * except.c (initialize_handler_parm): Adjust call to setart_decl_1. (expand_start_catch_block): Let cp_finish_decl initialize catch parameters. * cp-tree.h (start_decl_1): Adjust prototype. * pt.c (tsubst_expr): Don't set DECL_INITIAL to error_mark_node. (instantiate_decl): Let cp_finish_decl handle initialization. * semantics.c (finish_compound_literal): Create a temporary variable for the literal. * typeck.c (build_unary_op): Remove COMPOUND_LITERAL_P special cases. * decl2.c (finish_static_data_member_decl): Don't set DECL_INITIAL. (grokfield): Do not try to initialize functions. PR c++/20103 * g++.dg/ext/complit6.C: New test. * g++.dg/ext/complit3.C: Adjust error markers. * g++.dg/init/const3.C: New test. From-SVN: r114119
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/cp/ChangeLog22
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/decl.c60
-rw-r--r--gcc/cp/decl2.c7
-rw-r--r--gcc/cp/except.c5
-rw-r--r--gcc/cp/pt.c14
-rw-r--r--gcc/cp/semantics.c53
-rw-r--r--gcc/cp/typeck.c21
-rw-r--r--gcc/gimplify.c10
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/g++.dg/ext/complit3.C4
-rw-r--r--gcc/testsuite/g++.dg/ext/complit6.C19
-rw-r--r--gcc/testsuite/g++.dg/init/const3.C12
14 files changed, 137 insertions, 105 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8ab803d..4e271ed 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2006-05-25 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/20103
+ * gimplify.c (gimplify_decl_expr): Do not call gimple_add_tmp_var
+ for anonymous variables explicitly declared by front ends.
+
2006-05-25 Eric Botcazou <ebotcazou@adacore.com>
* tree-ssa-structalias.h (PTR_IS_REF_ALL): New macro.
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f6bcf57..45d25bb 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,25 @@
+2006-05-24 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/20103
+ * decl.c (cp_make_fname_decl): Don't set DECL_INITIAL to
+ error_mark_node to indicate an initialization is OK.
+ (start_decl): Likewise. Adjust call to start_decl_1.
+ (start_decl_1): Add initialized parameter. Simplify.
+ * except.c (initialize_handler_parm): Adjust call to
+ setart_decl_1.
+ (expand_start_catch_block): Let cp_finish_decl initialize catch
+ parameters.
+ * cp-tree.h (start_decl_1): Adjust prototype.
+ * pt.c (tsubst_expr): Don't set DECL_INITIAL to error_mark_node.
+ (instantiate_decl): Let cp_finish_decl handle initialization.
+ * semantics.c (finish_compound_literal): Create a temporary
+ variable for the literal.
+ * typeck.c (build_unary_op): Remove COMPOUND_LITERAL_P special
+ cases.
+ * decl2.c (finish_static_data_member_decl): Don't set
+ DECL_INITIAL.
+ (grokfield): Do not try to initialize functions.
+
2006-05-23 Mark Mitchell <mark@codesourcery.com>
PR c++/20173
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 044fe26..486a90d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3835,7 +3835,7 @@ extern tree check_tag_decl (cp_decl_specifier_seq *);
extern tree shadow_tag (cp_decl_specifier_seq *);
extern tree groktypename (cp_decl_specifier_seq *, const cp_declarator *);
extern tree start_decl (const cp_declarator *, cp_decl_specifier_seq *, int, tree, tree, tree *);
-extern void start_decl_1 (tree);
+extern void start_decl_1 (tree, bool);
extern void cp_finish_decl (tree, tree, bool, tree, int);
extern void finish_decl (tree, tree, tree);
extern int cp_complete_array_type (tree *, tree, bool);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 95acc85..fef09ed 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -3311,7 +3311,6 @@ cp_make_fname_decl (tree id, int type_dep)
TREE_STATIC (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
- DECL_INITIAL (decl) = init;
TREE_USED (decl) = 1;
@@ -3848,11 +3847,6 @@ start_decl (const cp_declarator *declarator,
DECL_EXTERNAL (decl) = 0;
if (toplevel_bindings_p ())
TREE_STATIC (decl) = 1;
-
- /* Tell `pushdecl' this is an initialized decl
- even though we don't yet have the initializer expression.
- Also tell `cp_finish_decl' it may store the real initializer. */
- DECL_INITIAL (decl) = error_mark_node;
}
/* Set attributes here so if duplicate decl, will have proper attributes. */
@@ -3895,8 +3889,7 @@ start_decl (const cp_declarator *declarator,
declaration will have DECL_EXTERNAL set, but will have an
initialization. Thus, duplicate_decls won't warn
about this situation, and so we check here. */
- if (DECL_INITIAL (decl)
- && DECL_INITIALIZED_IN_CLASS_P (field))
+ if (initialized && DECL_INITIALIZED_IN_CLASS_P (field))
error ("duplicate initialization of %qD", decl);
if (duplicate_decls (decl, field, /*newdecl_is_friend=*/false))
decl = field;
@@ -3930,8 +3923,7 @@ start_decl (const cp_declarator *declarator,
We check for processing_specialization so this only applies
to the new specialization syntax. */
- if (!DECL_INITIAL (decl)
- && processing_specialization)
+ if (!initialized && processing_specialization)
DECL_EXTERNAL (decl) = 1;
}
@@ -3960,21 +3952,25 @@ start_decl (const cp_declarator *declarator,
&& !have_global_bss_p ())
DECL_COMMON (tem) = 1;
- if (! processing_template_decl)
- start_decl_1 (tem);
+ if (!processing_template_decl && TREE_CODE (tem) == VAR_DECL)
+ start_decl_1 (tem, initialized);
return tem;
}
void
-start_decl_1 (tree decl)
+start_decl_1 (tree decl, bool initialized)
{
- tree type = TREE_TYPE (decl);
- int initialized = (DECL_INITIAL (decl) != NULL_TREE);
+ tree type;
- if (type == error_mark_node)
+ gcc_assert (!processing_template_decl);
+
+ if (error_operand_p (decl))
return;
+ gcc_assert (TREE_CODE (decl) == VAR_DECL);
+ type = TREE_TYPE (decl);
+
if (initialized)
/* Is it valid for this decl to have an initializer at all?
If not, set INITIALIZED to zero, which will indirectly
@@ -3998,16 +3994,10 @@ start_decl_1 (tree decl)
initialized = 0;
}
}
-
- if (!initialized
- && TREE_CODE (decl) != TYPE_DECL
- && TREE_CODE (decl) != TEMPLATE_DECL
- && type != error_mark_node
- && IS_AGGR_TYPE (type)
- && ! DECL_EXTERNAL (decl))
+ else if (IS_AGGR_TYPE (type)
+ && ! DECL_EXTERNAL (decl))
{
- if ((! processing_template_decl || ! uses_template_parms (type))
- && !COMPLETE_TYPE_P (complete_type (type)))
+ if (!COMPLETE_TYPE_P (complete_type (type)))
{
error ("aggregate %q#D has incomplete type and cannot be defined",
decl);
@@ -4027,9 +4017,6 @@ start_decl_1 (tree decl)
}
}
- if (! initialized)
- DECL_INITIAL (decl) = NULL_TREE;
-
/* Create a new scope to hold this declaration if necessary.
Whether or not a new scope is necessary cannot be determined
until after the type has been completed; if the type is a
@@ -4665,16 +4652,6 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
tree type = TREE_TYPE (decl);
tree init_code = NULL;
- /* If `start_decl' didn't like having an initialization, ignore it now. */
- if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
- init = NULL_TREE;
-
- /* If an initializer is present, DECL_INITIAL has been
- error_mark_node, to indicate that an as-of-yet unevaluated
- initialization will occur. From now on, DECL_INITIAL reflects
- the static initialization -- if any -- of DECL. */
- DECL_INITIAL (decl) = NULL_TREE;
-
/* Things that are going to be initialized need to have complete
type. */
TREE_TYPE (decl) = type = complete_type (TREE_TYPE (decl));
@@ -5040,7 +5017,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
if (at_function_scope_p ())
add_decl_expr (decl);
- if (init && DECL_INITIAL (decl))
+ if (init)
{
DECL_INITIAL (decl) = init;
if (init_const_expr_p)
@@ -5227,10 +5204,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
{
/* Initialize the local variable. */
if (processing_template_decl)
- {
- if (init || DECL_INITIAL (decl) == error_mark_node)
- DECL_INITIAL (decl) = init;
- }
+ DECL_INITIAL (decl) = init;
else if (!TREE_STATIC (decl))
initialize_local_var (decl, init);
}
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 27b88f0..c0bea8c 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -720,9 +720,6 @@ finish_static_data_member_decl (tree decl,
/* We cannot call pushdecl here, because that would fill in the
TREE_CHAIN of our decl. Instead, we modify cp_finish_decl to do
the right thing, namely, to put this decl out straight away. */
- /* current_class_type can be NULL_TREE in case of error. */
- if (!asmspec_tree && current_class_type)
- DECL_INITIAL (decl) = error_mark_node;
if (! processing_template_decl)
note_vague_linkage_var (decl);
@@ -920,7 +917,9 @@ grokfield (const cp_declarator *declarator,
if (asmspec)
set_user_assembler_name (value, asmspec);
- cp_finish_decl (value, init, /*init_const_expr_p=*/false,
+ cp_finish_decl (value,
+ /*init=*/NULL_TREE,
+ /*init_const_expr_p=*/false,
asmspec_tree, flags);
/* Pass friends back this way. */
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index efdbd91..4275910 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -392,11 +392,9 @@ initialize_handler_parm (tree decl, tree exp)
init = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (init), init);
}
- /* Let `cp_finish_decl' know that this initializer is ok. */
- DECL_INITIAL (decl) = error_mark_node;
decl = pushdecl (decl);
- start_decl_1 (decl);
+ start_decl_1 (decl, true);
cp_finish_decl (decl, init, /*init_const_expr_p=*/false, NULL_TREE,
LOOKUP_ONLYCONVERTING|DIRECT_BIND);
}
@@ -464,7 +462,6 @@ expand_start_catch_block (tree decl)
DECL_REGISTER (exp) = 1;
cp_finish_decl (exp, init, /*init_const_expr=*/false,
NULL_TREE, LOOKUP_ONLYCONVERTING);
- finish_expr_stmt (build_modify_expr (exp, INIT_EXPR, init));
initialize_handler_parm (decl, exp);
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index ca57676..4b8232e 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -8266,8 +8266,6 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
decl = tsubst (decl, args, complain, in_decl);
if (decl != error_mark_node)
{
- if (init)
- DECL_INITIAL (decl) = error_mark_node;
/* By marking the declaration as instantiated, we avoid
trying to instantiate it. Since instantiate_decl can't
handle local variables, and since we've already done
@@ -11850,7 +11848,6 @@ instantiate_decl (tree d, int defer_ok,
init = tsubst_expr (DECL_INITIAL (code_pattern),
args,
tf_warning_or_error, NULL_TREE);
- DECL_INITIAL (d) = init;
cp_finish_decl (d, init, /*init_const_expr_p=*/false,
/*asmspec_tree=*/NULL_TREE,
LOOKUP_ONLYCONVERTING);
@@ -11917,11 +11914,20 @@ instantiate_decl (tree d, int defer_ok,
if (TREE_CODE (d) == VAR_DECL)
{
+ tree init;
+
/* Clear out DECL_RTL; whatever was there before may not be right
since we've reset the type of the declaration. */
SET_DECL_RTL (d, NULL_RTX);
DECL_IN_AGGR_P (d) = 0;
+ /* The initializer is placed in DECL_INITIAL by
+ regenerate_decl_from_template. Pull it out so that
+ finish_decl can process it. */
+ init = DECL_INITIAL (d);
+ DECL_INITIAL (d) = NULL_TREE;
+ DECL_INITIALIZED_P (d) = 0;
+
/* Clear DECL_EXTERNAL so that cp_finish_decl will process the
initializer. That function will defer actual emission until
we have a chance to determine linkage. */
@@ -11929,7 +11935,7 @@ instantiate_decl (tree d, int defer_ok,
/* Enter the scope of D so that access-checking works correctly. */
push_nested_class (DECL_CONTEXT (d));
- finish_decl (d, DECL_INITIAL (d), NULL_TREE);
+ finish_decl (d, init, NULL_TREE);
pop_nested_class ();
}
else if (TREE_CODE (d) == FUNCTION_DECL)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 6af4564..976005c 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1089,7 +1089,6 @@ finish_handler_parms (tree decl, tree handler)
}
else
type = expand_start_catch_block (decl);
-
HANDLER_TYPE (handler) = type;
if (!processing_template_decl && type)
mark_used (eh_type_info (type));
@@ -2019,33 +2018,43 @@ finish_unary_op_expr (enum tree_code code, tree expr)
tree
finish_compound_literal (tree type, VEC(constructor_elt,gc) *initializer_list)
{
+ tree var;
tree compound_literal;
/* Build a CONSTRUCTOR for the INITIALIZER_LIST. */
compound_literal = build_constructor (NULL_TREE, initializer_list);
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:
-
- `(int []) { 2, 3 }'
-
- implies that the array has two elements. */
- if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
- cp_complete_array_type (&TREE_TYPE (compound_literal),
- compound_literal, 1);
- }
-
- /* Mark it as a compound-literal. */
- if (TREE_CODE (compound_literal) == CONSTRUCTOR)
- TREE_HAS_CONSTRUCTOR (compound_literal) = 1;
-
- return compound_literal;
+ TREE_TYPE (compound_literal) = type;
+ /* Mark the expression as a compound literal. */
+ TREE_HAS_CONSTRUCTOR (compound_literal) = 1;
+ return compound_literal;
+ }
+
+ /* Create a temporary variable to represent the compound literal. */
+ var = create_temporary_var (type);
+ if (!current_function_decl)
+ {
+ /* If this compound-literal appears outside of a function, then
+ the corresponding variable has static storage duration, just
+ like the variable in whose initializer it appears. */
+ TREE_STATIC (var) = 1;
+ /* The variable has internal linkage, since there is no need to
+ reference it from another translation unit. */
+ TREE_PUBLIC (var) = 0;
+ /* It must have a name, so that the name mangler can mangle it. */
+ DECL_NAME (var) = make_anon_name ();
+ }
+ /* We must call pushdecl, since the gimplifier complains if the
+ variable hase been declared via a BIND_EXPR. */
+ pushdecl (var);
+ /* Initialize the variable as we would any other variable with a
+ brace-enclosed initializer. */
+ cp_finish_decl (var, compound_literal,
+ /*init_const_expr_p=*/false,
+ /*asmspec_tree=*/NULL_TREE,
+ LOOKUP_ONLYCONVERTING);
+ return var;
}
/* Return the declaration for the function-name variable indicated by
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 5ee2ba1..975bfd3 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4324,9 +4324,6 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
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;
@@ -4343,24 +4340,6 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
return val;
}
- /* 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);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 103b36e..fe18bc1 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1216,10 +1216,12 @@ gimplify_decl_expr (tree *stmt_p)
walk_tree (&init, force_labels_r, NULL, NULL);
}
- /* This decl isn't mentioned in the enclosing block, so add it to the
- list of temps. FIXME it seems a bit of a kludge to say that
- anonymous artificial vars aren't pushed, but everything else is. */
- if (DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
+ /* Some front ends do not explicitly declare all anonymous
+ artificial variables. We compensate here by declaring the
+ variables, though it would be better if the front ends would
+ explicitly declare them. */
+ if (!DECL_SEEN_IN_BIND_EXPR_P (decl)
+ && DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
gimple_add_tmp_var (decl);
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4e3a9b8..78fa87a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2006-05-25 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/20103
+ * g++.dg/ext/complit6.C: New test.
+ * g++.dg/ext/complit3.C: Adjust error markers.
+ * g++.dg/init/const3.C: New test.
+
2006-05-25 Richard Guenther <rguenther@suse.de>
PR middle-end/27743
diff --git a/gcc/testsuite/g++.dg/ext/complit3.C b/gcc/testsuite/g++.dg/ext/complit3.C
index 1783a08..a54a8bc 100644
--- a/gcc/testsuite/g++.dg/ext/complit3.C
+++ b/gcc/testsuite/g++.dg/ext/complit3.C
@@ -2,7 +2,7 @@
int Compound_Literals_0()
{
- static int y[] = (int []) {1, 2, 3}; // { dg-error "compound literal" }
- static int z[] = (int [3]) {1}; // { dg-error "compound literal" }
+ static int y[] = (int []) {1, 2, 3}; // { dg-error "init" }
+ static int z[] = (int [3]) {1}; // { dg-error "init" }
return y[0]+z[0];
}
diff --git a/gcc/testsuite/g++.dg/ext/complit6.C b/gcc/testsuite/g++.dg/ext/complit6.C
new file mode 100644
index 0000000..d3187a6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/complit6.C
@@ -0,0 +1,19 @@
+// PR c++/20103
+// { dg-options "" }
+
+struct A
+{
+ A(const A&);
+};
+
+struct B
+{
+ A a;
+};
+
+void foo(B);
+
+void bar(A &x)
+{
+ foo((B){x});
+}
diff --git a/gcc/testsuite/g++.dg/init/const3.C b/gcc/testsuite/g++.dg/init/const3.C
new file mode 100644
index 0000000..96cb6f9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/const3.C
@@ -0,0 +1,12 @@
+// { dg-do run }
+
+struct S {
+ static const int i = 3;
+};
+
+const int S::i;
+
+int main () {
+ if (!S::i)
+ return 1;
+}