diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f31b531a7815134f3a72b8416fd005702d7177eb..4c39a9bfc0d417d5b9bb4f6e6972ba6bcbda0538 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,41 @@ +2009-03-28 Paolo Bonzini <bonzini@gnu.org> + + * c-common.c (c_expand_expr, c_staticp): Remove. + * c-common.def (COMPOUND_LITERAL_EXPR): Delete. + * c-common.h (emit_local_var, c_staticp, COMPOUND_LITERAL_EXPR_DECL, + COMPOUND_LITERAL_EXPR_DECL_EXPR): Remove. + * c-gimplify.c (gimplify_compound_literal_expr, + optimize_compound_literals_in_ctor): Remove. + (c_gimplify_expr): Remove COMPOUND_LITERAL_EXPR handling. + * c-objc-common.h (LANG_HOOKS_STATICP): Remove. + * c-semantics.c (emit_local_var): Remove. + + * langhooks-def.h (lhd_expand_expr): Remove. + * langhooks.c (lhd_expand_expr): Remove. + * langhooks.h (LANG_HOOKS_DEF): Remove LANG_HOOKS_EXPAND_EXPR. + + * expr.c (expand_expr_real_1): Move COMPOUND_LITERAL_EXPR + handling from c-semantics.c; don't call into langhook. + (expand_expr_addr_expr_1): Check that we don't get non-GENERIC trees. + * gimplify.c (gimplify_compound_literal_expr, + optimize_compound_literals_in_ctor): Move from c-gimplify.c. + (gimplify_init_constructor): Call optimize_compound_literals_in_ctor. + (gimplify_modify_expr_rhs, gimplify_expr): Handle COMPOUND_LITERAL_EXPR + as was done in c-gimplify.c. + * tree.c (staticp): Move COMPOUND_LITERAL_EXPR handling from c_staticp. + * tree.h (COMPOUND_LITERAL_EXPR_DECL, COMPOUND_LITERAL_EXPR_DECL_EXPR): + Move from c-common.h. + * tree.def (COMPOUND_LITERAL_EXPR): Move from c-common.def. + + * tree.c (staticp): Do not call langhook. + * langhooks.c (lhd_staticp): Delete. + * langhooks-def.h (lhd_staticp): Delete prototype. + (LANG_HOOKS_STATICP): Delete. + (LANG_HOOKS_INITIALIZER): Delete LANG_HOOKS_STATICP. + + * doc/c-tree.texi (Expression nodes): Refer to DECL_EXPRs + instead of DECL_STMTs. + 2009-03-29 Joseph Myers <joseph@codesourcery.com> PR c/456 diff --git a/gcc/c-common.c b/gcc/c-common.c index c066e95695908e4ff353a87e9b863d298cef66c8..8450cc9860514a1df4010d7508597beff972a109 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -5444,43 +5444,6 @@ finish_label_address_expr (tree label, location_t loc) return result; } - -/* Hook used by expand_expr to expand language-specific tree codes. */ -/* The only things that should go here are bits needed to expand - constant initializers. Everything else should be handled by the - gimplification routines. */ - -rtx -c_expand_expr (tree exp, rtx target, enum machine_mode tmode, - int modifiera /* Actually enum expand_modifier. */, - rtx *alt_rtl) -{ - enum expand_modifier modifier = (enum expand_modifier) modifiera; - switch (TREE_CODE (exp)) - { - case COMPOUND_LITERAL_EXPR: - { - /* Initialize the anonymous variable declared in the compound - literal, then return the variable. */ - tree decl = COMPOUND_LITERAL_EXPR_DECL (exp); - emit_local_var (decl); - return expand_expr_real (decl, target, tmode, modifier, alt_rtl); - } - - default: - gcc_unreachable (); - } -} - -/* Hook used by staticp to handle language-specific tree codes. */ - -tree -c_staticp (tree exp) -{ - return (TREE_CODE (exp) == COMPOUND_LITERAL_EXPR - && TREE_STATIC (COMPOUND_LITERAL_EXPR_DECL (exp)) - ? exp : NULL); -} /* Given a boolean expression ARG, return a tree representing an increment diff --git a/gcc/c-common.def b/gcc/c-common.def index 3080fd3cee8b548f2549b15bb1af857169b4496d..c4027f7dbed317f8f8e0c27b135c53721fdcc431 100644 --- a/gcc/c-common.def +++ b/gcc/c-common.def @@ -24,13 +24,6 @@ along with GCC; see the file COPYING3. If not see /* Tree nodes used in the C frontend. These are also shared with the C++ and Objective C frontends. */ -/* A COMPOUND_LITERAL_EXPR represents a C99 compound literal. The - COMPOUND_LITERAL_EXPR_DECL_STMT is the a DECL_STMT containing the decl - for the anonymous object represented by the COMPOUND_LITERAL; - the DECL_INITIAL of that decl is the CONSTRUCTOR that initializes - the compound literal. */ -DEFTREECODE (COMPOUND_LITERAL_EXPR, "compound_literal_expr", tcc_expression, 1) - /* A C_MAYBE_CONST_EXPR, currently only used for C and Objective C, tracks information about constancy of an expression and VLA type sizes or VM expressions from typeof that need to be evaluated diff --git a/gcc/c-common.h b/gcc/c-common.h index ce8b23826ce1ec3221fa568ce047b8a840f14683..6b5fb94ad8f7bf43753d2efc25808acfeb4e0113 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -798,12 +798,6 @@ extern void finish_file (void); #define STATEMENT_LIST_HAS_LABEL(NODE) \ TREE_LANG_FLAG_3 (STATEMENT_LIST_CHECK (NODE)) -/* COMPOUND_LITERAL_EXPR accessors. */ -#define COMPOUND_LITERAL_EXPR_DECL_STMT(NODE) \ - TREE_OPERAND (COMPOUND_LITERAL_EXPR_CHECK (NODE), 0) -#define COMPOUND_LITERAL_EXPR_DECL(NODE) \ - DECL_EXPR_DECL (COMPOUND_LITERAL_EXPR_DECL_STMT (NODE)) - /* C_MAYBE_CONST_EXPR accessors. */ #define C_MAYBE_CONST_EXPR_PRE(NODE) \ TREE_OPERAND (C_MAYBE_CONST_EXPR_CHECK (NODE), 0) @@ -827,7 +821,6 @@ extern void finish_file (void); #define CLEAR_DECL_C_BIT_FIELD(NODE) \ (DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) = 0) -extern void emit_local_var (tree); extern tree do_case (tree, tree); extern tree build_stmt (enum tree_code, ...); extern tree build_case_label (tree, tree, tree); @@ -876,8 +869,6 @@ extern bool vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_ extern rtx c_expand_expr (tree, rtx, enum machine_mode, int, rtx *); -extern tree c_staticp (tree); - extern void init_c_lex (void); extern void c_cpp_builtins (cpp_reader *); diff --git a/gcc/c-gimplify.c b/gcc/c-gimplify.c index 5b309343361d4a8700ddd8dd185087fc27596433..9cb4a0b2d17bbfe9750b5f63d7b5744286493941 100644 --- a/gcc/c-gimplify.c +++ b/gcc/c-gimplify.c @@ -176,145 +176,25 @@ c_build_bind_expr (tree block, tree body) /* Gimplification of expression trees. */ -/* Gimplify a C99 compound literal expression. This just means adding - the DECL_EXPR before the current statement and using its anonymous - decl instead. */ - -static enum gimplify_status -gimplify_compound_literal_expr (tree *expr_p, gimple_seq *pre_p) -{ - tree decl_s = COMPOUND_LITERAL_EXPR_DECL_STMT (*expr_p); - tree decl = DECL_EXPR_DECL (decl_s); - /* Mark the decl as addressable if the compound literal - expression is addressable now, otherwise it is marked too late - after we gimplify the initialization expression. */ - if (TREE_ADDRESSABLE (*expr_p)) - TREE_ADDRESSABLE (decl) = 1; - - /* Preliminarily mark non-addressed complex variables as eligible - for promotion to gimple registers. We'll transform their uses - as we find them. */ - if ((TREE_CODE (TREE_TYPE (decl)) == COMPLEX_TYPE - || TREE_CODE (TREE_TYPE (decl)) == VECTOR_TYPE) - && !TREE_THIS_VOLATILE (decl) - && !needs_to_live_in_memory (decl)) - DECL_GIMPLE_REG_P (decl) = 1; - - /* 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_NAME (decl) == NULL_TREE && !DECL_SEEN_IN_BIND_EXPR_P (decl)) - gimple_add_tmp_var (decl); - - gimplify_and_add (decl_s, pre_p); - *expr_p = decl; - return GS_OK; -} - -/* Optimize embedded COMPOUND_LITERAL_EXPRs within a CONSTRUCTOR, - return a new CONSTRUCTOR if something changed. */ - -static tree -optimize_compound_literals_in_ctor (tree orig_ctor) -{ - tree ctor = orig_ctor; - VEC(constructor_elt,gc) *elts = CONSTRUCTOR_ELTS (ctor); - unsigned int idx, num = VEC_length (constructor_elt, elts); - - for (idx = 0; idx < num; idx++) - { - tree value = VEC_index (constructor_elt, elts, idx)->value; - tree newval = value; - if (TREE_CODE (value) == CONSTRUCTOR) - newval = optimize_compound_literals_in_ctor (value); - else if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR) - { - tree decl_s = COMPOUND_LITERAL_EXPR_DECL_STMT (value); - tree decl = DECL_EXPR_DECL (decl_s); - tree init = DECL_INITIAL (decl); - - if (!TREE_ADDRESSABLE (value) - && !TREE_ADDRESSABLE (decl) - && init) - newval = init; - } - if (newval == value) - continue; - - if (ctor == orig_ctor) - { - ctor = copy_node (orig_ctor); - CONSTRUCTOR_ELTS (ctor) = VEC_copy (constructor_elt, gc, elts); - elts = CONSTRUCTOR_ELTS (ctor); - } - VEC_index (constructor_elt, elts, idx)->value = newval; - } - return ctor; -} - /* Do C-specific gimplification on *EXPR_P. PRE_P and POST_P are as in gimplify_expr. */ int -c_gimplify_expr (tree *expr_p, gimple_seq *pre_p, +c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED, gimple_seq *post_p ATTRIBUTE_UNUSED) { enum tree_code code = TREE_CODE (*expr_p); - switch (code) - { - case DECL_EXPR: - /* This is handled mostly by gimplify.c, but we have to deal with - not warning about int x = x; as it is a GCC extension to turn off - this warning but only if warn_init_self is zero. */ - if (TREE_CODE (DECL_EXPR_DECL (*expr_p)) == VAR_DECL - && !DECL_EXTERNAL (DECL_EXPR_DECL (*expr_p)) - && !TREE_STATIC (DECL_EXPR_DECL (*expr_p)) - && (DECL_INITIAL (DECL_EXPR_DECL (*expr_p)) - == DECL_EXPR_DECL (*expr_p)) - && !warn_init_self) - TREE_NO_WARNING (DECL_EXPR_DECL (*expr_p)) = 1; - return GS_UNHANDLED; - - case COMPOUND_LITERAL_EXPR: - return gimplify_compound_literal_expr (expr_p, pre_p); - - case INIT_EXPR: - case MODIFY_EXPR: - if (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == COMPOUND_LITERAL_EXPR) - { - tree complit = TREE_OPERAND (*expr_p, 1); - tree decl_s = COMPOUND_LITERAL_EXPR_DECL_STMT (complit); - tree decl = DECL_EXPR_DECL (decl_s); - tree init = DECL_INITIAL (decl); - - /* struct T x = (struct T) { 0, 1, 2 } can be optimized - into struct T x = { 0, 1, 2 } if the address of the - compound literal has never been taken. */ - if (!TREE_ADDRESSABLE (complit) - && !TREE_ADDRESSABLE (decl) - && init) - { - *expr_p = copy_node (*expr_p); - TREE_OPERAND (*expr_p, 1) = init; - return GS_OK; - } - } - else if (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == CONSTRUCTOR) - { - tree ctor - = optimize_compound_literals_in_ctor (TREE_OPERAND (*expr_p, 1)); - - if (ctor != TREE_OPERAND (*expr_p, 1)) - { - *expr_p = copy_node (*expr_p); - TREE_OPERAND (*expr_p, 1) = ctor; - return GS_OK; - } - } - return GS_UNHANDLED; - - default: - return GS_UNHANDLED; - } + /* This is handled mostly by gimplify.c, but we have to deal with + not warning about int x = x; as it is a GCC extension to turn off + this warning but only if warn_init_self is zero. */ + if (code == DECL_EXPR + && TREE_CODE (DECL_EXPR_DECL (*expr_p)) == VAR_DECL + && !DECL_EXTERNAL (DECL_EXPR_DECL (*expr_p)) + && !TREE_STATIC (DECL_EXPR_DECL (*expr_p)) + && (DECL_INITIAL (DECL_EXPR_DECL (*expr_p)) == DECL_EXPR_DECL (*expr_p)) + && !warn_init_self) + TREE_NO_WARNING (DECL_EXPR_DECL (*expr_p)) = 1; + + return GS_UNHANDLED; } diff --git a/gcc/c-objc-common.h b/gcc/c-objc-common.h index 2a981502b842c384cdb6d5d1e947a197c29ff057..6ef98febfb5b19a73cfc562dd42fca661a4af746 100644 --- a/gcc/c-objc-common.h +++ b/gcc/c-objc-common.h @@ -43,16 +43,12 @@ extern void c_initialize_diagnostics (diagnostic_context *); #define LANG_HOOKS_POST_OPTIONS c_common_post_options #undef LANG_HOOKS_GET_ALIAS_SET #define LANG_HOOKS_GET_ALIAS_SET c_common_get_alias_set -#undef LANG_HOOKS_EXPAND_EXPR -#define LANG_HOOKS_EXPAND_EXPR c_expand_expr #undef LANG_HOOKS_MARK_ADDRESSABLE #define LANG_HOOKS_MARK_ADDRESSABLE c_mark_addressable #undef LANG_HOOKS_PARSE_FILE #define LANG_HOOKS_PARSE_FILE c_common_parse_file #undef LANG_HOOKS_FINISH_INCOMPLETE_DECL #define LANG_HOOKS_FINISH_INCOMPLETE_DECL c_finish_incomplete_decl -#undef LANG_HOOKS_STATICP -#define LANG_HOOKS_STATICP c_staticp #undef LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL #define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL c_warn_unused_global_decl #undef LANG_HOOKS_PRINT_IDENTIFIER diff --git a/gcc/c-semantics.c b/gcc/c-semantics.c index 7731ac9351f52db3b65e059050754445a2e49f4c..3c7b241b999b75edf74704065193993708d6c270 100644 --- a/gcc/c-semantics.c +++ b/gcc/c-semantics.c @@ -1,6 +1,4 @@ -/* This file contains the definitions and documentation for the common - tree codes used in the GNU C and C++ compilers (see c-common.def - for the standard codes). +/* This file contains subroutine used by the C front-end to construct GENERIC. Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc. Written by Benjamin Chelf (chelf@codesourcery.com). @@ -145,23 +143,6 @@ build_stmt (enum tree_code code, ...) return ret; } -/* Let the back-end know about DECL. */ - -void -emit_local_var (tree decl) -{ - /* Create RTL for this variable. */ - if (!DECL_RTL_SET_P (decl)) - { - if (DECL_HARD_REGISTER (decl)) - /* The user specified an assembler name for this variable. - Set that up now. */ - rest_of_decl_compilation (decl, 0, 0); - else - expand_decl (decl); - } -} - /* Create a CASE_LABEL_EXPR tree node and return it. */ tree diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 449fb93c1beacaa4bba45a46e7049b0777411229..5bcd13e1c7d064d4f84da477127c0dee3609861c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2009-03-28 Paolo Bonzini <bonzini@gnu.org> + + * cp/cp-objcp-common.h (LANG_HOOKS_STATICP): Remove. + * cp/cp-objcp-common.c (cxx_staticp): Remove. + * cp/cp-tree.h (cxx_staticp): Remove. + 2009-03-28 Jakub Jelinek <jakub@redhat.com> PR c++/39554 diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c index daefa2b0d87fdb9df4caf4a90b7da73c5ca934f4..2363cd7abdbe747a85abd0b69d7b4b894d7b68a2 100644 --- a/gcc/cp/cp-objcp-common.c +++ b/gcc/cp/cp-objcp-common.c @@ -188,21 +188,6 @@ cxx_types_compatible_p (tree x, tree y) return same_type_ignoring_top_level_qualifiers_p (x, y); } -tree -cxx_staticp (tree arg) -{ - switch (TREE_CODE (arg)) - { - case BASELINK: - return staticp (BASELINK_FUNCTIONS (arg)); - - default: - break; - } - - return NULL_TREE; -} - /* Return true if DECL is explicit member function. */ bool diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h index bda23eb635b6a97b2d5d5c0c8d0556fc134544a1..1ce9d36a6529da18fae80cdb425500f41b9b173d 100644 --- a/gcc/cp/cp-objcp-common.h +++ b/gcc/cp/cp-objcp-common.h @@ -52,12 +52,8 @@ extern bool cp_function_decl_explicit_p (tree decl); #define LANG_HOOKS_POST_OPTIONS c_common_post_options #undef LANG_HOOKS_GET_ALIAS_SET #define LANG_HOOKS_GET_ALIAS_SET cxx_get_alias_set -#undef LANG_HOOKS_EXPAND_EXPR -#define LANG_HOOKS_EXPAND_EXPR c_expand_expr #undef LANG_HOOKS_PARSE_FILE #define LANG_HOOKS_PARSE_FILE c_common_parse_file -#undef LANG_HOOKS_STATICP -#define LANG_HOOKS_STATICP cxx_staticp #undef LANG_HOOKS_DUP_LANG_SPECIFIC_DECL #define LANG_HOOKS_DUP_LANG_SPECIFIC_DECL cxx_dup_lang_specific_decl #undef LANG_HOOKS_SET_DECL_ASSEMBLER_NAME diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 6b67d2dd62c86059771990cdad9528e984fda156..a4871e90f157f734b9418f8c6bb00ffec246514c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5053,7 +5053,6 @@ extern bool cp_var_mod_type_p (tree, tree); extern void cxx_initialize_diagnostics (struct diagnostic_context *); extern int cxx_types_compatible_p (tree, tree); extern void init_shadowed_var_for_decl (void); -extern tree cxx_staticp (tree); /* in cp-gimplify.c */ extern int cp_gimplify_expr (tree *, gimple_seq *, diff --git a/gcc/doc/c-tree.texi b/gcc/doc/c-tree.texi index 6eabd34a7b14baa01eaf652c527af93df7aa59df..0039228f18bf907e2e15100788eef5959550f055 100644 --- a/gcc/doc/c-tree.texi +++ b/gcc/doc/c-tree.texi @@ -2636,10 +2636,10 @@ declaration order. You should not assume that all fields will be represented. Unrepresented fields will be set to zero. @item COMPOUND_LITERAL_EXPR -@findex COMPOUND_LITERAL_EXPR_DECL_STMT +@findex COMPOUND_LITERAL_EXPR_DECL_EXPR @findex COMPOUND_LITERAL_EXPR_DECL These nodes represent ISO C99 compound literals. The -@code{COMPOUND_LITERAL_EXPR_DECL_STMT} is a @code{DECL_STMT} +@code{COMPOUND_LITERAL_EXPR_DECL_EXPR} is a @code{DECL_EXPR} containing an anonymous @code{VAR_DECL} for the unnamed object represented by the compound literal; the @code{DECL_INITIAL} of that @code{VAR_DECL} is a @code{CONSTRUCTOR} diff --git a/gcc/explow.c b/gcc/explow.c index c9bf675d36f5d750a43d2b0fafdc8041751aa1ab..11c2a477b84ca619e11040b0be9fe4cfd086dede 100644 --- a/gcc/explow.c +++ b/gcc/explow.c @@ -248,7 +248,7 @@ expr_size (tree exp) { size = lang_hooks.expr_size (exp); gcc_assert (size); - size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, exp); + gcc_assert (size == SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, exp)); } return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), EXPAND_NORMAL); diff --git a/gcc/expr.c b/gcc/expr.c index 0e8e0eeee5c9cd296732bc0f0a72c6fb24e8e4b1..ff3867e59ecc4813970408701c8d622080dc44f0 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -6821,9 +6821,10 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode, CONSTRUCTORs too, which should yield a memory reference for the constructor's contents. Assume language specific tree nodes can be expanded in some interesting way. */ + gcc_assert (TREE_CODE (exp) < LAST_AND_UNUSED_TREE_CODE); if (DECL_P (exp) || TREE_CODE (exp) == CONSTRUCTOR - || TREE_CODE (exp) >= LAST_AND_UNUSED_TREE_CODE) + || TREE_CODE (exp) == COMPOUND_LITERAL_EXPR) { result = expand_expr (exp, target, tmode, modifier == EXPAND_INITIALIZER @@ -8069,11 +8070,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, /* Check for a built-in function. */ if (fndecl && DECL_BUILT_IN (fndecl)) { - if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_FRONTEND) - return lang_hooks.expand_expr (exp, original_target, - tmode, modifier, alt_rtl); - else - return expand_builtin (exp, target, subtarget, tmode, ignore); + gcc_assert (DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_FRONTEND); + return expand_builtin (exp, target, subtarget, tmode, ignore); } } return expand_call (exp, target, ignore); @@ -9460,9 +9458,29 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); goto binop; + case COMPOUND_LITERAL_EXPR: + { + /* Initialize the anonymous variable declared in the compound + literal, then return the variable. */ + tree decl = COMPOUND_LITERAL_EXPR_DECL (exp); + + /* Create RTL for this variable. */ + if (!DECL_RTL_SET_P (decl)) + { + if (DECL_HARD_REGISTER (decl)) + /* The user specified an assembler name for this variable. + Set that up now. */ + rest_of_decl_compilation (decl, 0, 0); + else + expand_decl (decl); + } + + return expand_expr_real (decl, original_target, tmode, + modifier, alt_rtl); + } + default: - return lang_hooks.expand_expr (exp, original_target, tmode, - modifier, alt_rtl); + gcc_unreachable (); } /* Here to do an ordinary binary operator. */ diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 842ef378a9dfd5e7117a568daf59d538ff39ea2c..bd82051d158951754764ef441dc3a41e696cc86a 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -3456,6 +3456,83 @@ rhs_predicate_for (tree lhs) return is_gimple_mem_or_call_rhs; } +/* Gimplify a C99 compound literal expression. This just means adding + the DECL_EXPR before the current statement and using its anonymous + decl instead. */ + +static enum gimplify_status +gimplify_compound_literal_expr (tree *expr_p, gimple_seq *pre_p) +{ + tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (*expr_p); + tree decl = DECL_EXPR_DECL (decl_s); + /* Mark the decl as addressable if the compound literal + expression is addressable now, otherwise it is marked too late + after we gimplify the initialization expression. */ + if (TREE_ADDRESSABLE (*expr_p)) + TREE_ADDRESSABLE (decl) = 1; + + /* Preliminarily mark non-addressed complex variables as eligible + for promotion to gimple registers. We'll transform their uses + as we find them. */ + if ((TREE_CODE (TREE_TYPE (decl)) == COMPLEX_TYPE + || TREE_CODE (TREE_TYPE (decl)) == VECTOR_TYPE) + && !TREE_THIS_VOLATILE (decl) + && !needs_to_live_in_memory (decl)) + DECL_GIMPLE_REG_P (decl) = 1; + + /* 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_NAME (decl) == NULL_TREE && !DECL_SEEN_IN_BIND_EXPR_P (decl)) + gimple_add_tmp_var (decl); + + gimplify_and_add (decl_s, pre_p); + *expr_p = decl; + return GS_OK; +} + +/* Optimize embedded COMPOUND_LITERAL_EXPRs within a CONSTRUCTOR, + return a new CONSTRUCTOR if something changed. */ + +static tree +optimize_compound_literals_in_ctor (tree orig_ctor) +{ + tree ctor = orig_ctor; + VEC(constructor_elt,gc) *elts = CONSTRUCTOR_ELTS (ctor); + unsigned int idx, num = VEC_length (constructor_elt, elts); + + for (idx = 0; idx < num; idx++) + { + tree value = VEC_index (constructor_elt, elts, idx)->value; + tree newval = value; + if (TREE_CODE (value) == CONSTRUCTOR) + newval = optimize_compound_literals_in_ctor (value); + else if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR) + { + tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (value); + tree decl = DECL_EXPR_DECL (decl_s); + tree init = DECL_INITIAL (decl); + + if (!TREE_ADDRESSABLE (value) + && !TREE_ADDRESSABLE (decl) + && init) + newval = optimize_compound_literals_in_ctor (init); + } + if (newval == value) + continue; + + if (ctor == orig_ctor) + { + ctor = copy_node (orig_ctor); + CONSTRUCTOR_ELTS (ctor) = VEC_copy (constructor_elt, gc, elts); + elts = CONSTRUCTOR_ELTS (ctor); + } + VEC_index (constructor_elt, elts, idx)->value = newval; + } + return ctor; +} + + /* A subroutine of gimplify_modify_expr. Break out elements of a CONSTRUCTOR used as an initializer into separate MODIFY_EXPRs. @@ -3474,7 +3551,7 @@ static enum gimplify_status gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, bool want_value, bool notify_temp_creation) { - tree object; + tree object, new_ctor; tree ctor = TREE_OPERAND (*expr_p, 1); tree type = TREE_TYPE (ctor); enum gimplify_status ret; @@ -3492,7 +3569,8 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, } object = TREE_OPERAND (*expr_p, 0); - elts = CONSTRUCTOR_ELTS (ctor); + new_ctor = optimize_compound_literals_in_ctor (ctor); + elts = CONSTRUCTOR_ELTS (new_ctor); ret = GS_ALL_DONE; switch (TREE_CODE (type)) @@ -4099,6 +4177,26 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, return GS_OK; } + case COMPOUND_LITERAL_EXPR: + { + tree complit = TREE_OPERAND (*expr_p, 1); + tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (complit); + tree decl = DECL_EXPR_DECL (decl_s); + tree init = DECL_INITIAL (decl); + + /* struct T x = (struct T) { 0, 1, 2 } can be optimized + into struct T x = { 0, 1, 2 } if the address of the + compound literal has never been taken. */ + if (!TREE_ADDRESSABLE (complit) + && !TREE_ADDRESSABLE (decl) + && init) + { + *expr_p = copy_node (*expr_p); + TREE_OPERAND (*expr_p, 1) = init; + return GS_OK; + } + } + default: ret = GS_UNHANDLED; break; @@ -6361,6 +6459,10 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, ret = gimplify_compound_expr (expr_p, pre_p, fallback != fb_none); break; + case COMPOUND_LITERAL_EXPR: + ret = gimplify_compound_literal_expr (expr_p, pre_p); + break; + case MODIFY_EXPR: case INIT_EXPR: ret = gimplify_modify_expr (expr_p, pre_p, post_p, diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h index 96c091c7f054c98d757d8f7c451be3f52b03dec4..4b6ce274c00f3b07c1a1320a1884b21791d09b15 100644 --- a/gcc/langhooks-def.h +++ b/gcc/langhooks-def.h @@ -46,12 +46,10 @@ extern tree lhd_return_null_tree_v (void); extern tree lhd_return_null_tree (tree); extern tree lhd_return_null_const_tree (const_tree); extern tree lhd_do_nothing_iii_return_null_tree (int, int, int); -extern tree lhd_staticp (tree); extern void lhd_print_tree_nothing (FILE *, tree, int); extern const char *lhd_decl_printable_name (tree, int); extern const char *lhd_dwarf_name (tree, int); extern int lhd_types_compatible_p (tree, tree); -extern rtx lhd_expand_expr (tree, rtx, enum machine_mode, int, rtx *); extern void lhd_print_error_function (struct diagnostic_context *, const char *, struct diagnostic_info *); extern void lhd_set_decl_assembler_name (tree); @@ -92,9 +90,7 @@ extern void lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *, #define LANG_HOOKS_POST_OPTIONS lhd_post_options #define LANG_HOOKS_MISSING_NORETURN_OK_P hook_bool_tree_true #define LANG_HOOKS_GET_ALIAS_SET lhd_get_alias_set -#define LANG_HOOKS_EXPAND_EXPR lhd_expand_expr #define LANG_HOOKS_FINISH_INCOMPLETE_DECL lhd_do_nothing_t -#define LANG_HOOKS_STATICP lhd_staticp #define LANG_HOOKS_DUP_LANG_SPECIFIC_DECL lhd_do_nothing_t #define LANG_HOOKS_SET_DECL_ASSEMBLER_NAME lhd_set_decl_assembler_name #define LANG_HOOKS_PRINT_STATISTICS lhd_do_nothing @@ -241,10 +237,8 @@ extern tree lhd_make_node (enum tree_code); LANG_HOOKS_PARSE_FILE, \ LANG_HOOKS_MISSING_NORETURN_OK_P, \ LANG_HOOKS_GET_ALIAS_SET, \ - LANG_HOOKS_EXPAND_EXPR, \ LANG_HOOKS_FINISH_INCOMPLETE_DECL, \ LANG_HOOKS_MARK_ADDRESSABLE, \ - LANG_HOOKS_STATICP, \ LANG_HOOKS_DUP_LANG_SPECIFIC_DECL, \ LANG_HOOKS_SET_DECL_ASSEMBLER_NAME, \ LANG_HOOKS_PRINT_STATISTICS, \ diff --git a/gcc/langhooks.c b/gcc/langhooks.c index cdf1b6a7623ee1394e32f90f73149f3802a92772..bd01c3fb95ab876e0b163fde3139a4d0ee9afc01 100644 --- a/gcc/langhooks.c +++ b/gcc/langhooks.c @@ -117,14 +117,6 @@ lhd_print_tree_nothing (FILE * ARG_UNUSED (file), { } -/* Called from staticp. */ - -tree -lhd_staticp (tree ARG_UNUSED (exp)) -{ - return NULL; -} - /* Called from check_global_declarations. */ bool @@ -216,17 +208,6 @@ lhd_get_alias_set (tree ARG_UNUSED (t)) return -1; } -/* This is the default expand_expr function. */ - -rtx -lhd_expand_expr (tree ARG_UNUSED (t), rtx ARG_UNUSED (r), - enum machine_mode ARG_UNUSED (mm), - int ARG_UNUSED (em), - rtx * ARG_UNUSED (a)) -{ - gcc_unreachable (); -} - /* This is the default decl_printable_name function. */ const char * diff --git a/gcc/langhooks.h b/gcc/langhooks.h index 4069578168307e07f2a55d70b3fba37b5d23a6a9..6c57ca2599e8ea417a2eb042a90a2b7b49bf787e 100644 --- a/gcc/langhooks.h +++ b/gcc/langhooks.h @@ -293,10 +293,6 @@ struct lang_hooks Returns -1 if the language does nothing special for it. */ alias_set_type (*get_alias_set) (tree); - /* Called by expand_expr for language-specific tree codes. - Fourth argument is actually an enum expand_modifier. */ - rtx (*expand_expr) (tree, rtx, enum machine_mode, int, rtx *); - /* Function to finish handling an incomplete decl at the end of compilation. Default hook is does nothing. */ void (*finish_incomplete_decl) (tree); @@ -306,9 +302,6 @@ struct lang_hooks successful. */ bool (*mark_addressable) (tree); - /* Hook called by staticp for language-specific tree codes. */ - tree (*staticp) (tree); - /* Replace the DECL_LANG_SPECIFIC data, which may be NULL, of the DECL_NODE with a newly GC-allocated copy. */ void (*dup_lang_specific_decl) (tree); diff --git a/gcc/tree.c b/gcc/tree.c index d0117a0a4fe9d544acb6e429669a921075ed3728..9a6e00029408b24b60c6f9fa9dcca5410757dff4 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -2098,8 +2098,7 @@ staticp (tree arg) case COMPONENT_REF: /* If the thing being referenced is not a field, then it is something language specific. */ - if (TREE_CODE (TREE_OPERAND (arg, 1)) != FIELD_DECL) - return (*lang_hooks.staticp) (arg); + gcc_assert (TREE_CODE (TREE_OPERAND (arg, 1)) == FIELD_DECL); /* If we are referencing a bitfield, we can't evaluate an ADDR_EXPR at compile time and so it isn't a constant. */ @@ -2122,14 +2121,13 @@ staticp (tree arg) && TREE_CODE (TREE_OPERAND (arg, 1)) == INTEGER_CST) return staticp (TREE_OPERAND (arg, 0)); else - return false; + return NULL; + + case COMPOUND_LITERAL_EXPR: + return TREE_STATIC (COMPOUND_LITERAL_EXPR_DECL (arg)) ? arg : NULL; default: - if ((unsigned int) TREE_CODE (arg) - >= (unsigned int) LAST_AND_UNUSED_TREE_CODE) - return lang_hooks.staticp (arg); - else - return NULL; + return NULL; } } diff --git a/gcc/tree.def b/gcc/tree.def index c67581203d02a8dd875533f21170e4de5db877a3..21f4db02d1fe96d79a7604a52e91b75e10225236 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -786,6 +786,13 @@ DEFTREECODE (NON_LVALUE_EXPR, "non_lvalue_expr", tcc_unary, 1) generating insns. */ DEFTREECODE (VIEW_CONVERT_EXPR, "view_convert_expr", tcc_reference, 1) +/* A COMPOUND_LITERAL_EXPR represents a literal that is placed in a DECL. The + COMPOUND_LITERAL_EXPR_DECL_EXPR is the a DECL_EXPR containing the decl + for the anonymous object represented by the COMPOUND_LITERAL; + the DECL_INITIAL of that decl is the CONSTRUCTOR that initializes + the compound literal. */ +DEFTREECODE (COMPOUND_LITERAL_EXPR, "compound_literal_expr", tcc_expression, 1) + /* Represents something we computed once and will use multiple times. First operand is that expression. After it is evaluated once, it will be replaced by the temporary variable that holds the value. */ diff --git a/gcc/tree.h b/gcc/tree.h index 9ff30a39e2d1901345b5db4a0d85a1f2b4175ebc..0eb2dc6449b02b1fa4040e349977f3f13729d81b 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1590,6 +1590,12 @@ extern void protected_set_expr_location (tree, location_t); #define EXIT_EXPR_COND(NODE) TREE_OPERAND (EXIT_EXPR_CHECK (NODE), 0) +/* COMPOUND_LITERAL_EXPR accessors. */ +#define COMPOUND_LITERAL_EXPR_DECL_EXPR(NODE) \ + TREE_OPERAND (COMPOUND_LITERAL_EXPR_CHECK (NODE), 0) +#define COMPOUND_LITERAL_EXPR_DECL(NODE) \ + DECL_EXPR_DECL (COMPOUND_LITERAL_EXPR_DECL_EXPR (NODE)) + /* SWITCH_EXPR accessors. These give access to the condition, body and original condition type (before any compiler conversions) of the switch statement, respectively. */