* alias.c (adjust_offset_for_component_ref): Use
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 22 Jun 2004 03:07:05 +0000 (03:07 +0000)
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 22 Jun 2004 03:07:05 +0000 (03:07 +0000)
component_ref_field_offset.
* c-decl.c (build_array_declarator): Add news args for ARRAY_REF.
* c-gimplify.c (gimplify_expr_stmt): Use alloc_stmt_list.
(gimplify_decl_stmt): Call gimplify_type_sizes for type.
For decl, call gimplify_one_sizepos and use statement list.
(gimplify_compound_literal_expr): New arg PRE_P.
Add statement to PRE_P list and return DECL.
(c_gimplify_expr, case COMPOUND_LITERAL_EXPR): Add arg to
gimplify_compound_literal_expr.
* c-tree.h (getdecls): Deleted.
* c-typeck.c (build_component_ref): Add operand for COMPONENT_REF.
(build_array_ref): Add two operands for ARRAY_REF.
(build_unary_op): Set TREE_INVARIANT and TREE_CONSTANT for
COMPOUND_LITERAL_EXPR.
* coverage.c (tree_coverage_counter_ref): Add new operands
for ARRAY_REF.
* emit-rtl.c (component_ref_for_mem_expr): Add new operand
for COMPONENT_REF.
(set_mem_attributes_minus_bitpos): Use array_ref_low_bound
and array_ref_element_size.
(widen_memory_access):Use component_ref_field_offset.
* explow.c (update_nonlocal_goto_save_area): Add two operands
for ARRAY_REF.
* expr.c (array_ref_element_size, array_ref_low_bound): New functions.
(component_ref_field_offset): Likewise.
(get_inner_reference): Use them.
(expand_expr_real_1, case ARRAY_REF): Use array_ref_low_bound.
* fold-const.c (fold, case EQ_EXPR): Properly handle DECL_SIZE.
(fold_read_from_constant_string): Use array_ref_low_bound.
Verify that result is a character type.
(build_fold_indirect_ref): Add two operands for ARRAY_REF.
* function.c (expand_function_start): Likewise.
* gimple-low.c (expand_var_p): Delete duplicated line.
* gimplify.c: Add static decls for local functions.
(cgraph.h): Now included.
(create_tmp_var): Remove check for ARRAY_TYPE.
(copy_if_shared_r): Look at bounds and sizes of types.
(build_and_jump): Return alloc_stmt_list instead of build_empty_stmt.
(gimplify_exit_expr, shortcut_cond_expr): Likewise.
(gimplify_save_expr, gimple_push_cleanup): Likewise.
(gimplify_init_constructor): Likewise.
WANT_VALUE now bool.
If empty list with no result wanted, return GS_UNHANDLED.
Add additional operands for ARRAY_REF and COMPONENT_REF.
(canonicalize_component_ref): Convert to &array[L].
(gimplify_array_ref_to_plus): Use array_ref_element_size and
array_ref_lower_bound.
(build_addr_expr_with_type, build_addr_expr): New functions.
(gimplify_compound_lval): WANT_LVALUE now bool.
Major rework to allow handle_component_p and initialize and
gimplify new operands for ARRAY_REF, ARRAY_RANGE_REF, and
COMPONENT_REF.
(gimplify_array_ref): Deleted.
(gimplify_self_mod_expr): WANT_VALUE now bool.
(gimplify_modify_expr): Gimplify to_p and from_p later.
Factor out code into gimplify_modify_expr_rhs and call twice.
Move variable-size code earlier and handle PLACEHOLDER_EXPR.
(gimplify_modify_expr_rhs, gimplify_variable_sized_compare): New fns.
(gimplify_addr_expr, case VIEW_CONVERT_EXPR): New case.
(gimplify_expr, case ARRAY_REF): Delete special case.
Instead handle like COMPONENT_REF; also do ARRAY_RANGE_REF,
IMAGPART, and REALPART the same way.
(gimplify_expr, case VIEW_CONVERT_EXPR): New case.
(gimplify_expr): Call gimplify_variable_sized_compare if applicable.
Call alloc_stmt_list instead of build_empty_stmt.
Deal with _REF that's volatile.
(gimplify_type_sizes, gimplify_one_sizepos): New functions.
(unshare_body, unvisit_body): New functions.
(gimplify_body): Call them.
* stmt.c (expand_stack_alloc): Don't expand TYPE_MAX_VALUE.
* stor-layout.c (get_pending_sizes): Don't change SAVE_EXPR_CONTEXT.
* tree-alias-common.c (get_alias_var): Also skip ARRAY_RANGE_REF.
* tree-cfg.c (tree_node_can_be_shared): Treat ARRAY_RANGE_REF
like ARRAY_REF.
(verify_expr, case ADDR_EXPR): Use handled_component_p.
* tree-dfa.c (get_virtual_var): Likewise.
* tree-dump.c (dequeue_and_dump, case COMPONENT_REF, ARRAY_REF):
New cases to dump new operands; likewise for ARRAY_RANGE_REF.
* tree-eh.c (tree_could_trap, case ARRAY_RANGE_REF): Like ARRAY_REF.
* tree-gimple.c (is_gimple_addr_expr_arg): Add ARRAY_RANGE_REF
and INDIRECT_REF.
(get_base_address): Use handled_component_p.
* tree-gimple.h (gimplify_type_sizes, gimplify_one_sizepos): New.
* tree-line.c (walk_tree): Walk more things for types and decls.
* tree-mudflap.c (mf_build_check_statement_for): Add new operands
for ARRAY_REF and COMPONENT_REF.
(mx_xform_derefs_1): Clean up usage of decl sizes.
* tree-nested.c (build_addr): Use handled_component_p.
(walk_stmts, case CATCH_EXPR): Add missing "break".
(get_static_chain, get_frame_field): Add new operand for COMPONENT_REF.
(finalize_nesting_tree_1): Likewise.
(convert_nonlocal_reference, case ARRAY_RANGE_REF): Like ARRAY_REF
and process additional operands.
(convert_local_reference): Likewise.
* tree-outof-ssa.c (discover_nonconstant_array_refs_r): Treat
ARRAY_RANGE_REF similarly to ARRAY_REF.
* tree-pretty-print.c (dump_generic_node, case QUAL_UNION_TYPE): Handle
like RECORD_TYPE.
(dump_generic_node, case COMPONENT_REF): Print offset operand.
(dump_generic_node, case ARRAY_RANGE_REF): Treat like ARRAY_REF
and print lower bound and element size for both.
(op_prio, case ARRAY_RANGE_REF): Like ARRAY_REF.
* tree-sra.c (csc_build_component_ref): Add new operand.
(scalarize_call_expr): Use get_base_address.
* tree-ssa-ccp.c (widen_bitfield): Clean up size handling.
(maybe_fold_offset_to_array_ref): Rework to handle input having an
ARRAY_REF, refine handling of lower bound, and add new operands
for ARRAY_REF.
(maybe_fold_to_component_ref): Add new operand for COMPONENT_REF.
(maybe_fold_stmt_indirect): Only fold *&B to B if types match.
(maybe_fold_stmt_addition): Only handle constant lower bound.
* tree-ssa-operands.c (get_expr_operands): Minor rearrangements.
Treat ARRAY_REF and ARRAY_RANGE_REF the same; look at extra operands.
Look at new offset operand of COMPONENT_REF.
* tree-ssa.c (set_is_used): Use handled_component_p.
* tree.c (substitute_in_expr, case COMPONENT_REF): Add new operand.
(stabilize_reference, case COMPONENT_REF): Likewise.
(stabilize_reference, case ARRAY_RANGE_REF, ARRAY_REF): Similarly.
(recompute_tree_invariant_for_addr_expr): Completely rework to
be more precise.  Also set TREE_SIDE_EFFECTS.
(build1_stat, case ARRAY_EXPR): Don't handle TREE_SIDE_EFFECTS here.
(build2_stat, build3_stat, build4_stat): For references,
propagate TREE_THIS_VOLATILE.
(get_unwidened): Add new operand for COMPONENT_REF.
(get_narrower): Likewise; use host_integerp for DECL_SIZE.
* tree.def (COMPONENT_REF): Add new operand.
(ARRAY_REF, ARRAY_RANGE_REF): Add two new operands.
* tree.h (array_ref_element_size, array_ref_low_bound): New decls.
(component_ref_field_offset): Likewise.
* config/alpha/alpha.c (alpha_va_start): Add new op for COMPONENT_REF.
(alpha_gimplify_va_arg): Likewise.
* config/i386/i386.c (ix86_va_start, ix86_gimplify_va_arg): Likewise.
* config/i860/i860.c (i860_va_start, i860_va_arg): Likewise.
* config/iq2000/iq2000.c (iq2000_va_arg): Likewise.
* config/mips/mips.c (mips_va_start, mips_va_arg): Likewise.
* config/rs6000/rs6000.c (rs6000_va_start, rs6000_gimplify_va_arg):
Likewise.
* config/s390/s390.c (s390_va_start, s390_gimplify_va_arg): Likewise.
* config/sh/sh.c (sh_va_start, sh_va_arg): Likewise.
* config/stormy16/stormy16.c (xstormy1_expand_builin_va_start):
Likewise.
(xstormy16_expand_builtin_va_arg): Likewise.
* config/xtensa/xtensa.c (xtensa_va_start, xtensa_va_arg): Likewise.

* cp/call.c (build_vfield_ref): Add new operand for COMPONENT_REF.
(build_new_method_call): Likewise.
* cp/decl.c (local_variable_p_walkfn): Don't walk into types.
* cp/decl2.c (grok_array_decl): Add new operands for ARRAY_REF.
(build_anon_union_vars): Add new operand for COMPONENT_REF.
* cp/init.c (buld_new): Add new operand for ARRAY_REF.
* cp/method.c (do_build_copy_constructor): New op for COMPONENT_REF.
(do_build_assign_ref): Likewise.
* cp/parser.c (cp_parser_direct_new_declarator): Add new operands
for ARRAY_REF.
(cp_parser_direct_declarator): Likewise.
* cp/pt.c (tsubst): Likewise.
(tsubst_copy, tsubst_copy_and_build): Likewise; also add new operand
  for COMPONENT_REF.
* cp/semantics.c (finish_non_static_data_member): Add new operand
for COMPONENT_REF.
* cp/typeck.c (build_class_member_access_expr): Likewise.
(build_class_member_access_expr, finish_class_member_access_expr):
Likewise.
(build_ptrmemfunc_access_expr): Likewise.
(build_array_ref): Add new operands for ARRAY_REF.
* cp/typeck2.c (split_nonconstant_init_1): Likewise; COMPONENT_REF too.
* cp/tree.c (count_trees_r, no_linkage_helper): Don't walk in types.

* fortran/f95-lang.c (LANG_HOOKS_GIMPLE_BEFORE_INLINING): Deleted.
* fortran/trans-array.c (gfc_conv_descriptor_data): Add operand
for COMPONENT_REF.
(gfc_conv_descriptor_offset, gfc_conv_descriptor_dtype): Likewise.
(gfc_conv_descriptor_dimension, gfc_conv_descriptor_stride): Likewise.
(gfc_conv_descriptor_lbound, gfc_conv_descriptor_ubound): Likewise.
* fortran/trans-common.c (create_common): Likewise.
* fortran/trans-expr.c (gfc_conv_component_ref): Likewise.
* fortran/trans-io.c (set_parameter_value): Likewise.
(set_parameter_ref, set_string, set_flag, io_result): Likewise.
(transfer_expr): Likewise.
* fortran/trans-decl.c (gfc_trans_auto_character_variable):
Set up to get DECL_SIZE and DECL_SIZE_UNIT gimplified.
(gfc_simplify_function): New function.
(gfc_generate_function-code): Properly handle nested functions.
* fortran/trans.c (gfc_build_array_ref): Add two new operands
for ARRAY_REF.

* java/class.c (build_class_ref): Add new operand for COMPONENT_REF.
(build_static_field_ref): Likewise and add new operands for ARRAY_REF.
* java/constants.c (build_ref_from_constant_pool): Likewise.
* java/expr.c (build_java_array_length_access): Likewise.
(build_get_class, build_field_ref, build_known_method_ref): Likewise.
(invoke_build_dtable, build_invokevirtual): Likewise.
(build_invokeinterface, java_expand_expr): Likewise.
(emit_init_test_initialization): Likewise.
* java/java-gimplify.c (java_gimplify_new_array_init): Likewise.
* java/parse.y (make_qualifed_name, build_array_ref): Likewise.

* objc/ojbc-act.c (generate_static_references): Add additional
operands to ARRAY_REF.
(generate_strings, build_method_prototype_list_template): Likewise.
(generate_protocol_list): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@83474 138bc75d-0d04-0410-961f-82ee72b054a4

72 files changed:
gcc/ChangeLog
gcc/alias.c
gcc/c-decl.c
gcc/c-gimplify.c
gcc/c-tree.h
gcc/c-typeck.c
gcc/config/alpha/alpha.c
gcc/config/i386/i386.c
gcc/config/i860/i860.c
gcc/config/iq2000/iq2000.c
gcc/config/mips/mips.c
gcc/config/rs6000/rs6000.c
gcc/config/s390/s390.c
gcc/config/sh/sh.c
gcc/config/stormy16/stormy16.c
gcc/config/xtensa/xtensa.c
gcc/coverage.c
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/init.c
gcc/cp/method.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/cp/typeck2.c
gcc/emit-rtl.c
gcc/explow.c
gcc/expr.c
gcc/fold-const.c
gcc/fortran/ChangeLog
gcc/fortran/f95-lang.c
gcc/fortran/trans-array.c
gcc/fortran/trans-common.c
gcc/fortran/trans-decl.c
gcc/fortran/trans-expr.c
gcc/fortran/trans-io.c
gcc/fortran/trans.c
gcc/function.c
gcc/gimple-low.c
gcc/gimplify.c
gcc/java/ChangeLog
gcc/java/class.c
gcc/java/constants.c
gcc/java/expr.c
gcc/java/java-gimplify.c
gcc/java/parse.y
gcc/objc/objc-act.c
gcc/stmt.c
gcc/stor-layout.c
gcc/tree-alias-common.c
gcc/tree-cfg.c
gcc/tree-dfa.c
gcc/tree-dump.c
gcc/tree-eh.c
gcc/tree-gimple.c
gcc/tree-gimple.h
gcc/tree-inline.c
gcc/tree-mudflap.c
gcc/tree-nested.c
gcc/tree-outof-ssa.c
gcc/tree-pretty-print.c
gcc/tree-sra.c
gcc/tree-ssa-ccp.c
gcc/tree-ssa-operands.c
gcc/tree-ssa.c
gcc/tree.c
gcc/tree.def
gcc/tree.h

index 9f124c1..8829c32 100644 (file)
@@ -1,3 +1,153 @@
+2004-06-21  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
+
+       * alias.c (adjust_offset_for_component_ref): Use
+       component_ref_field_offset.
+       * c-decl.c (build_array_declarator): Add news args for ARRAY_REF.
+       * c-gimplify.c (gimplify_expr_stmt): Use alloc_stmt_list.
+       (gimplify_decl_stmt): Call gimplify_type_sizes for type.
+       For decl, call gimplify_one_sizepos and use statement list.
+       (gimplify_compound_literal_expr): New arg PRE_P.
+       Add statement to PRE_P list and return DECL.
+       (c_gimplify_expr, case COMPOUND_LITERAL_EXPR): Add arg to
+       gimplify_compound_literal_expr.
+       * c-tree.h (getdecls): Deleted.
+       * c-typeck.c (build_component_ref): Add operand for COMPONENT_REF.
+       (build_array_ref): Add two operands for ARRAY_REF.
+       (build_unary_op): Set TREE_INVARIANT and TREE_CONSTANT for
+       COMPOUND_LITERAL_EXPR.
+       * coverage.c (tree_coverage_counter_ref): Add new operands
+       for ARRAY_REF.
+       * emit-rtl.c (component_ref_for_mem_expr): Add new operand
+       for COMPONENT_REF.
+       (set_mem_attributes_minus_bitpos): Use array_ref_low_bound
+       and array_ref_element_size.
+       (widen_memory_access):Use component_ref_field_offset.
+       * explow.c (update_nonlocal_goto_save_area): Add two operands
+       for ARRAY_REF.
+       * expr.c (array_ref_element_size, array_ref_low_bound): New functions.
+       (component_ref_field_offset): Likewise.
+       (get_inner_reference): Use them.
+       (expand_expr_real_1, case ARRAY_REF): Use array_ref_low_bound.
+       * fold-const.c (fold, case EQ_EXPR): Properly handle DECL_SIZE.
+       (fold_read_from_constant_string): Use array_ref_low_bound.
+       Verify that result is a character type.
+       (build_fold_indirect_ref): Add two operands for ARRAY_REF.
+       * function.c (expand_function_start): Likewise.
+       * gimple-low.c (expand_var_p): Delete duplicated line.
+       * gimplify.c: Add static decls for local functions.
+       (cgraph.h): Now included.
+       (create_tmp_var): Remove check for ARRAY_TYPE.
+       (copy_if_shared_r): Look at bounds and sizes of types.
+       (build_and_jump): Return alloc_stmt_list instead of build_empty_stmt.
+       (gimplify_exit_expr, shortcut_cond_expr): Likewise.
+       (gimplify_save_expr, gimple_push_cleanup): Likewise.
+       (gimplify_init_constructor): Likewise.
+       WANT_VALUE now bool.
+       If empty list with no result wanted, return GS_UNHANDLED.
+       Add additional operands for ARRAY_REF and COMPONENT_REF.
+       (canonicalize_component_ref): Convert to &array[L].
+       (gimplify_array_ref_to_plus): Use array_ref_element_size and
+       array_ref_lower_bound.
+       (build_addr_expr_with_type, build_addr_expr): New functions.
+       (gimplify_compound_lval): WANT_LVALUE now bool.
+       Major rework to allow handle_component_p and initialize and
+       gimplify new operands for ARRAY_REF, ARRAY_RANGE_REF, and
+       COMPONENT_REF.
+       (gimplify_array_ref): Deleted.
+       (gimplify_self_mod_expr): WANT_VALUE now bool.
+       (gimplify_modify_expr): Gimplify to_p and from_p later.
+       Factor out code into gimplify_modify_expr_rhs and call twice.
+       Move variable-size code earlier and handle PLACEHOLDER_EXPR.
+       (gimplify_modify_expr_rhs, gimplify_variable_sized_compare): New fns.
+       (gimplify_addr_expr, case VIEW_CONVERT_EXPR): New case.
+       (gimplify_expr, case ARRAY_REF): Delete special case.
+       Instead handle like COMPONENT_REF; also do ARRAY_RANGE_REF,
+       IMAGPART, and REALPART the same way.
+       (gimplify_expr, case VIEW_CONVERT_EXPR): New case.
+       (gimplify_expr): Call gimplify_variable_sized_compare if applicable.
+       Call alloc_stmt_list instead of build_empty_stmt.
+       Deal with _REF that's volatile.
+       (gimplify_type_sizes, gimplify_one_sizepos): New functions.
+       (unshare_body, unvisit_body): New functions.
+       (gimplify_body): Call them.
+       * stmt.c (expand_stack_alloc): Don't expand TYPE_MAX_VALUE.
+       * stor-layout.c (get_pending_sizes): Don't change SAVE_EXPR_CONTEXT.
+       * tree-alias-common.c (get_alias_var): Also skip ARRAY_RANGE_REF.
+       * tree-cfg.c (tree_node_can_be_shared): Treat ARRAY_RANGE_REF
+       like ARRAY_REF.
+       (verify_expr, case ADDR_EXPR): Use handled_component_p.
+       * tree-dfa.c (get_virtual_var): Likewise.
+       * tree-dump.c (dequeue_and_dump, case COMPONENT_REF, ARRAY_REF):
+       New cases to dump new operands; likewise for ARRAY_RANGE_REF.
+       * tree-eh.c (tree_could_trap, case ARRAY_RANGE_REF): Like ARRAY_REF.
+       * tree-gimple.c (is_gimple_addr_expr_arg): Add ARRAY_RANGE_REF
+       and INDIRECT_REF.
+       (get_base_address): Use handled_component_p.
+       * tree-gimple.h (gimplify_type_sizes, gimplify_one_sizepos): New.
+       * tree-inline.c (walk_tree): Walk more things for types and decls.
+       * tree-mudflap.c (mf_build_check_statement_for): Add new operands
+       for ARRAY_REF and COMPONENT_REF.
+       (mx_xform_derefs_1): Clean up usage of decl sizes.
+       * tree-nested.c (build_addr): Use handled_component_p.
+       (walk_stmts, case CATCH_EXPR): Add missing "break".
+       (get_static_chain, get_frame_field): Add new operand for COMPONENT_REF.
+       (finalize_nesting_tree_1): Likewise.
+       (convert_nonlocal_reference, case ARRAY_RANGE_REF): Like ARRAY_REF
+       and process additional operands.
+       (convert_local_reference): Likewise.
+       * tree-outof-ssa.c (discover_nonconstant_array_refs_r): Treat
+       ARRAY_RANGE_REF similarly to ARRAY_REF.
+       * tree-pretty-print.c (dump_generic_node, case QUAL_UNION_TYPE): Handle
+       like RECORD_TYPE.
+       (dump_generic_node, case COMPONENT_REF): Print offset operand.
+       (dump_generic_node, case ARRAY_RANGE_REF): Treat like ARRAY_REF
+       and print lower bound and element size for both.
+       (op_prio, case ARRAY_RANGE_REF): Like ARRAY_REF.
+       * tree-sra.c (csc_build_component_ref): Add new operand.
+       (scalarize_call_expr): Use get_base_address.
+       * tree-ssa-ccp.c (widen_bitfield): Clean up size handling.
+       (maybe_fold_offset_to_array_ref): Rework to handle input having an
+       ARRAY_REF, refine handling of lower bound, and add new operands
+       for ARRAY_REF.
+       (maybe_fold_to_component_ref): Add new operand for COMPONENT_REF.
+       (maybe_fold_stmt_indirect): Only fold *&B to B if types match.
+       (maybe_fold_stmt_addition): Only handle constant lower bound.
+       * tree-ssa-operands.c (get_expr_operands): Minor rearrangements.
+       Treat ARRAY_REF and ARRAY_RANGE_REF the same; look at extra operands.
+       Look at new offset operand of COMPONENT_REF.
+       * tree-ssa.c (set_is_used): Use handled_component_p.
+       * tree.c (substitute_in_expr, case COMPONENT_REF): Add new operand.
+       (stabilize_reference, case COMPONENT_REF): Likewise.
+       (stabilize_reference, case ARRAY_RANGE_REF, ARRAY_REF): Similarly.
+       (recompute_tree_invariant_for_addr_expr): Completely rework to
+       be more precise.  Also set TREE_SIDE_EFFECTS.
+       (build1_stat, case ARRAY_EXPR): Don't handle TREE_SIDE_EFFECTS here.
+       (build2_stat, build3_stat, build4_stat): For references,
+       propagate TREE_THIS_VOLATILE.
+       (get_unwidened): Add new operand for COMPONENT_REF.
+       (get_narrower): Likewise; use host_integerp for DECL_SIZE.
+       * tree.def (COMPONENT_REF): Add new operand.
+       (ARRAY_REF, ARRAY_RANGE_REF): Add two new operands.
+       * tree.h (array_ref_element_size, array_ref_low_bound): New decls.
+       (component_ref_field_offset): Likewise.
+       * config/alpha/alpha.c (alpha_va_start): Add new op for COMPONENT_REF.
+       (alpha_gimplify_va_arg): Likewise.
+       * config/i386/i386.c (ix86_va_start, ix86_gimplify_va_arg): Likewise.
+       * config/i860/i860.c (i860_va_start, i860_va_arg): Likewise.
+       * config/iq2000/iq2000.c (iq2000_va_arg): Likewise.
+       * config/mips/mips.c (mips_va_start, mips_va_arg): Likewise.
+       * config/rs6000/rs6000.c (rs6000_va_start, rs6000_gimplify_va_arg):
+       Likewise.
+       * config/s390/s390.c (s390_va_start, s390_gimplify_va_arg): Likewise.
+       * config/sh/sh.c (sh_va_start, sh_va_arg): Likewise.
+       * config/stormy16/stormy16.c (xstormy1_expand_builin_va_start):
+       Likewise.
+       (xstormy16_expand_builtin_va_arg): Likewise.
+       * config/xtensa/xtensa.c (xtensa_va_start, xtensa_va_arg): Likewise.
+       * objc/objc-act.c (generate_static_references): Likewise.
+       (generate_strings, build_method_prototype_list_template): Likewise.
+       (generate_protocol_list): Likewise.
+
 2004-06-21  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
 
        PR rtl-optimization/14782
index 8e168c2..b8661d7 100644 (file)
@@ -2015,11 +2015,12 @@ adjust_offset_for_component_ref (tree x, rtx offset)
   ioffset = INTVAL (offset);
   do
     {
+      tree offset = component_ref_field_offset (x);
       tree field = TREE_OPERAND (x, 1);
 
-      if (! host_integerp (DECL_FIELD_OFFSET (field), 1))
+      if (! host_integerp (offset, 1))
        return NULL_RTX;
-      ioffset += (tree_low_cst (DECL_FIELD_OFFSET (field), 1)
+      ioffset += (tree_low_cst (offset, 1)
                  + (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
                     / BITS_PER_UNIT));
 
index ec1778b..4735dab 100644 (file)
@@ -2508,7 +2508,7 @@ tree
 build_array_declarator (tree expr, tree quals, int static_p, int vla_unspec_p)
 {
   tree decl;
-  decl = build_nt (ARRAY_REF, NULL_TREE, expr);
+  decl = build_nt (ARRAY_REF, NULL_TREE, expr, NULL_TREE, NULL_TREE);
   TREE_TYPE (decl) = quals;
   TREE_STATIC (decl) = (static_p ? 1 : 0);
   if (pedantic && !flag_isoc99)
index 3597331..113a09d 100644 (file)
@@ -243,7 +243,7 @@ gimplify_expr_stmt (tree *stmt_p)
     }
 
   if (stmt == NULL_TREE)
-    stmt = build_empty_stmt ();
+    stmt = alloc_stmt_list ();
 
   *stmt_p = stmt;
 
@@ -475,8 +475,6 @@ gimplify_decl_stmt (tree *stmt_p)
 {
   tree stmt = *stmt_p;
   tree decl = DECL_STMT_DECL (stmt);
-  tree pre = NULL_TREE;
-  tree post = NULL_TREE;
 
   if (TREE_TYPE (decl) == error_mark_node)
     {
@@ -485,38 +483,34 @@ gimplify_decl_stmt (tree *stmt_p)
     }
     
   if (TREE_CODE (decl) == TYPE_DECL)
-    {
-      tree type = TREE_TYPE (decl);
-      if (TYPE_SIZE_UNIT (type)
-          && !TREE_CONSTANT (TYPE_SIZE_UNIT (type)))
-        {
-          /* This is a variable-sized array type.  Simplify its size.  */
-          tree temp = TYPE_SIZE_UNIT (type);
-          gimplify_expr (&temp, &pre, &post, is_gimple_val, fb_rvalue);
-        }
-    }
+    *stmt_p = gimplify_type_sizes (TREE_TYPE (decl));
 
-  if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
+  else if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
     {
       tree init = DECL_INITIAL (decl);
 
+      *stmt_p = NULL_TREE;
+      gimplify_one_sizepos (&DECL_SIZE (decl), stmt_p);
+      gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), stmt_p);
+
       if (!TREE_CONSTANT (DECL_SIZE (decl)))
        {
-         tree pt_type = build_pointer_type (TREE_TYPE (decl));
-         tree alloc, size;
-
          /* This is a variable-sized decl.  Simplify its size and mark it
             for deferred expansion.  Note that mudflap depends on the format
             of the emitted code: see mx_register_decls().  */
 
-         size = get_initialized_tmp_var (DECL_SIZE_UNIT (decl), &pre, &post);
+         tree pt_type = build_pointer_type (TREE_TYPE (decl));
+         tree alloc_stmt
+           = (build_function_call_expr
+              (implicit_built_in_decls[BUILT_IN_STACK_ALLOC],
+               tree_cons (NULL_TREE,
+                          build1 (ADDR_EXPR, pt_type, decl),
+                          tree_cons (NULL_TREE, DECL_SIZE_UNIT (decl),
+                                     NULL_TREE))));
+
+         gimplify_stmt (&alloc_stmt);
+         append_to_statement_list(alloc_stmt, stmt_p);
          DECL_DEFER_OUTPUT (decl) = 1;
-         alloc = build_function_call_expr
-           (implicit_built_in_decls[BUILT_IN_STACK_ALLOC],
-            tree_cons (NULL_TREE,
-                       build1 (ADDR_EXPR, pt_type, decl),
-                       tree_cons (NULL_TREE, size, NULL_TREE)));
-         append_to_compound_expr (alloc, &pre);
        }
 
       if (init && init != error_mark_node)
@@ -531,14 +525,13 @@ gimplify_decl_stmt (tree *stmt_p)
               
              DECL_INITIAL (decl) = NULL_TREE;
              init = build (MODIFY_EXPR, void_type_node, decl, init);
-             append_to_compound_expr (init, &pre);
+             gimplify_stmt (&init);
+             append_to_statement_list (init, stmt_p);
            }
          else
-           {
-             /* We must still examine initializers for static variables
-                as they may contain a label address.  */
-             walk_tree (&init, force_labels_r, NULL, NULL);
-           }
+           /* We must still examine initializers for static variables
+              as they may contain a label address.  */
+           walk_tree (&init, force_labels_r, NULL, NULL);
        }
 
       /* This decl isn't mentioned in the enclosing block, so add it to the
@@ -547,10 +540,10 @@ gimplify_decl_stmt (tree *stmt_p)
       if (DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
        gimple_add_tmp_var (decl);
     }
+  else
+    *stmt_p = alloc_stmt_list ();
 
-  append_to_compound_expr (post, &pre);
-  *stmt_p = pre;
-  return GS_OK;
+  return GS_ALL_DONE;
 }
 
 /* Gimplification of expression trees.  */
@@ -560,7 +553,7 @@ gimplify_decl_stmt (tree *stmt_p)
    instead.  */
 
 static enum gimplify_status
-gimplify_compound_literal_expr (tree *expr_p)
+gimplify_compound_literal_expr (tree *expr_p, tree *pre_p)
 {
   tree decl_s = COMPOUND_LITERAL_EXPR_DECL_STMT (*expr_p);
   tree decl = DECL_STMT_DECL (decl_s);
@@ -572,7 +565,8 @@ gimplify_compound_literal_expr (tree *expr_p)
     gimple_add_tmp_var (decl);
 
   gimplify_decl_stmt (&decl_s);
-  *expr_p = decl_s ? decl_s : decl;
+  append_to_statement_list (decl_s, pre_p);
+  *expr_p = decl;
   return GS_OK;
 }
 
@@ -586,7 +580,7 @@ c_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p ATTRIBUTE_UNUSED)
   switch (code)
     {
     case COMPOUND_LITERAL_EXPR:
-      return gimplify_compound_literal_expr (expr_p);
+      return gimplify_compound_literal_expr (expr_p, pre_p);
 
     case FOR_STMT:
       return gimplify_for_stmt (expr_p, pre_p);
index 052275a..66691eb 100644 (file)
@@ -147,7 +147,6 @@ extern int c_in_iteration_stmt;
 extern int c_in_case_stmt;
 
 extern int global_bindings_p (void);
-extern tree getdecls (void);
 extern void push_scope (void);
 extern tree pop_scope (void);
 extern void insert_block (tree);
index e619fa1..63c9121 100644 (file)
@@ -1222,10 +1222,10 @@ default_function_array_conversion (tree exp)
 
       if (TREE_CODE (exp) == VAR_DECL)
        {
-         /* ??? This is not really quite correct
-            in that the type of the operand of ADDR_EXPR
-            is not the target type of the type of the ADDR_EXPR itself.
-            Question is, can this lossage be avoided?  */
+         /* We are making an ADDR_EXPR of ptrtype.  This is a valid
+            ADDR_EXPR because it's the best way of representing what
+            happens in C when we take the address of an array and place
+            it in a pointer to the element type.  */
          adr = build1 (ADDR_EXPR, ptrtype, exp);
          if (!c_mark_addressable (exp))
            return error_mark_node;
@@ -1483,7 +1483,8 @@ build_component_ref (tree datum, tree component)
          if (TREE_TYPE (subdatum) == error_mark_node)
            return error_mark_node;
 
-         ref = build (COMPONENT_REF, TREE_TYPE (subdatum), datum, subdatum);
+         ref = build (COMPONENT_REF, TREE_TYPE (subdatum), datum, subdatum,
+                      NULL_TREE);
          if (TREE_READONLY (datum) || TREE_READONLY (subdatum))
            TREE_READONLY (ref) = 1;
          if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (subdatum))
@@ -1636,7 +1637,7 @@ build_array_ref (tree array, tree index)
        }
 
       type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array)));
-      rval = build (ARRAY_REF, type, array, index);
+      rval = build (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE);
       /* Array ref is const/volatile if the array elements are
          or if the array is.  */
       TREE_READONLY (rval)
@@ -2562,6 +2563,9 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
        else
          addr = build1 (code, argtype, arg);
 
+       if (TREE_CODE (arg) == COMPOUND_LITERAL_EXPR)
+         TREE_INVARIANT (addr) = TREE_CONSTANT (addr) = 1;
+
        return addr;
       }
 
index 36b765e..dd4409a 100644 (file)
@@ -6274,9 +6274,9 @@ alpha_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
       offset_field = TREE_CHAIN (base_field);
 
       base_field = build (COMPONENT_REF, TREE_TYPE (base_field),
-                         valist, base_field);
+                         valist, base_field, NULL_TREE);
       offset_field = build (COMPONENT_REF, TREE_TYPE (offset_field),
-                           valist, offset_field);
+                           valist, offset_field, NULL_TREE);
 
       t = make_tree (ptr_type_node, virtual_incoming_args_rtx);
       t = build (PLUS_EXPR, ptr_type_node, t, build_int_2 (offset, 0));
@@ -6383,9 +6383,9 @@ alpha_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
   base_field = TYPE_FIELDS (va_list_type_node);
   offset_field = TREE_CHAIN (base_field);
   base_field = build (COMPONENT_REF, TREE_TYPE (base_field),
-                     valist, base_field);
+                     valist, base_field, NULL_TREE);
   offset_field = build (COMPONENT_REF, TREE_TYPE (offset_field),
-                       valist, offset_field);
+                       valist, offset_field, NULL_TREE);
 
   /* Pull the fields of the structure out into temporaries.  Since we never
      modify the base field, we can use a formal temporary.  Sign-extend the
index 8313e0a..30d0315 100644 (file)
@@ -3136,10 +3136,10 @@ ix86_va_start (tree valist, rtx nextarg)
   f_sav = TREE_CHAIN (f_ovf);
 
   valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist);
-  gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr);
-  fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr);
-  ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf);
-  sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav);
+  gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
+  fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
+  ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
+  sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
 
   /* Count number of gp and fp argument registers used.  */
   words = current_function_args_info.words;
@@ -3202,10 +3202,10 @@ ix86_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
   f_sav = TREE_CHAIN (f_ovf);
 
   valist = build_fold_indirect_ref (valist);
-  gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr);
-  fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr);
-  ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf);
-  sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav);
+  gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
+  fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
+  ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
+  sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
 
   size = int_size_in_bytes (type);
   if (size == -1)
index 7c455eb..d23277d 100644 (file)
@@ -1877,10 +1877,10 @@ i860_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
   f_fpr = TREE_CHAIN (f_gpr);
 #endif
 
-  gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr);
-  fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr);
-  sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav);
-  mem = build (COMPONENT_REF, TREE_TYPE (f_mem), valist, f_mem);
+  gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
+  fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
+  sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
+  mem = build (COMPONENT_REF, TREE_TYPE (f_mem), valist, f_mem, NULL_TREE);
 
   /* Initialize the `mem_ptr' field to the address of the first anonymous
      stack argument.  */
@@ -1943,10 +1943,10 @@ i860_va_arg (tree valist, tree type)
   f_fpr = TREE_CHAIN (f_gpr);
 #endif
 
-  gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr);
-  fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr);
-  mem = build (COMPONENT_REF, TREE_TYPE (f_mem), valist, f_mem);
-  sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav);
+  gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
+  fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
+  mem = build (COMPONENT_REF, TREE_TYPE (f_mem), valist, f_mem, NULL_TREE);
+  sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
 
   size = int_size_in_bytes (type);
 
index 41d4a0e..786a7b6 100644 (file)
@@ -1656,11 +1656,11 @@ iq2000_va_arg (tree valist, tree type)
   f_goff = TREE_CHAIN (f_ftop);
   f_foff = TREE_CHAIN (f_goff);
 
-  ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl);
-  gtop = build (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop);
-  ftop = build (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop);
-  goff = build (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff);
-  foff = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff);
+  ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl, NULL_TREE);
+  gtop = build (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop, NULL_TREE);
+  ftop = build (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop, NULL_TREE);
+  goff = build (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff, NULL_TREE);
+  foff = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff, NULL_TREE);
 
   lab_false = gen_label_rtx ();
   lab_over = gen_label_rtx ();
index 9abd0b3..15489b1 100644 (file)
@@ -4045,11 +4045,16 @@ mips_va_start (tree valist, rtx nextarg)
          f_goff = TREE_CHAIN (f_ftop);
          f_foff = TREE_CHAIN (f_goff);
 
-         ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl);
-         gtop = build (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop);
-         ftop = build (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop);
-         goff = build (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff);
-         foff = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff);
+         ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl,
+                       NULL_TREE);
+         gtop = build (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop,
+                       NULL_TREE);
+         ftop = build (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop,
+                       NULL_TREE);
+         goff = build (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff,
+                       NULL_TREE);
+         foff = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff,
+                       NULL_TREE);
 
          /* Emit code to initialize OVFL, which points to the next varargs
             stack argument.  CUM->STACK_WORDS gives the number of stack
@@ -4212,12 +4217,15 @@ mips_va_arg (tree valist, tree type)
          lab_false = gen_label_rtx ();
          lab_over = gen_label_rtx ();
 
-         ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl);
+         ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl,
+                       NULL_TREE);
          if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT
              && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_FPVALUE)
            {
-             top = build (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop);
-             off = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff);
+             top = build (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop,
+                          NULL_TREE);
+             off = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff,
+                          NULL_TREE);
 
              /* When floating-point registers are saved to the stack,
                 each one will take up UNITS_PER_HWFPVALUE bytes, regardless
@@ -4245,8 +4253,10 @@ mips_va_arg (tree valist, tree type)
            }
          else
            {
-             top = build (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop);
-             off = build (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff);
+             top = build (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop,
+                          NULL_TREE);
+             off = build (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff,
+                          NULL_TREE);
              if (rsize > UNITS_PER_WORD)
                {
                  /* [1] Emit code for: off &= -rsize.  */
index 2376fc4..861b00a 100644 (file)
@@ -5026,10 +5026,10 @@ rs6000_va_start (tree valist, rtx nextarg)
   f_sav = TREE_CHAIN (f_ovf);
 
   valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist);
-  gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr);
-  fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr);
-  ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf);
-  sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav);
+  gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
+  fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
+  ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
+  sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
 
   /* Count number of gp and fp argument registers used.  */
   words = current_function_args_info.words;
@@ -5131,10 +5131,10 @@ rs6000_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
   f_sav = TREE_CHAIN (f_ovf);
 
   valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist);
-  gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr);
-  fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr);
-  ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf);
-  sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav);
+  gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
+  fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
+  ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
+  sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
 
   size = int_size_in_bytes (type);
   rsize = (size + 3) / 4;
index 3e2ad5a..cc48d01 100644 (file)
@@ -6381,10 +6381,10 @@ s390_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
   f_sav = TREE_CHAIN (f_ovf);
 
   valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist);
-  gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr);
-  fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr);
-  ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf);
-  sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav);
+  gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
+  fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
+  ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
+  sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
 
   /* Count number of gp and fp argument registers used.  */
 
@@ -6462,10 +6462,10 @@ s390_gimplify_va_arg (tree valist, tree type, tree *pre_p,
   f_sav = TREE_CHAIN (f_ovf);
 
   valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist);
-  gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr);
-  fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr);
-  ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf);
-  sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav);
+  gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
+  fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
+  ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
+  sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
 
   size = int_size_in_bytes (type);
 
index d70178b..2308f1b 100644 (file)
@@ -6237,14 +6237,16 @@ sh_va_start (tree valist, rtx nextarg)
   f_next_fp_limit = TREE_CHAIN (f_next_fp);
   f_next_stack = TREE_CHAIN (f_next_fp_limit);
 
-  next_o = build (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o);
+  next_o = build (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o,
+                 NULL_TREE);
   next_o_limit = build (COMPONENT_REF, TREE_TYPE (f_next_o_limit),
-                       valist, f_next_o_limit);
-  next_fp = build (COMPONENT_REF, TREE_TYPE (f_next_fp), valist, f_next_fp);
+                       valist, f_next_o_limit, NULL_TREE);
+  next_fp = build (COMPONENT_REF, TREE_TYPE (f_next_fp), valist, f_next_fp,
+                  NULL_TREE);
   next_fp_limit = build (COMPONENT_REF, TREE_TYPE (f_next_fp_limit),
-                        valist, f_next_fp_limit);
+                        valist, f_next_fp_limit, NULL_TREE);
   next_stack = build (COMPONENT_REF, TREE_TYPE (f_next_stack),
-                     valist, f_next_stack);
+                     valist, f_next_stack, NULL_TREE);
 
   /* Call __builtin_saveregs.  */
   u = make_tree (ptr_type_node, expand_builtin_saveregs ());
@@ -6317,15 +6319,16 @@ sh_va_arg (tree valist, tree type)
       f_next_fp_limit = TREE_CHAIN (f_next_fp);
       f_next_stack = TREE_CHAIN (f_next_fp_limit);
 
-      next_o = build (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o);
+      next_o = build (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o,
+                     NULL_TREE);
       next_o_limit = build (COMPONENT_REF, TREE_TYPE (f_next_o_limit),
-                           valist, f_next_o_limit);
+                           valist, f_next_o_limit, NULL_TREE);
       next_fp = build (COMPONENT_REF, TREE_TYPE (f_next_fp),
-                      valist, f_next_fp);
+                      valist, f_next_fp, NULL_TREE);
       next_fp_limit = build (COMPONENT_REF, TREE_TYPE (f_next_fp_limit),
-                            valist, f_next_fp_limit);
+                            valist, f_next_fp_limit, NULL_TREE);
       next_stack = build (COMPONENT_REF, TREE_TYPE (f_next_stack),
-                         valist, f_next_stack);
+                         valist, f_next_stack, NULL_TREE);
 
       /* Structures with a single member with a distinct mode are passed
         like their member.  This is relevant if the latter has a REAL_TYPE
index 9ba54c1..8212794 100644 (file)
@@ -1285,8 +1285,9 @@ xstormy16_expand_builtin_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
   f_base = TYPE_FIELDS (va_list_type_node);
   f_count = TREE_CHAIN (f_base);
   
-  base = build (COMPONENT_REF, TREE_TYPE (f_base), valist, f_base);
-  count = build (COMPONENT_REF, TREE_TYPE (f_count), valist, f_count);
+  base = build (COMPONENT_REF, TREE_TYPE (f_base), valist, f_base, NULL_TREE);
+  count = build (COMPONENT_REF, TREE_TYPE (f_count), valist, f_count,
+                NULL_TREE);
 
   t = make_tree (TREE_TYPE (base), virtual_incoming_args_rtx);
   t = build (PLUS_EXPR, TREE_TYPE (base), t, 
@@ -1320,8 +1321,9 @@ xstormy16_expand_builtin_va_arg (tree valist, tree type)
   f_base = TYPE_FIELDS (va_list_type_node);
   f_count = TREE_CHAIN (f_base);
   
-  base = build (COMPONENT_REF, TREE_TYPE (f_base), valist, f_base);
-  count = build (COMPONENT_REF, TREE_TYPE (f_count), valist, f_count);
+  base = build (COMPONENT_REF, TREE_TYPE (f_base), valist, f_base, NULL_TREE);
+  count = build (COMPONENT_REF, TREE_TYPE (f_count), valist, f_count,
+                NULL_TREE);
 
   must_stack = MUST_PASS_IN_STACK (TYPE_MODE (type), type);
   size_tree = round_up (size_in_bytes (type), UNITS_PER_WORD);
index e062fd9..2d9ea52 100644 (file)
@@ -2430,9 +2430,9 @@ xtensa_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
   f_reg = TREE_CHAIN (f_stk);
   f_ndx = TREE_CHAIN (f_reg);
 
-  stk = build (COMPONENT_REF, TREE_TYPE (f_stk), valist, f_stk);
-  reg = build (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg);
-  ndx = build (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx);
+  stk = build (COMPONENT_REF, TREE_TYPE (f_stk), valist, f_stk, NULL_TREE);
+  reg = build (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg, NULL_TREE);
+  ndx = build (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx, NULL_TREE);
 
   /* Call __builtin_saveregs; save the result in __va_reg */
   u = make_tree (ptr_type_node, expand_builtin_saveregs ());
@@ -2494,9 +2494,9 @@ xtensa_va_arg (tree valist, tree type)
   f_reg = TREE_CHAIN (f_stk);
   f_ndx = TREE_CHAIN (f_reg);
 
-  stk = build (COMPONENT_REF, TREE_TYPE (f_stk), valist, f_stk);
-  reg = build (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg);
-  ndx = build (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx);
+  stk = build (COMPONENT_REF, TREE_TYPE (f_stk), valist, f_stk, NULL_TREE);
+  reg = build (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg, NULL_TREE);
+  ndx = build (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx, NULL_TREE);
 
   type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type));
 
index 3eab7a5..e39f0a6 100644 (file)
@@ -428,16 +428,18 @@ rtl_coverage_counter_ref (unsigned counter, unsigned no)
 tree
 tree_coverage_counter_ref (unsigned counter, unsigned no)
 {
-  tree t;
+  tree domain_type = TYPE_DOMAIN (TREE_TYPE (tree_ctr_tables[counter]));
 
   if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter])
     abort ();
   no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
 
   /* "no" here is an array index, scaled to bytes later.  */
-  t = build (ARRAY_REF, GCOV_TYPE_NODE, tree_ctr_tables[counter],
-            build_int_2 (no, 0));
-  return t;
+  return build (ARRAY_REF, GCOV_TYPE_NODE, tree_ctr_tables[counter],
+               fold_convert (domain_type, build_int_2 (no, 0)),
+               TYPE_MIN_VALUE (domain_type),
+               size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (GCOV_TYPE_NODE),
+                           size_int (TYPE_ALIGN (GCOV_TYPE_NODE))));
 }
 \f
 /* Generate a checksum for a string.  CHKSUM is the current
index 0291057..d8b494b 100644 (file)
@@ -1,3 +1,29 @@
+2004-06-21  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
+
+       * call.c (build_vfield_ref): Add new operand for COMPONENT_REF.
+       (build_new_method_call): Likewise.
+       * decl.c (local_variable_p_walkfn): Don't walk into types.
+       * decl2.c (grok_array_decl): Add new operands for ARRAY_REF.
+       (build_anon_union_vars): Add new operand for COMPONENT_REF.
+       * init.c (buld_new): Add new operand for ARRAY_REF.
+       * method.c (do_build_copy_constructor): New op for COMPONENT_REF.
+       (do_build_assign_ref): Likewise.
+       * parser.c (cp_parser_direct_new_declarator): Add new operands
+       for ARRAY_REF.
+       (cp_parser_direct_declarator): Likewise.
+       * pt.c (tsubst): Likewise.
+       (tsubst_copy, tsubst_copy_and_build): Likewise; also add new operand
+       for COMPONENT_REF.
+       * semantics.c (finish_non_static_data_member): Add new operand
+       for COMPONENT_REF.
+       * typeck.c (build_class_member_access_expr): Likewise.
+       (build_class_member_access_expr, finish_class_member_access_expr):
+       Likewise.
+       (build_ptrmemfunc_access_expr): Likewise.
+       (build_array_ref): Add new operands for ARRAY_REF.
+       * typeck2.c (split_nonconstant_init_1): Likewise; COMPONENT_REF too.
+       * tree.c (count_trees_r, no_linkage_helper): Don't walk in types.
+
 2004-06-21  Richard Henderson  <rth@redhat.com>
 
        * dump.c (cp_dump_tree): Don't use dump_next_stmt.
index 616cf81..0c247b8 100644 (file)
@@ -203,7 +203,7 @@ build_vfield_ref (tree datum, tree type)
     datum = convert_to_base (datum, type, /*check_access=*/false);
 
   return build (COMPONENT_REF, TREE_TYPE (TYPE_VFIELD (type)),
-               datum, TYPE_VFIELD (type));
+               datum, TYPE_VFIELD (type), NULL_TREE);
 }
 
 /* Returns nonzero iff the destructor name specified in NAME
@@ -3868,8 +3868,7 @@ builtin:
       return build_conditional_expr (arg1, arg2, arg3);
 
     case MEMBER_REF:
-      return build_m_component_ref
-       (build_indirect_ref (arg1, NULL), arg2);
+      return build_m_component_ref (build_indirect_ref (arg1, NULL), arg2);
 
       /* The caller will deal with these.  */
     case ADDR_EXPR:
@@ -5360,7 +5359,7 @@ build_new_method_call (tree instance, tree fns, tree args,
   if (processing_template_decl && call != error_mark_node)
     call = (build_min_non_dep
            (CALL_EXPR, call,
-            build_min_nt (COMPONENT_REF, orig_instance, orig_fns),
+            build_min_nt (COMPONENT_REF, orig_instance, orig_fns, NULL_TREE),
             orig_args, NULL_TREE));
 
  /* Free all the conversions we allocated.  */
index 84f3b84..55ce684 100644 (file)
@@ -8508,14 +8508,18 @@ nonstatic_local_decl_p (tree t)
    function.  */
 
 static tree
-local_variable_p_walkfn (tree* tp,
-                         int* walk_subtrees ATTRIBUTE_UNUSED ,
-                         void* data ATTRIBUTE_UNUSED )
+local_variable_p_walkfn (tree *tp, int *walk_subtrees,
+                        void *data ATTRIBUTE_UNUSED)
 {
-  return ((local_variable_p (*tp) && !DECL_ARTIFICIAL (*tp))
-         ? *tp : NULL_TREE);
+  if (local_variable_p (*tp) && !DECL_ARTIFICIAL (*tp))
+    return *tp;
+  else if (TYPE_P (*tp))
+    *walk_subtrees = 0;
+
+  return NULL_TREE;
 }
 
+
 /* Check that ARG, which is a default-argument expression for a
    parameter DECL, is valid.  Returns ARG, or ERROR_MARK_NODE, if
    something goes wrong.  DECL may also be a _TYPE node, rather than a
index eacab5f..00105a6 100644 (file)
@@ -369,7 +369,8 @@ grok_array_decl (tree array_expr, tree index_exp)
     {
       if (type_dependent_expression_p (array_expr)
          || type_dependent_expression_p (index_exp))
-       return build_min_nt (ARRAY_REF, array_expr, index_exp);
+       return build_min_nt (ARRAY_REF, array_expr, index_exp,
+                            NULL_TREE, NULL_TREE);
       array_expr = build_non_dependent_expr (array_expr);
       index_exp = build_non_dependent_expr (index_exp);
     }
@@ -426,8 +427,8 @@ grok_array_decl (tree array_expr, tree index_exp)
       expr = build_array_ref (array_expr, index_exp);
     }
   if (processing_template_decl && expr != error_mark_node)
-    return build_min_non_dep (ARRAY_REF, expr,
-                             orig_array_expr, orig_index_exp);
+    return build_min_non_dep (ARRAY_REF, expr, orig_array_expr, orig_index_exp,
+                             NULL_TREE, NULL_TREE);
   return expr;
 }
 
@@ -1175,7 +1176,8 @@ build_anon_union_vars (tree object)
        cp_pedwarn_at ("protected member `%#D' in anonymous union", field);
 
       if (processing_template_decl)
-       ref = build_min_nt (COMPONENT_REF, object, DECL_NAME (field));
+       ref = build_min_nt (COMPONENT_REF, object,
+                           DECL_NAME (field), NULL_TREE);
       else
        ref = build_class_member_access_expr (object, field, NULL_TREE,
                                              false);
index 6c88623..2af5118 100644 (file)
@@ -1777,7 +1777,8 @@ build_new (tree placement, tree decl, tree init, int use_global_new)
     {
       if (has_array)
        t = tree_cons (tree_cons (NULL_TREE, type, NULL_TREE),
-                      build_min_nt (ARRAY_REF, NULL_TREE, nelts),
+                      build_min_nt (ARRAY_REF, NULL_TREE, nelts,
+                                    NULL_TREE, NULL_TREE),
                       NULL_TREE);
       else
        t = type;
@@ -1815,7 +1816,7 @@ build_new (tree placement, tree decl, tree init, int use_global_new)
     }
 
   if (has_array)
-    t = build_nt (ARRAY_REF, type, nelts);
+    t = build_nt (ARRAY_REF, type, nelts, NULL_TREE, NULL_TREE);
   else
     t = type;
 
index 357ea86..495244f 100644 (file)
@@ -591,7 +591,7 @@ do_build_copy_constructor (tree fndecl)
          expr_type = TREE_TYPE (field);
          if (TREE_CODE (expr_type) != REFERENCE_TYPE)
            expr_type = cp_build_qualified_type (expr_type, cvquals);
-         init = build (COMPONENT_REF, expr_type, init, field);
+         init = build (COMPONENT_REF, expr_type, init, field, NULL_TREE);
          init = build_tree_list (NULL_TREE, init);
 
          member_init_list
@@ -687,10 +687,11 @@ do_build_assign_ref (tree fndecl)
          else
            continue;
 
-         comp = build (COMPONENT_REF, TREE_TYPE (field), comp, field);
+         comp = build (COMPONENT_REF, TREE_TYPE (field), comp, field,
+                       NULL_TREE);
          init = build (COMPONENT_REF,
                        cp_build_qualified_type (TREE_TYPE (field), cvquals),
-                       init, field);
+                       init, field, NULL_TREE);
 
          if (DECL_NAME (field))
            finish_expr_stmt (build_modify_expr (comp, NOP_EXPR, init));
index bd6abe8..5ad4250 100644 (file)
@@ -4767,7 +4767,8 @@ cp_parser_direct_new_declarator (cp_parser* parser)
       cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
 
       /* Add this bound to the declarator.  */
-      declarator = build_nt (ARRAY_REF, declarator, expression);
+      declarator = build_nt (ARRAY_REF, declarator, expression,
+                            NULL_TREE, NULL_TREE);
 
       /* If the next token is not a `[', then there are no more
         bounds.  */
@@ -10714,7 +10715,8 @@ cp_parser_direct_declarator (cp_parser* parser,
              break;
            }
 
-         declarator = build_nt (ARRAY_REF, declarator, bounds);
+         declarator = build_nt (ARRAY_REF, declarator, bounds,
+                                NULL_TREE, NULL_TREE);
        }
       else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT)
        {
index f8e259c..1e23acb 100644 (file)
@@ -7201,7 +7201,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
        if (e1 == error_mark_node || e2 == error_mark_node)
          return error_mark_node;
 
-       return build_nt (ARRAY_REF, e1, e2);
+       return build_nt (ARRAY_REF, e1, e2, NULL_TREE, NULL_TREE);
       }
 
     case CALL_EXPR:
@@ -7563,7 +7563,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
                                  in_decl);
        else
          name = tsubst_copy (name, args, complain, in_decl);
-       return build_nt (COMPONENT_REF, object, name);
+       return build_nt (COMPONENT_REF, object, name, NULL_TREE);
       }
 
     case PLUS_EXPR:
@@ -8143,7 +8143,7 @@ tsubst_copy_and_build (tree t,
        
        if (object)
          return build (COMPONENT_REF, TREE_TYPE (template), 
-                       object, template);
+                       object, template, NULL_TREE);
        else
          return template;
       }
@@ -8255,7 +8255,8 @@ tsubst_copy_and_build (tree t,
       if (tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl)
          == NULL_TREE)
        /* new-type-id */
-       return build_nt (ARRAY_REF, NULL_TREE, RECUR (TREE_OPERAND (t, 1)));
+       return build_nt (ARRAY_REF, NULL_TREE, RECUR (TREE_OPERAND (t, 1)),
+                        NULL_TREE, NULL_TREE);
 
       op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
                                                args, complain, in_decl);
index 0da9494..9e4b884 100644 (file)
@@ -1233,7 +1233,7 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
          type = cp_build_qualified_type (type, quals);
        }
       
-      return build_min (COMPONENT_REF, type, object, decl);
+      return build_min (COMPONENT_REF, type, object, decl, NULL_TREE);
     }
   else
     {
index 6b55880..527e9c2 100644 (file)
@@ -1026,11 +1026,13 @@ bind_template_template_parm (tree t, tree newargs)
 /* Called from count_trees via walk_tree.  */
 
 static tree
-count_trees_r (tree* tp ATTRIBUTE_UNUSED , 
-               int* walk_subtrees ATTRIBUTE_UNUSED , 
-               void* data)
+count_trees_r (tree *tp, int *walk_subtrees, void *data)
 {
-  ++ *((int*) data);
+  ++*((int *) data);
+
+  if (TYPE_P (*tp))
+    *walk_subtrees = 0;
+
   return NULL_TREE;
 }
 
@@ -1107,9 +1109,8 @@ find_tree (tree t, tree x)
 /* Passed to walk_tree.  Checks for the use of types with no linkage.  */
 
 static tree
-no_linkage_helper (tree* tp, 
-                   int* walk_subtrees ATTRIBUTE_UNUSED , 
-                   void* data ATTRIBUTE_UNUSED )
+no_linkage_helper (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
+                  void *data ATTRIBUTE_UNUSED)
 {
   tree t = *tp;
 
@@ -1118,6 +1119,7 @@ no_linkage_helper (tree* tp,
       && (decl_function_context (TYPE_MAIN_DECL (t))
          || TYPE_ANONYMOUS_P (t)))
     return t;
+
   return NULL_TREE;
 }
 
index bdf7377..8800007 100644 (file)
@@ -1752,7 +1752,8 @@ build_class_member_access_expr (tree object, tree member,
          member_type = cp_build_qualified_type (member_type, type_quals);
        }
 
-      result = fold (build (COMPONENT_REF, member_type, object, member));
+      result = fold (build (COMPONENT_REF, member_type, object, member,
+                           NULL_TREE));
 
       /* Mark the expression const or volatile, as appropriate.  Even
         though we've dealt with the type above, we still have to mark the
@@ -1779,7 +1780,7 @@ build_class_member_access_expr (tree object, tree member,
        type = unknown_type_node;
       /* Note that we do not convert OBJECT to the BASELINK_BINFO
         base.  That will happen when the function is called.  */
-      result = build (COMPONENT_REF, type, object, member);
+      result = build (COMPONENT_REF, type, object, member, NULL_TREE);
     }
   else if (TREE_CODE (member) == CONST_DECL)
     {
@@ -1878,7 +1879,7 @@ finish_class_member_access_expr (tree object, tree name)
          || (TREE_CODE (name) == SCOPE_REF
              && TYPE_P (TREE_OPERAND (name, 0))
              && dependent_type_p (TREE_OPERAND (name, 0))))
-       return build_min_nt (COMPONENT_REF, object, name);
+       return build_min_nt (COMPONENT_REF, object, name, NULL_TREE);
       object = build_non_dependent_expr (object);
     }
   
@@ -2005,7 +2006,7 @@ finish_class_member_access_expr (tree object, tree name)
                                         /*preserve_reference=*/false);
   if (processing_template_decl && expr != error_mark_node)
     return build_min_non_dep (COMPONENT_REF, expr,
-                             orig_object, orig_name);
+                             orig_object, orig_name, NULL_TREE);
   return expr;
 }
 
@@ -2033,7 +2034,7 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
                          /*want_type=*/false);
   member_type = cp_build_qualified_type (TREE_TYPE (member),
                                         cp_type_quals (ptrmem_type));
-  return fold (build (COMPONENT_REF, member_type, ptrmem, member));
+  return fold (build (COMPONENT_REF, member_type, ptrmem, member, NULL_TREE));
 }
 
 /* Given an expression PTR for a pointer, return an expression
@@ -2249,7 +2250,7 @@ build_array_ref (tree array, tree idx)
        }
 
       type = TREE_TYPE (TREE_TYPE (array));
-      rval = build (ARRAY_REF, type, array, idx);
+      rval = build (ARRAY_REF, type, array, idx, NULL_TREE, NULL_TREE);
       /* Array ref is const/volatile if the array elements are
         or if the array is..  */
       TREE_READONLY (rval)
index 9ea4f55..2e08d56 100644 (file)
@@ -320,9 +320,11 @@ split_nonconstant_init_1 (tree dest, tree init)
          if (TREE_CODE (value) == CONSTRUCTOR)
            {
              if (array_type_p)
-               sub = build (ARRAY_REF, inner_type, dest, field_index);
+               sub = build (ARRAY_REF, inner_type, dest, field_index,
+                            NULL_TREE, NULL_TREE);
              else
-               sub = build (COMPONENT_REF, inner_type, dest, field_index);
+               sub = build (COMPONENT_REF, inner_type, dest, field_index,
+                            NULL_TREE);
 
              split_nonconstant_init_1 (sub, value);
            }
@@ -331,9 +333,11 @@ split_nonconstant_init_1 (tree dest, tree init)
              *pelt = TREE_CHAIN (elt);
 
              if (array_type_p)
-               sub = build (ARRAY_REF, inner_type, dest, field_index);
+               sub = build (ARRAY_REF, inner_type, dest, field_index,
+                            NULL_TREE, NULL_TREE);
              else
-               sub = build (COMPONENT_REF, inner_type, dest, field_index);
+               sub = build (COMPONENT_REF, inner_type, dest, field_index,
+                            NULL_TREE);
 
              code = build (MODIFY_EXPR, inner_type, sub, value);
              code = build_stmt (EXPR_STMT, code);
index 4167915..984f81f 100644 (file)
@@ -1460,8 +1460,8 @@ component_ref_for_mem_expr (tree ref)
   if (inner == TREE_OPERAND (ref, 0))
     return ref;
   else
-    return build (COMPONENT_REF, TREE_TYPE (ref), inner,
-                 TREE_OPERAND (ref, 1));
+    return build (COMPONENT_REF, TREE_TYPE (ref), inner, TREE_OPERAND (ref, 1),
+                 NULL_TREE);
 }
 
 /* Returns 1 if both MEM_EXPR can be considered equal
@@ -1625,28 +1625,22 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
          do
            {
              tree index = TREE_OPERAND (t2, 1);
-             tree array = TREE_OPERAND (t2, 0);
-             tree domain = TYPE_DOMAIN (TREE_TYPE (array));
-             tree low_bound = (domain ? TYPE_MIN_VALUE (domain) : 0);
-             tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (array)));
+             tree low_bound = array_ref_low_bound (t2);
+             tree unit_size = array_ref_element_size (t2);
 
              /* We assume all arrays have sizes that are a multiple of a byte.
                 First subtract the lower bound, if any, in the type of the
-                index, then convert to sizetype and multiply by the size of the
-                array element.  */
-             if (low_bound != 0 && ! integer_zerop (low_bound))
+                index, then convert to sizetype and multiply by the size of
+                the array element.  */
+             if (! integer_zerop (low_bound))
                index = fold (build (MINUS_EXPR, TREE_TYPE (index),
                                     index, low_bound));
 
-             /* If the index has a self-referential type, instantiate it;
-                likewise for the component size.  */
-             index = SUBSTITUTE_PLACEHOLDER_IN_EXPR (index, t2);
-             unit_size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (unit_size, array);
-             off_tree
-               = fold (build (PLUS_EXPR, sizetype,
-                              fold (build (MULT_EXPR, sizetype,
-                                           index, unit_size)),
-                              off_tree));
+             off_tree = size_binop (PLUS_EXPR,
+                                    size_binop (MULT_EXPR, convert (sizetype,
+                                                                    index),
+                                                unit_size),
+                                    off_tree);
              t2 = TREE_OPERAND (t2, 0);
            }
          while (TREE_CODE (t2) == ARRAY_REF);
@@ -2042,6 +2036,7 @@ widen_memory_access (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset)
       if (TREE_CODE (expr) == COMPONENT_REF)
        {
          tree field = TREE_OPERAND (expr, 1);
+         tree offset = component_ref_field_offset (expr);
 
          if (! DECL_SIZE_UNIT (field))
            {
@@ -2056,17 +2051,18 @@ widen_memory_access (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset)
              && INTVAL (memoffset) >= 0)
            break;
 
-         if (! host_integerp (DECL_FIELD_OFFSET (field), 1))
+         if (! host_integerp (offset, 1))
            {
              expr = NULL_TREE;
              break;
            }
 
          expr = TREE_OPERAND (expr, 0);
-         memoffset = (GEN_INT (INTVAL (memoffset)
-                      + tree_low_cst (DECL_FIELD_OFFSET (field), 1)
-                      + (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
-                         / BITS_PER_UNIT)));
+         memoffset
+           = (GEN_INT (INTVAL (memoffset)
+                       + tree_low_cst (offset, 1)
+                       + (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
+                          / BITS_PER_UNIT)));
        }
       /* Similarly for the decl.  */
       else if (DECL_P (expr)
index af67003..672d3f6 100644 (file)
@@ -1100,7 +1100,7 @@ update_nonlocal_goto_save_area (void)
      STACK_SAVEAREA_MODE.  Create a reference to array index 1, the first
      of the stack save area slots.  */
   t_save = build (ARRAY_REF, ptr_type_node, cfun->nonlocal_goto_save_area,
-                 integer_one_node);
+                 integer_one_node, NULL_TREE, NULL_TREE);
   r_save = expand_expr (t_save, NULL_RTX, VOIDmode, EXPAND_WRITE);
 
   emit_stack_save (SAVE_NONLOCAL, &r_save, NULL_RTX);
index aad7b1c..989a5fa 100644 (file)
@@ -5591,15 +5591,13 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
       else if (TREE_CODE (exp) == COMPONENT_REF)
        {
          tree field = TREE_OPERAND (exp, 1);
-         tree this_offset = DECL_FIELD_OFFSET (field);
+         tree this_offset = component_ref_field_offset (exp);
 
          /* If this field hasn't been filled in yet, don't go
             past it.  This should only happen when folding expressions
             made during type construction.  */
          if (this_offset == 0)
            break;
-         else
-           this_offset = SUBSTITUTE_PLACEHOLDER_IN_EXPR (this_offset, exp);
 
          offset = size_binop (PLUS_EXPR, offset, this_offset);
          bit_offset = size_binop (PLUS_EXPR, bit_offset,
@@ -5612,23 +5610,17 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
               || TREE_CODE (exp) == ARRAY_RANGE_REF)
        {
          tree index = TREE_OPERAND (exp, 1);
-         tree array = TREE_OPERAND (exp, 0);
-         tree domain = TYPE_DOMAIN (TREE_TYPE (array));
-         tree low_bound = (domain ? TYPE_MIN_VALUE (domain) : 0);
-         tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (array)));
+         tree low_bound = array_ref_low_bound (exp);
+         tree unit_size = array_ref_element_size (exp);
 
          /* We assume all arrays have sizes that are a multiple of a byte.
             First subtract the lower bound, if any, in the type of the
             index, then convert to sizetype and multiply by the size of the
             array element.  */
-         if (low_bound != 0 && ! integer_zerop (low_bound))
+         if (! integer_zerop (low_bound))
            index = fold (build (MINUS_EXPR, TREE_TYPE (index),
                                 index, low_bound));
 
-         /* If the index has a self-referential type, instantiate it with
-            the object; likewise for the component size.  */
-         index = SUBSTITUTE_PLACEHOLDER_IN_EXPR (index, exp);
-         unit_size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (unit_size, array);
          offset = size_binop (PLUS_EXPR, offset,
                               size_binop (MULT_EXPR,
                                           convert (sizetype, index),
@@ -5676,6 +5668,70 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
   return exp;
 }
 
+/* Return a tree of sizetype representing the size, in bytes, of the element
+   of EXP, an ARRAY_REF.  */
+
+tree
+array_ref_element_size (tree exp)
+{
+  tree aligned_size = TREE_OPERAND (exp, 3);
+  tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0)));
+
+  /* If a size was specified in the ARRAY_REF, it's the size measured
+     in alignment units of the element type.  So multiply by that value.  */
+  if (aligned_size)
+    return size_binop (MULT_EXPR, aligned_size,
+                      size_int (TYPE_ALIGN (elmt_type) / BITS_PER_UNIT));
+
+  /* Otherwise, take the size from that of the element type.  Substitute 
+     any PLACEHOLDER_EXPR that we have.  */
+  else
+    return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_SIZE_UNIT (elmt_type), exp);
+}
+
+/* Return a tree representing the lower bound of the array mentioned in
+   EXP, an ARRAY_REF.  */
+
+tree
+array_ref_low_bound (tree exp)
+{
+  tree domain_type = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
+
+  /* If a lower bound is specified in EXP, use it.  */
+  if (TREE_OPERAND (exp, 2))
+    return TREE_OPERAND (exp, 2);
+
+  /* Otherwise, if there is a domain type and it has a lower bound, use it,
+     substituting for a PLACEHOLDER_EXPR as needed.  */
+  if (domain_type && TYPE_MIN_VALUE (domain_type))
+    return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_MIN_VALUE (domain_type), exp);
+
+  /* Otherwise, return a zero of the appropriate type.  */
+  return fold_convert (TREE_TYPE (TREE_OPERAND (exp, 1)), integer_zero_node);
+}
+
+/* Return a tree representing the offset, in bytes, of the field referenced
+   by EXP.  This does not include any offset in DECL_FIELD_BIT_OFFSET.  */
+
+tree
+component_ref_field_offset (tree exp)
+{
+  tree aligned_offset = TREE_OPERAND (exp, 2);
+  tree field = TREE_OPERAND (exp, 1);
+
+  /* If an offset was specified in the COMPONENT_REF, it's the offset measured
+     in units of DECL_OFFSET_ALIGN / BITS_PER_UNIT.  So multiply by that
+     value.  */
+  if (aligned_offset)
+    return size_binop (MULT_EXPR, aligned_offset,
+                      size_int (DECL_OFFSET_ALIGN (field) / BITS_PER_UNIT));
+
+  /* Otherwise, take the offset from that of the field.  Substitute 
+     any PLACEHOLDER_EXPR that we have.  */
+  else
+    return SUBSTITUTE_PLACEHOLDER_IN_EXPR (DECL_FIELD_OFFSET (field), exp);
+}
+
 /* Return 1 if T is an expression that get_inner_reference handles.  */
 
 int
@@ -7001,8 +7057,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 
       {
        tree array = TREE_OPERAND (exp, 0);
-       tree domain = TYPE_DOMAIN (TREE_TYPE (array));
-       tree low_bound = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node;
+       tree low_bound = array_ref_low_bound (exp);
        tree index = convert (sizetype, TREE_OPERAND (exp, 1));
        HOST_WIDE_INT i;
 
index 68c9722..3d4ccca 100644 (file)
@@ -2019,9 +2019,9 @@ non_lvalue (tree x)
   case COMPONENT_REF:
   case INDIRECT_REF:
   case ARRAY_REF:
+  case ARRAY_RANGE_REF:
   case BIT_FIELD_REF:
   case BUFFER_REF:
-  case ARRAY_RANGE_REF:
   case VTABLE_REF:
 
   case REALPART_EXPR:
@@ -7901,24 +7901,26 @@ fold (tree expr)
          /* If VAROP is a reference to a bitfield, we must mask
             the constant by the width of the field.  */
          if (TREE_CODE (TREE_OPERAND (varop, 0)) == COMPONENT_REF
-             && DECL_BIT_FIELD (TREE_OPERAND (TREE_OPERAND (varop, 0), 1)))
+             && DECL_BIT_FIELD (TREE_OPERAND (TREE_OPERAND (varop, 0), 1))
+             && host_integerp (DECL_SIZE (TREE_OPERAND
+                                          (TREE_OPERAND (varop, 0), 1)), 1))
            {
              tree fielddecl = TREE_OPERAND (TREE_OPERAND (varop, 0), 1);
-             int size = TREE_INT_CST_LOW (DECL_SIZE (fielddecl));
+             HOST_WIDE_INT size = tree_low_cst (DECL_SIZE (fielddecl), 1);
              tree folded_compare, shift;
 
              /* First check whether the comparison would come out
                 always the same.  If we don't do that we would
                 change the meaning with the masking.  */
              folded_compare = fold (build2 (code, type,
-                                            TREE_OPERAND (varop, 0),
-                                            arg1));
+                                            TREE_OPERAND (varop, 0), arg1));
              if (integer_zerop (folded_compare)
                  || integer_onep (folded_compare))
                return omit_one_operand (type, folded_compare, varop);
 
              shift = build_int_2 (TYPE_PRECISION (TREE_TYPE (varop)) - size,
                                   0);
+             shift = fold_convert (TREE_TYPE (varop), shift);
              newconst = fold (build2 (LSHIFT_EXPR, TREE_TYPE (varop),
                                       newconst, shift));
              newconst = fold (build2 (RSHIFT_EXPR, TREE_TYPE (varop),
@@ -10106,13 +10108,10 @@ fold_read_from_constant_string (tree exp)
       tree string;
 
       if (TREE_CODE (exp) == INDIRECT_REF)
-       {
-         string = string_constant (exp1, &index);
-       }
+       string = string_constant (exp1, &index);
       else
        {
-         tree domain = TYPE_DOMAIN (TREE_TYPE (exp1));
-         tree low_bound = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node;
+         tree low_bound = array_ref_low_bound (exp);
          index = fold_convert (sizetype, TREE_OPERAND (exp, 1));
          
          /* Optimize the special-case of a zero lower bound.
@@ -10129,6 +10128,7 @@ fold_read_from_constant_string (tree exp)
        }
 
       if (string
+         && TREE_TYPE (exp) == TREE_TYPE (TREE_TYPE (string))
          && TREE_CODE (string) == STRING_CST
          && TREE_CODE (index) == INTEGER_CST
          && compare_tree_int (index, TREE_STRING_LENGTH (string)) < 0
@@ -10456,7 +10456,7 @@ build_fold_indirect_ref (tree t)
       /* *(foo *)&fooarray => fooarray[0] */
       else if (TREE_CODE (optype) == ARRAY_TYPE
               && lang_hooks.types_compatible_p (type, TREE_TYPE (optype)))
-       return build2 (ARRAY_REF, type, op, size_zero_node);
+       return build4 (ARRAY_REF, type, op, size_zero_node, NULL_TREE, NULL_TREE);
     }
 
   /* *(foo *)fooarrptr => (*fooarrptr)[0] */
@@ -10465,7 +10465,7 @@ build_fold_indirect_ref (tree t)
       && lang_hooks.types_compatible_p (type, TREE_TYPE (TREE_TYPE (subtype))))
     {
       sub = build_fold_indirect_ref (sub);
-      return build2 (ARRAY_REF, type, sub, size_zero_node);
+      return build4 (ARRAY_REF, type, sub, size_zero_node, NULL_TREE, NULL_TREE);
     }
 
   return build1 (INDIRECT_REF, type, t);
index 0114728..a2bb02c 100644 (file)
@@ -1,3 +1,22 @@
+2004-06-21  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
+
+       * f95-lang.c (LANG_HOOKS_GIMPLE_BEFORE_INLINING): Deleted.
+       * trans-array.c (gfc_conv_descriptor_data): Add operand
+       for COMPONENT_REF.
+       (gfc_conv_descriptor_offset, gfc_conv_descriptor_dtype): Likewise.
+       (gfc_conv_descriptor_dimension, gfc_conv_descriptor_stride): Likewise.
+       (gfc_conv_descriptor_lbound, gfc_conv_descriptor_ubound): Likewise.
+       * trans-common.c (create_common): Likewise.
+       * trans-expr.c (gfc_conv_component_ref): Likewise.
+       * trans-io.c (set_parameter_value): Likewise.
+       (set_parameter_ref, set_string, set_flag, io_result): Likewise.
+       (transfer_expr): Likewise.
+       * trans-decl.c (gfc_trans_auto_character_variable):
+       Set up to get DECL_SIZE and DECL_SIZE_UNIT gimplified.
+       (gfc_simplify_function): New function.
+       (gfc_generate_function-code): Properly handle nested functions.
+       * trans.c (gfc_build_array_ref): Add two new operands for ARRAY_REF.
+
 2004-06-22  Janne Blomqvist  <jblomqvi@cc.hut.fi>
 
        PR fortran/15750
index ab151fc..fd4fe5c 100644 (file)
@@ -122,7 +122,6 @@ static void gfc_expand_function (tree);
 #undef LANG_HOOKS_UNSIGNED_TYPE
 #undef LANG_HOOKS_SIGNED_TYPE
 #undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE
-#undef LANG_HOOKS_GIMPLE_BEFORE_INLINING
 #undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION
 
 /* Define lang hooks.  */
@@ -141,7 +140,6 @@ static void gfc_expand_function (tree);
 #define LANG_HOOKS_UNSIGNED_TYPE           gfc_unsigned_type
 #define LANG_HOOKS_SIGNED_TYPE             gfc_signed_type
 #define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE gfc_signed_or_unsigned_type
-#define LANG_HOOKS_GIMPLE_BEFORE_INLINING false
 #define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION gfc_expand_function
 
 const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
index e83a45d..bccaf41 100644 (file)
@@ -189,7 +189,7 @@ gfc_conv_descriptor_data (tree desc)
          && TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
          && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == ARRAY_TYPE);
 
-  return build (COMPONENT_REF, TREE_TYPE (field), desc, field);
+  return build (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
 }
 
 tree
@@ -204,7 +204,7 @@ gfc_conv_descriptor_offset (tree desc)
   field = gfc_advance_chain (TYPE_FIELDS (type), OFFSET_FIELD);
   assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
 
-  return build (COMPONENT_REF, TREE_TYPE (field), desc, field);
+  return build (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
 }
 
 tree
@@ -219,7 +219,7 @@ gfc_conv_descriptor_dtype (tree desc)
   field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
   assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
 
-  return build (COMPONENT_REF, TREE_TYPE (field), desc, field);
+  return build (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
 }
 
 static tree
@@ -237,7 +237,7 @@ gfc_conv_descriptor_dimension (tree desc, tree dim)
          && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
          && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
 
-  tmp = build (COMPONENT_REF, TREE_TYPE (field), desc, field);
+  tmp = build (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
   tmp = gfc_build_array_ref (tmp, dim);
   return tmp;
 }
@@ -253,7 +253,7 @@ gfc_conv_descriptor_stride (tree desc, tree dim)
   field = gfc_advance_chain (field, STRIDE_SUBFIELD);
   assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
 
-  tmp = build (COMPONENT_REF, TREE_TYPE (field), tmp, field);
+  tmp = build (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE);
   return tmp;
 }
 
@@ -268,7 +268,7 @@ gfc_conv_descriptor_lbound (tree desc, tree dim)
   field = gfc_advance_chain (field, LBOUND_SUBFIELD);
   assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
 
-  tmp = build (COMPONENT_REF, TREE_TYPE (field), tmp, field);
+  tmp = build (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE);
   return tmp;
 }
 
@@ -283,7 +283,7 @@ gfc_conv_descriptor_ubound (tree desc, tree dim)
   field = gfc_advance_chain (field, UBOUND_SUBFIELD);
   assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
 
-  tmp = build (COMPONENT_REF, TREE_TYPE (field), tmp, field);
+  tmp = build (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE);
   return tmp;
 }
 
index 667038d..f0c385a 100644 (file)
@@ -425,7 +425,7 @@ create_common (gfc_symbol *sym)
   for (h = current_common; h; h = next_s)
     {
       h->sym->backend_decl = build (COMPONENT_REF, TREE_TYPE (h->field),
-                                    decl, h->field);
+                                    decl, h->field, NULL_TREE);
 
       next_s = h->next;
       gfc_free (h);
index ecabfc4..8cf6cbb 100644 (file)
@@ -1645,6 +1645,14 @@ gfc_trans_auto_character_variable (gfc_symbol * sym, tree fnbody)
 
   DECL_DEFER_OUTPUT (decl) = 1;
 
+  /* Since we don't use a DECL_STMT or equivalent, we have to deal
+     with getting these gimplified.  But we can't gimplify it yet since
+     we're still generating statements.
+
+     ??? This should be cleaned up and handled like other front ends.  */
+  gfc_add_expr_to_block (&body, save_expr (DECL_SIZE (decl)));
+  gfc_add_expr_to_block (&body, save_expr (DECL_SIZE_UNIT (decl)));
+
   /* Generate code to allocate the automatic variable.  It will be freed
      automatically.  */
   tmp = gfc_build_addr_expr (NULL, decl);
@@ -1949,6 +1957,24 @@ gfc_finalize (tree decl)
   cgraph_finalize_function (decl, false);
 }
 
+/* Convert FNDECL's code to GIMPLE and handle any nested functions.  */
+
+static void
+gfc_gimplify_function (tree fndecl)
+{
+  struct cgraph_node *cgn;
+
+  gimplify_function_tree (fndecl);
+  dump_function (TDI_generic, fndecl);
+
+  /* Convert all nested functions to GIMPLE now.  We do things in this order
+     so that items like VLA sizes are expanded properly in the context of the
+     correct function.  */
+  cgn = cgraph_node (fndecl);
+  for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
+    gfc_gimplify_function (cgn->decl);
+}
+
 /* Generate code for a function.  */
 
 void
@@ -2120,26 +2146,17 @@ gfc_generate_function_code (gfc_namespace * ns)
   current_function_decl = old_context;
 
   if (decl_function_context (fndecl))
-    {
-      /* Register this function with cgraph just far enough to get it
-        added to our parent's nested function list.  */
-      (void) cgraph_node (fndecl);
-
-      /* Lowering nested functions requires gimple input.  */
-      gimplify_function_tree (fndecl);
-    }
+    /* Register this function with cgraph just far enough to get it
+       added to our parent's nested function list.  */
+    (void) cgraph_node (fndecl);
   else
     {
-      if (cgraph_node (fndecl)->nested)
-       {
-         gimplify_function_tree (fndecl);
-          lower_nested_functions (fndecl);
-       }
+      gfc_gimplify_function (fndecl);
+      lower_nested_functions (fndecl);
       gfc_finalize (fndecl);
     }
 }
 
-
 void
 gfc_generate_constructors (void)
 {
index e4953f6..717a5d8 100644 (file)
@@ -221,7 +221,7 @@ gfc_conv_component_ref (gfc_se * se, gfc_ref * ref)
   field = c->backend_decl;
   assert (TREE_CODE (field) == FIELD_DECL);
   decl = se->expr;
-  tmp = build (COMPONENT_REF, TREE_TYPE (field), decl, field);
+  tmp = build (COMPONENT_REF, TREE_TYPE (field), decl, field, NULL_TREE);
 
   se->expr = tmp;
 
index 3f4076f..f3aa37d 100644 (file)
@@ -359,7 +359,7 @@ set_parameter_value (stmtblock_t * block, tree var, gfc_expr * e)
   gfc_conv_expr_type (&se, e, TREE_TYPE (var));
   gfc_add_block_to_block (block, &se.pre);
 
-  tmp = build (COMPONENT_REF, TREE_TYPE (var), ioparm_var, var);
+  tmp = build (COMPONENT_REF, TREE_TYPE (var), ioparm_var, var, NULL_TREE);
   gfc_add_modify_expr (block, tmp, se.expr);
 }
 
@@ -379,7 +379,7 @@ set_parameter_ref (stmtblock_t * block, tree var, gfc_expr * e)
   gfc_conv_expr_type (&se, e, TREE_TYPE (var));
   gfc_add_block_to_block (block, &se.pre);
 
-  tmp = build (COMPONENT_REF, TREE_TYPE (var), ioparm_var, var);
+  tmp = build (COMPONENT_REF, TREE_TYPE (var), ioparm_var, var, NULL_TREE);
   gfc_add_modify_expr (block, tmp, se.expr);
 }
 
@@ -400,8 +400,9 @@ set_string (stmtblock_t * block, stmtblock_t * postblock, tree var,
   gfc_init_se (&se, NULL);
   gfc_conv_expr (&se, e);
 
-  io = build (COMPONENT_REF, TREE_TYPE (var), ioparm_var, var);
-  len = build (COMPONENT_REF, TREE_TYPE (var_len), ioparm_var, var_len);
+  io = build (COMPONENT_REF, TREE_TYPE (var), ioparm_var, var, NULL_TREE);
+  len = build (COMPONENT_REF, TREE_TYPE (var_len), ioparm_var, var_len,
+              NULL_TREE);
 
   /*  Integer variable assigned a format label.  */
   if (e->ts.type == BT_INTEGER && e->symtree->n.sym->attr.assign == 1)
@@ -433,7 +434,7 @@ set_flag (stmtblock_t *block, tree var)
 {
   tree tmp;
 
-  tmp = build (COMPONENT_REF, TREE_TYPE(var), ioparm_var, var);
+  tmp = build (COMPONENT_REF, TREE_TYPE(var), ioparm_var, var, NULL_TREE);
   gfc_add_modify_expr (block, tmp, integer_one_node);
 }
 
@@ -496,7 +497,7 @@ io_result (stmtblock_t * block, gfc_st_label * err_label,
   tmp = gfc_finish_block (&body);
 
   rc = build (COMPONENT_REF, TREE_TYPE (ioparm_library_return), ioparm_var,
-             ioparm_library_return);
+             ioparm_library_return, NULL_TREE);
 
   tmp = build_v (SWITCH_EXPR, rc, tmp, NULL_TREE);
 
@@ -1127,7 +1128,8 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr)
          field = c->backend_decl;
          assert (field && TREE_CODE (field) == FIELD_DECL);
 
-         tmp = build (COMPONENT_REF, TREE_TYPE (field), expr, field);
+         tmp = build (COMPONENT_REF, TREE_TYPE (field), expr, field,
+                      NULL_TREE);
 
          if (c->ts.type == BT_CHARACTER)
            {
index bb994a7..2927728 100644 (file)
@@ -306,7 +306,7 @@ gfc_build_array_ref (tree base, tree offset)
   if (DECL_P (base))
     TREE_ADDRESSABLE (base) = 1;
 
-  return build (ARRAY_REF, type, base, offset);
+  return build (ARRAY_REF, type, base, offset, NULL_TREE, NULL_TREE);
 }
 
 
index 3f1f45b..8fd0a6f 100644 (file)
@@ -6544,7 +6544,7 @@ expand_function_start (tree subr, int parms_have_cleanups)
       expand_var (TREE_OPERAND (cfun->nonlocal_goto_save_area, 0));
 
       t_save = build (ARRAY_REF, ptr_type_node, cfun->nonlocal_goto_save_area,
-                     integer_zero_node);
+                     integer_zero_node, NULL_TREE, NULL_TREE);
       r_save = expand_expr (t_save, NULL_RTX, VOIDmode, EXPAND_WRITE);
 
       emit_move_insn (r_save, virtual_stack_vars_rtx);
index 98346cc..32e5cee 100644 (file)
@@ -476,8 +476,6 @@ expand_var_p (tree var)
   if (TREE_CODE (var) != VAR_DECL)
     return true;
 
-  ann = var_ann (var);
-
   /* Remove all unused, unaliased temporaries.  Also remove unused, unaliased
      local variables during highly optimizing compilations.  */
   ann = var_ann (var);
index f6e4a04..3649272 100644 (file)
@@ -1,6 +1,5 @@
 /* Tree lowering pass.  This pass converts the GENERIC functions-as-trees
    tree representation into the GIMPLE form.
-
    Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
    Major work done by Sebastian Pop <s.pop@laposte.net>,
    Diego Novillo <dnovillo@redhat.com> and Jason Merrill <jason@redhat.com>.
@@ -36,6 +35,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "langhooks.h"
 #include "langhooks-def.h"
 #include "tree-flow.h"
+#include "cgraph.h"
 #include "timevar.h"
 #include "except.h"
 #include "hashtab.h"
@@ -71,6 +71,73 @@ typedef struct gimple_temp_hash_elt
   tree temp;  /* Value */
 } elt_t;
 
+/* Forward declarations.  */
+static hashval_t gimple_tree_hash (const void *);
+static int gimple_tree_eq (const void *, const void *);
+static bool gimple_conditional_context (void);
+static void gimple_push_condition (void);
+static void gimple_pop_condition (tree *);
+static void append_to_statement_list_1 (tree, tree *, bool);
+static inline void remove_suffix (char *, int);
+static inline tree create_tmp_from_val (tree);
+static tree lookup_tmp_var (tree, bool);
+static tree internal_get_tmp_var (tree, tree *, tree *, bool);
+static bool should_carry_locus_p (tree);
+static tree mostly_copy_tree_r (tree *, int *, void *);
+static tree mark_decls_volatile_r (tree *, int *, void *);
+static tree copy_if_shared_r (tree *, int *, void *);
+static tree unmark_visited_r (tree *, int *, void *);
+static void unshare_body (tree *, tree);
+static void unvisit_body (tree *, tree);
+static void build_stack_save_restore (tree *, tree *);
+static enum gimplify_status gimplify_bind_expr (tree *, tree, tree *);
+static enum gimplify_status gimplify_return_expr (tree, tree *);
+static enum gimplify_status gimplify_loop_expr (tree *, tree *);
+static int compare_case_labels (const void *, const void *);
+static enum gimplify_status gimplify_switch_expr (tree *, tree *);
+static enum gimplify_status gimplify_case_label_expr (tree *);
+static enum gimplify_status gimplify_labeled_block_expr (tree *);
+static enum gimplify_status gimplify_exit_block_expr (tree *);
+static enum gimplify_status gimplify_exit_expr (tree *);
+static enum gimplify_status gimplify_init_constructor (tree *, tree *, tree *,
+                                                      bool);
+static void canonicalize_component_ref (tree *);
+static void canonicalize_addr_expr (tree *);
+static enum gimplify_status gimplify_conversion (tree *);
+static enum gimplify_status gimplify_minimax_expr (tree *, tree *, tree *);
+static enum gimplify_status gimplify_array_ref_to_plus (tree *, tree *,
+                                                       tree *);
+static tree build_addr_expr_with_type (tree, tree);
+static tree build_addr_expr (tree);
+static enum gimplify_status gimplify_compound_lval (tree *, tree *, tree *,
+                                                   bool);
+static enum gimplify_status gimplify_self_mod_expr (tree *, tree *, tree *,
+                                                   bool);
+static enum gimplify_status gimplify_call_expr (tree *, tree *,
+                                               bool (*) (tree));
+static tree shortcut_cond_r (tree, tree *, tree *);
+static tree shortcut_cond_expr (tree);
+static tree gimple_boolify (tree);
+static enum gimplify_status gimplify_cond_expr (tree *, tree *, tree);
+static enum gimplify_status gimplify_modify_expr (tree *, tree *, tree *,
+                                                 bool);
+static enum gimplify_status gimplify_modify_expr_rhs (tree *, tree *, tree *,
+                                                     tree *, tree *, bool);
+static enum gimplify_status gimplify_variable_sized_compare (tree *);
+static enum gimplify_status gimplify_boolean_expr (tree *);
+static enum gimplify_status gimplify_compound_expr (tree *, tree *, bool);
+static enum gimplify_status gimplify_statement_list (tree *);
+static enum gimplify_status gimplify_save_expr (tree *, tree *, tree *);
+static enum gimplify_status gimplify_addr_expr (tree *, tree *, tree *);
+static enum gimplify_status gimplify_asm_expr (tree *, tree *, tree *);
+static enum gimplify_status gimplify_cleanup_point_expr (tree *, tree *);
+static void gimple_push_cleanup (tree, tree, tree *);
+static enum gimplify_status gimplify_target_expr (tree *, tree *, tree *);
+#ifdef ENABLE_CHECKING
+static bool cpt_same_type (tree, tree);
+static tree check_pointer_types_r (tree *, int *, void *);
+#endif
+
 /* Return a hash value for a formal temporary table entry.  */
 
 static hashval_t
@@ -355,15 +422,11 @@ create_tmp_var (tree type, const char *prefix)
   tree tmp_var;
 
 #if defined ENABLE_CHECKING
-  /* If the type is an array or a type which must be created by the
-     frontend, something is wrong.  */
-  if (TREE_CODE (type) == ARRAY_TYPE || TREE_ADDRESSABLE (type))
-    abort ();
-  if (!COMPLETE_TYPE_P (type))
-    abort ();
-  /* Variable sized types require lots of machinery to create; the
-     optimizers shouldn't be doing anything of the sort.  */
-  if (TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST)
+  /* We don't allow types that are addressable (meaning we can't make copies),
+     incomplete, or of variable size.  */
+  if (TREE_ADDRESSABLE (type)
+      || !COMPLETE_TYPE_P (type)
+      || TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST)
     abort ();
 #endif
 
@@ -653,11 +716,19 @@ copy_if_shared_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
   tree t = *tp;
   enum tree_code code = TREE_CODE (t);
 
-  /* Skip types, decls, and constants.  */
+  /* Skip types, decls, and constants.  But we do want to look at their
+     types and the bounds of types.  Mark them as visited so we properly
+     unmark their subtrees on the unmark pass.  If we've already seen them,
+     don't look down further.  */
   if (TREE_CODE_CLASS (code) == 't'
       || TREE_CODE_CLASS (code) == 'd'
       || TREE_CODE_CLASS (code) == 'c')
-    *walk_subtrees = 0;
+    {
+      if (TREE_VISITED (t))
+       *walk_subtrees = 0;
+      else
+       TREE_VISITED (t) = 1;
+    }
 
   /* Special-case BIND_EXPR.  We should never be copying these, therefore
      we can omit examining BIND_EXPR_VARS.  Which also avoids problems with
@@ -715,6 +786,31 @@ unmark_visited_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
   return NULL_TREE;
 }
 
+/* Unshare all the trees in BODY_P, a pointer to the body of FNDECL, and the
+   bodies of any nested functions.  */
+
+static void
+unshare_body (tree *body_p, tree fndecl)
+{
+  struct cgraph_node *cgn = cgraph_node (fndecl);
+
+  walk_tree (body_p, copy_if_shared_r, NULL, NULL);
+  for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
+    unshare_body (&DECL_SAVED_TREE (cgn->decl), cgn->decl);
+}
+
+/* Likewise, but mark all trees as not visited.  */
+
+static void
+unvisit_body (tree *body_p, tree fndecl)
+{
+  struct cgraph_node *cgn = cgraph_node (fndecl);
+
+  walk_tree (body_p, unmark_visited_r, NULL, NULL);
+  for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
+    unvisit_body (&DECL_SAVED_TREE (cgn->decl), cgn->decl);
+}
+
 /* Unshare T and all the trees reached from T via TREE_CHAIN.  */
 
 void
@@ -1192,7 +1288,7 @@ build_and_jump (tree *label_p)
 {
   if (label_p == NULL)
     /* If there's nowhere to jump, just fall through.  */
-    return build_empty_stmt ();
+    return alloc_stmt_list ();
 
   if (*label_p == NULL_TREE)
     {
@@ -1214,7 +1310,7 @@ gimplify_exit_expr (tree *expr_p)
   tree expr;
 
   expr = build_and_jump (&gimplify_ctxp->exit_label);
-  expr = build (COND_EXPR, void_type_node, cond, expr, build_empty_stmt ());
+  expr = build (COND_EXPR, void_type_node, cond, expr, alloc_stmt_list ());
   *expr_p = expr;
 
   return GS_OK;
@@ -1243,7 +1339,7 @@ force_labels_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
 
 static enum gimplify_status
 gimplify_init_constructor (tree *expr_p, tree *pre_p,
-                          tree *post_p, int want_value)
+                          tree *post_p, bool want_value)
 {
   tree object = TREE_OPERAND (*expr_p, 0);
   tree ctor = TREE_OPERAND (*expr_p, 1);
@@ -1279,7 +1375,7 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
                return GS_OK;
              }
            else
-             return GS_ALL_DONE;
+             return GS_UNHANDLED;
          }
 
        categorize_ctor_elements (ctor, &num_nonzero_elements,
@@ -1307,7 +1403,7 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
               TU-local symbol, we must invoke the lhd version now.  */
            lhd_set_decl_assembler_name (object);
 
-           *expr_p = build_empty_stmt ();
+           *expr_p = alloc_stmt_list ();
            break;
          }
 
@@ -1416,13 +1512,11 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
                if (TREE_CODE (purpose) == RANGE_EXPR)
                  abort ();
 
-               cref = build (ARRAY_REF, t, object, purpose);
+               cref = build (ARRAY_REF, t, object, purpose, NULL_TREE, NULL_TREE);
              }
            else
-             {
-               cref = build (COMPONENT_REF, TREE_TYPE (purpose),
-                             object, purpose);
-             }
+             cref = build (COMPONENT_REF, TREE_TYPE (purpose), object,
+                           purpose, NULL_TREE);
 
            init = build (MODIFY_EXPR, TREE_TYPE (purpose), cref, value);
            /* Each member initialization is a full-expression.  */
@@ -1430,7 +1524,7 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
            append_to_statement_list (init, pre_p);
          }
 
-       *expr_p = build_empty_stmt ();
+       *expr_p = alloc_stmt_list ();
       }
       break;
 
@@ -1552,18 +1646,17 @@ canonicalize_component_ref (tree *expr_p)
 }
 
 /* If a NOP conversion is changing a pointer to array of foo to a pointer
-   to foo, embed that change in the ADDR_EXPR.  Lest we perturb the type
-   system too badly, we must take extra steps to ensure that the ADDR_EXPR
-   and the addressed object continue to agree on types.  */
-/* ??? We might could do better if we recognize
-       T array[N][M];
-       (T *)&array
+   to foo, embed that change in the ADDR_EXPR by converting 
+      T array[U];
+      (T *)&array
    ==>
-       &array[0][0];
-*/
+      &array[L]
+   where L is the lower bound.  Only do this for constant lower bound since
+   we have no place to put any statements made during gimplification of
+   the lower bound.  */
 
 static void
-canonicalize_addr_expr (treeexpr_p)
+canonicalize_addr_expr (tree *expr_p)
 {
   tree expr = *expr_p;
   tree ctype = TREE_TYPE (expr);
@@ -1592,8 +1685,20 @@ canonicalize_addr_expr (tree* expr_p)
   if (!lang_hooks.types_compatible_p (otype, datype))
     return;
 
+  /* The lower bound and element sizes must be constant.  */
+  if (TREE_CODE (TYPE_SIZE_UNIT (dctype)) != INTEGER_CST
+      || !TYPE_DOMAIN (datype) || !TYPE_MIN_VALUE (TYPE_DOMAIN (datype))
+      || TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (datype))) != INTEGER_CST)
+    return;
+
   /* All checks succeeded.  Build a new node to merge the cast.  */
-  *expr_p = build1 (ADDR_EXPR, ctype, obj_expr);
+  *expr_p = build4 (ARRAY_REF, dctype, obj_expr,
+                   TYPE_MIN_VALUE (TYPE_DOMAIN (datype)),
+                   TYPE_MIN_VALUE (TYPE_DOMAIN (datype)),
+                   size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (dctype),
+                               size_int (TYPE_ALIGN (dctype)
+                                         / BITS_PER_UNIT)));
+  *expr_p = build1 (ADDR_EXPR, ctype, *expr_p);
 }
 
 /* *EXPR_P is a NOP_EXPR or CONVERT_EXPR.  Remove it and/or other conversions
@@ -1666,7 +1771,7 @@ gimplify_minimax_expr (tree *expr_p, tree *pre_p, tree *post_p)
     return GS_OK;
 }
 
-/* Subroutine of gimplify_compound_lval and gimplify_array_ref.
+/* Subroutine of gimplify_compound_lval.
    Converts an ARRAY_REF to the equivalent *(&array + offset) form.  */
 
 static enum gimplify_status
@@ -1675,25 +1780,21 @@ gimplify_array_ref_to_plus (tree *expr_p, tree *pre_p, tree *post_p)
   tree array = TREE_OPERAND (*expr_p, 0);
   tree arrtype = TREE_TYPE (array);
   tree elttype = TREE_TYPE (arrtype);
-  tree size = size_in_bytes (elttype);
+  tree size = array_ref_element_size (*expr_p);
   tree ptrtype = build_pointer_type (elttype);
   enum tree_code add_code = PLUS_EXPR;
   tree idx = TREE_OPERAND (*expr_p, 1);
-  tree minidx, offset, addr, result;
+  tree minidx = unshare_expr (array_ref_low_bound (*expr_p));
+  tree offset, addr, result;
   enum gimplify_status ret;
 
   /* If the array domain does not start at zero, apply the offset.  */
-  minidx = TYPE_DOMAIN (arrtype);
-  if (minidx)
+  if (!integer_zerop (minidx))
     {
-      minidx = TYPE_MIN_VALUE (minidx);
-      if (minidx && !integer_zerop (minidx))
-       {
-         idx = convert (TREE_TYPE (minidx), idx);
-         idx = fold (build (MINUS_EXPR, TREE_TYPE (minidx), idx, minidx));
-       }
+      idx = convert (TREE_TYPE (minidx), idx);
+      idx = fold (build (MINUS_EXPR, TREE_TYPE (minidx), idx, minidx));
     }
-
+  
   /* If the index is negative -- a technically invalid situation now
      that we've biased the index back to zero -- then casting it to
      unsigned has ill effects.  In particular, -1*4U/4U != -1.
@@ -1707,7 +1808,7 @@ gimplify_array_ref_to_plus (tree *expr_p, tree *pre_p, tree *post_p)
     }
 
   /* Pointer arithmetic must be done in sizetype.  */
-  idx = convert (sizetype, idx);
+  idx = fold_convert (sizetype, idx);
 
   /* Convert the index to a byte offset.  */
   offset = size_binop (MULT_EXPR, size, idx);
@@ -1723,6 +1824,44 @@ gimplify_array_ref_to_plus (tree *expr_p, tree *pre_p, tree *post_p)
   return GS_OK;
 }
 
+/*  Build an expression for the address of T.  Folds away INDIRECT_REF to
+    avoid confusing the gimplify process.  */
+
+static tree
+build_addr_expr_with_type (tree t, tree ptrtype)
+{
+  if (TREE_CODE (t) == INDIRECT_REF)
+    {
+      t = TREE_OPERAND (t, 0);
+      if (TREE_TYPE (t) != ptrtype)
+       t = build1 (NOP_EXPR, ptrtype, t);
+    }
+  else
+    {
+      tree base = t;
+
+      if (TREE_CODE (base) == REALPART_EXPR
+         || TREE_CODE (base) == IMAGPART_EXPR)
+       base = TREE_OPERAND (base, 0);
+      else
+       while (handled_component_p (base))
+         base = TREE_OPERAND (base, 0);
+
+      if (DECL_P (base))
+       TREE_ADDRESSABLE (base) = 1;
+
+      t = build1 (ADDR_EXPR, ptrtype, t);
+    }
+
+  return t;
+}
+
+static tree
+build_addr_expr (tree t)
+{
+  return build_addr_expr_with_type (t, build_pointer_type (TREE_TYPE (t)));
+}
+
 /* Gimplify the COMPONENT_REF, ARRAY_REF, REALPART_EXPR or IMAGPART_EXPR
    node pointed by EXPR_P.
 
@@ -1747,63 +1886,49 @@ gimplify_array_ref_to_plus (tree *expr_p, tree *pre_p, tree *post_p)
 
 static enum gimplify_status
 gimplify_compound_lval (tree *expr_p, tree *pre_p,
-                       tree *post_p, int want_lvalue)
+                       tree *post_p, bool want_lvalue)
 {
   tree *p;
-  enum tree_code code;
   varray_type stack;
-  enum gimplify_status ret;
+  enum gimplify_status ret = GS_OK, tret;
 
 #if defined ENABLE_CHECKING
   if (TREE_CODE (*expr_p) != ARRAY_REF
+      && TREE_CODE (*expr_p) != ARRAY_RANGE_REF
       && TREE_CODE (*expr_p) != COMPONENT_REF
+      && TREE_CODE (*expr_p) != BIT_FIELD_REF
       && TREE_CODE (*expr_p) != REALPART_EXPR
       && TREE_CODE (*expr_p) != IMAGPART_EXPR)
     abort ();
 #endif
 
-  code = ERROR_MARK;   /* [GIMPLE] Avoid uninitialized use warning.  */
-
   /* Create a stack of the subexpressions so later we can walk them in
      order from inner to outer.  */
   VARRAY_TREE_INIT (stack, 10, "stack");
 
-  for (p = expr_p;
-       TREE_CODE (*p) == ARRAY_REF
-       || TREE_CODE (*p) == COMPONENT_REF
-       || TREE_CODE (*p) == REALPART_EXPR
-       || TREE_CODE (*p) == IMAGPART_EXPR;
-       p = &TREE_OPERAND (*p, 0))
-    {
-      code = TREE_CODE (*p);
-      if (code == ARRAY_REF)
-       {
-         tree elttype = TREE_TYPE (TREE_TYPE (TREE_OPERAND (*p, 0)));
-         if (!TREE_CONSTANT (TYPE_SIZE_UNIT (elttype)))
-           /* If the size of the array elements is not constant,
-              computing the offset is non-trivial, so expose it.  */
-           break;
-       }
+  /* We can either handle one REALPART_EXPR or IMAGEPART_EXPR or
+     nest of handled components.  */
+  if (TREE_CODE (*expr_p) == REALPART_EXPR
+      || TREE_CODE (*expr_p) == IMAGPART_EXPR)
+    p = &TREE_OPERAND (*expr_p, 0);
+  else
+    for (p = expr_p; handled_component_p (*p); p = &TREE_OPERAND (*p, 0))
       VARRAY_PUSH_TREE (stack, *p);
-    }
-
-  /* Now 'p' points to the first bit that isn't a ref, 'code' is the
-     TREE_CODE of the last bit that was, and 'stack' is a stack of pointers
-     to all the refs we've walked through.
 
-     Gimplify the base, and then process each of the outer nodes from left
-     to right.  */
-  ret = gimplify_expr (p, pre_p, post_p, is_gimple_min_lval,
-                      code != ARRAY_REF ? fb_either : fb_lvalue);
+  /* Now STACK is a stack of pointers to all the refs we've walked through
+     and P points to the innermost expression.
 
+     Process each of the outer nodes from left to right, then gimplify the
+     base.  We need to do it in this order so that PLACEHOLDER_EXPRs
+     can be resolved.  */
   for (; VARRAY_ACTIVE_SIZE (stack) > 0; )
     {
       tree t = VARRAY_TOP_TREE (stack);
-      if (TREE_CODE (t) == ARRAY_REF)
+
+      if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
        {
-         /* Gimplify the dimension.  */
-         enum gimplify_status tret;
-         /* Temporary fix for gcc.c-torture/execute/20040313-1.c.
+         /* Gimplify the dimension.
+            Temporary fix for gcc.c-torture/execute/20040313-1.c.
             Gimplify non-constant array indices into a temporary
             variable.
             FIXME - The real fix is to gimplify post-modify
@@ -1815,14 +1940,82 @@ gimplify_compound_lval (tree *expr_p, tree *pre_p,
            {
              tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p,
                                    is_gimple_tmp_var, fb_rvalue);
-             if (tret == GS_ERROR)
-               ret = GS_ERROR;
+             ret = MIN (ret, tret);
+           }
+
+         /* Gimplify the low bound and element type size and put them into
+            the ARRAY_REF.  If these values are set, they have already been
+            gimplified.  */
+         if (!TREE_OPERAND (t, 2))
+           {
+             TREE_OPERAND (t, 2) = unshare_expr (array_ref_low_bound (t));
+             if (!is_gimple_min_invariant (TREE_OPERAND (t, 2)))
+               {
+                 tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
+                                       is_gimple_tmp_var, fb_rvalue);
+                 ret = MIN (ret, tret);
+               }
+           }
+
+         if (!TREE_OPERAND (t, 3))
+           {
+             tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0)));
+             tree elmt_size = unshare_expr (array_ref_element_size (t));
+             tree factor = size_int (TYPE_ALIGN (elmt_type) / BITS_PER_UNIT);
+
+             /* Divide the element size by the alignment of the element
+                type (above).  */
+             elmt_size = size_binop (EXACT_DIV_EXPR, elmt_size, factor);
+
+             TREE_OPERAND (t, 3) = elmt_size;
+             if (!is_gimple_min_invariant (TREE_OPERAND (t, 3)))
+               {
+                 tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p, post_p,
+                                       is_gimple_tmp_var, fb_rvalue);
+                 ret = MIN (ret, tret);
+               }
            }
        }
+      else if (TREE_CODE (t) == COMPONENT_REF)
+       {
+         /* Set the field offset into T and gimplify it.  */
+         if (!TREE_OPERAND (t, 2))
+           {
+             tree offset = unshare_expr (component_ref_field_offset (t));
+             tree field = TREE_OPERAND (t, 1);
+             tree factor
+               = size_int (DECL_OFFSET_ALIGN (field) / BITS_PER_UNIT);
+
+             /* Divide the offset by its alignment.  */
+             offset = size_binop (EXACT_DIV_EXPR, offset, factor);
+
+             TREE_OPERAND (t, 2) = offset;
+             if (!is_gimple_min_invariant (TREE_OPERAND (t, 2)))
+               {
+                 tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
+                                       is_gimple_tmp_var, fb_rvalue);
+                 ret = MIN (ret, tret);
+               }
+           }
+       }
+      else if (TREE_CODE (t) == BIT_FIELD_REF)
+       {
+         tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p,
+                               is_gimple_val, fb_rvalue);
+         ret = MIN (ret, tret);
+         tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
+                               is_gimple_val, fb_rvalue);
+         ret = MIN (ret, tret);
+       }
+         
       recalculate_side_effects (t);
       VARRAY_POP (stack);
     }
 
+  tret = gimplify_expr (p, pre_p, post_p, is_gimple_min_lval,
+                       want_lvalue ? fb_lvalue : fb_rvalue);
+  ret = MIN (ret, tret);
+
   /* If the outermost expression is a COMPONENT_REF, canonicalize its type.  */
   if (!want_lvalue && TREE_CODE (*expr_p) == COMPONENT_REF)
     {
@@ -1833,33 +2026,6 @@ gimplify_compound_lval (tree *expr_p, tree *pre_p,
   return ret;
 }
 
-/*  Re-write the ARRAY_REF node pointed by EXPR_P.
-
-    PRE_P points to the list where side effects that must happen before
-       *EXPR_P should be stored.
-
-    POST_P points to the list where side effects that must happen after
-       *EXPR_P should be stored.
-
-    FIXME: ARRAY_REF currently doesn't accept a pointer as the array
-    argument, so this gimplification uses an INDIRECT_REF of ARRAY_TYPE.
-    ARRAY_REF should be extended.  */
-
-static enum gimplify_status
-gimplify_array_ref (tree *expr_p, tree *pre_p,
-                   tree *post_p, int want_lvalue)
-{
-  tree elttype = TREE_TYPE (TREE_TYPE (TREE_OPERAND (*expr_p, 0)));
-  if (!TREE_CONSTANT (TYPE_SIZE_UNIT (elttype)))
-    /* If the size of the array elements is not constant,
-       computing the offset is non-trivial, so expose it.  */
-    return gimplify_array_ref_to_plus (expr_p, pre_p, post_p);
-  else
-    /* Handle array and member refs together for now.  When alias analysis
-       improves, we may want to go back to handling them separately.  */
-    return gimplify_compound_lval (expr_p, pre_p, post_p, want_lvalue);
-}
-
 /*  Gimplify the self modifying expression pointed by EXPR_P (++, --, +=, -=).
 
     PRE_P points to the list where side effects that must happen before
@@ -1873,7 +2039,7 @@ gimplify_array_ref (tree *expr_p, tree *pre_p,
 
 static enum gimplify_status
 gimplify_self_mod_expr (tree *expr_p, tree *pre_p, tree *post_p,
-                       int want_value)
+                       bool want_value)
 {
   enum tree_code code;
   tree lhs, lvalue, rhs, t1;
@@ -2166,7 +2332,7 @@ shortcut_cond_expr (tree expr)
          then_ = shortcut_cond_expr (expr);
          pred = TREE_OPERAND (pred, 0);
          expr = build (COND_EXPR, void_type_node, pred, then_,
-                       build_empty_stmt ());
+                       alloc_stmt_list ());
        }
     }
   if (!TREE_SIDE_EFFECTS (then_))
@@ -2181,7 +2347,7 @@ shortcut_cond_expr (tree expr)
          else_ = shortcut_cond_expr (expr);
          pred = TREE_OPERAND (pred, 0);
          expr = build (COND_EXPR, void_type_node, pred,
-                       build_empty_stmt (), else_);
+                       alloc_stmt_list (), else_);
        }
     }
 
@@ -2207,14 +2373,14 @@ shortcut_cond_expr (tree expr)
       && TREE_CODE (GOTO_DESTINATION (then_)) == LABEL_DECL)
     {
       true_label = GOTO_DESTINATION (then_);
-      then_ = build_empty_stmt ();
+      then_ = alloc_stmt_list ();
     }
 
   if (TREE_CODE (else_) == GOTO_EXPR
       && TREE_CODE (GOTO_DESTINATION (else_)) == LABEL_DECL)
     {
       false_label = GOTO_DESTINATION (else_);
-      else_ = build_empty_stmt ();
+      else_ = alloc_stmt_list ();
     }
 
   /* If we aren't hijacking a label for the 'then' branch, it falls through.  */
@@ -2329,6 +2495,8 @@ gimple_boolify (tree expr)
 
     The second form is used when *EXPR_P is of type void.
 
+    TARGET is the tree for T1 above.
+
     PRE_P points to the list where side effects that must happen before
        *EXPR_P should be stored.  */
 
@@ -2456,7 +2624,7 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value)
 {
   tree *from_p = &TREE_OPERAND (*expr_p, 1);
   tree *to_p = &TREE_OPERAND (*expr_p, 0);
-  enum gimplify_status ret;
+  enum gimplify_status ret = GS_UNHANDLED;
 
 #if defined ENABLE_CHECKING
   if (TREE_CODE (*expr_p) != MODIFY_EXPR && TREE_CODE (*expr_p) != INIT_EXPR)
@@ -2467,40 +2635,51 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value)
   if (TREE_CODE (*expr_p) == INIT_EXPR)
     TREE_SET_CODE (*expr_p, MODIFY_EXPR);
 
-  ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
-  if (ret == GS_ERROR)
+  /* See if any simplifications can be done based on what the RHS is.  */
+  ret = gimplify_modify_expr_rhs (expr_p, from_p, to_p, pre_p, post_p,
+                                 want_value);
+  if (ret != GS_UNHANDLED)
     return ret;
 
-  /* If we are initializing something from a TARGET_EXPR, strip the
-     TARGET_EXPR and initialize it directly, if possible.  This can't
-     be done if the initializer is void, since that implies that the
-     temporary is set in some non-trivial way.  */
-  /* What about code that pulls out the temp and uses it elsewhere?  I
-     think that such code never uses the TARGET_EXPR as an initializer.  If
-     I'm wrong, we'll abort because the temp won't have any RTL.  In that
-     case, I guess we'll need to replace references somehow.  */
-  if (TREE_CODE (*from_p) == TARGET_EXPR)
+  /* If the value being copied is of variable width, expose the length
+     if the copy by converting the whole thing to a memcpy.  Note that
+     we need to do this before gimplifying any of the operands
+     so that we can resolve any PLACEHOLDER_EXPRs in the size.  */
+  if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (*to_p))) != INTEGER_CST)
     {
-      tree init = TARGET_EXPR_INITIAL (*from_p);
-      if (!VOID_TYPE_P (TREE_TYPE (init)))
-        *from_p = init;
+      tree args, t, dest;
+
+      t = TYPE_SIZE_UNIT (TREE_TYPE (*to_p));
+      t = SUBSTITUTE_PLACEHOLDER_IN_EXPR (t, *to_p);
+      t = SUBSTITUTE_PLACEHOLDER_IN_EXPR (t, *from_p);
+      t = unshare_expr (t);
+      args = tree_cons (NULL, t, NULL);
+      t = build_fold_addr_expr (*from_p);
+      args = tree_cons (NULL, t, args);
+      dest = build_fold_addr_expr (*to_p);
+      args = tree_cons (NULL, dest, args);
+      t = implicit_built_in_decls[BUILT_IN_MEMCPY];
+      t = build_function_call_expr (t, args);
+      if (want_value)
+       {
+         t = build1 (NOP_EXPR, TREE_TYPE (dest), t);
+         t = build1 (INDIRECT_REF, TREE_TYPE (*to_p), t);
+       }
+      *expr_p = t;
+      return GS_OK;
     }
 
-  /* If we're assigning from a ?: expression with ADDRESSABLE type, push
-     the assignment down into the branches, since we can't generate a
-     temporary of such a type.  */
-  if (TREE_CODE (*from_p) == COND_EXPR
-      && TREE_ADDRESSABLE (TREE_TYPE (*from_p)))
-    {
-      *expr_p = *from_p;
-      return gimplify_cond_expr (expr_p, pre_p, *to_p);
-    }
+  ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
+  if (ret == GS_ERROR)
+    return ret;
 
   ret = gimplify_expr (from_p, pre_p, post_p, is_gimple_rhs, fb_rvalue);
   if (ret == GS_ERROR)
     return ret;
 
-  ret = gimplify_init_constructor (expr_p, pre_p, post_p, want_value);
+  /* Now see if the above changed *from_p to something we handle specially.  */
+  ret = gimplify_modify_expr_rhs (expr_p, from_p, to_p, pre_p, post_p,
+                                 want_value);
   if (ret != GS_UNHANDLED)
     return ret;
 
@@ -2530,35 +2709,6 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value)
                   && !is_gimple_reg (*to_p)))
        gimplify_expr (from_p, pre_p, post_p, is_gimple_val, fb_rvalue);
 
-      /* If the value being copied is of variable width, expose the length
-        if the copy by converting the whole thing to a memcpy.  */
-      /* ??? Except that we can't manage this with VA_ARG_EXPR.  Yes, this
-        does leave us with an edge condition that doesn't work.  The only
-        way out is to rearrange how VA_ARG_EXPR works.  */
-      if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (*to_p))) != INTEGER_CST
-         && TREE_CODE (*from_p) != VA_ARG_EXPR)
-       {
-         tree args, t, dest;
-
-         t = TYPE_SIZE_UNIT (TREE_TYPE (*to_p));
-         t = unshare_expr (t);
-         args = tree_cons (NULL, t, NULL);
-         t = build_fold_addr_expr (*from_p);
-         args = tree_cons (NULL, t, args);
-         dest = build_fold_addr_expr (*to_p);
-         args = tree_cons (NULL, dest, args);
-         t = implicit_built_in_decls[BUILT_IN_MEMCPY];
-         t = build_function_call_expr (t, args);
-         if (want_value)
-           {
-             t = build1 (NOP_EXPR, TREE_TYPE (dest), t);
-             t = build1 (INDIRECT_REF, TREE_TYPE (*to_p), t);
-           }
-         *expr_p = t;
-
-         return GS_OK;
-       }
-
       ret = want_value ? GS_OK : GS_ALL_DONE;
     }
 
@@ -2571,6 +2721,101 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value)
   return ret;
 }
 
+/*  Subroutine of above to do simplications of MODIFY_EXPRs based on
+    the code of the RHS.  We loop for as long as we can do something.  */
+
+static enum gimplify_status
+gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p,
+                         tree *post_p, bool want_value)
+{
+  enum gimplify_status ret = GS_OK;
+
+  while (ret != GS_UNHANDLED)
+    switch (TREE_CODE (*from_p))
+      {
+      case TARGET_EXPR:
+       {
+         /* If we are initializing something from a TARGET_EXPR, strip the
+            TARGET_EXPR and initialize it directly, if possible.  This can't
+            be done if the initializer is void, since that implies that the
+            temporary is set in some non-trivial way.
+
+            ??? What about code that pulls out the temp and uses it
+            elsewhere? I think that such code never uses the TARGET_EXPR as
+            an initializer.  If I'm wrong, we'll abort because the temp won't
+            have any RTL.  In that case, I guess we'll need to replace
+            references somehow.  */
+         tree init = TARGET_EXPR_INITIAL (*from_p);
+
+         if (!VOID_TYPE_P (TREE_TYPE (init)))
+           {
+             *from_p = init;
+             ret = GS_OK;
+           }
+         else
+           ret = GS_UNHANDLED;
+       }
+       break;
+
+      case COMPOUND_EXPR:
+       /* Remove any COMPOUND_EXPR in the RHS so the following cases will be
+          caught.  */
+       gimplify_compound_expr (from_p, pre_p, true);
+       ret = GS_OK;
+       break;
+
+      case CONSTRUCTOR:
+       /* If we're initializing from a CONSTRUCTOR, break this into
+          individual MODIFY_EXPRs.  */
+       return gimplify_init_constructor (expr_p, pre_p, post_p, want_value);
+
+      case COND_EXPR:
+       /* If we're assigning from a ?: expression with ADDRESSABLE type, push
+          the assignment down into the branches, since we can't generate a
+          temporary of such a type.  */
+       if (TREE_ADDRESSABLE (TREE_TYPE (*from_p)))
+         {
+           *expr_p = *from_p;
+           return gimplify_cond_expr (expr_p, pre_p, *to_p);
+         }
+       else
+         ret = GS_UNHANDLED;
+       break;
+
+      default:
+       ret = GS_UNHANDLED;
+       break;
+      }
+
+  return ret;
+}
+
+/*  Gimplify a comparison between two variable-sized objects.  Do this
+    with a call to BUILT_IN_MEMCMP.  */
+
+static enum gimplify_status
+gimplify_variable_sized_compare (tree *expr_p)
+{
+  tree op0 = TREE_OPERAND (*expr_p, 0);
+  tree op1 = TREE_OPERAND (*expr_p, 1);
+  tree args, t, dest;
+
+  t = TYPE_SIZE_UNIT (TREE_TYPE (op0));
+  t = SUBSTITUTE_PLACEHOLDER_IN_EXPR (t, op0);
+  t = unshare_expr (t);
+  args = tree_cons (NULL, t, NULL);
+  t = build_addr_expr (op1);
+  args = tree_cons (NULL, t, args);
+  dest = build_addr_expr (op0);
+  args = tree_cons (NULL, dest, args);
+  t = implicit_built_in_decls[BUILT_IN_MEMCMP];
+  t = build_function_call_expr (t, args);
+  *expr_p
+    = build (TREE_CODE (*expr_p), TREE_TYPE (*expr_p), t, integer_zero_node);
+
+  return GS_OK;
+}
+
 /*  Gimplify TRUTH_ANDIF_EXPR and TRUTH_ORIF_EXPR expressions.  EXPR_P
     points to the expression to gimplify.
 
@@ -2696,7 +2941,7 @@ gimplify_save_expr (tree *expr_p, tree *pre_p, tree *post_p)
       tree body = TREE_OPERAND (*expr_p, 0);
       ret = gimplify_expr (& body, pre_p, post_p, is_gimple_stmt, fb_none);
       append_to_statement_list (body, pre_p);
-      *expr_p = build_empty_stmt ();
+      *expr_p = alloc_stmt_list ();
     }
   else
     *expr_p = TREE_OPERAND (*expr_p, 0)
@@ -2742,9 +2987,15 @@ gimplify_addr_expr (tree *expr_p, tree *pre_p, tree *post_p)
                                        pre_p, post_p);
 
       /* This added an INDIRECT_REF.  Fold it away.  */
-      op0 = TREE_OPERAND (TREE_OPERAND (expr, 0), 0);
+      *expr_p = TREE_OPERAND (TREE_OPERAND (expr, 0), 0);
+      break;
 
-      *expr_p = op0;
+    case VIEW_CONVERT_EXPR:
+      /* Take the address of our operand and then convert it to the type of
+        this ADDR_EXPR.  */
+      *expr_p = fold_convert (TREE_TYPE (expr),
+                             build_addr_expr (TREE_OPERAND (op0, 0)));
+      ret = GS_OK;
       break;
 
     default:
@@ -2993,7 +3244,7 @@ gimple_push_cleanup (tree var, tree cleanup, tree *pre_p)
       tree ftrue = build (MODIFY_EXPR, void_type_node, flag,
                          boolean_true_node);
       cleanup = build (COND_EXPR, void_type_node, flag, cleanup,
-                      build_empty_stmt ());
+                      alloc_stmt_list ());
       wce = build (WITH_CLEANUP_EXPR, void_type_node, NULL_TREE,
                   cleanup, NULL_TREE);
       append_to_statement_list (ffalse, &gimplify_ctxp->conditional_cleanups);
@@ -3208,10 +3459,9 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
          break;
 
        case ARRAY_REF:
-         ret = gimplify_array_ref (expr_p, pre_p, post_p,
-                                   fallback & fb_lvalue);
-         break;
-
+       case ARRAY_RANGE_REF:
+       case REALPART_EXPR:
+       case IMAGPART_EXPR:
        case COMPONENT_REF:
          ret = gimplify_compound_lval (expr_p, pre_p, post_p,
                                        fallback & fb_lvalue);
@@ -3232,12 +3482,6 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
          ret = gimplify_compound_expr (expr_p, pre_p, fallback != fb_none);
          break;
 
-       case REALPART_EXPR:
-       case IMAGPART_EXPR:
-         ret = gimplify_compound_lval (expr_p, pre_p, post_p,
-                                       fallback & fb_lvalue);
-         break;
-
        case MODIFY_EXPR:
        case INIT_EXPR:
          ret = gimplify_modify_expr (expr_p, pre_p, post_p,
@@ -3265,6 +3509,34 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
          ret = gimplify_va_arg_expr (expr_p, pre_p, post_p);
          break;
 
+       case VIEW_CONVERT_EXPR:
+         if (VOID_TYPE_P (TREE_TYPE (*expr_p))
+             || fallback == fb_none)
+           {
+             /* Just strip a conversion to void (or in void context) and
+                try again.  */
+             *expr_p = TREE_OPERAND (*expr_p, 0);
+             break;
+           }
+
+         /* If both types are BLKmode or if one type is of variable size,
+            convert this into a pointer punning operation.  This avoids
+            copies of large data or making a variable-size temporary.  */
+         if ((TYPE_MODE (TREE_TYPE (*expr_p)) == BLKmode
+              && TYPE_MODE (TREE_TYPE (TREE_OPERAND (*expr_p, 0))) == BLKmode)
+             || !TREE_CONSTANT (TYPE_SIZE (TREE_TYPE (*expr_p)))
+             || !TREE_CONSTANT (TYPE_SIZE (TREE_TYPE
+                                           (TREE_OPERAND (*expr_p,0)))))
+           {
+             tree restype = TREE_TYPE (*expr_p);
+             *expr_p = build1 (INDIRECT_REF, TREE_TYPE (*expr_p),
+                               fold_convert (build_pointer_type (restype),
+                                             build_addr_expr
+                                             (TREE_OPERAND (*expr_p, 0))));
+             break;
+           }
+         goto unary;
+
        case CONVERT_EXPR:
        case NOP_EXPR:
          if (IS_EMPTY_STMT (*expr_p))
@@ -3293,6 +3565,7 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
        case FIX_CEIL_EXPR:
        case FIX_FLOOR_EXPR:
        case FIX_ROUND_EXPR:
+       unary:
          /* unary_expr: ... | '(' cast ')' val | ...  */
          ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
                               is_gimple_val, fb_rvalue);
@@ -3484,9 +3757,18 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
          break;
 
        default:
+         /* If this is a comparison of objects of aggregate type, handle
+            it specially (by converting to a call to memcmp).  It would be
+            nice to only have to do this for variable-sized objects, but
+            then we'd have to allow the same nest of reference nodes we
+            allow for MODIFY_EXPR and that's too complex.  */
+         if (TREE_CODE_CLASS (TREE_CODE (*expr_p)) == '<'
+             && (AGGREGATE_TYPE_P (TREE_TYPE (TREE_OPERAND (*expr_p, 1)))))
+           ret = gimplify_variable_sized_compare (expr_p);
+
          /* If *EXPR_P does not need to be special-cased, handle it
             according to its class.  */
-         if (TREE_CODE_CLASS (TREE_CODE (*expr_p)) == '1')
+         else if (TREE_CODE_CLASS (TREE_CODE (*expr_p)) == '1')
            ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
                                 post_p, is_gimple_val, fb_rvalue);
          else if (TREE_CODE_CLASS (TREE_CODE (*expr_p)) == '2'
@@ -3529,7 +3811,7 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
   if (ret == GS_ERROR)
     {
       if (is_statement)
-       *expr_p = build_empty_stmt ();
+       *expr_p = alloc_stmt_list ();
       goto out;
     }
 
@@ -3541,17 +3823,37 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
 #endif
 
   if (!*expr_p)
-    *expr_p = build_empty_stmt ();
+    *expr_p = alloc_stmt_list ();
   if (fallback == fb_none && !is_gimple_stmt (*expr_p))
     {
       /* We aren't looking for a value, and we don't have a valid
         statement.  If it doesn't have side-effects, throw it away.  */
       if (!TREE_SIDE_EFFECTS (*expr_p))
-       *expr_p = build_empty_stmt ();
+       *expr_p = alloc_stmt_list ();
       else if (!TREE_THIS_VOLATILE (*expr_p))
-       /* We only handle volatiles here; anything else with side-effects
-          must be converted to a valid statement before we get here.  */
-       abort ();
+       {
+         /* This is probably a _REF that contains something nested that
+            has side effects.  Recurse through the operands to find it.  */
+         enum tree_code code = TREE_CODE (*expr_p);
+
+         if (code == COMPONENT_REF
+             || code == REALPART_EXPR || code == IMAGPART_EXPR)
+           gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
+                          gimple_test_f, fallback);
+         else if (code == ARRAY_REF || code == ARRAY_RANGE_REF)
+           {
+             gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
+                            gimple_test_f, fallback);
+             gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
+                          gimple_test_f, fallback);
+           }
+         else
+           /* Anything else with side-effects
+              must be converted to a valid statement before we get here.  */
+           abort ();
+
+         *expr_p = alloc_stmt_list ();
+       }
       else if (COMPLETE_TYPE_P (TREE_TYPE (*expr_p)))
        {
          /* Historically, the compiler has treated a bare
@@ -3562,7 +3864,7 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
       else
        /* We can't do anything useful with a volatile reference to
           incomplete type, so just throw it away.  */
-       *expr_p = build_empty_stmt ();
+       *expr_p = alloc_stmt_list ();
     }
 
   /* If we are gimplifying at the statement level, we're done.  Tack
@@ -3660,6 +3962,78 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
   return ret;
 }
 
+/* Look through TYPE for variable-sized objects and gimplify each such
+   size that we find.  Return a STATEMENT_LIST containing the result.  */
+
+tree
+gimplify_type_sizes (tree type)
+{
+  tree stmts = NULL_TREE;
+  tree field;
+
+  switch (TREE_CODE (type))
+    {
+    case ERROR_MARK:
+      return alloc_stmt_list ();
+
+    case INTEGER_TYPE:
+    case ENUMERAL_TYPE:
+    case BOOLEAN_TYPE:
+    case CHAR_TYPE:
+    case REAL_TYPE:
+      gimplify_one_sizepos (&TYPE_MIN_VALUE (type), &stmts);
+      gimplify_one_sizepos (&TYPE_MAX_VALUE (type), &stmts);
+      break;
+
+    case ARRAY_TYPE:
+      /* These anonymous types don't have declarations, so handle them here. */
+      append_to_statement_list (gimplify_type_sizes (TYPE_DOMAIN (type)),
+                               &stmts);
+      break;
+
+    case RECORD_TYPE:
+    case UNION_TYPE:
+    case QUAL_UNION_TYPE:
+      for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+       if (TREE_CODE (field) == FIELD_DECL)
+         gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), &stmts);
+      break;
+
+    default:
+      break;
+    }
+
+  gimplify_one_sizepos (&TYPE_SIZE (type), &stmts);
+  gimplify_one_sizepos (&TYPE_SIZE_UNIT (type), &stmts);
+
+  if (!stmts)
+    stmts = alloc_stmt_list ();
+
+  return stmts;
+}
+
+/* Subroutine of the above to gimplify one size or position, *EXPR_P.
+   We add any required statements to STMT_P.  */
+
+void
+gimplify_one_sizepos (tree *expr_p, tree *stmt_p)
+{
+  tree pre = NULL_TREE, post = NULL_TREE;
+
+  /* We don't do anything if the value isn't there, is constant, or contains
+     A PLACEHOLDER_EXPR.  */
+  if (*expr_p == NULL_TREE || TREE_CONSTANT (*expr_p)
+      || CONTAINS_PLACEHOLDER_P (*expr_p))
+    return;
+
+  gimplify_expr (expr_p, &pre, &post, is_gimple_val, fb_rvalue);
+
+  if (pre)
+    append_to_statement_list (pre, stmt_p);
+  if (post)
+    append_to_statement_list (post, stmt_p);
+}
+\f
 #ifdef ENABLE_CHECKING
 /* Compare types A and B for a "close enough" match.  */
 
@@ -3720,8 +4094,10 @@ check_pointer_types_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
       dtype = TREE_TYPE (ptype);
       if (!cpt_same_type (otype, dtype))
        {
-         /* &array is allowed to produce a pointer to the element,
-            rather than a pointer to the array type.  */
+         /* &array is allowed to produce a pointer to the element, rather than
+            a pointer to the array type.  We must allow this in order to
+            properly represent assigning the address of an array in C into
+            pointer to the element type.  */
          if (TREE_CODE (otype) == ARRAY_TYPE
              && POINTER_TYPE_P (ptype)
              && cpt_same_type (TREE_TYPE (otype), dtype))
@@ -3751,8 +4127,12 @@ gimplify_body (tree *body_p, tree fndecl)
   timevar_push (TV_TREE_GIMPLIFY);
   push_gimplify_context ();
 
-  /* Unshare most shared trees in the body.  */
-  unshare_all_trees (*body_p);
+  /* Unshare most shared trees in the body and in that of any nested functions.
+     It would seem we don't have to do this for nested functions because
+     they are supposed to be output and then the outer function gimplified
+     first, but the g++ front end doesn't always do it that way.  */
+  unshare_body (body_p, fndecl);
+  unvisit_body (body_p, fndecl);
 
   /* Make sure input_location isn't set to something wierd.  */
   input_location = DECL_SOURCE_LOCATION (fndecl);
@@ -3764,13 +4144,14 @@ gimplify_body (tree *body_p, tree fndecl)
   /* Unshare again, in case gimplification was sloppy.  */
   unshare_all_trees (body);
 
-  /* If there isn't an outer BIND_EXPR, add one.  */
   if (TREE_CODE (body) == STATEMENT_LIST)
     {
       tree t = expr_only (*body_p);
       if (t)
        body = t;
     }
+
+  /* If there isn't an outer BIND_EXPR, add one.  */
   if (TREE_CODE (body) != BIND_EXPR)
     {
       tree b = build (BIND_EXPR, void_type_node, NULL_TREE,
index cd9cffb..fd89917 100644 (file)
@@ -1,3 +1,16 @@
+2004-06-21  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
+
+       * class.c (build_class_ref): Add new operand for COMPONENT_REF.
+       (build_static_field_ref): Likewise and add new operands for ARRAY_REF.
+       * constants.c (build_ref_from_constant_pool): Likewise.
+       * expr.c (build_java_array_length_access): Likewise.
+       (build_get_class, build_field_ref, build_known_method_ref): Likewise.
+       (invoke_build_dtable, build_invokevirtual): Likewise.
+       (build_invokeinterface, java_expand_expr): Likewise.
+       (emit_init_test_initialization): Likewise.
+       * java-gimplify.c (java_gimplify_new_array_init): Likewise.
+       * parse.y (make_qualifed_name, build_array_ref): Likewise.
+       
 2004-06-21  Andrew Haley  <aph@redhat.com>
 
        * java-gimplify.c (java_gimplify_block): set TREE_USED on the new
index cfb3366..ca9d627 100644 (file)
@@ -1023,7 +1023,7 @@ build_class_ref (tree type)
 
              prim_class = lookup_class (get_identifier (prim_class_name));
              return build (COMPONENT_REF, NULL_TREE,
-                           prim_class, TYPE_identifier_node);
+                           prim_class, TYPE_identifier_node, NULL_TREE);
            }
          decl_name = TYPE_NAME (type);
          if (TREE_CODE (decl_name) == TYPE_DECL)
@@ -1088,7 +1088,8 @@ build_static_field_ref (tree fdecl)
                       (fdecl, &TYPE_ATABLE_METHODS (output_class)), 0);
       tree field_address
        = build (ARRAY_REF, build_pointer_type (TREE_TYPE (fdecl)), 
-                TYPE_ATABLE_DECL (output_class), table_index);
+                TYPE_ATABLE_DECL (output_class), table_index,
+                NULL_TREE, NULL_TREE);
       return fold (build1 (INDIRECT_REF, TREE_TYPE (fdecl), 
                           field_address));
     }
@@ -1101,7 +1102,8 @@ build_static_field_ref (tree fdecl)
       int field_index = 0;
       ref = build1 (INDIRECT_REF, class_type_node, ref);
       ref = build (COMPONENT_REF, field_ptr_type_node, ref,
-                  lookup_field (&class_type_node, fields_ident));
+                  lookup_field (&class_type_node, fields_ident),
+                  NULL_TREE);
 
       for (fld = TYPE_FIELDS (fclass); ; fld = TREE_CHAIN (fld))
        {
@@ -1118,9 +1120,11 @@ build_static_field_ref (tree fdecl)
                         ref, build_int_2 (field_index, 0)));
       ref = build1 (INDIRECT_REF, field_type_node, ref);
       ref = build (COMPONENT_REF, field_info_union_node,
-                  ref, lookup_field (&field_type_node, info_ident));
+                  ref, lookup_field (&field_type_node, info_ident),
+                  NULL_TREE);
       ref = build (COMPONENT_REF, ptr_type_node,
-                  ref, TREE_CHAIN (TYPE_FIELDS (field_info_union_node)));
+                  ref, TREE_CHAIN (TYPE_FIELDS (field_info_union_node)),
+                  NULL_TREE);
       return fold (build1 (INDIRECT_REF, TREE_TYPE(fdecl), ref));
     }
 }
index 32fc854..98127f5 100644 (file)
@@ -424,7 +424,8 @@ build_ref_from_constant_pool (int index)
 {
   tree d = build_constant_data_ref ();
   tree i = build_int_2 (index, 0);
-  return build (ARRAY_REF, TREE_TYPE (TREE_TYPE (d)), d, i);
+  return build (ARRAY_REF, TREE_TYPE (TREE_TYPE (d)), d, i,
+               NULL_TREE, NULL_TREE);
 }
 
 /* Build an initializer for the constants field of the current constant pool.
index 86a7899..446f8af 100644 (file)
@@ -698,7 +698,8 @@ build_java_array_length_access (tree node)
   node = build (COMPONENT_REF, int_type_node,
                build_java_indirect_ref (array_type, node,
                                         flag_check_references),
-               lookup_field (&array_type, get_identifier ("length")));
+               lookup_field (&array_type, get_identifier ("length")),
+               NULL_TREE);
   IS_ARRAY_LENGTH_ACCESS (node) = 1;
   return node;
 }
@@ -780,9 +781,9 @@ build_java_arrayaccess (tree array, tree type, tree index)
   ref = build (COMPONENT_REF, TREE_TYPE (data_field),    
               build_java_indirect_ref (array_type, array, 
                                        flag_check_references),
-              data_field);
+              data_field, NULL_TREE);
   
-  node = build (ARRAY_REF, type, ref, index);
+  node = build (ARRAY_REF, type, ref, index, NULL_TREE, NULL_TREE);
   return node;
 }
 
@@ -1181,8 +1182,8 @@ build_get_class (tree value)
                        build (COMPONENT_REF, dtable_ptr_type,
                               build_java_indirect_ref (object_type_node, value,
                                                        flag_check_references),
-                              vtable_field)),
-               class_field);
+                              vtable_field, NULL_TREE)),
+               class_field, NULL_TREE);
 }
 
 /* This builds the tree representation of the `instanceof' operator.
@@ -1531,13 +1532,16 @@ build_field_ref (tree self_value, tree self_class, tree name)
           in the same translation unit as output_class.  If it is,
           we can make a direct reference.  */
        {
-         tree otable_index =
-           build_int_2 (get_symbol_table_index 
-                        (field_decl, &TYPE_OTABLE_METHODS (output_class)), 0);
-         tree field_offset = 
-           build (ARRAY_REF, integer_type_node, TYPE_OTABLE_DECL (output_class), 
-                  otable_index);
+         tree otable_index
+           = build_int_2 (get_symbol_table_index 
+                          (field_decl, &TYPE_OTABLE_METHODS (output_class)),
+                          0);
+         tree field_offset
+           = build (ARRAY_REF, integer_type_node,
+                    TYPE_OTABLE_DECL (output_class), otable_index,
+                    NULL_TREE, NULL_TREE);
          tree address;
+
          field_offset = fold (convert (sizetype, field_offset));
          address 
            = fold (build (PLUS_EXPR, 
@@ -1549,7 +1553,7 @@ build_field_ref (tree self_value, tree self_class, tree name)
       self_value = build_java_indirect_ref (TREE_TYPE (TREE_TYPE (self_value)),
                                            self_value, check);
       return fold (build (COMPONENT_REF, TREE_TYPE (field_decl),
-                         self_value, field_decl));
+                         self_value, field_decl, NULL_TREE));
     }
 }
 
@@ -1826,12 +1830,12 @@ build_known_method_ref (tree method, tree method_type ATTRIBUTE_UNUSED,
        }
       else
        {
-         tree table_index = 
-           build_int_2 (get_symbol_table_index 
-                        (method, &TYPE_ATABLE_METHODS (output_class)), 0);
-         func = 
-           build (ARRAY_REF,  method_ptr_type_node, 
-                  TYPE_ATABLE_DECL (output_class), table_index);
+         tree table_index
+           build_int_2 (get_symbol_table_index 
+                          (method, &TYPE_ATABLE_METHODS (output_class)), 0);
+         func = build (ARRAY_REF,  method_ptr_type_node, 
+                       TYPE_ATABLE_DECL (output_class), table_index,
+                       NULL_TREE, NULL_TREE);
        }
       func = convert (method_ptr_type_node, func);
     }
@@ -1858,7 +1862,7 @@ build_known_method_ref (tree method, tree method_type ATTRIBUTE_UNUSED,
       if (methods_ident == NULL_TREE)
        methods_ident = get_identifier ("methods");
       ref = build (COMPONENT_REF, method_ptr_type_node, ref,
-                  lookup_field (&class_type_node, methods_ident));
+                  lookup_field (&class_type_node, methods_ident), NULL_TREE);
       for (meth = TYPE_METHODS (self_type);
           ; meth = TREE_CHAIN (meth))
        {
@@ -1874,8 +1878,8 @@ build_known_method_ref (tree method, tree method_type ATTRIBUTE_UNUSED,
                         ref, build_int_2 (method_index, 0)));
       ref = build1 (INDIRECT_REF, method_type_node, ref);
       func = build (COMPONENT_REF, nativecode_ptr_type_node,
-                   ref,
-                   lookup_field (&method_type_node, ncode_ident));
+                   ref, lookup_field (&method_type_node, ncode_ident),
+                   NULL_TREE);
     }
   return func;
 }
@@ -1899,7 +1903,7 @@ invoke_build_dtable (int is_invoke_interface, tree arg_list)
   dtable = build_java_indirect_ref (object_type_node, objectref, 
                                    flag_check_references);
   dtable = build (COMPONENT_REF, dtable_ptr_type, dtable,
-                 lookup_field (&object_type_node, dtable_ident));
+                 lookup_field (&object_type_node, dtable_ident), NULL_TREE);
 
   return dtable;
 }
@@ -1955,7 +1959,7 @@ build_invokevirtual (tree dtable, tree method)
                       (method, &TYPE_OTABLE_METHODS (output_class)), 0);
       method_index = build (ARRAY_REF, integer_type_node, 
                            TYPE_OTABLE_DECL (output_class), 
-                           otable_index);
+                           otable_index, NULL_TREE, NULL_TREE);
     }
   else
     {
@@ -2001,7 +2005,7 @@ build_invokeinterface (tree dtable, tree method)
   dtable = build_java_indirect_ref (dtable_type, dtable,
                                    flag_check_references);
   dtable = build (COMPONENT_REF, class_ptr_type, dtable,
-                 lookup_field (&dtable_type, class_ident));
+                 lookup_field (&dtable_type, class_ident), NULL_TREE);
 
   interface = DECL_CONTEXT (method);
   if (! CLASS_INTERFACE (TYPE_NAME (interface)))
@@ -2010,17 +2014,15 @@ build_invokeinterface (tree dtable, tree method)
   
   if (flag_indirect_dispatch)
     {
-      otable_index =
-       build_int_2 (get_symbol_table_index 
-                    (method, &TYPE_OTABLE_METHODS (output_class)), 0);
-      idx = 
-       build (ARRAY_REF, integer_type_node, TYPE_OTABLE_DECL (output_class),
-              otable_index);
+      otable_index
+       build_int_2 (get_symbol_table_index 
+                      (method, &TYPE_OTABLE_METHODS (output_class)), 0);
+      idx = build (ARRAY_REF, integer_type_node,
+                  TYPE_OTABLE_DECL (output_class), otable_index,
+                  NULL_TREE, NULL_TREE);
     }
   else
-    {
-      idx = build_int_2 (get_interface_method_index (method, interface), 0);
-    }
+    idx = build_int_2 (get_interface_method_index (method, interface), 0);
 
   lookup_arg = tree_cons (NULL_TREE, dtable,
                           tree_cons (NULL_TREE, build_class_ref (interface),
@@ -2577,7 +2579,8 @@ java_expand_expr (tree exp, rtx target, enum machine_mode tmode,
        expand_assignment (build (COMPONENT_REF, TREE_TYPE (data_fld),
                                  build_java_indirect_ref (array_type, 
                                          array_decl, flag_check_references), 
-                                 data_fld), init, 0);
+                                 data_fld, NULL_TREE),
+                          init, 0);
        return tmp;
       }
     case BLOCK:
@@ -3460,7 +3463,8 @@ emit_init_test_initialization (void **entry, void *x ATTRIBUTE_UNUSED)
                 build (COMPONENT_REF, byte_type_node,
                        build1 (INDIRECT_REF, class_type_node, klass),
                        lookup_field (&class_type_node,
-                                     get_identifier ("state"))),
+                                     get_identifier ("state")),
+                       NULL_TREE),
                 build_int_2 (JV_STATE_DONE, 0));
 
   expand_expr_stmt (build (MODIFY_EXPR, boolean_type_node, 
index 3c44667..766995e 100644 (file)
@@ -1,5 +1,4 @@
 /* Java(TM) language-specific gimplification routines.
-
    Copyright (C) 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -223,10 +222,11 @@ java_gimplify_new_array_init (tree exp)
         bounds checking.  */
       tree lhs = build (COMPONENT_REF, TREE_TYPE (data_field),    
                        build_java_indirect_ref (array_type, tmp, 0),
-                       data_field);
+                       data_field, NULL_TREE);
       tree assignment = build (MODIFY_EXPR, element_type,
                               build (ARRAY_REF, element_type, lhs,
-                                     build_int_2 (index++, 0)),
+                                     build_int_2 (index++, 0),
+                                     NULL_TREE, NULL_TREE),
                               TREE_VALUE (values));
       body = build (COMPOUND_EXPR, element_type, body, assignment);
       values = TREE_CHAIN (values);
index dd52a39..ed1f050 100644 (file)
@@ -9254,7 +9254,7 @@ static tree
 make_qualified_name (tree left, tree right, int location)
 {
 #ifdef USE_COMPONENT_REF
-  tree node = build (COMPONENT_REF, NULL_TREE, left, right);
+  tree node = build (COMPONENT_REF, NULL_TREE, left, right, NULL_TREE);
   EXPR_WFL_LINECOL (node) = location;
   return node;
 #else
@@ -14353,7 +14353,7 @@ build_null_of_type (tree type)
 static tree
 build_array_ref (int location, tree array, tree index)
 {
-  tree node = build (ARRAY_REF, NULL_TREE, array, index);
+  tree node = build (ARRAY_REF, NULL_TREE, array, index, NULL_TREE, NULL_TREE);
   EXPR_WFL_LINECOL (node) = location;
   return node;
 }
index 4414309..bf73956 100644 (file)
@@ -1975,7 +1975,7 @@ generate_static_references (void)
       sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class);
       ident = get_identifier (buf);
 
-      expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
+      expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE, NULL_TREE, NULL_TREE);
       decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
                             build_tree_list (NULL_TREE,
                                              ridpointers[(int) RID_STATIC]));
@@ -2014,7 +2014,7 @@ generate_static_references (void)
 
   decls = tree_cons (NULL_TREE, build_int_2 (0, 0), decls);
   ident = get_identifier ("_OBJC_STATIC_INSTANCES");
-  expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
+  expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE, NULL_TREE, NULL_TREE);
   decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
                         build_tree_list (NULL_TREE,
                                          ridpointers[(int) RID_STATIC]));
@@ -2044,7 +2044,8 @@ generate_strings (void)
       sc_spec
        = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
       decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
-      expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
+      expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE,
+                           NULL_TREE, NULL_TREE);
       decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
       DECL_CONTEXT (decl) = NULL_TREE;
       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
@@ -2059,7 +2060,8 @@ generate_strings (void)
       sc_spec
        = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
       decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
-      expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
+      expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE,
+                           NULL_TREE, NULL_TREE);
       decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
       DECL_CONTEXT (decl) = NULL_TREE;
       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
@@ -2074,7 +2076,8 @@ generate_strings (void)
       sc_spec
        = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE);
       decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
-      expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE);
+      expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE,
+                           NULL_TREE, NULL_TREE);
       decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE);
       DECL_CONTEXT (decl) = NULL_TREE;
       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
@@ -3521,7 +3524,7 @@ build_method_prototype_list_template (tree list_type, int size)
 
   decl_specs = build_tree_list (NULL_TREE, list_type);
   field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
-                        build_int_2 (size, 0));
+                        build_int_2 (size, 0), NULL_TREE, NULL_TREE);
   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
   chainon (field_decl_chain, field_decl);
 
@@ -4405,7 +4408,7 @@ build_ivar_list_template (tree list_type, int size)
 
   decl_specs = build_tree_list (NULL_TREE, list_type);
   field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
-                        build_int_2 (size, 0));
+                        build_int_2 (size, 0), NULL_TREE, NULL_TREE);
 
   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
   chainon (field_decl_chain, field_decl);
@@ -4453,7 +4456,7 @@ build_method_list_template (tree list_type, int size)
 
   decl_specs = build_tree_list (NULL_TREE, list_type);
   field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
-                        build_int_2 (size, 0));
+                        build_int_2 (size, 0), NULL_TREE, NULL_TREE);
 
   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
   chainon (field_decl_chain, field_decl);
@@ -4860,18 +4863,18 @@ generate_protocol_list (tree i_or_p)
     expr_decl = build_nt (ARRAY_REF,
                          synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS",
                                                      i_or_p),
-                         build_int_2 (size + 2, 0));
+                         build_int_2 (size + 2, 0), NULL_TREE, NULL_TREE);
   else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
     expr_decl = build_nt (ARRAY_REF,
                          synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS",
                                                      i_or_p),
-                         build_int_2 (size + 2, 0));
+                         build_int_2 (size + 2, 0), NULL_TREE, NULL_TREE);
   else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
     expr_decl
       = build_nt (ARRAY_REF,
                  synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS",
                                              i_or_p),
-                 build_int_2 (size + 2, 0));
+                 build_int_2 (size + 2, 0), NULL_TREE, NULL_TREE);
   else
     abort ();
 
index 4d878e3..5ee55b9 100644 (file)
@@ -3391,12 +3391,6 @@ expand_stack_alloc (tree alloc, tree t_size)
 
   type = TREE_TYPE (var);
 
-  /* In function-at-a-time mode, variable_size doesn't expand this,
-     so do it now.  */
-  if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
-    expand_expr (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
-                const0_rtx, VOIDmode, 0);
-
   /* Compute the variable's size, in bytes.  */
   size = expand_expr (t_size, NULL_RTX, VOIDmode, 0);
   free_temp_slots ();
index aa452b4..b2ef41d 100644 (file)
@@ -93,11 +93,6 @@ tree
 get_pending_sizes (void)
 {
   tree chain = pending_sizes;
-  tree t;
-
-  /* Put each SAVE_EXPR into the current function.  */
-  for (t = chain; t; t = TREE_CHAIN (t))
-    SAVE_EXPR_CONTEXT (TREE_VALUE (t)) = current_function_decl;
 
   pending_sizes = 0;
   return chain;
index 33ef6d3..561feb5 100644 (file)
@@ -207,12 +207,15 @@ get_alias_var (tree expr)
   switch (TREE_CODE (expr))
     {
     case ARRAY_REF:
+    case ARRAY_RANGE_REF:
       {
-       /* Find the first non-array ref, and return it's alias
-          variable */
+       /* Find the first non-array ref, and return its alias variable.  */
        tree p;
-       for (p = expr; TREE_CODE (p) == ARRAY_REF;
-            p = TREE_OPERAND (p, 0));
+
+       for (p = expr;
+            TREE_CODE (p) == ARRAY_REF || TREE_CODE (p) == ARRAY_RANGE_REF;
+            p = TREE_OPERAND (p, 0))
+         ;
        return get_alias_var (p);
       }
       break;
index 8babdc2..9b42073 100644 (file)
@@ -3156,12 +3156,10 @@ verify_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
       break;
 
     case ADDR_EXPR:
-      x = TREE_OPERAND (t, 0);
-      while (TREE_CODE (x) == ARRAY_REF
-            || TREE_CODE (x) == COMPONENT_REF
-            || TREE_CODE (x) == REALPART_EXPR
-            || TREE_CODE (x) == IMAGPART_EXPR)
-       x = TREE_OPERAND (x, 0);
+      for (x = TREE_OPERAND (t, 0); handled_component_p (x);
+          x = TREE_OPERAND (x, 0))
+       ;
+
       if (TREE_CODE (x) != VAR_DECL && TREE_CODE (x) != PARM_DECL)
        return NULL;
       if (!TREE_ADDRESSABLE (x))
@@ -3309,7 +3307,7 @@ tree_node_can_be_shared (tree t)
       || TREE_CODE (t) == SSA_NAME)
     return true;
 
-  while ((TREE_CODE (t) == ARRAY_REF
+  while (((TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
          /* We check for constants explicitly since they are not considered
             gimple invariants if they overflowed.  */
          && (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t, 1))) == 'c'
index e1445be..307086b 100644 (file)
@@ -926,24 +926,17 @@ add_referenced_var (tree var, struct walk_state *walk_state)
 tree
 get_virtual_var (tree var)
 {
-  enum tree_code code;
-
   STRIP_NOPS (var);
 
   if (TREE_CODE (var) == SSA_NAME)
     var = SSA_NAME_VAR (var);
 
-  code = TREE_CODE (var);
-
-  while (code == ARRAY_REF
-         || code == COMPONENT_REF
-        || code == REALPART_EXPR
-        || code == IMAGPART_EXPR)
-    {
+  if (TREE_CODE (var) == REALPART_EXPR || TREE_CODE (var) == IMAGPART_EXPR)
+    var = TREE_OPERAND (var, 0);
+  else
+    while (handled_component_p (var))
       var = TREE_OPERAND (var, 0);
-      code = TREE_CODE (var);
-    }
-
+    
 #ifdef ENABLE_CHECKING
   /* Treating GIMPLE registers as virtual variables makes no sense.
      Also complain if we couldn't extract a _DECL out of the original
index 45accae..39aeead 100644 (file)
@@ -536,9 +536,7 @@ dequeue_and_dump (dump_info_p di)
     case TRUTH_ORIF_EXPR:
     case INIT_EXPR:
     case MODIFY_EXPR:
-    case COMPONENT_REF:
     case COMPOUND_EXPR:
-    case ARRAY_REF:
     case PREDECREMENT_EXPR:
     case PREINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
@@ -548,6 +546,20 @@ dequeue_and_dump (dump_info_p di)
       dump_child ("op 1", TREE_OPERAND (t, 1));
       break;
 
+    case COMPONENT_REF:
+      dump_child ("op 0", TREE_OPERAND (t, 0));
+      dump_child ("op 1", TREE_OPERAND (t, 1));
+      dump_child ("op 2", TREE_OPERAND (t, 2));
+      break;
+
+    case ARRAY_REF:
+    case ARRAY_RANGE_REF:
+      dump_child ("op 0", TREE_OPERAND (t, 0));
+      dump_child ("op 1", TREE_OPERAND (t, 1));
+      dump_child ("op 2", TREE_OPERAND (t, 2));
+      dump_child ("op 3", TREE_OPERAND (t, 3));
+      break;
+
     case COND_EXPR:
       dump_child ("op 0", TREE_OPERAND (t, 0));
       dump_child ("op 1", TREE_OPERAND (t, 1));
index 27f33c9..21c3a1c 100644 (file)
@@ -1682,6 +1682,7 @@ tree_could_trap_p (tree expr)
   switch (code)
     {
     case ARRAY_REF:
+    case ARRAY_RANGE_REF:
     case COMPONENT_REF:
     case REALPART_EXPR:
     case IMAGPART_EXPR:
index d3231c0..7c992b3 100644 (file)
@@ -119,17 +119,34 @@ Boston, MA 02111-1307, USA.  */
    min-lval: ID | '*' ID
    bitfieldref :
      BIT_FIELD_REF
-       op0 -> compref | min-lval
+       op0 -> inner_compref
        op1 -> CONST
-       op2 -> CONST
+       op2 -> var
    compref :
      COMPONENT_REF
-       op0 -> compref | min-lval
+       op0 -> inner_compref
      | ARRAY_REF
-       op0 -> compref | min-lval
+       op0 -> inner_compref
        op1 -> val
+       op2 -> val
+       op3 -> val
+     | ARRAY_RANGE_REF
+       op0 -> inner_compref
+       op1 -> val
+       op2 -> val
+       op3 -> val
      | REALPART_EXPR
+       op0 -> inner_compref
      | IMAGPART_EXPR
+       op0 -> inner_compref
+
+   inner_compref : compref | min_lval
+     | VIEW_CONVERT_EXPR
+       op0 -> inner_compref
+     | NOP_EXPR
+       op0 -> inner_compref
+     | CONVERT_EXPR
+       op0 -> inner_compref
 
    condition : val | val relop val
    val : ID | CONST
@@ -284,9 +301,11 @@ is_gimple_addr_expr_arg (tree t)
 {
   return (is_gimple_id (t)
          || TREE_CODE (t) == ARRAY_REF
+         || TREE_CODE (t) == ARRAY_RANGE_REF
          || TREE_CODE (t) == COMPONENT_REF
          || TREE_CODE (t) == REALPART_EXPR
-         || TREE_CODE (t) == IMAGPART_EXPR);
+         || TREE_CODE (t) == IMAGPART_EXPR
+         || TREE_CODE (t) == INDIRECT_REF);
 }
 
 /* Return nonzero if T is function invariant.  Or rather a restricted
@@ -581,19 +600,12 @@ get_base_address (tree t)
          || TREE_CODE (t) == INDIRECT_REF)
        return t;
 
-      switch (TREE_CODE (t))
-       {
-       case ARRAY_REF:
-       case COMPONENT_REF:
-       case REALPART_EXPR:
-       case IMAGPART_EXPR:
-       case BIT_FIELD_REF:
-         t = TREE_OPERAND (t, 0);
-         break;
-
-       default:
-         return NULL_TREE;
-       }
+      if (TREE_CODE (t) == REALPART_EXPR || TREE_CODE (t) == IMAGPART_EXPR)
+       t = TREE_OPERAND (t, 0);
+      else if (handled_component_p (t))
+       t = get_base_address (TREE_OPERAND (t, 0));
+      else
+       return NULL_TREE;
     }
   while (t);
 
index 29352a5..98f4695 100644 (file)
@@ -42,45 +42,45 @@ extern void annotate_all_with_locus (tree *, location_t);
    underlying nodes are also of the right form.  */
 
 /* Returns true iff T is a valid GIMPLE statement.  */
-bool is_gimple_stmt (tree);
+extern bool is_gimple_stmt (tree);
 
 /* Returns true iff TYPE is a valid type for a scalar register variable.  */
-bool is_gimple_reg_type (tree);
+extern bool is_gimple_reg_type (tree);
 /* Returns true iff T is a scalar register variable.  */
-bool is_gimple_reg (tree);
+extern bool is_gimple_reg (tree);
 /* Returns true iff T is any sort of variable.  */
-bool is_gimple_variable (tree);
+extern bool is_gimple_variable (tree);
 /* Returns true iff T is a variable or an INDIRECT_REF (of a variable).  */
-bool is_gimple_min_lval (tree);
+extern bool is_gimple_min_lval (tree);
 /* Returns true iff T is an lvalue other than an INDIRECT_REF.  */
-bool is_gimple_addr_expr_arg (tree);
+extern bool is_gimple_addr_expr_arg (tree);
 /* Returns true iff T is any valid GIMPLE lvalue.  */
-bool is_gimple_lvalue (tree);
+extern bool is_gimple_lvalue (tree);
 
 /* Returns true iff T is a GIMPLE restricted function invariant.  */
-bool is_gimple_min_invariant (tree);
+extern bool is_gimple_min_invariant (tree);
 /* Returns true iff T is a GIMPLE rvalue.  */
-bool is_gimple_val (tree);
+extern bool is_gimple_val (tree);
 /* Returns true iff T is a valid rhs for a MODIFY_EXPR.  */
-bool is_gimple_rhs (tree);
+extern bool is_gimple_rhs (tree);
 
 /* Returns true iff T is a valid if-statement condition.  */
-bool is_gimple_condexpr (tree);
+extern bool is_gimple_condexpr (tree);
 
 /* Returns true iff T is a type conversion.  */
-bool is_gimple_cast (tree);
+extern bool is_gimple_cast (tree);
 /* Returns true iff T is a valid CONSTRUCTOR element (either an rvalue or
    another CONSTRUCTOR).  */
-bool is_gimple_constructor_elt (tree);
+extern bool is_gimple_constructor_elt (tree);
 /* Returns true iff T is a variable that does not need to live in memory.  */
-bool is_gimple_non_addressable (tree t);
+extern bool is_gimple_non_addressable (tree t);
 
 /* If T makes a function call, returns the CALL_EXPR operand.  */
-tree get_call_expr_in (tree t);
+extern tree get_call_expr_in (tree t);
 
-void recalculate_side_effects (tree);
+extern void recalculate_side_effects (tree);
 
-void append_to_compound_expr (tree, tree *);
+extern void append_to_compound_expr (tree, tree *);
 
 /* FIXME we should deduce this from the predicate.  */
 typedef enum fallback_t {
@@ -98,29 +98,31 @@ enum gimplify_status {
   GS_ALL_DONE  = 1     /* The expression is fully gimplified.  */
 };
 
-enum gimplify_status gimplify_expr (tree *, tree *, tree *,
-                                   bool (*) (tree), fallback_t);
-void gimplify_stmt (tree *);
-void gimplify_to_stmt_list (tree *);
-void gimplify_body (tree *, tree);
-void push_gimplify_context (void);
-void pop_gimplify_context (tree);
-void gimplify_and_add (tree, tree *);
+extern enum gimplify_status gimplify_expr (tree *, tree *, tree *,
+                                          bool (*) (tree), fallback_t);
+extern tree gimplify_type_sizes (tree);
+extern void gimplify_one_sizepos (tree *, tree *);
+extern void gimplify_stmt (tree *);
+extern void gimplify_to_stmt_list (tree *);
+extern void gimplify_body (tree *, tree);
+extern void push_gimplify_context (void);
+extern void pop_gimplify_context (tree);
+extern void gimplify_and_add (tree, tree *);
 
 /* Miscellaneous helpers.  */
-tree get_base_address (tree t);
-void gimple_add_tmp_var (tree);
-tree gimple_current_bind_expr (void);
-void gimple_push_bind_expr (tree);
-void gimple_pop_bind_expr (void);
-void unshare_all_trees (tree);
-tree voidify_wrapper_expr (tree, tree);
-tree gimple_build_eh_filter (tree, tree, tree);
-tree build_and_jump (tree *);
-tree alloc_stmt_list (void);
-void free_stmt_list (tree);
-tree force_labels_r (tree *, int *, void *);
-enum gimplify_status gimplify_va_arg_expr (tree *, tree *, tree *);
+extern tree get_base_address (tree t);
+extern void gimple_add_tmp_var (tree);
+extern tree gimple_current_bind_expr (void);
+extern void gimple_push_bind_expr (tree);
+extern void gimple_pop_bind_expr (void);
+extern void unshare_all_trees (tree);
+extern tree voidify_wrapper_expr (tree, tree);
+extern tree gimple_build_eh_filter (tree, tree, tree);
+extern tree build_and_jump (tree *);
+extern tree alloc_stmt_list (void);
+extern void free_stmt_list (tree);
+extern tree force_labels_r (tree *, int *, void *);
+extern enum gimplify_status gimplify_va_arg_expr (tree *, tree *, tree *);
 
 /* In tree-nested.c.  */
 extern void lower_nested_functions (tree);
index 24bf3d1..deb7360 100644 (file)
@@ -2054,8 +2054,14 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, void *htab_)
        }
 #endif
     }
-  else if (TREE_CODE_CLASS (code) == 'd')
+
+  /* Look inside the sizes of decls, but we don't ever use the values for
+     FIELD_DECL and RESULT_DECL, so ignore them.  */
+  else if (TREE_CODE_CLASS (code) == 'd'
+          && code != FIELD_DECL && code != RESULT_DECL)
     {
+      WALK_SUBTREE (DECL_SIZE (*tp));
+      WALK_SUBTREE (DECL_SIZE_UNIT (*tp));
       WALK_SUBTREE_TAIL (TREE_TYPE (*tp));
     }
   else
@@ -2077,23 +2083,20 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, void *htab_)
        case REAL_CST:
        case VECTOR_CST:
        case STRING_CST:
-       case REAL_TYPE:
-       case COMPLEX_TYPE:
        case VECTOR_TYPE:
        case VOID_TYPE:
-       case BOOLEAN_TYPE:
-       case UNION_TYPE:
-       case ENUMERAL_TYPE:
        case BLOCK:
-       case RECORD_TYPE:
        case PLACEHOLDER_EXPR:
        case SSA_NAME:
+       case FIELD_DECL:
+       case RESULT_DECL:
          /* None of thse have subtrees other than those already walked
             above.  */
          break;
 
        case POINTER_TYPE:
        case REFERENCE_TYPE:
+       case COMPLEX_TYPE:
          WALK_SUBTREE_TAIL (TREE_TYPE (*tp));
          break;
 
@@ -2126,6 +2129,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, void *htab_)
 
        case METHOD_TYPE:
          WALK_SUBTREE (TYPE_METHOD_BASETYPE (*tp));
+
          /* Fall through.  */
 
        case FUNCTION_TYPE:
@@ -2139,12 +2143,43 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, void *htab_)
          }
          break;
 
+       case RECORD_TYPE:
+       case UNION_TYPE:
+       case QUAL_UNION_TYPE:
+         {
+           tree field;
+
+           for (field = TYPE_FIELDS (*tp); field; field = TREE_CHAIN (field))
+             {
+               /* We would like to look at the type of the field, but we
+                  can easily get infinite recursion.  So assume it's
+                  pointed to elsewhere in the tree.  Also, ignore things that
+                  aren't fields.  */
+               if (TREE_CODE (field) != FIELD_DECL)
+                 continue;
+
+               WALK_SUBTREE (DECL_FIELD_OFFSET (field));
+               WALK_SUBTREE (DECL_SIZE (field));
+               WALK_SUBTREE (DECL_SIZE_UNIT (field));
+               if (code == QUAL_UNION_TYPE)
+                 WALK_SUBTREE (DECL_QUALIFIER (field));
+             }
+         }
+         break;
+
        case ARRAY_TYPE:
-         WALK_SUBTREE (TREE_TYPE (*tp));
+         /* Don't follow this nodes's type if a pointer for fear that we'll
+            have infinite recursion.  Those types are uninteresting anyway. */
+         if (!POINTER_TYPE_P (TREE_TYPE (*tp))
+             && TREE_CODE (TREE_TYPE (*tp)) != OFFSET_TYPE)
+           WALK_SUBTREE (TREE_TYPE (*tp));
          WALK_SUBTREE_TAIL (TYPE_DOMAIN (*tp));
 
+       case BOOLEAN_TYPE:
+       case ENUMERAL_TYPE:
        case INTEGER_TYPE:
        case CHAR_TYPE:
+       case REAL_TYPE:
          WALK_SUBTREE (TYPE_MIN_VALUE (*tp));
          WALK_SUBTREE_TAIL (TYPE_MAX_VALUE (*tp));
 
@@ -2166,8 +2201,8 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, void *htab_)
                /* Walk the DECL_INITIAL and DECL_SIZE.  We don't want to walk
                   into declarations that are just mentioned, rather than
                   declared; they don't really belong to this part of the tree.
-                  And, we can see cycles: the initializer for a declaration can
-                  refer to the declaration itself.  */
+                  And, we can see cycles: the initializer for a declaration
+                  can refer to the declaration itself.  */
                WALK_SUBTREE (DECL_INITIAL (decl));
                WALK_SUBTREE (DECL_SIZE (decl));
                WALK_SUBTREE (DECL_SIZE_UNIT (decl));
@@ -2185,7 +2220,9 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, void *htab_)
          break;
 
        default:
-         abort ();
+         /* ??? This could be a language-defined node.  We really should make
+            a hook for it, but right now just ignore it.  */
+         break;
        }
     }
 
index 732ef5e..6181bb6 100644 (file)
@@ -463,7 +463,7 @@ mf_build_check_statement_for (tree addr, tree size,
              (flag_mudflap_threads ? mf_cache_mask_decl : mf_cache_mask_decl_l));
   t = build (ARRAY_REF,
              TREE_TYPE (TREE_TYPE (mf_cache_array_decl)),
-             mf_cache_array_decl, t);
+             mf_cache_array_decl, t, NULL_TREE, NULL_TREE);
   t = build1 (ADDR_EXPR, mf_cache_structptr_type, t);
   t = build (MODIFY_EXPR, void_type_node, mf_elem, t);
   SET_EXPR_LOCUS (t, locus);
@@ -487,7 +487,7 @@ mf_build_check_statement_for (tree addr, tree size,
   /* Construct t <-- '__mf_elem->low  > __mf_base'.  */
   t = build (COMPONENT_REF, mf_uintptr_type,
              build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
-             TYPE_FIELDS (mf_cache_struct_type));
+             TYPE_FIELDS (mf_cache_struct_type), NULL_TREE);
   t = build (GT_EXPR, boolean_type_node, t, mf_base);
 
   /* Construct '__mf_elem->high < __mf_base + sizeof(T) - 1'.
@@ -501,7 +501,7 @@ mf_build_check_statement_for (tree addr, tree size,
 
   u = build (COMPONENT_REF, mf_uintptr_type,
              build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
-             TREE_CHAIN (TYPE_FIELDS (mf_cache_struct_type)));
+             TREE_CHAIN (TYPE_FIELDS (mf_cache_struct_type)), NULL_TREE);
 
   v = convert (mf_uintptr_type,
               size_binop (MINUS_EXPR, size, size_one_node));
@@ -660,14 +660,14 @@ mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp,
            things the hard way with PLUS.  */
         if (DECL_BIT_FIELD_TYPE (field))
           {
-            size = bitsize_int (BITS_PER_UNIT);
-            size = size_binop (CEIL_DIV_EXPR, DECL_SIZE (field), size);
-            size = convert (sizetype, size);
+           if (TREE_CODE (DECL_SIZE_UNIT (field)) == INTEGER_CST)
+             size = DECL_SIZE_UNIT (field);
 
             addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
-            addr = convert (ptr_type_node, addr);
+            addr = fold_convert (ptr_type_node, addr);
             addr = fold (build (PLUS_EXPR, ptr_type_node,
-                                addr, byte_position (field)));
+                                addr, fold_convert (ptr_type_node,
+                                                   byte_position (field))));
           }
         else
           {
index 24d3e74..1f32e1f 100644 (file)
@@ -157,8 +157,13 @@ static tree
 build_addr (tree exp)
 {
   tree base = exp;
-  while (TREE_CODE (base) == COMPONENT_REF || TREE_CODE (base) == ARRAY_REF)
+
+  if (TREE_CODE (base) == REALPART_EXPR || TREE_CODE (base) == IMAGPART_EXPR)
     base = TREE_OPERAND (base, 0);
+  else
+    while (handled_component_p (base))
+      base = TREE_OPERAND (base, 0);
+
   if (DECL_P (base))
     TREE_ADDRESSABLE (base) = 1;
 
@@ -550,6 +555,7 @@ walk_stmts (struct walk_stmt_info *wi, tree *tp)
       break;
     case CATCH_EXPR:
       walk_stmts (wi, &CATCH_BODY (t));
+      break;
     case EH_FILTER_EXPR:
       walk_stmts (wi, &EH_FILTER_FAILURE (t));
       break;
@@ -657,7 +663,7 @@ get_static_chain (struct nesting_info *info, tree target_context,
          tree field = get_chain_field (i);
 
          x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
-         x = build (COMPONENT_REF, TREE_TYPE (field), x, field);
+         x = build (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
          x = init_tmp_var (info, x, tsi);
        }
     }
@@ -691,14 +697,14 @@ get_frame_field (struct nesting_info *info, tree target_context,
          tree field = get_chain_field (i);
 
          x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
-         x = build (COMPONENT_REF, TREE_TYPE (field), x, field);
+         x = build (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
          x = init_tmp_var (info, x, tsi);
        }
 
       x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
     }
 
-  x = build (COMPONENT_REF, TREE_TYPE (field), x, field);
+  x = build (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
   return x;
 }
 
@@ -800,10 +806,13 @@ convert_nonlocal_reference (tree *tp, int *walk_subtrees, void *data)
       break;
 
     case ARRAY_REF:
+    case ARRAY_RANGE_REF:
       wi->val_only = false;
       walk_tree (&TREE_OPERAND (t, 0), convert_nonlocal_reference, wi, NULL);
       wi->val_only = true;
       walk_tree (&TREE_OPERAND (t, 1), convert_nonlocal_reference, wi, NULL);
+      walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference, wi, NULL);
+      walk_tree (&TREE_OPERAND (t, 3), convert_nonlocal_reference, wi, NULL);
       break;
 
     case BIT_FIELD_REF:
@@ -932,10 +941,13 @@ convert_local_reference (tree *tp, int *walk_subtrees, void *data)
       break;
 
     case ARRAY_REF:
+    case ARRAY_RANGE_REF:
       wi->val_only = false;
       walk_tree (&TREE_OPERAND (t, 0), convert_local_reference, wi, NULL);
       wi->val_only = true;
       walk_tree (&TREE_OPERAND (t, 1), convert_local_reference, wi, NULL);
+      walk_tree (&TREE_OPERAND (t, 2), convert_local_reference, wi, NULL);
+      walk_tree (&TREE_OPERAND (t, 3), convert_local_reference, wi, NULL);
       break;
 
     case BIT_FIELD_REF:
@@ -1242,7 +1254,7 @@ finalize_nesting_tree_1 (struct nesting_info *root)
            x = p;
 
          y = build (COMPONENT_REF, TREE_TYPE (field),
-                    root->frame_decl, field);
+                    root->frame_decl, field, NULL_TREE);
          x = build (MODIFY_EXPR, TREE_TYPE (field), y, x);
          append_to_statement_list (x, &stmt_list);
        }
@@ -1252,9 +1264,8 @@ finalize_nesting_tree_1 (struct nesting_info *root)
      from chain_decl.  */
   if (root->chain_field)
     {
-      tree x;
-      x = build (COMPONENT_REF, TREE_TYPE (root->chain_field),
-                root->frame_decl, root->chain_field);
+      tree x = build (COMPONENT_REF, TREE_TYPE (root->chain_field),
+                     root->frame_decl, root->chain_field, NULL_TREE);
       x = build (MODIFY_EXPR, TREE_TYPE (x), x, get_chain_decl (root));
       append_to_statement_list (x, &stmt_list);
     }
@@ -1281,7 +1292,7 @@ finalize_nesting_tree_1 (struct nesting_info *root)
          arg = tree_cons (NULL, x, arg);
 
          x = build (COMPONENT_REF, TREE_TYPE (field),
-                    root->frame_decl, field);
+                    root->frame_decl, field, NULL_TREE);
          x = build_addr (x);
          arg = tree_cons (NULL, x, arg);
 
index 28c8023..f19afdd 100644 (file)
@@ -1763,17 +1763,20 @@ discover_nonconstant_array_refs_r (tree * tp, int *walk_subtrees,
 
   if (TYPE_P (t) || DECL_P (t))
     *walk_subtrees = 0;
-  else if (TREE_CODE (t) == ARRAY_REF)
+  else if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
     {
-      while ((TREE_CODE (t) == ARRAY_REF
+      while (((TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
              && is_gimple_min_invariant (TREE_OPERAND (t, 1)))
             || (TREE_CODE (t) == COMPONENT_REF
                 || TREE_CODE (t) == BIT_FIELD_REF
                 || TREE_CODE (t) == REALPART_EXPR
-                || TREE_CODE (t) == IMAGPART_EXPR))
+                || TREE_CODE (t) == IMAGPART_EXPR
+                || TREE_CODE (t) == VIEW_CONVERT_EXPR
+                || TREE_CODE (t) == NOP_EXPR
+                || TREE_CODE (t) == CONVERT_EXPR))
        t = TREE_OPERAND (t, 0);
 
-      if (TREE_CODE (t) == ARRAY_REF)
+      if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
        {
          t = get_base_address (t);
          if (t && DECL_P (t))
index 4b8d2d4..52aa181 100644 (file)
@@ -392,6 +392,7 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
 
     case RECORD_TYPE:
     case UNION_TYPE:
+    case QUAL_UNION_TYPE:
       /* Print the name of the structure.  */
       if (TREE_CODE (node) == RECORD_TYPE)
        pp_string (buffer, "struct ");
@@ -404,11 +405,6 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
        print_struct_decl (buffer, node, spc, flags);
       break;
 
-    case QUAL_UNION_TYPE:
-      NIY;
-      break;
-
-
     case LANG_TYPE:
       NIY;
       break;
@@ -598,6 +594,14 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
        pp_character (buffer, ')');
       pp_string (buffer, str);
       dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
+      if (TREE_OPERAND (node, 2)
+         && TREE_CODE (TREE_OPERAND (node, 2)) != INTEGER_CST)
+       {
+         pp_string (buffer, "{off: ");
+         dump_generic_node (buffer, TREE_OPERAND (node, 2),
+                            spc, flags, false);
+         pp_character (buffer, '}');
+       }
       break;
 
     case BIT_FIELD_REF:
@@ -615,6 +619,7 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
       break;
 
     case ARRAY_REF:
+    case ARRAY_RANGE_REF:
       op0 = TREE_OPERAND (node, 0);
       if (op_prio (op0) < op_prio (node))
        pp_character (buffer, '(');
@@ -623,11 +628,23 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
        pp_character (buffer, ')');
       pp_character (buffer, '[');
       dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
+      if (TREE_CODE (node) == ARRAY_RANGE_REF)
+       pp_string (buffer, " ...");
       pp_character (buffer, ']');
-      break;
 
-    case ARRAY_RANGE_REF:
-      NIY;
+      if ((TREE_OPERAND (node, 2)
+          && TREE_CODE (TREE_OPERAND (node, 2)) != INTEGER_CST)
+         || (TREE_OPERAND (node, 3)
+             && TREE_CODE (TREE_OPERAND (node, 3)) != INTEGER_CST))
+       {
+         pp_string (buffer, "{lb: ");
+         dump_generic_node (buffer, TREE_OPERAND (node, 2),
+                            spc, flags, false);
+         pp_string (buffer, " sz: ");
+         dump_generic_node (buffer, TREE_OPERAND (node, 3),
+                            spc, flags, false);
+         pp_character (buffer, '}');
+       }
       break;
 
     case CONSTRUCTOR:
@@ -1490,10 +1507,10 @@ print_struct_decl (pretty_printer *buffer, tree node, int spc, int flags)
       INDENT (spc);
       if (TREE_CODE (node) == RECORD_TYPE)
        pp_string (buffer, "struct ");
-      else if (TREE_CODE (node) == UNION_TYPE)
+      else if ((TREE_CODE (node) == UNION_TYPE
+               || TREE_CODE (node) == QUAL_UNION_TYPE))
        pp_string (buffer, "union ");
-      else
-       NIY;
+
       dump_generic_node (buffer, TYPE_NAME (node), spc, 0, false);
     }
 
@@ -1515,8 +1532,8 @@ print_struct_decl (pretty_printer *buffer, tree node, int spc, int flags)
           Maybe this could be solved by looking at the scope in which the
           structure was declared.  */
        if (TREE_TYPE (tmp) != node
-           || (TREE_CODE (TREE_TYPE (tmp)) == POINTER_TYPE &&
-               TREE_TYPE (TREE_TYPE (tmp)) != node))
+           || (TREE_CODE (TREE_TYPE (tmp)) == POINTER_TYPE
+               && TREE_TYPE (TREE_TYPE (tmp)) != node))
          {
            print_declaration (buffer, tmp, spc+2, flags);
            pp_newline (buffer);
@@ -1656,6 +1673,7 @@ op_prio (tree op)
 
     case CALL_EXPR:
     case ARRAY_REF:
+    case ARRAY_RANGE_REF:
     case COMPONENT_REF:
       return 15;
 
index b5e4735..bbb5942 100644 (file)
@@ -621,7 +621,7 @@ csc_build_component_ref (tree base, tree field)
       break;
     }
 
-  return build (COMPONENT_REF, TREE_TYPE (field), base, field);
+  return build (COMPONENT_REF, TREE_TYPE (field), base, field, NULL_TREE);
 }
 
 /* Similarly for REALPART_EXPR and IMAGPART_EXPR for complex types.  */
@@ -1011,7 +1011,7 @@ scalarize_call_expr (block_stmt_iterator *si_p)
   /* Scalarize the return value, if any.  */
   if (TREE_CODE (stmt) == MODIFY_EXPR)
     {
-      tree var = TREE_OPERAND (stmt, 0);
+      tree var = get_base_address (TREE_OPERAND (stmt, 0));
 
       /* If the LHS of the assignment is a scalarizable structure, insert
         copies into the scalar replacements after the call.  */
index fb7a825..658a2cb 100644 (file)
@@ -1041,40 +1041,43 @@ dump_lattice_value (FILE *outf, const char *prefix, value val)
 tree
 widen_bitfield (tree val, tree field, tree var)
 {
-  unsigned var_size, field_size;
+  unsigned HOST_WIDE_INT var_size, field_size;
   tree wide_val;
   unsigned HOST_WIDE_INT mask;
-  unsigned i;
+  unsigned int i;
 
-  var_size = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE ((var))));
-  field_size = TREE_INT_CST_LOW (DECL_SIZE (field));
+  /* We can only do this if the size of the type and field and VAL are
+     all constants representable in HOST_WIDE_INT.  */
+  if (!host_integerp (TYPE_SIZE (TREE_TYPE (var)), 1)
+      || !host_integerp (DECL_SIZE (field), 1)
+      || !host_integerp (val, 0))
+    return NULL_TREE;
+
+  var_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (var)), 1);
+  field_size = tree_low_cst (DECL_SIZE (field), 1);
 
   /* Give up if either the bitfield or the variable are too wide.  */
   if (field_size > HOST_BITS_PER_WIDE_INT || var_size > HOST_BITS_PER_WIDE_INT)
-    return NULL;
+    return NULL_TREE;
 
 #if defined ENABLE_CHECKING
   if (var_size < field_size)
     abort ();
 #endif
 
-  /* If VAL is not an integer constant, then give up.  */
-  if (TREE_CODE (val) != INTEGER_CST)
-    return NULL;
-
-  /* If the sign bit of the value is not set, or the field's type is
-     unsigned, then just mask off the high order bits of the value.  */
-  if ((TREE_INT_CST_LOW (val) & (1 << (field_size - 1))) == 0
-      || DECL_UNSIGNED (field))
+  /* If the sign bit of the value is not set or the field's type is unsigned,
+     just mask off the high order bits of the value.  */
+  if (DECL_UNSIGNED (field)
+      || !(tree_low_cst (val, 0) & (((HOST_WIDE_INT)1) << (field_size - 1))))
     {
       /* Zero extension.  Build a mask with the lower 'field_size' bits
         set and a BIT_AND_EXPR node to clear the high order bits of
         the value.  */
       for (i = 0, mask = 0; i < field_size; i++)
-       mask |= 1 << i;
+       mask |= ((HOST_WIDE_INT) 1) << i;
 
       wide_val = build (BIT_AND_EXPR, TREE_TYPE (var), val, 
-                       build_int_2 (mask, 0));
+                       fold_convert (TREE_TYPE (var), build_int_2 (mask, 0)));
     }
   else
     {
@@ -1082,10 +1085,10 @@ widen_bitfield (tree val, tree field, tree var)
         bits set and a BIT_IOR_EXPR to set the high order bits of the
         value.  */
       for (i = 0, mask = 0; i < (var_size - field_size); i++)
-       mask |= 1 << (var_size - i - 1);
+       mask |= ((HOST_WIDE_INT) 1) << (var_size - i - 1);
 
       wide_val = build (BIT_IOR_EXPR, TREE_TYPE (var), val,
-                       build_int_2 (mask, 0));
+                       fold_convert (TREE_TYPE (var), build_int_2 (mask, 0)));
     }
 
   return fold (wide_val);
@@ -1493,10 +1496,26 @@ likely_value (tree stmt)
 static tree
 maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type)
 {
-  unsigned HOST_WIDE_INT lquo, lrem;
-  HOST_WIDE_INT hquo, hrem;
-  tree elt_size, min_idx, idx;
-  tree array_type, elt_type;
+  tree min_idx, idx, elt_offset = integer_zero_node;
+  tree array_type, elt_type, elt_size;
+
+  /* If BASE is an ARRAY_REF, we can pick up another offset (this time
+     measured in units of the size of elements type) from that ARRAY_REF).
+     We can't do anything if either is variable.
+
+     The case we handle here is *(&A[N]+O).  */
+  if (TREE_CODE (base) == ARRAY_REF)
+    {
+      tree low_bound = array_ref_low_bound (base);
+
+      elt_offset = TREE_OPERAND (base, 1);
+      if (TREE_CODE (low_bound) != INTEGER_CST
+         || TREE_CODE (elt_offset) != INTEGER_CST)
+       return NULL_TREE;
+
+      elt_offset = int_const_binop (MINUS_EXPR, elt_offset, low_bound, 0);
+      base = TREE_OPERAND (base, 0);
+    }
 
   /* Ignore stupid user tricks of indexing non-array variables.  */
   array_type = TREE_TYPE (base);
@@ -1506,37 +1525,62 @@ maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type)
   if (!lang_hooks.types_compatible_p (orig_type, elt_type))
     return NULL_TREE;
        
-  /* Whee.  Ignore indexing of variable sized types.  */
+  /* If OFFSET and ELT_OFFSET are zero, we don't care about the size of the
+     element type (so we can use the alignment if it's not constant).
+     Otherwise, compute the offset as an index by using a division.  If the
+     division isn't exact, then don't do anything.  */
   elt_size = TYPE_SIZE_UNIT (elt_type);
-  if (TREE_CODE (elt_size) != INTEGER_CST)
-    return NULL_TREE;
+  if (integer_zerop (offset))
+    {
+      if (TREE_CODE (elt_size) != INTEGER_CST)
+       elt_size = size_int (TYPE_ALIGN (elt_type));
 
-  /* If the division isn't exact, then don't do anything.  Equally
-     invalid as the above indexing of non-array variables.  */
-  if (div_and_round_double (TRUNC_DIV_EXPR, 1,
-                           TREE_INT_CST_LOW (offset),
-                           TREE_INT_CST_HIGH (offset),
-                           TREE_INT_CST_LOW (elt_size),
-                           TREE_INT_CST_HIGH (elt_size),
-                           &lquo, &hquo, &lrem, &hrem)
-      || lrem || hrem)
-    return NULL_TREE;
-  idx = build_int_2_wide (lquo, hquo);
+      idx = integer_zero_node;
+    }
+  else
+    {
+      unsigned HOST_WIDE_INT lquo, lrem;
+      HOST_WIDE_INT hquo, hrem;
+
+      if (TREE_CODE (elt_size) != INTEGER_CST
+         || div_and_round_double (TRUNC_DIV_EXPR, 1,
+                                  TREE_INT_CST_LOW (offset),
+                                  TREE_INT_CST_HIGH (offset),
+                                  TREE_INT_CST_LOW (elt_size),
+                                  TREE_INT_CST_HIGH (elt_size),
+                                  &lquo, &hquo, &lrem, &hrem)
+         || lrem || hrem)
+       return NULL_TREE;
 
-  /* Re-bias the index by the min index of the array type.  */
-  min_idx = TYPE_DOMAIN (TREE_TYPE (base));
-  if (min_idx)
+      idx = build_int_2_wide (lquo, hquo);
+    }
+
+  /* Assume the low bound is zero.  If there is a domain type, get the
+     low bound, if any, convert the index into that type, and add the
+     low bound.  */
+  min_idx = integer_zero_node;
+  if (TYPE_DOMAIN (array_type))
     {
-      min_idx = TYPE_MIN_VALUE (min_idx);
-      if (min_idx)
-       {
-         idx = convert (TREE_TYPE (min_idx), idx);
-         if (!integer_zerop (min_idx))
-           idx = int_const_binop (PLUS_EXPR, idx, min_idx, 1);
-       }
+      if (TYPE_MIN_VALUE (TYPE_DOMAIN (array_type)))
+       min_idx = TYPE_MIN_VALUE (TYPE_DOMAIN (array_type));
+      else
+       min_idx = fold_convert (TYPE_DOMAIN (array_type), min_idx);
+
+      if (TREE_CODE (min_idx) != INTEGER_CST)
+       return NULL_TREE;
+
+      idx = fold_convert (TYPE_DOMAIN (array_type), idx);
+      elt_offset = fold_convert (TYPE_DOMAIN (array_type), elt_offset);
     }
 
-  return build (ARRAY_REF, orig_type, base, idx);
+  if (!integer_zerop (min_idx))
+    idx = int_const_binop (PLUS_EXPR, idx, min_idx, 0);
+  if (!integer_zerop (elt_offset))
+    idx = int_const_binop (PLUS_EXPR, idx, elt_offset, 0);
+
+  return build (ARRAY_REF, orig_type, base, idx, min_idx,
+               size_int (tree_low_cst (elt_size, 1)
+                         / (TYPE_ALIGN (elt_type) / BITS_PER_UNIT)));
 }
 
 /* A subroutine of fold_stmt_r.  Attempts to fold *(S+O) to S.X.
@@ -1617,7 +1661,7 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
        {
          if (base_is_ptr)
            base = build1 (INDIRECT_REF, record_type, base);
-         t = build (COMPONENT_REF, field_type, base, f);
+         t = build (COMPONENT_REF, field_type, base, f, NULL_TREE);
          return t;
        }
 
@@ -1639,7 +1683,7 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
      nonzero offset into them.  Recurse and hope for a valid match.  */
   if (base_is_ptr)
     base = build1 (INDIRECT_REF, record_type, base);
-  base = build (COMPONENT_REF, field_type, base, f);
+  base = build (COMPONENT_REF, field_type, base, f, NULL_TREE);
 
   t = maybe_fold_offset_to_array_ref (base, offset, orig_type);
   if (t)
@@ -1697,8 +1741,12 @@ maybe_fold_stmt_indirect (tree expr, tree base, tree offset)
       if (t)
        return t;
 
-      /* Fold *&B to B.  */
-      if (integer_zerop (offset))
+      /* Fold *&B to B.  We can only do this if EXPR is the same type
+        as BASE.  We can't do this if EXPR is the element type of an array
+        and BASE is the array.  */
+      if (integer_zerop (offset)
+         && lang_hooks.types_compatible_p (TREE_TYPE (base),
+                                           TREE_TYPE (expr)))
        return base;
     }
   else
@@ -1803,6 +1851,9 @@ maybe_fold_stmt_addition (tree expr)
          min_idx = TYPE_MIN_VALUE (min_idx);
          if (min_idx)
            {
+             if (TREE_CODE (min_idx) != INTEGER_CST)
+               break;
+
              array_idx = convert (TREE_TYPE (min_idx), array_idx);
              if (!integer_zerop (min_idx))
                array_idx = int_const_binop (MINUS_EXPR, array_idx,
index 9eb0bd1..08330ab 100644 (file)
@@ -897,30 +897,18 @@ get_expr_operands (tree stmt, tree *expr_p, int flags, voperands_t prev_vops)
   code = TREE_CODE (expr);
   class = TREE_CODE_CLASS (code);
 
-  /* Expressions that make no memory references.  */
-  if (class == 'c'
-      || class == 't'
-      || code == BLOCK
-      || code == FUNCTION_DECL
-      || code == EXC_PTR_EXPR
-      || code == FILTER_EXPR
-      || code == LABEL_DECL)
-    return;
-
   /* We could have the address of a component, array member, etc which
      has interesting variable references.  */
   if (code == ADDR_EXPR)
     {
-      enum tree_code subcode = TREE_CODE (TREE_OPERAND (expr, 0));
-
       /* Taking the address of a variable does not represent a
         reference to it, but the fact that STMT takes its address will be
         of interest to some passes (e.g. alias resolution).  */
       add_stmt_operand (expr_p, stmt, 0, NULL);
 
-      /* If the address is invariant, there may be no interesting variable
-        references inside.  */
-      if (is_gimple_min_invariant (expr))
+      /* If the address is constant (invariant is not sufficient), there will
+        be no interesting variable references inside.  */
+      if (TREE_CONSTANT (expr))
        return;
 
       /* There should be no VUSEs created, since the referenced objects are
@@ -930,12 +918,22 @@ get_expr_operands (tree stmt, tree *expr_p, int flags, voperands_t prev_vops)
       flags |= opf_no_vops;
 
       /* Avoid recursion.  */
-      code = subcode;
-      class = TREE_CODE_CLASS (code);
       expr_p = &TREE_OPERAND (expr, 0);
       expr = *expr_p;
+      code =  TREE_CODE (expr);
+      class = TREE_CODE_CLASS (code);
     }
 
+  /* Expressions that make no memory references.  */
+  if (class == 'c'
+      || class == 't'
+      || code == BLOCK
+      || code == FUNCTION_DECL
+      || code == EXC_PTR_EXPR
+      || code == FILTER_EXPR
+      || code == LABEL_DECL)
+    return;
+
   /* If we found a variable, add it to DEFS or USES depending on the
      operand flags.  */
   if (SSA_VAR_P (expr))
@@ -1043,7 +1041,7 @@ get_expr_operands (tree stmt, tree *expr_p, int flags, voperands_t prev_vops)
   /* Treat array references as references to the virtual variable
      representing the array.  The virtual variable for an ARRAY_REF
      is the VAR_DECL for the array.  */
-  if (code == ARRAY_REF)
+  if (code == ARRAY_REF || code == ARRAY_RANGE_REF)
     {
       /* Add the virtual variable for the ARRAY_REF to VDEFS or VUSES
         according to the value of IS_DEF.  Recurse if the LHS of the
@@ -1054,6 +1052,8 @@ get_expr_operands (tree stmt, tree *expr_p, int flags, voperands_t prev_vops)
        get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags, prev_vops);
 
       get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none, prev_vops);
+      get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none, prev_vops);
+      get_expr_operands (stmt, &TREE_OPERAND (expr, 3), opf_none, prev_vops);
       return;
     }
 
@@ -1078,6 +1078,8 @@ get_expr_operands (tree stmt, tree *expr_p, int flags, voperands_t prev_vops)
       else
        get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags, prev_vops);
 
+      if (code == COMPONENT_REF)
+       get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none, prev_vops);
       return;
     }
 
index 5ba8f65..89d40a1 100644 (file)
@@ -473,20 +473,11 @@ set_is_used (tree t)
       if (SSA_VAR_P (t))
        break;
 
-      switch (TREE_CODE (t))
-       {
-       case ARRAY_REF:
-       case COMPONENT_REF:
-       case REALPART_EXPR:
-       case IMAGPART_EXPR:
-       case BIT_FIELD_REF:
-       case INDIRECT_REF:
+      if (TREE_CODE (t) == REALPART_EXPR || TREE_CODE (t) == IMAGPART_EXPR)
+       t = TREE_OPERAND (t, 0);
+      else
+       while (handled_component_p (t))
          t = TREE_OPERAND (t, 0);
-         break;
-
-       default:
-         return;
-       }
     }
 
   if (TREE_CODE (t) == SSA_NAME)
index fb1f4d7..716bc35 100644 (file)
@@ -1927,7 +1927,8 @@ substitute_in_expr (tree exp, tree f, tree r)
      if (op0 == TREE_OPERAND (exp, 0))
        return exp;
 
-     new = fold (build2 (code, TREE_TYPE (exp), op0, TREE_OPERAND (exp, 1)));
+     new = fold (build (code, TREE_TYPE (exp), op0, TREE_OPERAND (exp, 1),
+                       NULL_TREE));
    }
   else
     switch (TREE_CODE_CLASS (code))
@@ -2157,7 +2158,7 @@ stabilize_reference (tree ref)
     case COMPONENT_REF:
       result = build_nt (COMPONENT_REF,
                         stabilize_reference (TREE_OPERAND (ref, 0)),
-                        TREE_OPERAND (ref, 1));
+                        TREE_OPERAND (ref, 1), NULL_TREE);
       break;
 
     case BIT_FIELD_REF:
@@ -2170,13 +2171,15 @@ stabilize_reference (tree ref)
     case ARRAY_REF:
       result = build_nt (ARRAY_REF,
                         stabilize_reference (TREE_OPERAND (ref, 0)),
-                        stabilize_reference_1 (TREE_OPERAND (ref, 1)));
+                        stabilize_reference_1 (TREE_OPERAND (ref, 1)),
+                        TREE_OPERAND (ref, 2), TREE_OPERAND (ref, 3));
       break;
 
     case ARRAY_RANGE_REF:
       result = build_nt (ARRAY_RANGE_REF,
                         stabilize_reference (TREE_OPERAND (ref, 0)),
-                        stabilize_reference_1 (TREE_OPERAND (ref, 1)));
+                        stabilize_reference_1 (TREE_OPERAND (ref, 1)),
+                        TREE_OPERAND (ref, 2), TREE_OPERAND (ref, 3));
       break;
 
     case COMPOUND_EXPR:
@@ -2292,41 +2295,77 @@ stabilize_reference_1 (tree e)
 \f
 /* Low-level constructors for expressions.  */
 
-/* A helper function for build1 and constant folders.
-   Set TREE_CONSTANT and TREE_INVARIANT for an ADDR_EXPR.  */
+/* A helper function for build1 and constant folders.  Set TREE_CONSTANT,
+   TREE_INVARIANT, and TREE_SIDE_EFFECTS for an ADDR_EXPR.  */
 
 void
 recompute_tree_invarant_for_addr_expr (tree t)
 {
-  tree node = TREE_OPERAND (t, 0);
-  bool tc = false, ti = false;
+  tree node;
+  bool tc = true, ti = true, se = false;
 
-  /* Addresses of constants and static variables are constant;
-     all other decl addresses are invariant.  */
-  if (staticp (node))
-    tc = ti = true;
-  else
+  /* We started out assuming this address is both invariant and constant, but
+     does not have side effects.  Now go down any handled components and see if
+     any of them involve offsets that are either non-constant or non-invariant.
+     Also check for side-effects.
+
+     ??? Note that this code makes no attempt to deal with the case where
+     taking the address of something causes a copy due to misalignment.  */
+
+#define UPDATE_TITCSE(NODE)  \
+do { tree _node = (NODE); \
+     if (_node && !TREE_INVARIANT (_node)) ti = false; \
+     if (_node && !TREE_CONSTANT (_node)) tc = false; \
+     if (_node && TREE_SIDE_EFFECTS (_node)) se = true; } while (0)
+
+  for (node = TREE_OPERAND (t, 0); handled_component_p (node);
+       node = TREE_OPERAND (node, 0))
     {
-      /* Step past constant offsets.  */
-      while (1)
+      /* If the first operand doesn't have an ARRAY_TYPE, this is a bogus
+        array reference (probably made temporarily by the G++ front end),
+        so ignore all the operands.  */
+      if ((TREE_CODE (node) == ARRAY_REF
+          || TREE_CODE (node) == ARRAY_RANGE_REF)
+         && TREE_CODE (TREE_TYPE (TREE_OPERAND (node, 0))) == ARRAY_TYPE)
        {
-         if (TREE_CODE (node) == COMPONENT_REF
-             && TREE_CODE (TREE_OPERAND (node, 1)) == FIELD_DECL
-             && ! DECL_BIT_FIELD (TREE_OPERAND (node, 1)))
-           ;
-         else if (TREE_CODE (node) == ARRAY_REF
-                  && TREE_CONSTANT (TREE_OPERAND (node, 1)))
-           ;
-         else
-           break;
-         node = TREE_OPERAND (node, 0);
+         UPDATE_TITCSE (TREE_OPERAND (node, 1));
+         UPDATE_TITCSE (array_ref_low_bound (node));
+         UPDATE_TITCSE (array_ref_element_size (node));
        }
-      if (DECL_P (node))
-        ti = true;
+      /* Likewise, just because this is a COMPONENT_REF doesn't mean we have a
+        FIELD_DECL, apparently.  The G++ front end can put something else
+        there, at least temporarily.  */
+      else if (TREE_CODE (node) == COMPONENT_REF
+              && TREE_CODE (TREE_OPERAND (node, 1)) == FIELD_DECL)
+       UPDATE_TITCSE (component_ref_field_offset (node));
+      else if (TREE_CODE (node) == BIT_FIELD_REF)
+       UPDATE_TITCSE (TREE_OPERAND (node, 2));
+    }
+             
+  /* Now see what's inside.  If it's an INDIRECT_REF, copy our properties from
+     it.  If it's a decl, it's definitely invariant and it's constant if the
+     decl is static.  (Taking the address of a volatile variable is not
+     volatile.)  If it's a constant, the address is both invariant and
+     constant.  Otherwise it's neither.  */
+  if (TREE_CODE (node) == INDIRECT_REF)
+    UPDATE_TITCSE (node);
+  else if (DECL_P (node))
+    {
+      if (!staticp (node))
+       tc = false;
+    }
+  else if (TREE_CODE_CLASS (TREE_CODE (node)) == 'c')
+    ;
+  else
+    {
+      ti = tc = false;
+      se |= TREE_SIDE_EFFECTS (node);
     }
 
   TREE_CONSTANT (t) = tc;
   TREE_INVARIANT (t) = ti;
+  TREE_SIDE_EFFECTS (t) = se;
+#undef UPDATE_TITCSE
 }
 
 /* Build an expression of code CODE, data type TYPE, and operands as
@@ -2429,27 +2468,7 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
 
     case ADDR_EXPR:
       if (node)
-       {
-         recompute_tree_invarant_for_addr_expr (t);
-
-         /* The address of a volatile decl or reference does not have
-            side-effects.  But be careful not to ignore side-effects from
-            other sources deeper in the expression--if node is a _REF and
-            one of its operands has side-effects, so do we.  */
-         if (TREE_THIS_VOLATILE (node))
-           {
-             TREE_SIDE_EFFECTS (t) = 0;
-             if (!DECL_P (node))
-               {
-                 int i = first_rtl_op (TREE_CODE (node)) - 1;
-                 for (; i >= 0; --i)
-                   {
-                     if (TREE_SIDE_EFFECTS (TREE_OPERAND (node, i)))
-                       TREE_SIDE_EFFECTS (t) = 1;
-                   }
-               }
-           }
-       }
+       recompute_tree_invarant_for_addr_expr (t);
       break;
 
     default:
@@ -2516,6 +2535,8 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
   TREE_CONSTANT (t) = constant;
   TREE_INVARIANT (t) = invariant;
   TREE_SIDE_EFFECTS (t) = side_effects;  
+  TREE_THIS_VOLATILE (t)
+    = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0);
 
   return t;
 }
@@ -2565,6 +2586,8 @@ build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
     }
 
   TREE_SIDE_EFFECTS (t) = side_effects;  
+  TREE_THIS_VOLATILE (t)
+    = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0);
 
   return t;
 }
@@ -2595,6 +2618,8 @@ build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
   PROCESS_ARG(3);
 
   TREE_SIDE_EFFECTS (t) = side_effects;  
+  TREE_THIS_VOLATILE (t)
+    = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0);
 
   return t;
 }
@@ -4457,8 +4482,8 @@ get_unwidened (tree op, tree for_type)
          && (for_type || ! DECL_BIT_FIELD (TREE_OPERAND (op, 1)))
          && (! uns || final_prec <= innerprec || unsignedp))
        {
-         win = build2 (COMPONENT_REF, type, TREE_OPERAND (op, 0),
-                       TREE_OPERAND (op, 1));
+         win = build3 (COMPONENT_REF, type, TREE_OPERAND (op, 0),
+                       TREE_OPERAND (op, 1), NULL_TREE);
          TREE_SIDE_EFFECTS (win) = TREE_SIDE_EFFECTS (op);
          TREE_THIS_VOLATILE (win) = TREE_THIS_VOLATILE (op);
        }
@@ -4523,7 +4548,8 @@ get_narrower (tree op, int *unsignedp_ptr)
       /* Since type_for_size always gives an integer type.  */
       && TREE_CODE (TREE_TYPE (op)) != REAL_TYPE
       /* Ensure field is laid out already.  */
-      && DECL_SIZE (TREE_OPERAND (op, 1)) != 0)
+      && DECL_SIZE (TREE_OPERAND (op, 1)) != 0
+      && host_integerp (DECL_SIZE (TREE_OPERAND (op, 1)), 1))
     {
       unsigned HOST_WIDE_INT innerprec
        = tree_low_cst (DECL_SIZE (TREE_OPERAND (op, 1)), 1);
@@ -4546,8 +4572,8 @@ get_narrower (tree op, int *unsignedp_ptr)
        {
          if (first)
            uns = DECL_UNSIGNED (TREE_OPERAND (op, 1));
-         win = build2 (COMPONENT_REF, type, TREE_OPERAND (op, 0),
-                       TREE_OPERAND (op, 1));
+         win = build3 (COMPONENT_REF, type, TREE_OPERAND (op, 0),
+                       TREE_OPERAND (op, 1), NULL_TREE);
          TREE_SIDE_EFFECTS (win) = TREE_SIDE_EFFECTS (op);
          TREE_THIS_VOLATILE (win) = TREE_THIS_VOLATILE (op);
        }
index 5afe765..12a6394 100644 (file)
@@ -354,9 +354,11 @@ DEFTREECODE (TRANSLATION_UNIT_DECL, "translation_unit_decl", 'd', 0)
 /* References to storage.  */
 
 /* Value is structure or union component.
-   Operand 0 is the structure or union (an expression);
-   operand 1 is the field (a node of type FIELD_DECL).  */
-DEFTREECODE (COMPONENT_REF, "component_ref", 'r', 2)
+   Operand 0 is the structure or union (an expression).
+   Operand 1 is the field (a node of type FIELD_DECL).
+   Operand 2, if present, is the value of DECL_FIELD_OFFSET, measured
+   in units of DECL_OFFSET_ALIGN / BITS_PER_UNIT.  */
+DEFTREECODE (COMPONENT_REF, "component_ref", 'r', 3)
 
 /* Reference to a group of bits within an object.  Similar to COMPONENT_REF
    except the position is given explicitly rather than via a FIELD_DECL.
@@ -374,13 +376,16 @@ DEFTREECODE (INDIRECT_REF, "indirect_ref", 'r', 1)
 DEFTREECODE (BUFFER_REF, "buffer_ref", 'r', 1)
 
 /* Array indexing.
-   Operand 0 is the array; operand 1 is a (single) array index.  */
-DEFTREECODE (ARRAY_REF, "array_ref", 'r', 2)
+   Operand 0 is the array; operand 1 is a (single) array index.
+   Operand 2, if present, is a copy of TYPE_MIN_VALUE of the index.
+   Operand 3, if present, is the element size, measured in units of
+   the alignment of the element type.  */
+DEFTREECODE (ARRAY_REF, "array_ref", 'r', 4)
 
 /* Likewise, except that the result is a range ("slice") of the array.  The
    starting index of the resulting array is taken from operand 1 and the size
    of the range is taken from the type of the expression.  */
-DEFTREECODE (ARRAY_RANGE_REF, "array_range_ref", 'r', 2)
+DEFTREECODE (ARRAY_RANGE_REF, "array_range_ref", 'r', 4)
 
 /* Vtable indexing.  Carries data useful for emitting information
    for vtable garbage collection.
index d5d87b6..9b753a3 100644 (file)
@@ -3166,6 +3166,21 @@ extern tree get_inner_reference (tree, HOST_WIDE_INT *, HOST_WIDE_INT *,
 
 extern int handled_component_p (tree);
 
+/* Return a tree of sizetype representing the size, in bytes, of the element
+   of EXP, an ARRAY_REF.  */
+
+extern tree array_ref_element_size (tree);
+
+/* Return a tree representing the lower bound of the array mentioned in
+   EXP, an ARRAY_REF.  */
+
+extern tree array_ref_low_bound (tree);
+
+/* Return a tree representing the offset, in bytes, of the field referenced
+   by EXP.  This does not include any offset in DECL_FIELD_BIT_OFFSET.  */
+
+extern tree component_ref_field_offset (tree);
+
 /* Given a DECL or TYPE, return the scope in which it was declared, or
    NUL_TREE if there is no containing scope.  */