diff options
author | Mark Mitchell <mark@codesourcery.com> | 2006-05-25 20:18:26 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2006-05-25 20:18:26 +0000 |
commit | e92fb50114706dd60fc43ccec488a7ac99b5fa9b (patch) | |
tree | 622ad082d8859f1f7dcb1eac879fee90193bb6e0 /gcc | |
parent | 05a58ad48d4bad7dff39cc2c2b5263bbb89cab38 (diff) | |
download | gcc-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/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 22 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/cp/decl.c | 60 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 7 | ||||
-rw-r--r-- | gcc/cp/except.c | 5 | ||||
-rw-r--r-- | gcc/cp/pt.c | 14 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 53 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 21 | ||||
-rw-r--r-- | gcc/gimplify.c | 10 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/complit3.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/complit6.C | 19 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/const3.C | 12 |
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; +} |